summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Binaries/DafnyPrelude.bpl37
-rw-r--r--Dafny/Cloner.cs24
-rw-r--r--Dafny/Compiler.cs124
-rw-r--r--Dafny/Dafny.atg116
-rw-r--r--Dafny/DafnyAst.cs179
-rw-r--r--Dafny/Parser.cs1432
-rw-r--r--Dafny/Printer.cs89
-rw-r--r--Dafny/RefinementTransformer.cs85
-rw-r--r--Dafny/Resolver.cs635
-rw-r--r--Dafny/Scanner.cs200
-rw-r--r--Dafny/Translator.cs643
-rw-r--r--Test/dafny0/Answer89
-rw-r--r--Test/dafny0/IteratorResolution.dfy138
-rw-r--r--Test/dafny0/Iterators.dfy235
-rw-r--r--Test/dafny0/runtest.bat2
-rw-r--r--Util/Emacs/dafny-mode.el6
-rw-r--r--Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs10
-rw-r--r--Util/VS2010/DafnyExtension/DafnyExtension/IdentifierTagger.cs20
-rw-r--r--Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs3
-rw-r--r--Util/latex/dafny.sty8
-rw-r--r--Util/vim/syntax/dafny.vim7
21 files changed, 3043 insertions, 1039 deletions
diff --git a/Binaries/DafnyPrelude.bpl b/Binaries/DafnyPrelude.bpl
index 5530f8a7..fafc9484 100644
--- a/Binaries/DafnyPrelude.bpl
+++ b/Binaries/DafnyPrelude.bpl
@@ -603,6 +603,43 @@ axiom (forall h: HeapType, k: HeapType :: { $HeapSucc(h,k) }
$HeapSucc(h,k) ==> (forall o: ref :: { read(k, o, alloc) } read(h, o, alloc) ==> read(k, o, alloc)));
// ---------------------------------------------------------------
+// -- Useful macros ----------------------------------------------
+// ---------------------------------------------------------------
+
+// havoc everything in $Heap, except {this}+rds+nw
+procedure $YieldHavoc(this: ref, rds: Set BoxType, nw: Set BoxType);
+ modifies $Heap;
+ ensures (forall<alpha> $o: ref, $f: Field alpha :: { read($Heap, $o, $f) }
+ $o != null && read(old($Heap), $o, alloc) ==>
+ $o == this || rds[$Box($o)] || nw[$Box($o)] ==>
+ read($Heap, $o, $f) == read(old($Heap), $o, $f));
+ ensures $HeapSucc(old($Heap), $Heap);
+
+// havoc everything in $Heap, except rds-mod-{this}
+procedure $IterHavoc0(this: ref, rds: Set BoxType, mod: Set BoxType);
+ modifies $Heap;
+ ensures (forall<alpha> $o: ref, $f: Field alpha :: { read($Heap, $o, $f) }
+ $o != null && read(old($Heap), $o, alloc) ==>
+ rds[$Box($o)] && !mod[$Box($o)] && $o != this ==>
+ read($Heap, $o, $f) == read(old($Heap), $o, $f));
+ ensures $HeapSucc(old($Heap), $Heap);
+
+// havoc $Heap at {this}+mod+nw
+procedure $IterHavoc1(this: ref, mod: Set BoxType, nw: Set BoxType);
+ modifies $Heap;
+ ensures (forall<alpha> $o: ref, $f: Field alpha :: { read($Heap, $o, $f) }
+ $o != null && read(old($Heap), $o, alloc) ==>
+ read($Heap, $o, $f) == read(old($Heap), $o, $f) ||
+ $o == this || mod[$Box($o)] || nw[$Box($o)]);
+ ensures $HeapSucc(old($Heap), $Heap);
+
+procedure $IterCollectNewObjects(prevHeap: HeapType, newHeap: HeapType, this: ref, NW: Field (Set BoxType))
+ returns (s: Set BoxType);
+ ensures (forall bx: BoxType :: { s[bx] } s[bx] <==>
+ read(newHeap, this, NW)[bx] ||
+ ($Unbox(bx) != null && !read(prevHeap, $Unbox(bx):ref, alloc) && read(newHeap, $Unbox(bx):ref, alloc)));
+
+// ---------------------------------------------------------------
// -- Non-determinism --------------------------------------------
// ---------------------------------------------------------------
diff --git a/Dafny/Cloner.cs b/Dafny/Cloner.cs
index c972c5c4..38c793c5 100644
--- a/Dafny/Cloner.cs
+++ b/Dafny/Cloner.cs
@@ -42,6 +42,24 @@ namespace Microsoft.Dafny
var ctors = dd.Ctors.ConvertAll(CloneCtor);
var dt = new CoDatatypeDecl(Tok(dd.tok), dd.Name, m, tps, ctors, CloneAttributes(dd.Attributes));
return dt;
+ } else if (d is IteratorDecl) {
+ var dd = (IteratorDecl)d;
+ var tps = dd.TypeArgs.ConvertAll(CloneTypeParam);
+ var ins = dd.Ins.ConvertAll(CloneFormal);
+ var outs = dd.Outs.ConvertAll(CloneFormal);
+ var reads = CloneSpecFrameExpr(dd.Reads);
+ var mod = CloneSpecFrameExpr(dd.Modifies);
+ var decr = CloneSpecExpr(dd.Decreases);
+ var req = dd.Requires.ConvertAll(CloneMayBeFreeExpr);
+ var yreq = dd.YieldRequires.ConvertAll(CloneMayBeFreeExpr);
+ var ens = dd.Ensures.ConvertAll(CloneMayBeFreeExpr);
+ var yens = dd.YieldEnsures.ConvertAll(CloneMayBeFreeExpr);
+ var body = CloneBlockStmt(dd.Body);
+ var iter = new IteratorDecl(Tok(dd.tok), dd.Name, dd.Module,
+ tps, ins, outs, reads, mod, decr,
+ req, ens, yreq, yens,
+ body, CloneAttributes(dd.Attributes), dd.SignatureIsOmitted);
+ return iter;
} else if (d is ClassDecl) {
if (d is DefaultClassDecl) {
var dd = (ClassDecl)d;
@@ -95,7 +113,7 @@ namespace Microsoft.Dafny
if (member is Field) {
Contract.Assert(!(member is SpecialField)); // we don't expect a SpecialField to be cloned (or do we?)
var f = (Field)member;
- return new Field(Tok(f.tok), f.Name, f.IsGhost, f.IsMutable, CloneType(f.Type), CloneAttributes(f.Attributes));
+ return new Field(Tok(f.tok), f.Name, f.IsGhost, f.IsMutable, f.IsUserMutable, CloneType(f.Type), CloneAttributes(f.Attributes));
} else if (member is Function) {
var f = (Function)member;
return CloneFunction(f);
@@ -387,6 +405,10 @@ namespace Microsoft.Dafny
var s = (ReturnStmt)stmt;
r = new ReturnStmt(Tok(s.Tok), s.rhss == null ? null : s.rhss.ConvertAll(CloneRHS));
+ } else if (stmt is YieldStmt) {
+ var s = (YieldStmt)stmt;
+ r = new YieldStmt(Tok(s.Tok), s.rhss == null ? null : s.rhss.ConvertAll(CloneRHS));
+
} else if (stmt is AssignStmt) {
var s = (AssignStmt)stmt;
r = new AssignStmt(Tok(s.Tok), CloneExpr(s.Lhs), CloneRHS(s.Rhs));
diff --git a/Dafny/Compiler.cs b/Dafny/Compiler.cs
index a138f4d9..4c334033 100644
--- a/Dafny/Compiler.cs
+++ b/Dafny/Compiler.cs
@@ -92,8 +92,87 @@ namespace Microsoft.Dafny {
wr.WriteLine(" { }");
CompileDatatypeConstructors(dt, indent);
CompileDatatypeStruct(dt, indent);
+ } else if (d is IteratorDecl) {
+ var iter = (IteratorDecl)d;
+ // An iterator is compiled as follows:
+ // public class MyIteratorExample<T>
+ // {
+ // public T q; // in-parameter
+ // public T x; // yield-parameter
+ // public int y; // yield-parameter
+ // IEnumerator<object> _iter;
+ //
+ // public void _MyIteratorExample(T q) {
+ // this.q = q;
+ // _iter = TheIterator();
+ // }
+ //
+ // public void MoveNext(out bool more) {
+ // more =_iter.MoveNext();
+ // }
+ //
+ // private IEnumerator<object> TheIterator() {
+ // // the translation of the body of the iterator, with each "yield" turning into a "yield return null;"
+ // yield break;
+ // }
+ // }
+
+ Indent(indent);
+ wr.Write("public class @{0}", iter.CompileName);
+ if (iter.TypeArgs.Count != 0) {
+ wr.Write("<{0}>", TypeParameters(iter.TypeArgs));
+ }
+ wr.WriteLine(" {");
+ var ind = indent + IndentAmount;
+ // here come the fields
+ Constructor ct = null;
+ foreach (var member in iter.Members) {
+ var f = member as Field;
+ if (f != null && !f.IsGhost) {
+ Indent(ind);
+ wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type), f.CompileName, DefaultValue(f.Type));
+ } else if (member is Constructor) {
+ Contract.Assert(ct == null); // we're expecting just one constructor
+ ct = (Constructor)member;
+ }
+ }
+ Contract.Assert(ct != null); // we do expect a constructor
+ Indent(ind); wr.WriteLine("System.Collections.Generic.IEnumerator<object> __iter;");
+
+ // here's the initializer method
+ Indent(ind); wr.Write("public void @{0}(", ct.CompileName);
+ string sep = "";
+ foreach (var p in ct.Ins) {
+ if (!p.IsGhost) {
+ // here we rely on the parameters and the corresponding fields having the same names
+ wr.Write("{0}{1} @{2}", sep, TypeName(p.Type), p.CompileName);
+ sep = ", ";
+ }
+ }
+ wr.WriteLine(") {");
+ foreach (var p in ct.Ins) {
+ if (!p.IsGhost) {
+ Indent(ind + IndentAmount);
+ wr.WriteLine("this.@{0} = @{0};", p.CompileName);
+ }
+ }
+ Indent(ind + IndentAmount); wr.WriteLine("__iter = TheIterator();");
+ Indent(ind); wr.WriteLine("}");
+ // here are the enumerator methods
+ Indent(ind); wr.WriteLine("public void MoveNext(out bool more) { more = __iter.MoveNext(); }");
+ Indent(ind); wr.WriteLine("private System.Collections.Generic.IEnumerator<object> TheIterator() {");
+ if (iter.Body == null) {
+ Error("Iterator {0} has no body", iter.FullName);
+ } else {
+ TrStmt(iter.Body, ind + IndentAmount);
+ }
+ Indent(ind + IndentAmount); wr.WriteLine("yield break;");
+ Indent(ind); wr.WriteLine("}");
+ // end of the class
+ Indent(indent); wr.WriteLine("}");
+
} else if (d is ClassDecl) {
- ClassDecl cl = (ClassDecl)d;
+ var cl = (ClassDecl)d;
Indent(indent);
wr.Write("public class @{0}", cl.CompileName);
if (cl.TypeArgs.Count != 0) {
@@ -332,18 +411,18 @@ namespace Microsoft.Dafny {
Contract.Requires(dt != null);
// public struct Dt<T> : IDatatype{
- // Base_Dt<T> d;
+ // Base_Dt<T> _d;
// public Base_Dt<T> _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
+ // 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;
+ // return _d;
// }
// }
- // public Dt(Base_Dt<T> d) { this.d = d; }
+ // public Dt(Base_Dt<T> d) { this._d = d; }
// static Base_Dt<T> theDefault;
// public static Base_Dt<T> Default {
// get {
@@ -377,30 +456,30 @@ namespace Microsoft.Dafny {
int ind = indent + IndentAmount;
Indent(ind);
- wr.WriteLine("Base_{0} d;", DtT);
+ wr.WriteLine("Base_{0} _d;", DtT);
Indent(ind);
wr.WriteLine("public Base_{0} _D {{", DtT);
Indent(ind + IndentAmount);
wr.WriteLine("get {");
Indent(ind + 2 * IndentAmount);
- wr.WriteLine("if (d == null) {");
+ wr.WriteLine("if (_d == null) {");
Indent(ind + 3 * IndentAmount);
- wr.WriteLine("d = Default;");
+ 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.CompileName, typeParams);
+ wr.WriteLine("}} else if (_d is {0}__Lazy{1}) {{", dt.CompileName, typeParams);
Indent(ind + 3 * IndentAmount);
- wr.WriteLine("d = (({0}__Lazy{1})d).Get();", dt.CompileName, typeParams);
+ wr.WriteLine("_d = (({0}__Lazy{1})_d).Get();", dt.CompileName, typeParams);
}
Indent(ind + 2 * IndentAmount); wr.WriteLine("}");
- Indent(ind + 2 * IndentAmount); wr.WriteLine("return d;");
+ 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.CompileName, DtT);
+ wr.WriteLine("public @{0}(Base_{1} d) {{ this._d = d; }}", dt.CompileName, DtT);
Indent(ind);
wr.WriteLine("static Base_{0} theDefault;", DtT);
@@ -937,11 +1016,16 @@ namespace Microsoft.Dafny {
var s = (BreakStmt)stmt;
Indent(indent);
wr.WriteLine("goto after_{0};", s.TargetStmt.Labels.Data.UniqueId);
- } else if (stmt is ReturnStmt) {
- var s = (ReturnStmt)stmt;
+ } else if (stmt is ProduceStmt) {
+ var s = (ProduceStmt)stmt;
if (s.hiddenUpdate != null)
TrStmt(s.hiddenUpdate, indent);
- Indent(indent); wr.WriteLine("return;");
+ Indent(indent);
+ if (s is YieldStmt) {
+ wr.WriteLine("yield return null;");
+ } else {
+ wr.WriteLine("return;");
+ }
} else if (stmt is UpdateStmt) {
var s = (UpdateStmt)stmt;
var resolved = s.ResolvedStatements;
@@ -1565,7 +1649,7 @@ namespace Microsoft.Dafny {
string prefix = "(";
foreach (Expression dim in tp.ArrayDimensions) {
wr.Write(prefix);
- TrExpr(dim);
+ TrParenExpr(dim);
prefix = ", ";
}
wr.Write(")");
@@ -1574,7 +1658,7 @@ namespace Microsoft.Dafny {
string prefix = "[";
foreach (Expression dim in tp.ArrayDimensions) {
wr.Write("{0}(int)", prefix);
- TrExpr(dim);
+ TrParenExpr(dim);
prefix = ", ";
}
wr.Write("]");
diff --git a/Dafny/Dafny.atg b/Dafny/Dafny.atg
index e2d90f20..4c425497 100644
--- a/Dafny/Dafny.atg
+++ b/Dafny/Dafny.atg
@@ -139,7 +139,7 @@ IGNORE cr + lf + tab
/*------------------------------------------------------------------------*/
PRODUCTIONS
Dafny
-= (. ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at;
+= (. ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at; IteratorDecl iter;
List<MemberDecl/*!*/> membersDefaultClass = new List<MemberDecl/*!*/>();
ModuleDecl submodule;
// to support multiple files, create a default module only if theModule is null
@@ -159,6 +159,8 @@ Dafny
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); .)
+ | (. if (isGhost) { SemErr(t, "an iterator is not allowed to be declared as 'ghost'"); } .)
+ IteratorDecl<defaultModule, out iter> (. defaultModule.TopLevelDecls.Add(iter); .)
| ClassMemberDecl<membersDefaultClass, isGhost, false>
)
}
@@ -178,7 +180,7 @@ Dafny
EOF
.
SubModuleDecl<ModuleDefinition parent, bool isOverallModuleGhost, out ModuleDecl submodule>
-= (. ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at;
+= (. ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at; IteratorDecl iter;
Attributes attrs = null; IToken/*!*/ id;
List<MemberDecl/*!*/> namedModuleDefaultClassMembers = new List<MemberDecl>();;
List<IToken> idRefined = null, idPath = null, idAssignment = null;
@@ -196,13 +198,15 @@ SubModuleDecl<ModuleDefinition parent, bool isOverallModuleGhost, out ModuleDecl
"{" (. module.BodyStartTok = t; .)
{ (. isGhost = false; .)
[ "ghost" (. isGhost = true; .) ]
- ( SubModuleDecl<module, isGhost, out sm> (. module.TopLevelDecls.Add(sm); .)
+ ( SubModuleDecl<module, isGhost, out sm> (. module.TopLevelDecls.Add(sm); .)
| (. if (isGhost) { SemErr(t, "a class is not allowed to be declared as 'ghost'"); } .)
- ClassDecl<module, out c> (. module.TopLevelDecls.Add(c); .)
+ ClassDecl<module, out c> (. module.TopLevelDecls.Add(c); .)
| (. if (isGhost) { SemErr(t, "a datatype/codatatype is not allowed to be declared as 'ghost'"); } .)
- DatatypeDecl<module, out dt> (. module.TopLevelDecls.Add(dt); .)
+ DatatypeDecl<module, out dt> (. module.TopLevelDecls.Add(dt); .)
| (. if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); } .)
- ArbitraryTypeDecl<module, out at> (. module.TopLevelDecls.Add(at); .)
+ ArbitraryTypeDecl<module, out at> (. module.TopLevelDecls.Add(at); .)
+ | (. if (isGhost) { SemErr(t, "an iterator is not allowed to be declared as 'ghost'"); } .)
+ IteratorDecl<module, out iter> (. module.TopLevelDecls.Add(iter); .)
| ClassMemberDecl<namedModuleDefaultClassMembers, isGhost, false>
)
}
@@ -393,6 +397,56 @@ TypeIdentOptional<out IToken/*!*/ id, out string/*!*/ identName, out Type/*!*/ t
.)
.
/*------------------------------------------------------------------------*/
+IteratorDecl<ModuleDefinition module, out IteratorDecl/*!*/ iter>
+= (. Contract.Ensures(Contract.ValueAtReturn(out iter) != null);
+ IToken/*!*/ id;
+ Attributes attrs = null;
+ List<TypeParameter/*!*/>/*!*/ typeArgs = new List<TypeParameter/*!*/>();
+ IToken openParen;
+ List<Formal/*!*/> ins = new List<Formal/*!*/>();
+ List<Formal/*!*/> outs = new List<Formal/*!*/>();
+ List<FrameExpression/*!*/> reads = new List<FrameExpression/*!*/>();
+ List<FrameExpression/*!*/> mod = new List<FrameExpression/*!*/>();
+ List<Expression/*!*/> decreases = new List<Expression>();
+ List<MaybeFreeExpression/*!*/> req = new List<MaybeFreeExpression/*!*/>();
+ List<MaybeFreeExpression/*!*/> ens = new List<MaybeFreeExpression/*!*/>();
+ List<MaybeFreeExpression/*!*/> yieldReq = new List<MaybeFreeExpression/*!*/>();
+ List<MaybeFreeExpression/*!*/> yieldEns = new List<MaybeFreeExpression/*!*/>();
+ List<Expression/*!*/> dec = new List<Expression/*!*/>();
+ Attributes readsAttrs = null;
+ Attributes modAttrs = null;
+ Attributes decrAttrs = null;
+ BlockStmt body = null;
+ bool signatureOmitted = false;
+ IToken bodyStart = Token.NoToken;
+ IToken bodyEnd = Token.NoToken;
+ .)
+ SYNC
+ "iterator"
+ { Attribute<ref attrs> }
+ NoUSIdent<out id>
+ (
+ [ GenericParameters<typeArgs> ]
+ Formals<true, true, ins, out openParen>
+ [ "yields"
+ Formals<false, true, outs, out openParen>
+ ]
+ | "..." (. signatureOmitted = true; openParen = Token.NoToken; .)
+ )
+ { IteratorSpec<reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs> }
+ [ BlockStmt<out body, out bodyStart, out bodyEnd>
+ ]
+ (. iter = new IteratorDecl(id, id.val, module, typeArgs, ins, outs,
+ new Specification<FrameExpression>(reads, readsAttrs),
+ new Specification<FrameExpression>(mod, modAttrs),
+ new Specification<Expression>(decreases, decrAttrs),
+ req, ens, yieldReq, yieldEns,
+ body, attrs, signatureOmitted);
+ iter.BodyStartTok = bodyStart;
+ iter.BodyEndTok = bodyEnd;
+ .)
+ .
+/*------------------------------------------------------------------------*/
GenericParameters<.List<TypeParameter/*!*/>/*!*/ typeArgs.>
= (. Contract.Requires(cce.NonNullElements(typeArgs));
IToken/*!*/ id;
@@ -490,6 +544,44 @@ MethodSpec<.List<MaybeFreeExpression/*!*/>/*!*/ req, List<FrameExpression/*!*/>/
| "decreases" { IF(IsAttribute()) Attribute<ref decAttrs> } DecreasesList<decreases, true> SYNC ";"
)
.
+IteratorSpec<.List<FrameExpression/*!*/>/*!*/ reads, List<FrameExpression/*!*/>/*!*/ mod, List<Expression/*!*/> decreases,
+ List<MaybeFreeExpression/*!*/>/*!*/ req, List<MaybeFreeExpression/*!*/>/*!*/ ens,
+ List<MaybeFreeExpression/*!*/>/*!*/ yieldReq, List<MaybeFreeExpression/*!*/>/*!*/ yieldEns,
+ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs.>
+= (. Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; bool isYield = false; Attributes ensAttrs = null;
+ .)
+ SYNC
+ ( "reads" { IF(IsAttribute()) Attribute<ref readsAttrs> }
+ [ FrameExpression<out fe> (. reads.Add(fe); .)
+ { "," FrameExpression<out fe> (. reads.Add(fe); .)
+ }
+ ] SYNC ";"
+ | "modifies" { IF(IsAttribute()) Attribute<ref modAttrs> }
+ [ FrameExpression<out fe> (. mod.Add(fe); .)
+ { "," FrameExpression<out fe> (. mod.Add(fe); .)
+ }
+ ] SYNC ";"
+ | [ "free" (. isFree = true; .)
+ ]
+ [ "yield" (. isYield = true; .)
+ ]
+ ( "requires" Expression<out e> SYNC ";" (. if (isYield) {
+ yieldReq.Add(new MaybeFreeExpression(e, isFree));
+ } else {
+ req.Add(new MaybeFreeExpression(e, isFree));
+ }
+ .)
+ | "ensures" { IF(IsAttribute()) Attribute<ref ensAttrs> }
+ Expression<out e> SYNC ";" (. if (isYield) {
+ yieldEns.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
+ } else {
+ ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
+ }
+ .)
+ )
+ | "decreases" { IF(IsAttribute()) Attribute<ref decrAttrs> } DecreasesList<decreases, false> SYNC ";"
+ )
+ .
Formals<.bool incoming, bool allowGhostKeyword, List<Formal/*!*/>/*!*/ formals, out IToken openParen.>
= (. Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; bool isGhost; .)
"(" (. openParen = t; .)
@@ -815,14 +907,22 @@ ReturnStmt<out Statement/*!*/ s>
IToken returnTok = null;
List<AssignmentRhs> rhss = null;
AssignmentRhs r;
+ bool isYield = false;
.)
- "return" (. returnTok = t; .)
+ ( "return" (. returnTok = t; .)
+ | "yield" (. returnTok = t; isYield = true; .)
+ )
[
Rhs<out r, null> (. rhss = new List<AssignmentRhs>(); rhss.Add(r); .)
{ "," Rhs<out r, null> (. rhss.Add(r); .)
}
]
- ";" (. s = new ReturnStmt(returnTok, rhss); .)
+ ";" (. if (isYield) {
+ s = new YieldStmt(returnTok, rhss);
+ } else {
+ s = new ReturnStmt(returnTok, rhss);
+ }
+ .)
.
UpdateStmt<out Statement/*!*/ s>
= (. List<Expression> lhss = new List<Expression>();
diff --git a/Dafny/DafnyAst.cs b/Dafny/DafnyAst.cs
index 84154174..345fc6fa 100644
--- a/Dafny/DafnyAst.cs
+++ b/Dafny/DafnyAst.cs
@@ -73,7 +73,7 @@ namespace Microsoft.Dafny {
for (int d = 0; d < dims; d++) {
string name = dims == 1 ? "Length" : "Length" + d;
string compiledName = dims == 1 ? "Length" : "GetLength(" + d + ")";
- Field len = new SpecialField(Token.NoToken, name, compiledName, "new BigInteger(", ")", false, false, Type.Int, null);
+ Field len = new SpecialField(Token.NoToken, name, compiledName, "new BigInteger(", ")", false, false, false, Type.Int, null);
len.EnclosingClass = arrayClass; // resolve here
arrayClass.Members.Add(len);
}
@@ -465,7 +465,7 @@ namespace Microsoft.Dafny {
}
}
- public TopLevelDecl ResolvedClass; // filled in by resolution, if Name denotes a class/datatype and TypeArgs match the type parameters of that class/datatype
+ public TopLevelDecl ResolvedClass; // filled in by resolution, if Name denotes a class/datatype/iterator and TypeArgs match the type parameters of that class/datatype/iterator
public TypeParameter ResolvedParam; // filled in by resolution, if Name denotes an enclosing type parameter and TypeArgs is the empty list
public UserDefinedType(IToken/*!*/ tok, string/*!*/ name, [Captured] List<Type/*!*/>/*!*/ typeArgs, List<IToken> moduleName) {
@@ -481,7 +481,7 @@ namespace Microsoft.Dafny {
}
/// <summary>
- /// This constructor constructs a resolved class type
+ /// This constructor constructs a resolved class/datatype/iterator type
/// </summary>
public UserDefinedType(IToken/*!*/ tok, string/*!*/ name, TopLevelDecl/*!*/ cd, [Captured] List<Type/*!*/>/*!*/ typeArgs) {
Contract.Requires(tok != null);
@@ -744,7 +744,7 @@ namespace Microsoft.Dafny {
public IToken BodyEndTok = Token.NoToken;
public readonly string/*!*/ Name;
string compileName;
- public string CompileName {
+ public virtual string CompileName {
get {
if (compileName == null) {
compileName = NonglobalVariable.CompilerizeName(Name);
@@ -1146,6 +1146,98 @@ namespace Microsoft.Dafny {
}
}
+ public interface ICodeContext : ICallable
+ {
+ bool IsGhost { get; }
+ bool IsStatic { get; }
+ List<TypeParameter> TypeArgs { get; }
+ List<Formal> Ins { get ; }
+ List<Formal> Outs { get; }
+ Specification<FrameExpression> Modifies { get; }
+ Specification<Expression> Decreases { get; }
+ ModuleDefinition EnclosingModule { get; } // to be called only after signature-resolution is complete
+ bool MustReverify { get; }
+ }
+
+ public class IteratorDecl : ClassDecl, ICodeContext
+ {
+ public readonly List<Formal> Ins;
+ public readonly List<Formal> Outs;
+ public readonly Specification<FrameExpression> Reads;
+ public readonly Specification<FrameExpression> Modifies;
+ public readonly Specification<Expression> Decreases;
+ public bool InferredDecreases; // fill in during resolution/registration
+ public readonly List<MaybeFreeExpression> Requires;
+ public readonly List<MaybeFreeExpression> Ensures;
+ public readonly List<MaybeFreeExpression> YieldRequires;
+ public readonly List<MaybeFreeExpression> YieldEnsures;
+ public readonly BlockStmt Body;
+ public readonly bool SignatureIsOmitted;
+ public readonly List<Field> OutsFields;
+ public readonly List<Field> OutsHistoryFields; // these are the 'xs' variables
+ public readonly List<Field> DecreasesFields; // filled in during resolution
+ public SpecialField Member_Modifies; // filled in during resolution
+ public SpecialField Member_Reads; // filled in during resolution
+ public SpecialField Member_New; // filled in during resolution
+ public Constructor Member_Init; // created during registration phase of resolution; its specification is filled in during resolution
+ public Predicate Member_Valid; // created during registration phase of resolution; its specification is filled in during resolution
+ public Method Member_MoveNext; // created during registration phase of resolution; its specification is filled in during resolution
+ public IteratorDecl(IToken tok, string name, ModuleDefinition module, List<TypeParameter> typeArgs,
+ List<Formal> ins, List<Formal> outs,
+ Specification<FrameExpression> reads, Specification<FrameExpression> mod, Specification<Expression> decreases,
+ List<MaybeFreeExpression> requires,
+ List<MaybeFreeExpression> ensures,
+ List<MaybeFreeExpression> yieldRequires,
+ List<MaybeFreeExpression> yieldEnsures,
+ BlockStmt body, Attributes attributes, bool signatureIsOmitted)
+ : base(tok, name, module, typeArgs, new List<MemberDecl>(), attributes)
+ {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(module != null);
+ Contract.Requires(typeArgs != null);
+ Contract.Requires(ins != null);
+ Contract.Requires(outs != null);
+ Contract.Requires(reads != null);
+ Contract.Requires(mod != null);
+ Contract.Requires(decreases != null);
+ Contract.Requires(requires != null);
+ Contract.Requires(ensures != null);
+ Contract.Requires(yieldRequires != null);
+ Contract.Requires(yieldEnsures != null);
+ Ins = ins;
+ Outs = outs;
+ Reads = reads;
+ Modifies = mod;
+ Decreases = decreases;
+ Requires = requires;
+ Ensures = ensures;
+ YieldRequires = yieldRequires;
+ YieldEnsures = yieldEnsures;
+ Body = body;
+ SignatureIsOmitted = signatureIsOmitted;
+
+ OutsFields = new List<Field>();
+ OutsHistoryFields = new List<Field>();
+ DecreasesFields = new List<Field>();
+ }
+
+ bool ICodeContext.IsGhost { get { return false; } }
+ bool ICodeContext.IsStatic { get { return true; } }
+ List<TypeParameter> ICodeContext.TypeArgs { get { return this.TypeArgs; } }
+ List<Formal> ICodeContext.Ins { get { return this.Ins; } }
+ List<Formal> ICodeContext.Outs { get { return this.Outs; } }
+ Specification<FrameExpression> ICodeContext.Modifies { get { return this.Modifies; } }
+ Specification<Expression> ICodeContext.Decreases { get { return this.Decreases; } }
+ ModuleDefinition ICodeContext.EnclosingModule { get { return this.Module; } }
+ bool ICodeContext.MustReverify { get { return false; } }
+ }
+
+ /// <summary>
+ /// An "ICallable" is a function, method, or iterator.
+ /// </summary>
+ public interface ICallable { }
+
public abstract class MemberDecl : Declaration {
public readonly bool IsStatic;
public readonly bool IsGhost;
@@ -1175,6 +1267,15 @@ namespace Microsoft.Dafny {
return EnclosingClass.FullNameInContext(context) + "." + Name;
}
+ public override string CompileName {
+ get {
+ var nm = base.CompileName;
+ if (this.Name == EnclosingClass.Name) {
+ nm = "_" + nm;
+ }
+ return nm;
+ }
+ }
public string FullCompileName {
get {
Contract.Requires(EnclosingClass != null);
@@ -1186,26 +1287,30 @@ namespace Microsoft.Dafny {
}
public class Field : MemberDecl {
- public readonly bool IsMutable;
+ public readonly bool IsMutable; // says whether or not the field can ever change values
+ public readonly bool IsUserMutable; // says whether or not code is allowed to assign to the field (IsUserMutable implies IsMutable)
public readonly Type Type;
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(Type != null);
+ Contract.Invariant(!IsUserMutable || IsMutable); // IsUserMutable ==> IsMutable
}
public Field(IToken tok, string name, bool isGhost, Type type, Attributes attributes)
- : this(tok, name, isGhost, true, type, attributes) {
+ : this(tok, name, isGhost, true, true, type, attributes) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
Contract.Requires(type != null);
}
- public Field(IToken tok, string name, bool isGhost, bool isMutable, Type type, Attributes attributes)
+ public Field(IToken tok, string name, bool isGhost, bool isMutable, bool isUserMutable, Type type, Attributes attributes)
: base(tok, name, false, isGhost, attributes) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
Contract.Requires(type != null);
+ Contract.Requires(!isUserMutable || isMutable);
IsMutable = isMutable;
+ IsUserMutable = isUserMutable;
Type = type;
}
}
@@ -1215,13 +1320,14 @@ namespace Microsoft.Dafny {
public readonly string CompiledName;
public readonly string PreString;
public readonly string PostString;
- public SpecialField(IToken tok, string name, string compiledName, string preString, string postString, bool isGhost, bool isMutable, Type type, Attributes attributes)
- : base(tok, name, isGhost, isMutable, type, attributes) {
+ public SpecialField(IToken tok, string name, string compiledName, string preString, string postString, bool isGhost, bool isMutable, bool isUserMutable, Type type, Attributes attributes)
+ : base(tok, name, isGhost, isMutable, isUserMutable, type, attributes) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
Contract.Requires(compiledName != null);
Contract.Requires(preString != null);
Contract.Requires(postString != null);
+ Contract.Requires(!isUserMutable || isMutable);
Contract.Requires(type != null);
CompiledName = compiledName;
@@ -1236,7 +1342,7 @@ namespace Microsoft.Dafny {
public readonly Formal CorrespondingFormal;
public DatatypeDestructor(IToken tok, DatatypeCtor enclosingCtor, Formal correspondingFormal, string name, string compiledName, string preString, string postString, bool isGhost, Type type, Attributes attributes)
- : base(tok, name, compiledName, preString, postString, isGhost, false, type, attributes)
+ : base(tok, name, compiledName, preString, postString, isGhost, false, false, type, attributes)
{
Contract.Requires(tok != null);
Contract.Requires(enclosingCtor != null);
@@ -1303,31 +1409,31 @@ namespace Microsoft.Dafny {
public string Name {
get {
Contract.Ensures(Contract.Result<string>() != null);
- throw new NotImplementedException();
+ throw new NotImplementedException(); // this getter implementation is here only so that the Ensures contract can be given here
}
}
public string DisplayName {
get {
Contract.Ensures(Contract.Result<string>() != null);
- throw new NotImplementedException();
+ throw new NotImplementedException(); // this getter implementation is here only so that the Ensures contract can be given here
}
}
public string UniqueName {
get {
Contract.Ensures(Contract.Result<string>() != null);
- throw new NotImplementedException();
+ throw new NotImplementedException(); // this getter implementation is here only so that the Ensures contract can be given here
}
}
public string CompileName {
get {
Contract.Ensures(Contract.Result<string>() != null);
- throw new NotImplementedException();
+ throw new NotImplementedException(); // this getter implementation is here only so that the Ensures contract can be given here
}
}
public Type Type {
get {
Contract.Ensures(Contract.Result<Type>() != null);
- throw new NotImplementedException();
+ throw new NotImplementedException(); // this getter implementation is here only so that the Ensures contract can be given here
}
}
public bool IsMutable {
@@ -1502,7 +1608,7 @@ namespace Microsoft.Dafny {
}
}
- public class Function : MemberDecl, TypeParameter.ParentType {
+ public class Function : MemberDecl, TypeParameter.ParentType, ICallable {
public bool IsRecursive; // filled in during resolution
public readonly List<TypeParameter/*!*/>/*!*/ TypeArgs;
public readonly IToken OpenParen; // can be null (for predicates), if there are no formals
@@ -1588,7 +1694,7 @@ namespace Microsoft.Dafny {
}
}
- public class Method : MemberDecl, TypeParameter.ParentType
+ public class Method : MemberDecl, TypeParameter.ParentType, ICodeContext
{
public readonly bool SignatureIsOmitted;
public bool MustReverify;
@@ -1643,6 +1749,21 @@ namespace Microsoft.Dafny {
this.SignatureIsOmitted = signatureOmitted;
MustReverify = false;
}
+
+ bool ICodeContext.IsGhost { get { return this.IsGhost; } }
+ bool ICodeContext.IsStatic { get { return this.IsStatic; } }
+ List<TypeParameter> ICodeContext.TypeArgs { get { return this.TypeArgs; } }
+ List<Formal> ICodeContext.Ins { get { return this.Ins; } }
+ List<Formal> ICodeContext.Outs { get { return this.Outs; } }
+ Specification<FrameExpression> ICodeContext.Modifies { get { return Mod; } }
+ Specification<Expression> ICodeContext.Decreases { get { return this.Decreases; } }
+ ModuleDefinition ICodeContext.EnclosingModule {
+ get {
+ Contract.Assert(this.EnclosingClass != null); // this getter is supposed to be called only after signature-resolution is complete
+ return this.EnclosingClass.Module;
+ }
+ }
+ bool ICodeContext.MustReverify { get { return this.MustReverify; } }
}
public class Constructor : Method
@@ -1854,10 +1975,11 @@ namespace Microsoft.Dafny {
}
}
- public class ReturnStmt : Statement {
+ public abstract class ProduceStmt : Statement
+ {
public List<AssignmentRhs> rhss;
public UpdateStmt hiddenUpdate;
- public ReturnStmt(IToken tok, List<AssignmentRhs> rhss)
+ public ProduceStmt(IToken tok, List<AssignmentRhs> rhss)
: base(tok) {
Contract.Requires(tok != null);
this.rhss = rhss;
@@ -1876,7 +1998,24 @@ namespace Microsoft.Dafny {
}
}
- public abstract class AssignmentRhs {
+ public class ReturnStmt : ProduceStmt
+ {
+ public ReturnStmt(IToken tok, List<AssignmentRhs> rhss)
+ : base(tok, rhss) {
+ Contract.Requires(tok != null);
+ }
+ }
+
+ public class YieldStmt : ProduceStmt
+ {
+ public YieldStmt(IToken tok, List<AssignmentRhs> rhss)
+ : base(tok, rhss) {
+ Contract.Requires(tok != null);
+ }
+ }
+
+ public abstract class AssignmentRhs
+ {
public readonly IToken Tok;
private Attributes attributes;
diff --git a/Dafny/Parser.cs b/Dafny/Parser.cs
index 61af3111..9331775f 100644
--- a/Dafny/Parser.cs
+++ b/Dafny/Parser.cs
@@ -21,7 +21,7 @@ public class Parser {
public const int _colon = 5;
public const int _lbrace = 6;
public const int _rbrace = 7;
- public const int maxT = 112;
+ public const int maxT = 114;
const bool T = true;
const bool x = false;
@@ -189,7 +189,7 @@ bool IsAttribute() {
void Dafny() {
- ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at;
+ ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at; IteratorDecl iter;
List<MemberDecl/*!*/> membersDefaultClass = new List<MemberDecl/*!*/>();
ModuleDecl submodule;
// to support multiple files, create a default module only if theModule is null
@@ -204,24 +204,42 @@ bool IsAttribute() {
Get();
isGhost = true;
}
- if (la.kind == 9 || la.kind == 11) {
+ switch (la.kind) {
+ case 9: case 11: {
SubModuleDecl(defaultModule, isGhost, out submodule);
defaultModule.TopLevelDecls.Add(submodule);
- } else if (la.kind == 18) {
+ break;
+ }
+ case 18: {
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 == 20 || la.kind == 21) {
+ break;
+ }
+ case 20: case 21: {
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 == 25) {
+ break;
+ }
+ case 25: {
if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); }
ArbitraryTypeDecl(defaultModule, out at);
defaultModule.TopLevelDecls.Add(at);
- } else if (StartOf(2)) {
+ break;
+ }
+ case 29: {
+ if (isGhost) { SemErr(t, "an iterator is not allowed to be declared as 'ghost'"); }
+ IteratorDecl(defaultModule, out iter);
+ defaultModule.TopLevelDecls.Add(iter);
+ break;
+ }
+ case 8: case 19: case 23: case 34: case 35: case 52: case 53: case 54: {
ClassMemberDecl(membersDefaultClass, isGhost, false);
- } else SynErr(113);
+ break;
+ }
+ default: SynErr(115); break;
+ }
}
DefaultClassDecl defaultClass = null;
foreach (TopLevelDecl topleveldecl in defaultModule.TopLevelDecls) {
@@ -239,7 +257,7 @@ bool IsAttribute() {
}
void SubModuleDecl(ModuleDefinition parent, bool isOverallModuleGhost, out ModuleDecl submodule) {
- ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at;
+ ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at; IteratorDecl iter;
Attributes attrs = null; IToken/*!*/ id;
List<MemberDecl/*!*/> namedModuleDefaultClassMembers = new List<MemberDecl>();;
List<IToken> idRefined = null, idPath = null, idAssignment = null;
@@ -268,24 +286,42 @@ bool IsAttribute() {
Get();
isGhost = true;
}
- if (la.kind == 9 || la.kind == 11) {
+ switch (la.kind) {
+ case 9: case 11: {
SubModuleDecl(module, isGhost, out sm);
module.TopLevelDecls.Add(sm);
- } else if (la.kind == 18) {
+ break;
+ }
+ case 18: {
if (isGhost) { SemErr(t, "a class is not allowed to be declared as 'ghost'"); }
ClassDecl(module, out c);
module.TopLevelDecls.Add(c);
- } else if (la.kind == 20 || la.kind == 21) {
+ break;
+ }
+ case 20: case 21: {
if (isGhost) { SemErr(t, "a datatype/codatatype is not allowed to be declared as 'ghost'"); }
DatatypeDecl(module, out dt);
module.TopLevelDecls.Add(dt);
- } else if (la.kind == 25) {
+ break;
+ }
+ case 25: {
if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); }
ArbitraryTypeDecl(module, out at);
module.TopLevelDecls.Add(at);
- } else if (StartOf(2)) {
+ break;
+ }
+ case 29: {
+ if (isGhost) { SemErr(t, "an iterator is not allowed to be declared as 'ghost'"); }
+ IteratorDecl(module, out iter);
+ module.TopLevelDecls.Add(iter);
+ break;
+ }
+ case 8: case 19: case 23: case 34: case 35: case 52: case 53: case 54: {
ClassMemberDecl(namedModuleDefaultClassMembers, isGhost, false);
- } else SynErr(114);
+ break;
+ }
+ default: SynErr(116); break;
+ }
}
Expect(7);
module.BodyEndTok = t;
@@ -315,8 +351,8 @@ bool IsAttribute() {
}
Expect(14);
submodule = new AbstractModuleDecl(idPath, id, parent, idAssignment, opened);
- } else SynErr(115);
- } else SynErr(116);
+ } else SynErr(117);
+ } else SynErr(118);
}
void ClassDecl(ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) {
@@ -328,13 +364,13 @@ bool IsAttribute() {
List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>();
IToken bodyStart;
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(117); Get();}
+ while (!(la.kind == 0 || la.kind == 18)) {SynErr(119); Get();}
Expect(18);
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 29) {
+ if (la.kind == 32) {
GenericParameters(typeArgs);
}
Expect(6);
@@ -359,18 +395,18 @@ bool IsAttribute() {
IToken bodyStart = Token.NoToken; // dummy assignment
bool co = false;
- while (!(la.kind == 0 || la.kind == 20 || la.kind == 21)) {SynErr(118); Get();}
+ while (!(la.kind == 0 || la.kind == 20 || la.kind == 21)) {SynErr(120); Get();}
if (la.kind == 20) {
Get();
} else if (la.kind == 21) {
Get();
co = true;
- } else SynErr(119);
+ } else SynErr(121);
while (la.kind == 6) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 29) {
+ if (la.kind == 32) {
GenericParameters(typeArgs);
}
Expect(13);
@@ -380,7 +416,7 @@ bool IsAttribute() {
Get();
DatatypeMemberDecl(ctors);
}
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(120); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(122); Get();}
Expect(14);
if (co) {
dt = new CoDatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
@@ -409,10 +445,70 @@ bool IsAttribute() {
eqSupport = TypeParameter.EqualitySupportValue.Required;
}
at = new ArbitraryTypeDecl(id, id.val, module, eqSupport, attrs);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(121); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(123); Get();}
Expect(14);
}
+ void IteratorDecl(ModuleDefinition module, out IteratorDecl/*!*/ iter) {
+ Contract.Ensures(Contract.ValueAtReturn(out iter) != null);
+ IToken/*!*/ id;
+ Attributes attrs = null;
+ List<TypeParameter/*!*/>/*!*/ typeArgs = new List<TypeParameter/*!*/>();
+ IToken openParen;
+ List<Formal/*!*/> ins = new List<Formal/*!*/>();
+ List<Formal/*!*/> outs = new List<Formal/*!*/>();
+ List<FrameExpression/*!*/> reads = new List<FrameExpression/*!*/>();
+ List<FrameExpression/*!*/> mod = new List<FrameExpression/*!*/>();
+ List<Expression/*!*/> decreases = new List<Expression>();
+ List<MaybeFreeExpression/*!*/> req = new List<MaybeFreeExpression/*!*/>();
+ List<MaybeFreeExpression/*!*/> ens = new List<MaybeFreeExpression/*!*/>();
+ List<MaybeFreeExpression/*!*/> yieldReq = new List<MaybeFreeExpression/*!*/>();
+ List<MaybeFreeExpression/*!*/> yieldEns = new List<MaybeFreeExpression/*!*/>();
+ List<Expression/*!*/> dec = new List<Expression/*!*/>();
+ Attributes readsAttrs = null;
+ Attributes modAttrs = null;
+ Attributes decrAttrs = null;
+ BlockStmt body = null;
+ bool signatureOmitted = false;
+ IToken bodyStart = Token.NoToken;
+ IToken bodyEnd = Token.NoToken;
+
+ while (!(la.kind == 0 || la.kind == 29)) {SynErr(124); Get();}
+ Expect(29);
+ while (la.kind == 6) {
+ Attribute(ref attrs);
+ }
+ NoUSIdent(out id);
+ if (la.kind == 26 || la.kind == 32) {
+ if (la.kind == 32) {
+ GenericParameters(typeArgs);
+ }
+ Formals(true, true, ins, out openParen);
+ if (la.kind == 30) {
+ Get();
+ Formals(false, true, outs, out openParen);
+ }
+ } else if (la.kind == 31) {
+ Get();
+ signatureOmitted = true; openParen = Token.NoToken;
+ } else SynErr(125);
+ while (StartOf(3)) {
+ IteratorSpec(reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs);
+ }
+ if (la.kind == 6) {
+ BlockStmt(out body, out bodyStart, out bodyEnd);
+ }
+ iter = new IteratorDecl(id, id.val, module, typeArgs, ins, outs,
+ new Specification<FrameExpression>(reads, readsAttrs),
+ new Specification<FrameExpression>(mod, modAttrs),
+ new Specification<Expression>(decreases, decrAttrs),
+ req, ens, yieldReq, yieldEns,
+ body, attrs, signatureOmitted);
+ iter.BodyStartTok = bodyStart;
+ iter.BodyEndTok = bodyEnd;
+
+ }
+
void ClassMemberDecl(List<MemberDecl/*!*/>/*!*/ mm, bool isAlreadyGhost, bool allowConstructors) {
Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
@@ -431,13 +527,13 @@ bool IsAttribute() {
}
if (la.kind == 23) {
FieldDecl(mmod, mm);
- } else if (la.kind == 48 || la.kind == 49 || la.kind == 50) {
+ } else if (la.kind == 52 || la.kind == 53 || la.kind == 54) {
FunctionDecl(mmod, out f);
mm.Add(f);
- } else if (la.kind == 31 || la.kind == 32) {
+ } else if (la.kind == 34 || la.kind == 35) {
MethodDecl(mmod, allowConstructors, out m);
mm.Add(m);
- } else SynErr(122);
+ } else SynErr(126);
}
void Attribute(ref Attributes attrs) {
@@ -478,7 +574,7 @@ bool IsAttribute() {
IToken/*!*/ id;
TypeParameter.EqualitySupportValue eqSupport;
- Expect(29);
+ Expect(32);
NoUSIdent(out id);
eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
if (la.kind == 26) {
@@ -500,7 +596,7 @@ bool IsAttribute() {
}
typeArgs.Add(new TypeParameter(id, id.val, eqSupport));
}
- Expect(30);
+ Expect(33);
}
void FieldDecl(MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm) {
@@ -508,7 +604,7 @@ bool IsAttribute() {
Attributes attrs = null;
IToken/*!*/ id; Type/*!*/ ty;
- while (!(la.kind == 0 || la.kind == 23)) {SynErr(123); Get();}
+ while (!(la.kind == 0 || la.kind == 23)) {SynErr(127); Get();}
Expect(23);
if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); }
@@ -522,7 +618,7 @@ bool IsAttribute() {
IdentType(out id, out ty, false);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
}
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(124); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(128); Get();}
Expect(14);
}
@@ -545,9 +641,9 @@ bool IsAttribute() {
IToken bodyEnd = Token.NoToken;
bool signatureOmitted = false;
- if (la.kind == 48) {
+ if (la.kind == 52) {
Get();
- if (la.kind == 31) {
+ if (la.kind == 34) {
Get();
isFunctionMethod = true;
}
@@ -557,22 +653,22 @@ bool IsAttribute() {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 26 || la.kind == 29) {
- if (la.kind == 29) {
+ if (la.kind == 26 || la.kind == 32) {
+ if (la.kind == 32) {
GenericParameters(typeArgs);
}
Formals(true, isFunctionMethod, formals, out openParen);
Expect(5);
Type(out returnType);
- } else if (la.kind == 34) {
+ } else if (la.kind == 31) {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
- } else SynErr(125);
- } else if (la.kind == 49) {
+ } else SynErr(129);
+ } else if (la.kind == 53) {
Get();
isPredicate = true;
- if (la.kind == 31) {
+ if (la.kind == 34) {
Get();
isFunctionMethod = true;
}
@@ -582,8 +678,8 @@ bool IsAttribute() {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (StartOf(3)) {
- if (la.kind == 29) {
+ if (StartOf(4)) {
+ if (la.kind == 32) {
GenericParameters(typeArgs);
}
if (la.kind == 26) {
@@ -593,12 +689,12 @@ bool IsAttribute() {
SemErr(t, "predicates do not have an explicitly declared return type; it is always bool");
}
}
- } else if (la.kind == 34) {
+ } else if (la.kind == 31) {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
- } else SynErr(126);
- } else if (la.kind == 50) {
+ } else SynErr(130);
+ } else if (la.kind == 54) {
Get();
isCoPredicate = true;
if (mmod.IsGhost) { SemErr(t, "copredicates cannot be declared 'ghost' (they are ghost by default)"); }
@@ -607,8 +703,8 @@ bool IsAttribute() {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (StartOf(3)) {
- if (la.kind == 29) {
+ if (StartOf(4)) {
+ if (la.kind == 32) {
GenericParameters(typeArgs);
}
if (la.kind == 26) {
@@ -618,14 +714,14 @@ bool IsAttribute() {
SemErr(t, "copredicates do not have an explicitly declared return type; it is always bool");
}
}
- } else if (la.kind == 34) {
+ } else if (la.kind == 31) {
Get();
signatureOmitted = true;
openParen = Token.NoToken;
- } else SynErr(127);
- } else SynErr(128);
+ } else SynErr(131);
+ } else SynErr(132);
decreases = isCoPredicate ? null : new List<Expression/*!*/>();
- while (StartOf(4)) {
+ while (StartOf(5)) {
FunctionSpec(reqs, reads, ens, decreases);
}
if (la.kind == 6) {
@@ -666,10 +762,10 @@ bool IsAttribute() {
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
- while (!(la.kind == 0 || la.kind == 31 || la.kind == 32)) {SynErr(129); Get();}
- if (la.kind == 31) {
+ while (!(la.kind == 0 || la.kind == 34 || la.kind == 35)) {SynErr(133); Get();}
+ if (la.kind == 34) {
Get();
- } else if (la.kind == 32) {
+ } else if (la.kind == 35) {
Get();
if (allowConstructor) {
isConstructor = true;
@@ -677,7 +773,7 @@ bool IsAttribute() {
SemErr(t, "constructors are only allowed in classes");
}
- } else SynErr(130);
+ } else SynErr(134);
if (isConstructor) {
if (mmod.IsGhost) {
SemErr(t, "constructors cannot be declared 'ghost'");
@@ -691,21 +787,21 @@ bool IsAttribute() {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 26 || la.kind == 29) {
- if (la.kind == 29) {
+ if (la.kind == 26 || la.kind == 32) {
+ if (la.kind == 32) {
GenericParameters(typeArgs);
}
Formals(true, !mmod.IsGhost, ins, out openParen);
- if (la.kind == 33) {
+ if (la.kind == 36) {
Get();
if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); }
Formals(false, !mmod.IsGhost, outs, out openParen);
}
- } else if (la.kind == 34) {
+ } else if (la.kind == 31) {
Get();
signatureOmitted = true; openParen = Token.NoToken;
- } else SynErr(131);
- while (StartOf(5)) {
+ } else SynErr(135);
+ while (StartOf(6)) {
MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs);
}
if (la.kind == 6) {
@@ -742,7 +838,7 @@ bool IsAttribute() {
void FormalsOptionalIds(List<Formal/*!*/>/*!*/ formals) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost;
Expect(26);
- if (StartOf(6)) {
+ if (StartOf(7)) {
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
while (la.kind == 24) {
@@ -849,22 +945,22 @@ bool IsAttribute() {
List<Type/*!*/>/*!*/ gt;
switch (la.kind) {
- case 40: {
+ case 44: {
Get();
tok = t;
break;
}
- case 41: {
+ case 45: {
Get();
tok = t; ty = new NatType();
break;
}
- case 42: {
+ case 46: {
Get();
tok = t; ty = new IntType();
break;
}
- case 43: {
+ case 47: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -875,7 +971,7 @@ bool IsAttribute() {
break;
}
- case 44: {
+ case 48: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -886,7 +982,7 @@ bool IsAttribute() {
break;
}
- case 45: {
+ case 49: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -897,7 +993,7 @@ bool IsAttribute() {
break;
}
- case 46: {
+ case 50: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -908,11 +1004,11 @@ bool IsAttribute() {
break;
}
- case 1: case 3: case 47: {
+ case 1: case 3: case 51: {
ReferenceType(out tok, out ty);
break;
}
- default: SynErr(132); break;
+ default: SynErr(136); break;
}
}
@@ -932,18 +1028,35 @@ bool IsAttribute() {
Expect(28);
}
- void MethodSpec(List<MaybeFreeExpression/*!*/>/*!*/ req, List<FrameExpression/*!*/>/*!*/ mod, List<MaybeFreeExpression/*!*/>/*!*/ ens,
-List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes modAttrs) {
- 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;
+ void IteratorSpec(List<FrameExpression/*!*/>/*!*/ reads, List<FrameExpression/*!*/>/*!*/ mod, List<Expression/*!*/> decreases,
+List<MaybeFreeExpression/*!*/>/*!*/ req, List<MaybeFreeExpression/*!*/>/*!*/ ens,
+List<MaybeFreeExpression/*!*/>/*!*/ yieldReq, List<MaybeFreeExpression/*!*/>/*!*/ yieldEns,
+ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) {
+ Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; bool isYield = false; Attributes ensAttrs = null;
- while (!(StartOf(7))) {SynErr(133); Get();}
- if (la.kind == 35) {
+ while (!(StartOf(8))) {SynErr(137); Get();}
+ if (la.kind == 42) {
+ Get();
+ while (IsAttribute()) {
+ Attribute(ref readsAttrs);
+ }
+ if (StartOf(9)) {
+ FrameExpression(out fe);
+ reads.Add(fe);
+ while (la.kind == 24) {
+ Get();
+ FrameExpression(out fe);
+ reads.Add(fe);
+ }
+ }
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(138); Get();}
+ Expect(14);
+ } else if (la.kind == 37) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
}
- if (StartOf(8)) {
+ if (StartOf(9)) {
FrameExpression(out fe);
mod.Add(fe);
while (la.kind == 24) {
@@ -952,38 +1065,52 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(134); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(139); Get();}
Expect(14);
- } else if (la.kind == 36 || la.kind == 37 || la.kind == 38) {
- if (la.kind == 36) {
+ } else if (StartOf(10)) {
+ if (la.kind == 38) {
Get();
isFree = true;
}
- if (la.kind == 37) {
+ if (la.kind == 43) {
+ Get();
+ isYield = true;
+ }
+ if (la.kind == 39) {
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(135); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(140); Get();}
Expect(14);
- req.Add(new MaybeFreeExpression(e, isFree));
- } else if (la.kind == 38) {
+ if (isYield) {
+ yieldReq.Add(new MaybeFreeExpression(e, isFree));
+ } else {
+ req.Add(new MaybeFreeExpression(e, isFree));
+ }
+
+ } else if (la.kind == 40) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
Expression(out e);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(136); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(141); Get();}
Expect(14);
- ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
- } else SynErr(137);
- } else if (la.kind == 39) {
+ if (isYield) {
+ yieldEns.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
+ } else {
+ ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
+ }
+
+ } else SynErr(142);
+ } else if (la.kind == 41) {
Get();
while (IsAttribute()) {
- Attribute(ref decAttrs);
+ Attribute(ref decrAttrs);
}
- DecreasesList(decreases, true);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(138); Get();}
+ DecreasesList(decreases, false);
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(143); Get();}
Expect(14);
- } else SynErr(139);
+ } else SynErr(144);
}
void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
@@ -992,7 +1119,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expect(6);
bodyStart = t;
- while (StartOf(9)) {
+ while (StartOf(11)) {
Stmt(body);
}
Expect(7);
@@ -1000,6 +1127,60 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
block = new BlockStmt(bodyStart, body);
}
+ void MethodSpec(List<MaybeFreeExpression/*!*/>/*!*/ req, List<FrameExpression/*!*/>/*!*/ mod, List<MaybeFreeExpression/*!*/>/*!*/ ens,
+List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes modAttrs) {
+ 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(12))) {SynErr(145); Get();}
+ if (la.kind == 37) {
+ Get();
+ while (IsAttribute()) {
+ Attribute(ref modAttrs);
+ }
+ if (StartOf(9)) {
+ FrameExpression(out fe);
+ mod.Add(fe);
+ while (la.kind == 24) {
+ Get();
+ FrameExpression(out fe);
+ mod.Add(fe);
+ }
+ }
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(146); Get();}
+ Expect(14);
+ } else if (la.kind == 38 || la.kind == 39 || la.kind == 40) {
+ if (la.kind == 38) {
+ Get();
+ isFree = true;
+ }
+ if (la.kind == 39) {
+ Get();
+ Expression(out e);
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(147); Get();}
+ Expect(14);
+ req.Add(new MaybeFreeExpression(e, isFree));
+ } else if (la.kind == 40) {
+ Get();
+ while (IsAttribute()) {
+ Attribute(ref ensAttrs);
+ }
+ Expression(out e);
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(148); Get();}
+ Expect(14);
+ ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
+ } else SynErr(149);
+ } else if (la.kind == 41) {
+ Get();
+ while (IsAttribute()) {
+ Attribute(ref decAttrs);
+ }
+ DecreasesList(decreases, true);
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(150); Get();}
+ Expect(14);
+ } else SynErr(151);
+ }
+
void FrameExpression(out FrameExpression/*!*/ fe) {
Contract.Ensures(Contract.ValueAtReturn(out fe) != null);
Expression/*!*/ e;
@@ -1007,21 +1188,21 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
string fieldName = null; IToken feTok = null;
fe = null;
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expression(out e);
feTok = e.tok;
- if (la.kind == 53) {
+ if (la.kind == 56) {
Get();
Ident(out id);
fieldName = id.val; feTok = id;
}
fe = new FrameExpression(feTok, e, fieldName);
- } else if (la.kind == 53) {
+ } else if (la.kind == 56) {
Get();
Ident(out id);
fieldName = id.val;
fe = new FrameExpression(id, new ImplicitThisExpr(id), fieldName);
- } else SynErr(140);
+ } else SynErr(152);
}
void Expression(out Expression/*!*/ e) {
@@ -1051,7 +1232,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
void GenericInstantiation(List<Type/*!*/>/*!*/ gt) {
Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty;
- Expect(29);
+ Expect(32);
Type(out ty);
gt.Add(ty);
while (la.kind == 24) {
@@ -1059,7 +1240,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Type(out ty);
gt.Add(ty);
}
- Expect(30);
+ Expect(33);
}
void ReferenceType(out IToken/*!*/ tok, out Type/*!*/ ty) {
@@ -1068,7 +1249,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<Type/*!*/>/*!*/ gt;
List<IToken> path;
- if (la.kind == 47) {
+ if (la.kind == 51) {
Get();
tok = t; ty = new ObjectType();
} else if (la.kind == 3) {
@@ -1093,11 +1274,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
Ident(out tok);
}
- if (la.kind == 29) {
+ if (la.kind == 32) {
GenericInstantiation(gt);
}
ty = new UserDefinedType(tok, tok.val, gt, path);
- } else SynErr(141);
+ } else SynErr(153);
}
void FunctionSpec(List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ reads, List<Expression/*!*/>/*!*/ ens, List<Expression/*!*/> decreases) {
@@ -1105,16 +1286,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Contract.Requires(cce.NonNullElements(reads));
Contract.Requires(decreases == null || cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe;
- if (la.kind == 37) {
- while (!(la.kind == 0 || la.kind == 37)) {SynErr(142); Get();}
+ if (la.kind == 39) {
+ while (!(la.kind == 0 || la.kind == 39)) {SynErr(154); Get();}
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(143); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(155); Get();}
Expect(14);
reqs.Add(e);
- } else if (la.kind == 51) {
+ } else if (la.kind == 42) {
Get();
- if (StartOf(11)) {
+ if (StartOf(14)) {
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
while (la.kind == 24) {
@@ -1123,15 +1304,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
reads.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(144); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(156); Get();}
Expect(14);
- } else if (la.kind == 38) {
+ } else if (la.kind == 40) {
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(145); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(157); Get();}
Expect(14);
ens.Add(e);
- } else if (la.kind == 39) {
+ } else if (la.kind == 41) {
Get();
if (decreases == null) {
SemErr(t, "'decreases' clauses are meaningless for copredicates, so they are not allowed");
@@ -1139,9 +1320,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(146); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(158); Get();}
Expect(14);
- } else SynErr(147);
+ } else SynErr(159);
}
void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) {
@@ -1155,23 +1336,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 == 52) {
+ if (la.kind == 55) {
Get();
fe = new FrameExpression(t, new WildcardExpr(t), null);
- } else if (StartOf(8)) {
+ } else if (StartOf(9)) {
FrameExpression(out fe);
- } else SynErr(148);
+ } else SynErr(160);
}
void PossiblyWildExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e)!=null);
e = dummyExpr;
- if (la.kind == 52) {
+ if (la.kind == 55) {
Get();
e = new WildcardExpr(t);
- } else if (StartOf(10)) {
+ } else if (StartOf(13)) {
Expression(out e);
- } else SynErr(149);
+ } else SynErr(161);
}
void Stmt(List<Statement/*!*/>/*!*/ ss) {
@@ -1188,26 +1369,26 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IToken bodyStart, bodyEnd;
int breakCount;
- while (!(StartOf(12))) {SynErr(150); Get();}
+ while (!(StartOf(15))) {SynErr(162); Get();}
switch (la.kind) {
case 6: {
BlockStmt(out bs, out bodyStart, out bodyEnd);
s = bs;
break;
}
- case 72: {
+ case 75: {
AssertStmt(out s);
break;
}
- case 60: {
+ case 63: {
AssumeStmt(out s);
break;
}
- case 73: {
+ case 76: {
PrintStmt(out s);
break;
}
- case 1: case 2: case 22: case 26: case 98: case 99: case 100: case 101: case 102: case 103: {
+ case 1: case 2: case 22: case 26: case 100: case 101: case 102: case 103: case 104: case 105: {
UpdateStmt(out s);
break;
}
@@ -1215,27 +1396,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
VarDeclStatement(out s);
break;
}
- case 65: {
+ case 68: {
IfStmt(out s);
break;
}
- case 69: {
+ case 72: {
WhileStmt(out s);
break;
}
- case 71: {
+ case 74: {
MatchStmt(out s);
break;
}
- case 74: {
+ case 77: {
ParallelStmt(out s);
break;
}
- case 75: {
- CalcStmt(out s);
- break;
- }
- case 54: {
+ case 57: {
Get();
x = t;
NoUSIdent(out id);
@@ -1244,33 +1421,33 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
s.Labels = new LList<Label>(new Label(x, id.val), s.Labels);
break;
}
- case 55: {
+ case 58: {
Get();
x = t; breakCount = 1; label = null;
if (la.kind == 1) {
NoUSIdent(out id);
label = id.val;
- } else if (la.kind == 14 || la.kind == 55) {
- while (la.kind == 55) {
+ } else if (la.kind == 14 || la.kind == 58) {
+ while (la.kind == 58) {
Get();
breakCount++;
}
- } else SynErr(151);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(152); Get();}
+ } else SynErr(163);
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(164); Get();}
Expect(14);
s = label != null ? new BreakStmt(x, label) : new BreakStmt(x, breakCount);
break;
}
- case 58: {
+ case 43: case 61: {
ReturnStmt(out s);
break;
}
- case 34: {
+ case 31: {
SkeletonStmt(out s);
Expect(14);
break;
}
- default: SynErr(153); break;
+ default: SynErr(165); break;
}
}
@@ -1278,16 +1455,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x;
Expression e = null; Attributes attrs = null;
- Expect(72);
+ Expect(75);
x = t;
while (IsAttribute()) {
Attribute(ref attrs);
}
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expression(out e);
- } else if (la.kind == 34) {
+ } else if (la.kind == 31) {
Get();
- } else SynErr(154);
+ } else SynErr(166);
Expect(14);
if (e == null) {
s = new SkeletonStatement(new AssertStmt(x, new LiteralExpr(x, true), attrs), true, false);
@@ -1301,16 +1478,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x;
Expression e = null; Attributes attrs = null;
- Expect(60);
+ Expect(63);
x = t;
while (IsAttribute()) {
Attribute(ref attrs);
}
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expression(out e);
- } else if (la.kind == 34) {
+ } else if (la.kind == 31) {
Get();
- } else SynErr(155);
+ } else SynErr(167);
if (e == null) {
s = new SkeletonStatement(new AssumeStmt(x, new LiteralExpr(x, true), attrs), true, false);
} else {
@@ -1324,7 +1501,7 @@ 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(73);
+ Expect(76);
x = t;
AttributeArg(out arg);
args.Add(arg);
@@ -1355,14 +1532,14 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
Expect(14);
rhss.Add(new ExprRhs(e, attrs));
- } else if (la.kind == 24 || la.kind == 57 || la.kind == 59) {
+ } else if (la.kind == 24 || la.kind == 60 || la.kind == 62) {
lhss.Add(e); lhs0 = e;
while (la.kind == 24) {
Get();
Lhs(out e);
lhss.Add(e);
}
- if (la.kind == 57) {
+ if (la.kind == 60) {
Get();
x = t;
Rhs(out r, lhs0);
@@ -1372,20 +1549,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Rhs(out r, lhs0);
rhss.Add(r);
}
- } else if (la.kind == 59) {
+ } else if (la.kind == 62) {
Get();
x = t;
- if (la.kind == 60) {
+ if (la.kind == 63) {
Get();
suchThatAssume = t;
}
Expression(out suchThat);
- } else SynErr(156);
+ } else SynErr(168);
Expect(14);
} else if (la.kind == 5) {
Get();
SemErr(t, "invalid statement (did you forget the 'label' keyword?)");
- } else SynErr(157);
+ } else SynErr(169);
if (suchThat != null) {
s = new AssignSuchThatStmt(x, lhss, suchThat, suchThatAssume);
} else {
@@ -1420,8 +1597,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
LocalIdentTypeOptional(out d, isGhost);
lhss.Add(d);
}
- if (la.kind == 57 || la.kind == 59) {
- if (la.kind == 57) {
+ if (la.kind == 60 || la.kind == 62) {
+ if (la.kind == 60) {
Get();
assignTok = t;
lhs0 = new IdentifierExpr(lhss[0].Tok, lhss[0].Name);
@@ -1437,7 +1614,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else {
Get();
assignTok = t;
- if (la.kind == 60) {
+ if (la.kind == 63) {
Get();
suchThatAssume = t;
}
@@ -1476,9 +1653,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<GuardedAlternative> alternatives;
ifStmt = dummyStmt; // to please the compiler
- Expect(65);
+ Expect(68);
x = t;
- if (la.kind == 26 || la.kind == 34) {
+ if (la.kind == 26 || la.kind == 31) {
if (la.kind == 26) {
Guard(out guard);
} else {
@@ -1486,15 +1663,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
guardOmitted = true;
}
BlockStmt(out thn, out bodyStart, out bodyEnd);
- if (la.kind == 66) {
+ if (la.kind == 69) {
Get();
- if (la.kind == 65) {
+ if (la.kind == 68) {
IfStmt(out s);
els = s;
} else if (la.kind == 6) {
BlockStmt(out bs, out bodyStart, out bodyEnd);
els = bs;
- } else SynErr(158);
+ } else SynErr(170);
}
if (guardOmitted) {
ifStmt = new SkeletonStatement(new IfStmt(x, guard, thn, els), true, false);
@@ -1505,7 +1682,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else if (la.kind == 6) {
AlternativeBlock(out alternatives);
ifStmt = new AlternativeStmt(x, alternatives);
- } else SynErr(159);
+ } else SynErr(171);
}
void WhileStmt(out Statement/*!*/ stmt) {
@@ -1521,9 +1698,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<GuardedAlternative> alternatives;
stmt = dummyStmt; // to please the compiler
- Expect(69);
+ Expect(72);
x = t;
- if (la.kind == 26 || la.kind == 34) {
+ if (la.kind == 26 || la.kind == 31) {
if (la.kind == 26) {
Guard(out guard);
Contract.Assume(guard == null || cce.Owner.None(guard));
@@ -1534,10 +1711,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
LoopSpec(out invariants, out decreases, out mod, ref decAttrs, ref modAttrs);
if (la.kind == 6) {
BlockStmt(out body, out bodyStart, out bodyEnd);
- } else if (la.kind == 34) {
+ } else if (la.kind == 31) {
Get();
bodyOmitted = true;
- } else SynErr(160);
+ } else SynErr(172);
if (guardOmitted || bodyOmitted) {
if (mod != null) {
SemErr(mod[0].E.tok, "'modifies' clauses are not allowed on refining loops");
@@ -1553,22 +1730,22 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), body);
}
- } else if (StartOf(13)) {
+ } else if (StartOf(16)) {
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(161);
+ } else SynErr(173);
}
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(71);
+ Expect(74);
x = t;
Expression(out e);
Expect(6);
- while (la.kind == 67) {
+ while (la.kind == 70) {
CaseStatement(out c);
cases.Add(c);
}
@@ -1588,7 +1765,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
BlockStmt/*!*/ block;
IToken bodyStart, bodyEnd;
- Expect(74);
+ Expect(77);
x = t;
Expect(26);
if (la.kind == 1) {
@@ -1601,13 +1778,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (range == null) { range = new LiteralExpr(x, true); }
Expect(28);
- while (la.kind == 36 || la.kind == 38) {
+ while (la.kind == 38 || la.kind == 40) {
isFree = false;
- if (la.kind == 36) {
+ if (la.kind == 38) {
Get();
isFree = true;
}
- Expect(38);
+ Expect(40);
Expression(out e);
Expect(14);
ens.Add(new MaybeFreeExpression(e, isFree));
@@ -1616,68 +1793,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
s = new ParallelStmt(x, bvars, attrs, range, ens, block);
}
- void CalcStmt(out Statement/*!*/ s) {
- Contract.Ensures(Contract.ValueAtReturn(out s) != null);
- Token x;
- BinaryExpr.Opcode op, calcOp = BinaryExpr.Opcode.Eq, resOp = BinaryExpr.Opcode.Eq;
- var lines = new List<Expression/*!*/>();
- var hints = new List<BlockStmt/*!*/>();
- var customOps = new List<BinaryExpr.Opcode?>();
- BinaryExpr.Opcode? maybeOp;
- Expression/*!*/ e;
- BlockStmt/*!*/ h;
- IToken opTok;
-
- Expect(75);
- x = t;
- if (StartOf(14)) {
- CalcOp(out opTok, out calcOp);
- maybeOp = Microsoft.Dafny.CalcStmt.ResultOp(calcOp, calcOp); // guard against non-trasitive calcOp (like !=)
- if (maybeOp == null) {
- SemErr(opTok, "the main operator of a calculation must be transitive");
- }
- resOp = calcOp;
-
- }
- Expect(6);
- if (StartOf(10)) {
- Expression(out e);
- lines.Add(e);
- Expect(14);
- while (StartOf(15)) {
- Hint(out h);
- hints.Add(h);
- if (StartOf(14)) {
- CalcOp(out opTok, out op);
- maybeOp = Microsoft.Dafny.CalcStmt.ResultOp(resOp, op);
- if (maybeOp == null) {
- customOps.Add(null); // pretend the operator was not there to satisfy the precondition of the CalcStmt contructor
- SemErr(opTok, "this operator cannot continue this calculation");
- } else {
- customOps.Add(op);
- resOp = (BinaryExpr.Opcode)maybeOp;
- }
-
- } else if (StartOf(10)) {
- customOps.Add(null);
- } else SynErr(162);
- Expression(out e);
- lines.Add(e);
- Expect(14);
- }
- }
- Expect(7);
- s = new CalcStmt(x, calcOp, lines, hints, customOps);
- }
-
void ReturnStmt(out Statement/*!*/ s) {
IToken returnTok = null;
List<AssignmentRhs> rhss = null;
AssignmentRhs r;
+ bool isYield = false;
- Expect(58);
- returnTok = t;
- if (StartOf(16)) {
+ if (la.kind == 61) {
+ Get();
+ returnTok = t;
+ } else if (la.kind == 43) {
+ Get();
+ returnTok = t; isYield = true;
+ } else SynErr(174);
+ if (StartOf(17)) {
Rhs(out r, null);
rhss = new List<AssignmentRhs>(); rhss.Add(r);
while (la.kind == 24) {
@@ -1687,7 +1816,12 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
}
Expect(14);
- s = new ReturnStmt(returnTok, rhss);
+ if (isYield) {
+ s = new YieldStmt(returnTok, rhss);
+ } else {
+ s = new ReturnStmt(returnTok, rhss);
+ }
+
}
void SkeletonStmt(out Statement s) {
@@ -1695,9 +1829,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<Expression> exprs = null;
IToken tok, dotdotdot, whereTok;
Expression e;
- Expect(34);
+ Expect(31);
dotdotdot = t;
- if (la.kind == 56) {
+ if (la.kind == 59) {
Get();
names = new List<IToken>(); exprs = new List<Expression>(); whereTok = t;
Ident(out tok);
@@ -1707,7 +1841,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Ident(out tok);
names.Add(tok);
}
- Expect(57);
+ Expect(60);
Expression(out e);
exprs.Add(e);
while (la.kind == 24) {
@@ -1734,16 +1868,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
r = dummyRhs; // to please compiler
Attributes attrs = null;
- if (la.kind == 61) {
+ if (la.kind == 64) {
Get();
newToken = t;
TypeAndToken(out x, out ty);
- if (la.kind == 17 || la.kind == 26 || la.kind == 62) {
- if (la.kind == 62) {
+ if (la.kind == 17 || la.kind == 26 || la.kind == 65) {
+ if (la.kind == 65) {
Get();
ee = new List<Expression>();
Expressions(ee);
- Expect(63);
+ Expect(66);
UserDefinedType tmp = theBuiltIns.ArrayType(x, ee.Count, new IntType(), true);
} else if (la.kind == 17) {
@@ -1751,7 +1885,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Ident(out x);
Expect(26);
args = new List<Expression/*!*/>();
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expressions(args);
}
Expect(28);
@@ -1769,7 +1903,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
x = null;
}
args = new List<Expression/*!*/>();
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expressions(args);
}
Expect(28);
@@ -1785,18 +1919,18 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
r = new TypeRhs(newToken, ty, initCall);
}
- } else if (la.kind == 64) {
+ } else if (la.kind == 67) {
Get();
x = t;
Expression(out e);
r = new ExprRhs(new UnaryExpr(x, UnaryExpr.Opcode.SetChoose, e));
- } else if (la.kind == 52) {
+ } else if (la.kind == 55) {
Get();
r = new HavocRhs(t);
- } else if (StartOf(10)) {
+ } else if (StartOf(13)) {
Expression(out e);
r = new ExprRhs(e);
- } else SynErr(163);
+ } else SynErr(175);
while (la.kind == 6) {
Attribute(ref attrs);
}
@@ -1808,16 +1942,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (la.kind == 1) {
DottedIdentifiersAndFunction(out e);
- while (la.kind == 17 || la.kind == 62) {
+ while (la.kind == 17 || la.kind == 65) {
Suffix(ref e);
}
- } else if (StartOf(17)) {
+ } else if (StartOf(18)) {
ConstAtomExpression(out e);
Suffix(ref e);
- while (la.kind == 17 || la.kind == 62) {
+ while (la.kind == 17 || la.kind == 65) {
Suffix(ref e);
}
- } else SynErr(164);
+ } else SynErr(176);
}
void Expressions(List<Expression/*!*/>/*!*/ args) {
@@ -1834,13 +1968,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
void Guard(out Expression e) {
Expression/*!*/ ee; e = null;
Expect(26);
- if (la.kind == 52) {
+ if (la.kind == 55) {
Get();
e = null;
- } else if (StartOf(10)) {
+ } else if (StartOf(13)) {
Expression(out ee);
e = ee;
- } else SynErr(165);
+ } else SynErr(177);
Expect(28);
}
@@ -1851,13 +1985,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<Statement> body;
Expect(6);
- while (la.kind == 67) {
+ while (la.kind == 70) {
Get();
x = t;
Expression(out e);
- Expect(68);
+ Expect(71);
body = new List<Statement>();
- while (StartOf(9)) {
+ while (StartOf(11)) {
Stmt(body);
}
alternatives.Add(new GuardedAlternative(x, e, body));
@@ -1872,29 +2006,29 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
decreases = new List<Expression/*!*/>();
mod = null;
- while (StartOf(18)) {
- if (la.kind == 36 || la.kind == 70) {
+ while (StartOf(19)) {
+ if (la.kind == 38 || la.kind == 73) {
Invariant(out invariant);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(166); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(178); Get();}
Expect(14);
invariants.Add(invariant);
- } else if (la.kind == 39) {
- while (!(la.kind == 0 || la.kind == 39)) {SynErr(167); Get();}
+ } else if (la.kind == 41) {
+ while (!(la.kind == 0 || la.kind == 41)) {SynErr(179); Get();}
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, true);
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(168); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(180); Get();}
Expect(14);
} else {
- while (!(la.kind == 0 || la.kind == 35)) {SynErr(169); Get();}
+ while (!(la.kind == 0 || la.kind == 37)) {SynErr(181); 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 == 24) {
@@ -1903,7 +2037,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 14)) {SynErr(170); Get();}
+ while (!(la.kind == 0 || la.kind == 14)) {SynErr(182); Get();}
Expect(14);
}
}
@@ -1911,12 +2045,12 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
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 == 36 || la.kind == 70)) {SynErr(171); Get();}
- if (la.kind == 36) {
+ while (!(la.kind == 0 || la.kind == 38 || la.kind == 73)) {SynErr(183); Get();}
+ if (la.kind == 38) {
Get();
isFree = true;
}
- Expect(70);
+ Expect(73);
while (IsAttribute()) {
Attribute(ref attrs);
}
@@ -1931,7 +2065,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
BoundVar/*!*/ bv;
List<Statement/*!*/> body = new List<Statement/*!*/>();
- Expect(67);
+ Expect(70);
x = t;
Ident(out id);
if (la.kind == 26) {
@@ -1945,8 +2079,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
Expect(28);
}
- Expect(68);
- while (StartOf(9)) {
+ Expect(71);
+ while (StartOf(11)) {
Stmt(body);
}
c = new MatchCaseStmt(x, id.val, arguments, body);
@@ -1957,10 +2091,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(10)) {
+ } else if (StartOf(13)) {
Expression(out e);
arg = new Attributes.Argument(t, e);
- } else SynErr(172);
+ } else SynErr(184);
}
void QuantifierDomain(out List<BoundVar/*!*/> bvars, out Attributes attrs, out Expression range) {
@@ -1985,112 +2119,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
}
- void CalcOp(out IToken x, out BinaryExpr.Opcode/*!*/ op) {
- Contract.Ensures(Microsoft.Dafny.CalcStmt.ValidOp(Contract.ValueAtReturn(out op)));
- op = BinaryExpr.Opcode.Eq; // Returns Eq if parsing fails because it is compatible with any other operator
- x = null;
-
- switch (la.kind) {
- case 27: {
- Get();
- x = t; op = BinaryExpr.Opcode.Eq;
- break;
- }
- case 29: {
- Get();
- x = t; op = BinaryExpr.Opcode.Lt;
- break;
- }
- case 30: {
- Get();
- x = t; op = BinaryExpr.Opcode.Gt;
- break;
- }
- case 76: {
- Get();
- x = t; op = BinaryExpr.Opcode.Le;
- break;
- }
- case 77: {
- Get();
- x = t; op = BinaryExpr.Opcode.Ge;
- break;
- }
- case 78: {
- Get();
- x = t; op = BinaryExpr.Opcode.Neq;
- break;
- }
- case 79: {
- Get();
- x = t; op = BinaryExpr.Opcode.Neq;
- break;
- }
- case 80: {
- Get();
- x = t; op = BinaryExpr.Opcode.Le;
- break;
- }
- case 81: {
- Get();
- x = t; op = BinaryExpr.Opcode.Ge;
- break;
- }
- case 82: case 83: {
- EquivOp();
- x = t; op = BinaryExpr.Opcode.Iff;
- break;
- }
- case 84: case 85: {
- ImpliesOp();
- x = t; op = BinaryExpr.Opcode.Imp;
- break;
- }
- default: SynErr(173); break;
- }
- }
-
- void Hint(out BlockStmt s) {
- Contract.Ensures(Contract.ValueAtReturn(out s) != null); // returns an empty block statement if the hint is empty
- var subhints = new List<Statement/*!*/>();
- IToken bodyStart, bodyEnd;
- BlockStmt/*!*/ block;
- Statement/*!*/ calc;
- Token x = la;
-
- while (la.kind == 6 || la.kind == 75) {
- if (la.kind == 6) {
- BlockStmt(out block, out bodyStart, out bodyEnd);
- subhints.Add(block);
- } else {
- CalcStmt(out calc);
- subhints.Add(calc);
- }
- }
- s = new BlockStmt(x, subhints); // if the hint is empty x is the first token of the next line, but it doesn't matter cause the block statement is just used as a container
-
- }
-
- void EquivOp() {
- if (la.kind == 82) {
- Get();
- } else if (la.kind == 83) {
- Get();
- } else SynErr(174);
- }
-
- void ImpliesOp() {
- if (la.kind == 84) {
- Get();
- } else if (la.kind == 85) {
- Get();
- } else SynErr(175);
- }
-
void EquivExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
ImpliesExpression(out e0);
- while (la.kind == 82 || la.kind == 83) {
+ while (la.kind == 78 || la.kind == 79) {
EquivOp();
x = t;
ImpliesExpression(out e1);
@@ -2101,7 +2133,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 == 84 || la.kind == 85) {
+ if (la.kind == 80 || la.kind == 81) {
ImpliesOp();
x = t;
ImpliesExpression(out e1);
@@ -2109,16 +2141,24 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
}
+ void EquivOp() {
+ if (la.kind == 78) {
+ Get();
+ } else if (la.kind == 79) {
+ Get();
+ } else SynErr(185);
+ }
+
void LogicalExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
RelationalExpression(out e0);
- if (StartOf(19)) {
- if (la.kind == 86 || la.kind == 87) {
+ if (StartOf(20)) {
+ if (la.kind == 82 || la.kind == 83) {
AndOp();
x = t;
RelationalExpression(out e1);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1);
- while (la.kind == 86 || la.kind == 87) {
+ while (la.kind == 82 || la.kind == 83) {
AndOp();
x = t;
RelationalExpression(out e1);
@@ -2129,7 +2169,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 == 88 || la.kind == 89) {
+ while (la.kind == 84 || la.kind == 85) {
OrOp();
x = t;
RelationalExpression(out e1);
@@ -2139,6 +2179,14 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
}
+ void ImpliesOp() {
+ if (la.kind == 80) {
+ Get();
+ } else if (la.kind == 81) {
+ Get();
+ } else SynErr(186);
+ }
+
void RelationalExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null);
IToken x, firstOpTok = null; Expression e0, e1, acc = null; BinaryExpr.Opcode op;
@@ -2153,7 +2201,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Term(out e0);
e = e0;
- if (StartOf(20)) {
+ if (StartOf(21)) {
RelOp(out x, out op);
firstOpTok = x;
Term(out e1);
@@ -2161,7 +2209,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (op == BinaryExpr.Opcode.Disjoint)
acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, e0, e1); // accumulate first two operands.
- while (StartOf(20)) {
+ while (StartOf(21)) {
if (chain == null) {
chain = new List<Expression>();
ops = new List<BinaryExpr.Opcode>();
@@ -2230,25 +2278,25 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
void AndOp() {
- if (la.kind == 86) {
+ if (la.kind == 82) {
Get();
- } else if (la.kind == 87) {
+ } else if (la.kind == 83) {
Get();
- } else SynErr(176);
+ } else SynErr(187);
}
void OrOp() {
- if (la.kind == 88) {
+ if (la.kind == 84) {
Get();
- } else if (la.kind == 89) {
+ } else if (la.kind == 85) {
Get();
- } else SynErr(177);
+ } else SynErr(188);
}
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 == 93 || la.kind == 94) {
+ while (la.kind == 95 || la.kind == 96) {
AddOp(out x, out op);
Factor(out e1);
e0 = new BinaryExpr(x, op, e0, e1);
@@ -2266,45 +2314,45 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
x = t; op = BinaryExpr.Opcode.Eq;
break;
}
- case 29: {
+ case 32: {
Get();
x = t; op = BinaryExpr.Opcode.Lt;
break;
}
- case 30: {
+ case 33: {
Get();
x = t; op = BinaryExpr.Opcode.Gt;
break;
}
- case 76: {
+ case 86: {
Get();
x = t; op = BinaryExpr.Opcode.Le;
break;
}
- case 77: {
+ case 87: {
Get();
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- case 78: {
+ case 88: {
Get();
x = t; op = BinaryExpr.Opcode.Neq;
break;
}
- case 90: {
+ case 89: {
Get();
x = t; op = BinaryExpr.Opcode.Disjoint;
break;
}
- case 91: {
+ case 90: {
Get();
x = t; op = BinaryExpr.Opcode.In;
break;
}
- case 92: {
+ case 91: {
Get();
x = t; y = Token.NoToken;
- if (la.kind == 91) {
+ if (la.kind == 90) {
Get();
y = t;
}
@@ -2319,29 +2367,29 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
break;
}
- case 79: {
+ case 92: {
Get();
x = t; op = BinaryExpr.Opcode.Neq;
break;
}
- case 80: {
+ case 93: {
Get();
x = t; op = BinaryExpr.Opcode.Le;
break;
}
- case 81: {
+ case 94: {
Get();
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- default: SynErr(178); break;
+ default: SynErr(189); 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 == 52 || la.kind == 95 || la.kind == 96) {
+ while (la.kind == 55 || la.kind == 97 || la.kind == 98) {
MulOp(out x, out op);
UnaryExpression(out e1);
e0 = new BinaryExpr(x, op, e0, e1);
@@ -2350,103 +2398,103 @@ 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 == 93) {
+ if (la.kind == 95) {
Get();
x = t; op = BinaryExpr.Opcode.Add;
- } else if (la.kind == 94) {
+ } else if (la.kind == 96) {
Get();
x = t; op = BinaryExpr.Opcode.Sub;
- } else SynErr(179);
+ } else SynErr(190);
}
void UnaryExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; e = dummyExpr;
switch (la.kind) {
- case 94: {
+ case 96: {
Get();
x = t;
UnaryExpression(out e);
e = new BinaryExpr(x, BinaryExpr.Opcode.Sub, new LiteralExpr(x, 0), e);
break;
}
- case 92: case 97: {
+ case 91: case 99: {
NegOp();
x = t;
UnaryExpression(out e);
e = new UnaryExpr(x, UnaryExpr.Opcode.Not, e);
break;
}
- case 23: case 43: case 54: case 60: case 65: case 71: case 72: case 106: case 107: case 108: case 109: {
+ case 23: case 47: case 57: case 63: case 68: case 74: case 75: case 108: case 109: case 110: case 111: {
EndlessExpression(out e);
break;
}
case 1: {
DottedIdentifiersAndFunction(out e);
- while (la.kind == 17 || la.kind == 62) {
+ while (la.kind == 17 || la.kind == 65) {
Suffix(ref e);
}
break;
}
- case 6: case 62: {
+ case 6: case 65: {
DisplayExpr(out e);
- while (la.kind == 17 || la.kind == 62) {
+ while (la.kind == 17 || la.kind == 65) {
Suffix(ref e);
}
break;
}
- case 44: {
+ case 48: {
MultiSetExpr(out e);
- while (la.kind == 17 || la.kind == 62) {
+ while (la.kind == 17 || la.kind == 65) {
Suffix(ref e);
}
break;
}
- case 46: {
+ case 50: {
Get();
x = t;
- if (la.kind == 62) {
+ if (la.kind == 65) {
MapDisplayExpr(x, out e);
- while (la.kind == 17 || la.kind == 62) {
+ while (la.kind == 17 || la.kind == 65) {
Suffix(ref e);
}
} else if (la.kind == 1) {
MapComprehensionExpr(x, out e);
- } else if (StartOf(21)) {
+ } else if (StartOf(22)) {
SemErr("map must be followed by literal in brackets or comprehension.");
- } else SynErr(180);
+ } else SynErr(191);
break;
}
- case 2: case 22: case 26: case 98: case 99: case 100: case 101: case 102: case 103: {
+ case 2: case 22: case 26: case 100: case 101: case 102: case 103: case 104: case 105: {
ConstAtomExpression(out e);
- while (la.kind == 17 || la.kind == 62) {
+ while (la.kind == 17 || la.kind == 65) {
Suffix(ref e);
}
break;
}
- default: SynErr(181); break;
+ default: SynErr(192); 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 == 52) {
+ if (la.kind == 55) {
Get();
x = t; op = BinaryExpr.Opcode.Mul;
- } else if (la.kind == 95) {
+ } else if (la.kind == 97) {
Get();
x = t; op = BinaryExpr.Opcode.Div;
- } else if (la.kind == 96) {
+ } else if (la.kind == 98) {
Get();
x = t; op = BinaryExpr.Opcode.Mod;
- } else SynErr(182);
+ } else SynErr(193);
}
void NegOp() {
- if (la.kind == 92) {
+ if (la.kind == 91) {
Get();
- } else if (la.kind == 97) {
+ } else if (la.kind == 99) {
Get();
- } else SynErr(183);
+ } else SynErr(194);
}
void EndlessExpression(out Expression e) {
@@ -2455,30 +2503,30 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = dummyExpr;
switch (la.kind) {
- case 65: {
+ case 68: {
Get();
x = t;
Expression(out e);
- Expect(104);
+ Expect(106);
Expression(out e0);
- Expect(66);
+ Expect(69);
Expression(out e1);
e = new ITEExpr(x, e, e0, e1);
break;
}
- case 71: {
+ case 74: {
MatchExpression(out e);
break;
}
- case 106: case 107: case 108: case 109: {
+ case 108: case 109: case 110: case 111: {
QuantifierGuts(out e);
break;
}
- case 43: {
+ case 47: {
ComprehensionExpr(out e);
break;
}
- case 72: {
+ case 75: {
Get();
x = t;
Expression(out e0);
@@ -2487,7 +2535,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = new AssertExpr(x, e0, e1);
break;
}
- case 60: {
+ case 63: {
Get();
x = t;
Expression(out e0);
@@ -2500,11 +2548,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
LetExpr(out e);
break;
}
- case 54: {
+ case 57: {
NamedExpr(out e);
break;
}
- default: SynErr(184); break;
+ default: SynErr(195); break;
}
}
@@ -2523,7 +2571,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (la.kind == 26) {
Get();
openParen = t; args = new List<Expression>();
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expressions(args);
}
Expect(28);
@@ -2543,31 +2591,31 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (la.kind == 26) {
Get();
IToken openParen = t; args = new List<Expression/*!*/>(); func = true;
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expressions(args);
}
Expect(28);
e = new FunctionCallExpr(id, id.val, e, openParen, args);
}
if (!func) { e = new ExprDotName(id, e, id.val); }
- } else if (la.kind == 62) {
+ } else if (la.kind == 65) {
Get();
x = t;
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expression(out ee);
e0 = ee;
- if (la.kind == 105) {
+ if (la.kind == 107) {
Get();
anyDots = true;
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expression(out ee);
e1 = ee;
}
- } else if (la.kind == 57) {
+ } else if (la.kind == 60) {
Get();
Expression(out ee);
e1 = ee;
- } else if (la.kind == 24 || la.kind == 63) {
+ } else if (la.kind == 24 || la.kind == 66) {
while (la.kind == 24) {
Get();
Expression(out ee);
@@ -2578,15 +2626,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
multipleIndices.Add(ee);
}
- } else SynErr(185);
- } else if (la.kind == 105) {
+ } else SynErr(196);
+ } else if (la.kind == 107) {
Get();
anyDots = true;
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expression(out ee);
e1 = ee;
}
- } else SynErr(186);
+ } else SynErr(197);
if (multipleIndices != null) {
e = new MultiSelectExpr(x, e, multipleIndices);
// make sure an array class with this dimensionality exists
@@ -2609,8 +2657,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
}
- Expect(63);
- } else SynErr(187);
+ Expect(66);
+ } else SynErr(198);
}
void DisplayExpr(out Expression e) {
@@ -2621,20 +2669,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (la.kind == 6) {
Get();
x = t; elements = new List<Expression/*!*/>();
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expressions(elements);
}
e = new SetDisplayExpr(x, elements);
Expect(7);
- } else if (la.kind == 62) {
+ } else if (la.kind == 65) {
Get();
x = t; elements = new List<Expression/*!*/>();
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expressions(elements);
}
e = new SeqDisplayExpr(x, elements);
- Expect(63);
- } else SynErr(188);
+ Expect(66);
+ } else SynErr(199);
}
void MultiSetExpr(out Expression e) {
@@ -2642,12 +2690,12 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IToken/*!*/ x = null; List<Expression/*!*/>/*!*/ elements;
e = dummyExpr;
- Expect(44);
+ Expect(48);
x = t;
if (la.kind == 6) {
Get();
elements = new List<Expression/*!*/>();
- if (StartOf(10)) {
+ if (StartOf(13)) {
Expressions(elements);
}
e = new MultiSetDisplayExpr(x, elements);
@@ -2658,9 +2706,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression(out e);
e = new MultiSetFormingExpr(x, e);
Expect(28);
- } else if (StartOf(22)) {
+ } else if (StartOf(23)) {
SemErr("multiset must be followed by multiset literal or expression to coerce in parentheses.");
- } else SynErr(189);
+ } else SynErr(200);
}
void MapDisplayExpr(IToken/*!*/ mapToken, out Expression e) {
@@ -2668,12 +2716,12 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<ExpressionPair/*!*/>/*!*/ elements= new List<ExpressionPair/*!*/>() ;
e = dummyExpr;
- Expect(62);
- if (StartOf(10)) {
+ Expect(65);
+ if (StartOf(13)) {
MapLiteralExpressions(out elements);
}
e = new MapDisplayExpr(mapToken, elements);
- Expect(63);
+ Expect(66);
}
void MapComprehensionExpr(IToken/*!*/ mapToken, out Expression e) {
@@ -2701,17 +2749,17 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = dummyExpr;
switch (la.kind) {
- case 98: {
+ case 100: {
Get();
e = new LiteralExpr(t, false);
break;
}
- case 99: {
+ case 101: {
Get();
e = new LiteralExpr(t, true);
break;
}
- case 100: {
+ case 102: {
Get();
e = new LiteralExpr(t);
break;
@@ -2721,12 +2769,12 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = new LiteralExpr(t, n);
break;
}
- case 101: {
+ case 103: {
Get();
e = new ThisExpr(t);
break;
}
- case 102: {
+ case 104: {
Get();
x = t;
Expect(26);
@@ -2735,7 +2783,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = new FreshExpr(x, e);
break;
}
- case 103: {
+ case 105: {
Get();
x = t;
Expect(26);
@@ -2760,7 +2808,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expect(28);
break;
}
- default: SynErr(190); break;
+ default: SynErr(201); break;
}
}
@@ -2779,34 +2827,34 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression/*!*/ d, r;
elements = new List<ExpressionPair/*!*/>();
Expression(out d);
- Expect(57);
+ Expect(60);
Expression(out r);
elements.Add(new ExpressionPair(d,r));
while (la.kind == 24) {
Get();
Expression(out d);
- Expect(57);
+ Expect(60);
Expression(out r);
elements.Add(new ExpressionPair(d,r));
}
}
void QSep() {
- if (la.kind == 110) {
+ if (la.kind == 112) {
Get();
- } else if (la.kind == 111) {
+ } else if (la.kind == 113) {
Get();
- } else SynErr(191);
+ } else SynErr(202);
}
void MatchExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; MatchCaseExpr/*!*/ c;
List<MatchCaseExpr/*!*/> cases = new List<MatchCaseExpr/*!*/>();
- Expect(71);
+ Expect(74);
x = t;
Expression(out e);
- while (la.kind == 67) {
+ while (la.kind == 70) {
CaseExpression(out c);
cases.Add(c);
}
@@ -2821,13 +2869,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression range;
Expression/*!*/ body;
- if (la.kind == 106 || la.kind == 107) {
+ if (la.kind == 108 || la.kind == 109) {
Forall();
x = t; univ = true;
- } else if (la.kind == 108 || la.kind == 109) {
+ } else if (la.kind == 110 || la.kind == 111) {
Exists();
x = t;
- } else SynErr(192);
+ } else SynErr(203);
QuantifierDomain(out bvars, out attrs, out range);
QSep();
Expression(out body);
@@ -2847,7 +2895,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression/*!*/ range;
Expression body = null;
- Expect(43);
+ Expect(47);
x = t;
IdentTypeOptional(out bv);
bvars.Add(bv);
@@ -2858,7 +2906,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
Expect(22);
Expression(out range);
- if (la.kind == 110 || la.kind == 111) {
+ if (la.kind == 112 || la.kind == 113) {
QSep();
Expression(out body);
}
@@ -2884,7 +2932,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IdentTypeOptional(out d);
letVars.Add(d);
}
- Expect(57);
+ Expect(60);
Expression(out e);
letRHSs.Add(e);
while (la.kind == 24) {
@@ -2902,7 +2950,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = dummyExpr;
Expression expr;
- Expect(54);
+ Expect(57);
x = t;
NoUSIdent(out d);
Expect(5);
@@ -2917,7 +2965,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
BoundVar/*!*/ bv;
Expression/*!*/ body;
- Expect(67);
+ Expect(70);
x = t;
Ident(out id);
if (la.kind == 26) {
@@ -2931,25 +2979,25 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
Expect(28);
}
- Expect(68);
+ Expect(71);
Expression(out body);
c = new MatchCaseExpr(x, id.val, arguments, body);
}
void Forall() {
- if (la.kind == 106) {
+ if (la.kind == 108) {
Get();
- } else if (la.kind == 107) {
+ } else if (la.kind == 109) {
Get();
- } else SynErr(193);
+ } else SynErr(204);
}
void Exists() {
- if (la.kind == 108) {
+ if (la.kind == 110) {
Get();
- } else if (la.kind == 109) {
+ } else if (la.kind == 111) {
Get();
- } else SynErr(194);
+ } else SynErr(205);
}
void AttributeBody(ref Attributes attrs) {
@@ -2960,7 +3008,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expect(5);
Expect(1);
aName = t.val;
- if (StartOf(23)) {
+ if (StartOf(24)) {
AttributeArg(out aArg);
aArgs.Add(aArg);
while (la.kind == 24) {
@@ -2985,30 +3033,31 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
static readonly bool[,]/*!*/ set = {
- {T,T,T,x, x,x,T,x, T,x,x,x, x,x,T,x, x,x,T,x, T,T,T,T, x,x,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,x,T,T, x,x,T,x, T,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,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,T, x,x,x,x, x,x,T,T, T,T,x,T, x,T,x,x, x,x,x,T, T,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,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,T, x,x,x,T, x,x,x,x, x,x,x,T, T,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,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,T, x,x,x,x, x,x,T,T, T,T,x,T, x,T,T,x, x,T,x,T, T,x,x,x, x,T,T,T, 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,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,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,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, 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, 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, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,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,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,T, T,x,T,x, x,x,x,x, x,T,T,x, x,x,x,x, T,x,T,x, x,T,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, T,x,T,x, x,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,x,x, x,x,T,T, x,x,T,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,T,T, x,x,T,x, T,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,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,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,T, T,x,T,x, x,x,x,x, x,x,T,x, x,x,x,x, T,x,T,x, x,T,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, T,x,T,x, x,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, 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,T, T,x,T,x, x,x,x,x, T,T,T,x, x,x,x,x, T,x,T,x, x,T,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, T,x,T,x, x,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,x,x, x,x,T,T, x,x,T,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,T,T, x,x,T,x, T,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,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,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,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,T, 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, 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},
- {x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,T,T, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,T,x, x,x,x,x, x,x,T,x, x,x,x,x, T,x,T,x, x,T,x,x, x,x,x,T, T,x,x,T, T,T,T,T, T,T,T,T, T,T,x,x, x,x,x,x, T,x,T,x, x,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, 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,T, T,x,T,x, x,x,x,x, T,x,T,x, x,x,x,x, T,T,T,x, T,T,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, T,x,T,x, x,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,x,x, x,x,T,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,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,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,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,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,T, 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, T,T,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,T,T, x,x,x,x, x,x,T,x, x,x,x,x, x,x,T,x, T,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, T,T,x,x, x,T,x,x, x,x,x,T, 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,x,x,x, x,x,x,x, T,T,x,x, x,x,T,T, x,x},
- {x,x,x,x, x,x,T,T, x,x,x,x, x,x,T,x, x,T,x,x, x,x,T,x, T,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, T,T,x,x, x,T,x,x, x,x,T,T, 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,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,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,T, T,x,T,x, x,x,x,x, x,x,T,x, x,x,x,x, T,x,T,x, x,T,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, T,x,T,x, x,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,T,x, x,x,T,x, T,T,T,T, x,x,T,x, x,T,x,T, 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,x, x,T,x,T, x,x,x,x, T,x,x,x, 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, 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,T, x,x,x,x, x,x,T,T, T,T,x,T, x,T,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,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, T,x,x,x, x,x,x,x, x,x,x,T, x,x,x,T, 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, 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,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,x,x, x,x,x,x},
+ {T,x,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,T,T, T,T,x,T, x,T,T,x, x,T,x,x, T,x,T,T, x,x,x,T, T,T,T,x, 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,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,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,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, 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, 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, x,x,x,x, x,x,x,x, x,x,x,x, 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,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,x,x, x,x,x,x},
+ {x,T,T,x, x,x,T,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,T, T,x,T,x, x,x,x,x, T,T,x,x, x,x,x,T, x,T,x,x, T,x,x,x, x,x,T,T, 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,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,T,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,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,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, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,T,x, x,x,x,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,T,T,x, x,T,x,T, x,x,x,x, T,x,x,x, T,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, T,T,T,T, T,T,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,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,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,T, T,x,T,x, x,x,x,x, x,T,x,x, x,x,x,T, x,T,x,x, T,x,x,x, x,x,T,T, 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,x,x, T,T,T,T, x,x,x,x},
+ {x,T,T,x, x,x,T,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,T, T,x,T,x, x,x,x,T, T,T,x,x, x,x,x,T, x,T,x,x, T,x,x,x, x,x,T,T, 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,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,x,x, x,x,T,T, x,x,T,x, x,x,x,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,T,T,x, x,T,x,T, x,x,x,x, T,x,x,x, T,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, 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,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,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,T,T,x, x,x,T,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,T, T,x,T,x, x,x,x,T, x,T,x,x, x,x,x,T, T,T,x,T, T,x,x,x, x,x,T,T, 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,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,x,x, x,x,T,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, 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,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,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, 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,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,x,x, x,x,x,x, x,x,x,x, x,x,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,x, x,x,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,T,x, x,x,x,x, x,x,T,x, T,x,x,T, T,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,T, T,x,x,x, T,x,x,x, x,x,T,x, x,T,T,T, 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,x, x,x,x,x, x,x,T,T, x,x,x,x, T,T,x,x},
+ {x,x,x,x, x,x,T,T, x,x,x,x, x,x,T,x, x,T,x,x, x,x,T,x, T,x,x,T, T,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,T, T,x,x,x, T,x,x,x, x,T,T,x, x,T,T,T, 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,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,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,T, T,x,T,x, x,x,x,x, x,T,x,x, x,x,x,T, x,T,x,x, T,x,x,x, x,x,T,T, 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,x,x, T,T,T,T, x,x,x,x}
};
} // end Parser
@@ -3062,172 +3111,183 @@ public class Errors {
case 26: s = "\"(\" expected"; break;
case 27: s = "\"==\" expected"; break;
case 28: s = "\")\" expected"; break;
- case 29: s = "\"<\" expected"; break;
- case 30: s = "\">\" expected"; break;
- case 31: s = "\"method\" expected"; break;
- case 32: s = "\"constructor\" expected"; break;
- case 33: s = "\"returns\" expected"; break;
- case 34: s = "\"...\" expected"; break;
- case 35: s = "\"modifies\" expected"; break;
- case 36: s = "\"free\" expected"; break;
- case 37: s = "\"requires\" expected"; break;
- case 38: s = "\"ensures\" expected"; break;
- case 39: s = "\"decreases\" expected"; break;
- case 40: s = "\"bool\" expected"; break;
- case 41: s = "\"nat\" expected"; break;
- case 42: s = "\"int\" expected"; break;
- case 43: s = "\"set\" expected"; break;
- case 44: s = "\"multiset\" expected"; break;
- case 45: s = "\"seq\" expected"; break;
- case 46: s = "\"map\" expected"; break;
- case 47: s = "\"object\" expected"; break;
- case 48: s = "\"function\" expected"; break;
- case 49: s = "\"predicate\" expected"; break;
- case 50: s = "\"copredicate\" expected"; break;
- case 51: s = "\"reads\" expected"; break;
- case 52: s = "\"*\" expected"; break;
- case 53: s = "\"`\" expected"; break;
- case 54: s = "\"label\" expected"; break;
- case 55: s = "\"break\" expected"; break;
- case 56: s = "\"where\" expected"; break;
- case 57: s = "\":=\" expected"; break;
- case 58: s = "\"return\" expected"; break;
- case 59: s = "\":|\" expected"; break;
- case 60: s = "\"assume\" expected"; break;
- case 61: s = "\"new\" expected"; break;
- case 62: s = "\"[\" expected"; break;
- case 63: s = "\"]\" expected"; break;
- case 64: s = "\"choose\" expected"; break;
- case 65: s = "\"if\" expected"; break;
- case 66: s = "\"else\" expected"; break;
- case 67: s = "\"case\" expected"; break;
- case 68: s = "\"=>\" expected"; break;
- case 69: s = "\"while\" expected"; break;
- case 70: s = "\"invariant\" expected"; break;
- case 71: s = "\"match\" expected"; break;
- case 72: s = "\"assert\" expected"; break;
- case 73: s = "\"print\" expected"; break;
- case 74: s = "\"parallel\" expected"; break;
- case 75: s = "\"calc\" expected"; break;
- case 76: s = "\"<=\" expected"; break;
- case 77: s = "\">=\" expected"; break;
- case 78: s = "\"!=\" expected"; break;
- case 79: s = "\"\\u2260\" expected"; break;
- case 80: s = "\"\\u2264\" expected"; break;
- case 81: s = "\"\\u2265\" expected"; break;
- case 82: s = "\"<==>\" expected"; break;
- case 83: s = "\"\\u21d4\" expected"; break;
- case 84: s = "\"==>\" expected"; break;
- case 85: s = "\"\\u21d2\" expected"; break;
- case 86: s = "\"&&\" expected"; break;
- case 87: s = "\"\\u2227\" expected"; break;
- case 88: s = "\"||\" expected"; break;
- case 89: s = "\"\\u2228\" expected"; break;
- case 90: s = "\"!!\" expected"; break;
- case 91: s = "\"in\" expected"; break;
- case 92: s = "\"!\" expected"; break;
- case 93: s = "\"+\" expected"; break;
- case 94: s = "\"-\" expected"; break;
- case 95: s = "\"/\" expected"; break;
- case 96: s = "\"%\" expected"; break;
- case 97: s = "\"\\u00ac\" expected"; break;
- case 98: s = "\"false\" expected"; break;
- case 99: s = "\"true\" expected"; break;
- case 100: s = "\"null\" expected"; break;
- case 101: s = "\"this\" expected"; break;
- case 102: s = "\"fresh\" expected"; break;
- case 103: s = "\"old\" expected"; break;
- case 104: s = "\"then\" expected"; break;
- case 105: s = "\"..\" expected"; break;
- case 106: s = "\"forall\" expected"; break;
- case 107: s = "\"\\u2200\" expected"; break;
- case 108: s = "\"exists\" expected"; break;
- case 109: s = "\"\\u2203\" expected"; break;
- case 110: s = "\"::\" expected"; break;
- case 111: s = "\"\\u2022\" expected"; break;
- case 112: s = "??? expected"; break;
- case 113: s = "invalid Dafny"; break;
- case 114: s = "invalid SubModuleDecl"; break;
- case 115: s = "invalid SubModuleDecl"; break;
+ case 29: s = "\"iterator\" expected"; break;
+ case 30: s = "\"yields\" expected"; break;
+ case 31: s = "\"...\" expected"; break;
+ case 32: s = "\"<\" expected"; break;
+ case 33: s = "\">\" expected"; break;
+ case 34: s = "\"method\" expected"; break;
+ case 35: s = "\"constructor\" expected"; break;
+ case 36: s = "\"returns\" expected"; break;
+ case 37: s = "\"modifies\" expected"; break;
+ case 38: s = "\"free\" expected"; break;
+ case 39: s = "\"requires\" expected"; break;
+ case 40: s = "\"ensures\" expected"; break;
+ case 41: s = "\"decreases\" expected"; break;
+ case 42: s = "\"reads\" expected"; break;
+ case 43: s = "\"yield\" expected"; break;
+ case 44: s = "\"bool\" expected"; break;
+ case 45: s = "\"nat\" expected"; break;
+ case 46: s = "\"int\" expected"; break;
+ case 47: s = "\"set\" expected"; break;
+ case 48: s = "\"multiset\" expected"; break;
+ case 49: s = "\"seq\" expected"; break;
+ case 50: s = "\"map\" expected"; break;
+ case 51: s = "\"object\" expected"; break;
+ case 52: s = "\"function\" expected"; break;
+ case 53: s = "\"predicate\" expected"; break;
+ case 54: s = "\"copredicate\" expected"; break;
+ case 55: s = "\"*\" expected"; break;
+ case 56: s = "\"`\" expected"; break;
+ case 57: s = "\"label\" expected"; break;
+ case 58: s = "\"break\" expected"; break;
+ case 59: s = "\"where\" expected"; break;
+ case 60: s = "\":=\" expected"; break;
+ case 61: s = "\"return\" expected"; break;
+ case 62: s = "\":|\" expected"; break;
+ case 63: s = "\"assume\" expected"; break;
+ case 64: s = "\"new\" expected"; break;
+ case 65: s = "\"[\" expected"; break;
+ case 66: s = "\"]\" expected"; break;
+ case 67: s = "\"choose\" expected"; break;
+ case 68: s = "\"if\" expected"; break;
+ case 69: s = "\"else\" expected"; break;
+ case 70: s = "\"case\" expected"; break;
+ case 71: s = "\"=>\" expected"; break;
+ case 72: s = "\"while\" expected"; break;
+ case 73: s = "\"invariant\" expected"; break;
+ case 74: s = "\"match\" expected"; break;
+ case 75: s = "\"assert\" expected"; break;
+ case 76: s = "\"print\" expected"; break;
+ case 77: s = "\"parallel\" expected"; break;
+ case 78: s = "\"<==>\" expected"; break;
+ case 79: s = "\"\\u21d4\" expected"; break;
+ case 80: s = "\"==>\" expected"; break;
+ case 81: s = "\"\\u21d2\" expected"; break;
+ case 82: s = "\"&&\" expected"; break;
+ case 83: s = "\"\\u2227\" expected"; break;
+ case 84: s = "\"||\" expected"; break;
+ case 85: s = "\"\\u2228\" expected"; break;
+ case 86: s = "\"<=\" expected"; break;
+ case 87: s = "\">=\" expected"; break;
+ case 88: s = "\"!=\" expected"; break;
+ case 89: s = "\"!!\" expected"; break;
+ case 90: s = "\"in\" expected"; break;
+ case 91: s = "\"!\" expected"; break;
+ case 92: s = "\"\\u2260\" expected"; break;
+ case 93: s = "\"\\u2264\" expected"; break;
+ case 94: s = "\"\\u2265\" expected"; break;
+ case 95: s = "\"+\" expected"; break;
+ case 96: s = "\"-\" expected"; break;
+ case 97: s = "\"/\" expected"; break;
+ case 98: s = "\"%\" expected"; break;
+ case 99: s = "\"\\u00ac\" expected"; break;
+ case 100: s = "\"false\" expected"; break;
+ case 101: s = "\"true\" expected"; break;
+ case 102: s = "\"null\" expected"; break;
+ case 103: s = "\"this\" expected"; break;
+ case 104: s = "\"fresh\" expected"; break;
+ case 105: s = "\"old\" expected"; break;
+ case 106: s = "\"then\" expected"; break;
+ case 107: s = "\"..\" expected"; break;
+ case 108: s = "\"forall\" expected"; break;
+ case 109: s = "\"\\u2200\" expected"; break;
+ case 110: s = "\"exists\" expected"; break;
+ case 111: s = "\"\\u2203\" expected"; break;
+ case 112: s = "\"::\" expected"; break;
+ case 113: s = "\"\\u2022\" expected"; break;
+ case 114: s = "??? expected"; break;
+ case 115: s = "invalid Dafny"; break;
case 116: s = "invalid SubModuleDecl"; break;
- case 117: s = "this symbol not expected in ClassDecl"; break;
- case 118: s = "this symbol not expected in DatatypeDecl"; break;
- case 119: s = "invalid DatatypeDecl"; break;
+ case 117: s = "invalid SubModuleDecl"; break;
+ case 118: s = "invalid SubModuleDecl"; break;
+ case 119: s = "this symbol not expected in ClassDecl"; break;
case 120: s = "this symbol not expected in DatatypeDecl"; break;
- case 121: s = "this symbol not expected in ArbitraryTypeDecl"; break;
- case 122: s = "invalid ClassMemberDecl"; break;
- case 123: s = "this symbol not expected in FieldDecl"; break;
- case 124: s = "this symbol not expected in FieldDecl"; break;
- case 125: s = "invalid FunctionDecl"; break;
- case 126: s = "invalid FunctionDecl"; break;
- case 127: s = "invalid FunctionDecl"; break;
- case 128: s = "invalid FunctionDecl"; break;
- case 129: s = "this symbol not expected in MethodDecl"; break;
- case 130: s = "invalid MethodDecl"; break;
- case 131: s = "invalid MethodDecl"; break;
- case 132: s = "invalid TypeAndToken"; break;
- case 133: s = "this symbol not expected in MethodSpec"; break;
- case 134: s = "this symbol not expected in MethodSpec"; break;
- case 135: s = "this symbol not expected in MethodSpec"; break;
- case 136: s = "this symbol not expected in MethodSpec"; break;
- case 137: s = "invalid MethodSpec"; break;
- case 138: s = "this symbol not expected in MethodSpec"; break;
- case 139: s = "invalid MethodSpec"; break;
- case 140: s = "invalid FrameExpression"; break;
- case 141: s = "invalid ReferenceType"; break;
- case 142: s = "this symbol not expected in FunctionSpec"; break;
- case 143: s = "this symbol not expected in FunctionSpec"; break;
- case 144: s = "this symbol not expected in FunctionSpec"; break;
- case 145: s = "this symbol not expected in FunctionSpec"; break;
- case 146: s = "this symbol not expected in FunctionSpec"; break;
- case 147: s = "invalid FunctionSpec"; break;
- case 148: s = "invalid PossiblyWildFrameExpression"; break;
- case 149: s = "invalid PossiblyWildExpression"; break;
- case 150: s = "this symbol not expected in OneStmt"; break;
- case 151: s = "invalid OneStmt"; break;
- case 152: s = "this symbol not expected in OneStmt"; break;
- case 153: s = "invalid OneStmt"; break;
- case 154: s = "invalid AssertStmt"; break;
- case 155: s = "invalid AssumeStmt"; break;
- case 156: s = "invalid UpdateStmt"; break;
- case 157: s = "invalid UpdateStmt"; break;
- case 158: s = "invalid IfStmt"; break;
- case 159: s = "invalid IfStmt"; break;
- case 160: s = "invalid WhileStmt"; break;
- case 161: s = "invalid WhileStmt"; break;
- case 162: s = "invalid CalcStmt"; break;
- case 163: s = "invalid Rhs"; break;
- case 164: s = "invalid Lhs"; break;
- case 165: s = "invalid Guard"; break;
- case 166: s = "this symbol not expected in LoopSpec"; break;
- case 167: s = "this symbol not expected in LoopSpec"; break;
- case 168: s = "this symbol not expected in LoopSpec"; break;
- case 169: s = "this symbol not expected in LoopSpec"; break;
- case 170: s = "this symbol not expected in LoopSpec"; break;
- case 171: s = "this symbol not expected in Invariant"; break;
- case 172: s = "invalid AttributeArg"; break;
- case 173: s = "invalid CalcOp"; break;
- case 174: s = "invalid EquivOp"; break;
- case 175: s = "invalid ImpliesOp"; break;
- case 176: s = "invalid AndOp"; break;
- case 177: s = "invalid OrOp"; break;
- case 178: s = "invalid RelOp"; break;
- case 179: s = "invalid AddOp"; break;
- case 180: s = "invalid UnaryExpression"; break;
- case 181: s = "invalid UnaryExpression"; break;
- case 182: s = "invalid MulOp"; break;
- case 183: s = "invalid NegOp"; break;
- case 184: s = "invalid EndlessExpression"; break;
- case 185: s = "invalid Suffix"; break;
- case 186: s = "invalid Suffix"; break;
- case 187: s = "invalid Suffix"; break;
- case 188: s = "invalid DisplayExpr"; break;
- case 189: s = "invalid MultiSetExpr"; break;
- case 190: s = "invalid ConstAtomExpression"; break;
- case 191: s = "invalid QSep"; break;
- case 192: s = "invalid QuantifierGuts"; break;
- case 193: s = "invalid Forall"; break;
- case 194: s = "invalid Exists"; break;
+ case 121: s = "invalid DatatypeDecl"; break;
+ case 122: s = "this symbol not expected in DatatypeDecl"; break;
+ case 123: s = "this symbol not expected in ArbitraryTypeDecl"; break;
+ case 124: s = "this symbol not expected in IteratorDecl"; break;
+ case 125: s = "invalid IteratorDecl"; break;
+ case 126: s = "invalid ClassMemberDecl"; break;
+ case 127: s = "this symbol not expected in FieldDecl"; break;
+ case 128: s = "this symbol not expected in FieldDecl"; break;
+ case 129: s = "invalid FunctionDecl"; break;
+ case 130: s = "invalid FunctionDecl"; break;
+ case 131: s = "invalid FunctionDecl"; break;
+ case 132: s = "invalid FunctionDecl"; break;
+ case 133: s = "this symbol not expected in MethodDecl"; break;
+ case 134: s = "invalid MethodDecl"; break;
+ case 135: s = "invalid MethodDecl"; break;
+ case 136: s = "invalid TypeAndToken"; break;
+ case 137: s = "this symbol not expected in IteratorSpec"; break;
+ case 138: s = "this symbol not expected in IteratorSpec"; break;
+ case 139: s = "this symbol not expected in IteratorSpec"; break;
+ case 140: s = "this symbol not expected in IteratorSpec"; break;
+ case 141: s = "this symbol not expected in IteratorSpec"; break;
+ case 142: s = "invalid IteratorSpec"; break;
+ case 143: s = "this symbol not expected in IteratorSpec"; break;
+ case 144: s = "invalid IteratorSpec"; break;
+ case 145: s = "this symbol not expected in MethodSpec"; break;
+ case 146: s = "this symbol not expected in MethodSpec"; break;
+ case 147: s = "this symbol not expected in MethodSpec"; break;
+ case 148: s = "this symbol not expected in MethodSpec"; break;
+ case 149: s = "invalid MethodSpec"; break;
+ case 150: s = "this symbol not expected in MethodSpec"; break;
+ case 151: s = "invalid MethodSpec"; break;
+ case 152: s = "invalid FrameExpression"; break;
+ case 153: s = "invalid ReferenceType"; break;
+ case 154: s = "this symbol not expected in FunctionSpec"; break;
+ case 155: s = "this symbol not expected in FunctionSpec"; break;
+ case 156: s = "this symbol not expected in FunctionSpec"; break;
+ case 157: s = "this symbol not expected in FunctionSpec"; break;
+ case 158: s = "this symbol not expected in FunctionSpec"; break;
+ case 159: s = "invalid FunctionSpec"; break;
+ case 160: s = "invalid PossiblyWildFrameExpression"; break;
+ case 161: s = "invalid PossiblyWildExpression"; break;
+ case 162: s = "this symbol not expected in OneStmt"; break;
+ case 163: s = "invalid OneStmt"; break;
+ case 164: s = "this symbol not expected in OneStmt"; break;
+ case 165: s = "invalid OneStmt"; break;
+ case 166: s = "invalid AssertStmt"; break;
+ case 167: s = "invalid AssumeStmt"; break;
+ case 168: s = "invalid UpdateStmt"; break;
+ case 169: s = "invalid UpdateStmt"; break;
+ case 170: s = "invalid IfStmt"; break;
+ case 171: s = "invalid IfStmt"; break;
+ case 172: s = "invalid WhileStmt"; break;
+ case 173: s = "invalid WhileStmt"; break;
+ case 174: s = "invalid ReturnStmt"; break;
+ case 175: s = "invalid Rhs"; break;
+ case 176: s = "invalid Lhs"; break;
+ case 177: s = "invalid Guard"; break;
+ case 178: s = "this symbol not expected in LoopSpec"; break;
+ case 179: s = "this symbol not expected in LoopSpec"; break;
+ case 180: s = "this symbol not expected in LoopSpec"; break;
+ case 181: s = "this symbol not expected in LoopSpec"; break;
+ case 182: s = "this symbol not expected in LoopSpec"; break;
+ case 183: s = "this symbol not expected in Invariant"; break;
+ case 184: s = "invalid AttributeArg"; break;
+ case 185: s = "invalid EquivOp"; break;
+ case 186: s = "invalid ImpliesOp"; break;
+ case 187: s = "invalid AndOp"; break;
+ case 188: s = "invalid OrOp"; break;
+ case 189: s = "invalid RelOp"; break;
+ case 190: s = "invalid AddOp"; break;
+ case 191: s = "invalid UnaryExpression"; break;
+ case 192: s = "invalid UnaryExpression"; break;
+ case 193: s = "invalid MulOp"; break;
+ case 194: s = "invalid NegOp"; break;
+ case 195: s = "invalid EndlessExpression"; break;
+ case 196: s = "invalid Suffix"; break;
+ case 197: s = "invalid Suffix"; break;
+ case 198: s = "invalid Suffix"; break;
+ case 199: s = "invalid DisplayExpr"; break;
+ case 200: s = "invalid MultiSetExpr"; break;
+ case 201: s = "invalid ConstAtomExpression"; break;
+ case 202: s = "invalid QSep"; break;
+ case 203: s = "invalid QuantifierGuts"; break;
+ case 204: s = "invalid Forall"; break;
+ case 205: s = "invalid Exists"; break;
default: s = "error " + n; break;
}
diff --git a/Dafny/Printer.cs b/Dafny/Printer.cs
index b284f539..36658e2f 100644
--- a/Dafny/Printer.cs
+++ b/Dafny/Printer.cs
@@ -37,10 +37,10 @@ namespace Microsoft.Dafny {
PrintTopLevelDecls(prog.DefaultModuleDef.TopLevelDecls, 0);
}
- public void PrintTopLevelDecls(List<TopLevelDecl> classes, int indent) {
- Contract.Requires(classes!= null);
+ public void PrintTopLevelDecls(List<TopLevelDecl> decls, int indent) {
+ Contract.Requires(decls!= null);
int i = 0;
- foreach (TopLevelDecl d in classes) {
+ foreach (TopLevelDecl d in decls) {
Contract.Assert(d != null);
if (d is ArbitraryTypeDecl) {
var at = (ArbitraryTypeDecl)d;
@@ -54,6 +54,57 @@ namespace Microsoft.Dafny {
} else if (d is DatatypeDecl) {
if (i++ != 0) { wr.WriteLine(); }
PrintDatatype((DatatypeDecl)d, indent);
+ } else if (d is IteratorDecl) {
+ var iter = (IteratorDecl)d;
+ Indent(indent);
+ PrintClassMethodHelper("iterator", iter.Attributes, iter.Name, iter.TypeArgs);
+ if (iter.SignatureIsOmitted) {
+ wr.WriteLine(" ...");
+ } else {
+ PrintFormals(iter.Ins);
+ if (iter.Outs.Count != 0) {
+ if (iter.Ins.Count + iter.Outs.Count <= 3) {
+ wr.Write(" yields ");
+ } else {
+ wr.WriteLine();
+ Indent(indent + 2 * IndentAmount);
+ wr.Write("yields ");
+ }
+ PrintFormals(iter.Outs);
+ }
+ wr.WriteLine();
+ }
+
+ int ind = indent + IndentAmount;
+ PrintSpec("requires", iter.Requires, ind);
+ if (iter.Reads.Expressions != null) {
+ PrintFrameSpecLine("reads", iter.Reads.Expressions, ind, iter.Reads.HasAttributes() ? iter.Reads.Attributes : null);
+ }
+ if (iter.Modifies.Expressions != null) {
+ PrintFrameSpecLine("modifies", iter.Modifies.Expressions, ind, iter.Modifies.HasAttributes() ? iter.Modifies.Attributes : null);
+ }
+ PrintSpec("yield requires", iter.YieldRequires, ind);
+ PrintSpec("yield ensures", iter.YieldEnsures, ind);
+ PrintSpec("ensures", iter.Ensures, ind);
+ PrintDecreasesSpec(iter.Decreases, ind);
+
+ if (iter.Body != null) {
+ Indent(indent);
+ PrintStatement(iter.Body, indent);
+ wr.WriteLine();
+ }
+
+ if (DafnyOptions.O.DafnyPrintResolvedFile != null) {
+ // also print the members that were created as part of the interpretation of the iterator
+ Contract.Assert(iter.Members.Count != 0); // filled in during resolution
+ wr.WriteLine("/*---------- iterator members ----------");
+ PrintClassMethodHelper("class", null, iter.Name, iter.TypeArgs);
+ wr.WriteLine(" {");
+ PrintMembers(iter.Members, indent + IndentAmount);
+ Indent(indent); wr.WriteLine("}");
+ wr.WriteLine("---------- iterator members ----------*/");
+ }
+
} else if (d is ClassDecl) {
ClassDecl cl = (ClassDecl)d;
if (!cl.IsDefaultClass) {
@@ -63,8 +114,9 @@ namespace Microsoft.Dafny {
// print nothing
} else {
if (i++ != 0) { wr.WriteLine(); }
- PrintClass_Members(cl, indent);
+ PrintMembers(cl.Members, indent);
}
+
} else if (d is ModuleDecl) {
wr.WriteLine();
Indent(indent);
@@ -93,6 +145,8 @@ namespace Microsoft.Dafny {
wr.Write(" {0} ", ((AbstractModuleDecl)d).Name);
wr.WriteLine("as {0};", Util.Comma(".", ((AbstractModuleDecl)d).Path, id => id.val));
}
+ } else {
+ Contract.Assert(false); // unexpected TopLevelDecl
}
}
}
@@ -105,19 +159,18 @@ namespace Microsoft.Dafny {
wr.WriteLine(" { }");
} else {
wr.WriteLine(" {");
- PrintClass_Members(c, indent + IndentAmount);
+ PrintMembers(c.Members, indent + IndentAmount);
Indent(indent);
wr.WriteLine("}");
}
}
- public void PrintClass_Members(ClassDecl c, int indent)
+ public void PrintMembers(List<MemberDecl> members, int indent)
{
- Contract.Requires(c != null);
- Contract.Requires( c.Members.Count != 0);
+ Contract.Requires(members != null);
int state = 0; // 0 - no members yet; 1 - previous member was a field; 2 - previous member was non-field
- foreach (MemberDecl m in c.Members) {
+ foreach (MemberDecl m in members) {
if (m is Method) {
if (state != 0) { wr.WriteLine(); }
PrintMethod((Method)m, indent);
@@ -217,7 +270,15 @@ namespace Microsoft.Dafny {
PrintAttributes(field.Attributes);
wr.Write(" {0}: ", field.Name);
PrintType(field.Type);
- wr.WriteLine(";");
+ wr.Write(";");
+ if (field.IsUserMutable) {
+ // nothing more to say
+ } else if (field.IsMutable) {
+ wr.Write(" // may change, but not directly by program");
+ } else {
+ wr.Write(" // immutable");
+ }
+ wr.WriteLine();
}
public void PrintFunction(Function f, int indent) {
@@ -287,7 +348,7 @@ namespace Microsoft.Dafny {
wr.Write(" returns ");
} else {
wr.WriteLine();
- Indent(3 * IndentAmount);
+ Indent(indent + 2 * IndentAmount);
wr.Write("returns ");
}
PrintFormals(method.Outs);
@@ -459,9 +520,9 @@ namespace Microsoft.Dafny {
wr.Write(";");
}
- } else if (stmt is ReturnStmt) {
- var s = (ReturnStmt) stmt;
- wr.Write("return");
+ } else if (stmt is ProduceStmt) {
+ var s = (ProduceStmt) stmt;
+ wr.Write(s is YieldStmt ? "yield" : "return");
if (s.rhss != null) {
var sep = " ";
foreach (var rhs in s.rhss) {
diff --git a/Dafny/RefinementTransformer.cs b/Dafny/RefinementTransformer.cs
index f8f00904..03f8faad 100644
--- a/Dafny/RefinementTransformer.cs
+++ b/Dafny/RefinementTransformer.cs
@@ -128,37 +128,44 @@ namespace Microsoft.Dafny
} else if (dDemandsEqualitySupport) {
if (nw is ClassDecl) {
// fine, as long as "nw" does not take any type parameters
- if (nw.TypeArgs.Count != 0) {
- reporter.Error(nw, "arbitrary type '{0}' is not allowed to be replaced by a class that takes type parameters", nw.Name);
+ if (nw.TypeArgs.Count != d.TypeArgs.Count) {
+ reporter.Error(nw, "arbitrary type '{0}' is not allowed to be replaced by a class that takes a different number of type parameters", nw.Name);
}
} else if (nw is CoDatatypeDecl) {
reporter.Error(nw, "a type declaration that requires equality support cannot be replaced by a codatatype");
} else {
Contract.Assert(nw is IndDatatypeDecl);
- if (nw.TypeArgs.Count != 0) {
- reporter.Error(nw, "arbitrary type '{0}' is not allowed to be replaced by a datatype that takes type parameters", nw.Name);
+ if (nw.TypeArgs.Count != d.TypeArgs.Count) {
+ reporter.Error(nw, "arbitrary type '{0}' is not allowed to be replaced by a datatype that takes a different number of type parameters", nw.Name);
} else {
// Here, we need to figure out if the new type supports equality. But we won't know about that until resolution has
// taken place, so we defer it until the PostResolve phase.
var udt = new UserDefinedType(nw.tok, nw.Name, nw, new List<Type>());
- postTasks.Enqueue(delegate()
- {
+ postTasks.Enqueue(delegate() {
if (!udt.SupportsEquality) {
reporter.Error(udt.tok, "datatype '{0}' is used to refine an arbitrary type with equality support, but '{0}' does not support equality", udt.Name);
}
});
}
}
+ } else if (d.TypeArgs.Count != nw.TypeArgs.Count) {
+ reporter.Error(nw, "arbitrary type '{0}' is not allowed to be replaced by a type that takes a different number of type parameters", nw.Name);
}
}
} else if (nw is ArbitraryTypeDecl) {
reporter.Error(nw, "an arbitrary type declaration ({0}) in a refining module cannot replace a more specific type declaration in the refinement base", nw.Name);
} else if (nw is DatatypeDecl) {
reporter.Error(nw, "a datatype declaration ({0}) in a refinement module can only replace an arbitrary-type declaration", nw.Name);
+ } else if (nw is IteratorDecl) {
+ if (d is IteratorDecl) {
+ m.TopLevelDecls[index] = MergeIterator((IteratorDecl)nw, (IteratorDecl)d);
+ } else {
+ reporter.Error(nw, "an iterator declaration ({0}) is a refining module cannot replace a different kind of declaration in the refinement base", nw.Name);
+ }
} else {
Contract.Assert(nw is ClassDecl);
if (d is DatatypeDecl) {
- reporter.Error(nw, "a class declaration ({0}) in a refining module cannot replace a datatype declaration in the refinement base", nw.Name);
+ reporter.Error(nw, "a class declaration ({0}) in a refining module cannot replace a different kind of declaration in the refinement base", nw.Name);
} else {
m.TopLevelDecls[index] = MergeClass((ClassDecl)nw, (ClassDecl)d);
}
@@ -533,6 +540,66 @@ namespace Microsoft.Dafny
// -------------------------------------------------- Merging ---------------------------------------------------------------
+ IteratorDecl MergeIterator(IteratorDecl nw, IteratorDecl prev) {
+ Contract.Requires(nw != null);
+ Contract.Requires(prev != null);
+
+ if (nw.Requires.Count != 0) {
+ reporter.Error(nw.Requires[0].E.tok, "a refining iterator is not allowed to add preconditions");
+ }
+ if (nw.YieldRequires.Count != 0) {
+ reporter.Error(nw.YieldRequires[0].E.tok, "a refining iterator is not allowed to add yield preconditions");
+ }
+ if (nw.Reads.Expressions.Count != 0) {
+ reporter.Error(nw.Reads.Expressions[0].E.tok, "a refining iterator is not allowed to extend the reads clause");
+ }
+ if (nw.Modifies.Expressions.Count != 0) {
+ reporter.Error(nw.Modifies.Expressions[0].E.tok, "a refining iterator is not allowed to extend the modifies clause");
+ }
+ if (nw.Decreases.Expressions.Count != 0) {
+ reporter.Error(nw.Decreases.Expressions[0].tok, "a refining iterator is not allowed to extend the decreases clause");
+ }
+
+ if (nw.SignatureIsOmitted) {
+ Contract.Assert(nw.TypeArgs.Count == 0);
+ Contract.Assert(nw.Ins.Count == 0);
+ Contract.Assert(nw.Outs.Count == 0);
+ } else {
+ CheckAgreement_TypeParameters(nw.tok, prev.TypeArgs, nw.TypeArgs, nw.Name, "iterator");
+ CheckAgreement_Parameters(nw.tok, prev.Ins, nw.Ins, nw.Name, "iterator", "in-parameter");
+ CheckAgreement_Parameters(nw.tok, prev.Outs, nw.Outs, nw.Name, "iterator", "yield-parameter");
+ }
+
+ BlockStmt newBody;
+ if (nw.Body == null) {
+ newBody = prev.Body;
+ } else if (prev.Body == null) {
+ newBody = nw.Body;
+ } else {
+ newBody = MergeBlockStmt(nw.Body, prev.Body);
+ }
+
+ var ens = prev.Ensures.ConvertAll(rawCloner.CloneMayBeFreeExpr);
+ ens.AddRange(nw.Ensures);
+ var yens = prev.YieldEnsures.ConvertAll(rawCloner.CloneMayBeFreeExpr);
+ yens.AddRange(nw.YieldEnsures);
+
+ return new IteratorDecl(new RefinementToken(nw.tok, moduleUnderConstruction), nw.Name, moduleUnderConstruction,
+ nw.SignatureIsOmitted ? prev.TypeArgs.ConvertAll(refinementCloner.CloneTypeParam) : nw.TypeArgs,
+ nw.SignatureIsOmitted ? prev.Ins.ConvertAll(refinementCloner.CloneFormal) : nw.Ins,
+ nw.SignatureIsOmitted ? prev.Outs.ConvertAll(refinementCloner.CloneFormal) : nw.Outs,
+ refinementCloner.CloneSpecFrameExpr(prev.Reads),
+ refinementCloner.CloneSpecFrameExpr(prev.Modifies),
+ refinementCloner.CloneSpecExpr(prev.Decreases),
+ prev.Requires.ConvertAll(refinementCloner.CloneMayBeFreeExpr),
+ ens,
+ prev.YieldRequires.ConvertAll(refinementCloner.CloneMayBeFreeExpr),
+ yens,
+ newBody,
+ refinementCloner.MergeAttributes(prev.Attributes, nw.Attributes),
+ false);
+ }
+
ClassDecl MergeClass(ClassDecl nw, ClassDecl prev) {
CheckAgreement_TypeParameters(nw.tok, prev.TypeArgs, nw.TypeArgs, nw.Name, "class");
@@ -1209,8 +1276,8 @@ namespace Microsoft.Dafny
}
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 ProduceStmt) {
+ reporter.Error(s, (s is YieldStmt ? "yield" : "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) {
diff --git a/Dafny/Resolver.cs b/Dafny/Resolver.cs
index d5aef85c..61c5800f 100644
--- a/Dafny/Resolver.cs
+++ b/Dafny/Resolver.cs
@@ -5,6 +5,7 @@
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Numerics;
using System.Diagnostics.Contracts;
using System.Linq;
@@ -278,8 +279,9 @@ namespace Microsoft.Dafny
var datatypeDependencies = new Graph<IndDatatypeDecl>();
int prevErrorCount = ErrorCount;
ResolveTopLevelDecls_Signatures(m, m.TopLevelDecls, datatypeDependencies);
- if (ErrorCount == prevErrorCount)
+ if (ErrorCount == prevErrorCount) {
ResolveTopLevelDecls_Meat(m.TopLevelDecls, datatypeDependencies);
+ }
}
@@ -497,11 +499,141 @@ namespace Microsoft.Dafny
} else if (d is ArbitraryTypeDecl) {
// nothing more to register
+ } else if (d is IteratorDecl) {
+ var iter = (IteratorDecl)d;
+
+ // register the names of the implicit members
+ var members = new Dictionary<string, MemberDecl>();
+ classMembers.Add(iter, members);
+
+ // First, register the iterator's in- and out-parameters as readonly fields
+ foreach (var p in iter.Ins) {
+ if (members.ContainsKey(p.Name)) {
+ Error(p, "Name of in-parameter is used by another member of the iterator: {0}", p.Name);
+ } else {
+ var field = new SpecialField(p.tok, p.Name, p.CompileName, "", "", p.IsGhost, false, false, p.Type, null);
+ field.EnclosingClass = iter; // resolve here
+ members.Add(p.Name, field);
+ iter.Members.Add(field);
+ }
+ }
+ foreach (var p in iter.Outs) {
+ if (members.ContainsKey(p.Name)) {
+ Error(p, "Name of yield-parameter is used by another member of the iterator: {0}", p.Name);
+ } else {
+ var field = new SpecialField(p.tok, p.Name, p.CompileName, "", "", p.IsGhost, true, true, p.Type, null);
+ field.EnclosingClass = iter; // resolve here
+ iter.OutsFields.Add(field);
+ members.Add(p.Name, field);
+ iter.Members.Add(field);
+ }
+ }
+ foreach (var p in iter.Outs) {
+ var nm = p.Name + "s";
+ if (members.ContainsKey(nm)) {
+ Error(p.tok, "Name of implicit yield-history variable '{0}' is already used by another member of the iterator", p.Name);
+ } else {
+ var tp = new SeqType(p.Type.IsSubrangeType ? new IntType() : p.Type);
+ var field = new SpecialField(p.tok, nm, nm, "", "", true, true, false, tp, null);
+ field.EnclosingClass = iter; // resolve here
+ iter.OutsHistoryFields.Add(field); // for now, just record this field (until all parameters have been added as members)
+ }
+ }
+ // now that already-used 'ys' names have been checked for, add these yield-history variables
+ iter.OutsHistoryFields.ForEach(f => {
+ members.Add(f.Name, f);
+ iter.Members.Add(f);
+ });
+ // add the additional special variables as fields
+ iter.Member_Reads = new SpecialField(iter.tok, "_reads", "_reads", "", "", true, false, false, new SetType(new ObjectType()), null);
+ iter.Member_Modifies = new SpecialField(iter.tok, "_modifies", "_modifies", "", "", true, false, false, new SetType(new ObjectType()), null);
+ iter.Member_New = new SpecialField(iter.tok, "_new", "_new", "", "", true, true, true, new SetType(new ObjectType()), null);
+ foreach (var field in new List<Field>() { iter.Member_Reads, iter.Member_Modifies, iter.Member_New }) {
+ field.EnclosingClass = iter; // resolve here
+ members.Add(field.Name, field);
+ iter.Members.Add(field);
+ }
+ // finally, add special variables to hold the components of the (explicit or implicit) decreases clause
+ bool inferredDecreases;
+ var decr = Translator.MethodDecreasesWithDefault(iter, out inferredDecreases);
+ if (inferredDecreases) {
+ iter.InferredDecreases = true;
+ Contract.Assert(iter.Decreases.Expressions.Count == 0);
+ iter.Decreases.Expressions.AddRange(decr);
+ }
+ // create the fields; unfortunately, we don't know their types yet, so we'll just insert type proxies for now
+ var i = 0;
+ foreach (var p in iter.Decreases.Expressions) {
+ var nm = "_decreases" + i;
+ var field = new SpecialField(p.tok, nm, nm, "", "", true, false, false, new InferredTypeProxy(), null);
+ field.EnclosingClass = iter; // resolve here
+ iter.DecreasesFields.Add(field);
+ members.Add(field.Name, field);
+ iter.Members.Add(field);
+ i++;
+ }
+
+ // Note, the typeArgs parameter to the following Method/Predicate constructors is passed in as the empty list. What that is
+ // saying is that the Method/Predicate does not take any type parameters over and beyond what the enclosing type (namely, the
+ // iterator type) does.
+ // --- here comes the constructor
+ var init = new Constructor(iter.tok, iter.Name, new List<TypeParameter>(), iter.Ins,
+ new List<MaybeFreeExpression>(),
+ new Specification<FrameExpression>(new List<FrameExpression>(), null),
+ new List<MaybeFreeExpression>(),
+ new Specification<Expression>(new List<Expression>(), null),
+ null, null, false);
+ // --- here comes predicate Valid()
+ var valid = new Predicate(iter.tok, "Valid", false, true, new List<TypeParameter>(), iter.tok,
+ new List<Formal>(),
+ new List<Expression>(),
+ new List<FrameExpression>(),
+ new List<Expression>(),
+ new Specification<Expression>(new List<Expression>(), null),
+ null, Predicate.BodyOriginKind.OriginalOrInherited, null, false);
+ // --- here comes method MoveNext
+ var moveNext = new Method(iter.tok, "MoveNext", false, false, new List<TypeParameter>(),
+ new List<Formal>(), new List<Formal>() { new Formal(iter.tok, "more", Type.Bool, false, false) },
+ new List<MaybeFreeExpression>(),
+ new Specification<FrameExpression>(new List<FrameExpression>(), null),
+ new List<MaybeFreeExpression>(),
+ new Specification<Expression>(new List<Expression>(), null),
+ null, null, false);
+ // add these implicit members to the class
+ init.EnclosingClass = iter;
+ valid.EnclosingClass = iter;
+ moveNext.EnclosingClass = iter;
+ iter.HasConstructor = true;
+ iter.Member_Init = init;
+ iter.Member_Valid = valid;
+ iter.Member_MoveNext = moveNext;
+ MemberDecl member;
+ if (members.TryGetValue(init.Name, out member)) {
+ Error(member.tok, "member name '{0}' is already predefined for this iterator", init.Name);
+ } else {
+ members.Add(init.Name, init);
+ iter.Members.Add(init);
+ }
+ // If the name of the iterator is "Valid" or "MoveNext", one of the following will produce an error message. That
+ // error message may not be as clear as it could be, but the situation also seems unlikely to ever occur in practice.
+ if (members.TryGetValue("Valid", out member)) {
+ Error(member.tok, "member name 'Valid' is already predefined for iterators");
+ } else {
+ members.Add(valid.Name, valid);
+ iter.Members.Add(valid);
+ }
+ if (members.TryGetValue("MoveNext", out member)) {
+ Error(member.tok, "member name 'MoveNext' is already predefined for iterators");
+ } else {
+ members.Add(moveNext.Name, moveNext);
+ iter.Members.Add(moveNext);
+ }
+
} else if (d is ClassDecl) {
ClassDecl cl = (ClassDecl)d;
// register the names of the class members
- Dictionary<string, MemberDecl> members = new Dictionary<string, MemberDecl>();
+ var members = new Dictionary<string, MemberDecl>();
classMembers.Add(cl, members);
bool hasConstructor = false;
@@ -523,14 +655,15 @@ namespace Microsoft.Dafny
}
}
}
+
} else {
DatatypeDecl dt = (DatatypeDecl)d;
// register the names of the constructors
- Dictionary<string, DatatypeCtor> ctors = new Dictionary<string, DatatypeCtor>();
+ var ctors = new Dictionary<string, DatatypeCtor>();
datatypeCtors.Add(dt, ctors);
// ... and of the other members
- Dictionary<string, MemberDecl> members = new Dictionary<string, MemberDecl>();
+ var members = new Dictionary<string, MemberDecl>();
datatypeMembers.Add(dt, members);
foreach (DatatypeCtor ctor in dt.Ctors) {
@@ -543,7 +676,7 @@ namespace Microsoft.Dafny
// create and add the query "method" (field, really)
string queryName = ctor.Name + "?";
- var query = new SpecialField(ctor.tok, queryName, "is_" + ctor.CompileName, "", "", false, false, Type.Bool, null);
+ var query = new SpecialField(ctor.tok, queryName, "is_" + ctor.CompileName, "", "", false, false, false, Type.Bool, null);
query.EnclosingClass = dt; // resolve here
members.Add(queryName, query);
ctor.QueryField = query;
@@ -647,8 +780,9 @@ namespace Microsoft.Dafny
}
MemberDecl CloneMember(MemberDecl member) {
if (member is Field) {
+ Contract.Assert(!(member is SpecialField)); // we don't expect a SpecialField to be cloned (or do we?)
var f = (Field)member;
- return new Field(f.tok, f.Name, f.IsGhost, f.IsMutable, CloneType(f.Type), null);
+ return new Field(f.tok, f.Name, f.IsGhost, f.IsMutable, f.IsUserMutable, CloneType(f.Type), null);
} else if (member is Function) {
var f = (Function)member;
return CloneFunction(f.tok, f, f.IsGhost);
@@ -922,9 +1056,11 @@ namespace Microsoft.Dafny
foreach (TopLevelDecl d in declarations) {
Contract.Assert(d != null);
allTypeParameters.PushMarker();
- ResolveTypeParameters(d.TypeArgs, true, d, true);
+ ResolveTypeParameters(d.TypeArgs, true, d);
if (d is ArbitraryTypeDecl) {
// nothing to do
+ } else if (d is IteratorDecl) {
+ ResolveIteratorSignature((IteratorDecl)d);
} else if (d is ClassDecl) {
ResolveClassMemberTypes((ClassDecl)d);
} else if (d is ModuleDecl) {
@@ -958,9 +1094,19 @@ namespace Microsoft.Dafny
foreach (TopLevelDecl d in declarations) {
Contract.Assert(d != null);
allTypeParameters.PushMarker();
- ResolveTypeParameters(d.TypeArgs, false, d, true);
- if (d is ClassDecl) {
- ResolveClassMemberBodies((ClassDecl)d);
+ ResolveTypeParameters(d.TypeArgs, false, d);
+ if (d is IteratorDecl) {
+ var iter = (IteratorDecl)d;
+ allTypeParameters.PushMarker();
+ ResolveTypeParameters(iter.TypeArgs, false, iter);
+ ResolveIterator(iter);
+ allTypeParameters.PopMarker();
+ ResolveClassMemberBodies(iter); // resolve the automatically generated members
+
+ } else if (d is ClassDecl) {
+ var cl = (ClassDecl)d;
+ ResolveAttributes(cl.Attributes, false);
+ ResolveClassMemberBodies(cl);
}
allTypeParameters.PopMarker();
}
@@ -1068,7 +1214,27 @@ namespace Microsoft.Dafny
} while (inferredSomething);
// Now do it for Function and Method signatures
foreach (var d in declarations) {
- if (d is ClassDecl) {
+ if (d is IteratorDecl) {
+ var iter = (IteratorDecl)d;
+ foreach (var tp in iter.TypeArgs) {
+ if (tp.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
+ // here's our chance to infer the need for equality support
+ foreach (var p in iter.Ins) {
+ if (InferRequiredEqualitySupport(tp, p.Type)) {
+ tp.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
+ goto DONE;
+ }
+ }
+ foreach (var p in iter.Outs) {
+ if (InferRequiredEqualitySupport(tp, p.Type)) {
+ tp.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
+ goto DONE;
+ }
+ }
+ DONE: ;
+ }
+ }
+ } else if (d is ClassDecl) {
var cl = (ClassDecl)d;
foreach (var member in cl.Members) {
if (!member.IsGhost) {
@@ -1117,7 +1283,22 @@ namespace Microsoft.Dafny
// Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
// Note that this check can only be done after determining which expressions are ghosts.
foreach (var d in declarations) {
- if (d is ClassDecl) {
+ if (d is IteratorDecl) {
+ var iter = (IteratorDecl)d;
+ foreach (var p in iter.Ins) {
+ if (!p.IsGhost) {
+ CheckEqualityTypes_Type(p.tok, p.Type);
+ }
+ }
+ foreach (var p in iter.Outs) {
+ if (!p.IsGhost) {
+ CheckEqualityTypes_Type(p.tok, p.Type);
+ }
+ }
+ if (iter.Body != null) {
+ CheckEqualityTypes_Stmt(iter.Body);
+ }
+ } else if (d is ClassDecl) {
var cl = (ClassDecl)d;
foreach (var member in cl.Members) {
if (!member.IsGhost) {
@@ -1431,8 +1612,8 @@ namespace Microsoft.Dafny
}
}
} else if (stmt is BreakStmt) {
- } else if (stmt is ReturnStmt) {
- var s = (ReturnStmt)stmt;
+ } else if (stmt is ProduceStmt) {
+ var s = (ProduceStmt)stmt;
if (s.rhss != null) {
s.rhss.Iter(CheckEqualityTypes_Rhs);
}
@@ -1655,8 +1836,8 @@ namespace Microsoft.Dafny
var s = (PrintStmt)stmt;
s.Args.Iter(arg => CheckTypeInference(arg.E));
} else if (stmt is BreakStmt) {
- } else if (stmt is ReturnStmt) {
- var s = (ReturnStmt)stmt;
+ } else if (stmt is ProduceStmt) {
+ var s = (ProduceStmt)stmt;
if (s.rhss != null) {
s.rhss.Iter(rhs => rhs.SubExpressions.Iter(e => CheckTypeInference(e)));
}
@@ -1800,14 +1981,14 @@ namespace Microsoft.Dafny
} else if (member is Function) {
Function f = (Function)member;
allTypeParameters.PushMarker();
- ResolveTypeParameters(f.TypeArgs, true, f, false);
+ ResolveTypeParameters(f.TypeArgs, true, f);
ResolveFunctionSignature(f);
allTypeParameters.PopMarker();
} else if (member is Method) {
Method m = (Method)member;
allTypeParameters.PushMarker();
- ResolveTypeParameters(m.TypeArgs, true, m, false);
+ ResolveTypeParameters(m.TypeArgs, true, m);
ResolveMethodSignature(m);
allTypeParameters.PopMarker();
@@ -1826,7 +2007,6 @@ namespace Microsoft.Dafny
Contract.Requires(currentClass == null);
Contract.Ensures(currentClass == null);
- ResolveAttributes(cl.Attributes, false);
currentClass = cl;
foreach (MemberDecl member in cl.Members) {
if (member is Field) {
@@ -1836,14 +2016,14 @@ namespace Microsoft.Dafny
} else if (member is Function) {
Function f = (Function)member;
allTypeParameters.PushMarker();
- ResolveTypeParameters(f.TypeArgs, false, f, false);
+ ResolveTypeParameters(f.TypeArgs, false, f);
ResolveFunction(f);
allTypeParameters.PopMarker();
} else if (member is Method) {
Method m = (Method)member;
allTypeParameters.PushMarker();
- ResolveTypeParameters(m.TypeArgs, false, m, false);
+ ResolveTypeParameters(m.TypeArgs, false, m);
ResolveMethod(m);
allTypeParameters.PopMarker();
} else {
@@ -2112,8 +2292,7 @@ namespace Microsoft.Dafny
}
}
- void ResolveTypeParameters(List<TypeParameter/*!*/>/*!*/ tparams, bool emitErrors, TypeParameter.ParentType/*!*/ parent, bool isToplevel) {
-
+ void ResolveTypeParameters(List<TypeParameter/*!*/>/*!*/ tparams, bool emitErrors, TypeParameter.ParentType/*!*/ parent) {
Contract.Requires(tparams != null);
Contract.Requires(parent != null);
// push non-duplicated type parameter names
@@ -2338,6 +2517,247 @@ namespace Microsoft.Dafny
}
/// <summary>
+ /// Assumes type parameters have already been pushed
+ /// </summary>
+ void ResolveIteratorSignature(IteratorDecl iter) {
+ Contract.Requires(iter != null);
+ scope.PushMarker();
+ if (iter.SignatureIsOmitted) {
+ Error(iter, "iterator signature can be omitted only in refining methods");
+ }
+ var defaultTypeArguments = iter.TypeArgs.Count == 0 ? iter.TypeArgs : null;
+ // resolve the types of the parameters
+ foreach (var p in iter.Ins.Concat(iter.Outs)) {
+ ResolveType(p.tok, p.Type, defaultTypeArguments, true);
+ }
+ // resolve the types of the added fields (in case some of these types would cause the addition of default type arguments)
+ foreach (var p in iter.OutsHistoryFields) {
+ ResolveType(p.tok, p.Type, defaultTypeArguments, true);
+ }
+ scope.PopMarker();
+ }
+
+ /// <summary>
+ /// Assumes type parameters have already been pushed
+ /// </summary>
+ void ResolveIterator(IteratorDecl iter) {
+ Contract.Requires(iter != null);
+ Contract.Requires(currentClass == null);
+ Contract.Ensures(currentClass == null);
+
+ var initialErrorCount = ErrorCount;
+
+ // Add in-parameters to the scope, but don't care about any duplication errors, since they have already been reported
+ scope.PushMarker();
+ scope.AllowInstance = false; // disallow 'this' from use, which means that the special fields and methods added are not accessible in the syntactically given spec
+ iter.Ins.ForEach(p => scope.Push(p.Name, p));
+
+ // Start resolving specification...
+ // we start with the decreases clause, because the _decreases<n> fields were only given type proxies before; we'll know
+ // the types only after resolving the decreases clause (and it may be that some of resolution has already seen uses of
+ // these fields; so, with no further ado, here we go
+ Contract.Assert(iter.Decreases.Expressions.Count == iter.DecreasesFields.Count);
+ for (int i = 0; i < iter.Decreases.Expressions.Count; i++) {
+ var e = iter.Decreases.Expressions[i];
+ ResolveExpression(e, false);
+ // any type is fine, but associate this type with the corresponding _decreases<n> field
+ var d = iter.DecreasesFields[i];
+ if (!UnifyTypes(d.Type, e.Type)) {
+ // bummer, there was a use--and a bad use--of the field before, so this won't be the best of error messages
+ Error(e, "type of field {0} is {1}, but has been constrained elsewhere to be of type {2}", d.Name, e.Type, d.Type);
+ }
+ }
+ foreach (FrameExpression fe in iter.Reads.Expressions) {
+ ResolveFrameExpression(fe, "reads");
+ }
+ foreach (FrameExpression fe in iter.Modifies.Expressions) {
+ ResolveFrameExpression(fe, "modifies");
+ }
+ foreach (MaybeFreeExpression e in iter.Requires) {
+ ResolveExpression(e.E, false);
+ Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.E.Type, Type.Bool)) {
+ Error(e.E, "Precondition must be a boolean (got {0})", e.E.Type);
+ }
+ }
+
+ scope.PopMarker(); // for the in-parameters
+
+ // We resolve the rest of the specification in an instance context. So mentions of the in- or yield-parameters
+ // get resolved as field dereferences (with an implicit "this")
+ scope.PushMarker();
+ currentClass = iter;
+ Contract.Assert(scope.AllowInstance);
+
+ foreach (MaybeFreeExpression e in iter.YieldRequires) {
+ ResolveExpression(e.E, false);
+ Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.E.Type, Type.Bool)) {
+ Error(e.E, "Yield precondition must be a boolean (got {0})", e.E.Type);
+ }
+ }
+ foreach (MaybeFreeExpression e in iter.YieldEnsures) {
+ ResolveExpression(e.E, true);
+ Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.E.Type, Type.Bool)) {
+ Error(e.E, "Yield postcondition must be a boolean (got {0})", e.E.Type);
+ }
+ }
+ foreach (MaybeFreeExpression e in iter.Ensures) {
+ ResolveExpression(e.E, true);
+ Contract.Assert(e.E.Type != null); // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.E.Type, Type.Bool)) {
+ Error(e.E, "Postcondition must be a boolean (got {0})", e.E.Type);
+ }
+ }
+
+ ResolveAttributes(iter.Attributes, false);
+
+ var postSpecErrorCount = ErrorCount;
+
+ // Resolve body
+ if (iter.Body != null) {
+ ResolveBlockStatement(iter.Body, false, iter);
+ }
+
+ currentClass = null;
+ scope.PopMarker(); // pop off the AllowInstance setting
+
+ if (postSpecErrorCount == initialErrorCount) {
+ CreateIteratorMethodSpecs(iter);
+ }
+ }
+
+ /// <summary>
+ /// Assumes the specification of the iterator itself has been successfully resolved.
+ /// </summary>
+ void CreateIteratorMethodSpecs(IteratorDecl iter) {
+ Contract.Requires(iter != null);
+
+ // ---------- here comes the constructor ----------
+ // same requires clause as the iterator itself
+ iter.Member_Init.Req.AddRange(iter.Requires);
+ // modifies this;
+ iter.Member_Init.Mod.Expressions.Add(new FrameExpression(iter.tok, new ThisExpr(iter.tok), null));
+ var ens = iter.Member_Init.Ens;
+ foreach (var p in iter.Ins) {
+ // ensures this.x == x;
+ ens.Add(new MaybeFreeExpression(new BinaryExpr(p.tok, BinaryExpr.Opcode.Eq,
+ new FieldSelectExpr(p.tok, new ThisExpr(p.tok), p.Name), new IdentifierExpr(p.tok, p.Name))));
+ }
+ foreach (var p in iter.OutsHistoryFields) {
+ // ensures this.ys == [];
+ ens.Add(new MaybeFreeExpression(new BinaryExpr(p.tok, BinaryExpr.Opcode.Eq,
+ new FieldSelectExpr(p.tok, new ThisExpr(p.tok), p.Name), new SeqDisplayExpr(p.tok, new List<Expression>()))));
+ }
+ // ensures this.Valid();
+ ens.Add(new MaybeFreeExpression(new FunctionCallExpr(iter.tok, "Valid", new ThisExpr(iter.tok), iter.tok, new List<Expression>())));
+ // ensures this._reads == old(ReadsClause);
+ var modSetSingletons = new List<Expression>();
+ Expression frameSet = new SetDisplayExpr(iter.tok, modSetSingletons);
+ foreach (var fr in iter.Reads.Expressions) {
+ if (fr.FieldName != null) {
+ Error(fr.tok, "sorry, a reads clause for an iterator is not allowed to designate specific fields");
+ } else if (fr.E.Type.IsRefType) {
+ modSetSingletons.Add(fr.E);
+ } else {
+ frameSet = new BinaryExpr(fr.tok, BinaryExpr.Opcode.Add, frameSet, fr.E);
+ }
+ }
+ ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Eq,
+ new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_reads"),
+ new OldExpr(iter.tok, frameSet))));
+ // ensures this._modifies == old(ModifiesClause);
+ modSetSingletons = new List<Expression>();
+ frameSet = new SetDisplayExpr(iter.tok, modSetSingletons);
+ foreach (var fr in iter.Modifies.Expressions) {
+ if (fr.FieldName != null) {
+ Error(fr.tok, "sorry, a modifies clause for an iterator is not allowed to designate specific fields");
+ } else if (fr.E.Type.IsRefType) {
+ modSetSingletons.Add(fr.E);
+ } else {
+ frameSet = new BinaryExpr(fr.tok, BinaryExpr.Opcode.Add, frameSet, fr.E);
+ }
+ }
+ ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Eq,
+ new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_modifies"),
+ new OldExpr(iter.tok, frameSet))));
+ // ensures this._new == {};
+ ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Eq,
+ new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"),
+ new SetDisplayExpr(iter.tok, new List<Expression>()))));
+ // ensures this._decreases0 == old(DecreasesClause[0]) && ...;
+ Contract.Assert(iter.Decreases.Expressions.Count == iter.DecreasesFields.Count);
+ for (int i = 0; i < iter.Decreases.Expressions.Count; i++) {
+ var p = iter.Decreases.Expressions[i];
+ ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Eq,
+ new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), iter.DecreasesFields[i].Name),
+ new OldExpr(iter.tok, p))));
+ }
+
+ // ---------- here comes predicate Valid() ----------
+ var reads = iter.Member_Valid.Reads;
+ reads.Add(new FrameExpression(iter.tok, new ThisExpr(iter.tok), null)); // reads this;
+ reads.Add(new FrameExpression(iter.tok, new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_reads"), null)); // reads this._reads;
+ reads.Add(new FrameExpression(iter.tok, new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"), null)); // reads this._new;
+
+ // ---------- here comes method MoveNext() ----------
+ // requires this.Valid();
+ var req = iter.Member_MoveNext.Req;
+ req.Add(new MaybeFreeExpression(new FunctionCallExpr(iter.tok, "Valid", new ThisExpr(iter.tok), iter.tok, new List<Expression>())));
+ // requires YieldRequires;
+ req.AddRange(iter.YieldRequires);
+ // modifies this, this._modifies, this._new;
+ var mod = iter.Member_MoveNext.Mod.Expressions;
+ mod.Add(new FrameExpression(iter.tok, new ThisExpr(iter.tok), null));
+ mod.Add(new FrameExpression(iter.tok, new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_modifies"), null));
+ mod.Add(new FrameExpression(iter.tok, new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"), null));
+ // ensures fresh(_new - old(_new));
+ ens = iter.Member_MoveNext.Ens;
+ ens.Add(new MaybeFreeExpression(new FreshExpr(iter.tok,
+ new BinaryExpr(iter.tok, BinaryExpr.Opcode.Sub,
+ new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"),
+ new OldExpr(iter.tok, new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"))))));
+ // ensures more ==> this.Valid();
+ ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Imp,
+ new IdentifierExpr(iter.tok, "more"),
+ new FunctionCallExpr(iter.tok, "Valid", new ThisExpr(iter.tok), iter.tok, new List<Expression>()))));
+ // ensures this.ys == if more then old(this.ys) + [this.y] else old(this.ys);
+ Contract.Assert(iter.OutsFields.Count == iter.OutsHistoryFields.Count);
+ for (int i = 0; i < iter.OutsFields.Count; i++) {
+ var y = iter.OutsFields[i];
+ var ys = iter.OutsHistoryFields[i];
+ var ite = new ITEExpr(iter.tok, new IdentifierExpr(iter.tok, "more"),
+ new BinaryExpr(iter.tok, BinaryExpr.Opcode.Add,
+ new OldExpr(iter.tok, new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), ys.Name)),
+ new SeqDisplayExpr(iter.tok, new List<Expression>() { new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), y.Name) })),
+ new OldExpr(iter.tok, new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), ys.Name)));
+ var eq = new BinaryExpr(iter.tok, BinaryExpr.Opcode.Eq, new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), ys.Name), ite);
+ ens.Add(new MaybeFreeExpression(eq));
+ }
+ // ensures more ==> YieldEnsures;
+ foreach (var ye in iter.YieldEnsures) {
+ ens.Add(new MaybeFreeExpression(
+ new BinaryExpr(iter.tok, BinaryExpr.Opcode.Imp, new IdentifierExpr(iter.tok, "more"), ye.E),
+ ye.IsFree));
+ }
+ // ensures !more ==> Ensures;
+ foreach (var e in iter.Ensures) {
+ ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Imp,
+ new UnaryExpr(iter.tok, UnaryExpr.Opcode.Not, new IdentifierExpr(iter.tok, "more")),
+ e.E),
+ e.IsFree));
+ }
+ // decreases this._decreases0, this._decreases1, ...;
+ Contract.Assert(iter.Decreases.Expressions.Count == iter.DecreasesFields.Count);
+ for (int i = 0; i < iter.Decreases.Expressions.Count; i++) {
+ var p = iter.Decreases.Expressions[i];
+ iter.Member_MoveNext.Decreases.Expressions.Add(new FieldSelectExpr(p.tok, new ThisExpr(p.tok), iter.DecreasesFields[i].Name));
+ }
+ iter.Member_MoveNext.Decreases.Attributes = iter.Decreases.Attributes;
+ }
+
+ /// <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.
@@ -2732,9 +3152,9 @@ namespace Microsoft.Dafny
/// "specContextOnly" means that the statement must be erasable, that is, it should be okay to omit it
/// at run time. That means it must not have any side effects on non-ghost variables, for example.
/// </summary>
- public void ResolveStatement(Statement stmt, bool specContextOnly, Method method) {
+ public void ResolveStatement(Statement stmt, bool specContextOnly, ICodeContext codeContext) {
Contract.Requires(stmt != null);
- Contract.Requires(method != null);
+ Contract.Requires(codeContext != null);
if (stmt is PredicateStmt) {
PredicateStmt s = (PredicateStmt)stmt;
ResolveAttributes(s.Attributes, false);
@@ -2781,22 +3201,25 @@ namespace Microsoft.Dafny
}
}
- } else if (stmt is ReturnStmt) {
- if (specContextOnly && !method.IsGhost) {
- // TODO: investigate. This error message is suspicious. It seems that a return statement is only
- // disallowed from a ghost if or while in a non-ghost method, which is not what this says.
- Error(stmt, "return statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)");
+ } else if (stmt is ProduceStmt) {
+ var kind = stmt is YieldStmt ? "yield" : "return";
+ if (stmt is YieldStmt && !(codeContext is IteratorDecl)) {
+ Error(stmt, "yield statement is allowed only in iterators");
+ } else if (stmt is ReturnStmt && !(codeContext is Method)) {
+ Error(stmt, "return statement is allowed only in method");
+ } else if (specContextOnly && !codeContext.IsGhost) {
+ Error(stmt, "{0} statement is not allowed in this context (because it is guarded by a specification-only expression)", kind);
}
- ReturnStmt s = (ReturnStmt)stmt;
+ var s = (ProduceStmt)stmt;
if (s.rhss != null) {
- if (method.Outs.Count != s.rhss.Count)
- Error(s, "number of return parameters does not match declaration (found {0}, expected {1})", s.rhss.Count, method.Outs.Count);
+ if (codeContext.Outs.Count != s.rhss.Count)
+ Error(s, "number of {2} parameters does not match declaration (found {0}, expected {1})", s.rhss.Count, codeContext.Outs.Count, kind);
else {
Contract.Assert(s.rhss.Count > 0);
// Create a hidden update statement using the out-parameter formals, resolve the RHS, and check that the RHS is good.
List<Expression> formals = new List<Expression>();
int i = 0;
- foreach (Formal f in method.Outs) {
+ foreach (Formal f in codeContext.Outs) {
IdentifierExpr ident = new IdentifierExpr(f.tok, f.Name);
ident.Var = f;
ident.Type = ident.Var.Type;
@@ -2812,22 +3235,22 @@ namespace Microsoft.Dafny
i++;
}
s.hiddenUpdate = new UpdateStmt(s.Tok, formals, s.rhss, true);
- // resolving the update statement will check for return statement specifics.
- ResolveStatement(s.hiddenUpdate, specContextOnly, method);
+ // resolving the update statement will check for return/yield statement specifics.
+ ResolveStatement(s.hiddenUpdate, specContextOnly, codeContext);
}
- } else {// this is a regular return statement.
+ } else {// this is a regular return/yield statement.
s.hiddenUpdate = null;
}
} else if (stmt is ConcreteUpdateStatement) {
- ResolveUpdateStmt((ConcreteUpdateStatement)stmt, specContextOnly, method);
+ ResolveUpdateStmt((ConcreteUpdateStatement)stmt, specContextOnly, codeContext);
} else if (stmt is VarDeclStmt) {
var s = (VarDeclStmt)stmt;
foreach (var vd in s.Lhss) {
- ResolveStatement(vd, specContextOnly, method);
+ ResolveStatement(vd, specContextOnly, codeContext);
s.ResolvedStatements.Add(vd);
}
if (s.Update != null) {
- ResolveStatement(s.Update, specContextOnly, method);
+ ResolveStatement(s.Update, specContextOnly, codeContext);
s.ResolvedStatements.Add(s.Update);
}
@@ -2849,7 +3272,7 @@ namespace Microsoft.Dafny
if (var == null) {
// the LHS didn't resolve correctly; some error would already have been reported
} else {
- lvalueIsGhost = var.IsGhost || method.IsGhost;
+ lvalueIsGhost = var.IsGhost || codeContext.IsGhost;
if (!var.IsMutable) {
Error(stmt, "LHS of assignment must denote a mutable variable or field");
}
@@ -2872,7 +3295,7 @@ namespace Microsoft.Dafny
}
}
}
- if (!fse.Field.IsMutable) {
+ if (!fse.Field.IsUserMutable) {
Error(stmt, "LHS of assignment does not denote a mutable field");
}
}
@@ -2919,7 +3342,7 @@ namespace Microsoft.Dafny
}
} else if (s.Rhs is TypeRhs) {
TypeRhs rr = (TypeRhs)s.Rhs;
- Type t = ResolveTypeRhs(rr, stmt, lvalueIsGhost, method);
+ Type t = ResolveTypeRhs(rr, stmt, lvalueIsGhost, codeContext);
if (!lvalueIsGhost) {
if (rr.ArrayDimensions != null) {
foreach (var dim in rr.ArrayDimensions) {
@@ -2958,11 +3381,11 @@ namespace Microsoft.Dafny
} else if (stmt is CallStmt) {
CallStmt s = (CallStmt)stmt;
- ResolveCallStmt(s, specContextOnly, method, null);
+ ResolveCallStmt(s, specContextOnly, codeContext, null);
} else if (stmt is BlockStmt) {
scope.PushMarker();
- ResolveBlockStatement((BlockStmt)stmt, specContextOnly, method);
+ ResolveBlockStatement((BlockStmt)stmt, specContextOnly, codeContext);
scope.PopMarker();
} else if (stmt is IfStmt) {
@@ -2981,14 +3404,14 @@ namespace Microsoft.Dafny
}
}
s.IsGhost = branchesAreSpecOnly;
- ResolveStatement(s.Thn, branchesAreSpecOnly, method);
+ ResolveStatement(s.Thn, branchesAreSpecOnly, codeContext);
if (s.Els != null) {
- ResolveStatement(s.Els, branchesAreSpecOnly, method);
+ ResolveStatement(s.Els, branchesAreSpecOnly, codeContext);
}
} else if (stmt is AlternativeStmt) {
var s = (AlternativeStmt)stmt;
- s.IsGhost = ResolveAlternatives(s.Alternatives, specContextOnly, null, method);
+ s.IsGhost = ResolveAlternatives(s.Alternatives, specContextOnly, null, codeContext);
} else if (stmt is WhileStmt) {
WhileStmt s = (WhileStmt)stmt;
@@ -3033,12 +3456,12 @@ namespace Microsoft.Dafny
inSpecOnlyContext.Add(s, specContextOnly);
}
- ResolveStatement(s.Body, bodyMustBeSpecOnly, method);
+ ResolveStatement(s.Body, bodyMustBeSpecOnly, codeContext);
loopStack.RemoveAt(loopStack.Count - 1); // pop
} else if (stmt is AlternativeLoopStmt) {
var s = (AlternativeLoopStmt)stmt;
- s.IsGhost = ResolveAlternatives(s.Alternatives, specContextOnly, s, method);
+ s.IsGhost = ResolveAlternatives(s.Alternatives, specContextOnly, s, codeContext);
foreach (MaybeFreeExpression inv in s.Invariants) {
ResolveExpression(inv.E, true);
Contract.Assert(inv.E.Type != null); // follows from postcondition of ResolveExpression
@@ -3097,7 +3520,7 @@ namespace Microsoft.Dafny
var prevLoopStack = loopStack;
labeledStatements = new Scope<Statement>();
loopStack = new List<Statement>();
- ResolveStatement(s.Body, bodyMustBeSpecOnly, method);
+ ResolveStatement(s.Body, bodyMustBeSpecOnly, codeContext);
labeledStatements = prevLblStmts;
loopStack = prevLoopStack;
scope.PopMarker();
@@ -3243,7 +3666,7 @@ namespace Microsoft.Dafny
i++;
}
foreach (Statement ss in mc.Body) {
- ResolveStatement(ss, bodyIsSpecOnly, method);
+ ResolveStatement(ss, bodyIsSpecOnly, codeContext);
}
scope.PopMarker();
}
@@ -3266,13 +3689,15 @@ namespace Microsoft.Dafny
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);
+ ResolveStatement(s.S, specContextOnly, codeContext);
}
} else {
Contract.Assert(false); throw new cce.UnreachableException();
}
}
- private void ResolveUpdateStmt(ConcreteUpdateStatement s, bool specContextOnly, Method method) {
+ private void ResolveUpdateStmt(ConcreteUpdateStatement s, bool specContextOnly, ICodeContext codeContext) {
+ Contract.Requires(codeContext != null);
+
int prevErrorCount = ErrorCount;
// First, resolve all LHS's and expression-looking RHS's.
SeqSelectExpr arrayRangeLhs = null;
@@ -3321,7 +3746,7 @@ namespace Microsoft.Dafny
bool isEffectful;
if (rhs is TypeRhs) {
var tr = (TypeRhs)rhs;
- ResolveTypeRhs(tr, s, specContextOnly, method);
+ ResolveTypeRhs(tr, s, specContextOnly, codeContext);
isEffectful = tr.InitCall != null;
} else if (rhs is HavocRhs) {
isEffectful = false;
@@ -3427,14 +3852,14 @@ namespace Microsoft.Dafny
}
foreach (var a in s.ResolvedStatements) {
- ResolveStatement(a, specContextOnly, method);
+ ResolveStatement(a, specContextOnly, codeContext);
}
s.IsGhost = s.ResolvedStatements.TrueForAll(ss => ss.IsGhost);
}
- bool ResolveAlternatives(List<GuardedAlternative> alternatives, bool specContextOnly, AlternativeLoopStmt loopToCatchBreaks, Method method) {
+ bool ResolveAlternatives(List<GuardedAlternative> alternatives, bool specContextOnly, AlternativeLoopStmt loopToCatchBreaks, ICodeContext codeContext) {
Contract.Requires(alternatives != null);
- Contract.Requires(method != null);
+ Contract.Requires(codeContext != null);
bool isGhost = specContextOnly;
// first, resolve the guards, which tells us whether or not the entire statement is a ghost statement
@@ -3460,7 +3885,7 @@ namespace Microsoft.Dafny
foreach (var alternative in alternatives) {
scope.PushMarker();
foreach (Statement ss in alternative.Body) {
- ResolveStatement(ss, isGhost, method);
+ ResolveStatement(ss, isGhost, codeContext);
}
scope.PopMarker();
}
@@ -3475,9 +3900,9 @@ namespace Microsoft.Dafny
/// Resolves the given call statement.
/// Assumes all LHSs have already been resolved (and checked for mutability).
/// </summary>
- void ResolveCallStmt(CallStmt s, bool specContextOnly, Method method, Type receiverType) {
+ void ResolveCallStmt(CallStmt s, bool specContextOnly, ICodeContext codeContext, Type receiverType) {
Contract.Requires(s != null);
- Contract.Requires(method != null);
+ Contract.Requires(codeContext != null);
bool isInitCall = receiverType != null;
// resolve receiver
@@ -3492,11 +3917,9 @@ namespace Microsoft.Dafny
Method callee = null;
if (member == null) {
// error has already been reported by ResolveMember
- } else if (!(member is Method)) {
- Error(s, "member {0} in type {1} does not refer to a method", s.MethodName, nptype);
- } else {
- callee = (Method)member;
- s.Method = callee;
+ } else if (member is Method) {
+ s.Method = (Method)member;
+ callee = s.Method;
if (!isInitCall && callee is Constructor) {
Error(s, "a constructor is only allowed to be called when an object is being allocated");
}
@@ -3504,6 +3927,8 @@ namespace Microsoft.Dafny
if (specContextOnly && !callee.IsGhost) {
Error(s, "only ghost methods can be called from this context");
}
+ } else {
+ Error(s, "member {0} in type {1} does not refer to a method", s.MethodName, nptype);
}
// resolve left-hand sides
@@ -3605,7 +4030,7 @@ namespace Microsoft.Dafny
}
} else if (resolvedLhs is FieldSelectExpr) {
var ll = (FieldSelectExpr)resolvedLhs;
- if (!ll.Field.IsMutable) {
+ if (!ll.Field.IsUserMutable) {
Error(resolvedLhs, "LHS of assignment must denote a mutable field");
}
}
@@ -3613,23 +4038,22 @@ namespace Microsoft.Dafny
}
// Resolution termination check
- if (method.EnclosingClass != null && callee.EnclosingClass != null) {
- ModuleDefinition callerModule = method.EnclosingClass.Module;
- ModuleDefinition calleeModule = callee.EnclosingClass.Module;
- if (callerModule == calleeModule) {
- // intra-module call; this is allowed; add edge in module's call graph
- callerModule.CallGraph.AddEdge(method, callee);
- } else {
- //Contract.Assert(dependencies.Reaches(callerModule, calleeModule));
- //
- }
+ ModuleDefinition callerModule = codeContext.EnclosingModule;
+ ModuleDefinition calleeModule = ((ICodeContext)callee).EnclosingModule;
+ if (callerModule == calleeModule) {
+ // intra-module call; this is allowed; add edge in module's call graph
+ var caller = codeContext is Method ? (Method)codeContext : ((IteratorDecl)codeContext).Member_MoveNext;
+ callerModule.CallGraph.AddEdge(caller, callee);
+ } else {
+ //Contract.Assert(dependencies.Reaches(callerModule, calleeModule));
+ //
}
}
}
- void ResolveBlockStatement(BlockStmt blockStmt, bool specContextOnly, Method method) {
+ void ResolveBlockStatement(BlockStmt blockStmt, bool specContextOnly, ICodeContext codeContext) {
Contract.Requires(blockStmt != null);
- Contract.Requires(method != null);
+ Contract.Requires(codeContext != null);
foreach (Statement ss in blockStmt.Body) {
labeledStatements.PushMarker();
@@ -3650,7 +4074,7 @@ namespace Microsoft.Dafny
}
}
}
- ResolveStatement(ss, specContextOnly, method);
+ ResolveStatement(ss, specContextOnly, codeContext);
labeledStatements.PopMarker();
}
}
@@ -3668,6 +4092,8 @@ 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 YieldStmt) {
+ Error(stmt, "yield statement is not allowed inside a parallel statement");
} else if (stmt is AssignSuchThatStmt) {
var s = (AssignSuchThatStmt)stmt;
foreach (var lhs in s.Lhss) {
@@ -3798,10 +4224,10 @@ namespace Microsoft.Dafny
}
}
- Type ResolveTypeRhs(TypeRhs rr, Statement stmt, bool specContextOnly, Method method) {
+ Type ResolveTypeRhs(TypeRhs rr, Statement stmt, bool specContextOnly, ICodeContext codeContext) {
Contract.Requires(rr != null);
Contract.Requires(stmt != null);
- Contract.Requires(method != null);
+ Contract.Requires(codeContext != null);
Contract.Ensures(Contract.Result<Type>() != null);
if (rr.Type == null) {
@@ -3812,7 +4238,7 @@ namespace Microsoft.Dafny
} else {
bool callsConstructor = false;
if (rr.InitCall != null) {
- ResolveCallStmt(rr.InitCall, specContextOnly, method, rr.EType);
+ ResolveCallStmt(rr.InitCall, specContextOnly, codeContext, rr.EType);
if (rr.InitCall.Method is Constructor) {
callsConstructor = true;
}
@@ -3861,11 +4287,11 @@ namespace Microsoft.Dafny
UserDefinedType ctype = UserDefinedType.DenotesClass(receiverType);
if (ctype != null) {
- ClassDecl cd = (ClassDecl)ctype.ResolvedClass; // correctness of cast follows from postcondition of DenotesClass
+ var cd = (ClassDecl)ctype.ResolvedClass; // correctness of cast follows from postcondition of DenotesClass
Contract.Assert(ctype.TypeArgs.Count == cd.TypeArgs.Count); // follows from the fact that ctype was resolved
MemberDecl member;
if (!classMembers[cd].TryGetValue(memberName, out member)) {
- Error(tok, "member {0} does not exist in class {1}", memberName, ctype.Name);
+ Error(tok, "member {0} does not exist in {2} {1}", memberName, ctype.Name, cd is IteratorDecl ? "iterator" : "class");
return null;
} else {
nptype = ctype;
@@ -3999,7 +4425,6 @@ namespace Microsoft.Dafny
/// </summary>
void ResolveExpression(Expression expr, bool twoState, List<IVariable> matchVarContext) {
Contract.Requires(expr != null);
- Contract.Requires(currentClass != null);
Contract.Ensures(expr.Type != null);
if (expr.Type != null) {
// expression has already been resovled
@@ -4043,7 +4468,9 @@ namespace Microsoft.Dafny
if (!scope.AllowInstance) {
Error(expr, "'this' is not allowed in a 'static' context");
}
- expr.Type = GetThisType(expr.tok, currentClass); // do this regardless of scope.AllowInstance, for better error reporting
+ if (currentClass != null) {
+ expr.Type = GetThisType(expr.tok, currentClass); // do this regardless of scope.AllowInstance, for better error reporting
+ }
} else if (expr is IdentifierExpr) {
IdentifierExpr e = (IdentifierExpr)expr;
@@ -4792,7 +5219,6 @@ namespace Microsoft.Dafny
/// </summary>
void CheckIsNonGhost(Expression expr) {
Contract.Requires(expr != null);
- Contract.Requires(currentClass != null);
Contract.Requires(expr.WasResolved()); // this check approximates the requirement that "expr" be resolved
if (expr is IdentifierExpr) {
@@ -4982,6 +5408,7 @@ namespace Microsoft.Dafny
// (if two imported types have the same name, an error message is produced here)
// - unambiguous constructor name of a datatype (if two constructors have the same name, an error message is produced here)
// - field, function or method name (with implicit receiver) (if the field is occluded by anything above, one can use an explicit "this.")
+ // - iterator
// - static function or method in the enclosing module, or its imports.
Expression r = null; // resolved version of e
@@ -5045,7 +5472,7 @@ namespace Microsoft.Dafny
}
}
- } else if ((classMembers.TryGetValue(currentClass, out members) && members.TryGetValue(id.val, out member))
+ } else if ((currentClass != null && classMembers.TryGetValue(currentClass, out members) && members.TryGetValue(id.val, out member))
|| moduleInfo.StaticMembers.TryGetValue(id.val, out member)) // try static members of the current module too.
{
// ----- field, function, or method
@@ -5197,14 +5624,24 @@ namespace Microsoft.Dafny
if (p < e.Tokens.Count) {
Contract.Assert(e.Arguments != null);
- Dictionary<string, MemberDecl> members;
- MemberDecl member;
- UserDefinedType receiverType = UserDefinedType.DenotesClass(r.Type);
- if (allowMethodCall &&
- receiverType != null &&
- classMembers.TryGetValue((ClassDecl)receiverType.ResolvedClass, out members) &&
- members.TryGetValue(e.Tokens[p].val, out member) &&
- member is Method) {
+
+ bool itIsAMethod = false;
+ if (allowMethodCall) {
+ var udt = r.Type.Normalize() as UserDefinedType;
+ if (udt != null && udt.ResolvedClass != null) {
+ Dictionary<string, MemberDecl> members;
+ if (udt.ResolvedClass is ClassDecl) {
+ classMembers.TryGetValue((ClassDecl)udt.ResolvedClass, out members);
+ } else {
+ members = null;
+ }
+ MemberDecl member;
+ if (members != null && members.TryGetValue(e.Tokens[p].val, out member) && member is Method) {
+ itIsAMethod = true;
+ }
+ }
+ }
+ if (itIsAMethod) {
// method
call = new CallRhs(e.Tokens[p], r, e.Tokens[p].val, e.Arguments);
r = null;
@@ -5704,12 +6141,12 @@ namespace Microsoft.Dafny
void ResolveReceiver(Expression expr, bool twoState) {
Contract.Requires(expr != null);
- Contract.Requires(currentClass != null);
Contract.Ensures(expr.Type != null);
if (expr is ThisExpr && !expr.WasResolved()) {
// Allow 'this' here, regardless of scope.AllowInstance. The caller is responsible for
// making sure 'this' does not really get used when it's not available.
+ Contract.Assume(currentClass != null); // this is really a precondition, in this case
expr.Type = GetThisType(expr.tok, currentClass);
} else {
ResolveExpression(expr, twoState);
@@ -5915,7 +6352,7 @@ namespace Microsoft.Dafny
/// </summary>
bool UsesSpecFeatures(Expression expr) {
Contract.Requires(expr != null);
- Contract.Requires(currentClass != null);
+ Contract.Requires(expr.WasResolved()); // this check approximates the requirement that "expr" be resolved
if (expr is LiteralExpr) {
return false;
diff --git a/Dafny/Scanner.cs b/Dafny/Scanner.cs
index 8de52992..0ebbab1f 100644
--- a/Dafny/Scanner.cs
+++ b/Dafny/Scanner.cs
@@ -211,8 +211,8 @@ public class UTF8Buffer: Buffer {
public class Scanner {
const char EOL = '\n';
const int eofSym = 0; /* pdt */
- const int maxT = 112;
- const int noSym = 112;
+ const int maxT = 114;
+ const int noSym = 114;
[ContractInvariantMethod]
@@ -274,15 +274,15 @@ public class Scanner {
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] = 33;
- start[8804] = 34;
- start[8805] = 35;
- start[8660] = 38;
- start[8658] = 40;
- start[38] = 41;
- start[8743] = 43;
- start[8744] = 45;
+ start[8800] = 44;
+ start[8804] = 45;
+ start[8805] = 46;
start[43] = 47;
start[45] = 48;
start[47] = 49;
@@ -501,53 +501,55 @@ public class Scanner {
case "codatatype": t.kind = 21; break;
case "var": t.kind = 23; break;
case "type": t.kind = 25; break;
- case "method": t.kind = 31; break;
- case "constructor": t.kind = 32; break;
- case "returns": t.kind = 33; break;
- case "modifies": t.kind = 35; break;
- case "free": t.kind = 36; break;
- case "requires": t.kind = 37; break;
- case "ensures": t.kind = 38; break;
- case "decreases": t.kind = 39; break;
- case "bool": t.kind = 40; break;
- case "nat": t.kind = 41; break;
- case "int": t.kind = 42; break;
- case "set": t.kind = 43; break;
- case "multiset": t.kind = 44; break;
- case "seq": t.kind = 45; break;
- case "map": t.kind = 46; break;
- case "object": t.kind = 47; break;
- case "function": t.kind = 48; break;
- case "predicate": t.kind = 49; break;
- case "copredicate": t.kind = 50; break;
- case "reads": t.kind = 51; break;
- case "label": t.kind = 54; break;
- case "break": t.kind = 55; break;
- case "where": t.kind = 56; break;
- case "return": t.kind = 58; break;
- case "assume": t.kind = 60; break;
- case "new": t.kind = 61; break;
- case "choose": t.kind = 64; break;
- case "if": t.kind = 65; break;
- case "else": t.kind = 66; break;
- case "case": t.kind = 67; break;
- case "while": t.kind = 69; break;
- case "invariant": t.kind = 70; break;
- case "match": t.kind = 71; break;
- case "assert": t.kind = 72; break;
- case "print": t.kind = 73; break;
- case "parallel": t.kind = 74; break;
- case "calc": t.kind = 75; break;
- case "in": t.kind = 91; break;
- case "false": t.kind = 98; break;
- case "true": t.kind = 99; break;
- case "null": t.kind = 100; break;
- case "this": t.kind = 101; break;
- case "fresh": t.kind = 102; break;
- case "old": t.kind = 103; break;
- case "then": t.kind = 104; break;
- case "forall": t.kind = 106; break;
- case "exists": t.kind = 108; break;
+ case "iterator": t.kind = 29; break;
+ case "yields": t.kind = 30; break;
+ case "method": t.kind = 34; break;
+ case "constructor": t.kind = 35; break;
+ case "returns": t.kind = 36; break;
+ case "modifies": t.kind = 37; break;
+ case "free": t.kind = 38; break;
+ case "requires": t.kind = 39; break;
+ case "ensures": t.kind = 40; break;
+ case "decreases": t.kind = 41; break;
+ case "reads": t.kind = 42; break;
+ case "yield": t.kind = 43; break;
+ case "bool": t.kind = 44; break;
+ case "nat": t.kind = 45; break;
+ case "int": t.kind = 46; break;
+ case "set": t.kind = 47; break;
+ case "multiset": t.kind = 48; break;
+ case "seq": t.kind = 49; break;
+ case "map": t.kind = 50; break;
+ case "object": t.kind = 51; break;
+ case "function": t.kind = 52; break;
+ case "predicate": t.kind = 53; break;
+ case "copredicate": t.kind = 54; break;
+ case "label": t.kind = 57; break;
+ case "break": t.kind = 58; break;
+ case "where": t.kind = 59; break;
+ case "return": t.kind = 61; break;
+ case "assume": t.kind = 63; break;
+ case "new": t.kind = 64; break;
+ case "choose": t.kind = 67; break;
+ case "if": t.kind = 68; break;
+ case "else": t.kind = 69; break;
+ case "case": t.kind = 70; break;
+ case "while": t.kind = 72; break;
+ case "invariant": t.kind = 73; break;
+ case "match": t.kind = 74; break;
+ case "assert": t.kind = 75; break;
+ case "print": t.kind = 76; break;
+ case "parallel": t.kind = 77; break;
+ case "in": t.kind = 90; break;
+ case "false": t.kind = 100; break;
+ case "true": t.kind = 101; break;
+ case "null": t.kind = 102; break;
+ case "this": t.kind = 103; break;
+ case "fresh": t.kind = 104; break;
+ case "old": t.kind = 105; break;
+ case "then": t.kind = 106; break;
+ case "forall": t.kind = 108; break;
+ case "exists": t.kind = 110; break;
default: break;
}
}
@@ -661,23 +663,24 @@ public class Scanner {
case 22:
{t.kind = 28; break;}
case 23:
- {t.kind = 34; break;}
+ {t.kind = 31; break;}
case 24:
- {t.kind = 52; break;}
+ {t.kind = 55; break;}
case 25:
- {t.kind = 53; break;}
+ {t.kind = 56; break;}
case 26:
- {t.kind = 57; break;}
+ {t.kind = 60; break;}
case 27:
- {t.kind = 59; break;}
- case 28:
{t.kind = 62; break;}
+ case 28:
+ {t.kind = 65; break;}
case 29:
- {t.kind = 63; break;}
+ {t.kind = 66; break;}
case 30:
- {t.kind = 68; break;}
+ {t.kind = 71; break;}
case 31:
- {t.kind = 77; break;}
+ if (ch == '>') {AddCh(); goto case 32;}
+ else {goto case 0;}
case 32:
{t.kind = 78; break;}
case 33:
@@ -687,7 +690,7 @@ public class Scanner {
case 35:
{t.kind = 81; break;}
case 36:
- if (ch == '>') {AddCh(); goto case 37;}
+ if (ch == '&') {AddCh(); goto case 37;}
else {goto case 0;}
case 37:
{t.kind = 82; break;}
@@ -698,36 +701,35 @@ public class Scanner {
case 40:
{t.kind = 85; break;}
case 41:
- if (ch == '&') {AddCh(); goto case 42;}
- else {goto case 0;}
+ {t.kind = 87; break;}
case 42:
- {t.kind = 86; break;}
+ {t.kind = 88; break;}
case 43:
- {t.kind = 87; break;}
+ {t.kind = 89; break;}
case 44:
- {t.kind = 88; break;}
+ {t.kind = 92; break;}
case 45:
- {t.kind = 89; break;}
+ {t.kind = 93; break;}
case 46:
- {t.kind = 90; break;}
+ {t.kind = 94; break;}
case 47:
- {t.kind = 93; break;}
+ {t.kind = 95; break;}
case 48:
- {t.kind = 94; break;}
+ {t.kind = 96; break;}
case 49:
- {t.kind = 95; break;}
+ {t.kind = 97; break;}
case 50:
- {t.kind = 96; break;}
+ {t.kind = 98; break;}
case 51:
- {t.kind = 97; break;}
+ {t.kind = 99; break;}
case 52:
- {t.kind = 107; break;}
- case 53:
{t.kind = 109; break;}
+ case 53:
+ {t.kind = 111; break;}
case 54:
- {t.kind = 110; break;}
+ {t.kind = 112; break;}
case 55:
- {t.kind = 111; break;}
+ {t.kind = 113; break;}
case 56:
recEnd = pos; recKind = 5;
if (ch == '=') {AddCh(); goto case 26;}
@@ -745,33 +747,33 @@ public class Scanner {
else {t.kind = 17; break;}
case 59:
recEnd = pos; recKind = 22;
- if (ch == '|') {AddCh(); goto case 44;}
+ if (ch == '|') {AddCh(); goto case 39;}
else {t.kind = 22; break;}
case 60:
- recEnd = pos; recKind = 29;
+ recEnd = pos; recKind = 32;
if (ch == '=') {AddCh(); goto case 65;}
- else {t.kind = 29; break;}
+ else {t.kind = 32; break;}
case 61:
- recEnd = pos; recKind = 30;
- if (ch == '=') {AddCh(); goto case 31;}
- else {t.kind = 30; break;}
+ recEnd = pos; recKind = 33;
+ if (ch == '=') {AddCh(); goto case 41;}
+ else {t.kind = 33; break;}
case 62:
- recEnd = pos; recKind = 92;
- if (ch == '=') {AddCh(); goto case 32;}
- else if (ch == '!') {AddCh(); goto case 46;}
- else {t.kind = 92; break;}
+ recEnd = pos; recKind = 91;
+ if (ch == '=') {AddCh(); goto case 42;}
+ else if (ch == '!') {AddCh(); goto case 43;}
+ else {t.kind = 91; break;}
case 63:
recEnd = pos; recKind = 27;
- if (ch == '>') {AddCh(); goto case 39;}
+ if (ch == '>') {AddCh(); goto case 34;}
else {t.kind = 27; break;}
case 64:
- recEnd = pos; recKind = 105;
+ recEnd = pos; recKind = 107;
if (ch == '.') {AddCh(); goto case 23;}
- else {t.kind = 105; break;}
+ else {t.kind = 107; break;}
case 65:
- recEnd = pos; recKind = 76;
- if (ch == '=') {AddCh(); goto case 36;}
- else {t.kind = 76; break;}
+ recEnd = pos; recKind = 86;
+ if (ch == '=') {AddCh(); goto case 31;}
+ else {t.kind = 86; break;}
}
t.val = new String(tval, 0, tlen);
diff --git a/Dafny/Translator.cs b/Dafny/Translator.cs
index ccc9ff4f..40795129 100644
--- a/Dafny/Translator.cs
+++ b/Dafny/Translator.cs
@@ -5,6 +5,7 @@
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Numerics;
using System.Diagnostics.Contracts;
using Bpl = Microsoft.Boogie;
@@ -35,7 +36,7 @@ namespace Microsoft.Dafny {
Contract.Invariant(cce.NonNullDictionaryAndValues(classes));
Contract.Invariant(cce.NonNullDictionaryAndValues(fields));
Contract.Invariant(cce.NonNullDictionaryAndValues(fieldFunctions));
- Contract.Invariant(currentMethod == null || currentMethod.EnclosingClass.Module == currentModule);
+ Contract.Invariant(codeContext == null || codeContext.EnclosingModule == currentModule);
}
readonly Bpl.Program sink;
@@ -347,6 +348,9 @@ namespace Microsoft.Dafny {
// submodules have already been added as a top level module, ignore this.
} else if (d is ClassDecl) {
AddClassMembers((ClassDecl)d);
+ if (d is IteratorDecl) {
+ AddIteratorSpecAndBody((IteratorDecl)d);
+ }
} else {
Contract.Assert(false);
}
@@ -377,8 +381,6 @@ namespace Microsoft.Dafny {
return sink;
}
-
-
void AddDatatype(DatatypeDecl dt)
{
Contract.Requires(dt != null);
@@ -641,7 +643,11 @@ namespace Microsoft.Dafny {
// wellformedness check for method specification
Bpl.Procedure proc = AddMethod(m, 0, isRefinementMethod);
sink.TopLevelDeclarations.Add(proc);
- AddMethodImpl(m, proc, true);
+ if (m.EnclosingClass is IteratorDecl && m == ((IteratorDecl)m.EnclosingClass).Member_MoveNext) {
+ // skip the well-formedness check, because it has already been done for the iterator
+ } else {
+ AddMethodImpl(m, proc, true);
+ }
// the method itself
proc = AddMethod(m, 1, isRefinementMethod);
sink.TopLevelDeclarations.Add(proc);
@@ -662,6 +668,292 @@ namespace Microsoft.Dafny {
}
}
+ void AddIteratorSpecAndBody(IteratorDecl iter) {
+ Contract.Requires(iter != null);
+
+ bool isRefinementMethod = RefinementToken.IsInherited(iter.tok, iter.Module);
+
+ // wellformedness check for method specification
+ Bpl.Procedure proc = AddIteratorProc(iter, 0, isRefinementMethod);
+ sink.TopLevelDeclarations.Add(proc);
+ AddIteratorWellformed(iter, proc);
+ // the method itself
+ if (iter.Body != null) {
+ proc = AddIteratorProc(iter, 1, isRefinementMethod);
+ sink.TopLevelDeclarations.Add(proc);
+ if (isRefinementMethod) {
+ proc = AddIteratorProc(iter, 3, isRefinementMethod);
+ sink.TopLevelDeclarations.Add(proc);
+ }
+ // ...and its implementation
+ AddIteratorImpl(iter, proc);
+ }
+ }
+
+ /// <summary>
+ /// This method is expected to be called at most 3 times for each procedure in the program:
+ /// * once with kind==0, which says to create a procedure for the wellformedness check of the
+ /// method's specification
+ /// * once with kind==1, which says to create the ordinary procedure for the method, always
+ /// suitable for inter-module callers, and for non-refinement methods also suitable for
+ /// the implementation and intra-module callers of the method
+ /// * possibly once with kind==3 (allowed only if isRefinementMethod), which says to create
+ /// a procedure suitable for the implementation of a refinement method
+ /// </summary>
+ Bpl.Procedure AddIteratorProc(IteratorDecl iter, int kind, bool isRefinementMethod) {
+ Contract.Requires(iter != null);
+ Contract.Requires(0 <= kind && kind < 4 && kind != 2);
+ Contract.Requires(isRefinementMethod || kind < 2);
+ Contract.Requires(predef != null);
+ Contract.Requires(currentModule == null && codeContext == null);
+ Contract.Ensures(currentModule == null && codeContext == null);
+ Contract.Ensures(Contract.Result<Bpl.Procedure>() != null);
+
+ currentModule = iter.Module;
+ codeContext = iter;
+
+ ExpressionTranslator etran = new ExpressionTranslator(this, predef, iter.tok);
+
+ Bpl.VariableSeq inParams, outParams;
+ GenerateMethodParametersChoose(iter.tok, iter, true, true, false, etran, out inParams, out outParams);
+
+ var req = new Bpl.RequiresSeq();
+ var mod = new Bpl.IdentifierExprSeq();
+ var ens = new Bpl.EnsuresSeq();
+ if (kind == 0 || (kind == 1 && !isRefinementMethod) || kind == 3) { // the other cases have no need for a free precondition
+ // free requires mh == ModuleContextHeight && InMethodContext;
+ Bpl.Expr context = Bpl.Expr.And(
+ Bpl.Expr.Eq(Bpl.Expr.Literal(iter.Module.Height), etran.ModuleContextHeight()),
+ etran.InMethodContext());
+ req.Add(Requires(iter.tok, true, context, null, null));
+ }
+ mod.Add((Bpl.IdentifierExpr/*TODO: this cast is rather dubious*/)etran.HeapExpr);
+ mod.Add(etran.Tick());
+
+ if (kind != 0) {
+ string comment = "user-defined preconditions";
+ foreach (var p in iter.Requires) {
+ bool splitHappened; // we actually don't care
+ foreach (var s in TrSplitExpr(p.E, etran, out splitHappened)) {
+ if (kind == 2 && RefinementToken.IsInherited(s.E.tok, currentModule)) {
+ // this precondition was inherited into this module, so just ignore it
+ } else {
+ req.Add(Requires(s.E.tok, s.IsFree, s.E, null, null));
+ // the free here is not linked to the free on the original expression (this is free things generated in the splitting.)
+ }
+ }
+ comment = null;
+ }
+ comment = "user-defined postconditions";
+ foreach (MaybeFreeExpression p in iter.Ensures) {
+ if (p.IsFree && !DafnyOptions.O.DisallowSoundnessCheating) {
+ ens.Add(Ensures(p.E.tok, true, etran.TrExpr(p.E), null, comment));
+ } else {
+ bool splitHappened; // we actually don't care
+ foreach (var s in TrSplitExpr(p.E, etran, out splitHappened)) {
+ if (kind == 3 && RefinementToken.IsInherited(s.E.tok, currentModule)) {
+ // this postcondition was inherited into this module, so just ignore it
+ } else {
+ ens.Add(Ensures(s.E.tok, s.IsFree, s.E, null, null));
+ }
+ }
+ }
+ comment = null;
+ }
+ foreach (BoilerplateTriple tri in GetTwoStateBoilerplate(iter.tok, iter.Modifies.Expressions, etran.Old, etran, etran.Old)) {
+ ens.Add(Ensures(tri.tok, tri.IsFree, tri.Expr, tri.ErrorMessage, tri.Comment));
+ }
+ }
+
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(iter.TypeArgs);
+ string name;
+ switch (kind) {
+ case 0: name = "CheckWellformed$$" + iter.FullCompileName; break;
+ case 1: name = iter.FullCompileName; break;
+ case 3: name = string.Format("RefinementImpl_{0}$${1}", iter.Module.Name, iter.FullCompileName); break;
+ default: Contract.Assert(false); throw new cce.UnreachableException(); // unexpected kind
+ }
+ Bpl.Procedure proc = new Bpl.Procedure(iter.tok, name, typeParams, inParams, outParams, req, mod, ens);
+
+ currentModule = null;
+ codeContext = null;
+
+ return proc;
+ }
+
+ void AddIteratorWellformed(IteratorDecl iter, Procedure proc) {
+ currentModule = iter.Module;
+ codeContext = iter;
+
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(iter.TypeArgs);
+ Bpl.VariableSeq inParams = Bpl.Formal.StripWhereClauses(proc.InParams);
+ Contract.Assert(1 <= inParams.Length); // there should at least be a receiver parameter
+ Contract.Assert(proc.OutParams.Length == 0);
+
+ var builder = new Bpl.StmtListBuilder();
+ var etran = new ExpressionTranslator(this, predef, iter.tok);
+ var localVariables = new Bpl.VariableSeq();
+
+ Bpl.StmtList stmts;
+ // check well-formedness of the preconditions, and then assume each one of them
+ foreach (var p in iter.Requires) {
+ CheckWellformed(p.E, new WFOptions(), localVariables, builder, etran);
+ builder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
+ }
+ // check well-formedness of the decreases clauses
+ foreach (var p in iter.Decreases.Expressions) {
+ CheckWellformed(p, new WFOptions(), localVariables, builder, etran);
+ }
+ // Note: the reads and modifies clauses are not checked for well-formedness (is that sound?), because it used to
+ // be that the syntax was not rich enough for programmers to specify modifies clauses and always being
+ // absolutely well-defined.
+
+ // Next, we assume about this.* whatever we said that the iterator constructor promises
+ foreach (var p in iter.Member_Init.Ens) {
+ builder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
+ }
+
+ // play havoc with the heap, except at the locations prescribed by (this._reads - this._modifies - {this})
+ var th = new ThisExpr(iter.tok);
+ th.Type = Resolver.GetThisType(iter.tok, iter); // resolve here
+ var rds = new FieldSelectExpr(iter.tok, th, iter.Member_Reads.Name);
+ rds.Field = iter.Member_Reads; // resolve here
+ rds.Type = iter.Member_Reads.Type; // resolve here
+ var mod = new FieldSelectExpr(iter.tok, th, iter.Member_Modifies.Name);
+ mod.Field = iter.Member_Modifies; // resolve here
+ mod.Type = iter.Member_Modifies.Type; // resolve here
+ builder.Add(new Bpl.CallCmd(iter.tok, "$IterHavoc0",
+ new List<Bpl.Expr>() { etran.TrExpr(th), etran.TrExpr(rds), etran.TrExpr(mod) },
+ new List<Bpl.IdentifierExpr>()));
+
+ // assume the automatic yield-requires precondition (which is always well-formed): this.Valid()
+ var validCall = new FunctionCallExpr(iter.tok, "Valid", th, iter.tok, new List<Expression>());
+ validCall.Function = iter.Member_Valid; // resolve here
+ validCall.Type = Type.Bool; // resolve here
+ builder.Add(new Bpl.AssumeCmd(iter.tok, etran.TrExpr(validCall)));
+
+ // check well-formedness of the user-defined part of the yield-requires
+ foreach (var p in iter.YieldRequires) {
+ CheckWellformed(p.E, new WFOptions(), localVariables, builder, etran);
+ builder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
+ }
+
+ // simulate a modifies this, this._modifies, this._new;
+ var nw = new FieldSelectExpr(iter.tok, th, iter.Member_New.Name);
+ nw.Field = iter.Member_New; // resolve here
+ nw.Type = iter.Member_New.Type; // resolve here
+ builder.Add(new Bpl.CallCmd(iter.tok, "$IterHavoc1",
+ new List<Bpl.Expr>() { etran.TrExpr(th), etran.TrExpr(mod), etran.TrExpr(nw) },
+ new List<Bpl.IdentifierExpr>()));
+
+ // check wellformedness of postconditions
+ var yeBuilder = new Bpl.StmtListBuilder();
+ var endBuilder = new Bpl.StmtListBuilder();
+ foreach (var p in iter.YieldEnsures) {
+ CheckWellformed(p.E, new WFOptions(), localVariables, yeBuilder, etran);
+ yeBuilder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
+ }
+ foreach (var p in iter.Ensures) {
+ CheckWellformed(p.E, new WFOptions(), localVariables, endBuilder, etran);
+ endBuilder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
+ }
+ builder.Add(new Bpl.IfCmd(iter.tok, null, yeBuilder.Collect(iter.tok), null, endBuilder.Collect(iter.tok)));
+
+ stmts = builder.Collect(iter.tok);
+
+ QKeyValue kv = etran.TrAttributes(iter.Attributes, null);
+
+ Bpl.Implementation impl = new Bpl.Implementation(iter.tok, proc.Name,
+ typeParams, inParams, new VariableSeq(),
+ localVariables, stmts, kv);
+ sink.TopLevelDeclarations.Add(impl);
+
+ currentModule = null;
+ codeContext = null;
+ loopHeapVarCount = 0;
+ otherTmpVarCount = 0;
+ _tmpIEs.Clear();
+ }
+
+ void AddIteratorImpl(IteratorDecl iter, Bpl.Procedure proc) {
+ Contract.Requires(iter != null);
+ Contract.Requires(proc != null);
+ Contract.Requires(sink != null && predef != null);
+ Contract.Requires(iter.Body != null);
+ Contract.Requires(currentModule == null && codeContext == null && yieldCountVariable == null && loopHeapVarCount == 0 && _tmpIEs.Count == 0);
+ Contract.Ensures(currentModule == null && codeContext == null && yieldCountVariable == null && loopHeapVarCount == 0 && _tmpIEs.Count == 0);
+
+ currentModule = iter.Module;
+ codeContext = iter;
+
+ Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(iter.TypeArgs);
+ Bpl.VariableSeq inParams = Bpl.Formal.StripWhereClauses(proc.InParams);
+ Contract.Assert(1 <= inParams.Length); // there should at least be a receiver parameter
+ Contract.Assert(proc.OutParams.Length == 0);
+
+ Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder();
+ ExpressionTranslator etran = new ExpressionTranslator(this, predef, iter.tok);
+ Bpl.VariableSeq localVariables = new Bpl.VariableSeq();
+ GenerateIteratorImplPrelude(iter, inParams, new VariableSeq(), builder, localVariables);
+
+ // add locals for the yield-history variables and the extra variables
+ // Assume the precondition and postconditions of the iterator constructor method
+ foreach (var p in iter.Member_Init.Req) {
+ builder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
+ }
+ foreach (var p in iter.Member_Init.Ens) {
+ // these postconditions are two-state predicates, but that's okay, because we haven't changed anything yet
+ builder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
+ }
+ // add the _yieldCount variable, and assume its initial value to be 0
+ yieldCountVariable = new Bpl.LocalVariable(iter.tok, new Bpl.TypedIdent(iter.tok, "_yieldCount", Bpl.Type.Int));
+ yieldCountVariable.TypedIdent.WhereExpr = YieldCountAssumption(iter, etran); // by doing this after setting "yieldCountVariable", the variable can be used by YieldCountAssumption
+ localVariables.Add(yieldCountVariable);
+ builder.Add(new Bpl.AssumeCmd(iter.tok, Bpl.Expr.Eq(new Bpl.IdentifierExpr(iter.tok, yieldCountVariable), Bpl.Expr.Literal(0))));
+ // add a variable $_OldIterHeap
+ var oih = new Bpl.IdentifierExpr(iter.tok, "$_OldIterHeap", predef.HeapType);
+ Bpl.Expr wh = BplAnd(
+ FunctionCall(iter.tok, BuiltinFunction.IsGoodHeap, null, oih),
+ FunctionCall(iter.tok, BuiltinFunction.HeapSucc, null, oih, etran.HeapExpr));
+ localVariables.Add(new Bpl.LocalVariable(iter.tok, new Bpl.TypedIdent(iter.tok, "$_OldIterHeap", predef.HeapType, wh)));
+
+ // do an initial YieldHavoc
+ YieldHavoc(iter.tok, iter, builder, etran);
+
+ // translate the body of the method
+ var stmts = TrStmt2StmtList(builder, iter.Body, localVariables, etran);
+
+ QKeyValue kv = etran.TrAttributes(iter.Attributes, null);
+
+ Bpl.Implementation impl = new Bpl.Implementation(iter.tok, proc.Name,
+ typeParams, inParams, new VariableSeq(),
+ localVariables, stmts, kv);
+ sink.TopLevelDeclarations.Add(impl);
+
+ currentModule = null;
+ codeContext = null;
+ yieldCountVariable = null;
+ loopHeapVarCount = 0;
+ otherTmpVarCount = 0;
+ _tmpIEs.Clear();
+ }
+
+ Bpl.Expr YieldCountAssumption(IteratorDecl iter, ExpressionTranslator etran) {
+ Contract.Requires(iter != null);
+ Contract.Requires(etran != null);
+ Contract.Requires(yieldCountVariable != null);
+ Bpl.Expr wh = Bpl.Expr.True;
+ foreach (var ys in iter.OutsHistoryFields) {
+ // add the conjunct: _yieldCount == |this.ys|
+ wh = Bpl.Expr.And(wh, Bpl.Expr.Eq(new Bpl.IdentifierExpr(iter.tok, yieldCountVariable),
+ FunctionCall(iter.tok, BuiltinFunction.SeqLength, null,
+ ExpressionTranslator.ReadHeap(iter.tok, etran.HeapExpr,
+ new Bpl.IdentifierExpr(iter.tok, etran.This, predef.RefType),
+ new Bpl.IdentifierExpr(iter.tok, GetField(ys))))));
+ }
+ return wh;
+ }
+
void AddFunctionAxiomCase(Function f, MatchExpr me, Specialization prev, int layerOffset) {
Contract.Requires(f != null);
Contract.Requires(me != null);
@@ -1032,7 +1324,7 @@ namespace Microsoft.Dafny {
Bpl.Expr.Neq(o, predef.Null)),
etran.IsAlloced(f.tok, o));
Bpl.Expr body = Bpl.Expr.Imp(ante, wh);
- Bpl.Trigger tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(oDotF));
+ Bpl.Trigger tr = f.IsMutable ? new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(oDotF)) : null; // the trigger must include both "o" and "h"
Bpl.Expr ax = new Bpl.ForallExpr(f.tok, new Bpl.VariableSeq(hVar, oVar), tr, body);
sink.TopLevelDeclarations.Add(new Bpl.Axiom(f.tok, ax));
}
@@ -1061,7 +1353,8 @@ namespace Microsoft.Dafny {
}
ModuleDefinition currentModule = null; // the name of the module whose members are currently being translated
- Method currentMethod = null; // the method whose implementation is currently being translated
+ ICodeContext codeContext = null; // the method/iterator whose implementation is currently being translated
+ LocalVariable yieldCountVariable = null; // non-null when an iterator body is being translated
int loopHeapVarCount = 0;
int otherTmpVarCount = 0;
Dictionary<string, Bpl.IdentifierExpr> _tmpIEs = new Dictionary<string, Bpl.IdentifierExpr>();
@@ -1134,11 +1427,11 @@ namespace Microsoft.Dafny {
Contract.Requires(proc != null);
Contract.Requires(sink != null && predef != null);
Contract.Requires(wellformednessProc || m.Body != null);
- Contract.Requires(currentModule == null && currentMethod == null && loopHeapVarCount == 0 && _tmpIEs.Count == 0);
- Contract.Ensures(currentModule == null && currentMethod == null && loopHeapVarCount == 0 && _tmpIEs.Count == 0);
+ Contract.Requires(currentModule == null && codeContext == null && loopHeapVarCount == 0 && _tmpIEs.Count == 0);
+ Contract.Ensures(currentModule == null && codeContext == null && loopHeapVarCount == 0 && _tmpIEs.Count == 0);
currentModule = m.EnclosingClass.Module;
- currentMethod = m;
+ codeContext = m;
Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(m.TypeArgs);
Bpl.VariableSeq inParams = Bpl.Formal.StripWhereClauses(proc.InParams);
@@ -1287,7 +1580,7 @@ namespace Microsoft.Dafny {
// play havoc with the heap according to the modifies clause
builder.Add(new Bpl.HavocCmd(m.tok, new Bpl.IdentifierExprSeq((Bpl.IdentifierExpr/*TODO: this cast is rather dubious*/)etran.HeapExpr)));
// assume the usual two-state boilerplate information
- foreach (BoilerplateTriple tri in GetTwoStateBoilerplate(m.tok, currentMethod.Mod.Expressions, etran.Old, etran, etran.Old))
+ foreach (BoilerplateTriple tri in GetTwoStateBoilerplate(m.tok, m.Mod.Expressions, etran.Old, etran, etran.Old))
{
if (tri.IsFree) {
builder.Add(new Bpl.AssumeCmd(m.tok, tri.Expr));
@@ -1321,7 +1614,7 @@ namespace Microsoft.Dafny {
sink.TopLevelDeclarations.Add(impl);
currentModule = null;
- currentMethod = null;
+ codeContext = null;
loopHeapVarCount = 0;
otherTmpVarCount = 0;
_tmpIEs.Clear();
@@ -1340,6 +1633,24 @@ namespace Microsoft.Dafny {
DefineFrame(m.tok, m.Mod.Expressions, builder, localVariables, null);
}
+ void GenerateIteratorImplPrelude(IteratorDecl iter, Bpl.VariableSeq inParams, Bpl.VariableSeq outParams,
+ Bpl.StmtListBuilder builder, Bpl.VariableSeq localVariables) {
+ Contract.Requires(iter != null);
+ Contract.Requires(inParams != null);
+ Contract.Requires(outParams != null);
+ Contract.Requires(builder != null);
+ Contract.Requires(localVariables != null);
+ Contract.Requires(predef != null);
+
+ // set up the information used to verify the method's modifies clause
+ var iteratorFrame = new List<FrameExpression>();
+ var th = new ThisExpr(iter.tok);
+ th.Type = Resolver.GetThisType(iter.tok, iter); // resolve here
+ iteratorFrame.Add(new FrameExpression(iter.tok, th, null));
+ iteratorFrame.AddRange(iter.Modifies.Expressions);
+ DefineFrame(iter.tok, iteratorFrame, builder, localVariables, null);
+ }
+
Bpl.Cmd CaptureState(IToken tok, string/*?*/ additionalInfo) {
Contract.Requires(tok != null);
Contract.Ensures(Contract.Result<Bpl.Cmd>() != null);
@@ -2665,11 +2976,11 @@ namespace Microsoft.Dafny {
/// <summary>
/// Returns true if it is known how to meaningfully compare the type's inhabitants.
/// </summary>
- bool IsOrdered(Type t) {
+ static bool IsOrdered(Type t) {
return !t.IsTypeParameter && !t.IsCoDatatype;
}
- List<Expression> MethodDecreasesWithDefault(Method m, out bool inferredDecreases) {
+ public static List<Expression> MethodDecreasesWithDefault(ICodeContext m, out bool inferredDecreases) {
Contract.Requires(m != null);
inferredDecreases = false;
@@ -2678,12 +2989,14 @@ namespace Microsoft.Dafny {
decr = new List<Expression>();
foreach (Formal p in m.Ins) {
if (IsOrdered(p.Type)) {
- IdentifierExpr ie = new IdentifierExpr(p.tok, p.UniqueName);
+ IdentifierExpr ie = new IdentifierExpr(p.tok, p.Name);
ie.Var = p; ie.Type = ie.Var.Type; // resolve it here
decr.Add(ie); // use the method's first parameter instead
}
}
inferredDecreases = true;
+ } else if (m is IteratorDecl) {
+ inferredDecreases = ((IteratorDecl)m).InferredDecreases;
}
return decr;
}
@@ -2768,9 +3081,28 @@ namespace Microsoft.Dafny {
}
}
}
+ if (yieldCountVariable != null) {
+ var decr = new List<Expression>();
+ decr.Add(new BoogieWrapper(new Bpl.IdentifierExpr(tok, yieldCountVariable), new EverIncreasingType()));
+ decr.AddRange(theDecreases);
+ theDecreases = decr;
+ }
return theDecreases;
}
+ /// <summary>
+ /// This Dafny type, which exists only during translation of Dafny into Boogie, represents
+ /// an integer component in a "decreases" clause whose order is (\lambda x,y :: x GREATER y),
+ /// not the usual (\lambda x,y :: x LESS y AND 0 ATMOST y).
+ /// </summary>
+ public class EverIncreasingType : BasicType
+ {
+ [Pure]
+ public override string TypeName(ModuleDefinition context) {
+ return "_increasingInt";
+ }
+ }
+
Expression FrameToObjectSet(List<FrameExpression> fexprs) {
Contract.Requires(fexprs != null);
Contract.Ensures(Contract.Result<Expression>() != null);
@@ -2906,7 +3238,11 @@ namespace Microsoft.Dafny {
if (a == null) {
return null;
}
- Bpl.Expr t = new Bpl.IdentifierExpr(tok, ct is SetType ? "class._System.set" : (ct is SeqType ? "class._System.seq" : "class._System.multiset"), predef.ClassNameType); // ^^^ todo: this needs to talk about multisets too.
+ Bpl.Expr t = new Bpl.IdentifierExpr(tok,
+ ct is SetType ? "class._System.set" :
+ ct is SeqType ? "class._System.seq" :
+ "class._System.multiset",
+ predef.ClassNameType);
return FunctionCall(tok, BuiltinFunction.TypeTuple, null, t, a);
} else {
UserDefinedType ct = (UserDefinedType)type;
@@ -3042,17 +3378,17 @@ namespace Microsoft.Dafny {
Contract.Requires(0 <= kind && kind < 4);
Contract.Requires(isRefinementMethod || kind < 2);
Contract.Requires(predef != null);
- Contract.Requires(currentModule == null && currentMethod == null);
- Contract.Ensures(currentModule == null && currentMethod == null);
+ Contract.Requires(currentModule == null && codeContext == null);
+ Contract.Ensures(currentModule == null && codeContext == null);
Contract.Ensures(Contract.Result<Bpl.Procedure>() != null);
currentModule = m.EnclosingClass.Module;
- currentMethod = m;
+ codeContext = m;
ExpressionTranslator etran = new ExpressionTranslator(this, predef, m.tok);
Bpl.VariableSeq inParams, outParams;
- GenerateMethodParameters(m, etran, out inParams, out outParams);
+ GenerateMethodParameters(m.tok, m, etran, out inParams, out outParams);
Bpl.RequiresSeq req = new Bpl.RequiresSeq();
Bpl.IdentifierExprSeq mod = new Bpl.IdentifierExprSeq();
@@ -3118,7 +3454,7 @@ namespace Microsoft.Dafny {
Bpl.Procedure proc = new Bpl.Procedure(m.tok, name, typeParams, inParams, outParams, req, mod, ens);
currentModule = null;
- currentMethod = null;
+ codeContext = null;
return proc;
}
@@ -3130,12 +3466,12 @@ namespace Microsoft.Dafny {
// to the refining method.
Method m = methodCheck.Refined;
currentModule = m.EnclosingClass.Module;
- currentMethod = m;
+ codeContext = m;
ExpressionTranslator etran = new ExpressionTranslator(this, predef, m.tok);
Bpl.VariableSeq inParams, outParams;
- GenerateMethodParameters(m, etran, out inParams, out outParams);
+ GenerateMethodParameters(m.tok, m, etran, out inParams, out outParams);
Bpl.RequiresSeq req = new Bpl.RequiresSeq();
Bpl.IdentifierExprSeq mod = new Bpl.IdentifierExprSeq();
@@ -3269,7 +3605,7 @@ namespace Microsoft.Dafny {
// Clean up
currentModule = null;
- currentMethod = null;
+ codeContext = null;
otherTmpVarCount = 0;
_tmpIEs.Clear();
}
@@ -3388,29 +3724,40 @@ namespace Microsoft.Dafny {
currentModule = null;
}
- private void GenerateMethodParameters(Method m, ExpressionTranslator etran, out Bpl.VariableSeq inParams, out Bpl.VariableSeq outParams) {
+ private void GenerateMethodParameters(IToken tok, ICodeContext m, ExpressionTranslator etran, out Bpl.VariableSeq inParams, out Bpl.VariableSeq outParams) {
+ GenerateMethodParametersChoose(tok, m, !m.IsStatic, true, true, etran, out inParams, out outParams);
+ }
+
+ private void GenerateMethodParametersChoose(IToken tok, ICodeContext m, bool includeReceiver, bool includeInParams, bool includeOutParams,
+ ExpressionTranslator etran, out Bpl.VariableSeq inParams, out Bpl.VariableSeq outParams) {
inParams = new Bpl.VariableSeq();
outParams = new Bpl.VariableSeq();
- if (!m.IsStatic) {
+ if (includeReceiver) {
+ var receiverType = m is MemberDecl ? Resolver.GetReceiverType(tok, (MemberDecl)m) : Resolver.GetThisType(tok, (IteratorDecl)m);
Bpl.Expr wh = Bpl.Expr.And(
- Bpl.Expr.Neq(new Bpl.IdentifierExpr(m.tok, "this", predef.RefType), predef.Null),
- etran.GoodRef(m.tok, new Bpl.IdentifierExpr(m.tok, "this", predef.RefType), Resolver.GetReceiverType(m.tok, m)));
- Bpl.Formal thVar = new Bpl.Formal(m.tok, new Bpl.TypedIdent(m.tok, "this", predef.RefType, wh), true);
+ Bpl.Expr.Neq(new Bpl.IdentifierExpr(tok, "this", predef.RefType), predef.Null),
+ etran.GoodRef(tok, new Bpl.IdentifierExpr(tok, "this", predef.RefType), receiverType));
+ Bpl.Formal thVar = new Bpl.Formal(tok, new Bpl.TypedIdent(tok, "this", predef.RefType, wh), true);
inParams.Add(thVar);
}
- foreach (Formal p in m.Ins) {
- Bpl.Type varType = TrType(p.Type);
- Bpl.Expr wh = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
- inParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, wh), true));
+ if (includeInParams) {
+ foreach (Formal p in m.Ins) {
+ Bpl.Type varType = TrType(p.Type);
+ Bpl.Expr wh = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
+ inParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, wh), true));
+ }
}
- foreach (Formal p in m.Outs) {
- Bpl.Type varType = TrType(p.Type);
- Bpl.Expr wh = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
- outParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, wh), false));
+ if (includeOutParams) {
+ foreach (Formal p in m.Outs) {
+ Bpl.Type varType = TrType(p.Type);
+ Bpl.Expr wh = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
+ outParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, wh), false));
+ }
}
}
- class BoilerplateTriple { // a triple that is now a quintuple
+ class BoilerplateTriple
+ { // a triple that is now a quintuple
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(tok != null);
@@ -3555,6 +3902,8 @@ namespace Microsoft.Dafny {
return Bpl.Type.Bool;
} else if (type is IntType) {
return Bpl.Type.Int;
+ } else if (type is EverIncreasingType) {
+ return Bpl.Type.Int;
} else if (type.IsTypeParameter) {
return predef.BoxType;
} else if (type.IsRefType) {
@@ -3613,7 +3962,7 @@ namespace Microsoft.Dafny {
Contract.Requires(errorMessage != null);
Contract.Ensures(Contract.Result<Bpl.PredicateCmd>() != null);
- if (RefinementToken.IsInherited(refinesToken, currentModule) && (currentMethod == null || !currentMethod.MustReverify)) {
+ if (RefinementToken.IsInherited(refinesToken, currentModule) && (codeContext == null || !codeContext.MustReverify)) {
// produce an assume instead
return new Bpl.AssumeCmd(tok, condition);
} else {
@@ -3632,7 +3981,7 @@ namespace Microsoft.Dafny {
Contract.Requires(condition != null);
Contract.Ensures(Contract.Result<Bpl.PredicateCmd>() != null);
- if (RefinementToken.IsInherited(refinesTok, currentModule) && (currentMethod == null || !currentMethod.MustReverify)) {
+ if (RefinementToken.IsInherited(refinesTok, currentModule) && (codeContext == null || !codeContext.MustReverify)) {
// produce a "skip" instead
return new Bpl.AssumeCmd(tok, Bpl.Expr.True);
} else {
@@ -3652,7 +4001,7 @@ namespace Microsoft.Dafny {
Contract.Requires(condition != null);
Contract.Ensures(Contract.Result<Bpl.PredicateCmd>() != null);
- if (RefinementToken.IsInherited(tok, currentModule) && (currentMethod == null || !currentMethod.MustReverify)) {
+ if (RefinementToken.IsInherited(tok, currentModule) && (codeContext == null || !codeContext.MustReverify)) {
// produce an assume instead
return new Bpl.AssumeCmd(tok, condition, kv);
} else {
@@ -3691,7 +4040,7 @@ namespace Microsoft.Dafny {
Contract.Requires(block != null);
Contract.Requires(locals != null);
Contract.Requires(etran != null);
- Contract.Requires(currentMethod != null && predef != null);
+ Contract.Requires(codeContext != null && predef != null);
Contract.Ensures(Contract.Result<Bpl.StmtList>() != null);
return TrStmt2StmtList(new Bpl.StmtListBuilder(), block, locals, etran);
@@ -3703,7 +4052,7 @@ namespace Microsoft.Dafny {
Contract.Requires(block != null);
Contract.Requires(locals != null);
Contract.Requires(etran != null);
- Contract.Requires(currentMethod != null && predef != null);
+ Contract.Requires(codeContext != null && predef != null);
Contract.Ensures(Contract.Result<Bpl.StmtList>() != null);
TrStmt(block, builder, locals, etran);
@@ -3716,7 +4065,7 @@ namespace Microsoft.Dafny {
Contract.Requires(builder != null);
Contract.Requires(locals != null);
Contract.Requires(etran != null);
- Contract.Requires(currentMethod != null && predef != null);
+ Contract.Requires(codeContext != null && predef != null);
if (stmt is PredicateStmt) {
if (stmt is AssertStmt || DafnyOptions.O.DisallowSoundnessCheating) {
AddComment(builder, stmt, "assert statement");
@@ -3766,6 +4115,58 @@ namespace Microsoft.Dafny {
TrStmt(s.hiddenUpdate, builder, locals, etran);
}
builder.Add(new Bpl.ReturnCmd(stmt.Tok));
+ } else if (stmt is YieldStmt) {
+ var s = (YieldStmt)stmt;
+ AddComment(builder, s, "yield statement");
+ Contract.Assert(codeContext is IteratorDecl);
+ var iter = (IteratorDecl)codeContext;
+ // this.ys := this.ys + [this.y];
+ var th = new ThisExpr(iter.tok);
+ th.Type = Resolver.GetThisType(iter.tok, iter); // resolve here
+ Contract.Assert(iter.OutsFields.Count == iter.OutsHistoryFields.Count);
+ for (int i = 0; i < iter.OutsFields.Count; i++) {
+ var y = iter.OutsFields[i];
+ var dafnyY = new FieldSelectExpr(s.Tok, th, y.Name);
+ dafnyY.Field = y; dafnyY.Type = y.Type; // resolve here
+ var ys = iter.OutsHistoryFields[i];
+ var dafnyYs = new FieldSelectExpr(s.Tok, th, ys.Name);
+ dafnyYs.Field = ys; dafnyYs.Type = ys.Type; // resolve here
+ var dafnySingletonY = new SeqDisplayExpr(s.Tok, new List<Expression>() { dafnyY });
+ dafnySingletonY.Type = ys.Type; // resolve here
+ var rhs = new BinaryExpr(s.Tok, BinaryExpr.Opcode.Add, dafnyYs, dafnySingletonY);
+ rhs.ResolvedOp = BinaryExpr.ResolvedOpcode.Concat;
+ rhs.Type = ys.Type; // resolve here
+ var cmd = Bpl.Cmd.SimpleAssign(s.Tok, (Bpl.IdentifierExpr/*TODO: this cast is rather dubious*/)etran.HeapExpr,
+ ExpressionTranslator.UpdateHeap(s.Tok, etran.HeapExpr, etran.TrExpr(th), new Bpl.IdentifierExpr(s.Tok, GetField(ys)), etran.TrExpr(rhs)));
+ builder.Add(cmd);
+ }
+ // yieldCount := yieldCount + 1; assume yieldCount == |ys|;
+ var yc = new Bpl.IdentifierExpr(s.Tok, yieldCountVariable);
+ var incYieldCount = Bpl.Cmd.SimpleAssign(s.Tok, yc, Bpl.Expr.Binary(s.Tok, Bpl.BinaryOperator.Opcode.Add, yc, Bpl.Expr.Literal(1)));
+ builder.Add(incYieldCount);
+ builder.Add(new Bpl.AssumeCmd(s.Tok, YieldCountAssumption(iter, etran)));
+ // assert YieldEnsures[subst]; // where 'subst' replaces "old(E)" with "E" being evaluated in $_OldIterHeap
+ var yeEtran = new ExpressionTranslator(this, predef, etran.HeapExpr, new Bpl.IdentifierExpr(s.Tok, "$_OldIterHeap", predef.HeapType));
+ foreach (var p in iter.YieldEnsures) {
+ if (p.IsFree && !DafnyOptions.O.DisallowSoundnessCheating) {
+ // do nothing
+ } else {
+ bool splitHappened; // actually, we don't care
+ var ss = TrSplitExpr(p.E, yeEtran, out splitHappened);
+ foreach (var split in ss) {
+ if (RefinementToken.IsInherited(split.E.tok, currentModule)) {
+ // this postcondition was inherited into this module, so just ignore it
+ } else if (!split.IsFree) {
+ var yieldToken = new NestedToken(s.Tok, split.E.tok);
+ builder.Add(AssertNS(yieldToken, split.E, "possible violation of yield-ensures condition", stmt.Tok));
+ }
+ }
+ builder.Add(new Bpl.AssumeCmd(stmt.Tok, yeEtran.TrExpr(p.E)));
+ }
+ }
+ YieldHavoc(iter.tok, iter, builder, etran);
+ builder.Add(CaptureState(s.Tok));
+
} else if (stmt is AssignSuchThatStmt) {
var s = (AssignSuchThatStmt)stmt;
AddComment(builder, s, "assign-such-that statement");
@@ -4106,6 +4507,38 @@ namespace Microsoft.Dafny {
}
}
+ /// <summary>
+ /// Generate:
+ /// havoc Heap \ {this} \ _reads \ _new;
+ /// assume this.Valid();
+ /// assume YieldRequires;
+ /// $_OldIterHeap := Heap;
+ /// </summary>
+ void YieldHavoc(IToken tok, IteratorDecl iter, StmtListBuilder builder, ExpressionTranslator etran) {
+ Contract.Requires(tok != null);
+ Contract.Requires(iter != null);
+ Contract.Requires(builder != null);
+ Contract.Requires(etran != null);
+ // havoc Heap \ {this} \ _reads \ _new;
+ var th = new ThisExpr(tok);
+ th.Type = Resolver.GetThisType(tok, iter); // resolve here
+ var rds = new FieldSelectExpr(tok, th, iter.Member_Reads.Name);
+ rds.Field = iter.Member_Reads; // resolve here
+ rds.Type = iter.Member_Reads.Type; // resolve here
+ var nw = new FieldSelectExpr(tok, th, iter.Member_New.Name);
+ nw.Field = iter.Member_New; // resolve here
+ nw.Type = iter.Member_New.Type; // resolve here
+ builder.Add(new Bpl.CallCmd(tok, "$YieldHavoc",
+ new List<Bpl.Expr>() { etran.TrExpr(th), etran.TrExpr(rds), etran.TrExpr(nw) },
+ new List<Bpl.IdentifierExpr>()));
+ // assume YieldRequires;
+ foreach (var p in iter.YieldRequires) {
+ builder.Add(new Bpl.AssumeCmd(tok, etran.TrExpr(p.E)));
+ }
+ // $_OldIterHeap := Heap;
+ builder.Add(Bpl.Cmd.SimpleAssign(tok, new Bpl.IdentifierExpr(tok, "$_OldIterHeap", predef.HeapType), etran.HeapExpr));
+ }
+
List<Tuple<List<BoundVar>, Expression>> GeneratePartialGuesses(List<BoundVar> bvars, Expression expression) {
if (bvars.Count == 0) {
var tup = new Tuple<List<BoundVar>, Expression>(new List<BoundVar>(), expression);
@@ -4280,7 +4713,12 @@ namespace Microsoft.Dafny {
} else {
lhsType = ((MultiSelectExpr)lhs).Type;
}
- CheckSubrange(r.Tok, etran.TrExpr(rhs), lhsType, definedness);
+ var translatedRhs = etran.TrExpr(rhs);
+ CheckSubrange(r.Tok, translatedRhs, lhsType, definedness);
+ if (lhs is FieldSelectExpr) {
+ var fse = (FieldSelectExpr)lhs;
+ Check_NewRestrictions(fse.tok, obj, fse.Field, translatedRhs, definedness, etran);
+ }
}
// check for duplicate LHSs
@@ -4432,13 +4870,18 @@ namespace Microsoft.Dafny {
// initHeap := $Heap;
exporter.Add(Bpl.Cmd.SimpleAssign(tok, initHeap, etran.HeapExpr));
if (s0.Method.Ens.Exists(ens => MentionsOldState(ens.E))) {
+ var heapIdExpr = (Bpl.IdentifierExpr/*TODO: this cast is rather dubious*/)etran.HeapExpr;
// advance $Heap, Tick;
- exporter.Add(new Bpl.HavocCmd(tok, new Bpl.IdentifierExprSeq((Bpl.IdentifierExpr/*TODO: this cast is rather dubious*/)etran.HeapExpr, etran.Tick())));
+ exporter.Add(new Bpl.HavocCmd(tok, new Bpl.IdentifierExprSeq(heapIdExpr, etran.Tick())));
foreach (BoilerplateTriple tri in GetTwoStateBoilerplate(tok, new List<FrameExpression>(), initEtran, etran, initEtran)) {
if (tri.IsFree) {
exporter.Add(new Bpl.AssumeCmd(tok, tri.Expr));
}
}
+ if (codeContext is IteratorDecl) {
+ var iter = (IteratorDecl)codeContext;
+ RecordNewObjectsIn_New(tok, iter, initHeap, heapIdExpr, exporter, locals, etran);
+ }
} else {
// As an optimization, create the illusion that the $Heap is unchanged by the parallel body.
exporter.Add(new Bpl.HavocCmd(tok, new Bpl.IdentifierExprSeq(etran.Tick())));
@@ -4476,6 +4919,32 @@ namespace Microsoft.Dafny {
}
}
+ void RecordNewObjectsIn_New(IToken tok, IteratorDecl iter, Bpl.Expr initHeap, Bpl.IdentifierExpr currentHeap,
+ Bpl.StmtListBuilder builder, Bpl.VariableSeq locals, ExpressionTranslator etran) {
+ Contract.Requires(tok != null);
+ Contract.Requires(iter != null);
+ Contract.Requires(initHeap != null);
+ Contract.Requires(currentHeap != null);
+ Contract.Requires(builder != null);
+ Contract.Requires(locals != null);
+ Contract.Requires(etran != null);
+ // Add all newly allocated objects to the set this._new
+ var updatedSet = new Bpl.LocalVariable(iter.tok, new Bpl.TypedIdent(iter.tok, "$iter_newUpdate" + otherTmpVarCount, predef.SetType(iter.tok, predef.BoxType)));
+ otherTmpVarCount++;
+ locals.Add(updatedSet);
+ var updatedSetIE = new Bpl.IdentifierExpr(iter.tok, updatedSet);
+ // call $iter_newUpdate := $IterCollectNewObjects(initHeap, $Heap, this, _new);
+ var th = new Bpl.IdentifierExpr(iter.tok, etran.This, predef.RefType);
+ var nwField = new Bpl.IdentifierExpr(tok, GetField(iter.Member_New));
+ Bpl.Cmd cmd = new CallCmd(iter.tok, "$IterCollectNewObjects",
+ new List<Bpl.Expr>() { initHeap, etran.HeapExpr, th, nwField },
+ new List<Bpl.IdentifierExpr>() { updatedSetIE });
+ builder.Add(cmd);
+ // $Heap[this, _new] := $iter_newUpdate;
+ cmd = Bpl.Cmd.SimpleAssign(iter.tok, currentHeap, ExpressionTranslator.UpdateHeap(iter.tok, currentHeap, th, nwField, updatedSetIE));
+ builder.Add(cmd);
+ }
+
void TrParallelProof(ParallelStmt s, Bpl.StmtListBuilder definedness, Bpl.StmtListBuilder exporter, Bpl.VariableSeq locals, ExpressionTranslator etran) {
// Translate:
// parallel (x,y | Range(x,y))
@@ -4674,7 +5143,7 @@ namespace Microsoft.Dafny {
TrStmt_CheckWellformed(e, invDefinednessBuilder, locals, etran, true);
}
// include boilerplate invariants
- foreach (BoilerplateTriple tri in GetTwoStateBoilerplate(s.Tok, currentMethod.Mod.Expressions, etranPreLoop, etran, etran.Old))
+ foreach (BoilerplateTriple tri in GetTwoStateBoilerplate(s.Tok, codeContext.Modifies.Expressions, etranPreLoop, etran, etran.Old))
{
if (tri.IsFree) {
invariants.Add(new Bpl.AssumeCmd(s.Tok, tri.Expr));
@@ -4830,6 +5299,16 @@ namespace Microsoft.Dafny {
bLhss[i] = new Bpl.IdentifierExpr(lhs.tok, var.Name, ty);
}
}
+ Bpl.IdentifierExpr initHeap = null;
+ if (codeContext is IteratorDecl) {
+ // var initHeap := $Heap;
+ var initHeapVar = new Bpl.LocalVariable(s.Tok, new Bpl.TypedIdent(s.Tok, "$initHeapCallStmt#" + otherTmpVarCount, predef.HeapType));
+ otherTmpVarCount++;
+ locals.Add(initHeapVar);
+ initHeap = new Bpl.IdentifierExpr(s.Tok, initHeapVar);
+ // initHeap := $Heap;
+ builder.Add(Bpl.Cmd.SimpleAssign(s.Tok, initHeap, etran.HeapExpr));
+ }
ProcessCallStmt(s.Tok, s.Receiver, actualReceiver, s.Method, s.Args, bLhss, lhsTypes, builder, locals, etran);
for (int i = 0; i < lhsBuilders.Count; i++) {
var lhs = s.Lhs[i];
@@ -4849,6 +5328,11 @@ namespace Microsoft.Dafny {
lhsBuilders[i](bRhs, builder, etran);
}
+ if (codeContext is IteratorDecl) {
+ var iter = (IteratorDecl)codeContext;
+ Contract.Assert(initHeap != null);
+ RecordNewObjectsIn_New(s.Tok, iter, initHeap, (Bpl.IdentifierExpr/*TODO: this cast is dubious*/)etran.HeapExpr, builder, locals, etran);
+ }
builder.Add(CaptureState(s.Tok));
}
@@ -4911,9 +5395,10 @@ namespace Microsoft.Dafny {
// Check termination
ModuleDefinition module = method.EnclosingClass.Module;
if (module == currentModule) {
- if (module.CallGraph.GetSCCRepresentative(method) == module.CallGraph.GetSCCRepresentative(currentMethod)) {
+ var caller = codeContext is Method ? (Method)codeContext : ((IteratorDecl)codeContext).Member_MoveNext;
+ if (module.CallGraph.GetSCCRepresentative(method) == module.CallGraph.GetSCCRepresentative(caller)) {
bool contextDecrInferred, calleeDecrInferred;
- List<Expression> contextDecreases = MethodDecreasesWithDefault(currentMethod, out contextDecrInferred);
+ List<Expression> contextDecreases = MethodDecreasesWithDefault(caller, out contextDecrInferred);
List<Expression> calleeDecreases = MethodDecreasesWithDefault(method, out calleeDecrInferred);
CheckCallTermination(tok, contextDecreases, calleeDecreases, null, receiver, substMap, etran, builder, contextDecrInferred, null);
}
@@ -4940,7 +5425,7 @@ namespace Microsoft.Dafny {
// Make the call
string name;
- if (RefinementToken.IsInherited(method.tok, currentModule) && (currentMethod == null || !currentMethod.MustReverify)) {
+ if (RefinementToken.IsInherited(method.tok, currentModule) && (codeContext == null || !codeContext.MustReverify)) {
name = string.Format("RefinementCall_{0}$${1}", currentModule.Name, method.FullCompileName);
} else {
name = method.FullCompileName;
@@ -5246,6 +5731,10 @@ namespace Microsoft.Dafny {
less = Bpl.Expr.And(Bpl.Expr.Le(Bpl.Expr.Literal(0), e0), less);
atmost = Bpl.Expr.And(Bpl.Expr.Le(Bpl.Expr.Literal(0), e0), atmost);
}
+ } else if (ty is EverIncreasingType) {
+ eq = Bpl.Expr.Eq(e0, e1);
+ less = Bpl.Expr.Gt(e0, e1);
+ atmost = Bpl.Expr.Ge(e0, e1);
} else if (ty is SetType) {
eq = FunctionCall(tok, BuiltinFunction.SetEqual, null, e0, e1);
less = etran.ProperSubset(tok, e0, e1);
@@ -5640,7 +6129,7 @@ namespace Microsoft.Dafny {
var bLhs = (Bpl.IdentifierExpr)etran.TrExpr(lhs); // TODO: is this cast always justified?
bLhss.Add(rhsCanAffectPreviouslyKnownExpressions ? null : bLhs);
lhsBuilders.Add(delegate(Bpl.Expr rhs, Bpl.StmtListBuilder bldr, ExpressionTranslator et) {
- builder.Add(Bpl.Cmd.SimpleAssign(tok, bLhs, rhs));
+ bldr.Add(Bpl.Cmd.SimpleAssign(tok, bLhs, rhs));
});
} else if (lhs is FieldSelectExpr) {
@@ -5664,11 +6153,12 @@ namespace Microsoft.Dafny {
bLhss.Add(null);
lhsBuilders.Add(delegate(Bpl.Expr rhs, Bpl.StmtListBuilder bldr, ExpressionTranslator et) {
+ Check_NewRestrictions(tok, obj, fse.Field, rhs, bldr, et);
var h = (Bpl.IdentifierExpr)et.HeapExpr; // TODO: is this cast always justified?
Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(tok, h, ExpressionTranslator.UpdateHeap(tok, h, obj, new Bpl.IdentifierExpr(tok, GetField(fse.Field)), rhs));
- builder.Add(cmd);
+ bldr.Add(cmd);
// assume $IsGoodHeap($Heap);
- builder.Add(AssumeGoodHeap(tok, et));
+ bldr.Add(AssumeGoodHeap(tok, et));
});
} else if (lhs is SeqSelectExpr) {
@@ -5700,9 +6190,9 @@ namespace Microsoft.Dafny {
lhsBuilders.Add(delegate(Bpl.Expr rhs, Bpl.StmtListBuilder bldr, ExpressionTranslator et) {
var h = (Bpl.IdentifierExpr)et.HeapExpr; // TODO: is this cast always justified?
Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(tok, h, ExpressionTranslator.UpdateHeap(tok, h, obj, fieldName, rhs));
- builder.Add(cmd);
+ bldr.Add(cmd);
// assume $IsGoodHeap($Heap);
- builder.Add(AssumeGoodHeap(tok, et));
+ bldr.Add(AssumeGoodHeap(tok, et));
});
} else {
@@ -5732,9 +6222,9 @@ namespace Microsoft.Dafny {
lhsBuilders.Add(delegate(Bpl.Expr rhs, Bpl.StmtListBuilder bldr, ExpressionTranslator et) {
var h = (Bpl.IdentifierExpr)et.HeapExpr; // TODO: is this cast always justified?
Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(tok, h, ExpressionTranslator.UpdateHeap(tok, h, obj, fieldName, rhs));
- builder.Add(cmd);
+ bldr.Add(cmd);
// assume $IsGoodHeap($Heap);
- builder.Add(AssumeGoodHeap(tok, etran));
+ bldr.Add(AssumeGoodHeap(tok, etran));
});
}
@@ -5835,6 +6325,16 @@ namespace Microsoft.Dafny {
Bpl.IdentifierExpr heap = (Bpl.IdentifierExpr/*TODO: this cast is dubious*/)etran.HeapExpr;
Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(tok, heap, ExpressionTranslator.UpdateHeap(tok, heap, nw, alloc, Bpl.Expr.True));
builder.Add(cmd);
+ if (codeContext is IteratorDecl) {
+ var iter = (IteratorDecl)codeContext;
+ // $Heap[this, _new] := Set#UnionOne<BoxType>($Heap[this, _new], $Box($nw));
+ var th = new Bpl.IdentifierExpr(tok, etran.This, predef.RefType);
+ var nwField = new Bpl.IdentifierExpr(tok, GetField(iter.Member_New));
+ var thisDotNew = ExpressionTranslator.ReadHeap(tok, etran.HeapExpr, th, nwField);
+ var unionOne = FunctionCall(tok, BuiltinFunction.SetUnionOne, predef.BoxType, thisDotNew, FunctionCall(tok, BuiltinFunction.Box, null, nw));
+ var heapRhs = ExpressionTranslator.UpdateHeap(tok, etran.HeapExpr, th, nwField, unionOne);
+ builder.Add(Bpl.Cmd.SimpleAssign(tok, heap, heapRhs));
+ }
// assume $IsGoodHeap($Heap);
builder.Add(AssumeGoodHeap(tok, etran));
if (tRhs.InitCall != null) {
@@ -5870,6 +6370,23 @@ namespace Microsoft.Dafny {
return null;
}
+ void Check_NewRestrictions(IToken tok, Bpl.Expr obj, Field f, Bpl.Expr rhs, StmtListBuilder builder, ExpressionTranslator etran) {
+ Contract.Requires(tok != null);
+ Contract.Requires(obj != null);
+ Contract.Requires(f != null);
+ Contract.Requires(rhs != null);
+ Contract.Requires(builder != null);
+ Contract.Requires(etran != null);
+ var iter = f.EnclosingClass as IteratorDecl;
+ if (iter != null && f == iter.Member_New) {
+ // Assignments to an iterator _new field is only allowed to shrink the set, so:
+ // assert Set#Subset(rhs, obj._new);
+ var fId = new Bpl.IdentifierExpr(tok, GetField(f));
+ var subset = FunctionCall(tok, BuiltinFunction.SetSubset, null, rhs, ExpressionTranslator.ReadHeap(tok, etran.HeapExpr, obj, fId));
+ builder.Add(Assert(tok, subset, "an assignment to " + f.Name + " is only allowed to shrink the set"));
+ }
+ }
+
Bpl.AssumeCmd AssumeGoodHeap(IToken tok, ExpressionTranslator etran) {
Contract.Requires(tok != null);
Contract.Requires(etran != null);
@@ -6014,7 +6531,13 @@ namespace Microsoft.Dafny {
Contract.Requires(layerOffset + offset <= 1);
Contract.Ensures(Contract.Result<ExpressionTranslator>() != null);
- return new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, layerOffset + offset, modifiesFrame);
+ var et = new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, layerOffset + offset, modifiesFrame);
+ if (this.oldEtran != null) {
+ var etOld = new ExpressionTranslator(translator, predef, Old.HeapExpr, This, applyLimited_CurrentFunction, layerOffset + offset, modifiesFrame);
+ etOld.oldEtran = etOld;
+ et.oldEtran = etOld;
+ }
+ return et;
}
public Bpl.IdentifierExpr TheFrame(IToken tok)
@@ -7518,7 +8041,7 @@ namespace Microsoft.Dafny {
if (f.Body != null && !(f.Body.Resolved is MatchExpr)) {
if (RefinementToken.IsInherited(fexp.tok, currentModule) &&
f is Predicate && ((Predicate)f).BodyOrigin == Predicate.BodyOriginKind.DelayedDefinition &&
- (currentMethod == null || !currentMethod.MustReverify)) {
+ (codeContext == null || !codeContext.MustReverify)) {
// The function was inherited as body-less but is now given a body. Don't inline the body (since, apparently, everything
// that needed to be proved about the function was proved already in the previous module, even without the body definition).
} else {
@@ -7669,7 +8192,7 @@ namespace Microsoft.Dafny {
}
// TODO: Is the the following call to ContainsChange expensive? It's linear in the size of "expr", but we get here many times in TrSpliExpr, so wouldn't the total
// time in the size of the expression passed to the first TrSpliExpr be quadratic?
- if (RefinementToken.IsInherited(expr.tok, currentModule) && (currentMethod == null || !currentMethod.MustReverify) && RefinementTransformer.ContainsChange(expr, currentModule)) {
+ if (RefinementToken.IsInherited(expr.tok, currentModule) && (codeContext == null || !codeContext.MustReverify) && RefinementTransformer.ContainsChange(expr, currentModule)) {
// If "expr" contains a subexpression that has changed from the inherited expression, we'll destructively
// change the token of the translated expression to make it look like it's not inherited. This will cause "e" to
// be verified again in the refining module.
@@ -8693,7 +9216,7 @@ namespace Microsoft.Dafny {
}
}
- Attributes SubstAttributes(Attributes attrs) {
+ public Attributes SubstAttributes(Attributes attrs) {
Contract.Requires(cce.NonNullDictionaryAndValues(substMap));
if (attrs != null) {
List<Attributes.Argument> newArgs = new List<Attributes.Argument>(); // allocate it eagerly, what the heck, it doesn't seem worth the extra complexity in the code to do it lazily for the infrequently occurring attributes
diff --git a/Test/dafny0/Answer b/Test/dafny0/Answer
index 571377e8..140f642f 100644
--- a/Test/dafny0/Answer
+++ b/Test/dafny0/Answer
@@ -510,7 +510,7 @@ ResolutionErrors.dfy(194,27): Error: ghost-context break statement is not allowe
ResolutionErrors.dfy(217,12): Error: ghost-context break statement is not allowed to break out of non-ghost loop
ResolutionErrors.dfy(229,12): Error: trying to break out of more loop levels than there are enclosing loops
ResolutionErrors.dfy(233,12): Error: ghost-context break statement is not allowed to break out of non-ghost loop
-ResolutionErrors.dfy(238,8): Error: return statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
+ResolutionErrors.dfy(238,8): Error: return statement is not allowed in this context (because it is guarded by a specification-only expression)
ResolutionErrors.dfy(10,16): Error: 'decreases *' is not allowed on ghost loops
ResolutionErrors.dfy(22,11): Error: array selection requires an array2 (got array3<T>)
ResolutionErrors.dfy(23,12): Error: sequence/array/map selection requires a sequence, array or map (got array3<T>)
@@ -1359,8 +1359,8 @@ Dafny program verifier finished with 12 verified, 0 errors
-------------------- EqualityTypes.dfy --------------------
EqualityTypes.dfy(31,13): Error: a type declaration that requires equality support cannot be replaced by a codatatype
EqualityTypes.dfy(32,11): Error: datatype 'Y' is used to refine an arbitrary type with equality support, but 'Y' does not support equality
-EqualityTypes.dfy(37,11): Error: arbitrary type 'X' is not allowed to be replaced by a datatype that takes type parameters
-EqualityTypes.dfy(38,8): Error: arbitrary type 'Y' is not allowed to be replaced by a class that takes type parameters
+EqualityTypes.dfy(37,11): Error: arbitrary type 'X' is not allowed to be replaced by a datatype that takes a different number of type parameters
+EqualityTypes.dfy(38,8): Error: arbitrary type 'Y' is not allowed to be replaced by a class that takes a different number of type parameters
EqualityTypes.dfy(42,11): Error: datatype 'X' is used to refine an arbitrary type with equality support, but 'X' does not support equality
EqualityTypes.dfy(43,11): Error: datatype 'Y' is used to refine an arbitrary type with equality support, but 'Y' does not support equality
EqualityTypes.dfy(63,7): Error: == can only be applied to expressions of types that support equality (got Dt<T>)
@@ -1649,6 +1649,89 @@ Execution trace:
Calculations.dfy(31,2): anon5_Else
Dafny program verifier finished with 4 verified, 4 errors
+-------------------- IteratorResolution.dfy --------------------
+IteratorResolution.dfy(59,11): Error: LHS of assignment does not denote a mutable field
+IteratorResolution.dfy(64,18): Error: arguments must have the same type (got _T0 and int)
+IteratorResolution.dfy(76,19): Error: RHS (of type bool) not assignable to LHS (of type int)
+IteratorResolution.dfy(79,13): Error: when allocating an object of type 'GenericIteratorResult', one of its constructor methods must be called
+IteratorResolution.dfy(83,15): Error: logical negation expects a boolean argument (instead got int)
+IteratorResolution.dfy(17,11): Error: LHS of assignment does not denote a mutable field
+IteratorResolution.dfy(19,12): Error: LHS of assignment does not denote a mutable field
+IteratorResolution.dfy(123,9): Error: unresolved identifier: _decreases3
+IteratorResolution.dfy(124,21): Error: arguments must have the same type (got int and ?)
+IteratorResolution.dfy(125,14): Error: LHS of assignment does not denote a mutable field
+IteratorResolution.dfy(132,9): Error: unresolved identifier: _decreases1
+IteratorResolution.dfy(137,9): Error: unresolved identifier: _decreases0
+12 resolution/type errors detected in IteratorResolution.dfy
+
+-------------------- Iterators.dfy --------------------
+Iterators.dfy(100,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Iterators.dfy(103,14): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Then
+ (0,0): anon3
+Iterators.dfy(174,28): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon15_Then
+Iterators.dfy(205,7): Error: an assignment to _new is only allowed to shrink the set
+Execution trace:
+ (0,0): anon0
+ Iterators.dfy(194,3): anon17_LoopHead
+ (0,0): anon17_LoopBody
+ Iterators.dfy(194,3): anon18_Else
+ (0,0): anon5
+ Iterators.dfy(194,3): anon20_Else
+ (0,0): anon21_Then
+Iterators.dfy(209,21): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Iterators.dfy(194,3): anon17_LoopHead
+ (0,0): anon17_LoopBody
+ Iterators.dfy(194,3): anon18_Else
+ (0,0): anon5
+ Iterators.dfy(194,3): anon20_Else
+ (0,0): anon22_Then
+Iterators.dfy(37,14): Error BP5002: A precondition for this call might not hold.
+Iterators.dfy(1,10): Related location: This is the precondition that might not hold.
+Execution trace:
+ (0,0): anon0
+ (0,0): anon37_Then
+ (0,0): anon2
+ (0,0): anon38_Then
+ (0,0): anon5
+ (0,0): anon39_Then
+Iterators.dfy(86,14): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Iterators.dfy(116,16): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+Iterators.dfy(147,16): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Else
+Iterators.dfy(152,16): Error BP5002: A precondition for this call might not hold.
+Iterators.dfy(122,10): Related location: This is the precondition that might not hold.
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Then
+ (0,0): anon3
+Iterators.dfy(231,14): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Iterators.dfy(222,3): anon15_LoopHead
+ (0,0): anon15_LoopBody
+ Iterators.dfy(222,3): anon16_Else
+ (0,0): anon8
+ Iterators.dfy(222,3): anon19_Else
+ (0,0): anon20_Else
+
+Dafny program verifier finished with 38 verified, 11 errors
-------------------- Superposition.dfy --------------------
diff --git a/Test/dafny0/IteratorResolution.dfy b/Test/dafny0/IteratorResolution.dfy
new file mode 100644
index 00000000..60b1bc7e
--- /dev/null
+++ b/Test/dafny0/IteratorResolution.dfy
@@ -0,0 +1,138 @@
+iterator MyIter()
+
+module Mx {
+
+ iterator ExampleIterator(k: int) yields (x: int, y: int)
+ {
+ var i := k;
+ while (true) {
+ if (i % 77 == 0) { yield; }
+ yield i, -i;
+ i := i + 1;
+ }
+ }
+
+ method IteratorUser() {
+ var iter := new ExampleIterator.ExampleIterator(15);
+ iter.k := 12; // error: not allowed to assign to iterator's in-parameters
+ iter.x := 12; // allowed (but this destroys the validity of 'iter'
+ iter.xs := []; // error: not allowed to assign to iterator's yield-history variables
+ var j := 0;
+ while (j < 100) {
+ var more := iter.MoveNext();
+ if (!more) {
+ break;
+ }
+ print iter.x, iter.y;
+ j := j + 1;
+ }
+ }
+
+ static method StaticM(k: nat) returns (m: int)
+ {
+ m := k;
+ }
+
+ module Inner {
+ iterator YetAnother(x: int, y: int, z: int) yields (a: bool, b: bool)
+ requires true;
+ }
+
+ class Client {
+ method M() {
+ var m := StaticM(5);
+ var it := new ExampleIterator.ExampleIterator(100);
+ var a, b := Worker(it);
+ }
+ method Worker(xi: ExampleIterator) returns (k: int, m: int) {
+ k, m := xi.k + xi.x, xi.y;
+ var mr := xi.MoveNext();
+ if (mr) {
+ k := xi.x;
+ } else {
+ assert k == xi.k + xi.x && m == xi.y;
+ }
+ }
+ method GenericTester(g0: GenericIterator<bool>, g2: GenericIterator)
+ requires g0.u;
+ {
+ g0.t := true; // error: not allowed to assign to .t
+ g0.u := true; // allowed (but this destroys the validity of 'iter'
+ var g1 := new GenericIterator.GenericIterator(20);
+ assert g1.u < 200; // .u is an integer
+
+ assert g2.u == 200; // error: the type parameter of g2 is unknown
+
+ var h0 := new GenericIteratorResult.GenericIteratorResult();
+ // so far, the instantiated type of h0 is unknown
+ var k := h0.t;
+ assert k < 87;
+
+ var h1 := new GenericIteratorResult.GenericIteratorResult();
+ // so far, the instantiated type of h1 is unknown
+ if (*) {
+ var b: bool := h1.t; // this determines h1 to be of type GenericIteratorResult<bool>
+ } else {
+ var x: int := h1.t; // error: h1 would have to be a GenericIteratorResult<int>
+ }
+
+ var h2 := new GenericIteratorResult; // error: constructor is not mentioned
+
+ var h3 := new GenericIterator.GenericIterator(30);
+ if (h3.t == h3.u) {
+ assert !h3.t; // error: type mismatch
+ }
+ }
+ }
+
+ iterator GenericIterator<T>(t: T) yields (u: T)
+ {
+ while (true) {
+ yield t;
+ }
+ }
+
+ iterator GenericIteratorResult<T>() yields (t: T)
+ {
+ while (*) { yield; }
+ }
+
+ class AnotherClient {
+ method StaticM(b: bool) // [sic]
+ {
+ }
+ method Q() {
+ StaticM(true); // this is supposed to resolve to AnotherClient.StaticM, not _default.StaticM
+ }
+ }
+}
+
+// --------------------------------- _decreases<n> fields
+
+class Cell
+{
+ var data: int;
+}
+
+iterator Dieter0(c: Cell)
+ requires c != null;
+ decreases c.data, c.data, c != null;
+{
+ assert _decreases0 == _decreases1;
+ assert _decreases2;
+ assert _decreases3 == null; // error: there is no _decreases3
+ assert _decreases0 == null; // error: type mismatch
+ _decreases2 := false; // error: the field is immutable
+}
+
+iterator Dieter1(c: Cell)
+ requires c != null;
+{
+ assert _decreases0 == c;
+ assert _decreases1; // error: there is no _decreases1
+}
+
+iterator Dieter2()
+{
+ assert _decreases0 == null; // error: there is no _decreases0
+}
diff --git a/Test/dafny0/Iterators.dfy b/Test/dafny0/Iterators.dfy
new file mode 100644
index 00000000..c6a0488b
--- /dev/null
+++ b/Test/dafny0/Iterators.dfy
@@ -0,0 +1,235 @@
+iterator MyIter<T>(q: T) yields (x: T, y: T)
+{
+}
+
+iterator MyIntIter() yields (x: int, y: int)
+{
+ x, y := 0, 0;
+ yield;
+ yield 2, 3;
+ x, y := y, x;
+ yield;
+}
+
+iterator Naturals(u: int) yields (n: nat)
+ requires u < 25; // just to have some precondition
+ ensures false; // never ends
+{
+ n := 0;
+ while (true)
+ {
+ yield n;
+ n := n + 1;
+ }
+}
+
+method Main() {
+ var m := new MyIter.MyIter(12);
+ assert m.ys == m.xs == [];
+ var a := m.x;
+ if (a <= 13) {
+ print "-- ", m.x, " --\n";
+ }
+
+ var mer := m.MoveNext();
+ if (mer) {
+ mer := m.MoveNext();
+ mer := m.MoveNext(); // error
+ }
+
+ var n := new MyIntIter.MyIntIter();
+ var patience := 10;
+ while (patience != 0)
+ invariant n.Valid() && fresh(n._new);
+ {
+ var more := n.MoveNext();
+ if (!more) { break; }
+ print n.x, ", ", n.y, "\n";
+ patience := patience - 1;
+ }
+
+ var o := new Naturals.Naturals(18);
+ var remaining := 100;
+ while (remaining != 0)
+ invariant o.Valid() && fresh(o._new);
+ {
+ var more := o.MoveNext();
+ assert more;
+ print o.n, " ";
+ remaining := remaining - 1;
+ if (remaining % 10 == 0) { print "\n"; }
+ }
+}
+
+// -----------------------------------------------------------
+
+class Cell {
+ var data: int;
+}
+
+iterator IterA(c: Cell)
+ requires c != null;
+ modifies c;
+{
+ while (true) {
+ c.data := *;
+ yield;
+ }
+}
+
+method TestIterA()
+{
+ var c := new Cell;
+ var iter := new IterA.IterA(c);
+ var tmp := c.data;
+ var more := iter.MoveNext();
+ assert tmp == c.data; // error
+}
+
+// -----------------------------------------------------------
+
+iterator IterB(c: Cell)
+ requires c != null;
+ modifies c;
+ yield ensures c.data == old(c.data);
+ ensures true;
+ decreases c, c != null, c.data;
+{
+ assert _decreases0 == c;
+ assert _decreases1 == (c != null);
+ assert _decreases2 == c.data; // error: c is not protected by the reads clause
+ var tmp := c.data;
+ if (*) { yield; }
+ assert tmp == c.data; // error: c is not protected by the reads clause
+ c.data := *;
+}
+
+method TestIterB()
+{
+ var c := new Cell;
+ var iter := new IterB.IterB(c);
+ var tmp := c.data;
+ var more := iter.MoveNext();
+ if (more) {
+ assert tmp == c.data; // no prob
+ } else {
+ assert tmp == c.data; // error: the postcondition says nothing about this
+ }
+}
+
+// ------------------ yield statements, and_decreases variables ----------------------------------
+
+iterator IterC(c: Cell)
+ requires c != null;
+ modifies c;
+ reads c;
+ yield ensures c.data == old(c.data);
+ ensures true;
+ decreases c, c, c.data;
+{
+ assert _decreases2 == c.data; // this time, all is fine, because the iterator has an appropriate reads clause
+ var tmp := c.data;
+ if (*) { yield; }
+ if (*) { yield; }
+ assert tmp == c.data; // this time, all is fine, because the iterator has an appropriate reads clause
+ c.data := *;
+}
+
+method TestIterC()
+{
+ var c := new Cell;
+ var iter := new IterC.IterC(c);
+ var tmp := c.data;
+ var more := iter.MoveNext();
+ if (more) {
+ assert tmp == c.data; // no prob
+ } else {
+ assert tmp == c.data; // error: the postcondition says nothing about this
+ }
+
+ iter := new IterC.IterC(c);
+ c.data := 17;
+ more := iter.MoveNext(); // error: iter.Valid() may not hold
+}
+
+// ------------------ allocations inside an iterator ------------------
+
+iterator AllocationIterator(x: Cell)
+{
+ assert _new == {};
+ var h := new Cell;
+ assert _new == {h};
+
+ SomeMethod();
+ assert x !in _new;
+ assert null !in _new;
+ assert h in _new;
+
+ ghost var saveNew := _new;
+ var u, v := AnotherMethod();
+ assert u in _new;
+ if {
+ case true => assert v in _new - saveNew ==> v != null && fresh(v);
+ case true => assert !fresh(v) ==> v !in _new;
+ case true => assert v in _new; // error: it may be, but, then again, it may not be
+ }
+}
+
+static method SomeMethod()
+{
+}
+
+static method AnotherMethod() returns (u: Cell, v: Cell)
+ ensures u != null && fresh(u);
+{
+ u := new Cell;
+}
+
+iterator DoleOutReferences(u: Cell) yields (r: Cell, c: Cell)
+ yield ensures r != null && fresh(r) && r !in _new;
+ yield ensures c != null && fresh(c); // but we don't say whether it's in _new
+ ensures false; // goes forever
+{
+ var myCells: seq<Cell> := [];
+ while (true)
+ invariant forall z :: z in myCells ==> z in _new;
+ {
+ c := new Cell;
+ r := new Cell;
+ c.data, r.data := 12, 12;
+ myCells := myCells + [c];
+ _new := _new - {r}; // remove our interest in 'r'
+ yield;
+ if (*) {
+ _new := _new + {c}; // fine, since 'c' is already in _new
+ _new := _new + {u}; // error: this does not shrink the set
+ } else if (*) {
+ assert c.data == 12; // still true, since 'c' is in _new
+ assert c in _new; // as is checked here as well
+ assert r.data == 12; // error: it may have changed
+ } else {
+ parallel (z | z in myCells) {
+ z.data := z.data + 1; // we're allowed to modify these, because they are all in _new
+ }
+ }
+ }
+}
+
+method ClientOfNewReferences()
+{
+ var m := new DoleOutReferences.DoleOutReferences(null);
+ var i := 86;
+ while (i != 0)
+ invariant m.Valid() && fresh(m._new);
+ {
+ var more := m.MoveNext();
+ assert more; // follows from 'ensures' clause of the iterator
+ if (*) {
+ m.r.data := i; // this change is allowed, because we own it
+ } else {
+ m.c.data := i; // this change, by itself, is allowed
+ assert m.Valid(); // error: ... however, don't expect m.Valid() to survive the change to m.c.data
+ }
+ i := i - 1;
+ }
+}
diff --git a/Test/dafny0/runtest.bat b/Test/dafny0/runtest.bat
index 23dc20e0..9118e388 100644
--- a/Test/dafny0/runtest.bat
+++ b/Test/dafny0/runtest.bat
@@ -24,7 +24,7 @@ for %%f in (TypeTests.dfy NatTypes.dfy SmallTests.dfy Definedness.dfy
CallStmtTests.dfy MultiSets.dfy PredExpr.dfy LetExpr.dfy
Predicates.dfy Skeletons.dfy Maps.dfy LiberalEquality.dfy
RefinementModificationChecking.dfy TailCalls.dfy
- Calculations.dfy) do (
+ Calculations.dfy IteratorResolution.dfy Iterators.dfy) do (
echo.
echo -------------------- %%f --------------------
%DAFNY_EXE% /compile:0 /print:out.bpl.tmp /dprint:out.dfy.tmp %* %%f
diff --git a/Util/Emacs/dafny-mode.el b/Util/Emacs/dafny-mode.el
index 1e197644..1ba6186b 100644
--- a/Util/Emacs/dafny-mode.el
+++ b/Util/Emacs/dafny-mode.el
@@ -31,13 +31,15 @@
`(,(dafny-regexp-opt '(
"class" "datatype" "codatatype" "type" "function" "predicate" "copredicate"
+ "iterator"
"ghost" "var" "method" "constructor"
"module" "import" "default" "as" "opened" "static" "refines"
- "returns" "requires" "ensures" "modifies" "reads" "free"
+ "returns" "yields" "requires" "ensures" "modifies" "reads" "free"
"invariant" "decreases"
)) . font-lock-builtin-face)
`(,(dafny-regexp-opt '(
- "assert" "assume" "break" "choose" "then" "else" "if" "label" "return" "while" "print" "where"
+ "assert" "assume" "break" "choose" "then" "else" "if" "label" "return" "yield"
+ "while" "print" "where"
"old" "forall" "exists" "new" "parallel" "calc" "in" "this" "fresh"
"match" "case" "false" "true" "null")) . font-lock-keyword-face)
`(,(dafny-regexp-opt '("array" "array2" "array3" "bool" "multiset" "map" "nat" "int" "object" "set" "seq")) . font-lock-type-face)
diff --git a/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs b/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs
index 8c3eee59..ac1b755c 100644
--- a/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs
+++ b/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs
@@ -17,12 +17,13 @@ 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", "codatatype", "type",
+ "class", "ghost", "static", "var", "method", "constructor", "datatype", "codatatype",
+ "iterator", "type",
"assert", "assume", "new", "this", "object", "refines",
"module", "import", "as", "default", "opened",
"if", "then", "else", "while", "invariant",
- "break", "label", "return", "parallel", "print",
- "returns", "requires", "ensures", "modifies", "reads", "decreases",
+ "break", "label", "return", "yield", "parallel", "print",
+ "returns", "yields", "requires", "ensures", "modifies", "reads", "decreases",
"bool", "nat", "int", "false", "true", "null",
"function", "predicate", "copredicate", "free",
"in", "forall", "exists",
@@ -269,6 +270,7 @@ namespace Demo
| "datatype"
| "codatatype"
| "type"
+ | "iterator"
| "assert"
| "assume"
| "new"
@@ -288,10 +290,12 @@ namespace Demo
| "break"
| "label"
| "return"
+ | "yield"
| "parallel"
| "calc"
| "print"
| "returns"
+ | "yields"
| "requires"
| "ensures"
| "modifies"
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension/IdentifierTagger.cs b/Util/VS2010/DafnyExtension/DafnyExtension/IdentifierTagger.cs
index 80a6dbb5..5ecc8dc2 100644
--- a/Util/VS2010/DafnyExtension/DafnyExtension/IdentifierTagger.cs
+++ b/Util/VS2010/DafnyExtension/DafnyExtension/IdentifierTagger.cs
@@ -139,7 +139,7 @@ namespace DafnyLanguage
foreach (var ctor in dt.Ctors) {
foreach (var dtor in ctor.Destructors) {
if (dtor != null) {
- IdRegion.Add(newRegions, dtor.tok, dtor, "destructor", true, module);
+ IdRegion.Add(newRegions, dtor.tok, dtor, null, "destructor", true, module);
}
}
}
@@ -175,7 +175,7 @@ namespace DafnyLanguage
}
} else if (member is Field) {
var fld = (Field)member;
- IdRegion.Add(newRegions, fld.tok, fld, "field", true, module);
+ IdRegion.Add(newRegions, fld.tok, fld, null, "field", true, module);
}
}
}
@@ -194,7 +194,8 @@ namespace DafnyLanguage
ExprRegions(fe.E, regions, module);
}
if (fe.Field != null) {
- IdRegion.Add(regions, fe.tok, fe.Field, "field", false, module);
+ Microsoft.Dafny.Type showType = null; // TODO: if we had the instantiated type of this field, that would have been nice to use here (but the Resolver currently does not compute or store the instantiated type for a FrameExpression)
+ IdRegion.Add(regions, fe.tok, fe.Field, showType, "field", false, module);
}
}
@@ -206,7 +207,7 @@ namespace DafnyLanguage
IdRegion.Add(regions, e.tok, e.Var, false, module);
} else if (expr is FieldSelectExpr) {
var e = (FieldSelectExpr)expr;
- IdRegion.Add(regions, e.tok, e.Field, "field", false, module);
+ IdRegion.Add(regions, e.tok, e.Field, e.Type, "field", false, module);
} else if (expr is ComprehensionExpr) {
var e = (ComprehensionExpr)expr;
foreach (var bv in e.BoundVars) {
@@ -298,13 +299,13 @@ namespace DafnyLanguage
regions.Add(new IdRegion(tok, v, isDefinition, context));
}
}
- public static void Add(List<IdRegion> regions, Bpl.IToken tok, Field decl, string kind, bool isDefinition, ModuleDefinition context) {
+ public static void Add(List<IdRegion> regions, Bpl.IToken tok, Field decl, Microsoft.Dafny.Type showType, string kind, bool isDefinition, ModuleDefinition context) {
Contract.Requires(regions != null);
Contract.Requires(tok != null);
Contract.Requires(decl != null);
Contract.Requires(kind != null);
if (SurfaceSyntaxToken(tok)) {
- regions.Add(new IdRegion(tok, decl, kind, isDefinition, context));
+ regions.Add(new IdRegion(tok, decl, showType, kind, isDefinition, context));
}
}
@@ -325,13 +326,16 @@ namespace DafnyLanguage
HoverText = string.Format("({2}{3}) {0}: {1}", v.DisplayName, v.Type.TypeName(context), v.IsGhost ? "ghost " : "", kind);
Kind = !isDefinition ? OccurrenceKind.Use : VarDecl.HasWildcardName(v) ? OccurrenceKind.WildDefinition : OccurrenceKind.Definition;
}
- private IdRegion(Bpl.IToken tok, Field decl, string kind, bool isDefinition, ModuleDefinition context) {
+ private IdRegion(Bpl.IToken tok, Field decl, Microsoft.Dafny.Type showType, string kind, bool isDefinition, ModuleDefinition context) {
Contract.Requires(tok != null);
Contract.Requires(decl != null);
Contract.Requires(kind != null);
+ if (showType == null) {
+ showType = decl.Type;
+ }
Start = tok.pos;
Length = decl.Name.Length;
- HoverText = string.Format("({2}{3}) {0}: {1}", decl.FullNameInContext(context), decl.Type.TypeName(context), decl.IsGhost ? "ghost " : "", kind);
+ HoverText = string.Format("({2}{3}) {0}: {1}", decl.FullNameInContext(context), showType.TypeName(context), decl.IsGhost ? "ghost " : "", kind);
Kind = !isDefinition ? OccurrenceKind.Use : OccurrenceKind.Definition;
}
}
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs b/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs
index ec1514ae..2f295429 100644
--- a/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs
+++ b/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs
@@ -255,6 +255,7 @@ namespace DafnyLanguage
case "in":
case "int":
case "invariant":
+ case "iterator":
case "label":
case "match":
case "method":
@@ -285,6 +286,8 @@ namespace DafnyLanguage
case "type":
case "var":
case "while":
+ case "yield":
+ case "yields":
#endregion
break;
default:
diff --git a/Util/latex/dafny.sty b/Util/latex/dafny.sty
index d60488d1..879b90cb 100644
--- a/Util/latex/dafny.sty
+++ b/Util/latex/dafny.sty
@@ -5,15 +5,17 @@
\usepackage{listings}
\lstdefinelanguage{dafny}{
- morekeywords={class,datatype,codatatype,type,bool,nat,int,object,set,multiset,seq,array,array2,array3,map,%
+ morekeywords={class,datatype,codatatype,type,iterator,
+ bool,nat,int,object,set,multiset,seq,array,array2,array3,map,
function,predicate,copredicate,
ghost,var,static,refines,
- method,constructor,returns,module,import,default,opened,as,in,
+ method,constructor,returns,yields,module,import,default,opened,as,in,
requires,modifies,ensures,reads,decreases,free,
% expressions
match,case,false,true,null,old,fresh,choose,this,
% statements
- assert,assume,print,new,if,then,else,while,invariant,break,label,return,parallel,where,calc
+ assert,assume,print,new,if,then,else,while,invariant,break,label,return,yield,
+ parallel,where,calc
},
literate=%
{:}{$\colon$}1
diff --git a/Util/vim/syntax/dafny.vim b/Util/vim/syntax/dafny.vim
index cc1c9d79..45afbcf0 100644
--- a/Util/vim/syntax/dafny.vim
+++ b/Util/vim/syntax/dafny.vim
@@ -6,11 +6,12 @@
syntax clear
syntax case match
syntax keyword dafnyFunction function predicate copredicate method constructor
-syntax keyword dafnyTypeDef class datatype codatatype type module import opened as default
+syntax keyword dafnyTypeDef class datatype codatatype type iterator
+syntax keyword module import opened as default
syntax keyword dafnyConditional if then else match case
syntax keyword dafnyRepeat while parallel
-syntax keyword dafnyStatement assume assert return new print break label where calc
-syntax keyword dafnyKeyword var ghost returns null static this refines
+syntax keyword dafnyStatement assume assert return yield new print break label where calc
+syntax keyword dafnyKeyword var ghost returns yields null static this refines
syntax keyword dafnyType bool nat int seq set multiset object array array2 array3 map
syntax keyword dafnyLogic requires ensures modifies reads decreases invariant
syntax keyword dafnyOperator forall exists old fresh choose