summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Dan Rosén <danr@chalmers.se>2014-08-11 14:57:27 -0700
committerGravatar Dan Rosén <danr@chalmers.se>2014-08-11 14:57:27 -0700
commit4cbe4583b329a39dee2b4b456758cafbe7e2fa79 (patch)
tree6bb2377f06036fd41d939d168365d4e47cc7a327
parentc377658acba5472b6d0c1e1452ce4c4c8f1fc28e (diff)
Add higher-order-functions and some other goodies
* The reads clause now needs to be self framing. * The requires clause now needs to be framed by the reads clause. * There are one-shot lambdas, with a single arrow, but they will probably be removed. * There is a {:heapQuantifier} attribute to quantifiers, but they will probably be removed. * Add smart handling of type variables * Add < and > for datatype & type parameter
-rw-r--r--Binaries/DafnyPrelude.bpl11
-rw-r--r--Source/Dafny/Cloner.cs16
-rw-r--r--Source/Dafny/Compiler.cs45
-rw-r--r--Source/Dafny/Dafny.atg460
-rw-r--r--Source/Dafny/DafnyAst.cs268
-rw-r--r--Source/Dafny/Parser.cs2047
-rw-r--r--Source/Dafny/Printer.cs39
-rw-r--r--Source/Dafny/RefinementTransformer.cs4
-rw-r--r--Source/Dafny/Resolver.cs402
-rw-r--r--Source/Dafny/Rewriter.cs18
-rw-r--r--Source/Dafny/Scanner.cs376
-rw-r--r--Source/Dafny/Translator.cs1528
-rw-r--r--Source/Dafny/Util.cs54
-rw-r--r--Source/DafnyExtension/IdentifierTagger.cs9
-rw-r--r--Test/VSI-Benchmarks/b6.dfy48
-rw-r--r--Test/dafny0/Definedness.dfy8
-rw-r--r--Test/dafny0/Modules0.dfy8
-rw-r--r--Test/dafny0/Reads.dfy57
-rw-r--r--Test/dafny0/Reads.dfy.expect26
-rw-r--r--Test/dafny0/SmallTests.dfy2
-rw-r--r--Test/dafny0/Termination.dfy6
-rw-r--r--Test/dafny1/PriorityQueue.dfy60
-rw-r--r--Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy2
-rw-r--r--Test/demo/tmap.dfy31
-rw-r--r--Test/hofs/Apply.dfy29
-rw-r--r--Test/hofs/Apply.dfy.expect7
-rw-r--r--Test/hofs/Classes.dfy50
-rw-r--r--Test/hofs/Classes.dfy.expect10
-rw-r--r--Test/hofs/Consequence.dfy9
-rw-r--r--Test/hofs/Consequence.dfy.expect2
-rw-r--r--Test/hofs/Examples.dfy59
-rw-r--r--Test/hofs/Examples.dfy.expect2
-rw-r--r--Test/hofs/Field.dfy23
-rw-r--r--Test/hofs/Field.dfy.expect14
-rw-r--r--Test/hofs/FnRef.dfy70
-rw-r--r--Test/hofs/FnRef.dfy.expect27
-rw-r--r--Test/hofs/Frame.dfy128
-rw-r--r--Test/hofs/Frame.dfy.expect38
-rw-r--r--Test/hofs/Lambda.dfy60
-rw-r--r--Test/hofs/Lambda.dfy.expect14
-rw-r--r--Test/hofs/LambdaParsefail.dfy33
-rw-r--r--Test/hofs/LambdaParsefail.dfy.expect5
-rw-r--r--Test/hofs/LambdaParsefail2.dfy8
-rw-r--r--Test/hofs/LambdaParsefail2.dfy.expect2
-rw-r--r--Test/hofs/Map.dfy117
-rw-r--r--Test/hofs/MutableField.dfy15
-rw-r--r--Test/hofs/MutableField.dfy.expect2
-rw-r--r--Test/hofs/Naked.dfy51
-rw-r--r--Test/hofs/Naked.dfy.expect50
-rw-r--r--Test/hofs/OneShot.dfy25
-rw-r--r--Test/hofs/OneShot.dfy.expect20
-rw-r--r--Test/hofs/Quant.dfy132
-rw-r--r--Test/hofs/ReadsReads.dfy59
-rw-r--r--Test/hofs/ReadsReads.dfy.expect18
-rw-r--r--Test/hofs/Renaming.dfy25
-rw-r--r--Test/hofs/Renaming.dfy.expect2
-rw-r--r--Test/hofs/ResolveError.dfy51
-rw-r--r--Test/hofs/ResolveError.dfy.expect14
-rw-r--r--Test/hofs/Simple.dfy90
-rw-r--r--Test/hofs/Simple.dfy.expect32
-rw-r--r--Test/hofs/TreeMap.dfy215
-rw-r--r--Test/hofs/TreeMapSimple.dfy49
-rw-r--r--Test/hofs/TreeMapSimple.dfy.expect2
-rw-r--r--Test/hofs/Twice.dfy38
-rw-r--r--Test/hofs/Twice.dfy.expect11
-rw-r--r--Test/hofs/Types.dfy20
-rw-r--r--Test/hofs/Types.dfy.expect4
-rw-r--r--Test/hofs/WhileLoop.dfy50
-rw-r--r--Test/hofs/WhileLoop.dfy.expect2
-rw-r--r--Test/scratch/Reads.dfy26
70 files changed, 5379 insertions, 1856 deletions
diff --git a/Binaries/DafnyPrelude.bpl b/Binaries/DafnyPrelude.bpl
index 7b52f69f..3d5bf111 100644
--- a/Binaries/DafnyPrelude.bpl
+++ b/Binaries/DafnyPrelude.bpl
@@ -243,6 +243,10 @@ axiom (forall a: ClassName, b: ClassName :: { TypeTuple(a,b) }
TypeTupleCar(TypeTuple(a,b)) == a &&
TypeTupleCdr(TypeTuple(a,b)) == b);
+// -- Function handles -------------------------------------------
+
+type HandleType;
+
// ---------------------------------------------------------------
// -- Datatypes --------------------------------------------------
// ---------------------------------------------------------------
@@ -257,6 +261,9 @@ type DtCtorId;
function DatatypeCtorId(DatatypeType): DtCtorId;
function DtRank(DatatypeType): int;
+function BoxRank(Box): int;
+
+axiom (forall d: DatatypeType :: {BoxRank($Box(d))} BoxRank($Box(d)) == DtRank(d));
// ---------------------------------------------------------------
// -- Axiom contexts ---------------------------------------------
@@ -274,6 +281,10 @@ type LayerType;
const $LZ: LayerType;
function $LS(LayerType): LayerType;
+function AtLayer<A>([LayerType]A, LayerType): A;
+axiom (forall<A> f : [LayerType]A, ly : LayerType :: { AtLayer(f,ly) } AtLayer(f,ly) == f[ly]);
+axiom (forall<A> f : [LayerType]A, ly : LayerType :: { AtLayer(f,$LS(ly)) } AtLayer(f,$LS(ly)) == AtLayer(f,ly));
+
// ---------------------------------------------------------------
// -- Fields -----------------------------------------------------
// ---------------------------------------------------------------
diff --git a/Source/Dafny/Cloner.cs b/Source/Dafny/Cloner.cs
index bb644825..f3a97f92 100644
--- a/Source/Dafny/Cloner.cs
+++ b/Source/Dafny/Cloner.cs
@@ -140,6 +140,9 @@ namespace Microsoft.Dafny
} else if (t is MapType) {
var tt = (MapType)t;
return new MapType(CloneType(tt.Domain), CloneType(tt.Range));
+ } else if (t is ArrowType) {
+ var tt = (ArrowType)t;
+ return new ArrowType(tt.Args.ConvertAll(CloneType), CloneType(tt.Result));
} else if (t is UserDefinedType) {
var tt = (UserDefinedType)t;
return new UserDefinedType(Tok(tt.tok), tt.Name, tt.TypeArgs.ConvertAll(CloneType), tt.Path.ConvertAll(Tok));
@@ -251,9 +254,9 @@ namespace Microsoft.Dafny
var e = (ExprDotName)expr;
return new ExprDotName(Tok(e.tok), CloneExpr(e.Obj), e.SuffixName);
- } else if (expr is FieldSelectExpr) {
- var e = (FieldSelectExpr)expr;
- return new FieldSelectExpr(Tok(e.tok), CloneExpr(e.Obj), e.FieldName);
+ } else if (expr is MemberSelectExpr) {
+ var e = (MemberSelectExpr)expr;
+ return new MemberSelectExpr(Tok(e.tok), CloneExpr(e.Obj), e.MemberName);
} else if (expr is SeqSelectExpr) {
var e = (SeqSelectExpr)expr;
@@ -271,6 +274,10 @@ namespace Microsoft.Dafny
var e = (FunctionCallExpr)expr;
return new FunctionCallExpr(Tok(e.tok), e.Name, CloneExpr(e.Receiver), e.OpenParen == null ? null : Tok(e.OpenParen), e.Args.ConvertAll(CloneExpr));
+ } else if (expr is ApplyExpr) {
+ var e = (ApplyExpr)expr;
+ return new ApplyExpr(Tok(e.tok), Tok(e.OpenParen), CloneExpr(e.Receiver), e.Args.ConvertAll(CloneExpr));
+
} else if (expr is OldExpr) {
var e = (OldExpr)expr;
return new OldExpr(Tok(e.tok), CloneExpr(e.E));
@@ -324,6 +331,9 @@ namespace Microsoft.Dafny
}
} else if (e is MapComprehension) {
return new MapComprehension(tk, bvs, range, term);
+ } else if (e is LambdaExpr) {
+ var l = (LambdaExpr)e;
+ return new LambdaExpr(tk, l.OneShot, bvs, range, l.Reads.ConvertAll(CloneFrameExpr), term);
} else {
Contract.Assert(e is SetComprehension);
return new SetComprehension(tk, bvs, range, term);
diff --git a/Source/Dafny/Compiler.cs b/Source/Dafny/Compiler.cs
index c665026c..97a53a66 100644
--- a/Source/Dafny/Compiler.cs
+++ b/Source/Dafny/Compiler.cs
@@ -936,14 +936,7 @@ namespace Microsoft.Dafny {
string/*!*/ TypeNames(List<Type/*!*/>/*!*/ types) {
Contract.Requires(cce.NonNullElements(types));
Contract.Ensures(Contract.Result<string>() != null);
-
- string s = "";
- string sep = "";
- foreach (Type t in types) {
- s += sep + TypeName(t);
- sep = ",";
- }
- return s;
+ return Util.Comma(types, TypeName);
}
string/*!*/ TypeParameters(List<TypeParameter/*!*/>/*!*/ targs) {
@@ -1390,8 +1383,8 @@ namespace Microsoft.Dafny {
// Compute L
int L;
string tupleTypeArgs;
- if (s0.Lhs is FieldSelectExpr) {
- var lhs = (FieldSelectExpr)s0.Lhs;
+ if (s0.Lhs is MemberSelectExpr) {
+ var lhs = (MemberSelectExpr)s0.Lhs;
L = 2;
tupleTypeArgs = TypeName(lhs.Obj.Type);
} else if (s0.Lhs is SeqSelectExpr) {
@@ -1474,8 +1467,8 @@ namespace Microsoft.Dafny {
SpillLetVariableDecls(rhs, indFinal);
Indent(indFinal);
wr.Write("{0}.Add(new System.Tuple<{1}>(", ingredients, tupleTypeArgs);
- if (s0.Lhs is FieldSelectExpr) {
- var lhs = (FieldSelectExpr)s0.Lhs;
+ if (s0.Lhs is MemberSelectExpr) {
+ var lhs = (MemberSelectExpr)s0.Lhs;
TrExpr(lhs.Obj);
} else if (s0.Lhs is SeqSelectExpr) {
var lhs = (SeqSelectExpr)s0.Lhs;
@@ -1511,9 +1504,9 @@ namespace Microsoft.Dafny {
Indent(indent);
wr.WriteLine("foreach (var {0} in {1}) {{", tup, ingredients);
Indent(indent + IndentAmount);
- if (s0.Lhs is FieldSelectExpr) {
- var lhs = (FieldSelectExpr)s0.Lhs;
- wr.WriteLine("{0}.Item1.@{1} = {0}.Item2;", tup, lhs.FieldName);
+ if (s0.Lhs is MemberSelectExpr) {
+ var lhs = (MemberSelectExpr)s0.Lhs;
+ wr.WriteLine("{0}.Item1.@{1} = {0}.Item2;", tup, lhs.MemberName);
} else if (s0.Lhs is SeqSelectExpr) {
var lhs = (SeqSelectExpr)s0.Lhs;
wr.WriteLine("{0}.Item1[{0}.Item2] = {0}.Item3;", tup);
@@ -1588,15 +1581,15 @@ namespace Microsoft.Dafny {
if (lhs is IdentifierExpr) {
var ll = (IdentifierExpr)lhs;
return "@" + ll.Var.CompileName;
- } else if (lhs is FieldSelectExpr) {
- var ll = (FieldSelectExpr)lhs;
+ } else if (lhs is MemberSelectExpr) {
+ var ll = (MemberSelectExpr)lhs;
string obj = "_obj" + tmpVarCount;
tmpVarCount++;
Indent(indent);
wr.Write("var {0} = ", obj);
TrExpr(ll.Obj);
wr.WriteLine(";");
- return string.Format("{0}.@{1}", obj, ll.Field.CompileName);
+ return string.Format("{0}.@{1}", obj, ll.Member.CompileName);
} else if (lhs is SeqSelectExpr) {
var ll = (SeqSelectExpr)lhs;
string arr = "_arr" + tmpVarCount;
@@ -2028,9 +2021,9 @@ namespace Microsoft.Dafny {
wr.Write("{0}.FromElements", TypeName(e.Type));
TrExprPairList(e.Elements);
- } else if (expr is FieldSelectExpr) {
- FieldSelectExpr e = (FieldSelectExpr)expr;
- SpecialField sf = e.Field as SpecialField;
+ } else if (expr is MemberSelectExpr) {
+ MemberSelectExpr e = (MemberSelectExpr)expr;
+ SpecialField sf = e.Member as SpecialField;
if (sf != null) {
wr.Write(sf.PreString);
TrParenExpr(e.Obj);
@@ -2038,7 +2031,7 @@ namespace Microsoft.Dafny {
wr.Write(sf.PostString);
} else {
TrParenExpr(e.Obj);
- wr.Write(".@{0}", e.Field.CompileName);
+ wr.Write(".@{0}", e.Member.CompileName);
}
} else if (expr is SeqSelectExpr) {
@@ -2650,6 +2643,14 @@ namespace Microsoft.Dafny {
wr.Write("return Dafny.Map<{0},{1}>.FromCollection(_coll); ", domtypeName, rantypeName);
wr.Write("})()");
+ } else if (expr is LambdaExpr) {
+ LambdaExpr e = (LambdaExpr)expr;
+ wr.Write("((");
+ wr.Write(Util.Comma(e.BoundVars, bv => bv.CompileName));
+ wr.Write(") => ");
+ TrExpr(e.Body);
+ wr.Write(")");
+
} else if (expr is StmtExpr) {
var e = (StmtExpr)expr;
TrExpr(e.E);
diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg
index c870dc81..dffa2df8 100644
--- a/Source/Dafny/Dafny.atg
+++ b/Source/Dafny/Dafny.atg
@@ -120,6 +120,13 @@ bool IsParenStar() {
return la.kind == _openparen && x.kind == _star;
}
+bool IsLambda(bool allowLambda)
+{
+ return allowLambda &&
+ (la.kind == _darrow || la.kind == _arrow
+ || la.kind == _reads || la.kind == _requires);
+}
+
bool IsIdentParen() {
Token x = scanner.Peek();
return la.kind == _ident && x.kind == _openparen;
@@ -127,7 +134,7 @@ bool IsIdentParen() {
bool SemiFollowsCall(bool allowSemi, Expression e) {
return allowSemi && la.kind == _semi &&
- (e is FunctionCallExpr ||
+ (e is FunctionCallExpr || e is ApplyExpr ||
(e is IdentifierSequence && ((IdentifierSequence)e).OpenParen != null));
}
@@ -138,6 +145,7 @@ bool CloseOptionalParen(bool usesOptionalParen) {
bool CloseOptionalBrace(bool usesOptionalBrace) {
return usesOptionalBrace && la.kind == _rbrace;
}
+
/*--------------------------------------------------------------------------*/
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
@@ -177,6 +185,10 @@ TOKENS
string = quote {nonquote} quote.
colon = ':'.
semi = ';'.
+ darrow = "=>".
+ arrow = "->".
+ reads = "reads".
+ requires = "requires".
lbrace = '{'.
rbrace = '}'.
openparen = '('.
@@ -679,10 +691,10 @@ MethodSpec<.List<MaybeFreeExpression/*!*/>/*!*/ req, List<FrameExpression/*!*/>/
] SYNC ";"
| [ "free" (. isFree = true; .)
]
- ( "requires" Expression<out e, false> SYNC ";" (. req.Add(new MaybeFreeExpression(e, isFree)); .)
+ ( "requires" Expression<out e, false, true> SYNC ";" (. req.Add(new MaybeFreeExpression(e, isFree)); .)
| "ensures"
{ IF(IsAttribute()) Attribute<ref ensAttrs> }
- Expression<out e, false> SYNC ";" (. ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); .)
+ Expression<out e, false, true> SYNC ";" (. ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs)); .)
)
| "decreases" { IF(IsAttribute()) Attribute<ref decAttrs> } DecreasesList<decreases, true> SYNC ";"
)
@@ -708,14 +720,14 @@ IteratorSpec<.List<FrameExpression/*!*/>/*!*/ reads, List<FrameExpression/*!*/>/
]
[ "yield" (. isYield = true; .)
]
- ( "requires" Expression<out e, false> SYNC ";" (. if (isYield) {
+ ( "requires" Expression<out e, false, true> 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, false> SYNC ";" (. if (isYield) {
+ Expression<out e, false, true> SYNC ";" (. if (isYield) {
yieldEns.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
} else {
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
@@ -746,14 +758,15 @@ FormalsOptionalIds<.List<Formal/*!*/>/*!*/ formals.>
")"
.
/*------------------------------------------------------------------------*/
-Type<out Type/*!*/ ty>
+Type<out Type ty>
= (. Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok; .)
TypeAndToken<out tok, out ty>
.
-TypeAndToken<out IToken/*!*/ tok, out Type/*!*/ ty>
+
+TypeAndToken<out IToken tok, out Type ty>
= (. Contract.Ensures(Contract.ValueAtReturn(out tok)!=null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
tok = Token.NoToken; ty = new BoolType(); /*keep compiler happy*/
- List<Type> gt;
+ List<Type> gt = null;
.)
( "bool" (. tok = t; .)
| "nat" (. tok = t; ty = new NatType(); .)
@@ -801,8 +814,17 @@ TypeAndToken<out IToken/*!*/ tok, out Type/*!*/ ty>
ty = new UserDefinedType(tok, BuiltIns.TupleTypeName(dims), gt, new List<IToken>());
}
.)
- | ReferenceType<out tok, out ty>
+ | ReferenceType<out tok, out ty>
)
+ [ (. Type t2; .)
+ "->" Type<out t2>
+ (. if (gt == null) {
+ gt = new List<Type>{ ty };
+ }
+ ty = new ArrowType(gt, t2);
+ .)
+ ]
+
.
ReferenceType<out IToken/*!*/ tok, out Type/*!*/ ty>
= (. Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
@@ -933,12 +955,12 @@ FunctionSpec<.List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ r
Expression/*!*/ e; FrameExpression/*!*/ fe; .)
(
SYNC
- "requires" Expression<out e, false> SYNC ";" (. reqs.Add(e); .)
+ "requires" Expression<out e, false, true> SYNC ";" (. reqs.Add(e); .)
| "reads" [ PossiblyWildFrameExpression<out fe> (. reads.Add(fe); .)
{ "," PossiblyWildFrameExpression<out fe> (. reads.Add(fe); .)
}
] SYNC ";"
- | "ensures" Expression<out e, false> SYNC ";" (. ens.Add(e); .)
+ | "ensures" Expression<out e, false, true> SYNC ";" (. ens.Add(e); .)
| "decreases" (. if (decreases == null) {
SemErr(t, "'decreases' clauses are meaningless for copredicates, so they are not allowed");
decreases = new List<Expression/*!*/>();
@@ -947,6 +969,22 @@ FunctionSpec<.List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ r
DecreasesList<decreases, false> SYNC ";"
)
.
+
+LambdaSpec<.out Expression req, List<FrameExpression> reads.>
+= (. Contract.Requires(reads != null);
+ Expression e; req = null; FrameExpression fe; .)
+ { ( "requires" Expression<out e, false, false>
+ (. if (req == null) {
+ req = e;
+ } else {
+ req = new BinaryExpr(req.tok, BinaryExpr.Opcode.And, req, e);
+ }
+ .)
+ | "reads" PossiblyWildFrameExpression<out fe> (. reads.Add(fe); .)
+ )
+ }
+ .
+
PossiblyWildExpression<out Expression/*!*/ e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e)!=null);
e = dummyExpr; .)
@@ -954,7 +992,7 @@ PossiblyWildExpression<out Expression/*!*/ e>
* Use of this feature is sound only with respect to partial correctness.
*/
( "*" (. e = new WildcardExpr(t); .)
- | Expression<out e, false>
+ | Expression<out e, false, false>
)
.
PossiblyWildFrameExpression<out FrameExpression/*!*/ fe>
@@ -976,7 +1014,7 @@ FrameExpression<out FrameExpression/*!*/ fe>
string fieldName = null; IToken feTok = null;
fe = null;
.)
- (( Expression<out e, false> (. feTok = e.tok; .)
+ (( Expression<out e, false, false> (. feTok = e.tok; .)
[ "`" Ident<out id> (. fieldName = id.val; feTok = id; .)
]
(. fe = new FrameExpression(feTok, e, fieldName); .)
@@ -989,7 +1027,7 @@ FrameExpression<out FrameExpression/*!*/ fe>
FunctionBody<out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); e = dummyExpr; .)
"{" (. bodyStart = t; .)
- Expression<out e, true>
+ Expression<out e, true, true>
"}" (. bodyEnd = t; .)
.
/*------------------------------------------------------------------------*/
@@ -1054,8 +1092,8 @@ SkeletonStmt<out Statement s>
{"," Ident<out tok> (. names.Add(tok); .)
}
":="
- Expression<out e, false> (. exprs.Add(e); .)
- {"," Expression<out e, false> (. exprs.Add(e); .)
+ Expression<out e, false, true> (. exprs.Add(e); .)
+ {"," Expression<out e, false, true> (. exprs.Add(e); .)
}
(. if (exprs.Count != names.Count) {
SemErr(whereTok, exprs.Count < names.Count ? "not enough expressions" : "too many expressions");
@@ -1111,7 +1149,7 @@ UpdateStmt<out Statement/*!*/ s>
| ":|" (. x = t; .)
[ "assume" (. suchThatAssume = t; .)
]
- Expression<out suchThat, false>
+ Expression<out suchThat, false, true>
)
";" (. endTok = t; .)
| ":" (. SemErr(t, "invalid statement (did you forget the 'label' keyword?)"); .)
@@ -1158,7 +1196,7 @@ Rhs<out AssignmentRhs r, Expression receiverForInitCall>
}
.)
| "*" (. r = new HavocRhs(t); .)
- | Expression<out e, false> (. r = new ExprRhs(e); .)
+ | Expression<out e, false, true> (. r = new ExprRhs(e); .)
)
{ Attribute<ref attrs> } (. r.Attributes = attrs; .)
.
@@ -1191,7 +1229,7 @@ VarDeclStatement<.out Statement/*!*/ s.>
| ":|" (. assignTok = t; .)
[ "assume" (. suchThatAssume = t; .)
]
- Expression<out suchThat, false>
+ Expression<out suchThat, false, true>
]
";" (. endTok = t; .)
(. ConcreteUpdateStatement update;
@@ -1255,7 +1293,7 @@ AlternativeBlock<.out List<GuardedAlternative> alternatives, out IToken endTok.>
.)
"{"
{ "case" (. x = t; .)
- Expression<out e, true>
+ Expression<out e, true, false> // NB: don't allow lambda here
"=>"
(. body = new List<Statement>(); .)
{ Stmt<body> }
@@ -1334,7 +1372,7 @@ Invariant<out MaybeFreeExpression/*!*/ invariant>
["free" (. isFree = true; .)
]
"invariant" { IF(IsAttribute()) Attribute<ref attrs> }
- Expression<out e, false> (. invariant = new MaybeFreeExpression(e, isFree, attrs); .)
+ Expression<out e, false, true> (. invariant = new MaybeFreeExpression(e, isFree, attrs); .)
.
DecreasesList<.List<Expression/*!*/> decreases, bool allowWildcard.>
= (. Expression/*!*/ e; .)
@@ -1356,7 +1394,7 @@ Guard<out Expression e> /* null represents demonic-choice */
= (. Expression/*!*/ ee; e = null; .)
( "*" (. e = null; .)
| IF(IsParenStar()) "(" "*" ")" (. e = null; .)
- | Expression<out ee, true> (. e = ee; .)
+ | Expression<out ee, true, true> (. e = ee; .)
)
.
MatchStmt<out Statement/*!*/ s>
@@ -1366,7 +1404,7 @@ MatchStmt<out Statement/*!*/ s>
bool usesOptionalBrace = false;
.)
"match" (. x = t; .)
- Expression<out e, true>
+ Expression<out e, true, true>
[ "{" (. usesOptionalBrace = true; .)
]
{ CaseStatement<out c> (. cases.Add(c); .)
@@ -1403,7 +1441,7 @@ AssertStmt<out Statement/*!*/ s>
.)
"assert" (. x = t; .)
{ IF(IsAttribute()) Attribute<ref attrs> }
- ( Expression<out e, false>
+ ( Expression<out e, false, true>
| "..." (. dotdotdot = t; .)
)
";"
@@ -1421,7 +1459,7 @@ AssumeStmt<out Statement/*!*/ s>
.)
"assume" (. x = t; .)
{ IF(IsAttribute()) Attribute<ref attrs> }
- ( Expression<out e, false>
+ ( Expression<out e, false, true>
| "..." (. dotdotdot = t; .)
)
";"
@@ -1479,7 +1517,7 @@ ForallStmt<out Statement/*!*/ s>
{ (. isFree = false; .)
[ "free" (. isFree = true; .)
]
- "ensures" Expression<out e, false> (. ens.Add(new MaybeFreeExpression(e, isFree)); .)
+ "ensures" Expression<out e, false, true> (. ens.Add(new MaybeFreeExpression(e, isFree)); .)
";" (. tok = t; .)
}
[ BlockStmt<out block, out bodyStart, out bodyEnd>
@@ -1546,7 +1584,7 @@ CalcStmt<out Statement/*!*/ s>
.)
]
"{"
- { Expression<out e, false> (. lines.Add(e); stepOp = calcOp; danglingOperator = null; .)
+ { Expression<out e, false, true> (. lines.Add(e); stepOp = calcOp; danglingOperator = null; .)
";"
[ CalcOp<out opTok, out op> (. maybeOp = resOp.ResultOp(op);
if (maybeOp == null) {
@@ -1580,7 +1618,7 @@ CalcOp<out IToken x, out CalcStmt.CalcOp/*!*/ op>
x = null;
.)
( "==" (. x = t; binOp = BinaryExpr.Opcode.Eq; .)
- [ "#" "[" Expression<out k, true> "]" ]
+ [ "#" "[" Expression<out k, true, true> "]" ]
| "<" (. x = t; binOp = BinaryExpr.Opcode.Lt; .)
| ">" (. x = t; binOp = BinaryExpr.Opcode.Gt; .)
| "<=" (. x = t; binOp = BinaryExpr.Opcode.Le; .)
@@ -1621,13 +1659,16 @@ Hint<out BlockStmt s>
* to be parsed is allowed to have the form S;E where S is a call to a lemma.
* "allowSemi" should be passed in as "false" whenever the expression to
* be parsed sits in a context that itself is terminated by a semi-colon.
+ *
+ * The "allowLambda" is there to be able to parse "case x => e".
+ * Directly after the case keyword, you cannot do identifier-sequence-lambdas.
*/
-Expression<out Expression e, bool allowSemi>
+Expression<out Expression e, bool allowSemi, bool allowLambda>
= (. Expression e0; IToken endTok; .)
- EquivExpression<out e, allowSemi>
+ EquivExpression<out e, allowSemi, allowLambda>
[ IF(SemiFollowsCall(allowSemi, e))
";" (. endTok = t; .)
- Expression<out e0, allowSemi>
+ Expression<out e0, allowSemi, allowLambda>
(. e = new StmtExpr(e.tok,
new UpdateStmt(e.tok, endTok, new List<Expression>(), new List<AssignmentRhs>() { new ExprRhs(e, null) }),
e0);
@@ -1635,56 +1676,56 @@ Expression<out Expression e, bool allowSemi>
]
.
/*------------------------------------------------------------------------*/
-EquivExpression<out Expression e0, bool allowSemi>
+EquivExpression<out Expression e0, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; .)
- ImpliesExpliesExpression<out e0, allowSemi>
- { EquivOp (. x = t; .)
- ImpliesExpliesExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Iff, e0, e1); .)
+ ImpliesExpliesExpression<out e0, allowSemi, allowLambda>
+ { EquivOp (. x = t; .)
+ ImpliesExpliesExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Iff, e0, e1); .)
}
.
EquivOp = "<==>" | '\u21d4'.
/*------------------------------------------------------------------------*/
-ImpliesExpliesExpression<out Expression e0, bool allowSemi>
+ImpliesExpliesExpression<out Expression e0, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; .)
- LogicalExpression<out e0, allowSemi>
- [ ImpliesOp (. x = t; .)
- ImpliesExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); .)
- | ExpliesOp (. x = t; .)
- LogicalExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e0, e1); .)
- { ExpliesOp (. x = t; .)
- LogicalExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e0, e1); .)
+ LogicalExpression<out e0, allowSemi, allowLambda>
+ [ ImpliesOp (. x = t; .)
+ ImpliesExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); .)
+ | ExpliesOp (. x = t; .)
+ LogicalExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e0, e1); .)
+ { ExpliesOp (. x = t; .)
+ LogicalExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e0, e1); .)
}
]
.
-ImpliesExpression<out Expression e0, bool allowSemi>
+ImpliesExpression<out Expression e0, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; .)
- LogicalExpression<out e0, allowSemi>
- [ ImpliesOp (. x = t; .)
- ImpliesExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); .)
+ LogicalExpression<out e0, allowSemi, allowLambda>
+ [ ImpliesOp (. x = t; .)
+ ImpliesExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); .)
]
.
ImpliesOp = "==>" | '\u21d2'.
ExpliesOp = "<==" | '\u21d0'.
/*------------------------------------------------------------------------*/
-LogicalExpression<out Expression e0, bool allowSemi>
+LogicalExpression<out Expression e0, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; .)
- RelationalExpression<out e0, allowSemi>
- [ AndOp (. x = t; .)
- RelationalExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
- { AndOp (. x = t; .)
- RelationalExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
+ RelationalExpression<out e0, allowSemi, allowLambda>
+ [ AndOp (. x = t; .)
+ RelationalExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
+ { AndOp (. x = t; .)
+ RelationalExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); .)
}
- | OrOp (. x = t; .)
- RelationalExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
- { OrOp (. x = t; .)
- RelationalExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
+ | OrOp (. x = t; .)
+ RelationalExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
+ { OrOp (. x = t; .)
+ RelationalExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); .)
}
]
.
AndOp = "&&" | '\u2227'.
OrOp = "||" | '\u2228'.
/*------------------------------------------------------------------------*/
-RelationalExpression<out Expression e, bool allowSemi>
+RelationalExpression<out Expression e, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
IToken x, firstOpTok = null; Expression e0, e1, acc = null; BinaryExpr.Opcode op;
List<Expression> chain = null;
@@ -1698,9 +1739,11 @@ RelationalExpression<out Expression e, bool allowSemi>
// 4 ("disjoint") indicates chain of disjoint set operators
bool hasSeenNeq = false;
.)
- Term<out e0, allowSemi> (. e = e0; .)
+ Term<out e0, allowSemi, allowLambda>
+ (. e = e0; .)
[ RelOp<out x, out op, out k> (. firstOpTok = x; .)
- Term<out e1, allowSemi> (. if (k == null) {
+ Term<out e1, allowSemi, allowLambda>
+ (. if (k == null) {
e = new BinaryExpr(x, op, e0, e1);
if (op == BinaryExpr.Opcode.Disjoint)
acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, e0, e1); // accumulate first two operands.
@@ -1759,7 +1802,8 @@ RelationalExpression<out Expression e, bool allowSemi>
kind = 3; break;
}
.)
- Term<out e1, allowSemi> (. ops.Add(op); prefixLimits.Add(k); chain.Add(e1);
+ Term<out e1, allowSemi, allowLambda>
+ (. ops.Add(op); prefixLimits.Add(k); chain.Add(e1);
if (k != null) {
Contract.Assert(op == BinaryExpr.Opcode.Eq || op == BinaryExpr.Opcode.Neq);
e = new TernaryExpr(x, op == BinaryExpr.Opcode.Eq ? TernaryExpr.Opcode.PrefixEqOp : TernaryExpr.Opcode.PrefixNeqOp, k, e0, e1);
@@ -1784,13 +1828,13 @@ RelOp<out IToken/*!*/ x, out BinaryExpr.Opcode op, out Expression k>
k = null;
.)
( "==" (. x = t; op = BinaryExpr.Opcode.Eq; .)
- [ "#" "[" Expression<out k, true> "]" ]
+ [ "#" "[" Expression<out k, true, true> "]" ]
| "<" (. x = t; op = BinaryExpr.Opcode.Lt; .)
| ">" (. x = t; op = BinaryExpr.Opcode.Gt; .)
| "<=" (. x = t; op = BinaryExpr.Opcode.Le; .)
| ">=" (. x = t; op = BinaryExpr.Opcode.Ge; .)
| "!=" (. x = t; op = BinaryExpr.Opcode.Neq; .)
- [ "#" "[" Expression<out k, true> "]" ]
+ [ "#" "[" Expression<out k, true, true> "]" ]
| "in" (. x = t; op = BinaryExpr.Opcode.In; .)
| notIn (. x = t; op = BinaryExpr.Opcode.NotIn; .)
| /* The next operator is "!!", but we have to scan it as two "!", since the scanner is gready
@@ -1812,11 +1856,11 @@ RelOp<out IToken/*!*/ x, out BinaryExpr.Opcode op, out Expression k>
)
.
/*------------------------------------------------------------------------*/
-Term<out Expression e0, bool allowSemi>
+Term<out Expression e0, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op; .)
- Factor<out e0, allowSemi>
+ Factor<out e0, allowSemi, allowLambda>
{ AddOp<out x, out op>
- Factor<out e1, allowSemi> (. e0 = new BinaryExpr(x, op, e0, e1); .)
+ Factor<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, op, e0, e1); .)
}
.
AddOp<out IToken x, out BinaryExpr.Opcode op>
@@ -1826,11 +1870,11 @@ AddOp<out IToken x, out BinaryExpr.Opcode op>
)
.
/*------------------------------------------------------------------------*/
-Factor<out Expression e0, bool allowSemi>
+Factor<out Expression e0, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op; .)
- UnaryExpression<out e0, allowSemi>
+ UnaryExpression<out e0, allowSemi, allowLambda>
{ MulOp<out x, out op>
- UnaryExpression<out e1, allowSemi> (. e0 = new BinaryExpr(x, op, e0, e1); .)
+ UnaryExpression<out e1, allowSemi, allowLambda> (. e0 = new BinaryExpr(x, op, e0, e1); .)
}
.
MulOp<out IToken x, out BinaryExpr.Opcode op>
@@ -1841,15 +1885,18 @@ MulOp<out IToken x, out BinaryExpr.Opcode op>
)
.
/*------------------------------------------------------------------------*/
-UnaryExpression<out Expression e, bool allowSemi>
+UnaryExpression<out Expression e, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; e = dummyExpr; .)
( "-" (. x = t; .)
- UnaryExpression<out e, allowSemi> (. e = new NegationExpression(x, e); .)
+ UnaryExpression<out e, allowSemi, allowLambda>
+ (. e = new NegationExpression(x, e); .)
| NegOp (. x = t; .)
- UnaryExpression<out e, allowSemi> (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Not, e); .)
- | EndlessExpression<out e, allowSemi> /* these have no further suffix */
- | DottedIdentifiersAndFunction<out e>
+ UnaryExpression<out e, allowSemi, allowLambda>
+ (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Not, e); .)
+ | EndlessExpression<out e, allowSemi, allowLambda>
+ | DottedIdentifiersAndFunction<out e, allowSemi, allowLambda>
{ Suffix<ref e> }
+ ApplySuffix<ref e>
| DisplayExpr<out e>
{ Suffix<ref e> }
| MultiSetExpr<out e>
@@ -1860,16 +1907,17 @@ UnaryExpression<out Expression e, bool allowSemi>
| MapComprehensionExpr<x, out e, allowSemi>
| (. SemErr("map must be followed by literal in brackets or comprehension."); .)
)
- | ConstAtomExpression<out e>
+ | ConstAtomExpression<out e, allowSemi, allowLambda>
{ Suffix<ref e> }
)
.
Lhs<out Expression e>
= (. e = dummyExpr; // the assignment is to please the compiler, the dummy value to satisfy contracts in the event of a parse error
.)
- ( DottedIdentifiersAndFunction<out e>
+ ( DottedIdentifiersAndFunction<out e, false, false>
{ Suffix<ref e> }
- | ConstAtomExpression<out e>
+ ApplySuffix<ref e>
+ | ConstAtomExpression<out e, false, false>
Suffix<ref e>
{ Suffix<ref e> }
)
@@ -1879,7 +1927,7 @@ NegOp = "!" | '\u00ac'.
* an open paren (but could very well have a suffix that starts with a period or a square bracket).
* (The "Also..." part may change if expressions in Dafny could yield functions.)
*/
-ConstAtomExpression<out Expression e>
+ConstAtomExpression<out Expression e, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
IToken/*!*/ x; BigInteger n; Basetypes.BigDec d;
e = dummyExpr; Type toType = null;
@@ -1891,46 +1939,106 @@ ConstAtomExpression<out Expression e>
| Dec<out d> (. e = new LiteralExpr(t, d); .)
| "this" (. e = new ThisExpr(t); .)
| "fresh" (. x = t; .)
- "(" Expression<out e, true> ")" (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Fresh, e); .)
+ "(" Expression<out e, true, true> ")" (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Fresh, e); .)
| "old" (. x = t; .)
- "(" Expression<out e, true> ")" (. e = new OldExpr(x, e); .)
+ "(" Expression<out e, true, true> ")" (. e = new OldExpr(x, e); .)
| "|" (. x = t; .)
- Expression<out e, true> (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Cardinality, e); .)
+ Expression<out e, true, true> (. e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Cardinality, e); .)
"|"
| ( "int" (. x = t; toType = new IntType(); .)
| "real" (. x = t; toType = new RealType(); .)
)
- "(" Expression<out e, true> ")" (. e = new ConversionExpr(x, e, toType); .)
- | ParensExpression<out e>
+ "(" Expression<out e, true, true> ")" (. e = new ConversionExpr(x, e, toType); .)
+ | ParensExpression<out e, allowSemi, allowLambda>
+ )
+ .
+
+LambdaArrow<out bool oneShot>
+= (. oneShot = true; .)
+ ( "=>" (. oneShot = false; .)
+ | "->" (. oneShot = true; .)
)
.
-ParensExpression<out Expression e>
+
+ParensExpression<out Expression e, bool allowSemi, bool allowLambda>
= (. IToken x;
- List<Expression> args = null;
+ Expression ee;
+ e = null;
+ List<Expression> args = new List<Expression>();
+ List<Type> types = new List<Type>();
+ Type tt;
+ bool isLambda = false;
+ .)
+ "(" (. x = t; .)
+ [
+ OptTypedExpr<out ee, out tt, true> (. args.Add(ee); types.Add(tt); .)
+ { "," OptTypedExpr<out ee, out tt, true> (. args.Add(ee); types.Add(tt); .)
+ }
+ ]
+ ")"
+ [ IF(IsLambda(allowLambda))
+ (. Expression body = null;
+ Expression req = null;
+ bool oneShot;
+ var reads = new List<FrameExpression>();
+ x = t;
+ .)
+ LambdaSpec<out req, reads>
+ LambdaArrow<out oneShot>
+ Expression<out body, allowSemi, true>
+ (. List<BoundVar> bvs = new List<BoundVar>();
+ for (int i = 0; i < args.Count; i++) {
+ ee = args[i];
+ tt = types[i];
+ if (ee is IdentifierSequence) {
+ IdentifierSequence ise = (IdentifierSequence)ee;
+ List<IToken> idents = ise.Tokens;
+ Contract.Assert(idents != null);
+ Contract.Assert(idents.Count > 0);
+ IToken id = idents[0];
+ if (idents.Count != 1) {
+ SemErr(id, "Expected variable binding.");
+ }
+ if (ise.Arguments != null) {
+ SemErr(ise.OpenParen, "Expected variable binding.");
+ }
+ bvs.Add(new BoundVar(id, id.val, tt ?? new InferredTypeProxy()));
+ } else {
+ SemErr(ee.tok, "Expected variable binding.");
+ }
+ }
+ e = new LambdaExpr(x, oneShot, bvs, req, reads, body);
+ isLambda = true;
+ .)
+ ]
+ (. if (!isLambda) {
+ for (int i = 0; i < args.Count; i++) {
+ if (types[i] != null) {
+ SemErr(args[i].tok, "Type specification not allowed here, comma separator was expected.");
+ }
+ }
+ if (args.Count == 1) {
+ e = new ParensExpression(x, args[0]);
+ } else {
+ // make sure the corresponding tuple type exists
+ var tmp = theBuiltIns.TupleType(x, args.Count, true);
+ e = new DatatypeValue(x, BuiltIns.TupleTypeName(args.Count), BuiltIns.TupleTypeCtorName, args);
+ }
+ }
.)
- "(" (. x = t; e = null; .)
- ( ")" (. // unit
- // make sure the nullary tuple type exists
- var tmp = theBuiltIns.TupleType(x, 0, true);
- e = new DatatypeValue(x, BuiltIns.TupleTypeName(0), BuiltIns.TupleTypeCtorName, new List<Expression>());
- .)
- | Expression<out e, true>
- { "," (. if (args == null) {
- args = new List<Expression>();
- args.Add(e); // add the first argument, which was parsed above
- }
- .)
- Expression<out e, true> (. args.Add(e); .)
+ [ IF(!isLambda && args.Count == 1 && la.kind == _openparen)
+ (. IToken openParen; .)
+ { "(" (. openParen = t; args = new List<Expression>(); .)
+ [ Expressions<args> ]
+ ")"
+ (. e = new ApplyExpr(x, openParen, e, args); .)
}
- ")" (. if (args == null) {
- e = new ParensExpression(x, e);
- } else {
- // make sure the corresponding tuple type exists
- var tmp = theBuiltIns.TupleType(x, args.Count, true);
- e = new DatatypeValue(x, BuiltIns.TupleTypeName(args.Count), BuiltIns.TupleTypeCtorName, args);
- }
- .)
- )
+ ]
+ .
+OptTypedExpr<out Expression e, out Type tt, bool allowSemi>
+= (. tt = null; .)
+ Expression<out e, allowSemi, true>
+ [ ":" Type<out tt> ]
.
DisplayExpr<out Expression e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
@@ -1955,7 +2063,7 @@ MultiSetExpr<out Expression e>
[ Expressions<elements> ] (. e = new MultiSetDisplayExpr(x, elements);.)
"}"
| "(" (. x = t; elements = new List<Expression/*!*/>(); .)
- Expression<out e, true> (. e = new MultiSetFormingExpr(x, e); .)
+ Expression<out e, true, true> (. e = new MultiSetFormingExpr(x, e); .)
")"
| (. SemErr("multiset must be followed by multiset literal or expression to coerce in parentheses."); .)
)
@@ -1972,8 +2080,8 @@ MapDisplayExpr<IToken/*!*/ mapToken, out Expression e>
MapLiteralExpressions<.out List<ExpressionPair> elements.>
= (. Expression/*!*/ d, r;
elements = new List<ExpressionPair/*!*/>(); .)
- Expression<out d, true> ":=" Expression<out r, true> (. elements.Add(new ExpressionPair(d,r)); .)
- { "," Expression<out d, true> ":=" Expression<out r, true> (. elements.Add(new ExpressionPair(d,r)); .)
+ Expression<out d, true, true> ":=" Expression<out r, true, true> (. elements.Add(new ExpressionPair(d,r)); .)
+ { "," Expression<out d, true, true> ":=" Expression<out r, true, true> (. elements.Add(new ExpressionPair(d,r)); .)
}
.
MapComprehensionExpr<IToken mapToken, out Expression e, bool allowSemi>
@@ -1984,29 +2092,29 @@ MapComprehensionExpr<IToken mapToken, out Expression e, bool allowSemi>
Expression body;
.)
IdentTypeOptional<out bv> (. bvars.Add(bv); .)
- [ "|" Expression<out range, true> ]
+ [ "|" Expression<out range, true, true> ]
QSep
- Expression<out body, allowSemi>
+ Expression<out body, allowSemi, true>
(. e = new MapComprehension(mapToken, bvars, range ?? new LiteralExpr(mapToken, true), body);
.)
.
-EndlessExpression<out Expression e, bool allowSemi>
+EndlessExpression<out Expression e, bool allowSemi, bool allowLambda>
= (. IToken/*!*/ x;
Expression e0, e1;
Statement s;
e = dummyExpr;
.)
( "if" (. x = t; .)
- Expression<out e, true>
- "then" Expression<out e0, true>
- "else" Expression<out e1, allowSemi> (. e = new ITEExpr(x, e, e0, e1); .)
- | MatchExpression<out e, allowSemi>
- | QuantifierGuts<out e, allowSemi>
- | ComprehensionExpr<out e, allowSemi>
+ Expression<out e, true, true>
+ "then" Expression<out e0, true, true>
+ "else" Expression<out e1, allowSemi, allowLambda> (. e = new ITEExpr(x, e, e0, e1); .)
+ | MatchExpression<out e, allowSemi, allowLambda>
+ | QuantifierGuts<out e, allowSemi, allowLambda>
+ | ComprehensionExpr<out e, allowSemi, allowLambda>
| StmtInExpr<out s>
- Expression<out e, allowSemi> (. e = new StmtExpr(s.Tok, s, e); .)
- | LetExpr<out e, allowSemi>
- | NamedExpr<out e, allowSemi>
+ Expression<out e, allowSemi, allowLambda> (. e = new StmtExpr(s.Tok, s, e); .)
+ | LetExpr<out e, allowSemi, allowLambda>
+ | NamedExpr<out e, allowSemi, allowLambda>
)
.
@@ -2018,7 +2126,7 @@ StmtInExpr<out Statement s>
)
.
-LetExpr<out Expression e, bool allowSemi>
+LetExpr<out Expression e, bool allowSemi, bool allowLambda>
= (. IToken x = null;
bool isGhost = false;
var letLHSs = new List<CasePattern>();
@@ -2046,14 +2154,14 @@ LetExpr<out Expression e, bool allowSemi>
}
.)
)
- Expression<out e, false> (. letRHSs.Add(e); .)
- { "," Expression<out e, false> (. letRHSs.Add(e); .)
+ Expression<out e, false, true> (. letRHSs.Add(e); .)
+ { "," Expression<out e, false, true> (. letRHSs.Add(e); .)
}
";"
- Expression<out e, allowSemi> (. e = new LetExpr(x, letLHSs, letRHSs, e, exact); .)
+ Expression<out e, allowSemi, allowLambda> (. e = new LetExpr(x, letLHSs, letRHSs, e, exact); .)
.
-NamedExpr<out Expression e, bool allowSemi>
+NamedExpr<out Expression e, bool allowSemi, bool allowLambda>
= (. IToken/*!*/ x, d;
e = dummyExpr;
Expression expr;
@@ -2061,23 +2169,24 @@ NamedExpr<out Expression e, bool allowSemi>
"label" (. x = t; .)
NoUSIdent<out d>
":"
- Expression<out e, allowSemi> (. expr = e;
+ Expression<out e, allowSemi, allowLambda> (. expr = e;
e = new NamedExpr(x, d.val, expr); .)
.
-MatchExpression<out Expression e, bool allowSemi>
+MatchExpression<out Expression e, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; MatchCaseExpr/*!*/ c;
List<MatchCaseExpr/*!*/> cases = new List<MatchCaseExpr/*!*/>();
bool usesOptionalBrace = false;
.)
"match" (. x = t; .)
- Expression<out e, allowSemi>
+ Expression<out e, allowSemi, true>
[ "{" (. usesOptionalBrace = true; .)
]
/* Note: The following gives rise to a '"case" is start & successor of deletable structure' error,
but it's okay, because we want this closer match expression to bind as much as possible--use
parens around it to limit its scope. */
- { CaseExpression<out c, allowSemi> (. cases.Add(c); .)
+ { CaseExpression<out c, allowSemi, usesOptionalBrace || allowLambda>
+ (. cases.Add(c); .)
}
( IF(CloseOptionalBrace(usesOptionalBrace))
"}"
@@ -2085,7 +2194,7 @@ MatchExpression<out Expression e, bool allowSemi>
)
(. e = new MatchExpr(x, e, cases, usesOptionalBrace); .)
.
-CaseExpression<out MatchCaseExpr c, bool allowSemi>
+CaseExpression<out MatchCaseExpr c, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken/*!*/ x, id;
List<BoundVar/*!*/> arguments = new List<BoundVar/*!*/>();
BoundVar/*!*/ bv;
@@ -2099,7 +2208,7 @@ CaseExpression<out MatchCaseExpr c, bool allowSemi>
}
")" ]
"=>"
- Expression<out body, allowSemi> (. c = new MatchCaseExpr(x, id.val, arguments, body); .)
+ Expression<out body, allowSemi, allowLambda> (. c = new MatchCaseExpr(x, id.val, arguments, body); .)
.
CasePattern<out CasePattern pat>
= (. IToken id; List<CasePattern> arguments;
@@ -2126,10 +2235,12 @@ CasePattern<out CasePattern pat>
.
/*------------------------------------------------------------------------*/
-DottedIdentifiersAndFunction<out Expression e>
+DottedIdentifiersAndFunction<out Expression e, bool allowSemi, bool allowLambda>
= (. IToken id, idPrime; IToken openParen = null;
List<Expression> args = null;
List<IToken> idents = new List<IToken>();
+ e = null;
+ var applyArgLists = new List<List<Expression>>();
.)
Ident<out id> (. idents.Add(id); .)
{ IdentOrDigitsSuffix<out id, out idPrime> (. idents.Add(id);
@@ -2138,13 +2249,47 @@ DottedIdentifiersAndFunction<out Expression e>
}
[ (. args = new List<Expression>(); .)
[ "#" (. id.val = id.val + "#"; Expression k; .)
- "[" Expression<out k, true> "]" (. args.Add(k); .)
+ "[" Expression<out k, true, true> "]" (. args.Add(k); .)
]
"(" (. openParen = t; .)
[ Expressions<args> ]
")"
+ /*
+ { "(" (. openParen = t; var argList = new List<Expression>(); .)
+ [ Expressions<argList> ]
+ ")" (. applyArgLists.Add(argList); .)
+ }
+ */
+ ]
+ // A quick-and-dirty lambda expression?
+ [ IF(IsLambda(allowLambda))
+ (. Expression body = null;
+ Expression req = null;
+ bool oneShot;
+ var reads = new List<FrameExpression>();
+ .)
+ LambdaSpec<out req, reads>
+ LambdaArrow<out oneShot>
+ Expression<out body, allowSemi, true>
+ (.
+ if (idents.Count != 1) {
+ SemErr(id, "Invalid variable binding in lambda.");
+ }
+ if (args != null) {
+ SemErr(openParen, "Expected variable binding.");
+ }
+ BoundVar bv = new BoundVar(id, id.val, new InferredTypeProxy());
+ e = new LambdaExpr(id, oneShot, new List<BoundVar>{ bv }, req, reads, body);
+ .)
]
- (. e = new IdentifierSequence(idents, openParen, args); .)
+ // If it wasn't a lambda expression, then it indeed is an identifier sequence
+ (. if (e == null) {
+ e = new IdentifierSequence(idents, openParen, args);
+ foreach (var args_ in applyArgLists) {
+ e = new ApplyExpr(id, openParen, e, args_);
+ }
+ }
+ .)
.
Suffix<ref Expression e>
= (. Contract.Requires(e != null); Contract.Ensures(e!=null); IToken/*!*/ id, x; List<Expression/*!*/>/*!*/ args;
@@ -2160,31 +2305,31 @@ Suffix<ref Expression e>
.)
[ (. args = new List<Expression/*!*/>(); func = true; .)
[ "#" (. id.val = id.val + "#"; Expression k; .)
- "[" Expression<out k, true> "]" (. args.Add(k); .)
+ "[" Expression<out k, true, true> "]" (. args.Add(k); .)
]
"(" (. IToken openParen = t; .)
[ Expressions<args> ]
")" (. e = new FunctionCallExpr(id, id.val, e, openParen, args); .)
] (. if (!func) { e = new ExprDotName(id, e, id.val); } .)
| "[" (. x = t; .)
- ( Expression<out ee, true> (. e0 = ee; .)
+ ( Expression<out ee, true, true> (. e0 = ee; .)
( ".." (. anyDots = true; .)
- [ Expression<out ee, true> (. e1 = ee; .)
+ [ Expression<out ee, true, true> (. e1 = ee; .)
]
| ":="
- Expression<out ee, true> (. e1 = ee; .)
+ Expression<out ee, true, true> (. e1 = ee; .)
| { ":" (. if (multipleLengths == null) {
multipleLengths = new List<Expression>();
multipleLengths.Add(e0);
}
takeRest = true;
.)
- [Expression<out ee, true> (. multipleLengths.Add(ee);
+ [Expression<out ee, true, true> (. multipleLengths.Add(ee);
takeRest = false;
.)
]
}
- | { "," Expression<out ee, true> (. if (multipleIndices == null) {
+ | { "," Expression<out ee, true, true> (. if (multipleIndices == null) {
multipleIndices = new List<Expression>();
multipleIndices.Add(e0);
}
@@ -2193,7 +2338,7 @@ Suffix<ref Expression e>
}
)
| ".." (. anyDots = true; .)
- [ Expression<out ee, true> (. e1 = ee; .)
+ [ Expression<out ee, true, true> (. e1 = ee; .)
]
)
(. if (multipleIndices != null) {
@@ -2237,9 +2382,18 @@ Suffix<ref Expression e>
.)
"]"
)
+ ApplySuffix<ref e>
.
+
+ApplySuffix<ref Expression e>
+= { "(" (. IToken openParen = t; var args = new List<Expression>(); .)
+ [ Expressions<args> ]
+ ")" (. e = new ApplyExpr(e.tok, openParen, e, args); .)
+ }
+ .
+
/*------------------------------------------------------------------------*/
-QuantifierGuts<out Expression q, bool allowSemi>
+QuantifierGuts<out Expression q, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out q) != null); IToken/*!*/ x = Token.NoToken;
bool univ = false;
List<BoundVar/*!*/> bvars;
@@ -2252,7 +2406,7 @@ QuantifierGuts<out Expression q, bool allowSemi>
)
QuantifierDomain<out bvars, out attrs, out range>
QSep
- Expression<out body, allowSemi>
+ Expression<out body, allowSemi, allowLambda>
(. if (univ) {
q = new ForallExpr(x, bvars, range, body, attrs);
} else {
@@ -2278,11 +2432,11 @@ QuantifierDomain<.out List<BoundVar> bvars, out Attributes attrs, out Expression
}
{ IF(IsAttribute()) Attribute<ref attrs> }
[ "|"
- Expression<out range, true>
+ Expression<out range, true, true>
]
.
-ComprehensionExpr<out Expression q, bool allowSemi>
+ComprehensionExpr<out Expression q, bool allowSemi, bool allowLambda>
= (. Contract.Ensures(Contract.ValueAtReturn(out q) != null);
IToken x = Token.NoToken;
BoundVar bv;
@@ -2295,10 +2449,10 @@ ComprehensionExpr<out Expression q, bool allowSemi>
{ ","
IdentTypeOptional<out bv> (. bvars.Add(bv); .)
}
- "|" Expression<out range, allowSemi>
+ "|" Expression<out range, allowSemi, allowLambda>
[
QSep
- Expression<out body, allowSemi>
+ Expression<out body, allowSemi, allowLambda>
]
(. if (body == null && bvars.Count != 1) { SemErr(t, "a set comprehension with more than one bound variable must have a term expression"); }
q = new SetComprehension(x, bvars, range, body);
@@ -2306,8 +2460,8 @@ ComprehensionExpr<out Expression q, bool allowSemi>
.
Expressions<.List<Expression/*!*/>/*!*/ args.>
= (. Contract.Requires(cce.NonNullElements(args)); Expression/*!*/ e; .)
- Expression<out e, true> (. args.Add(e); .)
- { "," Expression<out e, true> (. args.Add(e); .)
+ Expression<out e, true, true> (. args.Add(e); .)
+ { "," Expression<out e, true, true> (. args.Add(e); .)
}
.
/*------------------------------------------------------------------------*/
@@ -2330,7 +2484,7 @@ AttributeBody<ref Attributes attrs>
AttributeArg<out Attributes.Argument arg, bool allowSemi>
= (. Contract.Ensures(Contract.ValueAtReturn(out arg) != null); Expression/*!*/ e; arg = dummyAttrArg; .)
( string (. arg = new Attributes.Argument(t, t.val.Substring(1, t.val.Length-2)); .)
- | Expression<out e, allowSemi> (. arg = new Attributes.Argument(t, e); .)
+ | Expression<out e, allowSemi, true> (. arg = new Attributes.Argument(t, e); .)
)
.
/*------------------------------------------------------------------------*/
@@ -2374,6 +2528,8 @@ IdentOrDigitsSuffix<out IToken x, out IToken y>
}
}
.)
+ | "requires" (. x = t; .)
+ | "reads" (. x = t; .)
)
.
// Identifier, disallowing leading underscores
diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs
index 21227dd6..54c5c12b 100644
--- a/Source/Dafny/DafnyAst.cs
+++ b/Source/Dafny/DafnyAst.cs
@@ -370,7 +370,9 @@ namespace Microsoft.Dafny {
return true;
} else {
UserDefinedType udt = this as UserDefinedType;
- return udt != null && udt.ResolvedParam == null && udt.ResolvedClass is ClassDecl;
+ return udt != null && udt.ResolvedParam == null && udt.ResolvedClass is ClassDecl
+ && !(udt.ResolvedClass is ArrowType.ArrowTypeDecl);
+
}
}
}
@@ -535,6 +537,115 @@ namespace Microsoft.Dafny {
}
}
+ public class ArrowType : UserDefinedType
+ {
+ public List<Type> Args {
+ get { return TypeArgs.GetRange(0, Arity); }
+ }
+
+ public Type Result {
+ get { return TypeArgs[Arity]; }
+ }
+
+ public int Arity {
+ get { return TypeArgs.Count - 1; }
+ }
+
+ public ArrowType(List<Type> args, Type result) :
+ base(Token.NoToken, ArrowType.ArrowTypeName(args.Count), Util.Snoc(args, result), null) {
+ ResolvedClass = GetArrowDecl(args.Count);
+ }
+
+ public static string ArrowTypeName(int arity) {
+ return "_Func" + arity;
+ }
+
+ public static bool IsArrowTypeName(string s) {
+ return s.StartsWith("_Func");
+ }
+
+ public override string TypeName(ModuleDefinition context) {
+ string s = "", closeparen = "";
+ if (Args.Count != 1 || Args[0] is ArrowType) {
+ s += "("; closeparen = ")";
+ }
+ s += Util.Comma(Args, arg => arg.TypeName(context));
+ s += closeparen;
+ s += " -> ";
+ s += Result.TypeName(context);
+ return s;
+ }
+
+ private static ArrowTypeDecl GetArrowDecl(int arity) {
+ ArrowTypeDecl arrowDecl;
+ if (!arrowTypeDecls.TryGetValue(arity, out arrowDecl)) {
+ var tok = Token.NoToken;
+ var tps = Util.Map(Enumerable.Range(0, arity + 1),
+ x => new TypeParameter(tok, "_Fn" + x));
+ var tys = tps.ConvertAll(tp => (Type)(new UserDefinedType(tp)));
+ var args = tys.GetRange(0, arity).ConvertAll(t => new Formal(tok, "x", t, true, false));
+ var argExprs = args.ConvertAll(a =>
+ (Expression)new IdentifierExpr(tok, a.Name) { Var = a, Type = a.Type });
+ var readsIS = new IdentifierSequence(new List<IToken> { tok }, tok, argExprs) {
+ Type = new SetType(new ObjectType()),
+ };
+ var readsFrame = new List<FrameExpression> { new FrameExpression(tok, readsIS, null) };
+ var req = new Function(tok, "requires", false, true,
+ new List<TypeParameter>(), tok, args, Type.Bool,
+ new List<Expression>(), readsFrame, new List<Expression>(),
+ new Specification<Expression>(new List<Expression>(), null),
+ null, null, null);
+ var reads = new Function(tok, "reads", false, true,
+ new List<TypeParameter>(), tok, args, new SetType(new ObjectType()),
+ new List<Expression>(), readsFrame, new List<Expression>(),
+ new Specification<Expression>(new List<Expression>(), null),
+ null, null, null);
+ var readsFexp =
+ new FunctionCallExpr(tok, "reads", new ThisExpr(tok), tok, argExprs) {
+ Function = reads,
+ Type = readsIS.Type,
+ TypeArgumentSubstitutions = Util.Dict(tps, tys)
+ };
+ readsIS.ResolvedExpression = readsFexp;
+ arrowDecl = new ArrowTypeDecl(tps, req, reads);
+ arrowTypeDecls[arity] = arrowDecl;
+ }
+ return arrowDecl;
+ }
+
+ private readonly static Dictionary<int, ArrowTypeDecl> arrowTypeDecls = new Dictionary<int, ArrowTypeDecl>();
+ private static readonly ModuleDefinition FunctionModule = new ModuleDefinition(Token.NoToken, "_Fn", false, false, null, null, null, true) { Height = -1 };
+
+ public static IEnumerable<ArrowTypeDecl> ArrowTypeDecls {
+ get {
+ return ArrowType.arrowTypeDecls.Values;
+ }
+ }
+
+ public class ArrowTypeDecl : ClassDecl
+ {
+ public readonly int Arity;
+ public readonly Function Requires;
+ public readonly Function Reads;
+
+ public ArrowTypeDecl(List<TypeParameter> tps, Function req, Function reads)
+ : base(Token.NoToken, "_Func" + (tps.Count-1), FunctionModule, tps,
+ new List<MemberDecl>{ req, reads }, null) {
+ Arity = tps.Count-1;
+ Requires = req;
+ Reads = reads;
+ Requires.EnclosingClass = this;
+ Reads.EnclosingClass = this;
+ }
+ }
+
+ public override bool SupportsEquality {
+ get {
+ return false;
+ }
+ }
+ }
+
public abstract class CollectionType : NonProxyType
{
public abstract string CollectionTypeName { get; }
@@ -656,6 +767,7 @@ namespace Microsoft.Dafny {
Contract.Invariant(Name != null);
Contract.Invariant(cce.NonNullElements(TypeArgs));
Contract.Invariant(cce.NonNullElements(Path));
+ Contract.Invariant(!ArrowType.IsArrowTypeName(Name) || this is ArrowType);
}
public readonly List<IToken> Path;
@@ -2268,6 +2380,12 @@ namespace Microsoft.Dafny {
public readonly IToken SignatureEllipsis;
public bool IsBuiltin;
+ public Type Type {
+ get {
+ return new ArrowType(Formals.ConvertAll(f => f.Type), ResultType);
+ }
+ }
+
/// <summary>
/// The "AllCalls" field is used for non-CoPredicate, non-PrefixPredicate functions only (so its value should not be relied upon for CoPredicate and PrefixPredicate functions).
/// It records all function calls made by the Function, including calls made in the body as well as in the specification.
@@ -3255,9 +3373,9 @@ namespace Microsoft.Dafny {
if (lhs is IdentifierExpr) {
var x = (IdentifierExpr)lhs;
return x.Var.IsGhost;
- } else if (lhs is FieldSelectExpr) {
- var x = (FieldSelectExpr)lhs;
- return x.Field.IsGhost;
+ } else if (lhs is MemberSelectExpr) {
+ var x = (MemberSelectExpr)lhs;
+ return x.Member.IsGhost;
} else {
// LHS denotes an array element, which is always non-ghost
return false;
@@ -4846,26 +4964,54 @@ namespace Microsoft.Dafny {
}
}
- public class FieldSelectExpr : Expression {
+ // Former FieldSelectExpression
+ public class MemberSelectExpr : Expression {
public readonly Expression Obj;
- public readonly string FieldName;
- public Field Field; // filled in by resolution
+ public readonly string MemberName;
+ public MemberDecl Member; // filled in by resolution, will be a Field or Function
+ public List<Type> TypeApplication;
+ // If it is a function, it must have all its polymorphic variables applied
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(Obj != null);
- Contract.Invariant(FieldName != null);
+ Contract.Invariant(MemberName != null);
+ Contract.Invariant((Member is Function) == (TypeApplication != null));
}
- public FieldSelectExpr(IToken tok, Expression obj, string fieldName)
+ public MemberSelectExpr(IToken tok, Expression obj, string memberName)
: base(tok) {
Contract.Requires(tok != null);
Contract.Requires(obj != null);
- Contract.Requires(fieldName != null);
+ Contract.Requires(memberName != null);
this.Obj = obj;
- this.FieldName = fieldName;
+ this.MemberName = memberName;
+ }
+
+ public void MemberSelectCase(Action<Field> fieldK, Action<Function> functionK) {
+ MemberSelectCase<bool>(
+ f => {
+ fieldK(f);
+ return true;
+ },
+ f => {
+ functionK(f);
+ return true;
+ });
+ }
+
+ public A MemberSelectCase<A>(Func<Field,A> fieldK, Func<Function,A> functionK) {
+ var field = Member as Field;
+ var function = Member as Function;
+ if (field != null) {
+ return fieldK(field);
+ } else {
+ Contract.Assert(function != null);
+ return functionK(function);
+ }
}
+
public override IEnumerable<Expression> SubExpressions {
get { yield return Obj; }
}
@@ -4970,6 +5116,32 @@ namespace Microsoft.Dafny {
}
}
+ public class ApplyExpr : Expression {
+ // The idea is that this apply expression does not need a type argument substitution,
+ // since lambda functions and anonymous functions are never polymorphic.
+ // Make a FunctionCallExpr otherwise, to call a resolvable anonymous function.
+ public readonly Expression Receiver;
+ public readonly List<Expression> Args;
+ public readonly IToken OpenParen;
+
+ public override IEnumerable<Expression> SubExpressions {
+ get {
+ yield return Receiver;
+ foreach (var e in Args) {
+ yield return e;
+ }
+ }
+ }
+
+ public ApplyExpr(IToken tok, IToken openParen, Expression receiver, List<Expression> args)
+ : base(tok)
+ {
+ OpenParen = openParen;
+ Receiver = receiver;
+ Args = args;
+ }
+ }
+
public class FunctionCallExpr : Expression {
public readonly string Name;
public readonly Expression Receiver;
@@ -5606,19 +5778,18 @@ namespace Microsoft.Dafny {
public abstract class QuantifierExpr : ComprehensionExpr, TypeParameter.ParentType {
public List<TypeParameter> TypeArgs;
- public static int quantCount = 0;
+ private static int quantCount = 0;
private readonly int quantUnique;
- private int typeRefreshCount = 0;
public string FullName {
get {
return "q$" + quantUnique;
}
}
- public String Refresh(String s) {
- return s + "#" + typeRefreshCount++ + FullName;
+ public String Refresh(String s, ref int counter) {
+ return s + "#" + counter++ + FullName;
}
- public TypeParameter Refresh(TypeParameter p) {
- TypeParameter cp = new TypeParameter(p.tok, typeRefreshCount++ + "#" + p.Name, p.EqualitySupport);
+ public TypeParameter Refresh(TypeParameter p, ref int counter) {
+ var cp = new TypeParameter(p.tok, counter++ + "#" + p.Name, p.EqualitySupport);
cp.Parent = this;
return cp;
}
@@ -5634,7 +5805,6 @@ namespace Microsoft.Dafny {
Contract.Requires(term != null);
this.TypeArgs = tvars;
this.quantUnique = quantCount++;
- this.typeRefreshCount = 0;
}
public abstract Expression LogicalBody();
}
@@ -5713,6 +5883,48 @@ namespace Microsoft.Dafny {
}
}
+ public class LambdaExpr : ComprehensionExpr
+ {
+ private static int lamUniques = 0;
+
+ public readonly bool OneShot;
+
+ public readonly List<FrameExpression> Reads;
+
+ public string MkName(string nm) {
+ return "$l" + lamUniques++ + "#" + nm;
+ }
+
+ public LambdaExpr(IToken tok, bool oneShot, List<BoundVar> bvars, Expression requires, List<FrameExpression> reads, Expression body)
+ : base(tok, bvars, requires, body, null)
+ {
+ Contract.Requires(reads != null);
+ Reads = reads;
+ OneShot = oneShot;
+ }
+
+ // Synonym
+ public Expression Body {
+ get {
+ return Term;
+ }
+ }
+
+ public override IEnumerable<Expression> SubExpressions {
+ get {
+ yield return Term;
+ if (Range != null) {
+ yield return Range;
+ }
+ foreach (var read in Reads) {
+ yield return read.E;
+ }
+ }
+ }
+
+ }
+
+
public class WildcardExpr : Expression
{ // a WildcardExpr can occur only in reads clauses and a loop's decreases clauses (with different meanings)
public WildcardExpr(IToken tok)
@@ -6104,6 +6316,26 @@ namespace Microsoft.Dafny {
}
}
+ public class TypeExpr : ParensExpression
+ {
+ public readonly Type T;
+ public TypeExpr(IToken tok, Expression e, Type t)
+ : base(tok, e)
+ {
+ Contract.Requires(t != null);
+ T = t;
+ }
+
+ public static Expression MaybeTypeExpr(Expression e, Type t) {
+ if (t == null) {
+ return e;
+ } else {
+ return new TypeExpr(e.tok, e, t);
+ }
+ }
+ }
+
+
/// <summary>
/// An AutoGeneratedExpression is simply a wrapper around an expression. This expression tells the generation of hover text (in the Dafny IDE)
/// that the expression was no supplied directly in the program text and should therefore be ignored. In other places, an AutoGeneratedExpression
diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs
index 63c555aa..b812bf1d 100644
--- a/Source/Dafny/Parser.cs
+++ b/Source/Dafny/Parser.cs
@@ -22,13 +22,17 @@ public class Parser {
public const int _string = 6;
public const int _colon = 7;
public const int _semi = 8;
- public const int _lbrace = 9;
- public const int _rbrace = 10;
- public const int _openparen = 11;
- public const int _closeparen = 12;
- public const int _star = 13;
- public const int _notIn = 14;
- public const int maxT = 126;
+ public const int _darrow = 9;
+ public const int _arrow = 10;
+ public const int _reads = 11;
+ public const int _requires = 12;
+ public const int _lbrace = 13;
+ public const int _rbrace = 14;
+ public const int _openparen = 15;
+ public const int _closeparen = 16;
+ public const int _star = 17;
+ public const int _notIn = 18;
+ public const int maxT = 127;
const bool T = true;
const bool x = false;
@@ -147,6 +151,13 @@ bool IsParenStar() {
return la.kind == _openparen && x.kind == _star;
}
+bool IsLambda(bool allowLambda)
+{
+ return allowLambda &&
+ (la.kind == _darrow || la.kind == _arrow
+ || la.kind == _reads || la.kind == _requires);
+}
+
bool IsIdentParen() {
Token x = scanner.Peek();
return la.kind == _ident && x.kind == _openparen;
@@ -154,7 +165,7 @@ bool IsIdentParen() {
bool SemiFollowsCall(bool allowSemi, Expression e) {
return allowSemi && la.kind == _semi &&
- (e is FunctionCallExpr ||
+ (e is FunctionCallExpr || e is ApplyExpr ||
(e is IdentifierSequence && ((IdentifierSequence)e).OpenParen != null));
}
@@ -165,6 +176,7 @@ bool CloseOptionalParen(bool usesOptionalParen) {
bool CloseOptionalBrace(bool usesOptionalBrace) {
return usesOptionalBrace && la.kind == _rbrace;
}
+
/*--------------------------------------------------------------------------*/
@@ -245,7 +257,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
// theModule should be a DefaultModuleDecl (actually, the singular DefaultModuleDecl)
Contract.Assert(defaultModule != null);
- while (la.kind == 15) {
+ while (la.kind == 19) {
Get();
Expect(6);
{
@@ -263,32 +275,32 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
}
while (StartOf(1)) {
switch (la.kind) {
- case 16: case 17: case 19: {
+ case 20: case 21: case 23: {
SubModuleDecl(defaultModule, out submodule);
defaultModule.TopLevelDecls.Add(submodule);
break;
}
- case 24: {
+ case 28: {
ClassDecl(defaultModule, out c);
defaultModule.TopLevelDecls.Add(c);
break;
}
- case 27: case 28: {
+ case 31: case 32: {
DatatypeDecl(defaultModule, out dt);
defaultModule.TopLevelDecls.Add(dt);
break;
}
- case 32: {
+ case 36: {
OtherTypeDecl(defaultModule, out td);
defaultModule.TopLevelDecls.Add(td);
break;
}
- case 34: {
+ case 38: {
IteratorDecl(defaultModule, out iter);
defaultModule.TopLevelDecls.Add(iter);
break;
}
- case 25: case 26: case 30: case 40: case 41: case 42: case 43: case 44: case 62: case 63: case 64: {
+ case 29: case 30: case 34: case 44: case 45: case 46: case 47: case 48: case 64: case 65: case 66: {
ClassMemberDecl(membersDefaultClass, false);
break;
}
@@ -320,76 +332,76 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
bool isAbstract = false;
bool opened = false;
- if (la.kind == 16 || la.kind == 17) {
- if (la.kind == 16) {
+ if (la.kind == 20 || la.kind == 21) {
+ if (la.kind == 20) {
Get();
isAbstract = true;
}
- Expect(17);
- while (la.kind == 9) {
+ Expect(21);
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 18) {
+ if (la.kind == 22) {
Get();
QualifiedName(out idRefined);
}
module = new ModuleDefinition(id, id.val, isAbstract, false, idRefined == null ? null : idRefined, parent, attrs, false);
- Expect(9);
+ Expect(13);
module.BodyStartTok = t;
while (StartOf(1)) {
switch (la.kind) {
- case 16: case 17: case 19: {
+ case 20: case 21: case 23: {
SubModuleDecl(module, out sm);
module.TopLevelDecls.Add(sm);
break;
}
- case 24: {
+ case 28: {
ClassDecl(module, out c);
module.TopLevelDecls.Add(c);
break;
}
- case 27: case 28: {
+ case 31: case 32: {
DatatypeDecl(module, out dt);
module.TopLevelDecls.Add(dt);
break;
}
- case 32: {
+ case 36: {
OtherTypeDecl(module, out td);
module.TopLevelDecls.Add(td);
break;
}
- case 34: {
+ case 38: {
IteratorDecl(module, out iter);
module.TopLevelDecls.Add(iter);
break;
}
- case 25: case 26: case 30: case 40: case 41: case 42: case 43: case 44: case 62: case 63: case 64: {
+ case 29: case 30: case 34: case 44: case 45: case 46: case 47: case 48: case 64: case 65: case 66: {
ClassMemberDecl(namedModuleDefaultClassMembers, false);
break;
}
}
}
- Expect(10);
+ Expect(14);
module.BodyEndTok = t;
module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
submodule = new LiteralModuleDecl(module, parent);
- } else if (la.kind == 19) {
+ } else if (la.kind == 23) {
Get();
- if (la.kind == 20) {
+ if (la.kind == 24) {
Get();
opened = true;
}
NoUSIdent(out id);
- if (la.kind == 21 || la.kind == 22) {
- if (la.kind == 21) {
+ if (la.kind == 25 || la.kind == 26) {
+ if (la.kind == 25) {
Get();
QualifiedName(out idPath);
submodule = new AliasModuleDecl(idPath, id, parent, opened);
} else {
Get();
QualifiedName(out idPath);
- if (la.kind == 23) {
+ if (la.kind == 27) {
Get();
QualifiedName(out idAssignment);
}
@@ -397,7 +409,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
}
}
if (la.kind == 8) {
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(127); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(128); Get();}
Get();
}
if (submodule == null) {
@@ -406,7 +418,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
submodule = new AliasModuleDecl(idPath, id, parent, opened);
}
- } else SynErr(128);
+ } else SynErr(129);
}
void ClassDecl(ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) {
@@ -418,21 +430,21 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>();
IToken bodyStart;
- while (!(la.kind == 0 || la.kind == 24)) {SynErr(129); Get();}
- Expect(24);
- while (la.kind == 9) {
+ while (!(la.kind == 0 || la.kind == 28)) {SynErr(130); Get();}
+ Expect(28);
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
- Expect(9);
+ Expect(13);
bodyStart = t;
while (StartOf(2)) {
ClassMemberDecl(members, true);
}
- Expect(10);
+ Expect(14);
c = new ClassDecl(id, id.val, module, typeArgs, members, attrs);
c.BodyStartTok = bodyStart;
c.BodyEndTok = t;
@@ -449,29 +461,29 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
IToken bodyStart = Token.NoToken; // dummy assignment
bool co = false;
- while (!(la.kind == 0 || la.kind == 27 || la.kind == 28)) {SynErr(130); Get();}
- if (la.kind == 27) {
+ while (!(la.kind == 0 || la.kind == 31 || la.kind == 32)) {SynErr(131); Get();}
+ if (la.kind == 31) {
Get();
- } else if (la.kind == 28) {
+ } else if (la.kind == 32) {
Get();
co = true;
- } else SynErr(131);
- while (la.kind == 9) {
+ } else SynErr(132);
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
- Expect(21);
+ Expect(25);
bodyStart = t;
DatatypeMemberDecl(ctors);
- while (la.kind == 29) {
+ while (la.kind == 33) {
Get();
DatatypeMemberDecl(ctors);
}
if (la.kind == 8) {
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(132); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(133); Get();}
Get();
}
if (co) {
@@ -492,35 +504,35 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
td = null;
Type ty;
- Expect(32);
- while (la.kind == 9) {
+ Expect(36);
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 11) {
+ if (la.kind == 15) {
Get();
- Expect(33);
- Expect(12);
+ Expect(37);
+ Expect(16);
eqSupport = TypeParameter.EqualitySupportValue.Required;
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
} else if (StartOf(3)) {
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
- if (la.kind == 21) {
+ if (la.kind == 25) {
Get();
Type(out ty);
td = new TypeSynonymDecl(id, id.val, typeArgs, module, ty, attrs);
}
- } else SynErr(133);
+ } else SynErr(134);
if (td == null) {
td = new OpaqueTypeDecl(id, id.val, module, eqSupport, typeArgs, attrs);
}
if (la.kind == 8) {
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(134); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(135); Get();}
Get();
}
}
@@ -549,19 +561,19 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
- while (!(la.kind == 0 || la.kind == 34)) {SynErr(135); Get();}
- Expect(34);
- while (la.kind == 9) {
+ while (!(la.kind == 0 || la.kind == 38)) {SynErr(136); Get();}
+ Expect(38);
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 11 || la.kind == 38) {
- if (la.kind == 38) {
+ if (la.kind == 15 || la.kind == 42) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
Formals(true, true, ins, out openParen);
- if (la.kind == 35 || la.kind == 36) {
- if (la.kind == 35) {
+ if (la.kind == 39 || la.kind == 40) {
+ if (la.kind == 39) {
Get();
} else {
Get();
@@ -569,14 +581,14 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
}
Formals(false, true, outs, out openParen);
}
- } else if (la.kind == 37) {
+ } else if (la.kind == 41) {
Get();
signatureEllipsis = t; openParen = Token.NoToken;
- } else SynErr(136);
+ } else SynErr(137);
while (StartOf(4)) {
IteratorSpec(reads, mod, decreases, req, ens, yieldReq, yieldEns, ref readsAttrs, ref modAttrs, ref decrAttrs);
}
- if (la.kind == 9) {
+ if (la.kind == 13) {
BlockStmt(out body, out bodyStart, out bodyEnd);
}
iter = new IteratorDecl(id, id.val, module, typeArgs, ins, outs,
@@ -596,8 +608,8 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
Function/*!*/ f;
MemberModifiers mmod = new MemberModifiers();
- while (la.kind == 25 || la.kind == 26) {
- if (la.kind == 25) {
+ while (la.kind == 29 || la.kind == 30) {
+ if (la.kind == 29) {
Get();
mmod.IsGhost = true;
} else {
@@ -605,21 +617,21 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
mmod.IsStatic = true;
}
}
- if (la.kind == 30) {
+ if (la.kind == 34) {
FieldDecl(mmod, mm);
- } else if (la.kind == 62 || la.kind == 63 || la.kind == 64) {
+ } else if (la.kind == 64 || la.kind == 65 || la.kind == 66) {
FunctionDecl(mmod, out f);
mm.Add(f);
} else if (StartOf(5)) {
MethodDecl(mmod, allowConstructors, out m);
mm.Add(m);
- } else SynErr(137);
+ } else SynErr(138);
}
void Attribute(ref Attributes attrs) {
- Expect(9);
+ Expect(13);
AttributeBody(ref attrs);
- Expect(10);
+ Expect(14);
}
void NoUSIdent(out IToken/*!*/ x) {
@@ -636,7 +648,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
IToken id; IToken idPrime; ids = new List<IToken>();
Ident(out id);
ids.Add(id);
- while (la.kind == 61) {
+ while (la.kind == 63) {
IdentOrDigitsSuffix(out id, out idPrime);
ids.Add(id);
if (idPrime != null) { ids.Add(idPrime); }
@@ -655,7 +667,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
x = Token.NoToken;
y = null;
- Expect(61);
+ Expect(63);
if (la.kind == 1) {
Get();
x = t;
@@ -683,7 +695,13 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
}
}
- } else SynErr(138);
+ } else if (la.kind == 12) {
+ Get();
+ x = t;
+ } else if (la.kind == 11) {
+ Get();
+ x = t;
+ } else SynErr(139);
}
void GenericParameters(List<TypeParameter/*!*/>/*!*/ typeArgs) {
@@ -691,29 +709,29 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
IToken/*!*/ id;
TypeParameter.EqualitySupportValue eqSupport;
- Expect(38);
+ Expect(42);
NoUSIdent(out id);
eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
- if (la.kind == 11) {
+ if (la.kind == 15) {
Get();
- Expect(33);
- Expect(12);
+ Expect(37);
+ Expect(16);
eqSupport = TypeParameter.EqualitySupportValue.Required;
}
typeArgs.Add(new TypeParameter(id, id.val, eqSupport));
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
NoUSIdent(out id);
eqSupport = TypeParameter.EqualitySupportValue.Unspecified;
- if (la.kind == 11) {
+ if (la.kind == 15) {
Get();
- Expect(33);
- Expect(12);
+ Expect(37);
+ Expect(16);
eqSupport = TypeParameter.EqualitySupportValue.Required;
}
typeArgs.Add(new TypeParameter(id, id.val, eqSupport));
}
- Expect(39);
+ Expect(43);
}
void FieldDecl(MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm) {
@@ -721,21 +739,21 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
Attributes attrs = null;
IToken/*!*/ id; Type/*!*/ ty;
- while (!(la.kind == 0 || la.kind == 30)) {SynErr(139); Get();}
- Expect(30);
+ while (!(la.kind == 0 || la.kind == 34)) {SynErr(140); Get();}
+ Expect(34);
if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); }
- while (la.kind == 9) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
FIdentType(out id, out ty);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
FIdentType(out id, out ty);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
}
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(140); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(141); Get();}
Expect(8);
}
@@ -758,90 +776,90 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
IToken bodyEnd = Token.NoToken;
IToken signatureEllipsis = null;
- if (la.kind == 62) {
+ if (la.kind == 64) {
Get();
- if (la.kind == 40) {
+ if (la.kind == 44) {
Get();
isFunctionMethod = true;
}
if (mmod.IsGhost) { SemErr(t, "functions cannot be declared 'ghost' (they are ghost by default)"); }
- while (la.kind == 9) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 11 || la.kind == 38) {
- if (la.kind == 38) {
+ if (la.kind == 15 || la.kind == 42) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
Formals(true, isFunctionMethod, formals, out openParen);
Expect(7);
Type(out returnType);
- } else if (la.kind == 37) {
+ } else if (la.kind == 41) {
Get();
signatureEllipsis = t;
openParen = Token.NoToken;
- } else SynErr(141);
- } else if (la.kind == 63) {
+ } else SynErr(142);
+ } else if (la.kind == 65) {
Get();
isPredicate = true;
- if (la.kind == 40) {
+ if (la.kind == 44) {
Get();
isFunctionMethod = true;
}
if (mmod.IsGhost) { SemErr(t, "predicates cannot be declared 'ghost' (they are ghost by default)"); }
- while (la.kind == 9) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (StartOf(6)) {
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
- if (la.kind == 11) {
+ if (la.kind == 15) {
Formals(true, isFunctionMethod, formals, out openParen);
if (la.kind == 7) {
Get();
SemErr(t, "predicates do not have an explicitly declared return type; it is always bool");
}
}
- } else if (la.kind == 37) {
+ } else if (la.kind == 41) {
Get();
signatureEllipsis = t;
openParen = Token.NoToken;
- } else SynErr(142);
- } else if (la.kind == 64) {
+ } else SynErr(143);
+ } else if (la.kind == 66) {
Get();
isCoPredicate = true;
if (mmod.IsGhost) { SemErr(t, "copredicates cannot be declared 'ghost' (they are ghost by default)"); }
- while (la.kind == 9) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
if (StartOf(6)) {
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
- if (la.kind == 11) {
+ if (la.kind == 15) {
Formals(true, isFunctionMethod, formals, out openParen);
if (la.kind == 7) {
Get();
SemErr(t, "copredicates do not have an explicitly declared return type; it is always bool");
}
}
- } else if (la.kind == 37) {
+ } else if (la.kind == 41) {
Get();
signatureEllipsis = t;
openParen = Token.NoToken;
- } else SynErr(143);
- } else SynErr(144);
+ } else SynErr(144);
+ } else SynErr(145);
decreases = isCoPredicate ? null : new List<Expression/*!*/>();
while (StartOf(7)) {
FunctionSpec(reqs, reads, ens, decreases);
}
- if (la.kind == 9) {
+ if (la.kind == 13) {
FunctionBody(out body, out bodyStart, out bodyEnd);
}
if (DafnyOptions.O.DisallowSoundnessCheating && body == null && ens.Count > 0 && !Attributes.Contains(attrs, "axiom")) {
@@ -887,21 +905,21 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
- while (!(StartOf(8))) {SynErr(145); Get();}
- if (la.kind == 40) {
+ while (!(StartOf(8))) {SynErr(146); Get();}
+ if (la.kind == 44) {
Get();
- } else if (la.kind == 41) {
+ } else if (la.kind == 45) {
Get();
isLemma = true;
- } else if (la.kind == 42) {
+ } else if (la.kind == 46) {
Get();
isCoLemma = true;
- } else if (la.kind == 43) {
+ } else if (la.kind == 47) {
Get();
isCoLemma = true;
errors.Warning(t, "the 'comethod' keyword has been deprecated; it has been renamed to 'colemma'");
- } else if (la.kind == 44) {
+ } else if (la.kind == 48) {
Get();
if (allowConstructor) {
isConstructor = true;
@@ -909,7 +927,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
SemErr(t, "constructors are only allowed in classes");
}
- } else SynErr(146);
+ } else SynErr(147);
keywordToken = t;
if (isLemma) {
if (mmod.IsGhost) {
@@ -928,7 +946,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
}
}
- while (la.kind == 9) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
if (la.kind == 1) {
@@ -942,24 +960,24 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
}
}
- if (la.kind == 11 || la.kind == 38) {
- if (la.kind == 38) {
+ if (la.kind == 15 || la.kind == 42) {
+ if (la.kind == 42) {
GenericParameters(typeArgs);
}
Formals(true, !mmod.IsGhost, ins, out openParen);
- if (la.kind == 36) {
+ if (la.kind == 40) {
Get();
if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); }
Formals(false, !mmod.IsGhost, outs, out openParen);
}
- } else if (la.kind == 37) {
+ } else if (la.kind == 41) {
Get();
signatureEllipsis = t; openParen = Token.NoToken;
- } else SynErr(147);
+ } else SynErr(148);
while (StartOf(9)) {
MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs);
}
- if (la.kind == 9) {
+ if (la.kind == 13) {
BlockStmt(out body, out bodyStart, out bodyEnd);
}
if (Attributes.Contains(attrs, "axiom") && !mmod.IsGhost && !isLemma) {
@@ -995,11 +1013,11 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
IToken/*!*/ id;
List<Formal/*!*/> formals = new List<Formal/*!*/>();
- while (la.kind == 9) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
NoUSIdent(out id);
- if (la.kind == 11) {
+ if (la.kind == 15) {
FormalsOptionalIds(formals);
}
ctors.Add(new DatatypeCtor(id, id.val, formals, attrs));
@@ -1007,17 +1025,17 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
void FormalsOptionalIds(List<Formal/*!*/>/*!*/ formals) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost;
- Expect(11);
+ Expect(15);
if (StartOf(10)) {
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
}
}
- Expect(12);
+ Expect(16);
}
void FIdentType(out IToken/*!*/ id, out Type/*!*/ ty) {
@@ -1029,12 +1047,12 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
} else if (la.kind == 2) {
Get();
id = t;
- } else SynErr(148);
+ } else SynErr(149);
Expect(7);
Type(out ty);
}
- void Type(out Type/*!*/ ty) {
+ void Type(out Type ty) {
Contract.Ensures(Contract.ValueAtReturn(out ty) != null); IToken/*!*/ tok;
TypeAndToken(out tok, out ty);
}
@@ -1043,7 +1061,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
Contract.Ensures(Contract.ValueAtReturn(out id)!=null);
Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
isGhost = false;
- if (la.kind == 25) {
+ if (la.kind == 29) {
Get();
if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); }
}
@@ -1101,7 +1119,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
Contract.Ensures(Contract.ValueAtReturn(out identName)!=null);
string name = null; id = Token.NoToken; ty = new BoolType()/*dummy*/; isGhost = false;
- if (la.kind == 25) {
+ if (la.kind == 29) {
Get();
isGhost = true;
}
@@ -1123,7 +1141,7 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
id = t; name = id.val;
Expect(7);
Type(out ty);
- } else SynErr(149);
+ } else SynErr(150);
if (name != null) {
identName = name;
} else {
@@ -1132,36 +1150,36 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
}
- void TypeAndToken(out IToken/*!*/ tok, out Type/*!*/ ty) {
+ void TypeAndToken(out IToken tok, out Type ty) {
Contract.Ensures(Contract.ValueAtReturn(out tok)!=null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);
tok = Token.NoToken; ty = new BoolType(); /*keep compiler happy*/
- List<Type> gt;
+ List<Type> gt = null;
switch (la.kind) {
- case 52: {
+ case 54: {
Get();
tok = t;
break;
}
- case 53: {
+ case 55: {
Get();
tok = t; ty = new NatType();
break;
}
- case 54: {
+ case 56: {
Get();
tok = t; ty = new IntType();
break;
}
- case 55: {
+ case 57: {
Get();
tok = t; ty = new RealType();
break;
}
- case 56: {
+ case 58: {
Get();
tok = t; gt = new List<Type/*!*/>();
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericInstantiation(gt);
}
if (gt.Count > 1) {
@@ -1171,10 +1189,10 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
break;
}
- case 57: {
+ case 59: {
Get();
tok = t; gt = new List<Type/*!*/>();
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericInstantiation(gt);
}
if (gt.Count > 1) {
@@ -1184,10 +1202,10 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
break;
}
- case 58: {
+ case 60: {
Get();
tok = t; gt = new List<Type/*!*/>();
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericInstantiation(gt);
}
if (gt.Count > 1) {
@@ -1197,10 +1215,10 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
break;
}
- case 59: {
+ case 61: {
Get();
tok = t; gt = new List<Type/*!*/>();
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericInstantiation(gt);
}
if (gt.Count == 0) {
@@ -1214,19 +1232,19 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
break;
}
- case 11: {
+ case 15: {
Get();
tok = t; gt = new List<Type>();
if (StartOf(11)) {
Type(out ty);
gt.Add(ty);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
Type(out ty);
gt.Add(ty);
}
}
- Expect(12);
+ Expect(16);
if (gt.Count == 1) {
// just return the type 'ty'
} else {
@@ -1238,28 +1256,38 @@ bool CloseOptionalBrace(bool usesOptionalBrace) {
break;
}
- case 1: case 5: case 60: {
+ case 1: case 5: case 62: {
ReferenceType(out tok, out ty);
break;
}
- default: SynErr(150); break;
+ default: SynErr(151); break;
+ }
+ if (la.kind == 10) {
+ Type t2;
+ Get();
+ Type(out t2);
+ if (gt == null) {
+ gt = new List<Type>{ ty };
+ }
+ ty = new ArrowType(gt, t2);
+
}
}
void Formals(bool incoming, bool allowGhostKeyword, List<Formal/*!*/>/*!*/ formals, out IToken openParen) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; bool isGhost;
- Expect(11);
+ Expect(15);
openParen = t;
- if (la.kind == 1 || la.kind == 25) {
+ if (la.kind == 1 || la.kind == 29) {
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
}
}
- Expect(12);
+ Expect(16);
}
void IteratorSpec(List<FrameExpression/*!*/>/*!*/ reads, List<FrameExpression/*!*/>/*!*/ mod, List<Expression/*!*/> decreases,
@@ -1268,8 +1296,8 @@ List<MaybeFreeExpression/*!*/>/*!*/ yieldReq, List<MaybeFreeExpression/*!*/>/*!*
ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) {
Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; bool isYield = false; Attributes ensAttrs = null;
- while (!(StartOf(12))) {SynErr(151); Get();}
- if (la.kind == 50) {
+ while (!(StartOf(12))) {SynErr(152); Get();}
+ if (la.kind == 11) {
Get();
while (IsAttribute()) {
Attribute(ref readsAttrs);
@@ -1277,15 +1305,15 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) {
if (StartOf(13)) {
FrameExpression(out fe);
reads.Add(fe);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
FrameExpression(out fe);
reads.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(152); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(153); Get();}
Expect(8);
- } else if (la.kind == 45) {
+ } else if (la.kind == 49) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
@@ -1293,70 +1321,70 @@ ref Attributes readsAttrs, ref Attributes modAttrs, ref Attributes decrAttrs) {
if (StartOf(13)) {
FrameExpression(out fe);
mod.Add(fe);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(153); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(154); Get();}
Expect(8);
} else if (StartOf(14)) {
- if (la.kind == 46) {
+ if (la.kind == 50) {
Get();
isFree = true;
}
- if (la.kind == 51) {
+ if (la.kind == 53) {
Get();
isYield = true;
}
- if (la.kind == 47) {
+ if (la.kind == 12) {
Get();
- Expression(out e, false);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(154); Get();}
+ Expression(out e, false, true);
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(155); Get();}
Expect(8);
if (isYield) {
- yieldReq.Add(new MaybeFreeExpression(e, isFree));
+ yieldReq.Add(new MaybeFreeExpression(e, isFree));
} else {
- req.Add(new MaybeFreeExpression(e, isFree));
+ req.Add(new MaybeFreeExpression(e, isFree));
}
- } else if (la.kind == 48) {
+ } else if (la.kind == 51) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
- Expression(out e, false);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(155); Get();}
+ Expression(out e, false, true);
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(156); Get();}
Expect(8);
if (isYield) {
- yieldEns.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
+ yieldEns.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
} else {
- ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
+ ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
}
- } else SynErr(156);
- } else if (la.kind == 49) {
+ } else SynErr(157);
+ } else if (la.kind == 52) {
Get();
while (IsAttribute()) {
Attribute(ref decrAttrs);
}
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(157); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(158); Get();}
Expect(8);
- } else SynErr(158);
+ } else SynErr(159);
}
void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
Contract.Ensures(Contract.ValueAtReturn(out block) != null);
List<Statement/*!*/> body = new List<Statement/*!*/>();
- Expect(9);
+ Expect(13);
bodyStart = t;
while (StartOf(15)) {
Stmt(body);
}
- Expect(10);
+ Expect(14);
bodyEnd = t;
block = new BlockStmt(bodyStart, bodyEnd, body);
}
@@ -1366,8 +1394,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Contract.Requires(cce.NonNullElements(req)); Contract.Requires(cce.NonNullElements(mod)); Contract.Requires(cce.NonNullElements(ens)); Contract.Requires(cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; Attributes ensAttrs = null;
- while (!(StartOf(16))) {SynErr(159); Get();}
- if (la.kind == 45) {
+ while (!(StartOf(16))) {SynErr(160); Get();}
+ if (la.kind == 49) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
@@ -1375,44 +1403,44 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (StartOf(13)) {
FrameExpression(out fe);
mod.Add(fe);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(160); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(161); Get();}
Expect(8);
- } else if (la.kind == 46 || la.kind == 47 || la.kind == 48) {
- if (la.kind == 46) {
+ } else if (la.kind == 12 || la.kind == 50 || la.kind == 51) {
+ if (la.kind == 50) {
Get();
isFree = true;
}
- if (la.kind == 47) {
+ if (la.kind == 12) {
Get();
- Expression(out e, false);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(161); Get();}
+ Expression(out e, false, true);
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(162); Get();}
Expect(8);
req.Add(new MaybeFreeExpression(e, isFree));
- } else if (la.kind == 48) {
+ } else if (la.kind == 51) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
- Expression(out e, false);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(162); Get();}
+ Expression(out e, false, true);
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(163); Get();}
Expect(8);
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
- } else SynErr(163);
- } else if (la.kind == 49) {
+ } else SynErr(164);
+ } else if (la.kind == 52) {
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, true);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(164); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(165); Get();}
Expect(8);
- } else SynErr(165);
+ } else SynErr(166);
}
void FrameExpression(out FrameExpression/*!*/ fe) {
@@ -1423,29 +1451,29 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
fe = null;
if (StartOf(17)) {
- Expression(out e, false);
+ Expression(out e, false, false);
feTok = e.tok;
- if (la.kind == 65) {
+ if (la.kind == 67) {
Get();
Ident(out id);
fieldName = id.val; feTok = id;
}
fe = new FrameExpression(feTok, e, fieldName);
- } else if (la.kind == 65) {
+ } else if (la.kind == 67) {
Get();
Ident(out id);
fieldName = id.val;
fe = new FrameExpression(id, new ImplicitThisExpr(id), fieldName);
- } else SynErr(166);
+ } else SynErr(167);
}
- void Expression(out Expression e, bool allowSemi) {
+ void Expression(out Expression e, bool allowSemi, bool allowLambda) {
Expression e0; IToken endTok;
- EquivExpression(out e, allowSemi);
+ EquivExpression(out e, allowSemi, allowLambda);
if (SemiFollowsCall(allowSemi, e)) {
Expect(8);
endTok = t;
- Expression(out e0, allowSemi);
+ Expression(out e0, allowSemi, allowLambda);
e = new StmtExpr(e.tok,
new UpdateStmt(e.tok, endTok, new List<Expression>(), new List<AssignmentRhs>() { new ExprRhs(e, null) }),
e0);
@@ -1462,7 +1490,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
decreases.Add(e);
}
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
PossiblyWildExpression(out e);
if (!allowWildcard && e is WildcardExpr) {
@@ -1476,15 +1504,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
void GenericInstantiation(List<Type/*!*/>/*!*/ gt) {
Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty;
- Expect(38);
+ Expect(42);
Type(out ty);
gt.Add(ty);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
Type(out ty);
gt.Add(ty);
}
- Expect(39);
+ Expect(43);
}
void ReferenceType(out IToken/*!*/ tok, out Type/*!*/ ty) {
@@ -1493,13 +1521,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<Type> gt;
List<IToken> path;
- if (la.kind == 60) {
+ if (la.kind == 62) {
Get();
tok = t; ty = new ObjectType();
} else if (la.kind == 5) {
Get();
tok = t; gt = new List<Type>();
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericInstantiation(gt);
}
int dims = tok.val.Length == 5 ? 1 : int.Parse(tok.val.Substring(5));
@@ -1509,16 +1537,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Ident(out tok);
gt = new List<Type>();
path = new List<IToken>();
- while (la.kind == 61) {
+ while (la.kind == 63) {
path.Add(tok);
Get();
Ident(out tok);
}
- if (la.kind == 38) {
+ if (la.kind == 42) {
GenericInstantiation(gt);
}
ty = new UserDefinedType(tok, tok.val, gt, path);
- } else SynErr(167);
+ } else SynErr(168);
}
void FunctionSpec(List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ reads, List<Expression/*!*/>/*!*/ ens, List<Expression/*!*/> decreases) {
@@ -1526,33 +1554,33 @@ 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 == 47) {
- while (!(la.kind == 0 || la.kind == 47)) {SynErr(168); Get();}
+ if (la.kind == 12) {
+ while (!(la.kind == 0 || la.kind == 12)) {SynErr(169); Get();}
Get();
- Expression(out e, false);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(169); Get();}
+ Expression(out e, false, true);
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(170); Get();}
Expect(8);
reqs.Add(e);
- } else if (la.kind == 50) {
+ } else if (la.kind == 11) {
Get();
if (StartOf(18)) {
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(170); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(171); Get();}
Expect(8);
- } else if (la.kind == 48) {
+ } else if (la.kind == 51) {
Get();
- Expression(out e, false);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(171); Get();}
+ Expression(out e, false, true);
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(172); Get();}
Expect(8);
ens.Add(e);
- } else if (la.kind == 49) {
+ } else if (la.kind == 52) {
Get();
if (decreases == null) {
SemErr(t, "'decreases' clauses are meaningless for copredicates, so they are not allowed");
@@ -1560,39 +1588,60 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(172); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(173); Get();}
Expect(8);
- } else SynErr(173);
+ } else SynErr(174);
}
void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); e = dummyExpr;
- Expect(9);
+ Expect(13);
bodyStart = t;
- Expression(out e, true);
- Expect(10);
+ Expression(out e, true, true);
+ Expect(14);
bodyEnd = t;
}
void PossiblyWildFrameExpression(out FrameExpression/*!*/ fe) {
Contract.Ensures(Contract.ValueAtReturn(out fe) != null); fe = dummyFrameExpr;
- if (la.kind == 13) {
+ if (la.kind == 17) {
Get();
fe = new FrameExpression(t, new WildcardExpr(t), null);
} else if (StartOf(13)) {
FrameExpression(out fe);
- } else SynErr(174);
+ } else SynErr(175);
+ }
+
+ void LambdaSpec(out Expression req, List<FrameExpression> reads) {
+ Contract.Requires(reads != null);
+ Expression e; req = null; FrameExpression fe;
+ while (la.kind == 11 || la.kind == 12) {
+ if (la.kind == 12) {
+ Get();
+ Expression(out e, false, false);
+ if (req == null) {
+ req = e;
+ } else {
+ req = new BinaryExpr(req.tok, BinaryExpr.Opcode.And, req, e);
+ }
+
+ } else {
+ Get();
+ PossiblyWildFrameExpression(out fe);
+ reads.Add(fe);
+ }
+ }
}
void PossiblyWildExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e)!=null);
e = dummyExpr;
- if (la.kind == 13) {
+ if (la.kind == 17) {
Get();
e = new WildcardExpr(t);
} else if (StartOf(17)) {
- Expression(out e, false);
- } else SynErr(175);
+ Expression(out e, false, false);
+ } else SynErr(176);
}
void Stmt(List<Statement/*!*/>/*!*/ ss) {
@@ -1609,58 +1658,58 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IToken bodyStart, bodyEnd;
int breakCount;
- while (!(StartOf(19))) {SynErr(176); Get();}
+ while (!(StartOf(19))) {SynErr(177); Get();}
switch (la.kind) {
- case 9: {
+ case 13: {
BlockStmt(out bs, out bodyStart, out bodyEnd);
s = bs;
break;
}
- case 83: {
+ case 84: {
AssertStmt(out s);
break;
}
- case 72: {
+ case 74: {
AssumeStmt(out s);
break;
}
- case 84: {
+ case 85: {
PrintStmt(out s);
break;
}
- case 1: case 2: case 3: case 4: case 11: case 29: case 54: case 55: case 113: case 114: case 115: case 116: case 117: case 118: {
+ case 1: case 2: case 3: case 4: case 15: case 33: case 56: case 57: case 114: case 115: case 116: case 117: case 118: case 119: {
UpdateStmt(out s);
break;
}
- case 25: case 30: {
+ case 29: case 34: {
VarDeclStatement(out s);
break;
}
- case 76: {
+ case 78: {
IfStmt(out s);
break;
}
- case 80: {
+ case 81: {
WhileStmt(out s);
break;
}
- case 82: {
+ case 83: {
MatchStmt(out s);
break;
}
- case 85: case 86: {
+ case 86: case 87: {
ForallStmt(out s);
break;
}
- case 88: {
+ case 89: {
CalcStmt(out s);
break;
}
- case 87: {
+ case 88: {
ModifyStmt(out s);
break;
}
- case 66: {
+ case 68: {
Get();
x = t;
NoUSIdent(out id);
@@ -1669,32 +1718,32 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
s.Labels = new LList<Label>(new Label(x, id.val), s.Labels);
break;
}
- case 67: {
+ case 69: {
Get();
x = t; breakCount = 1; label = null;
if (la.kind == 1) {
NoUSIdent(out id);
label = id.val;
- } else if (la.kind == 8 || la.kind == 67) {
- while (la.kind == 67) {
+ } else if (la.kind == 8 || la.kind == 69) {
+ while (la.kind == 69) {
Get();
breakCount++;
}
- } else SynErr(177);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(178); Get();}
+ } else SynErr(178);
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(179); Get();}
Expect(8);
s = label != null ? new BreakStmt(x, t, label) : new BreakStmt(x, t, breakCount);
break;
}
- case 51: case 70: {
+ case 53: case 72: {
ReturnStmt(out s);
break;
}
- case 37: {
+ case 41: {
SkeletonStmt(out s);
break;
}
- default: SynErr(179); break;
+ default: SynErr(180); break;
}
}
@@ -1703,17 +1752,17 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression e = dummyExpr; Attributes attrs = null;
IToken dotdotdot = null;
- Expect(83);
+ Expect(84);
x = t;
while (IsAttribute()) {
Attribute(ref attrs);
}
if (StartOf(17)) {
- Expression(out e, false);
- } else if (la.kind == 37) {
+ Expression(out e, false, true);
+ } else if (la.kind == 41) {
Get();
dotdotdot = t;
- } else SynErr(180);
+ } else SynErr(181);
Expect(8);
if (dotdotdot != null) {
s = new SkeletonStatement(new AssertStmt(x, t, new LiteralExpr(x, true), attrs), dotdotdot, null);
@@ -1728,17 +1777,17 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression e = dummyExpr; Attributes attrs = null;
IToken dotdotdot = null;
- Expect(72);
+ Expect(74);
x = t;
while (IsAttribute()) {
Attribute(ref attrs);
}
if (StartOf(17)) {
- Expression(out e, false);
- } else if (la.kind == 37) {
+ Expression(out e, false, true);
+ } else if (la.kind == 41) {
Get();
dotdotdot = t;
- } else SynErr(181);
+ } else SynErr(182);
Expect(8);
if (dotdotdot != null) {
s = new SkeletonStatement(new AssumeStmt(x, t, new LiteralExpr(x, true), attrs), dotdotdot, null);
@@ -1752,11 +1801,11 @@ 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(84);
+ Expect(85);
x = t;
AttributeArg(out arg, false);
args.Add(arg);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
AttributeArg(out arg, false);
args.Add(arg);
@@ -1777,44 +1826,44 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Lhs(out e);
x = e.tok;
- if (la.kind == 8 || la.kind == 9) {
- while (la.kind == 9) {
+ if (la.kind == 8 || la.kind == 13) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
Expect(8);
endTok = t; rhss.Add(new ExprRhs(e, attrs));
- } else if (la.kind == 31 || la.kind == 69 || la.kind == 71) {
+ } else if (la.kind == 35 || la.kind == 71 || la.kind == 73) {
lhss.Add(e); lhs0 = e;
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
Lhs(out e);
lhss.Add(e);
}
- if (la.kind == 69) {
+ if (la.kind == 71) {
Get();
x = t;
Rhs(out r, lhs0);
rhss.Add(r);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
Rhs(out r, lhs0);
rhss.Add(r);
}
- } else if (la.kind == 71) {
+ } else if (la.kind == 73) {
Get();
x = t;
- if (la.kind == 72) {
+ if (la.kind == 74) {
Get();
suchThatAssume = t;
}
- Expression(out suchThat, false);
- } else SynErr(182);
+ Expression(out suchThat, false, true);
+ } else SynErr(183);
Expect(8);
endTok = t;
} else if (la.kind == 7) {
Get();
SemErr(t, "invalid statement (did you forget the 'label' keyword?)");
- } else SynErr(183);
+ } else SynErr(184);
if (suchThat != null) {
s = new AssignSuchThatStmt(x, endTok, lhss, suchThat, suchThatAssume);
} else {
@@ -1838,34 +1887,34 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Attributes attrs = null;
IToken endTok;
- if (la.kind == 25) {
+ if (la.kind == 29) {
Get();
isGhost = true; x = t;
}
- Expect(30);
+ Expect(34);
if (!isGhost) { x = t; }
- while (la.kind == 9) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
LocalIdentTypeOptional(out d, isGhost);
lhss.Add(d); d.Attributes = attrs; attrs = null;
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
- while (la.kind == 9) {
+ while (la.kind == 13) {
Attribute(ref attrs);
}
LocalIdentTypeOptional(out d, isGhost);
lhss.Add(d); d.Attributes = attrs; attrs = null;
}
- if (la.kind == 69 || la.kind == 71) {
- if (la.kind == 69) {
+ if (la.kind == 71 || la.kind == 73) {
+ if (la.kind == 71) {
Get();
assignTok = t;
lhs0 = new IdentifierExpr(lhss[0].Tok, lhss[0].Name);
Rhs(out r, lhs0);
rhss.Add(r);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
Rhs(out r, lhs0);
rhss.Add(r);
@@ -1873,11 +1922,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
} else {
Get();
assignTok = t;
- if (la.kind == 72) {
+ if (la.kind == 74) {
Get();
suchThatAssume = t;
}
- Expression(out suchThat, false);
+ Expression(out suchThat, false, true);
}
}
Expect(8);
@@ -1913,7 +1962,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<GuardedAlternative> alternatives;
ifStmt = dummyStmt; // to please the compiler
- Expect(76);
+ Expect(78);
x = t;
if (IsAlternative()) {
AlternativeBlock(out alternatives, out endTok);
@@ -1927,15 +1976,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
BlockStmt(out thn, out bodyStart, out bodyEnd);
endTok = thn.EndTok;
- if (la.kind == 77) {
+ if (la.kind == 79) {
Get();
- if (la.kind == 76) {
+ if (la.kind == 78) {
IfStmt(out s);
els = s; endTok = s.EndTok;
- } else if (la.kind == 9) {
+ } else if (la.kind == 13) {
BlockStmt(out bs, out bodyStart, out bodyEnd);
els = bs; endTok = bs.EndTok;
- } else SynErr(184);
+ } else SynErr(185);
}
if (guardEllipsis != null) {
ifStmt = new SkeletonStatement(new IfStmt(x, endTok, guard, thn, els), guardEllipsis, null);
@@ -1943,7 +1992,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
ifStmt = new IfStmt(x, endTok, guard, thn, els);
}
- } else SynErr(185);
+ } else SynErr(186);
}
void WhileStmt(out Statement/*!*/ stmt) {
@@ -1959,7 +2008,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<GuardedAlternative> alternatives;
stmt = dummyStmt; // to please the compiler
- Expect(80);
+ Expect(81);
x = t;
if (IsLoopSpecOrAlternative()) {
LoopSpec(out invariants, out decreases, out mod, ref decAttrs, ref modAttrs);
@@ -1974,13 +2023,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
guardEllipsis = t;
}
LoopSpec(out invariants, out decreases, out mod, ref decAttrs, ref modAttrs);
- if (la.kind == 9) {
+ if (la.kind == 13) {
BlockStmt(out body, out bodyStart, out bodyEnd);
endTok = body.EndTok;
- } else if (la.kind == 37) {
+ } else if (la.kind == 41) {
Get();
bodyEllipsis = t; endTok = t;
- } else SynErr(186);
+ } else SynErr(187);
if (guardEllipsis != null || bodyEllipsis != null) {
if (mod != null) {
SemErr(mod[0].E.tok, "'modifies' clauses are not allowed on refining loops");
@@ -1996,7 +2045,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
stmt = new WhileStmt(x, endTok, guard, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), body);
}
- } else SynErr(187);
+ } else SynErr(188);
}
void MatchStmt(out Statement/*!*/ s) {
@@ -2005,22 +2054,22 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<MatchCaseStmt/*!*/> cases = new List<MatchCaseStmt/*!*/>();
bool usesOptionalBrace = false;
- Expect(82);
+ Expect(83);
x = t;
- Expression(out e, true);
- if (la.kind == 9) {
+ Expression(out e, true, true);
+ if (la.kind == 13) {
Get();
usesOptionalBrace = true;
}
- while (la.kind == 78) {
+ while (la.kind == 80) {
CaseStatement(out c);
cases.Add(c);
}
if (CloseOptionalBrace(usesOptionalBrace)) {
- Expect(10);
+ Expect(14);
} else if (StartOf(22)) {
if (usesOptionalBrace) { SemErr(t, "expecting close curly brace"); }
- } else SynErr(188);
+ } else SynErr(189);
s = new MatchStmt(x, t, e, cases, usesOptionalBrace);
}
@@ -2038,16 +2087,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IToken bodyStart, bodyEnd;
IToken tok = Token.NoToken;
- if (la.kind == 85) {
+ if (la.kind == 86) {
Get();
x = t; tok = x;
- } else if (la.kind == 86) {
+ } else if (la.kind == 87) {
Get();
x = t;
errors.Warning(t, "the 'parallel' keyword has been deprecated; the comprehension statement now uses the keyword 'forall' (and the parentheses around the bound variables are now optional)");
- } else SynErr(189);
- if (la.kind == 11) {
+ } else SynErr(190);
+ if (la.kind == 15) {
Get();
usesOptionalParen = true;
}
@@ -2061,23 +2110,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (range == null) { range = new LiteralExpr(x, true); }
if (CloseOptionalParen(usesOptionalParen)) {
- Expect(12);
+ Expect(16);
} else if (StartOf(23)) {
if (usesOptionalParen) { SemErr(t, "expecting close parenthesis"); }
- } else SynErr(190);
- while (la.kind == 46 || la.kind == 48) {
+ } else SynErr(191);
+ while (la.kind == 50 || la.kind == 51) {
isFree = false;
- if (la.kind == 46) {
+ if (la.kind == 50) {
Get();
isFree = true;
}
- Expect(48);
- Expression(out e, false);
+ Expect(51);
+ Expression(out e, false, true);
ens.Add(new MaybeFreeExpression(e, isFree));
Expect(8);
tok = t;
}
- if (la.kind == 9) {
+ if (la.kind == 13) {
BlockStmt(out block, out bodyStart, out bodyEnd);
}
if (DafnyOptions.O.DisallowSoundnessCheating && block == null && 0 < ens.Count) {
@@ -2105,7 +2154,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IToken opTok;
IToken danglingOperator = null;
- Expect(88);
+ Expect(89);
x = t;
if (StartOf(24)) {
CalcOp(out opTok, out calcOp);
@@ -2116,9 +2165,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
resOp = calcOp;
}
- Expect(9);
+ Expect(13);
while (StartOf(17)) {
- Expression(out e, false);
+ Expression(out e, false, true);
lines.Add(e); stepOp = calcOp; danglingOperator = null;
Expect(8);
if (StartOf(24)) {
@@ -2139,7 +2188,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (h.Body.Count != 0) { danglingOperator = null; }
}
- Expect(10);
+ Expect(14);
if (danglingOperator != null) {
SemErr(danglingOperator, "a calculation cannot end with an operator");
}
@@ -2158,7 +2207,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
BlockStmt body = null; IToken bodyStart;
IToken ellipsisToken = null;
- Expect(87);
+ Expect(88);
tok = t;
while (IsAttribute()) {
Attribute(ref attrs);
@@ -2167,7 +2216,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (StartOf(13)) {
FrameExpression(out fe);
mod.Add(fe);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
FrameExpression(out fe);
mod.Add(fe);
@@ -2177,13 +2226,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
ellipsisToken = t;
}
}
- if (la.kind == 9) {
+ if (la.kind == 13) {
BlockStmt(out body, out bodyStart, out endTok);
} else if (la.kind == 8) {
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(191); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(192); Get();}
Get();
endTok = t;
- } else SynErr(192);
+ } else SynErr(193);
s = new ModifyStmt(tok, endTok, mod, attrs, body);
if (ellipsisToken != null) {
s = new SkeletonStatement(s, ellipsisToken, null);
@@ -2197,17 +2246,17 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
AssignmentRhs r;
bool isYield = false;
- if (la.kind == 70) {
+ if (la.kind == 72) {
Get();
returnTok = t;
- } else if (la.kind == 51) {
+ } else if (la.kind == 53) {
Get();
returnTok = t; isYield = true;
- } else SynErr(193);
+ } else SynErr(194);
if (StartOf(26)) {
Rhs(out r, null);
rhss = new List<AssignmentRhs>(); rhss.Add(r);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
Rhs(out r, null);
rhss.Add(r);
@@ -2227,24 +2276,24 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<Expression> exprs = null;
IToken tok, dotdotdot, whereTok;
Expression e;
- Expect(37);
+ Expect(41);
dotdotdot = t;
- if (la.kind == 68) {
+ if (la.kind == 70) {
Get();
names = new List<IToken>(); exprs = new List<Expression>(); whereTok = t;
Ident(out tok);
names.Add(tok);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
Ident(out tok);
names.Add(tok);
}
- Expect(69);
- Expression(out e, false);
+ Expect(71);
+ Expression(out e, false, true);
exprs.Add(e);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
- Expression(out e, false);
+ Expression(out e, false, true);
exprs.Add(e);
}
if (exprs.Count != names.Count) {
@@ -2266,29 +2315,29 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
r = dummyRhs; // to please compiler
Attributes attrs = null;
- if (la.kind == 73) {
+ if (la.kind == 75) {
Get();
newToken = t;
TypeAndToken(out x, out ty);
- if (la.kind == 11 || la.kind == 61 || la.kind == 74) {
- if (la.kind == 74) {
+ if (la.kind == 15 || la.kind == 63 || la.kind == 76) {
+ if (la.kind == 76) {
Get();
ee = new List<Expression>();
Expressions(ee);
- Expect(75);
+ Expect(77);
var tmp = theBuiltIns.ArrayType(ee.Count, new IntType(), true);
} else {
x = null; args = new List<Expression/*!*/>();
- if (la.kind == 61) {
+ if (la.kind == 63) {
Get();
Ident(out x);
}
- Expect(11);
+ Expect(15);
if (StartOf(17)) {
Expressions(args);
}
- Expect(12);
+ Expect(16);
}
}
if (ee != null) {
@@ -2299,14 +2348,14 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
r = new TypeRhs(newToken, ty);
}
- } else if (la.kind == 13) {
+ } else if (la.kind == 17) {
Get();
r = new HavocRhs(t);
} else if (StartOf(17)) {
- Expression(out e, false);
+ Expression(out e, false, true);
r = new ExprRhs(e);
- } else SynErr(194);
- while (la.kind == 9) {
+ } else SynErr(195);
+ while (la.kind == 13) {
Attribute(ref attrs);
}
r.Attributes = attrs;
@@ -2316,26 +2365,27 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = dummyExpr; // the assignment is to please the compiler, the dummy value to satisfy contracts in the event of a parse error
if (la.kind == 1) {
- DottedIdentifiersAndFunction(out e);
- while (la.kind == 61 || la.kind == 74) {
+ DottedIdentifiersAndFunction(out e, false, false);
+ while (la.kind == 63 || la.kind == 76) {
Suffix(ref e);
}
+ ApplySuffix(ref e);
} else if (StartOf(27)) {
- ConstAtomExpression(out e);
+ ConstAtomExpression(out e, false, false);
Suffix(ref e);
- while (la.kind == 61 || la.kind == 74) {
+ while (la.kind == 63 || la.kind == 76) {
Suffix(ref e);
}
- } else SynErr(195);
+ } else SynErr(196);
}
void Expressions(List<Expression/*!*/>/*!*/ args) {
Contract.Requires(cce.NonNullElements(args)); Expression/*!*/ e;
- Expression(out e, true);
+ Expression(out e, true, true);
args.Add(e);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
- Expression(out e, true);
+ Expression(out e, true, true);
args.Add(e);
}
}
@@ -2346,36 +2396,36 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression e;
List<Statement> body;
- Expect(9);
- while (la.kind == 78) {
+ Expect(13);
+ while (la.kind == 80) {
Get();
x = t;
- Expression(out e, true);
- Expect(79);
+ Expression(out e, true, false);
+ Expect(9);
body = new List<Statement>();
while (StartOf(15)) {
Stmt(body);
}
alternatives.Add(new GuardedAlternative(x, e, body));
}
- Expect(10);
+ Expect(14);
endTok = t;
}
void Guard(out Expression e) {
Expression/*!*/ ee; e = null;
- if (la.kind == 13) {
+ if (la.kind == 17) {
Get();
e = null;
} else if (IsParenStar()) {
- Expect(11);
- Expect(13);
- Expect(12);
+ Expect(15);
+ Expect(17);
+ Expect(16);
e = null;
} else if (StartOf(17)) {
- Expression(out ee, true);
+ Expression(out ee, true, true);
e = ee;
- } else SynErr(196);
+ } else SynErr(197);
}
void LoopSpec(out List<MaybeFreeExpression/*!*/> invariants, out List<Expression/*!*/> decreases, out List<FrameExpression/*!*/> mod, ref Attributes decAttrs, ref Attributes modAttrs) {
@@ -2386,22 +2436,22 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
mod = null;
while (StartOf(28)) {
- if (la.kind == 46 || la.kind == 81) {
+ if (la.kind == 50 || la.kind == 82) {
Invariant(out invariant);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(197); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(198); Get();}
Expect(8);
invariants.Add(invariant);
- } else if (la.kind == 49) {
- while (!(la.kind == 0 || la.kind == 49)) {SynErr(198); Get();}
+ } else if (la.kind == 52) {
+ while (!(la.kind == 0 || la.kind == 52)) {SynErr(199); Get();}
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, true);
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(199); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(200); Get();}
Expect(8);
} else {
- while (!(la.kind == 0 || la.kind == 45)) {SynErr(200); Get();}
+ while (!(la.kind == 0 || la.kind == 49)) {SynErr(201); Get();}
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
@@ -2410,13 +2460,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (StartOf(13)) {
FrameExpression(out fe);
mod.Add(fe);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 8)) {SynErr(201); Get();}
+ while (!(la.kind == 0 || la.kind == 8)) {SynErr(202); Get();}
Expect(8);
}
}
@@ -2424,16 +2474,16 @@ 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 == 46 || la.kind == 81)) {SynErr(202); Get();}
- if (la.kind == 46) {
+ while (!(la.kind == 0 || la.kind == 50 || la.kind == 82)) {SynErr(203); Get();}
+ if (la.kind == 50) {
Get();
isFree = true;
}
- Expect(81);
+ Expect(82);
while (IsAttribute()) {
Attribute(ref attrs);
}
- Expression(out e, false);
+ Expression(out e, false, true);
invariant = new MaybeFreeExpression(e, isFree, attrs);
}
@@ -2444,21 +2494,21 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
BoundVar/*!*/ bv;
List<Statement/*!*/> body = new List<Statement/*!*/>();
- Expect(78);
+ Expect(80);
x = t;
Ident(out id);
- if (la.kind == 11) {
+ if (la.kind == 15) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
}
- Expect(12);
+ Expect(16);
}
- Expect(79);
+ Expect(9);
while (StartOf(15)) {
Stmt(body);
}
@@ -2471,9 +2521,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Get();
arg = new Attributes.Argument(t, t.val.Substring(1, t.val.Length-2));
} else if (StartOf(17)) {
- Expression(out e, allowSemi);
+ Expression(out e, allowSemi, true);
arg = new Attributes.Argument(t, e);
- } else SynErr(203);
+ } else SynErr(204);
}
void QuantifierDomain(out List<BoundVar> bvars, out Attributes attrs, out Expression range) {
@@ -2484,7 +2534,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IdentTypeOptional(out bv);
bvars.Add(bv);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
IdentTypeOptional(out bv);
bvars.Add(bv);
@@ -2492,9 +2542,9 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
while (IsAttribute()) {
Attribute(ref attrs);
}
- if (la.kind == 29) {
+ if (la.kind == 33) {
Get();
- Expression(out range, true);
+ Expression(out range, true, true);
}
}
@@ -2504,73 +2554,73 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
x = null;
switch (la.kind) {
- case 33: {
+ case 37: {
Get();
x = t; binOp = BinaryExpr.Opcode.Eq;
- if (la.kind == 89) {
+ if (la.kind == 90) {
Get();
- Expect(74);
- Expression(out k, true);
- Expect(75);
+ Expect(76);
+ Expression(out k, true, true);
+ Expect(77);
}
break;
}
- case 38: {
+ case 42: {
Get();
x = t; binOp = BinaryExpr.Opcode.Lt;
break;
}
- case 39: {
+ case 43: {
Get();
x = t; binOp = BinaryExpr.Opcode.Gt;
break;
}
- case 90: {
+ case 91: {
Get();
x = t; binOp = BinaryExpr.Opcode.Le;
break;
}
- case 91: {
+ case 92: {
Get();
x = t; binOp = BinaryExpr.Opcode.Ge;
break;
}
- case 92: {
+ case 93: {
Get();
x = t; binOp = BinaryExpr.Opcode.Neq;
break;
}
- case 93: {
+ case 94: {
Get();
x = t; binOp = BinaryExpr.Opcode.Neq;
break;
}
- case 94: {
+ case 95: {
Get();
x = t; binOp = BinaryExpr.Opcode.Le;
break;
}
- case 95: {
+ case 96: {
Get();
x = t; binOp = BinaryExpr.Opcode.Ge;
break;
}
- case 96: case 97: {
+ case 97: case 98: {
EquivOp();
x = t; binOp = BinaryExpr.Opcode.Iff;
break;
}
- case 98: case 99: {
+ case 99: case 100: {
ImpliesOp();
x = t; binOp = BinaryExpr.Opcode.Imp;
break;
}
- case 100: case 101: {
+ case 101: case 102: {
ExpliesOp();
x = t; binOp = BinaryExpr.Opcode.Exp;
break;
}
- default: SynErr(204); break;
+ default: SynErr(205); break;
}
if (k == null) {
op = new Microsoft.Dafny.CalcStmt.BinaryCalcOp(binOp);
@@ -2589,8 +2639,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Token x = la;
IToken endTok = x;
- while (la.kind == 9 || la.kind == 88) {
- if (la.kind == 9) {
+ while (la.kind == 13 || la.kind == 89) {
+ if (la.kind == 13) {
BlockStmt(out block, out bodyStart, out bodyEnd);
endTok = block.EndTok; subhints.Add(block);
} else {
@@ -2603,106 +2653,106 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
void EquivOp() {
- if (la.kind == 96) {
+ if (la.kind == 97) {
Get();
- } else if (la.kind == 97) {
+ } else if (la.kind == 98) {
Get();
- } else SynErr(205);
+ } else SynErr(206);
}
void ImpliesOp() {
- if (la.kind == 98) {
+ if (la.kind == 99) {
Get();
- } else if (la.kind == 99) {
+ } else if (la.kind == 100) {
Get();
- } else SynErr(206);
+ } else SynErr(207);
}
void ExpliesOp() {
- if (la.kind == 100) {
+ if (la.kind == 101) {
Get();
- } else if (la.kind == 101) {
+ } else if (la.kind == 102) {
Get();
- } else SynErr(207);
+ } else SynErr(208);
}
- void EquivExpression(out Expression e0, bool allowSemi) {
+ void EquivExpression(out Expression e0, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
- ImpliesExpliesExpression(out e0, allowSemi);
- while (la.kind == 96 || la.kind == 97) {
+ ImpliesExpliesExpression(out e0, allowSemi, allowLambda);
+ while (la.kind == 97 || la.kind == 98) {
EquivOp();
x = t;
- ImpliesExpliesExpression(out e1, allowSemi);
+ ImpliesExpliesExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Iff, e0, e1);
}
}
- void ImpliesExpliesExpression(out Expression e0, bool allowSemi) {
+ void ImpliesExpliesExpression(out Expression e0, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
- LogicalExpression(out e0, allowSemi);
+ LogicalExpression(out e0, allowSemi, allowLambda);
if (StartOf(29)) {
- if (la.kind == 98 || la.kind == 99) {
+ if (la.kind == 99 || la.kind == 100) {
ImpliesOp();
x = t;
- ImpliesExpression(out e1, allowSemi);
+ ImpliesExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1);
} else {
ExpliesOp();
x = t;
- LogicalExpression(out e1, allowSemi);
+ LogicalExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e0, e1);
- while (la.kind == 100 || la.kind == 101) {
+ while (la.kind == 101 || la.kind == 102) {
ExpliesOp();
x = t;
- LogicalExpression(out e1, allowSemi);
+ LogicalExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e0, e1);
}
}
}
}
- void LogicalExpression(out Expression e0, bool allowSemi) {
+ void LogicalExpression(out Expression e0, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
- RelationalExpression(out e0, allowSemi);
+ RelationalExpression(out e0, allowSemi, allowLambda);
if (StartOf(30)) {
- if (la.kind == 102 || la.kind == 103) {
+ if (la.kind == 103 || la.kind == 104) {
AndOp();
x = t;
- RelationalExpression(out e1, allowSemi);
+ RelationalExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1);
- while (la.kind == 102 || la.kind == 103) {
+ while (la.kind == 103 || la.kind == 104) {
AndOp();
x = t;
- RelationalExpression(out e1, allowSemi);
+ RelationalExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1);
}
} else {
OrOp();
x = t;
- RelationalExpression(out e1, allowSemi);
+ RelationalExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1);
- while (la.kind == 104 || la.kind == 105) {
+ while (la.kind == 105 || la.kind == 106) {
OrOp();
x = t;
- RelationalExpression(out e1, allowSemi);
+ RelationalExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1);
}
}
}
}
- void ImpliesExpression(out Expression e0, bool allowSemi) {
+ void ImpliesExpression(out Expression e0, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
- LogicalExpression(out e0, allowSemi);
- if (la.kind == 98 || la.kind == 99) {
+ LogicalExpression(out e0, allowSemi, allowLambda);
+ if (la.kind == 99 || la.kind == 100) {
ImpliesOp();
x = t;
- ImpliesExpression(out e1, allowSemi);
+ ImpliesExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1);
}
}
- void RelationalExpression(out Expression e, bool allowSemi) {
+ void RelationalExpression(out Expression e, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null);
IToken x, firstOpTok = null; Expression e0, e1, acc = null; BinaryExpr.Opcode op;
List<Expression> chain = null;
@@ -2716,12 +2766,12 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
// 4 ("disjoint") indicates chain of disjoint set operators
bool hasSeenNeq = false;
- Term(out e0, allowSemi);
+ Term(out e0, allowSemi, allowLambda);
e = e0;
if (StartOf(31)) {
RelOp(out x, out op, out k);
firstOpTok = x;
- Term(out e1, allowSemi);
+ Term(out e1, allowSemi, allowLambda);
if (k == null) {
e = new BinaryExpr(x, op, e0, e1);
if (op == BinaryExpr.Opcode.Disjoint)
@@ -2783,7 +2833,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
kind = 3; break;
}
- Term(out e1, allowSemi);
+ Term(out e1, allowSemi, allowLambda);
ops.Add(op); prefixLimits.Add(k); chain.Add(e1);
if (k != null) {
Contract.Assert(op == BinaryExpr.Opcode.Eq || op == BinaryExpr.Opcode.Neq);
@@ -2804,27 +2854,27 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
void AndOp() {
- if (la.kind == 102) {
+ if (la.kind == 103) {
Get();
- } else if (la.kind == 103) {
+ } else if (la.kind == 104) {
Get();
- } else SynErr(208);
+ } else SynErr(209);
}
void OrOp() {
- if (la.kind == 104) {
+ if (la.kind == 105) {
Get();
- } else if (la.kind == 105) {
+ } else if (la.kind == 106) {
Get();
- } else SynErr(209);
+ } else SynErr(210);
}
- void Term(out Expression e0, bool allowSemi) {
+ void Term(out Expression e0, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op;
- Factor(out e0, allowSemi);
- while (la.kind == 108 || la.kind == 109) {
+ Factor(out e0, allowSemi, allowLambda);
+ while (la.kind == 109 || la.kind == 110) {
AddOp(out x, out op);
- Factor(out e1, allowSemi);
+ Factor(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, op, e0, e1);
}
}
@@ -2836,62 +2886,62 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
k = null;
switch (la.kind) {
- case 33: {
+ case 37: {
Get();
x = t; op = BinaryExpr.Opcode.Eq;
- if (la.kind == 89) {
+ if (la.kind == 90) {
Get();
- Expect(74);
- Expression(out k, true);
- Expect(75);
+ Expect(76);
+ Expression(out k, true, true);
+ Expect(77);
}
break;
}
- case 38: {
+ case 42: {
Get();
x = t; op = BinaryExpr.Opcode.Lt;
break;
}
- case 39: {
+ case 43: {
Get();
x = t; op = BinaryExpr.Opcode.Gt;
break;
}
- case 90: {
+ case 91: {
Get();
x = t; op = BinaryExpr.Opcode.Le;
break;
}
- case 91: {
+ case 92: {
Get();
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- case 92: {
+ case 93: {
Get();
x = t; op = BinaryExpr.Opcode.Neq;
- if (la.kind == 89) {
+ if (la.kind == 90) {
Get();
- Expect(74);
- Expression(out k, true);
- Expect(75);
+ Expect(76);
+ Expression(out k, true, true);
+ Expect(77);
}
break;
}
- case 106: {
+ case 107: {
Get();
x = t; op = BinaryExpr.Opcode.In;
break;
}
- case 14: {
+ case 18: {
Get();
x = t; op = BinaryExpr.Opcode.NotIn;
break;
}
- case 107: {
+ case 108: {
Get();
x = t; y = Token.NoToken;
- if (la.kind == 107) {
+ if (la.kind == 108) {
Get();
y = t;
}
@@ -2906,215 +2956,243 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
break;
}
- case 93: {
+ case 94: {
Get();
x = t; op = BinaryExpr.Opcode.Neq;
break;
}
- case 94: {
+ case 95: {
Get();
x = t; op = BinaryExpr.Opcode.Le;
break;
}
- case 95: {
+ case 96: {
Get();
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- default: SynErr(210); break;
+ default: SynErr(211); break;
}
}
- void Factor(out Expression e0, bool allowSemi) {
+ void Factor(out Expression e0, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op;
- UnaryExpression(out e0, allowSemi);
- while (la.kind == 13 || la.kind == 110 || la.kind == 111) {
+ UnaryExpression(out e0, allowSemi, allowLambda);
+ while (la.kind == 17 || la.kind == 111 || la.kind == 112) {
MulOp(out x, out op);
- UnaryExpression(out e1, allowSemi);
+ UnaryExpression(out e1, allowSemi, allowLambda);
e0 = new BinaryExpr(x, op, e0, e1);
}
}
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 == 108) {
+ if (la.kind == 109) {
Get();
x = t; op = BinaryExpr.Opcode.Add;
- } else if (la.kind == 109) {
+ } else if (la.kind == 110) {
Get();
x = t; op = BinaryExpr.Opcode.Sub;
- } else SynErr(211);
+ } else SynErr(212);
}
- void UnaryExpression(out Expression e, bool allowSemi) {
+ void UnaryExpression(out Expression e, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; e = dummyExpr;
switch (la.kind) {
- case 109: {
+ case 110: {
Get();
x = t;
- UnaryExpression(out e, allowSemi);
+ UnaryExpression(out e, allowSemi, allowLambda);
e = new NegationExpression(x, e);
break;
}
- case 107: case 112: {
+ case 108: case 113: {
NegOp();
x = t;
- UnaryExpression(out e, allowSemi);
+ UnaryExpression(out e, allowSemi, allowLambda);
e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Not, e);
break;
}
- case 25: case 30: case 56: case 66: case 72: case 76: case 82: case 83: case 85: case 88: case 121: case 122: case 123: {
- EndlessExpression(out e, allowSemi);
+ case 29: case 34: case 58: case 68: case 74: case 78: case 83: case 84: case 86: case 89: case 122: case 123: case 124: {
+ EndlessExpression(out e, allowSemi, allowLambda);
break;
}
case 1: {
- DottedIdentifiersAndFunction(out e);
- while (la.kind == 61 || la.kind == 74) {
+ DottedIdentifiersAndFunction(out e, allowSemi, allowLambda);
+ while (la.kind == 63 || la.kind == 76) {
Suffix(ref e);
}
+ ApplySuffix(ref e);
break;
}
- case 9: case 74: {
+ case 13: case 76: {
DisplayExpr(out e);
- while (la.kind == 61 || la.kind == 74) {
+ while (la.kind == 63 || la.kind == 76) {
Suffix(ref e);
}
break;
}
- case 57: {
+ case 59: {
MultiSetExpr(out e);
- while (la.kind == 61 || la.kind == 74) {
+ while (la.kind == 63 || la.kind == 76) {
Suffix(ref e);
}
break;
}
- case 59: {
+ case 61: {
Get();
x = t;
- if (la.kind == 74) {
+ if (la.kind == 76) {
MapDisplayExpr(x, out e);
- while (la.kind == 61 || la.kind == 74) {
+ while (la.kind == 63 || la.kind == 76) {
Suffix(ref e);
}
} else if (la.kind == 1) {
MapComprehensionExpr(x, out e, allowSemi);
} else if (StartOf(32)) {
SemErr("map must be followed by literal in brackets or comprehension.");
- } else SynErr(212);
+ } else SynErr(213);
break;
}
- case 2: case 3: case 4: case 11: case 29: case 54: case 55: case 113: case 114: case 115: case 116: case 117: case 118: {
- ConstAtomExpression(out e);
- while (la.kind == 61 || la.kind == 74) {
+ case 2: case 3: case 4: case 15: case 33: case 56: case 57: case 114: case 115: case 116: case 117: case 118: case 119: {
+ ConstAtomExpression(out e, allowSemi, allowLambda);
+ while (la.kind == 63 || la.kind == 76) {
Suffix(ref e);
}
break;
}
- default: SynErr(213); break;
+ default: SynErr(214); 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 == 13) {
+ if (la.kind == 17) {
Get();
x = t; op = BinaryExpr.Opcode.Mul;
- } else if (la.kind == 110) {
+ } else if (la.kind == 111) {
Get();
x = t; op = BinaryExpr.Opcode.Div;
- } else if (la.kind == 111) {
+ } else if (la.kind == 112) {
Get();
x = t; op = BinaryExpr.Opcode.Mod;
- } else SynErr(214);
+ } else SynErr(215);
}
void NegOp() {
- if (la.kind == 107) {
+ if (la.kind == 108) {
Get();
- } else if (la.kind == 112) {
+ } else if (la.kind == 113) {
Get();
- } else SynErr(215);
+ } else SynErr(216);
}
- void EndlessExpression(out Expression e, bool allowSemi) {
+ void EndlessExpression(out Expression e, bool allowSemi, bool allowLambda) {
IToken/*!*/ x;
Expression e0, e1;
Statement s;
e = dummyExpr;
switch (la.kind) {
- case 76: {
+ case 78: {
Get();
x = t;
- Expression(out e, true);
- Expect(119);
- Expression(out e0, true);
- Expect(77);
- Expression(out e1, allowSemi);
+ Expression(out e, true, true);
+ Expect(120);
+ Expression(out e0, true, true);
+ Expect(79);
+ Expression(out e1, allowSemi, allowLambda);
e = new ITEExpr(x, e, e0, e1);
break;
}
- case 82: {
- MatchExpression(out e, allowSemi);
+ case 83: {
+ MatchExpression(out e, allowSemi, allowLambda);
break;
}
- case 85: case 121: case 122: case 123: {
- QuantifierGuts(out e, allowSemi);
+ case 86: case 122: case 123: case 124: {
+ QuantifierGuts(out e, allowSemi, allowLambda);
break;
}
- case 56: {
- ComprehensionExpr(out e, allowSemi);
+ case 58: {
+ ComprehensionExpr(out e, allowSemi, allowLambda);
break;
}
- case 72: case 83: case 88: {
+ case 74: case 84: case 89: {
StmtInExpr(out s);
- Expression(out e, allowSemi);
+ Expression(out e, allowSemi, allowLambda);
e = new StmtExpr(s.Tok, s, e);
break;
}
- case 25: case 30: {
- LetExpr(out e, allowSemi);
+ case 29: case 34: {
+ LetExpr(out e, allowSemi, allowLambda);
break;
}
- case 66: {
- NamedExpr(out e, allowSemi);
+ case 68: {
+ NamedExpr(out e, allowSemi, allowLambda);
break;
}
- default: SynErr(216); break;
+ default: SynErr(217); break;
}
}
- void DottedIdentifiersAndFunction(out Expression e) {
+ void DottedIdentifiersAndFunction(out Expression e, bool allowSemi, bool allowLambda) {
IToken id, idPrime; IToken openParen = null;
List<Expression> args = null;
List<IToken> idents = new List<IToken>();
+ e = null;
+ var applyArgLists = new List<List<Expression>>();
Ident(out id);
idents.Add(id);
- while (la.kind == 61) {
+ while (la.kind == 63) {
IdentOrDigitsSuffix(out id, out idPrime);
idents.Add(id);
if (idPrime != null) { idents.Add(idPrime); id = idPrime; }
}
- if (la.kind == 11 || la.kind == 89) {
+ if (la.kind == 15 || la.kind == 90) {
args = new List<Expression>();
- if (la.kind == 89) {
+ if (la.kind == 90) {
Get();
id.val = id.val + "#"; Expression k;
- Expect(74);
- Expression(out k, true);
- Expect(75);
+ Expect(76);
+ Expression(out k, true, true);
+ Expect(77);
args.Add(k);
}
- Expect(11);
+ Expect(15);
openParen = t;
if (StartOf(17)) {
Expressions(args);
}
- Expect(12);
+ Expect(16);
}
- e = new IdentifierSequence(idents, openParen, args);
+ if (IsLambda(allowLambda)) {
+ Expression body = null;
+ Expression req = null;
+ bool oneShot;
+ var reads = new List<FrameExpression>();
+
+ LambdaSpec(out req, reads);
+ LambdaArrow(out oneShot);
+ Expression(out body, allowSemi, true);
+ if (idents.Count != 1) {
+ SemErr(id, "Invalid variable binding in lambda.");
+ }
+ if (args != null) {
+ SemErr(openParen, "Expected variable binding.");
+ }
+ BoundVar bv = new BoundVar(id, id.val, new InferredTypeProxy());
+ e = new LambdaExpr(id, oneShot, new List<BoundVar>{ bv }, req, reads, body);
+
+ }
+ if (e == null) {
+ e = new IdentifierSequence(idents, openParen, args);
+ foreach (var args_ in applyArgLists) {
+ e = new ApplyExpr(id, openParen, e, args_);
+ }
+ }
+
}
void Suffix(ref Expression e) {
@@ -3123,7 +3201,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<Expression> multipleIndices = null;
bool func = false;
- if (la.kind == 61) {
+ if (la.kind == 63) {
IdentOrDigitsSuffix(out id, out x);
if (x != null) {
// process id as a Suffix in its own right
@@ -3131,43 +3209,43 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
id = x; // move to the next Suffix
}
- if (la.kind == 11 || la.kind == 89) {
+ if (la.kind == 15 || la.kind == 90) {
args = new List<Expression/*!*/>(); func = true;
- if (la.kind == 89) {
+ if (la.kind == 90) {
Get();
id.val = id.val + "#"; Expression k;
- Expect(74);
- Expression(out k, true);
- Expect(75);
+ Expect(76);
+ Expression(out k, true, true);
+ Expect(77);
args.Add(k);
}
- Expect(11);
+ Expect(15);
IToken openParen = t;
if (StartOf(17)) {
Expressions(args);
}
- Expect(12);
+ Expect(16);
e = new FunctionCallExpr(id, id.val, e, openParen, args);
}
if (!func) { e = new ExprDotName(id, e, id.val); }
- } else if (la.kind == 74) {
+ } else if (la.kind == 76) {
Get();
x = t;
if (StartOf(17)) {
- Expression(out ee, true);
+ Expression(out ee, true, true);
e0 = ee;
- if (la.kind == 120) {
+ if (la.kind == 121) {
Get();
anyDots = true;
if (StartOf(17)) {
- Expression(out ee, true);
+ Expression(out ee, true, true);
e1 = ee;
}
- } else if (la.kind == 69) {
+ } else if (la.kind == 71) {
Get();
- Expression(out ee, true);
+ Expression(out ee, true, true);
e1 = ee;
- } else if (la.kind == 7 || la.kind == 75) {
+ } else if (la.kind == 7 || la.kind == 77) {
while (la.kind == 7) {
Get();
if (multipleLengths == null) {
@@ -3177,32 +3255,32 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
takeRest = true;
if (StartOf(17)) {
- Expression(out ee, true);
+ Expression(out ee, true, true);
multipleLengths.Add(ee);
takeRest = false;
}
}
- } else if (la.kind == 31 || la.kind == 75) {
- while (la.kind == 31) {
+ } else if (la.kind == 35 || la.kind == 77) {
+ while (la.kind == 35) {
Get();
- Expression(out ee, true);
+ Expression(out ee, true, true);
if (multipleIndices == null) {
- multipleIndices = new List<Expression>();
- multipleIndices.Add(e0);
+ multipleIndices = new List<Expression>();
+ multipleIndices.Add(e0);
}
multipleIndices.Add(ee);
}
- } else SynErr(217);
- } else if (la.kind == 120) {
+ } else SynErr(218);
+ } else if (la.kind == 121) {
Get();
anyDots = true;
if (StartOf(17)) {
- Expression(out ee, true);
+ Expression(out ee, true, true);
e1 = ee;
}
- } else SynErr(218);
+ } else SynErr(219);
if (multipleIndices != null) {
e = new MultiSelectExpr(x, e, multipleIndices);
// make sure an array class with this dimensionality exists
@@ -3242,8 +3320,21 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
}
- Expect(75);
- } else SynErr(219);
+ Expect(77);
+ } else SynErr(220);
+ ApplySuffix(ref e);
+ }
+
+ void ApplySuffix(ref Expression e) {
+ while (la.kind == 15) {
+ Get();
+ IToken openParen = t; var args = new List<Expression>();
+ if (StartOf(17)) {
+ Expressions(args);
+ }
+ Expect(16);
+ e = new ApplyExpr(e.tok, openParen, e, args);
+ }
}
void DisplayExpr(out Expression e) {
@@ -3251,23 +3342,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IToken/*!*/ x = null; List<Expression/*!*/>/*!*/ elements;
e = dummyExpr;
- if (la.kind == 9) {
+ if (la.kind == 13) {
Get();
x = t; elements = new List<Expression/*!*/>();
if (StartOf(17)) {
Expressions(elements);
}
e = new SetDisplayExpr(x, elements);
- Expect(10);
- } else if (la.kind == 74) {
+ Expect(14);
+ } else if (la.kind == 76) {
Get();
x = t; elements = new List<Expression/*!*/>();
if (StartOf(17)) {
Expressions(elements);
}
e = new SeqDisplayExpr(x, elements);
- Expect(75);
- } else SynErr(220);
+ Expect(77);
+ } else SynErr(221);
}
void MultiSetExpr(out Expression e) {
@@ -3275,25 +3366,25 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IToken/*!*/ x = null; List<Expression/*!*/>/*!*/ elements;
e = dummyExpr;
- Expect(57);
+ Expect(59);
x = t;
- if (la.kind == 9) {
+ if (la.kind == 13) {
Get();
elements = new List<Expression/*!*/>();
if (StartOf(17)) {
Expressions(elements);
}
e = new MultiSetDisplayExpr(x, elements);
- Expect(10);
- } else if (la.kind == 11) {
+ Expect(14);
+ } else if (la.kind == 15) {
Get();
x = t; elements = new List<Expression/*!*/>();
- Expression(out e, true);
+ Expression(out e, true, true);
e = new MultiSetFormingExpr(x, e);
- Expect(12);
- } else if (StartOf(33)) {
+ Expect(16);
+ } else if (StartOf(32)) {
SemErr("multiset must be followed by multiset literal or expression to coerce in parentheses.");
- } else SynErr(221);
+ } else SynErr(222);
}
void MapDisplayExpr(IToken/*!*/ mapToken, out Expression e) {
@@ -3301,12 +3392,12 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
List<ExpressionPair/*!*/>/*!*/ elements= new List<ExpressionPair/*!*/>() ;
e = dummyExpr;
- Expect(74);
+ Expect(76);
if (StartOf(17)) {
MapLiteralExpressions(out elements);
}
e = new MapDisplayExpr(mapToken, elements);
- Expect(75);
+ Expect(77);
}
void MapComprehensionExpr(IToken mapToken, out Expression e, bool allowSemi) {
@@ -3318,33 +3409,33 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
IdentTypeOptional(out bv);
bvars.Add(bv);
- if (la.kind == 29) {
+ if (la.kind == 33) {
Get();
- Expression(out range, true);
+ Expression(out range, true, true);
}
QSep();
- Expression(out body, allowSemi);
+ Expression(out body, allowSemi, true);
e = new MapComprehension(mapToken, bvars, range ?? new LiteralExpr(mapToken, true), body);
}
- void ConstAtomExpression(out Expression e) {
+ void ConstAtomExpression(out Expression e, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null);
IToken/*!*/ x; BigInteger n; Basetypes.BigDec d;
e = dummyExpr; Type toType = null;
switch (la.kind) {
- case 113: {
+ case 114: {
Get();
e = new LiteralExpr(t, false);
break;
}
- case 114: {
+ case 115: {
Get();
e = new LiteralExpr(t, true);
break;
}
- case 115: {
+ case 116: {
Get();
e = new LiteralExpr(t);
break;
@@ -3359,56 +3450,56 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
e = new LiteralExpr(t, d);
break;
}
- case 116: {
+ case 117: {
Get();
e = new ThisExpr(t);
break;
}
- case 117: {
+ case 118: {
Get();
x = t;
- Expect(11);
- Expression(out e, true);
- Expect(12);
+ Expect(15);
+ Expression(out e, true, true);
+ Expect(16);
e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Fresh, e);
break;
}
- case 118: {
+ case 119: {
Get();
x = t;
- Expect(11);
- Expression(out e, true);
- Expect(12);
+ Expect(15);
+ Expression(out e, true, true);
+ Expect(16);
e = new OldExpr(x, e);
break;
}
- case 29: {
+ case 33: {
Get();
x = t;
- Expression(out e, true);
+ Expression(out e, true, true);
e = new UnaryOpExpr(x, UnaryOpExpr.Opcode.Cardinality, e);
- Expect(29);
+ Expect(33);
break;
}
- case 54: case 55: {
- if (la.kind == 54) {
+ case 56: case 57: {
+ if (la.kind == 56) {
Get();
x = t; toType = new IntType();
} else {
Get();
x = t; toType = new RealType();
}
- Expect(11);
- Expression(out e, true);
- Expect(12);
+ Expect(15);
+ Expression(out e, true, true);
+ Expect(16);
e = new ConversionExpr(x, e, toType);
break;
}
- case 11: {
- ParensExpression(out e);
+ case 15: {
+ ParensExpression(out e, allowSemi, allowLambda);
break;
}
- default: SynErr(222); break;
+ default: SynErr(223); break;
}
}
@@ -3433,7 +3524,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
n = BigInteger.Zero;
}
- } else SynErr(223);
+ } else SynErr(224);
}
void Dec(out Basetypes.BigDec d) {
@@ -3448,90 +3539,160 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
- void ParensExpression(out Expression e) {
+ void ParensExpression(out Expression e, bool allowSemi, bool allowLambda) {
IToken x;
- List<Expression> args = null;
+ Expression ee;
+ e = null;
+ List<Expression> args = new List<Expression>();
+ List<Type> types = new List<Type>();
+ Type tt;
+ bool isLambda = false;
- Expect(11);
- x = t; e = null;
- if (la.kind == 12) {
- Get();
- var tmp = theBuiltIns.TupleType(x, 0, true);
- e = new DatatypeValue(x, BuiltIns.TupleTypeName(0), BuiltIns.TupleTypeCtorName, new List<Expression>());
-
- } else if (StartOf(17)) {
- Expression(out e, true);
- while (la.kind == 31) {
+ Expect(15);
+ x = t;
+ if (StartOf(17)) {
+ OptTypedExpr(out ee, out tt, true);
+ args.Add(ee); types.Add(tt);
+ while (la.kind == 35) {
Get();
- if (args == null) {
- args = new List<Expression>();
- args.Add(e); // add the first argument, which was parsed above
- }
-
- Expression(out e, true);
- args.Add(e);
+ OptTypedExpr(out ee, out tt, true);
+ args.Add(ee); types.Add(tt);
}
- Expect(12);
- if (args == null) {
- e = new ParensExpression(x, e);
- } else {
- // make sure the corresponding tuple type exists
- var tmp = theBuiltIns.TupleType(x, args.Count, true);
- e = new DatatypeValue(x, BuiltIns.TupleTypeName(args.Count), BuiltIns.TupleTypeCtorName, args);
+ }
+ Expect(16);
+ if (IsLambda(allowLambda)) {
+ Expression body = null;
+ Expression req = null;
+ bool oneShot;
+ var reads = new List<FrameExpression>();
+ x = t;
+
+ LambdaSpec(out req, reads);
+ LambdaArrow(out oneShot);
+ Expression(out body, allowSemi, true);
+ List<BoundVar> bvs = new List<BoundVar>();
+ for (int i = 0; i < args.Count; i++) {
+ ee = args[i];
+ tt = types[i];
+ if (ee is IdentifierSequence) {
+ IdentifierSequence ise = (IdentifierSequence)ee;
+ List<IToken> idents = ise.Tokens;
+ Contract.Assert(idents != null);
+ Contract.Assert(idents.Count > 0);
+ IToken id = idents[0];
+ if (idents.Count != 1) {
+ SemErr(id, "Expected variable binding.");
+ }
+ if (ise.Arguments != null) {
+ SemErr(ise.OpenParen, "Expected variable binding.");
+ }
+ bvs.Add(new BoundVar(id, id.val, tt ?? new InferredTypeProxy()));
+ } else {
+ SemErr(ee.tok, "Expected variable binding.");
+ }
}
+ e = new LambdaExpr(x, oneShot, bvs, req, reads, body);
+ isLambda = true;
- } else SynErr(224);
+ }
+ if (!isLambda) {
+ for (int i = 0; i < args.Count; i++) {
+ if (types[i] != null) {
+ SemErr(args[i].tok, "Type specification not allowed here, comma separator was expected.");
+ }
+ }
+ if (args.Count == 1) {
+ e = new ParensExpression(x, args[0]);
+ } else {
+ // make sure the corresponding tuple type exists
+ var tmp = theBuiltIns.TupleType(x, args.Count, true);
+ e = new DatatypeValue(x, BuiltIns.TupleTypeName(args.Count), BuiltIns.TupleTypeCtorName, args);
+ }
+ }
+
+ if (!isLambda && args.Count == 1 && la.kind == _openparen) {
+ IToken openParen;
+ while (la.kind == 15) {
+ Get();
+ openParen = t; args = new List<Expression>();
+ if (StartOf(17)) {
+ Expressions(args);
+ }
+ Expect(16);
+ e = new ApplyExpr(x, openParen, e, args);
+ }
+ }
+ }
+
+ void LambdaArrow(out bool oneShot) {
+ oneShot = true;
+ if (la.kind == 9) {
+ Get();
+ oneShot = false;
+ } else if (la.kind == 10) {
+ Get();
+ oneShot = true;
+ } else SynErr(225);
+ }
+
+ void OptTypedExpr(out Expression e, out Type tt, bool allowSemi) {
+ tt = null;
+ Expression(out e, allowSemi, true);
+ if (la.kind == 7) {
+ Get();
+ Type(out tt);
+ }
}
void MapLiteralExpressions(out List<ExpressionPair> elements) {
Expression/*!*/ d, r;
elements = new List<ExpressionPair/*!*/>();
- Expression(out d, true);
- Expect(69);
- Expression(out r, true);
+ Expression(out d, true, true);
+ Expect(71);
+ Expression(out r, true, true);
elements.Add(new ExpressionPair(d,r));
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
- Expression(out d, true);
- Expect(69);
- Expression(out r, true);
+ Expression(out d, true, true);
+ Expect(71);
+ Expression(out r, true, true);
elements.Add(new ExpressionPair(d,r));
}
}
void QSep() {
- if (la.kind == 124) {
+ if (la.kind == 125) {
Get();
- } else if (la.kind == 125) {
+ } else if (la.kind == 126) {
Get();
- } else SynErr(225);
+ } else SynErr(226);
}
- void MatchExpression(out Expression e, bool allowSemi) {
+ void MatchExpression(out Expression e, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; MatchCaseExpr/*!*/ c;
List<MatchCaseExpr/*!*/> cases = new List<MatchCaseExpr/*!*/>();
bool usesOptionalBrace = false;
- Expect(82);
+ Expect(83);
x = t;
- Expression(out e, allowSemi);
- if (la.kind == 9) {
+ Expression(out e, allowSemi, true);
+ if (la.kind == 13) {
Get();
usesOptionalBrace = true;
}
- while (la.kind == 78) {
- CaseExpression(out c, allowSemi);
+ while (la.kind == 80) {
+ CaseExpression(out c, allowSemi, usesOptionalBrace || allowLambda);
cases.Add(c);
}
if (CloseOptionalBrace(usesOptionalBrace)) {
- Expect(10);
+ Expect(14);
} else if (StartOf(32)) {
if (usesOptionalBrace) { SemErr(t, "expecting close curly brace"); }
- } else SynErr(226);
+ } else SynErr(227);
e = new MatchExpr(x, e, cases, usesOptionalBrace);
}
- void QuantifierGuts(out Expression q, bool allowSemi) {
+ void QuantifierGuts(out Expression q, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out q) != null); IToken/*!*/ x = Token.NoToken;
bool univ = false;
List<BoundVar/*!*/> bvars;
@@ -3539,16 +3700,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression range;
Expression/*!*/ body;
- if (la.kind == 85 || la.kind == 121) {
+ if (la.kind == 86 || la.kind == 122) {
Forall();
x = t; univ = true;
- } else if (la.kind == 122 || la.kind == 123) {
+ } else if (la.kind == 123 || la.kind == 124) {
Exists();
x = t;
- } else SynErr(227);
+ } else SynErr(228);
QuantifierDomain(out bvars, out attrs, out range);
QSep();
- Expression(out body, allowSemi);
+ Expression(out body, allowSemi, allowLambda);
if (univ) {
q = new ForallExpr(x, bvars, range, body, attrs);
} else {
@@ -3557,7 +3718,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
- void ComprehensionExpr(out Expression q, bool allowSemi) {
+ void ComprehensionExpr(out Expression q, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out q) != null);
IToken x = Token.NoToken;
BoundVar bv;
@@ -3565,20 +3726,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expression range;
Expression body = null;
- Expect(56);
+ Expect(58);
x = t;
IdentTypeOptional(out bv);
bvars.Add(bv);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
IdentTypeOptional(out bv);
bvars.Add(bv);
}
- Expect(29);
- Expression(out range, allowSemi);
- if (la.kind == 124 || la.kind == 125) {
+ Expect(33);
+ Expression(out range, allowSemi, allowLambda);
+ if (la.kind == 125 || la.kind == 126) {
QSep();
- Expression(out body, allowSemi);
+ Expression(out body, allowSemi, allowLambda);
}
if (body == null && bvars.Count != 1) { SemErr(t, "a set comprehension with more than one bound variable must have a term expression"); }
q = new SetComprehension(x, bvars, range, body);
@@ -3587,16 +3748,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
void StmtInExpr(out Statement s) {
s = dummyStmt;
- if (la.kind == 83) {
+ if (la.kind == 84) {
AssertStmt(out s);
- } else if (la.kind == 72) {
+ } else if (la.kind == 74) {
AssumeStmt(out s);
- } else if (la.kind == 88) {
+ } else if (la.kind == 89) {
CalcStmt(out s);
- } else SynErr(228);
+ } else SynErr(229);
}
- void LetExpr(out Expression e, bool allowSemi) {
+ void LetExpr(out Expression e, bool allowSemi, bool allowLambda) {
IToken x = null;
bool isGhost = false;
var letLHSs = new List<CasePattern>();
@@ -3605,26 +3766,26 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
bool exact = true;
e = dummyExpr;
- if (la.kind == 25) {
+ if (la.kind == 29) {
Get();
isGhost = true; x = t;
}
- Expect(30);
+ Expect(34);
if (!isGhost) { x = t; }
CasePattern(out pat);
if (isGhost) { pat.Vars.Iter(bv => bv.IsGhost = true); }
letLHSs.Add(pat);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
CasePattern(out pat);
if (isGhost) { pat.Vars.Iter(bv => bv.IsGhost = true); }
letLHSs.Add(pat);
}
- if (la.kind == 69) {
+ if (la.kind == 71) {
Get();
- } else if (la.kind == 71) {
+ } else if (la.kind == 73) {
Get();
exact = false;
foreach (var lhs in letLHSs) {
@@ -3633,29 +3794,29 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
}
- } else SynErr(229);
- Expression(out e, false);
+ } else SynErr(230);
+ Expression(out e, false, true);
letRHSs.Add(e);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
- Expression(out e, false);
+ Expression(out e, false, true);
letRHSs.Add(e);
}
Expect(8);
- Expression(out e, allowSemi);
+ Expression(out e, allowSemi, allowLambda);
e = new LetExpr(x, letLHSs, letRHSs, e, exact);
}
- void NamedExpr(out Expression e, bool allowSemi) {
+ void NamedExpr(out Expression e, bool allowSemi, bool allowLambda) {
IToken/*!*/ x, d;
e = dummyExpr;
Expression expr;
- Expect(66);
+ Expect(68);
x = t;
NoUSIdent(out d);
Expect(7);
- Expression(out e, allowSemi);
+ Expression(out e, allowSemi, allowLambda);
expr = e;
e = new NamedExpr(x, d.val, expr);
}
@@ -3667,65 +3828,65 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
if (IsIdentParen()) {
Ident(out id);
- Expect(11);
+ Expect(15);
arguments = new List<CasePattern>();
if (la.kind == 1) {
CasePattern(out pat);
arguments.Add(pat);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
CasePattern(out pat);
arguments.Add(pat);
}
}
- Expect(12);
+ Expect(16);
pat = new CasePattern(id, id.val, arguments);
} else if (la.kind == 1) {
IdentTypeOptional(out bv);
pat = new CasePattern(bv.tok, bv);
- } else SynErr(230);
+ } else SynErr(231);
}
- void CaseExpression(out MatchCaseExpr c, bool allowSemi) {
+ void CaseExpression(out MatchCaseExpr c, bool allowSemi, bool allowLambda) {
Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken/*!*/ x, id;
List<BoundVar/*!*/> arguments = new List<BoundVar/*!*/>();
BoundVar/*!*/ bv;
Expression/*!*/ body;
- Expect(78);
+ Expect(80);
x = t;
Ident(out id);
- if (la.kind == 11) {
+ if (la.kind == 15) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
}
- Expect(12);
+ Expect(16);
}
- Expect(79);
- Expression(out body, allowSemi);
+ Expect(9);
+ Expression(out body, allowSemi, allowLambda);
c = new MatchCaseExpr(x, id.val, arguments, body);
}
void Forall() {
- if (la.kind == 85) {
+ if (la.kind == 86) {
Get();
- } else if (la.kind == 121) {
+ } else if (la.kind == 122) {
Get();
- } else SynErr(231);
+ } else SynErr(232);
}
void Exists() {
- if (la.kind == 122) {
+ if (la.kind == 123) {
Get();
- } else if (la.kind == 123) {
+ } else if (la.kind == 124) {
Get();
- } else SynErr(232);
+ } else SynErr(233);
}
void AttributeBody(ref Attributes attrs) {
@@ -3736,10 +3897,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
Expect(7);
Expect(1);
aName = t.val;
- if (StartOf(34)) {
+ if (StartOf(33)) {
AttributeArg(out aArg, true);
aArgs.Add(aArg);
- while (la.kind == 31) {
+ while (la.kind == 35) {
Get();
AttributeArg(out aArg, true);
aArgs.Add(aArg);
@@ -3761,41 +3922,40 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo
}
static readonly bool[,]/*!*/ set = {
- {T,T,T,T, T,x,x,x, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,T,x,T, T,T,T,x, x,x,T,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,T, x,x,T,T, x,x,x,x, x,x,x,x, x,x,T,T, x,x,T,x, T,x,x,x, T,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,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, T,T,x,T, x,x,x,x, T,T,T,T, T,x,T,x, T,x,T,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,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,T,T,x, x,x,T,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,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,x,x, T,x,T,x, x,x,x,x, T,T,x,T, x,T,x,x, T,T,T,T, T,x,T,x, T,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,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,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,x,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {T,x,x,x, x,x,x,x, x,T,T,T, x,x,x,x, T,T,x,T, x,x,x,x, T,T,T,T, T,x,T,x, T,x,T,x, x,x,T,x, T,T,T,T, T,x,x,T, T,T,T,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,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},
- {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,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,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,T,T,x, x,T,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,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,T,x,x, x,T,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, 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,x,x, x,x,x,x, x,x,x,x, x,x,x,x, 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,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,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,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, x,x,T,T, T,T,x,T, x,x,x,x, x,T,T,x, x,x,x,x, T,x,T,x, T,x,x,x, x,x,T,T, x,T,x,x, T,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, x,x,x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, x,x,x,x, x,x,x,x, x,x,T,T, x,x,T,x, T,x,x,x, T,x,x,x, T,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,T,T,T, T,T,T,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,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,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, x,x,T,T, T,T,x,T, x,x,x,x, x,x,T,x, x,x,x,x, T,x,T,x, T,x,x,x, x,x,T,T, x,T,x,x, T,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, x,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,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, x,x,T,T, T,T,x,T, x,x,x,x, x,T,T,x, x,x,x,x, T,x,T,x, T,x,x,x, x,x,T,T, x,T,x,x, T,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, x,x,x,x},
- {T,T,T,T, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, x,x,x,x, x,x,x,x, x,x,T,T, x,x,T,x, T,x,x,x, T,x,x,x, T,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,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,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,T,T, T,T,x,T, x,x,x,x, x,x,T,x, x,x,x,x, T,x,T,x, T,x,x,x, x,x,T,T, x,T,x,x, T,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, x,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,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, x,x,T,T, T,T,x,T, x,x,x,x, x,x,T,x, x,x,x,x, T,x,T,x, T,x,x,x, x,x,T,T, x,T,x,x, T,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, x,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, x,x,x,x, x,x,x,x, x,x,T,T, x,x,T,x, T,x,x,x, T,x,T,x, T,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,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,T,x, T,x,x,T, x,x,T,T, x,x,x,x, x,x,x,x, x,x,T,T, x,x,T,x, T,x,x,x, T,x,T,x, T,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,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,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,T,T, 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,T,T,T, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,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,T,T, T,T,x,T, x,x,x,x, x,T,T,x, x,x,x,x, T,x,T,x, T,x,x,x, x,x,T,T, x,T,x,x, T,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, x,x,x,x},
- {x,T,T,T, T,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,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, x,x,T,T, T,T,x,T, x,x,x,x, x,x,T,x, x,x,x,x, T,T,T,x, T,x,x,x, x,x,T,T, x,T,x,x, T,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, x,x,x,x},
- {x,x,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,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,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,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,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,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, 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,T,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,T,T, T,T,T,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, x,x,x,x},
- {x,T,T,T, T,x,x,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,T, x,T,x,x, x,T,T,T, x,x,x,x, x,T,T,x, T,T,x,T, x,x,T,T, x,x,x,x, x,x,x,x, x,T,T,T, x,T,T,x, T,x,x,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, x,T,T,T, T,T,T,T, T,x,x,x, T,T,x,x},
- {x,T,T,T, T,x,x,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,T, x,T,x,x, x,T,T,T, x,x,x,x, x,T,T,x, T,T,x,T, x,x,T,T, x,x,x,x, x,T,x,x, x,T,T,T, x,T,T,x, T,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, x,T,T,T, T,T,T,T, T,x,x,x, T,T,x,x},
- {x,T,T,T, T,x,T,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,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, x,x,T,T, T,T,x,T, x,x,x,x, x,x,T,x, x,x,x,x, T,x,T,x, T,x,x,x, x,x,T,T, x,T,x,x, T,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, x,x,x,x}
+ {T,T,T,T, T,x,x,x, T,x,x,T, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,T,x,T, T,T,T,x, x,x,T,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, T,T,x,x, T,x,T,x, x,x,T,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,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,T, x,x,x,x, T,T,T,T, T,x,T,x, T,x,T,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, 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,T,T,x, x,x,T,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, 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},
+ {T,x,x,x, x,x,x,x, T,x,x,x, x,x,T,x, x,x,x,x, T,T,x,T, x,T,x,x, T,T,T,T, T,x,T,x, T,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, 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, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {T,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, x,x,x,x, T,T,x,T, x,x,x,x, T,T,T,T, T,x,T,x, T,x,T,x, x,x,T,x, T,T,T,T, T,x,x,T, T,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,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,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,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,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,T, 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,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, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,T,x,x, x,T,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,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, x,x,x,x, x,x,x,x, x,x,x,x, x,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, 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},
+ {x,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,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,T,T, x,T,x,x, x,x,x,T, T,x,x,x, x,x,T,x, T,x,T,x, x,x,x,T, T,x,T,x, x,T,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,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,T,T, 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,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, T,T,x,x, T,x,T,x, x,x,T,x, x,T,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,T,T, T,T,T,T, x,x,x,x, x,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,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,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,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,T,T, x,T,x,x, x,x,x,x, T,x,x,x, x,x,T,x, T,x,T,x, x,x,x,T, T,x,T,x, x,T,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,x,x,x, x},
+ {x,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,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,T,T, x,T,x,x, x,x,x,T, T,x,x,x, x,x,T,x, T,x,T,x, x,x,x,T, T,x,T,x, x,T,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,x,x,x, x},
+ {T,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, T,T,x,x, T,x,T,x, x,x,T,x, x,T,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,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x},
+ {x,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,T,x,x, x,x,x,x, T,x,x,x, x,x,T,x, T,x,T,x, x,x,x,T, T,x,T,x, x,T,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,x,x,x, x},
+ {x,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,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,T,T, x,T,x,x, x,x,x,x, T,x,x,x, x,x,T,x, T,x,T,x, x,x,x,T, T,x,T,x, x,T,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,x,x,x, x},
+ {x,T,T,T, T,x,x,x, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, T,T,x,x, T,x,T,x, x,x,T,x, T,T,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,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x},
+ {x,T,T,T, T,x,x,x, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,T,T, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, T,T,x,x, T,x,T,x, x,x,T,x, T,T,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,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,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,T, T,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,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,T,x,x, x,x,x,T, T,x,x,x, x,x,T,x, T,x,T,x, x,x,x,T, T,x,T,x, x,T,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,x,x,x, x},
+ {x,T,T,T, T,x,x,x, x,x,x,x, x,T,x,T, x,T,x,x, x,x,x,x, x,x,x,x, x,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,T,T, x,T,x,x, x,x,x,x, T,x,x,x, x,x,T,T, T,x,T,x, x,x,x,T, T,x,T,x, x,T,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,x,x,x, x},
+ {x,x,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,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,x,x, x,x,x,x, x,x,x,x, x,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,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, 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,T,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,T, T,T,T,T, 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,x,x,x, x},
+ {x,T,T,T, T,x,x,T, T,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,T,T, x,T,x,x, x,T,T,T, x,x,x,x, x,T,T,T, T,T,x,x, T,T,x,x, x,x,x,T, x,x,x,T, T,T,x,T, T,T,T,x, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,T,T, T,T,T,T, T,T,x,x, x,T,T,x, x},
+ {x,T,T,T, T,x,T,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,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,T,T, x,T,x,x, x,x,x,x, T,x,x,x, x,x,T,x, T,x,T,x, x,x,x,T, T,x,T,x, x,T,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,x,x,x, x}
};
} // end Parser
@@ -3829,230 +3989,231 @@ public class Errors {
case 6: s = "string expected"; break;
case 7: s = "colon expected"; break;
case 8: s = "semi expected"; break;
- case 9: s = "lbrace expected"; break;
- case 10: s = "rbrace expected"; break;
- case 11: s = "openparen expected"; break;
- case 12: s = "closeparen expected"; break;
- case 13: s = "star expected"; break;
- case 14: s = "notIn expected"; break;
- case 15: s = "\"include\" expected"; break;
- case 16: s = "\"abstract\" expected"; break;
- case 17: s = "\"module\" expected"; break;
- case 18: s = "\"refines\" expected"; break;
- case 19: s = "\"import\" expected"; break;
- case 20: s = "\"opened\" expected"; break;
- case 21: s = "\"=\" expected"; break;
- case 22: s = "\"as\" expected"; break;
- case 23: s = "\"default\" expected"; break;
- case 24: s = "\"class\" expected"; break;
- case 25: s = "\"ghost\" expected"; break;
- case 26: s = "\"static\" expected"; break;
- case 27: s = "\"datatype\" expected"; break;
- case 28: s = "\"codatatype\" expected"; break;
- case 29: s = "\"|\" expected"; break;
- case 30: s = "\"var\" expected"; break;
- case 31: s = "\",\" expected"; break;
- case 32: s = "\"type\" expected"; break;
- case 33: s = "\"==\" expected"; break;
- case 34: s = "\"iterator\" expected"; break;
- case 35: s = "\"yields\" expected"; break;
- case 36: s = "\"returns\" expected"; break;
- case 37: s = "\"...\" expected"; break;
- case 38: s = "\"<\" expected"; break;
- case 39: s = "\">\" expected"; break;
- case 40: s = "\"method\" expected"; break;
- case 41: s = "\"lemma\" expected"; break;
- case 42: s = "\"colemma\" expected"; break;
- case 43: s = "\"comethod\" expected"; break;
- case 44: s = "\"constructor\" expected"; break;
- case 45: s = "\"modifies\" expected"; break;
- case 46: s = "\"free\" expected"; break;
- case 47: s = "\"requires\" expected"; break;
- case 48: s = "\"ensures\" expected"; break;
- case 49: s = "\"decreases\" expected"; break;
- case 50: s = "\"reads\" expected"; break;
- case 51: s = "\"yield\" expected"; break;
- case 52: s = "\"bool\" expected"; break;
- case 53: s = "\"nat\" expected"; break;
- case 54: s = "\"int\" expected"; break;
- case 55: s = "\"real\" expected"; break;
- case 56: s = "\"set\" expected"; break;
- case 57: s = "\"multiset\" expected"; break;
- case 58: s = "\"seq\" expected"; break;
- case 59: s = "\"map\" expected"; break;
- case 60: s = "\"object\" expected"; break;
- case 61: s = "\".\" expected"; break;
- case 62: s = "\"function\" expected"; break;
- case 63: s = "\"predicate\" expected"; break;
- case 64: s = "\"copredicate\" expected"; break;
- case 65: s = "\"`\" expected"; break;
- case 66: s = "\"label\" expected"; break;
- case 67: s = "\"break\" expected"; break;
- case 68: s = "\"where\" expected"; break;
- case 69: s = "\":=\" expected"; break;
- case 70: s = "\"return\" expected"; break;
- case 71: s = "\":|\" expected"; break;
- case 72: s = "\"assume\" expected"; break;
- case 73: s = "\"new\" expected"; break;
- case 74: s = "\"[\" expected"; break;
- case 75: s = "\"]\" expected"; break;
- case 76: s = "\"if\" expected"; break;
- case 77: s = "\"else\" expected"; break;
- case 78: s = "\"case\" expected"; break;
- case 79: s = "\"=>\" expected"; break;
- case 80: s = "\"while\" expected"; break;
- case 81: s = "\"invariant\" expected"; break;
- case 82: s = "\"match\" expected"; break;
- case 83: s = "\"assert\" expected"; break;
- case 84: s = "\"print\" expected"; break;
- case 85: s = "\"forall\" expected"; break;
- case 86: s = "\"parallel\" expected"; break;
- case 87: s = "\"modify\" expected"; break;
- case 88: s = "\"calc\" expected"; break;
- case 89: s = "\"#\" expected"; break;
- case 90: s = "\"<=\" expected"; break;
- case 91: s = "\">=\" expected"; break;
- case 92: s = "\"!=\" expected"; break;
- case 93: s = "\"\\u2260\" expected"; break;
- case 94: s = "\"\\u2264\" expected"; break;
- case 95: s = "\"\\u2265\" expected"; break;
- case 96: s = "\"<==>\" expected"; break;
- case 97: s = "\"\\u21d4\" expected"; break;
- case 98: s = "\"==>\" expected"; break;
- case 99: s = "\"\\u21d2\" expected"; break;
- case 100: s = "\"<==\" expected"; break;
- case 101: s = "\"\\u21d0\" expected"; break;
- case 102: s = "\"&&\" expected"; break;
- case 103: s = "\"\\u2227\" expected"; break;
- case 104: s = "\"||\" expected"; break;
- case 105: s = "\"\\u2228\" expected"; break;
- case 106: s = "\"in\" expected"; break;
- case 107: s = "\"!\" expected"; break;
- case 108: s = "\"+\" expected"; break;
- case 109: s = "\"-\" expected"; break;
- case 110: s = "\"/\" expected"; break;
- case 111: s = "\"%\" expected"; break;
- case 112: s = "\"\\u00ac\" expected"; break;
- case 113: s = "\"false\" expected"; break;
- case 114: s = "\"true\" expected"; break;
- case 115: s = "\"null\" expected"; break;
- case 116: s = "\"this\" expected"; break;
- case 117: s = "\"fresh\" expected"; break;
- case 118: s = "\"old\" expected"; break;
- case 119: s = "\"then\" expected"; break;
- case 120: s = "\"..\" expected"; break;
- case 121: s = "\"\\u2200\" expected"; break;
- case 122: s = "\"exists\" expected"; break;
- case 123: s = "\"\\u2203\" expected"; break;
- case 124: s = "\"::\" expected"; break;
- case 125: s = "\"\\u2022\" expected"; break;
- case 126: s = "??? expected"; break;
- case 127: s = "this symbol not expected in SubModuleDecl"; break;
- case 128: s = "invalid SubModuleDecl"; break;
- case 129: s = "this symbol not expected in ClassDecl"; break;
- case 130: s = "this symbol not expected in DatatypeDecl"; break;
- case 131: s = "invalid DatatypeDecl"; break;
- case 132: s = "this symbol not expected in DatatypeDecl"; break;
- case 133: s = "invalid OtherTypeDecl"; break;
- case 134: s = "this symbol not expected in OtherTypeDecl"; break;
- case 135: s = "this symbol not expected in IteratorDecl"; break;
- case 136: s = "invalid IteratorDecl"; break;
- case 137: s = "invalid ClassMemberDecl"; break;
- case 138: s = "invalid IdentOrDigitsSuffix"; break;
- case 139: s = "this symbol not expected in FieldDecl"; break;
+ case 9: s = "darrow expected"; break;
+ case 10: s = "arrow expected"; break;
+ case 11: s = "reads expected"; break;
+ case 12: s = "requires expected"; break;
+ case 13: s = "lbrace expected"; break;
+ case 14: s = "rbrace expected"; break;
+ case 15: s = "openparen expected"; break;
+ case 16: s = "closeparen expected"; break;
+ case 17: s = "star expected"; break;
+ case 18: s = "notIn expected"; break;
+ case 19: s = "\"include\" expected"; break;
+ case 20: s = "\"abstract\" expected"; break;
+ case 21: s = "\"module\" expected"; break;
+ case 22: s = "\"refines\" expected"; break;
+ case 23: s = "\"import\" expected"; break;
+ case 24: s = "\"opened\" expected"; break;
+ case 25: s = "\"=\" expected"; break;
+ case 26: s = "\"as\" expected"; break;
+ case 27: s = "\"default\" expected"; break;
+ case 28: s = "\"class\" expected"; break;
+ case 29: s = "\"ghost\" expected"; break;
+ case 30: s = "\"static\" expected"; break;
+ case 31: s = "\"datatype\" expected"; break;
+ case 32: s = "\"codatatype\" expected"; break;
+ case 33: s = "\"|\" expected"; break;
+ case 34: s = "\"var\" expected"; break;
+ case 35: s = "\",\" expected"; break;
+ case 36: s = "\"type\" expected"; break;
+ case 37: s = "\"==\" expected"; break;
+ case 38: s = "\"iterator\" expected"; break;
+ case 39: s = "\"yields\" expected"; break;
+ case 40: s = "\"returns\" expected"; break;
+ case 41: s = "\"...\" expected"; break;
+ case 42: s = "\"<\" expected"; break;
+ case 43: s = "\">\" expected"; break;
+ case 44: s = "\"method\" expected"; break;
+ case 45: s = "\"lemma\" expected"; break;
+ case 46: s = "\"colemma\" expected"; break;
+ case 47: s = "\"comethod\" expected"; break;
+ case 48: s = "\"constructor\" expected"; break;
+ case 49: s = "\"modifies\" expected"; break;
+ case 50: s = "\"free\" expected"; break;
+ case 51: s = "\"ensures\" expected"; break;
+ case 52: s = "\"decreases\" expected"; break;
+ case 53: s = "\"yield\" expected"; break;
+ case 54: s = "\"bool\" expected"; break;
+ case 55: s = "\"nat\" expected"; break;
+ case 56: s = "\"int\" expected"; break;
+ case 57: s = "\"real\" expected"; break;
+ case 58: s = "\"set\" expected"; break;
+ case 59: s = "\"multiset\" expected"; break;
+ case 60: s = "\"seq\" expected"; break;
+ case 61: s = "\"map\" expected"; break;
+ case 62: s = "\"object\" expected"; break;
+ case 63: s = "\".\" expected"; break;
+ case 64: s = "\"function\" expected"; break;
+ case 65: s = "\"predicate\" expected"; break;
+ case 66: s = "\"copredicate\" expected"; break;
+ case 67: s = "\"`\" expected"; break;
+ case 68: s = "\"label\" expected"; break;
+ case 69: s = "\"break\" expected"; break;
+ case 70: s = "\"where\" expected"; break;
+ case 71: s = "\":=\" expected"; break;
+ case 72: s = "\"return\" expected"; break;
+ case 73: s = "\":|\" expected"; break;
+ case 74: s = "\"assume\" expected"; break;
+ case 75: s = "\"new\" expected"; break;
+ case 76: s = "\"[\" expected"; break;
+ case 77: s = "\"]\" expected"; break;
+ case 78: s = "\"if\" expected"; break;
+ case 79: s = "\"else\" expected"; break;
+ case 80: s = "\"case\" expected"; break;
+ case 81: s = "\"while\" expected"; break;
+ case 82: s = "\"invariant\" expected"; break;
+ case 83: s = "\"match\" expected"; break;
+ case 84: s = "\"assert\" expected"; break;
+ case 85: s = "\"print\" expected"; break;
+ case 86: s = "\"forall\" expected"; break;
+ case 87: s = "\"parallel\" expected"; break;
+ case 88: s = "\"modify\" expected"; break;
+ case 89: s = "\"calc\" expected"; break;
+ case 90: s = "\"#\" expected"; break;
+ case 91: s = "\"<=\" expected"; break;
+ case 92: s = "\">=\" expected"; break;
+ case 93: s = "\"!=\" expected"; break;
+ case 94: s = "\"\\u2260\" expected"; break;
+ case 95: s = "\"\\u2264\" expected"; break;
+ case 96: s = "\"\\u2265\" expected"; break;
+ case 97: s = "\"<==>\" expected"; break;
+ case 98: s = "\"\\u21d4\" expected"; break;
+ case 99: s = "\"==>\" expected"; break;
+ case 100: s = "\"\\u21d2\" expected"; break;
+ case 101: s = "\"<==\" expected"; break;
+ case 102: s = "\"\\u21d0\" expected"; break;
+ case 103: s = "\"&&\" expected"; break;
+ case 104: s = "\"\\u2227\" expected"; break;
+ case 105: s = "\"||\" expected"; break;
+ case 106: s = "\"\\u2228\" expected"; break;
+ case 107: s = "\"in\" expected"; break;
+ case 108: s = "\"!\" expected"; break;
+ case 109: s = "\"+\" expected"; break;
+ case 110: s = "\"-\" expected"; break;
+ case 111: s = "\"/\" expected"; break;
+ case 112: s = "\"%\" expected"; break;
+ case 113: s = "\"\\u00ac\" expected"; break;
+ case 114: s = "\"false\" expected"; break;
+ case 115: s = "\"true\" expected"; break;
+ case 116: s = "\"null\" expected"; break;
+ case 117: s = "\"this\" expected"; break;
+ case 118: s = "\"fresh\" expected"; break;
+ case 119: s = "\"old\" expected"; break;
+ case 120: s = "\"then\" expected"; break;
+ case 121: s = "\"..\" expected"; break;
+ case 122: s = "\"\\u2200\" expected"; break;
+ case 123: s = "\"exists\" expected"; break;
+ case 124: s = "\"\\u2203\" expected"; break;
+ case 125: s = "\"::\" expected"; break;
+ case 126: s = "\"\\u2022\" expected"; break;
+ case 127: s = "??? expected"; break;
+ case 128: s = "this symbol not expected in SubModuleDecl"; break;
+ case 129: s = "invalid SubModuleDecl"; break;
+ case 130: s = "this symbol not expected in ClassDecl"; break;
+ case 131: s = "this symbol not expected in DatatypeDecl"; break;
+ case 132: s = "invalid DatatypeDecl"; break;
+ case 133: s = "this symbol not expected in DatatypeDecl"; break;
+ case 134: s = "invalid OtherTypeDecl"; break;
+ case 135: s = "this symbol not expected in OtherTypeDecl"; break;
+ case 136: s = "this symbol not expected in IteratorDecl"; break;
+ case 137: s = "invalid IteratorDecl"; break;
+ case 138: s = "invalid ClassMemberDecl"; break;
+ case 139: s = "invalid IdentOrDigitsSuffix"; break;
case 140: s = "this symbol not expected in FieldDecl"; break;
- case 141: s = "invalid FunctionDecl"; break;
+ case 141: s = "this symbol not expected in FieldDecl"; break;
case 142: s = "invalid FunctionDecl"; break;
case 143: s = "invalid FunctionDecl"; break;
case 144: s = "invalid FunctionDecl"; break;
- case 145: s = "this symbol not expected in MethodDecl"; break;
- case 146: s = "invalid MethodDecl"; break;
+ case 145: s = "invalid FunctionDecl"; break;
+ case 146: s = "this symbol not expected in MethodDecl"; break;
case 147: s = "invalid MethodDecl"; break;
- case 148: s = "invalid FIdentType"; break;
- case 149: s = "invalid TypeIdentOptional"; break;
- case 150: s = "invalid TypeAndToken"; break;
- case 151: s = "this symbol not expected in IteratorSpec"; break;
+ case 148: s = "invalid MethodDecl"; break;
+ case 149: s = "invalid FIdentType"; break;
+ case 150: s = "invalid TypeIdentOptional"; break;
+ case 151: s = "invalid TypeAndToken"; break;
case 152: s = "this symbol not expected in IteratorSpec"; break;
case 153: s = "this symbol not expected in IteratorSpec"; break;
case 154: s = "this symbol not expected in IteratorSpec"; break;
case 155: s = "this symbol not expected in IteratorSpec"; break;
- case 156: s = "invalid IteratorSpec"; break;
- case 157: s = "this symbol not expected in IteratorSpec"; break;
- case 158: s = "invalid IteratorSpec"; break;
- case 159: s = "this symbol not expected in MethodSpec"; break;
+ case 156: s = "this symbol not expected in IteratorSpec"; break;
+ case 157: s = "invalid IteratorSpec"; break;
+ case 158: s = "this symbol not expected in IteratorSpec"; break;
+ case 159: s = "invalid IteratorSpec"; break;
case 160: s = "this symbol not expected in MethodSpec"; break;
case 161: s = "this symbol not expected in MethodSpec"; break;
case 162: s = "this symbol not expected in MethodSpec"; break;
- case 163: s = "invalid MethodSpec"; break;
- case 164: s = "this symbol not expected in MethodSpec"; break;
- case 165: s = "invalid MethodSpec"; break;
- case 166: s = "invalid FrameExpression"; break;
- case 167: s = "invalid ReferenceType"; break;
- case 168: s = "this symbol not expected in FunctionSpec"; break;
+ case 163: s = "this symbol not expected in MethodSpec"; break;
+ case 164: s = "invalid MethodSpec"; break;
+ case 165: s = "this symbol not expected in MethodSpec"; break;
+ case 166: s = "invalid MethodSpec"; break;
+ case 167: s = "invalid FrameExpression"; break;
+ case 168: s = "invalid ReferenceType"; break;
case 169: s = "this symbol not expected in FunctionSpec"; break;
case 170: s = "this symbol not expected in FunctionSpec"; break;
case 171: s = "this symbol not expected in FunctionSpec"; break;
case 172: s = "this symbol not expected in FunctionSpec"; break;
- case 173: s = "invalid FunctionSpec"; break;
- case 174: s = "invalid PossiblyWildFrameExpression"; break;
- case 175: s = "invalid PossiblyWildExpression"; break;
- case 176: s = "this symbol not expected in OneStmt"; break;
- case 177: s = "invalid OneStmt"; break;
- case 178: s = "this symbol not expected in OneStmt"; break;
- case 179: s = "invalid OneStmt"; break;
- case 180: s = "invalid AssertStmt"; break;
- case 181: s = "invalid AssumeStmt"; break;
- case 182: s = "invalid UpdateStmt"; break;
+ case 173: s = "this symbol not expected in FunctionSpec"; break;
+ case 174: s = "invalid FunctionSpec"; break;
+ case 175: s = "invalid PossiblyWildFrameExpression"; break;
+ case 176: s = "invalid PossiblyWildExpression"; break;
+ case 177: s = "this symbol not expected in OneStmt"; break;
+ case 178: s = "invalid OneStmt"; break;
+ case 179: s = "this symbol not expected in OneStmt"; break;
+ case 180: s = "invalid OneStmt"; break;
+ case 181: s = "invalid AssertStmt"; break;
+ case 182: s = "invalid AssumeStmt"; break;
case 183: s = "invalid UpdateStmt"; break;
- case 184: s = "invalid IfStmt"; break;
+ case 184: s = "invalid UpdateStmt"; break;
case 185: s = "invalid IfStmt"; break;
- case 186: s = "invalid WhileStmt"; break;
+ case 186: s = "invalid IfStmt"; break;
case 187: s = "invalid WhileStmt"; break;
- case 188: s = "invalid MatchStmt"; break;
- case 189: s = "invalid ForallStmt"; break;
+ case 188: s = "invalid WhileStmt"; break;
+ case 189: s = "invalid MatchStmt"; break;
case 190: s = "invalid ForallStmt"; break;
- case 191: s = "this symbol not expected in ModifyStmt"; break;
- case 192: s = "invalid ModifyStmt"; break;
- case 193: s = "invalid ReturnStmt"; break;
- case 194: s = "invalid Rhs"; break;
- case 195: s = "invalid Lhs"; break;
- case 196: s = "invalid Guard"; break;
- case 197: s = "this symbol not expected in LoopSpec"; break;
+ case 191: s = "invalid ForallStmt"; break;
+ case 192: s = "this symbol not expected in ModifyStmt"; break;
+ case 193: s = "invalid ModifyStmt"; break;
+ case 194: s = "invalid ReturnStmt"; break;
+ case 195: s = "invalid Rhs"; break;
+ case 196: s = "invalid Lhs"; break;
+ case 197: s = "invalid Guard"; break;
case 198: s = "this symbol not expected in LoopSpec"; break;
case 199: s = "this symbol not expected in LoopSpec"; break;
case 200: s = "this symbol not expected in LoopSpec"; break;
case 201: s = "this symbol not expected in LoopSpec"; break;
- case 202: s = "this symbol not expected in Invariant"; break;
- case 203: s = "invalid AttributeArg"; break;
- case 204: s = "invalid CalcOp"; break;
- case 205: s = "invalid EquivOp"; break;
- case 206: s = "invalid ImpliesOp"; break;
- case 207: s = "invalid ExpliesOp"; break;
- case 208: s = "invalid AndOp"; break;
- case 209: s = "invalid OrOp"; break;
- case 210: s = "invalid RelOp"; break;
- case 211: s = "invalid AddOp"; break;
- case 212: s = "invalid UnaryExpression"; break;
+ case 202: s = "this symbol not expected in LoopSpec"; break;
+ case 203: s = "this symbol not expected in Invariant"; break;
+ case 204: s = "invalid AttributeArg"; break;
+ case 205: s = "invalid CalcOp"; break;
+ case 206: s = "invalid EquivOp"; break;
+ case 207: s = "invalid ImpliesOp"; break;
+ case 208: s = "invalid ExpliesOp"; break;
+ case 209: s = "invalid AndOp"; break;
+ case 210: s = "invalid OrOp"; break;
+ case 211: s = "invalid RelOp"; break;
+ case 212: s = "invalid AddOp"; break;
case 213: s = "invalid UnaryExpression"; break;
- case 214: s = "invalid MulOp"; break;
- case 215: s = "invalid NegOp"; break;
- case 216: s = "invalid EndlessExpression"; break;
- case 217: s = "invalid Suffix"; break;
+ case 214: s = "invalid UnaryExpression"; break;
+ case 215: s = "invalid MulOp"; break;
+ case 216: s = "invalid NegOp"; break;
+ case 217: s = "invalid EndlessExpression"; break;
case 218: s = "invalid Suffix"; break;
case 219: s = "invalid Suffix"; break;
- case 220: s = "invalid DisplayExpr"; break;
- case 221: s = "invalid MultiSetExpr"; break;
- case 222: s = "invalid ConstAtomExpression"; break;
- case 223: s = "invalid Nat"; break;
- case 224: s = "invalid ParensExpression"; break;
- case 225: s = "invalid QSep"; break;
- case 226: s = "invalid MatchExpression"; break;
- case 227: s = "invalid QuantifierGuts"; break;
- case 228: s = "invalid StmtInExpr"; break;
- case 229: s = "invalid LetExpr"; break;
- case 230: s = "invalid CasePattern"; break;
- case 231: s = "invalid Forall"; break;
- case 232: s = "invalid Exists"; break;
+ case 220: s = "invalid Suffix"; break;
+ case 221: s = "invalid DisplayExpr"; break;
+ case 222: s = "invalid MultiSetExpr"; break;
+ case 223: s = "invalid ConstAtomExpression"; break;
+ case 224: s = "invalid Nat"; break;
+ case 225: s = "invalid LambdaArrow"; break;
+ case 226: s = "invalid QSep"; break;
+ case 227: s = "invalid MatchExpression"; break;
+ case 228: s = "invalid QuantifierGuts"; break;
+ case 229: s = "invalid StmtInExpr"; break;
+ case 230: s = "invalid LetExpr"; break;
+ case 231: s = "invalid CasePattern"; break;
+ case 232: s = "invalid Forall"; break;
+ case 233: s = "invalid Exists"; break;
default: s = "error " + n; break;
}
diff --git a/Source/Dafny/Printer.cs b/Source/Dafny/Printer.cs
index 1da5e7b2..ce693036 100644
--- a/Source/Dafny/Printer.cs
+++ b/Source/Dafny/Printer.cs
@@ -1255,8 +1255,8 @@ namespace Microsoft.Dafny {
wr.Write(e.SuffixName);
if (parensNeeded) { wr.Write(")"); }
- } else if (expr is FieldSelectExpr) {
- FieldSelectExpr e = (FieldSelectExpr)expr;
+ } else if (expr is MemberSelectExpr) {
+ MemberSelectExpr e = (MemberSelectExpr)expr;
// determine if parens are needed
int opBindingStrength = 0x70;
bool parensNeeded = !(e.Obj is ImplicitThisExpr) &&
@@ -1268,7 +1268,7 @@ namespace Microsoft.Dafny {
PrintExpr(e.Obj, opBindingStrength, false, false, !parensNeeded && isFollowedBySemicolon, -1);
wr.Write(".");
}
- wr.Write(e.FieldName);
+ wr.Write(e.MemberName);
if (parensNeeded) { wr.Write(")"); }
} else if (expr is SeqSelectExpr) {
@@ -1337,6 +1337,23 @@ namespace Microsoft.Dafny {
wr.Write("]");
if (parensNeeded) { wr.Write(")"); }
}
+ } else if (expr is ApplyExpr) {
+ var e = (ApplyExpr)expr;
+ // determine if parens are needed
+ int opBindingStrength = 0x70;
+ bool parensNeeded =
+ opBindingStrength < contextBindingStrength ||
+ (fragileContext && opBindingStrength == contextBindingStrength);
+
+ if (parensNeeded) { wr.Write("("); }
+
+ PrintExpr(e.Receiver, opBindingStrength, false, false, !parensNeeded && isFollowedBySemicolon, -1);
+ wr.Write("(");
+ PrintExpressionList(e.Args, false);
+ wr.Write(")");
+
+ if (parensNeeded) { wr.Write(")"); }
+
} else if (expr is FunctionCallExpr) {
var e = (FunctionCallExpr)expr;
// determine if parens are needed
@@ -1626,6 +1643,22 @@ namespace Microsoft.Dafny {
wr.Write(" :: ");
PrintExpression(e.Term, !parensNeeded && isFollowedBySemicolon);
if (parensNeeded) { wr.Write(")"); }
+
+ } else if (expr is LambdaExpr) {
+ var e = (LambdaExpr)expr;
+ wr.Write("(");
+ wr.Write(Util.Comma(e.BoundVars, bv => bv.DisplayName + ":" + bv.Type));
+ wr.Write(")");
+ if (e.Range != null) {
+ wr.Write(" requires ");
+ PrintExpression(e.Range, false);
+ }
+ foreach (var read in e.Reads) {
+ wr.Write(" reads ");
+ PrintExpression(read.E, false);
+ }
+ wr.Write(e.OneShot ? " -> " : " => ");
+ PrintExpression(e.Body, isFollowedBySemicolon);
} else if (expr is WildcardExpr) {
wr.Write("*");
diff --git a/Source/Dafny/RefinementTransformer.cs b/Source/Dafny/RefinementTransformer.cs
index d23aadc8..d90d2362 100644
--- a/Source/Dafny/RefinementTransformer.cs
+++ b/Source/Dafny/RefinementTransformer.cs
@@ -1441,8 +1441,8 @@ namespace Microsoft.Dafny
reporter.Error(l.tok, "cannot assign to variable defined previously");
return false;
}
- } else if (l is FieldSelectExpr) {
- if (RefinementToken.IsInherited(((FieldSelectExpr)l).Field.tok, m)) {
+ } else if (l is MemberSelectExpr) {
+ if (RefinementToken.IsInherited(((MemberSelectExpr)l).Member.tok, m)) {
return false;
}
} else {
diff --git a/Source/Dafny/Resolver.cs b/Source/Dafny/Resolver.cs
index 5e7381d9..5bb85d35 100644
--- a/Source/Dafny/Resolver.cs
+++ b/Source/Dafny/Resolver.cs
@@ -902,15 +902,6 @@ namespace Microsoft.Dafny
List<TypeParameter> tyvars = cop.TypeArgs.ConvertAll(cloner.CloneTypeParam);
- /*
- Dictionary<TypeParameter, Type> su = new Dictionary<TypeParameter, Type>();
- for (int i = 0; i < tyvars.Count; i++) {
- su[cop.TypeArgs[i]] = new UserDefinedType(tyvars[i].tok, tyvars[i].Name, tyvars[i]);
- }
- var sub = new Translator.Substituter(null, new Dictionary<IVariable, Expression>(), su, null);
- // We would like to apply this substitution the new body... he-hum
- */
-
// create prefix predicate
cop.PrefixPredicate = new PrefixPredicate(cop.tok, extraName, cop.IsStatic,
tyvars, cop.OpenParen, k, formals,
@@ -1131,6 +1122,9 @@ namespace Microsoft.Dafny
} else if (t is MapType) {
var tt = (MapType)t;
return new MapType(CloneType(tt.Domain), CloneType(tt.Range));
+ } else if (t is ArrowType) {
+ var tt = (ArrowType)t;
+ return new ArrowType(tt.Args.ConvertAll(CloneType), CloneType(tt.Result));
} else if (t is UserDefinedType) {
var tt = (UserDefinedType)t;
return new UserDefinedType(tt.tok, tt.Name, tt.TypeArgs.ConvertAll(CloneType), tt.Path.ConvertAll(x => x));
@@ -1264,9 +1258,9 @@ namespace Microsoft.Dafny
var e = (ExprDotName)expr;
return new ExprDotName(e.tok, CloneExpr(e.Obj), e.SuffixName);
- } else if (expr is FieldSelectExpr) {
- var e = (FieldSelectExpr)expr;
- return new FieldSelectExpr(e.tok, CloneExpr(e.Obj), e.FieldName);
+ } else if (expr is MemberSelectExpr) {
+ var e = (MemberSelectExpr)expr;
+ return new MemberSelectExpr(e.tok, CloneExpr(e.Obj), e.MemberName);
} else if (expr is SeqSelectExpr) {
var e = (SeqSelectExpr)expr;
@@ -1334,6 +1328,9 @@ namespace Microsoft.Dafny
}
} else if (e is MapComprehension) {
return new MapComprehension(tk, bvs, range, term);
+ } else if (e is LambdaExpr) {
+ var l = (LambdaExpr)e;
+ return new LambdaExpr(tk, l.OneShot, bvs, range, l.Reads.ConvertAll(CloneFrameExpr), term);
} else {
Contract.Assert(e is SetComprehension);
return new SetComprehension(tk, bvs, range, term);
@@ -1641,22 +1638,24 @@ namespace Microsoft.Dafny
foreach (var d in declarations) {
if (d is IteratorDecl) {
var iter = (IteratorDecl)d;
+ var done = false;
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;
+ done = true;
+ break;
}
}
foreach (var p in iter.Outs) {
+ if (done) break;
if (InferRequiredEqualitySupport(tp, p.Type)) {
tp.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
- goto DONE;
+ break;
}
}
- DONE: ;
}
}
} else if (d is ClassDecl) {
@@ -1682,22 +1681,24 @@ namespace Microsoft.Dafny
}
} else if (member is Method) {
var m = (Method)member;
+ bool done = false;
foreach (var tp in m.TypeArgs) {
if (tp.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
// here's our chance to infer the need for equality support
foreach (var p in m.Ins) {
if (InferRequiredEqualitySupport(tp, p.Type)) {
tp.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
- goto DONE;
+ done = true;
+ break;
}
}
foreach (var p in m.Outs) {
+ if (done) break;
if (InferRequiredEqualitySupport(tp, p.Type)) {
tp.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
- goto DONE;
+ break;
}
}
- DONE: ;
}
}
}
@@ -1712,7 +1713,7 @@ namespace Microsoft.Dafny
var iter = (IteratorDecl)d;
foreach (var p in iter.Ins) {
if (!p.IsGhost) {
- CheckEqualityTypes_Type(p.tok, p.Type);
+ // CheckEqualityTypes_Type(p.tok, p.Type);
}
}
foreach (var p in iter.Outs) {
@@ -1729,15 +1730,18 @@ namespace Microsoft.Dafny
if (!member.IsGhost) {
if (member is Field) {
var f = (Field)member;
- CheckEqualityTypes_Type(f.tok, f.Type);
+ // CheckEqualityTypes_Type(f.tok, f.Type);
+ // Why check this?!
} else if (member is Function) {
var f = (Function)member;
foreach (var p in f.Formals) {
if (!p.IsGhost) {
- CheckEqualityTypes_Type(p.tok, p.Type);
+ // CheckEqualityTypes_Type(p.tok, p.Type);
+ // Why check this?!
}
}
- CheckEqualityTypes_Type(f.tok, f.ResultType);
+ // CheckEqualityTypes_Type(f.tok, f.ResultType);
+ // Why should we check this?!
if (f.Body != null) {
CheckEqualityTypes(f.Body);
}
@@ -1745,12 +1749,12 @@ namespace Microsoft.Dafny
var m = (Method)member;
foreach (var p in m.Ins) {
if (!p.IsGhost) {
- CheckEqualityTypes_Type(p.tok, p.Type);
+ // CheckEqualityTypes_Type(p.tok, p.Type);
}
}
foreach (var p in m.Outs) {
if (!p.IsGhost) {
- CheckEqualityTypes_Type(p.tok, p.Type);
+ // CheckEqualityTypes_Type(p.tok, p.Type);
}
}
if (m.Body != null) {
@@ -1975,7 +1979,17 @@ namespace Microsoft.Dafny
if (e != null) {
foreach (var bv in e.BoundVars) {
if (bv.Type.Normalize() is TypeProxy) {
- Error(bv.tok, "type of bound variable '{0}' could not determined; please specify the type explicitly", bv.Name);
+ Error(bv.tok, "type of bound variable '{0}' could not determined; please specify the type explicitly",
+ bv.Name);
+ }
+ }
+ }
+ } else if (expr is MemberSelectExpr) {
+ var e = (MemberSelectExpr)expr;
+ if (e.Member is Function) {
+ foreach (var p in e.TypeApplication) {
+ if (p.Normalize() is TypeProxy) {
+ Error(e.tok, "type '{0}' to the function '{1}' is not determined", p, e.Member.Name);
}
}
}
@@ -2481,7 +2495,7 @@ namespace Microsoft.Dafny
Error(e.E0, "{0} can only be applied to expressions of types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t0, TypeEqualityErrorMessageHint(t0));
} else if (!t1.SupportsEquality) {
Error(e.E1, "{0} can only be applied to expressions of types that support equality (got {1}){2}", BinaryExpr.OpcodeString(e.Op), t1, TypeEqualityErrorMessageHint(t1));
- }
+ }
break;
default:
switch (e.ResolvedOp) {
@@ -3149,7 +3163,7 @@ namespace Microsoft.Dafny
var option = f.TypeArgs.Count == 0 ? new ResolveTypeOption(f) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowPrefix);
foreach (Formal p in f.Formals) {
if (!scope.Push(p.Name, p)) {
- Error(p, "Duplicate earameter name: {0}", p.Name);
+ Error(p, "Duplicate parameter name: {0}", p.Name);
}
ResolveType(p.tok, p.Type, option, f.TypeArgs);
}
@@ -3490,12 +3504,12 @@ namespace Microsoft.Dafny
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))));
+ new MemberSelectExpr(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>()))));
+ new MemberSelectExpr(p.tok, new ThisExpr(p.tok), p.Name), new SeqDisplayExpr(p.tok, new List<Expression>()))));
}
// ensures this.Valid();
var valid_call = new FunctionCallExpr(iter.tok, "Valid", new ThisExpr(iter.tok), iter.tok, new List<Expression>());
@@ -3513,7 +3527,7 @@ namespace Microsoft.Dafny
}
}
ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Eq,
- new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_reads"),
+ new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), "_reads"),
new OldExpr(iter.tok, frameSet))));
// ensures this._modifies == old(ModifiesClause);
modSetSingletons = new List<Expression>();
@@ -3528,26 +3542,26 @@ namespace Microsoft.Dafny
}
}
ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Eq,
- new FieldSelectExpr(iter.tok, new ThisExpr(iter.tok), "_modifies"),
+ new MemberSelectExpr(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 MemberSelectExpr(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 MemberSelectExpr(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;
+ reads.Add(new FrameExpression(iter.tok, new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), "_reads"), null)); // reads this._reads;
+ reads.Add(new FrameExpression(iter.tok, new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"), null)); // reads this._new;
// ---------- here comes method MoveNext() ----------
// requires this.Valid();
@@ -3559,14 +3573,14 @@ namespace Microsoft.Dafny
// 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));
+ mod.Add(new FrameExpression(iter.tok, new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), "_modifies"), null));
+ mod.Add(new FrameExpression(iter.tok, new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"), null));
// ensures fresh(_new - old(_new));
ens = iter.Member_MoveNext.Ens;
ens.Add(new MaybeFreeExpression(new UnaryOpExpr(iter.tok, UnaryOpExpr.Opcode.Fresh,
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"))))));
+ new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"),
+ new OldExpr(iter.tok, new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), "_new"))))));
// ensures more ==> this.Valid();
valid_call = new FunctionCallExpr(iter.tok, "Valid", new ThisExpr(iter.tok), iter.tok, new List<Expression>());
ens.Add(new MaybeFreeExpression(new BinaryExpr(iter.tok, BinaryExpr.Opcode.Imp,
@@ -3579,10 +3593,10 @@ namespace Microsoft.Dafny
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);
+ new OldExpr(iter.tok, new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), ys.Name)),
+ new SeqDisplayExpr(iter.tok, new List<Expression>() { new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), y.Name) })),
+ new OldExpr(iter.tok, new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), ys.Name)));
+ var eq = new BinaryExpr(iter.tok, BinaryExpr.Opcode.Eq, new MemberSelectExpr(iter.tok, new ThisExpr(iter.tok), ys.Name), ite);
ens.Add(new MaybeFreeExpression(eq));
}
// ensures more ==> YieldEnsures;
@@ -3602,7 +3616,7 @@ namespace Microsoft.Dafny
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.Expressions.Add(new MemberSelectExpr(p.tok, new ThisExpr(p.tok), iter.DecreasesFields[i].Name));
}
iter.Member_MoveNext.Decreases.Attributes = iter.Decreases.Attributes;
}
@@ -3754,14 +3768,20 @@ namespace Microsoft.Dafny
if (t.Arg.IsSubrangeType) {
Error(tok, "sorry, cannot instantiate collection type with a subrange type");
}
+
} else if (type is UserDefinedType) {
var t = (UserDefinedType)type;
+ var isArrow = t is ArrowType;
foreach (Type tt in t.TypeArgs) {
ResolveType(t.tok, tt, option, defaultTypeArguments);
- if (tt.IsSubrangeType) {
+ if (tt.IsSubrangeType && !isArrow) {
Error(t.tok, "sorry, cannot instantiate type parameter with a subrange type");
}
}
+ if (isArrow) {
+ return null;
+ // Done already, all arrow types are resolved at construction time
+ }
TypeParameter tp = t.Path.Count == 0 ? allTypeParameters.Find(t.Name) : null;
if (tp != null) {
if (t.TypeArgs.Count == 0) {
@@ -3795,10 +3815,19 @@ namespace Microsoft.Dafny
}
if (j == t.Path.Count) {
if (!sig.TopLevels.TryGetValue(t.Name, out d)) {
- if (j == 0)
- Error(t.tok, "Undeclared top-level type or type parameter: {0} (did you forget to qualify a name?)", t.Name);
- else
+ if (j == 0) {
+ if (option.Opt == ResolveTypeOptionEnum.AllowPrefixExtend && t.TypeArgs.Count == 0) {
+ tp = new TypeParameter(tok, t.Name, defaultTypeArguments.Count, option.Parent);
+ defaultTypeArguments.Add(tp);
+ t.ResolvedParam = tp;
+ allTypeParameters.Push(t.Name, tp);
+ } else {
+ Error(t.tok, "Undeclared top-level type or type parameter: {0} (did you forget to qualify a name?)",
+ t.Name);
+ }
+ } else {
Error(t.tok, "Undeclared type {0} in module {1}", t.Name, t.Path[t.Path.Count - 1].val);
+ }
}
} else {
// error has already been reported
@@ -3927,10 +3956,8 @@ namespace Microsoft.Dafny
// these are both resolved class/datatype types
Contract.Assert(aa.TypeArgs.Count == bb.TypeArgs.Count);
bool successSoFar = true;
- for (int i = 0; i < aa.TypeArgs.Count; i++) {
- if (!UnifyTypes(aa.TypeArgs[i], bb.TypeArgs[i])) {
- successSoFar = false;
- }
+ for (int i = 0; successSoFar && i < aa.TypeArgs.Count; i++) {
+ successSoFar = UnifyTypes(aa.TypeArgs[i], bb.TypeArgs[i]);
}
return successSoFar;
} else if (aa.ResolvedParam != null && aa.ResolvedParam == bb.ResolvedParam) {
@@ -4265,7 +4292,7 @@ namespace Microsoft.Dafny
Contract.Assert(f.Type != null);
produceLhs = ident;
} else {
- var yieldIdent = new FieldSelectExpr(f.tok, new ImplicitThisExpr(f.tok), f.Name);
+ var yieldIdent = new MemberSelectExpr(f.tok, new ImplicitThisExpr(f.tok), f.Name);
ResolveExpression(yieldIdent, true, codeContext);
produceLhs = yieldIdent;
}
@@ -4414,10 +4441,10 @@ namespace Microsoft.Dafny
}
}
}
- } else if (lhs is FieldSelectExpr) {
- var fse = (FieldSelectExpr)lhs;
- if (fse.Field != null) { // otherwise, an error was reported above
- lvalueIsGhost = fse.Field.IsGhost;
+ } else if (lhs is MemberSelectExpr) {
+ var fse = (MemberSelectExpr)lhs;
+ if (fse.Member != null) { // otherwise, an error was reported above
+ lvalueIsGhost = fse.Member.IsGhost;
if (!lvalueIsGhost) {
if (specContextOnly) {
Error(stmt, "Assignment to non-ghost field is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)");
@@ -5264,9 +5291,9 @@ namespace Microsoft.Dafny
Error(s, "actual out-parameter {0} is required to be a ghost variable", i);
}
}
- } else if (resolvedLhs is FieldSelectExpr) {
- var ll = (FieldSelectExpr)resolvedLhs;
- if (!ll.Field.IsGhost) {
+ } else if (resolvedLhs is MemberSelectExpr) {
+ var ll = (MemberSelectExpr)resolvedLhs;
+ if (!ll.Member.IsGhost) {
Error(s, "actual out-parameter {0} is required to be a ghost field", i);
}
} else {
@@ -5311,9 +5338,10 @@ namespace Microsoft.Dafny
if (!ll.Var.IsMutable) {
Error(lhs, "LHS of assignment must denote a mutable variable");
}
- } else if (lhs is FieldSelectExpr) {
- var ll = (FieldSelectExpr)lhs;
- if (!ll.Field.IsUserMutable) {
+ } else if (lhs is MemberSelectExpr) {
+ var ll = (MemberSelectExpr)lhs;
+ var field = ll.Member as Field;
+ if (field == null || !field.IsUserMutable) {
Error(lhs, "LHS of assignment must denote a mutable field");
}
} else if (lhs is SeqSelectExpr) {
@@ -5722,8 +5750,9 @@ namespace Microsoft.Dafny
if (ctype != null) {
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)) {
+ MemberDecl member = cd.Members.Find(md => md.Name == memberName);
+ if (member == null &&
+ (!classMembers.ContainsKey(cd) || !classMembers[cd].TryGetValue(memberName, out member))) {
var kind = cd is IteratorDecl ? "iterator" : "class";
if (memberName == "_ctor") {
Error(tok, "{0} {1} does not have a default constructor", kind, ctype.Name);
@@ -5756,13 +5785,13 @@ namespace Microsoft.Dafny
/// <summary>
/// Returns a resolved FieldSelectExpr.
/// </summary>
- public static FieldSelectExpr NewFieldSelectExpr(IToken tok, Expression obj, Field field, Dictionary<TypeParameter, Type> typeSubstMap) {
+ public static MemberSelectExpr NewFieldSelectExpr(IToken tok, Expression obj, Field field, Dictionary<TypeParameter, Type> typeSubstMap) {
Contract.Requires(tok != null);
Contract.Requires(obj != null);
Contract.Requires(field != null);
Contract.Requires(obj.Type != null); // "obj" is required to be resolved
- var e = new FieldSelectExpr(tok, obj, field.Name);
- e.Field = field; // resolve here
+ var e = new MemberSelectExpr(tok, obj, field.Name);
+ e.Member = field; // resolve here
e.Type = typeSubstMap == null ? field.Type : SubstType(field.Type, typeSubstMap); // resolve here
return e;
}
@@ -5811,6 +5840,9 @@ namespace Microsoft.Dafny
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected collection type
}
+ } else if (type is ArrowType) {
+ var t = (ArrowType)type;
+ return new ArrowType(t.Args.ConvertAll(u => SubstType(u, subst)), SubstType(t.Result, subst));
} else if (type is UserDefinedType) {
var t = (UserDefinedType)type;
if (t.ResolvedParam != null) {
@@ -6030,43 +6062,62 @@ namespace Microsoft.Dafny
expr.Type = new MapType(domainType, rangeType);
} else if (expr is ExprDotName) {
var e = (ExprDotName)expr;
+
// The following call to ResolveExpression is just preliminary. If it succeeds, it is redone below on the resolved expression. Thus,
// it's okay to be more lenient here and use coLevel (instead of trying to use CoLevel_Dec(coLevel), which is needed when .Name denotes a
// destructor for a co-datatype).
ResolveExpression(e.Obj, twoState, codeContext);
Contract.Assert(e.Obj.Type != null); // follows from postcondition of ResolveExpression
- Expression resolved = ResolvePredicateOrField(expr.tok, e.Obj, e.SuffixName);
+ Expression resolved = ResolveMemberSelect(expr.tok, e.Obj, e.SuffixName);
+
if (resolved == null) {
// error has already been reported by ResolvePredicateOrField
} else {
- // the following will cause e.Obj to be resolved again, but that's still correct
+ // the following will cause e.Obj to be resolved again, but that's still correct
e.ResolvedExpression = resolved;
ResolveExpression(e.ResolvedExpression, twoState, codeContext);
e.Type = e.ResolvedExpression.Type;
}
- } else if (expr is FieldSelectExpr) {
- var e = (FieldSelectExpr)expr;
+ } else if (expr is MemberSelectExpr) {
+ var e = (MemberSelectExpr)expr;
ResolveExpression(e.Obj, twoState, codeContext);
Contract.Assert(e.Obj.Type != null); // follows from postcondition of ResolveExpression
NonProxyType nptype;
- MemberDecl member = ResolveMember(expr.tok, e.Obj.Type, e.FieldName, out nptype);
+ MemberDecl member = ResolveMember(expr.tok, e.Obj.Type, e.MemberName, out nptype);
#if !NO_WORK_TO_BE_DONE
- UserDefinedType ctype = (UserDefinedType)nptype;
+ UserDefinedType ctype = nptype as UserDefinedType;
#endif
if (member == null) {
// error has already been reported by ResolveMember
+ } else if (member is Function) {
+ var fn = member as Function;
+ e.Member = fn;
+ // build the type substitution map
+ var subst = TypeSubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
+ // instantiate all type arguments from the functions. no polymorphic application
+ e.TypeApplication = new List<Type>(ctype.TypeArgs);
+ foreach (var tp in fn.TypeArgs) {
+ Type prox = new InferredTypeProxy();
+ subst[tp] = prox;
+ e.TypeApplication.Add(prox);
+ }
+ e.Type = SubstType(fn.Type, subst);
+ AddCallGraphEdge(e, codeContext, fn);
} else if (!(member is Field)) {
- Error(expr, "member {0} in type {1} does not refer to a field", e.FieldName, cce.NonNull(ctype).Name);
+ Error(expr, "member {0} in type {1} does not refer to a field or a function", e.MemberName,
+ cce.NonNull(ctype).Name);
} else {
- Contract.Assert(ctype != null && ctype.ResolvedClass != null); // follows from postcondition of ResolveMember
- e.Field = (Field)member;
+ Contract.Assert(member is Field);
+ Contract.Assert(ctype != null && ctype.ResolvedClass != null); // follows from postcondition of ResolveMember
+ var field = (Field)member;
+ e.Member = field;
if (e.Obj is StaticReceiverExpr) {
Error(expr, "a field must be selected via an object, not just a class name");
}
// build the type substitution map
var subst = TypeSubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
- e.Type = SubstType(e.Field.Type, subst);
+ e.Type = SubstType(field.Type, subst);
}
} else if (expr is SeqSelectExpr) {
@@ -6189,6 +6240,21 @@ namespace Microsoft.Dafny
FunctionCallExpr e = (FunctionCallExpr)expr;
ResolveFunctionCallExpr(e, twoState, codeContext, false);
+ } else if (expr is ApplyExpr) {
+ ApplyExpr e = (ApplyExpr)expr;
+ ResolveExpression(e.Receiver, twoState, codeContext);
+ foreach (var arg in e.Args) {
+ ResolveExpression(arg, twoState, codeContext);
+ }
+ Type tb = new InferredTypeProxy();
+ var targs = e.Args.ConvertAll(arg => arg.Type);
+ Type tc = new ArrowType(targs, tb);
+ if (!UnifyTypes(e.Receiver.Type, tc)) {
+ Error(e.OpenParen, "cannot apply arguments with types {0} to expression with type {1}",
+ Util.Comma(targs, x => x.ToString()), e.Receiver.Type, ", ");
+ }
+ expr.Type = tb;
+
} else if (expr is OldExpr) {
OldExpr e = (OldExpr)expr;
if (!twoState) {
@@ -6330,7 +6396,7 @@ namespace Microsoft.Dafny
}
expr.Type = Type.Bool;
} else if (e.Op == BinaryExpr.Opcode.Lt && e.E1.Type.IsIndDatatype) {
- if (UnifyTypes(e.E0.Type, new DatatypeProxy(false))) {
+ if (UnifyTypes(e.E0.Type, new DatatypeProxy(false)) || e.E0.Type.IsTypeParameter) {
e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankLt;
} else {
Error(expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E0.Type);
@@ -6360,7 +6426,7 @@ namespace Microsoft.Dafny
case BinaryExpr.Opcode.Gt:
case BinaryExpr.Opcode.Ge: {
if (e.Op == BinaryExpr.Opcode.Gt && e.E0.Type.IsIndDatatype) {
- if (UnifyTypes(e.E1.Type, new DatatypeProxy(false))) {
+ if (UnifyTypes(e.E1.Type, new DatatypeProxy(false)) || e.E1.Type.IsTypeParameter) {
e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankGt;
} else {
Error(expr, "arguments to rank comparison must be datatypes (instead of {0})", e.E1.Type);
@@ -6640,10 +6706,35 @@ namespace Microsoft.Dafny
}
}
}
+ } else if (expr is LambdaExpr) {
+ var e = (LambdaExpr)expr;
+ int prevErrorCount = ErrorCount;
+ scope.PushMarker();
+ foreach (BoundVar v in e.BoundVars) {
+ if (!scope.Push(v.Name, v)) {
+ Error(v, "Duplicate bound-variable name: {0}", v.Name);
+ }
+ ResolveType(v.tok, v.Type, ResolveTypeOptionEnum.InferTypeProxies, null);
+ }
+ if (e.Range != null) {
+ ResolveExpression(e.Range, twoState, codeContext);
+ Contract.Assert(e.Range.Type != null); // follows from postcondition of ResolveExpression
+ if (!UnifyTypes(e.Range.Type, Type.Bool)) {
+ Error(expr, "requires clause for lambda must be bool (instead got {0})", e.Range.Type);
+ }
+ }
+
+ foreach (var read in e.Reads) {
+ ResolveFrameExpression(read, "reads", false, codeContext);
+ }
+
+ ResolveExpression(e.Term, twoState, codeContext);
+ Contract.Assert(e.Term.Type != null);
+ scope.PopMarker();
+ expr.Type = new ArrowType(Util.Map(e.BoundVars, v => v.Type), e.Body.Type);
} else if (expr is WildcardExpr) {
expr.Type = new SetType(new ObjectType());
-
} else if (expr is StmtExpr) {
var e = (StmtExpr)expr;
int prevErrorCount = ErrorCount;
@@ -6869,7 +6960,7 @@ namespace Microsoft.Dafny
}
}
- private bool ComparableTypes(Type A, Type B) {
+ public bool ComparableTypes(Type A, Type B) {
if (A.IsArrayType && B.IsArrayType) {
Type a = UserDefinedType.ArrayElementType(A);
Type b = UserDefinedType.ArrayElementType(B);
@@ -6878,6 +6969,9 @@ namespace Microsoft.Dafny
if (A is UserDefinedType && B is UserDefinedType) {
UserDefinedType a = (UserDefinedType)A;
UserDefinedType b = (UserDefinedType)B;
+ if ((a is ArrowType) != (b is ArrowType)) {
+ return false;
+ }
if (a.ResolvedClass != null && b.ResolvedClass != null && a.ResolvedClass.Name == b.ResolvedClass.Name) {
if (a.TypeArgs.Count != b.TypeArgs.Count) {
return false; // this probably doesn't happen if the classes are the same.
@@ -6894,7 +6988,10 @@ namespace Microsoft.Dafny
}
return false;
}
- private bool CouldPossiblyBeSameType(Type A, Type B) {
+ public bool CouldPossiblyBeSameType(Type A, Type B) {
+ if ((A is ArrowType) != (B is ArrowType)) {
+ return false;
+ }
if (A.IsTypeParameter || B.IsTypeParameter) {
return true;
}
@@ -6938,9 +7035,9 @@ namespace Microsoft.Dafny
return;
}
- } else if (expr is FieldSelectExpr) {
- var e = (FieldSelectExpr)expr;
- if (e.Field != null && e.Field.IsGhost) {
+ } else if (expr is MemberSelectExpr) {
+ var e = (MemberSelectExpr)expr;
+ if (e.Member != null && e.Member.IsGhost) {
Error(expr, "ghost fields are allowed only in specification contexts");
return;
}
@@ -7044,6 +7141,10 @@ namespace Microsoft.Dafny
var e = (ChainingExpression)expr;
e.Operands.ForEach(CheckIsNonGhost);
return;
+ } else if (expr is LambdaExpr) {
+ var e = expr as LambdaExpr;
+ CheckIsNonGhost(e.Body);
+ return;
}
foreach (var ee in expr.SubExpressions) {
@@ -7052,6 +7153,21 @@ namespace Microsoft.Dafny
}
/// <summary>
+ /// If you are calling a field that could be a function, creates an ApplyExpr, otherwise an ordinary FunctionCallExpr.
+ /// </summary>
+ private Expression NewFunctionCallExpr(IToken tok, string fn, Expression receiver, IToken openParen, List<Expression> args) {
+ NonProxyType nptype;
+ MemberDecl member = ResolveMember(tok, receiver.Type, fn, out nptype);
+ var field = member as Field;
+ if (field != null) {
+ if (field.Type is ArrowType || field.Type.IsTypeParameter) {
+ return new ApplyExpr(tok, openParen, new ExprDotName(tok, receiver, fn), args);
+ }
+ }
+ return new FunctionCallExpr(tok, fn, receiver, openParen, args);
+ }
+
+ /// <summary>
/// If "!allowMethodCall" or if what is being called does not refer to a method, resolves "e" and returns "null".
/// Otherwise (that is, if "allowMethodCall" and what is being called refers to a method), resolves the receiver
/// of "e" but NOT the arguments, and returns a CallRhs corresponding to the call.
@@ -7060,6 +7176,7 @@ namespace Microsoft.Dafny
ResolveReceiver(e.Receiver, twoState, codeContext);
Contract.Assert(e.Receiver.Type != null); // follows from postcondition of ResolveExpression
NonProxyType nptype;
+
MemberDecl member = ResolveMember(e.tok, e.Receiver.Type, e.Name, out nptype);
#if !NO_WORK_TO_BE_DONE
UserDefinedType ctype = (UserDefinedType)nptype;
@@ -7123,28 +7240,35 @@ namespace Microsoft.Dafny
e.Type = SubstType(function.ResultType, e.TypeArgumentSubstitutions);
}
- // Resolution termination check
- ModuleDefinition callerModule = codeContext.EnclosingModule;
- ModuleDefinition calleeModule = function.EnclosingClass.Module;
- if (callerModule == calleeModule) {
- // intra-module call; add edge in module's call graph
- var caller = codeContext as ICallable;
- if (caller == null) {
- // don't add anything to the call graph after all
- } else if (caller is IteratorDecl) {
- callerModule.CallGraph.AddEdge(((IteratorDecl)codeContext).Member_MoveNext, function);
- } else {
- callerModule.CallGraph.AddEdge(caller, function);
- if (caller is Function) {
- ((Function)caller).AllCalls.Add(e);
- }
- if (caller == function) {
- function.IsRecursive = true; // self recursion (mutual recursion is determined elsewhere)
+ AddCallGraphEdge(e, codeContext, function);
+ }
+ return null;
+ }
+
+ private static void AddCallGraphEdge(Expression e, ICodeContext codeContext, Function function) {
+ // Resolution termination check
+ ModuleDefinition callerModule = codeContext.EnclosingModule;
+ ModuleDefinition calleeModule = function.EnclosingClass.Module;
+ if (callerModule == calleeModule) {
+ // intra-module call; add edge in module's call graph
+ var caller = codeContext as ICallable;
+ if (caller == null) {
+ // don't add anything to the call graph after all
+ } else if (caller is IteratorDecl) {
+ callerModule.CallGraph.AddEdge(((IteratorDecl)codeContext).Member_MoveNext, function);
+ } else {
+ callerModule.CallGraph.AddEdge(caller, function);
+ if (caller is Function) {
+ FunctionCallExpr ee = e as FunctionCallExpr;
+ if (ee != null) {
+ ((Function)caller).AllCalls.Add(ee);
}
}
+ if (caller == function) {
+ function.IsRecursive = true; // self recursion (mutual recursion is determined elsewhere)
+ }
}
}
- return null;
}
/// <summary>
@@ -7370,7 +7494,7 @@ namespace Microsoft.Dafny
call = null;
int nonCallArguments = e.Arguments == null ? e.Tokens.Count : e.Tokens.Count - 1;
for (; p < nonCallArguments; p++) {
- var resolved = ResolvePredicateOrField(e.Tokens[p], r, e.Tokens[p].val);
+ var resolved = ResolveMemberSelect(e.Tokens[p], r, e.Tokens[p].val);
if (resolved != null) {
r = resolved;
ResolveExpression(r, twoState, codeContext);
@@ -7401,27 +7525,32 @@ namespace Microsoft.Dafny
call = new CallRhs(e.Tokens[p], r, e.Tokens[p].val, e.Arguments);
r = null;
} else {
- r = new FunctionCallExpr(e.Tokens[p], e.Tokens[p].val, r, e.OpenParen, e.Arguments);
+ r = NewFunctionCallExpr(e.Tokens[p], e.Tokens[p].val, r, e.OpenParen, e.Arguments);
ResolveExpression(r, twoState, codeContext);
}
} else if (e.Arguments != null) {
Contract.Assert(p == e.Tokens.Count);
- Error(e.OpenParen, "non-function expression is called with parameters");
- // resolve the arguments nonetheless
- foreach (var arg in e.Arguments) {
- ResolveExpression(arg, twoState, codeContext);
+ if (r.Type is ArrowType || r.Type.IsTypeParameter) {
+ r = new ApplyExpr(e.tok, e.OpenParen, r, e.Arguments);
+ ResolveExpression(r, twoState, codeContext);
+ } else {
+ Error(e.OpenParen, "non-function expression is called with parameters");
+ // resolve the arguments nonetheless
+ foreach (var arg in e.Arguments) {
+ ResolveExpression(arg, twoState, codeContext);
+ }
}
- }
+ }
return r;
}
/// <summary>
- /// Resolves "obj . suffixName" to either a parameter-less predicate invocation or a field selection.
+ /// Resolves "obj . suffixName" to a member select expression,
/// Expects "obj" already to have been resolved.
/// On success, returns the result of the resolution--as an un-resolved expression.
/// On failure, returns null (in which case an error has been reported to the user).
/// </summary>
- Expression/*?*/ ResolvePredicateOrField(IToken tok, Expression obj, string suffixName) {
+ Expression/*?*/ ResolveMemberSelect(IToken tok, Expression obj, string suffixName) {
Contract.Requires(tok != null);
Contract.Requires(obj != null);
Contract.Requires(obj.Type != null); // obj is expected already to have been resolved
@@ -7432,12 +7561,9 @@ namespace Microsoft.Dafny
if (member == null) {
// error has already been reported by ResolveMember
return null;
- } else if (member is Predicate && ((Predicate)member).Formals.Count == 0) {
- // parameter-less predicates are allowed to be used without parentheses
- return new FunctionCallExpr(tok, suffixName, obj, null, new List<Expression>());
} else {
// assume it's a field and let the resolution of the FieldSelectExpr check any further problems
- return new FieldSelectExpr(tok, obj, suffixName);
+ return new MemberSelectExpr(tok, obj, suffixName);
}
}
@@ -7893,6 +8019,20 @@ namespace Microsoft.Dafny
s.UnionWith(t);
}
return s;
+
+ } else if (expr is LambdaExpr) {
+ var e = (LambdaExpr)expr;
+ var s = FreeVariables(e.Term);
+ if (e.Range != null) {
+ s.UnionWith(FreeVariables(e.Range));
+ }
+ foreach (var fe in e.Reads) {
+ s.UnionWith(FreeVariables(fe.E));
+ }
+ foreach (var bv in e.BoundVars) {
+ s.Remove(bv);
+ }
+ return s;
} else {
ISet<IVariable> s = null;
@@ -8141,10 +8281,14 @@ namespace Microsoft.Dafny
} else if (expr is MapDisplayExpr) {
MapDisplayExpr e = (MapDisplayExpr)expr;
return e.Elements.Exists(p => UsesSpecFeatures(p.A) || UsesSpecFeatures(p.B));
- } else if (expr is FieldSelectExpr) {
- FieldSelectExpr e = (FieldSelectExpr)expr;
- return cce.NonNull(e.Field).IsGhost || UsesSpecFeatures(e.Obj);
- } else if (expr is SeqSelectExpr) {
+ } else if (expr is MemberSelectExpr) {
+ MemberSelectExpr e = (MemberSelectExpr) expr;
+ if (e.Member != null) {
+ return cce.NonNull(e.Member).IsGhost || UsesSpecFeatures(e.Obj);
+ } else {
+ return false;
+ }
+ } else if (expr is SeqSelectExpr) {
SeqSelectExpr e = (SeqSelectExpr)expr;
return UsesSpecFeatures(e.Seq) ||
(e.E0 != null && UsesSpecFeatures(e.E0)) ||
@@ -8163,6 +8307,9 @@ namespace Microsoft.Dafny
return true;
}
return e.Args.Exists(arg => UsesSpecFeatures(arg));
+ } else if (expr is ApplyExpr) {
+ ApplyExpr e = (ApplyExpr)expr;
+ return UsesSpecFeatures(e.Receiver) || e.Args.Exists(UsesSpecFeatures);
} else if (expr is OldExpr) {
OldExpr e = (OldExpr)expr;
return UsesSpecFeatures(e.E);
@@ -8212,6 +8359,8 @@ namespace Microsoft.Dafny
} else if (expr is MapComprehension) {
var e = (MapComprehension)expr;
return (UsesSpecFeatures(e.Range)) || (UsesSpecFeatures(e.Term));
+ } else if (expr is LambdaExpr) {
+ return Contract.Exists(expr.SubExpressions, UsesSpecFeatures);
} else if (expr is WildcardExpr) {
return false;
} else if (expr is StmtExpr) {
@@ -8232,7 +8381,8 @@ namespace Microsoft.Dafny
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected expression
}
- }
+}
+
/// <summary>
/// This method adds to "coConclusions" all copredicate calls and codatatype equalities that occur
@@ -8360,9 +8510,9 @@ namespace Microsoft.Dafny
}
return;
}
- } else if (expr is FieldSelectExpr) {
- var e = (FieldSelectExpr)expr;
- if (e.Field.EnclosingClass is CoDatatypeDecl) {
+ } else if (expr is MemberSelectExpr) {
+ var e = (MemberSelectExpr)expr;
+ if (e.Member.EnclosingClass is CoDatatypeDecl) {
int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel + 1;
CheckCoCalls(e.Obj, dl, null, coCandidates);
return;
@@ -8401,7 +8551,7 @@ namespace Microsoft.Dafny
CheckCoCalls(arg, int.MaxValue, null, coCandidates);
}
// Second, investigate the possibility that this call itself may be a candidate co-call
- if (ModuleDefinition.InSameSCC(currentFunction, e.Function)) {
+ if (e.Name != "requires" && ModuleDefinition.InSameSCC(currentFunction, e.Function)) {
// This call goes to another function in the same recursive cluster
if (destructionLevel > 0) {
// a potentially destructive context
diff --git a/Source/Dafny/Rewriter.cs b/Source/Dafny/Rewriter.cs
index ca3c105d..f57c1380 100644
--- a/Source/Dafny/Rewriter.cs
+++ b/Source/Dafny/Rewriter.cs
@@ -109,7 +109,7 @@ namespace Microsoft.Dafny
// reads this;
valid.Reads.Add(new FrameExpression(tok, new ThisExpr(tok), null));
// reads Repr;
- valid.Reads.Add(new FrameExpression(tok, new FieldSelectExpr(tok, new ImplicitThisExpr(tok), "Repr"), null));
+ valid.Reads.Add(new FrameExpression(tok, new MemberSelectExpr(tok, new ImplicitThisExpr(tok), "Repr"), null));
} else if (member is Constructor) {
var ctor = (Constructor)member;
// modifies this;
@@ -118,7 +118,7 @@ namespace Microsoft.Dafny
ctor.Ens.Insert(0, new MaybeFreeExpression(new FunctionCallExpr(tok, "Valid", new ImplicitThisExpr(tok), tok, new List<Expression>())));
// ensures fresh(Repr - {this});
var freshness = new UnaryOpExpr(tok, UnaryOpExpr.Opcode.Fresh, new BinaryExpr(tok, BinaryExpr.Opcode.Sub,
- new FieldSelectExpr(tok, new ImplicitThisExpr(tok), "Repr"),
+ new MemberSelectExpr(tok, new ImplicitThisExpr(tok), "Repr"),
new SetDisplayExpr(tok, new List<Expression>() { new ThisExpr(tok) })));
ctor.Ens.Insert(1, new MaybeFreeExpression(freshness));
} else if (member is Method && !member.IsStatic) {
@@ -187,8 +187,8 @@ namespace Microsoft.Dafny
self.Type = ty;
var implicitSelf = new ImplicitThisExpr(clTok);
implicitSelf.Type = ty;
- var Repr = new FieldSelectExpr(clTok, implicitSelf, "Repr");
- Repr.Field = ReprField;
+ var Repr = new MemberSelectExpr(clTok, implicitSelf, "Repr");
+ Repr.Member = ReprField;
Repr.Type = ReprField.Type;
var cNull = new LiteralExpr(clTok);
cNull.Type = new ObjectType();
@@ -224,8 +224,8 @@ namespace Microsoft.Dafny
// F != null ==> F in Repr (so, nothing else to do)
} else {
// F != null ==> F in Repr && F.Repr <= Repr && this !in F.Repr
- var FRepr = new FieldSelectExpr(tok, F, ff.Item2.Name);
- FRepr.Field = ff.Item2;
+ var FRepr = new MemberSelectExpr(tok, F, ff.Item2.Name);
+ FRepr.Member = ff.Item2;
FRepr.Type = ff.Item2.Type;
var c2 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.Subset, FRepr, Repr);
var c3 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NotInSet, self, FRepr);
@@ -826,9 +826,9 @@ namespace Microsoft.Dafny
reqs.AddRange(generateAutoReqs(p.A));
reqs.AddRange(generateAutoReqs(p.B));
}
- } else if (expr is FieldSelectExpr) {
- FieldSelectExpr e = (FieldSelectExpr)expr;
- Contract.Assert(e.Field != null);
+ } else if (expr is MemberSelectExpr) {
+ MemberSelectExpr e = (MemberSelectExpr)expr;
+ Contract.Assert(e.Member != null && e.Member is Field);
reqs.AddRange(generateAutoReqs(e.Obj));
} else if (expr is SeqSelectExpr) {
diff --git a/Source/Dafny/Scanner.cs b/Source/Dafny/Scanner.cs
index 87dee5aa..7d453d2d 100644
--- a/Source/Dafny/Scanner.cs
+++ b/Source/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 = 126;
- const int noSym = 126;
+ const int maxT = 127;
+ const int noSym = 127;
[ContractInvariantMethod]
@@ -255,39 +255,39 @@ public class Scanner {
for (int i = 92; i <= 92; ++i) start[i] = 1;
for (int i = 95; i <= 95; ++i) start[i] = 1;
for (int i = 98; i <= 122; ++i) start[i] = 1;
- for (int i = 49; i <= 57; ++i) start[i] = 22;
+ for (int i = 49; i <= 57; ++i) start[i] = 24;
for (int i = 34; i <= 34; ++i) start[i] = 11;
- start[97] = 23;
- start[48] = 24;
+ start[97] = 25;
+ start[48] = 26;
start[58] = 64;
start[59] = 13;
- start[123] = 14;
- start[125] = 15;
- start[40] = 16;
- start[41] = 17;
- start[42] = 18;
- start[33] = 65;
- start[61] = 66;
- start[124] = 67;
- start[44] = 31;
- start[46] = 68;
- start[60] = 69;
- start[62] = 70;
- start[96] = 33;
- start[91] = 36;
- start[93] = 37;
- start[35] = 39;
- start[8800] = 42;
- start[8804] = 43;
- start[8805] = 44;
- start[8660] = 46;
- start[8658] = 48;
- start[8656] = 49;
- start[38] = 50;
- start[8743] = 52;
- start[8744] = 54;
- start[43] = 55;
- start[45] = 56;
+ start[61] = 65;
+ start[45] = 66;
+ start[123] = 16;
+ start[125] = 17;
+ start[40] = 18;
+ start[41] = 19;
+ start[42] = 20;
+ start[33] = 67;
+ start[124] = 68;
+ start[44] = 33;
+ start[46] = 69;
+ start[60] = 70;
+ start[62] = 71;
+ start[96] = 35;
+ start[91] = 38;
+ start[93] = 39;
+ start[35] = 40;
+ start[8800] = 43;
+ start[8804] = 44;
+ start[8805] = 45;
+ start[8660] = 47;
+ start[8658] = 49;
+ start[8656] = 50;
+ start[38] = 51;
+ start[8743] = 53;
+ start[8744] = 55;
+ start[43] = 56;
start[47] = 57;
start[37] = 58;
start[172] = 59;
@@ -491,75 +491,75 @@ public class Scanner {
void CheckLiteral() {
switch (t.val) {
- case "include": t.kind = 15; break;
- case "abstract": t.kind = 16; break;
- case "module": t.kind = 17; break;
- case "refines": t.kind = 18; break;
- case "import": t.kind = 19; break;
- case "opened": t.kind = 20; break;
- case "as": t.kind = 22; break;
- case "default": t.kind = 23; break;
- case "class": t.kind = 24; break;
- case "ghost": t.kind = 25; break;
- case "static": t.kind = 26; break;
- case "datatype": t.kind = 27; break;
- case "codatatype": t.kind = 28; break;
- case "var": t.kind = 30; break;
- case "type": t.kind = 32; break;
- case "iterator": t.kind = 34; break;
- case "yields": t.kind = 35; break;
- case "returns": t.kind = 36; break;
- case "method": t.kind = 40; break;
- case "lemma": t.kind = 41; break;
- case "colemma": t.kind = 42; break;
- case "comethod": t.kind = 43; break;
- case "constructor": t.kind = 44; break;
- case "modifies": t.kind = 45; break;
- case "free": t.kind = 46; break;
- case "requires": t.kind = 47; break;
- case "ensures": t.kind = 48; break;
- case "decreases": t.kind = 49; break;
- case "reads": t.kind = 50; break;
- case "yield": t.kind = 51; break;
- case "bool": t.kind = 52; break;
- case "nat": t.kind = 53; break;
- case "int": t.kind = 54; break;
- case "real": t.kind = 55; break;
- case "set": t.kind = 56; break;
- case "multiset": t.kind = 57; break;
- case "seq": t.kind = 58; break;
- case "map": t.kind = 59; break;
- case "object": t.kind = 60; break;
- case "function": t.kind = 62; break;
- case "predicate": t.kind = 63; break;
- case "copredicate": t.kind = 64; break;
- case "label": t.kind = 66; break;
- case "break": t.kind = 67; break;
- case "where": t.kind = 68; break;
- case "return": t.kind = 70; break;
- case "assume": t.kind = 72; break;
- case "new": t.kind = 73; break;
- case "if": t.kind = 76; break;
- case "else": t.kind = 77; break;
- case "case": t.kind = 78; break;
- case "while": t.kind = 80; break;
- case "invariant": t.kind = 81; break;
- case "match": t.kind = 82; break;
- case "assert": t.kind = 83; break;
- case "print": t.kind = 84; break;
- case "forall": t.kind = 85; break;
- case "parallel": t.kind = 86; break;
- case "modify": t.kind = 87; break;
- case "calc": t.kind = 88; break;
- case "in": t.kind = 106; break;
- case "false": t.kind = 113; break;
- case "true": t.kind = 114; break;
- case "null": t.kind = 115; break;
- case "this": t.kind = 116; break;
- case "fresh": t.kind = 117; break;
- case "old": t.kind = 118; break;
- case "then": t.kind = 119; break;
- case "exists": t.kind = 122; break;
+ case "reads": t.kind = 11; break;
+ case "requires": t.kind = 12; break;
+ case "include": t.kind = 19; break;
+ case "abstract": t.kind = 20; break;
+ case "module": t.kind = 21; break;
+ case "refines": t.kind = 22; break;
+ case "import": t.kind = 23; break;
+ case "opened": t.kind = 24; break;
+ case "as": t.kind = 26; break;
+ case "default": t.kind = 27; break;
+ case "class": t.kind = 28; break;
+ case "ghost": t.kind = 29; break;
+ case "static": t.kind = 30; break;
+ case "datatype": t.kind = 31; break;
+ case "codatatype": t.kind = 32; break;
+ case "var": t.kind = 34; break;
+ case "type": t.kind = 36; break;
+ case "iterator": t.kind = 38; break;
+ case "yields": t.kind = 39; break;
+ case "returns": t.kind = 40; break;
+ case "method": t.kind = 44; break;
+ case "lemma": t.kind = 45; break;
+ case "colemma": t.kind = 46; break;
+ case "comethod": t.kind = 47; break;
+ case "constructor": t.kind = 48; break;
+ case "modifies": t.kind = 49; break;
+ case "free": t.kind = 50; break;
+ case "ensures": t.kind = 51; break;
+ case "decreases": t.kind = 52; break;
+ case "yield": t.kind = 53; break;
+ case "bool": t.kind = 54; break;
+ case "nat": t.kind = 55; break;
+ case "int": t.kind = 56; break;
+ case "real": t.kind = 57; break;
+ case "set": t.kind = 58; break;
+ case "multiset": t.kind = 59; break;
+ case "seq": t.kind = 60; break;
+ case "map": t.kind = 61; break;
+ case "object": t.kind = 62; break;
+ case "function": t.kind = 64; break;
+ case "predicate": t.kind = 65; break;
+ case "copredicate": t.kind = 66; break;
+ case "label": t.kind = 68; break;
+ case "break": t.kind = 69; break;
+ case "where": t.kind = 70; break;
+ case "return": t.kind = 72; break;
+ case "assume": t.kind = 74; break;
+ case "new": t.kind = 75; break;
+ case "if": t.kind = 78; break;
+ case "else": t.kind = 79; break;
+ case "case": t.kind = 80; break;
+ case "while": t.kind = 81; break;
+ case "invariant": t.kind = 82; break;
+ case "match": t.kind = 83; break;
+ case "assert": t.kind = 84; break;
+ case "print": t.kind = 85; break;
+ case "forall": t.kind = 86; break;
+ case "parallel": t.kind = 87; break;
+ case "modify": t.kind = 88; break;
+ case "calc": t.kind = 89; break;
+ case "in": t.kind = 107; break;
+ case "false": t.kind = 114; break;
+ case "true": t.kind = 115; break;
+ case "null": t.kind = 116; break;
+ case "this": t.kind = 117; break;
+ case "fresh": t.kind = 118; break;
+ case "old": t.kind = 119; break;
+ case "then": t.kind = 120; break;
+ case "exists": t.kind = 123; break;
default: break;
}
}
@@ -644,87 +644,87 @@ public class Scanner {
case 15:
{t.kind = 10; break;}
case 16:
- {t.kind = 11; break;}
+ {t.kind = 13; break;}
case 17:
- {t.kind = 12; break;}
+ {t.kind = 14; break;}
case 18:
- {t.kind = 13; break;}
+ {t.kind = 15; break;}
case 19:
- if (ch == 'n') {AddCh(); goto case 20;}
- else {goto case 0;}
+ {t.kind = 16; break;}
case 20:
- if (ch <= '&' || ch >= '(' && ch <= '/' || ch >= ':' && ch <= '>' || ch == '@' || ch == '[' || ch >= ']' && ch <= '^' || ch == '`' || ch >= '{' && ch <= 65535) {apx++; AddCh(); goto case 21;}
- else {goto case 0;}
+ {t.kind = 17; break;}
case 21:
+ if (ch == 'n') {AddCh(); goto case 22;}
+ else {goto case 0;}
+ case 22:
+ if (ch <= '&' || ch >= '(' && ch <= '/' || ch >= ':' && ch <= '>' || ch == '@' || ch == '[' || ch >= ']' && ch <= '^' || ch == '`' || ch >= '{' && ch <= 65535) {apx++; AddCh(); goto case 23;}
+ else {goto case 0;}
+ case 23:
{
tlen -= apx;
SetScannerBehindT();
- t.kind = 14; break;}
- case 22:
+ t.kind = 18; break;}
+ case 24:
recEnd = pos; recKind = 2;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 22;}
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 24;}
else if (ch == '.') {AddCh(); goto case 9;}
else {t.kind = 2; break;}
- case 23:
+ case 25:
recEnd = pos; recKind = 1;
if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'a' && ch <= 'q' || ch >= 's' && ch <= 'z') {AddCh(); goto case 2;}
- else if (ch == 'r') {AddCh(); goto case 26;}
+ else if (ch == 'r') {AddCh(); goto case 28;}
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
- case 24:
+ case 26:
recEnd = pos; recKind = 2;
- if (ch >= '0' && ch <= '9') {AddCh(); goto case 22;}
+ if (ch >= '0' && ch <= '9') {AddCh(); goto case 24;}
else if (ch == 'x') {AddCh(); goto case 7;}
else if (ch == '.') {AddCh(); goto case 9;}
else {t.kind = 2; break;}
- case 25:
+ case 27:
recEnd = pos; recKind = 1;
- if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 25;}
+ if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 27;}
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
- case 26:
+ case 28:
recEnd = pos; recKind = 1;
if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'a' && ch <= 'q' || ch >= 's' && ch <= 'z') {AddCh(); goto case 3;}
- else if (ch == 'r') {AddCh(); goto case 27;}
+ else if (ch == 'r') {AddCh(); goto case 29;}
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
- case 27:
+ case 29:
recEnd = pos; recKind = 1;
if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'b' && ch <= 'z') {AddCh(); goto case 4;}
- else if (ch == 'a') {AddCh(); goto case 28;}
+ else if (ch == 'a') {AddCh(); goto case 30;}
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
- case 28:
+ case 30:
recEnd = pos; recKind = 1;
if (ch == 39 || ch >= '0' && ch <= '9' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'a' && ch <= 'x' || ch == 'z') {AddCh(); goto case 5;}
- else if (ch == 'y') {AddCh(); goto case 29;}
+ else if (ch == 'y') {AddCh(); goto case 31;}
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
- case 29:
+ case 31:
recEnd = pos; recKind = 5;
if (ch == 39 || ch == '0' || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 6;}
- else if (ch >= '1' && ch <= '9') {AddCh(); goto case 30;}
+ else if (ch >= '1' && ch <= '9') {AddCh(); goto case 32;}
else {t.kind = 5; break;}
- case 30:
+ case 32:
recEnd = pos; recKind = 5;
- if (ch == 39 || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 25;}
- else if (ch >= '0' && ch <= '9') {AddCh(); goto case 30;}
+ if (ch == 39 || ch == '?' || ch >= 'A' && ch <= 'Z' || ch == 92 || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 27;}
+ else if (ch >= '0' && ch <= '9') {AddCh(); goto case 32;}
else {t.kind = 5; break;}
- case 31:
- {t.kind = 31; break;}
- case 32:
- {t.kind = 37; break;}
case 33:
- {t.kind = 65; break;}
+ {t.kind = 35; break;}
case 34:
- {t.kind = 69; break;}
+ {t.kind = 41; break;}
case 35:
- {t.kind = 71; break;}
+ {t.kind = 67; break;}
case 36:
- {t.kind = 74; break;}
+ {t.kind = 71; break;}
case 37:
- {t.kind = 75; break;}
+ {t.kind = 73; break;}
case 38:
- {t.kind = 79; break;}
+ {t.kind = 76; break;}
case 39:
- {t.kind = 89; break;}
+ {t.kind = 77; break;}
case 40:
- {t.kind = 91; break;}
+ {t.kind = 90; break;}
case 41:
{t.kind = 92; break;}
case 42:
@@ -742,12 +742,12 @@ public class Scanner {
case 48:
{t.kind = 99; break;}
case 49:
- {t.kind = 101; break;}
+ {t.kind = 100; break;}
case 50:
- if (ch == '&') {AddCh(); goto case 51;}
- else {goto case 0;}
- case 51:
{t.kind = 102; break;}
+ case 51:
+ if (ch == '&') {AddCh(); goto case 52;}
+ else {goto case 0;}
case 52:
{t.kind = 103; break;}
case 53:
@@ -755,71 +755,75 @@ public class Scanner {
case 54:
{t.kind = 105; break;}
case 55:
- {t.kind = 108; break;}
+ {t.kind = 106; break;}
case 56:
{t.kind = 109; break;}
case 57:
- {t.kind = 110; break;}
- case 58:
{t.kind = 111; break;}
- case 59:
+ case 58:
{t.kind = 112; break;}
+ case 59:
+ {t.kind = 113; break;}
case 60:
- {t.kind = 121; break;}
+ {t.kind = 122; break;}
case 61:
- {t.kind = 123; break;}
- case 62:
{t.kind = 124; break;}
- case 63:
+ case 62:
{t.kind = 125; break;}
+ case 63:
+ {t.kind = 126; break;}
case 64:
recEnd = pos; recKind = 7;
- if (ch == '=') {AddCh(); goto case 34;}
- else if (ch == '|') {AddCh(); goto case 35;}
+ if (ch == '=') {AddCh(); goto case 36;}
+ else if (ch == '|') {AddCh(); goto case 37;}
else if (ch == ':') {AddCh(); goto case 62;}
else {t.kind = 7; break;}
case 65:
- recEnd = pos; recKind = 107;
- if (ch == 'i') {AddCh(); goto case 19;}
- else if (ch == '=') {AddCh(); goto case 41;}
- else {t.kind = 107; break;}
+ recEnd = pos; recKind = 25;
+ if (ch == '>') {AddCh(); goto case 14;}
+ else if (ch == '=') {AddCh(); goto case 72;}
+ else {t.kind = 25; break;}
case 66:
- recEnd = pos; recKind = 21;
- if (ch == '=') {AddCh(); goto case 71;}
- else if (ch == '>') {AddCh(); goto case 38;}
- else {t.kind = 21; break;}
+ recEnd = pos; recKind = 110;
+ if (ch == '>') {AddCh(); goto case 15;}
+ else {t.kind = 110; break;}
case 67:
- recEnd = pos; recKind = 29;
- if (ch == '|') {AddCh(); goto case 53;}
- else {t.kind = 29; break;}
+ recEnd = pos; recKind = 108;
+ if (ch == 'i') {AddCh(); goto case 21;}
+ else if (ch == '=') {AddCh(); goto case 42;}
+ else {t.kind = 108; break;}
case 68:
- recEnd = pos; recKind = 61;
- if (ch == '.') {AddCh(); goto case 72;}
- else {t.kind = 61; break;}
+ recEnd = pos; recKind = 33;
+ if (ch == '|') {AddCh(); goto case 54;}
+ else {t.kind = 33; break;}
case 69:
- recEnd = pos; recKind = 38;
- if (ch == '=') {AddCh(); goto case 73;}
- else {t.kind = 38; break;}
+ recEnd = pos; recKind = 63;
+ if (ch == '.') {AddCh(); goto case 73;}
+ else {t.kind = 63; break;}
case 70:
- recEnd = pos; recKind = 39;
- if (ch == '=') {AddCh(); goto case 40;}
- else {t.kind = 39; break;}
+ recEnd = pos; recKind = 42;
+ if (ch == '=') {AddCh(); goto case 74;}
+ else {t.kind = 42; break;}
case 71:
- recEnd = pos; recKind = 33;
- if (ch == '>') {AddCh(); goto case 47;}
- else {t.kind = 33; break;}
+ recEnd = pos; recKind = 43;
+ if (ch == '=') {AddCh(); goto case 41;}
+ else {t.kind = 43; break;}
case 72:
- recEnd = pos; recKind = 120;
- if (ch == '.') {AddCh(); goto case 32;}
- else {t.kind = 120; break;}
+ recEnd = pos; recKind = 37;
+ if (ch == '>') {AddCh(); goto case 48;}
+ else {t.kind = 37; break;}
case 73:
- recEnd = pos; recKind = 90;
- if (ch == '=') {AddCh(); goto case 74;}
- else {t.kind = 90; break;}
+ recEnd = pos; recKind = 121;
+ if (ch == '.') {AddCh(); goto case 34;}
+ else {t.kind = 121; break;}
case 74:
- recEnd = pos; recKind = 100;
- if (ch == '>') {AddCh(); goto case 45;}
- else {t.kind = 100; break;}
+ recEnd = pos; recKind = 91;
+ if (ch == '=') {AddCh(); goto case 75;}
+ else {t.kind = 91; break;}
+ case 75:
+ recEnd = pos; recKind = 101;
+ if (ch == '>') {AddCh(); goto case 46;}
+ else {t.kind = 101; break;}
}
t.val = new String(tval, 0, tlen);
diff --git a/Source/Dafny/Translator.cs b/Source/Dafny/Translator.cs
index a936200e..63158bd7 100644
--- a/Source/Dafny/Translator.cs
+++ b/Source/Dafny/Translator.cs
@@ -29,6 +29,8 @@ namespace Microsoft.Dafny {
// translation state
readonly Dictionary<TopLevelDecl/*!*/,Bpl.Constant/*!*/>/*!*/ classes = new Dictionary<TopLevelDecl/*!*/,Bpl.Constant/*!*/>();
readonly Dictionary<TopLevelDecl, string>/*!*/ classConstants = new Dictionary<TopLevelDecl, string>();
+ readonly Dictionary<int, string> functionConstants = new Dictionary<int, string>();
+ readonly Dictionary<Function, string> functionHandles = new Dictionary<Function, string>();
readonly Dictionary<Field/*!*/,Bpl.Constant/*!*/>/*!*/ fields = new Dictionary<Field/*!*/,Bpl.Constant/*!*/>();
readonly Dictionary<Field/*!*/, Bpl.Function/*!*/>/*!*/ fieldFunctions = new Dictionary<Field/*!*/, Bpl.Function/*!*/>();
readonly Dictionary<string, Bpl.Constant> fieldConstants = new Dictionary<string,Constant>();
@@ -65,6 +67,7 @@ namespace Microsoft.Dafny {
public readonly Bpl.Type ClassNameType;
public readonly Bpl.Type NameFamilyType;
public readonly Bpl.Type DatatypeType;
+ public readonly Bpl.Type HandleType;
public readonly Bpl.Type LayerType;
public readonly Bpl.Type DtCtorId;
public readonly Bpl.Type Ty;
@@ -81,11 +84,11 @@ namespace Microsoft.Dafny {
Contract.Invariant(ArrayLength != null);
Contract.Invariant(seqTypeCtor != null);
Contract.Invariant(fieldName != null);
- Contract.Invariant(HeapType != null);
Contract.Invariant(HeapVarName != null);
Contract.Invariant(ClassNameType != null);
Contract.Invariant(NameFamilyType != null);
Contract.Invariant(DatatypeType != null);
+ Contract.Invariant(HandleType != null);
Contract.Invariant(LayerType != null);
Contract.Invariant(DtCtorId != null);
Contract.Invariant(Ty != null);
@@ -143,7 +146,7 @@ namespace Microsoft.Dafny {
Bpl.TypeSynonymDecl setTypeCtor, Bpl.TypeSynonymDecl multiSetTypeCtor, Bpl.TypeCtorDecl mapTypeCtor, Bpl.Function arrayLength, Bpl.TypeCtorDecl seqTypeCtor, Bpl.TypeCtorDecl fieldNameType,
Bpl.TypeCtorDecl tyType, Bpl.TypeCtorDecl tyTagType,
Bpl.GlobalVariable heap, Bpl.TypeCtorDecl classNameType, Bpl.TypeCtorDecl nameFamilyType,
- Bpl.TypeCtorDecl datatypeType, Bpl.TypeCtorDecl layerType, Bpl.TypeCtorDecl dtCtorId,
+ Bpl.TypeCtorDecl datatypeType, Bpl.TypeCtorDecl handleType, Bpl.TypeCtorDecl layerType, Bpl.TypeCtorDecl dtCtorId,
Bpl.Constant allocField) {
#region Non-null preconditions on parameters
Contract.Requires(refType != null);
@@ -182,6 +185,7 @@ namespace Microsoft.Dafny {
this.ClassNameType = new Bpl.CtorType(Token.NoToken, classNameType, new List<Bpl.Type>());
this.NameFamilyType = new Bpl.CtorType(Token.NoToken, nameFamilyType, new List<Bpl.Type>());
this.DatatypeType = new Bpl.CtorType(Token.NoToken, datatypeType, new List<Bpl.Type>());
+ this.HandleType = new Bpl.CtorType(Token.NoToken, handleType, new List<Bpl.Type>());
this.LayerType = new Bpl.CtorType(Token.NoToken, layerType, new List<Bpl.Type>());
this.DtCtorId = new Bpl.CtorType(Token.NoToken, dtCtorId, new List<Bpl.Type>());
this.allocField = allocField;
@@ -207,6 +211,7 @@ namespace Microsoft.Dafny {
Bpl.TypeCtorDecl tyTagType = null;
Bpl.TypeCtorDecl nameFamilyType = null;
Bpl.TypeCtorDecl datatypeType = null;
+ Bpl.TypeCtorDecl handleType = null;
Bpl.TypeCtorDecl layerType = null;
Bpl.TypeCtorDecl dtCtorId = null;
Bpl.TypeCtorDecl boxType = null;
@@ -229,6 +234,8 @@ namespace Microsoft.Dafny {
tyTagType = dt;
} else if (dt.Name == "DatatypeType") {
datatypeType = dt;
+ } else if (dt.Name == "HandleType") {
+ handleType = dt;
} else if (dt.Name == "LayerType") {
layerType = dt;
} else if (dt.Name == "DtCtorId") {
@@ -290,6 +297,8 @@ namespace Microsoft.Dafny {
Console.WriteLine("Error: Dafny prelude is missing declaration of type NameFamily");
} else if (datatypeType == null) {
Console.WriteLine("Error: Dafny prelude is missing declaration of type DatatypeType");
+ } else if (handleType == null) {
+ Console.WriteLine("Error: Dafny prelude is missing declaration of type HandleType");
} else if (layerType == null) {
Console.WriteLine("Error: Dafny prelude is missing declaration of type LayerType");
} else if (dtCtorId == null) {
@@ -306,7 +315,7 @@ namespace Microsoft.Dafny {
Console.WriteLine("Error: Dafny prelude is missing declaration of constant alloc");
} else {
return new PredefinedDecls(refType, boxType, tickType,
- setTypeCtor, multiSetTypeCtor, mapTypeCtor, arrayLength, seqTypeCtor, fieldNameType, tyType, tyTagType, heap, classNameType, nameFamilyType, datatypeType, layerType, dtCtorId,
+ setTypeCtor, multiSetTypeCtor, mapTypeCtor, arrayLength, seqTypeCtor, fieldNameType, tyType, tyTagType, heap, classNameType, nameFamilyType, datatypeType, handleType, layerType, dtCtorId,
allocField);
}
return null;
@@ -349,6 +358,12 @@ namespace Microsoft.Dafny {
return new Bpl.Program();
}
+ foreach (var ad in ArrowType.ArrowTypeDecls) {
+ currentDeclaration = ad;
+ GetClassTyCon(ad);
+ AddArrowTypeAxioms(ad);
+ }
+
foreach (TopLevelDecl d in program.BuiltIns.SystemModule.TopLevelDecls) {
currentDeclaration = d;
if (d is OpaqueTypeDecl) {
@@ -572,7 +587,7 @@ namespace Microsoft.Dafny {
// Add Lit axiom:
// axiom (forall p0, ..., pn :: #dt.ctor(Lit(p0), ..., Lit(pn)) == Lit(#dt.ctor(p0, .., pn)));
CreateBoundVariables(ctor.Formals, out bvs, out args);
- List<Bpl.Expr> litargs = new List<Bpl.Expr>();
+ var litargs = new List<Bpl.Expr>();
foreach (Bpl.Expr arg in args) {
litargs.Add(Lit(arg));
}
@@ -583,7 +598,7 @@ namespace Microsoft.Dafny {
}
// Injectivity axioms for normal arguments
- i = 0; // NB: counting of i starts from /after/ the type indicies!
+ i = 0;
foreach (Formal arg in ctor.Formals) {
// function ##dt.ctor#i(DatatypeType) returns (Ti);
var sf = ctor.Destructors[i];
@@ -602,8 +617,7 @@ namespace Microsoft.Dafny {
// for datatype: axiom (forall params :: DtRank(params_i) < DtRank(#dt.ctor(params)));
// for type-parameter type: axiom (forall params :: DtRank(Unbox(params_i)) < DtRank(#dt.ctor(params)));
CreateBoundVariables(ctor.Formals, out bvs, out args);
- Bpl.Expr lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null,
- arg.Type.IsDatatype ? args[i] : FunctionCall(ctor.tok, BuiltinFunction.Unbox, predef.DatatypeType, args[i]));
+ Bpl.Expr lhs = FunctionCall(ctor.tok, arg.Type.IsDatatype ? BuiltinFunction.DtRank : BuiltinFunction.BoxRank, null, args[i]);
Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Lt(lhs, rhs));
@@ -759,9 +773,9 @@ namespace Microsoft.Dafny {
} else {
kVar = null; k = null; kGtZero = Bpl.Expr.True;
}
- Bpl.Expr ly; var lyVar = BplBoundVar("ly", predef.LayerType, out ly); vars.Add(lyVar);
- Bpl.Expr d0; var d0Var = BplBoundVar("d0", predef.DatatypeType, out d0); vars.Add(d0Var);
- Bpl.Expr d1; var d1Var = BplBoundVar("d1", predef.DatatypeType, out d1); vars.Add(d1Var);
+ var ly = BplBoundVar("ly", predef.LayerType, vars);
+ var d0 = BplBoundVar("d0", predef.DatatypeType, vars);
+ var d1 = BplBoundVar("d1", predef.DatatypeType, vars);
K(tyargs, vars, lexprs, rexprs, kVar, k, kGtZero, ly, d0, d1);
};
@@ -846,12 +860,12 @@ namespace Microsoft.Dafny {
// A consequence of the definition of prefix equalities is the following:
// axiom (forall k, m: int, d0, d1: DatatypeType :: 0 <= k <= m && $PrefixEq#Dt(m, d0, d1) ==> $PrefixEq#0#Dt(k, d0, d1));
CoAxHelper(true, (tyargs, vars, lexprs, rexprs, kVar, k, kGtZero, ly, d0, d1) => {
- Bpl.Expr m; var mVar = BplBoundVar("m", Bpl.Type.Int, out m);
+ var m = BplBoundVar("m", Bpl.Type.Int, vars);
var PEqK = CoEqualCall(codecl, lexprs, rexprs, k, LayerSucc(ly), d0, d1);
var PEqM = CoEqualCall(codecl, lexprs, rexprs, m, LayerSucc(ly), d0, d1);
var kLtM = Bpl.Expr.Lt(k, m);
sink.TopLevelDeclarations.Add(new Axiom(dt.tok,
- BplForall(Snoc(vars, mVar),
+ BplForall(vars,
new Bpl.Trigger(dt.tok, true, new List<Bpl.Expr> { PEqK, PEqM }),
BplImp(BplAnd(BplAnd(kGtZero, kLtM), PEqM), PEqK)),
"Prefix equality consequence"));
@@ -899,8 +913,8 @@ namespace Microsoft.Dafny {
// (A.Nil? ==> B.Nil?) &&
// (A.Cons? ==> (B.Cons? && A.head == B.head && Equal(k, A.tail, B.tail)))
- Dictionary<TypeParameter, Type> lsu = Dict(GetTypeParams(dt), largs);
- Dictionary<TypeParameter, Type> rsu = Dict(GetTypeParams(dt), rargs);
+ Dictionary<TypeParameter, Type> lsu = Util.Dict(GetTypeParams(dt), largs);
+ Dictionary<TypeParameter, Type> rsu = Util.Dict(GetTypeParams(dt), rargs);
foreach (var ctor in dt.Ctors) {
Bpl.Expr aq = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(GetReadonlyField(ctor.QueryField)), new List<Bpl.Expr> { A });
@@ -1061,9 +1075,7 @@ namespace Microsoft.Dafny {
List<Bpl.Expr> tyexprs;
var vars = MkTyParamBinders(GetTypeParams(c), out tyexprs);
- Bpl.Expr o;
- var oVar = BplBoundVar("$o", predef.RefType, out o);
- vars.Add(oVar);
+ var o = BplBoundVar("$o", predef.RefType, vars);
Bpl.Expr body, is_o;
Bpl.Expr o_null = Bpl.Expr.Eq(o, predef.Null);
@@ -1072,9 +1084,7 @@ namespace Microsoft.Dafny {
if (is_alloc) {
name = c + ": Class $IsAlloc";
- Bpl.Expr h;
- var hVar = BplBoundVar("$h", predef.HeapType, out h);
- vars.Add(hVar);
+ var h = BplBoundVar("$h", predef.HeapType, vars);
// $IsAlloc(o, ..)
is_o = MkIsAlloc(o, o_ty, h);
body = BplIff(is_o, BplOr(o_null, IsAlloced(c.tok, h, o)));
@@ -1298,8 +1308,8 @@ namespace Microsoft.Dafny {
builder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
}
// check well-formedness of the modifies and reads clauses
- CheckFrameWellFormed(iter.Modifies.Expressions, localVariables, builder, etran);
- CheckFrameWellFormed(iter.Reads.Expressions, localVariables, builder, etran);
+ CheckFrameWellFormed(new WFOptions(), iter.Modifies.Expressions, localVariables, builder, etran);
+ CheckFrameWellFormed(new WFOptions(), iter.Reads.Expressions, localVariables, builder, etran);
// check well-formedness of the decreases clauses
foreach (var p in iter.Decreases.Expressions) {
CheckWellformed(p, new WFOptions(), localVariables, builder, etran);
@@ -1313,11 +1323,11 @@ namespace Microsoft.Dafny {
// 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
+ var rds = new MemberSelectExpr(iter.tok, th, iter.Member_Reads.Name);
+ rds.Member = 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
+ var mod = new MemberSelectExpr(iter.tok, th, iter.Member_Modifies.Name);
+ mod.Member = 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) },
@@ -1346,8 +1356,8 @@ namespace Microsoft.Dafny {
localVariables.Add(oldIterHeap);
builder.Add(Bpl.Cmd.SimpleAssign(iter.tok, new Bpl.IdentifierExpr(iter.tok, oldIterHeap), etran.HeapExpr));
// 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
+ var nw = new MemberSelectExpr(iter.tok, th, iter.Member_New.Name);
+ nw.Member = 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) },
@@ -1372,10 +1382,10 @@ namespace Microsoft.Dafny {
for (int i = 0; i < iter.OutsFields.Count; i++) {
var y = iter.OutsFields[i];
var ys = iter.OutsHistoryFields[i];
- var thisY = new FieldSelectExpr(iter.tok, th, y.Name);
- thisY.Field = y; thisY.Type = y.Type; // resolve here
- var thisYs = new FieldSelectExpr(iter.tok, th, ys.Name);
- thisYs.Field = ys; thisYs.Type = ys.Type; // resolve here
+ var thisY = new MemberSelectExpr(iter.tok, th, y.Name);
+ thisY.Member = y; thisY.Type = y.Type; // resolve here
+ var thisYs = new MemberSelectExpr(iter.tok, th, ys.Name);
+ thisYs.Member = ys; thisYs.Type = ys.Type; // resolve here
var oldThisYs = new OldExpr(iter.tok, thisYs);
oldThisYs.Type = thisYs.Type; // resolve here
var singleton = new SeqDisplayExpr(iter.tok, new List<Expression>() { thisY });
@@ -1876,8 +1886,24 @@ namespace Microsoft.Dafny {
Bpl.IdentifierExpr canCallFuncID = new Bpl.IdentifierExpr(f.tok, f.FullSanitizedName + "#canCall", Bpl.Type.Bool);
Bpl.Expr useViaCanCall = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(canCallFuncID), Concat(tyargs,args));
+ // ante := (useViaContext && typeAnte && pre)
+ ante = BplAnd(useViaContext, BplAnd(ante, pre));
+
+ // Add the precondition function and its axiom (which is equivalent to the ante)
+ if (visibility == FunctionAxiomVisibility.IntraModuleOnly && lits == null) {
+ var precondF = new Bpl.Function(f.tok,
+ RequiresName(f), new List<Bpl.TypeVariable>(),
+ formals.ConvertAll(v => (Bpl.Variable)BplFormalVar(null, v.TypedIdent.Type, true)),
+ BplFormalVar(null, Bpl.Type.Bool, false));
+ sink.TopLevelDeclarations.Add(precondF);
+ var appl = FunctionCall(f.tok, RequiresName(f), Bpl.Type.Bool,
+ formals.ConvertAll(x => (Bpl.Expr)(new Bpl.IdentifierExpr(f.tok, x))));
+ sink.TopLevelDeclarations.Add(new Axiom(f.tok, BplForall(formals, BplTrigger(appl), Bpl.Expr.Eq(appl, ante))));
+ ante = appl; // might just as well use it and check that it always works :-)
+ }
+
// ante := useViaCanCall || (useViaContext && typeAnte && pre)
- ante = Bpl.Expr.Or(useViaCanCall, BplAnd(useViaContext, BplAnd(ante, pre)));
+ ante = Bpl.Expr.Or(useViaCanCall, ante);
Bpl.Trigger tr = new Bpl.Trigger(f.tok, true, new List<Bpl.Expr> { funcAppl });
var typeParams = TrTypeParamDecls(f.TypeArgs);
@@ -1929,7 +1955,7 @@ namespace Microsoft.Dafny {
Expression PrefixSubstitution(PrefixPredicate pp, Expression body) {
Contract.Requires(pp != null);
- var typeMap = Dict<TypeParameter,Type>(pp.Co.TypeArgs, Map(pp.TypeArgs, x => new UserDefinedType(x)));
+ var typeMap = Util.Dict<TypeParameter,Type>(pp.Co.TypeArgs, Map(pp.TypeArgs, x => new UserDefinedType(x)));
var paramMap = new Dictionary<IVariable, Expression>();
for (int i = 0; i < pp.Co.Formals.Count; i++) {
@@ -2479,7 +2505,7 @@ namespace Microsoft.Dafny {
builder.Add(new Bpl.AssumeCmd(p.E.tok, etran.TrExpr(p.E)));
}
// check well-formedness of the modifies clause
- CheckFrameWellFormed(m.Mod.Expressions, localVariables, builder, etran);
+ CheckFrameWellFormed(new WFOptions(), m.Mod.Expressions, localVariables, builder, etran);
// check well-formedness of the decreases clauses
foreach (Expression p in m.Decreases.Expressions)
{
@@ -2640,13 +2666,13 @@ namespace Microsoft.Dafny {
}
}
- void CheckFrameWellFormed(List<FrameExpression> fes, List<Variable> locals, StmtListBuilder builder, ExpressionTranslator etran) {
+ void CheckFrameWellFormed(WFOptions wfo, List<FrameExpression> fes, List<Variable> locals, StmtListBuilder builder, ExpressionTranslator etran) {
Contract.Requires(fes != null);
Contract.Requires(locals != null);
Contract.Requires(builder != null);
Contract.Requires(etran != null);
foreach (var fe in fes) {
- CheckWellformed(fe.E, new WFOptions(), locals, builder, etran);
+ CheckWellformed(fe.E, wfo, locals, builder, etran);
if (fe.Field != null && fe.E.Type.IsRefType) {
builder.Add(Assert(fe.tok, Bpl.Expr.Neq(etran.TrExpr(fe.E), predef.Null), "frame expression may dereference null"));
}
@@ -2715,7 +2741,7 @@ namespace Microsoft.Dafny {
Contract.Requires(cce.NonNullElements(localVariables));
Contract.Requires(predef != null);
- ExpressionTranslator etran = new ExpressionTranslator(this, predef, tok);
+ var etran = new ExpressionTranslator(this, predef, tok);
// Declare a local variable $_Frame: <alpha>[ref, Field alpha]bool
Bpl.IdentifierExpr theFrame = etran.TheFrame(tok); // this is a throw-away expression, used only to extract the type and name of the $_Frame variable
Contract.Assert(theFrame.Type != null); // follows from the postcondition of TheFrame
@@ -2736,15 +2762,28 @@ namespace Microsoft.Dafny {
}
void CheckFrameSubset(IToken tok, List<FrameExpression> calleeFrame,
+ Expression receiverReplacement, Dictionary<IVariable, Expression /*!*/> substMap,
+ ExpressionTranslator /*!*/ etran,
+ Bpl.StmtListBuilder /*!*/ builder,
+ string errorMessage,
+ Bpl.QKeyValue kv)
+ {
+ CheckFrameSubset(tok, calleeFrame, receiverReplacement, substMap, etran,
+ (t, e, s, q) => builder.Add(Assert(t, e, s, q)), errorMessage, kv);
+ }
+
+ void CheckFrameSubset(IToken tok, List<FrameExpression> calleeFrame,
Expression receiverReplacement, Dictionary<IVariable,Expression/*!*/> substMap,
- ExpressionTranslator/*!*/ etran, Bpl.StmtListBuilder/*!*/ builder, string errorMessage,
+ ExpressionTranslator/*!*/ etran,
+ Action<IToken, Bpl.Expr, string, Bpl.QKeyValue> MakeAssert,
+ string errorMessage,
Bpl.QKeyValue kv)
{
Contract.Requires(tok != null);
Contract.Requires(calleeFrame != null);
Contract.Requires((receiverReplacement == null) == (substMap == null));
Contract.Requires(etran != null);
- Contract.Requires(builder != null);
+ Contract.Requires(MakeAssert != null);
Contract.Requires(errorMessage != null);
Contract.Requires(predef != null);
@@ -2759,7 +2798,7 @@ namespace Microsoft.Dafny {
Bpl.Expr inEnclosingFrame = Bpl.Expr.Select(etran.TheFrame(tok), o, f);
Bpl.Expr q = new Bpl.ForallExpr(tok, new List<TypeVariable> { alpha }, new List<Variable> { oVar, fVar },
Bpl.Expr.Imp(Bpl.Expr.And(ante, oInCallee), inEnclosingFrame));
- builder.Add(Assert(tok, q, errorMessage, kv));
+ MakeAssert(tok, q, errorMessage, kv);
}
/// <summary>
@@ -2931,8 +2970,16 @@ namespace Microsoft.Dafny {
}
var canCall = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.tok, f.FullSanitizedName + "#canCall", Bpl.Type.Bool));
wellFormed = Bpl.Expr.And(wellFormed, Bpl.Expr.And(
- Bpl.Expr.Or(new Bpl.NAryExpr(f.tok, canCall, f0argsCanCall), fwf0),
+ Bpl.Expr.Or(new Bpl.NAryExpr(f.tok, canCall, f0argsCanCall), fwf0),
Bpl.Expr.Or(new Bpl.NAryExpr(f.tok, canCall, f1argsCanCall), fwf1)));
+
+ /*
+ DR: I conjecture that this should be enough,
+ as the requires is preserved when the frame is:
+
+ wellFormed = Bpl.Expr.And(wellFormed,
+ Bpl.Expr.Or(new Bpl.NAryExpr(f.tok, canCall, f0argsCanCall), fwf0));
+ */
var fn = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.tok, f.FullSanitizedName, TrType(f.ResultType)));
var F0 = new Bpl.NAryExpr(f.tok, fn, f0args);
@@ -2955,7 +3002,7 @@ namespace Microsoft.Dafny {
Expression receiverReplacement, Dictionary<IVariable,Expression/*!*/> substMap) {
Contract.Requires(tok != null);
Contract.Requires(o != null);
- Contract.Requires(f != null);
+ // Contract.Requires(f != null); // f == null means approximate
Contract.Requires(etran != null);
Contract.Requires(cce.NonNullElements(rw));
Contract.Requires(substMap == null || cce.NonNullDictionaryAndValues(substMap));
@@ -2992,15 +3039,15 @@ namespace Microsoft.Dafny {
// o == old(e)
disjunct = Bpl.Expr.Eq(o, etran.TrExpr(e));
}
- if (rwComponent.Field != null) {
+ if (rwComponent.Field != null && f != null) {
disjunct = Bpl.Expr.And(disjunct, Bpl.Expr.Eq(f, new Bpl.IdentifierExpr(rwComponent.E.tok, GetField(rwComponent.Field))));
}
disjunction = BplOr(disjunction, disjunct);
}
return disjunction;
}
-
- void AddWellformednessCheck(Function f) {
+
+ private void AddWellformednessCheck(Function f) {
Contract.Requires(f != null);
Contract.Requires(sink != null && predef != null);
Contract.Requires(f.EnclosingClass != null);
@@ -3013,7 +3060,7 @@ namespace Microsoft.Dafny {
ExpressionTranslator etran = new ExpressionTranslator(this, predef, f.tok);
// parameters of the procedure
List<Variable> inParams = new List<Variable>();
- var typeInParams = MkTyParamFormals(GetTypeParams(f));
+ var typeInParams = MkTyParamFormals(GetTypeParams(f));
if (!f.IsStatic) {
Bpl.Expr wh = Bpl.Expr.And(
Bpl.Expr.Neq(new Bpl.IdentifierExpr(f.tok, "this", predef.RefType), predef.Null),
@@ -3032,25 +3079,28 @@ namespace Microsoft.Dafny {
// free requires mh == ModuleContextHeight && fh == FunctionContextHeight;
req.Add(Requires(f.tok, true, etran.HeightContext(f), null, null));
// modifies $Heap, $Tick
- var mod = new List<Bpl.IdentifierExpr> { (Bpl.IdentifierExpr/*TODO: this cast is rather dubious*/)etran.HeapExpr, etran.Tick() };
+ var mod = new List<Bpl.IdentifierExpr> {
+ (Bpl.IdentifierExpr /*TODO: this cast is rather dubious*/)etran.HeapExpr,
+ etran.Tick()
+ };
// check that postconditions hold
var ens = new List<Bpl.Ensures>();
foreach (Expression p in f.Ens) {
var functionHeight = currentModule.CallGraph.GetSCCRepresentativeId(f);
var splits = new List<SplitExprInfo>();
- bool splitHappened/*we actually don't care*/ = TrSplitExpr(p, splits, true, functionHeight, true, etran);
+ bool splitHappened /*we actually don't care*/ = TrSplitExpr(p, splits, true, functionHeight, true, etran);
foreach (var s in splits) {
if (s.IsChecked && !RefinementToken.IsInherited(s.E.tok, currentModule)) {
ens.Add(Ensures(s.E.tok, false, s.E, null, null));
}
}
}
- Bpl.Procedure proc = new Bpl.Procedure(f.tok, "CheckWellformed$$" + f.FullSanitizedName, typeParams, Concat(typeInParams, inParams), new List<Variable>(),
+ Bpl.Procedure proc = new Bpl.Procedure(f.tok, "CheckWellformed$$" + f.FullSanitizedName, typeParams,
+ Concat(typeInParams, inParams), new List<Variable>(),
req, mod, ens, etran.TrAttributes(f.Attributes, null));
sink.TopLevelDeclarations.Add(proc);
- if (InsertChecksums)
- {
+ if (InsertChecksums) {
InsertChecksum(f, proc, true);
}
@@ -3063,14 +3113,25 @@ namespace Microsoft.Dafny {
builder.Add(new CommentCmd("AddWellformednessCheck for function " + f));
builder.Add(CaptureState(f.tok, false, "initial state"));
- // check well-formedness of the preconditions (including termination, but no reads checks), and then
+ DefineFrame(f.tok, f.Reads, builder, locals, null);
+
+ // check well-formedness of the preconditions (including termination, and reads checks), and then
// assume each one of them
+ var wfo = new WFOptions(null, true, true /* do delayed reads checks over requires */);
+
+ // check well-formedness of the reads clause
+ CheckFrameWellFormed(wfo, f.Reads, locals, builder, etran);
+
+ // check the reads of the preconditions now
+ foreach (var a in wfo.Asserts) {
+ builder.Add(a);
+ }
+
foreach (Expression p in f.Req) {
- CheckWellformed(p, new WFOptions(null, false), locals, builder, etran);
+ CheckWellformed(p, new WFOptions(null, true /* do reads checks */), locals, builder, etran);
builder.Add(new Bpl.AssumeCmd(p.tok, etran.TrExpr(p)));
}
- // check well-formedness of the reads clause
- CheckFrameWellFormed(f.Reads, locals, builder, etran);
+
// check well-formedness of the decreases clauses (including termination, but no reads checks)
foreach (Expression p in f.Decreases.Expressions)
{
@@ -3136,16 +3197,29 @@ namespace Microsoft.Dafny {
}
Bpl.Expr funcAppl = new Bpl.NAryExpr(f.tok, funcID, args);
- DefineFrame(f.tok, f.Reads, bodyCheckBuilder, locals, null);
+ DefineFrame(f.tok, f.Reads, bodyCheckBuilder
+ , new List<Variable>() /* dummy local variable list, since frame axiom variable (and its definition)
+ * is already added. The only reason why we add the frame axiom definition
+ * again is to make boogie gives the same trace as before the change that
+ * makes reads clauses also guard the requires */
+ , null);
+
CheckWellformedWithResult(f.Body, new WFOptions(null, true), funcAppl, f.ResultType, locals, bodyCheckBuilder, etran);
}
// Combine the two, letting the postcondition be checked on after the "bodyCheckBuilder" branch
postCheckBuilder.Add(new Bpl.AssumeCmd(f.tok, Bpl.Expr.False));
builder.Add(new Bpl.IfCmd(f.tok, null, postCheckBuilder.Collect(f.tok), null, bodyCheckBuilder.Collect(f.tok)));
+ // var b$reads_guards_requires#0 : bool
+ locals.AddRange(wfo.Locals);
+ // This ugly way seems to be the way to add things at the start of a builder:
+ StmtList sl = builder.Collect(f.tok);
+ // b$reads_guards_requires#0 := true ...
+ sl.BigBlocks[0].simpleCmds.InsertRange(0, wfo.AssignLocals);
+
Bpl.Implementation impl = new Bpl.Implementation(f.tok, proc.Name,
typeParams, Concat(typeInParams, implInParams), new List<Variable>(),
- locals, builder.Collect(f.tok), etran.TrAttributes(f.Attributes, null));
+ locals, sl, etran.TrAttributes(f.Attributes, null));
sink.TopLevelDeclarations.Add(impl);
if (InsertChecksums)
@@ -3225,8 +3299,8 @@ namespace Microsoft.Dafny {
l.Add(p.A); l.Add(p.B);
}
return CanCallAssumption(l, etran);
- } else if (expr is FieldSelectExpr) {
- FieldSelectExpr e = (FieldSelectExpr)expr;
+ } else if (expr is MemberSelectExpr) {
+ MemberSelectExpr e = (MemberSelectExpr)expr;
if (e.Obj is ThisExpr) {
return Bpl.Expr.True;
} else {
@@ -3266,18 +3340,25 @@ namespace Microsoft.Dafny {
total = BplAnd(total, CanCallAssumption(e.Index, etran));
total = BplAnd(total, CanCallAssumption(e.Value, etran));
return total;
+ } else if (expr is ApplyExpr) {
+ ApplyExpr e = (ApplyExpr)expr;
+ return BplAnd(
+ Cons(CanCallAssumption(e.Receiver, etran),
+ e.Args.ConvertAll(ee => CanCallAssumption(ee, etran))));
} else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
- Contract.Assert(e.Function != null); // follows from the fact that expr has been successfully resolved
// check well-formedness of receiver
Bpl.Expr r = CanCallAssumption(e.Receiver, etran);
// check well-formedness of the other parameters
r = BplAnd(r, CanCallAssumption(e.Args, etran));
- // get to assume canCall
- Bpl.IdentifierExpr canCallFuncID = new Bpl.IdentifierExpr(expr.tok, e.Function.FullSanitizedName + "#canCall", Bpl.Type.Bool);
- List<Bpl.Expr> args = etran.FunctionInvocationArguments(e, null);
- Bpl.Expr canCallFuncAppl = new Bpl.NAryExpr(expr.tok, new Bpl.FunctionCall(canCallFuncID), args);
- r = BplAnd(r, canCallFuncAppl);
+ // if (e.Name != "requires" && e.Name != "reads") {
+ Contract.Assert(e.Function != null); // follows from the fact that expr has been successfully resolved
+ // get to assume canCall
+ Bpl.IdentifierExpr canCallFuncID = new Bpl.IdentifierExpr(expr.tok, e.Function.FullSanitizedName + "#canCall", Bpl.Type.Bool);
+ List<Bpl.Expr> args = etran.FunctionInvocationArguments(e, null);
+ Bpl.Expr canCallFuncAppl = new Bpl.NAryExpr(expr.tok, new Bpl.FunctionCall(canCallFuncID), args);
+ r = BplAnd(r, canCallFuncAppl);
+ // }
return r;
} else if (expr is DatatypeValue) {
DatatypeValue dtv = (DatatypeValue)expr;
@@ -3355,6 +3436,28 @@ namespace Microsoft.Dafny {
if (e.Contract != null)
return BplAnd(canCall, CanCallAssumption(e.Contract, etran));
else return canCall;
+ } else if (expr is LambdaExpr) {
+ var e = (LambdaExpr)expr;
+
+ List<Bpl.Variable> bvars = new List<Bpl.Variable>();
+
+ int u = otherTmpVarCount++;
+ Func<string, string> MkName = s => "$l" + u + "#" + s;
+
+ Bpl.Expr heap; var hVar = BplBoundVar(MkName("heap"), predef.HeapType, out heap);
+ bvars.Add(hVar);
+
+ Dictionary<IVariable, Expression> subst = new Dictionary<IVariable,Expression>();
+ foreach (var bv in e.BoundVars) {
+ Bpl.Expr ve; var yVar = BplBoundVar(MkName(bv.Name), TrType(bv.Type), out ve);
+ bvars.Add(yVar);
+
+ subst[bv] = new BoogieWrapper(ve, bv.Type);
+ }
+
+ ExpressionTranslator et = new ExpressionTranslator(etran, heap);
+ var ebody = CanCallAssumption(Substitute(e.Body, null, subst), et);
+ return BplForall(bvars, ebody);
} else if (expr is ComprehensionExpr) {
var e = (ComprehensionExpr)expr;
var canCall = CanCallAssumption(e.Term, etran);
@@ -3468,6 +3571,8 @@ namespace Microsoft.Dafny {
if (e is ThisExpr) {
// already known to be non-null
+ } else if (e is StaticReceiverExpr) {
+ // also ok
} else {
builder.Add(Assert(tok, Bpl.Expr.Neq(etran.TrExpr(e), predef.Null), "target object may be null", kv));
}
@@ -3482,19 +3587,51 @@ namespace Microsoft.Dafny {
/// "DoReadsChecks" indicates whether or not to perform reads checks. If so, the generated code
/// will make references to $_Frame.
/// </summary>
- class WFOptions
+ private class WFOptions
{
+ public readonly List<Bpl.Variable> Locals;
+ public readonly List<Bpl.Cmd> Asserts;
public readonly Function SelfCallsAllowance;
public readonly bool DoReadsChecks;
public readonly Bpl.QKeyValue AssertKv;
- public WFOptions() { }
- public WFOptions(Function selfCallsAllowance, bool doReadsChecks) {
+
+ public WFOptions() {
+ }
+
+ public WFOptions(Function selfCallsAllowance, bool doReadsChecks, bool saveReadsChecks = false) {
SelfCallsAllowance = selfCallsAllowance;
DoReadsChecks = doReadsChecks;
+ if (saveReadsChecks) {
+ Locals = new List<Variable>();
+ Asserts = new List<Bpl.Cmd>();
+ }
}
+
public WFOptions(Bpl.QKeyValue kv) {
AssertKv = kv;
}
+
+ public Action<IToken, Bpl.Expr, string, Bpl.QKeyValue> AssertSink(Translator tran, StmtListBuilder builder) {
+ return (t, e, s, qk) => {
+ if (Locals != null) {
+ var b = BplLocalVar("b$reqreads#" + tran.otherTmpVarCount++, Bpl.Type.Bool, Locals);
+ Asserts.Add(tran.Assert(t, b, s, qk));
+ builder.Add(Bpl.Cmd.SimpleAssign(e.tok, (Bpl.IdentifierExpr)b, e));
+ } else {
+ builder.Add(tran.Assert(t, e, s, qk));
+ }
+ };
+ }
+
+ public List<Bpl.AssignCmd> AssignLocals {
+ get {
+ return Map(Locals, l =>
+ Bpl.Cmd.SimpleAssign(l.tok,
+ new Bpl.IdentifierExpr(Token.NoToken, l),
+ Bpl.Expr.True)
+ );
+ }
+ }
}
void TrStmt_CheckWellformed(Expression expr, Bpl.StmtListBuilder builder, List<Variable> locals, ExpressionTranslator etran, bool subsumption) {
@@ -3550,13 +3687,14 @@ namespace Microsoft.Dafny {
CheckWellformed(p.A, options, locals, builder, etran);
CheckWellformed(p.B, options, locals, builder, etran);
}
- } else if (expr is FieldSelectExpr) {
- FieldSelectExpr e = (FieldSelectExpr)expr;
+ } else if (expr is MemberSelectExpr) {
+ MemberSelectExpr e = (MemberSelectExpr)expr;
+ CheckFunctionSelectWF("naked function", builder, etran, e, " Possible solution: eta expansion.");
CheckWellformed(e.Obj, options, locals, builder, etran);
if (e.Obj.Type.IsRefType) {
CheckNonNull(expr.tok, e.Obj, builder, etran, options.AssertKv);
- } else if (e.Field is DatatypeDestructor) {
- var dtor = (DatatypeDestructor)e.Field;
+ } else if (e.Member is DatatypeDestructor) {
+ var dtor = (DatatypeDestructor)e.Member;
var correctConstructor = FunctionCall(e.tok, dtor.EnclosingCtor.QueryField.FullSanitizedName, Bpl.Type.Bool, etran.TrExpr(e.Obj));
if (dtor.EnclosingCtor.EnclosingDatatype.Ctors.Count == 1) {
// There is only one constructor, so the value must be been constructed by it; might as well assume that here.
@@ -3566,8 +3704,8 @@ namespace Microsoft.Dafny {
string.Format("destructor '{0}' can only be applied to datatype values constructed by '{1}'", dtor.Name, dtor.EnclosingCtor.Name)));
}
}
- if (options.DoReadsChecks && e.Field.IsMutable) {
- builder.Add(Assert(expr.tok, Bpl.Expr.SelectTok(expr.tok, etran.TheFrame(expr.tok), etran.TrExpr(e.Obj), GetField(e)), "insufficient reads clause to read field", options.AssertKv));
+ if (options.DoReadsChecks && e.Member is Field && ((Field)e.Member).IsMutable) {
+ options.AssertSink(this, builder)(expr.tok, Bpl.Expr.SelectTok(expr.tok, etran.TheFrame(expr.tok), etran.TrExpr(e.Obj), GetField(e)), "insufficient reads clause to read field", options.AssertKv);
}
} else if (expr is SeqSelectExpr) {
SeqSelectExpr e = (SeqSelectExpr)expr;
@@ -3602,7 +3740,7 @@ namespace Microsoft.Dafny {
if (e.SelectOne) {
Contract.Assert(e.E0 != null);
Bpl.Expr fieldName = FunctionCall(expr.tok, BuiltinFunction.IndexField, null, etran.TrExpr(e.E0));
- builder.Add(Assert(expr.tok, Bpl.Expr.SelectTok(expr.tok, etran.TheFrame(expr.tok), seq, fieldName), "insufficient reads clause to read array element", options.AssertKv));
+ options.AssertSink(this, builder)(expr.tok, Bpl.Expr.SelectTok(expr.tok, etran.TheFrame(expr.tok), seq, fieldName), "insufficient reads clause to read array element", options.AssertKv);
} else {
Bpl.Expr lowerBound = e.E0 == null ? Bpl.Expr.Literal(0) : etran.TrExpr(e.E0);
Contract.Assert((e.Seq.Type).AsArrayType.Dims == 1);
@@ -3614,7 +3752,7 @@ namespace Microsoft.Dafny {
var fieldName = FunctionCall(e.tok, BuiltinFunction.IndexField, null, i);
var allowedToRead = Bpl.Expr.SelectTok(e.tok, etran.TheFrame(e.tok), seq, fieldName);
var qq = new Bpl.ForallExpr(e.tok, new List<Variable> { iVar }, Bpl.Expr.Imp(range, allowedToRead));
- builder.Add(Assert(expr.tok, qq, "insufficient reads clause to read the indicated range of array elements", options.AssertKv));
+ options.AssertSink(this, builder)(expr.tok, qq, "insufficient reads clause to read the indicated range of array elements", options.AssertKv);
}
}
} else if (expr is MultiSelectExpr) {
@@ -3663,13 +3801,74 @@ namespace Microsoft.Dafny {
}
CheckWellformed(e.Value, options, locals, builder, etran);
}
+ } else if (expr is ApplyExpr) {
+ var e = (ApplyExpr)expr;
+ int arity = e.Args.Count;
+ var tt = e.Receiver.Type as ArrowType;
+ Contract.Assert(tt != null);
+ Contract.Assert(tt.Arity == arity);
+
+ // check WF of receiver and arguments
+ CheckWellformed(e.Receiver, options, locals, builder, etran);
+ foreach (Expression arg in e.Args) {
+ CheckWellformed(arg, options, locals, builder, etran);
+ }
+
+ // check subranges of arguments
+ for (int i = 0; i < arity; ++i) {
+ CheckSubrange(e.Args[i].tok, etran.TrExpr(e.Args[i]), tt.Args[i], builder);
+ }
+
+ // check parameter availability
+ if (etran.UsesOldHeap) {
+ for (int i = 0; i < e.Args.Count; i++) {
+ Expression ee = e.Args[i];
+ Bpl.Expr wh = GetWhereClause(ee.tok, etran.TrExpr(ee), ee.Type, etran);
+ if (wh != null) {
+ builder.Add(Assert(ee.tok, wh, "argument must be allocated in the state in which the function is invoked"));
+ }
+ }
+ }
+
+ // translate arguments to requires and reads
+ Func<Expression, Bpl.Expr> TrArg = arg => {
+ Bpl.Expr inner = etran.TrExpr(arg);
+ if (ModeledAsBoxType(arg.Type)) {
+ return inner;
+ } else {
+ return FunctionCall(arg.tok, BuiltinFunction.Box, null, inner);
+ }
+ };
+
+ var args = Concat(
+ Map(tt.TypeArgs, TypeToTy),
+ Cons(etran.TrExpr(e.Receiver),
+ Cons(etran.HeapExpr,
+ e.Args.ConvertAll(arg => TrArg(arg)))));
+
+ // check precond
+ var precond = FunctionCall(e.tok, Requires(arity), Bpl.Type.Bool, args);
+ builder.Add(Assert(expr.tok, precond, "possible violation of function precondition"));
+
+ if (options.DoReadsChecks) {
+ Type objset = new SetType(new ObjectType());
+ Expression wrap = new BoogieWrapper(
+ FunctionCall(e.tok, Reads(arity), TrType(objset), args),
+ objset);
+ var reads = new FrameExpression(e.tok, wrap, null);
+ CheckFrameSubset(expr.tok, new List<FrameExpression>{ reads }, null, null,
+ etran, options.AssertSink(this, builder), "insufficient reads clause to invoke function", options.AssertKv);
+ }
+
} else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
Contract.Assert(e.Function != null); // follows from the fact that expr has been successfully resolved
// check well-formedness of receiver
CheckWellformed(e.Receiver, options, locals, builder, etran);
- if (!e.Function.IsStatic && !(e.Receiver is ThisExpr)) {
+ if (!e.Function.IsStatic && !(e.Receiver is ThisExpr) && !(e.Receiver.Type is ArrowType)) {
CheckNonNull(expr.tok, e.Receiver, builder, etran, options.AssertKv);
+ } else if (e.Receiver.Type is ArrowType) {
+ CheckFunctionSelectWF("function specification", builder, etran, e.Receiver, "");
}
// check well-formedness of the other parameters
foreach (Expression arg in e.Args) {
@@ -3690,7 +3889,7 @@ namespace Microsoft.Dafny {
Bpl.IdentifierExpr lhs = (Bpl.IdentifierExpr)etran.TrExpr(ie); // TODO: is this cast always justified?
Expression ee = e.Args[i];
Type et = Resolver.SubstType(p.Type, e.TypeArgumentSubstitutions);
- CheckSubrange(ee.tok, etran.TrExpr(ee), et, builder);
+ CheckSubrange(ee.tok, etran.TrExpr(ee), et, builder);
Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(p.tok, lhs, CondApplyBox(p.tok, etran.TrExpr(ee), cce.NonNull(ee.Type), p.Type));
builder.Add(cmd);
builder.Add(new Bpl.CommentCmd("assume allocatedness for argument to function"));
@@ -3737,7 +3936,10 @@ namespace Microsoft.Dafny {
}
if (options.DoReadsChecks) {
// check that the callee reads only what the caller is already allowed to read
- CheckFrameSubset(expr.tok, e.Function.Reads, e.Receiver, substMap, etran, builder, "insufficient reads clause to invoke function", options.AssertKv);
+ var s = new Substituter(null, new Dictionary<IVariable,Expression>(), e.TypeArgumentSubstitutions, this);
+ CheckFrameSubset(expr.tok,
+ e.Function.Reads.ConvertAll(s.SubstFrameExpr),
+ e.Receiver, substMap, etran, options.AssertSink(this, builder), "insufficient reads clause to invoke function", options.AssertKv);
}
Bpl.Expr allowance = null;
@@ -3784,6 +3986,7 @@ namespace Microsoft.Dafny {
CheckCallTermination(expr.tok, contextDecreases, calleeDecreases, allowance, e.Receiver, substMap, etran, etran, builder,
codeContext.InferredDecreases, hint);
}
+
}
// all is okay, so allow this function application access to the function's axiom, except if it was okay because of the self-call allowance.
Bpl.IdentifierExpr canCallFuncID = new Bpl.IdentifierExpr(expr.tok, e.Function.FullSanitizedName + "#canCall", Bpl.Type.Bool);
@@ -3931,25 +4134,85 @@ namespace Microsoft.Dafny {
} else if (expr is ComprehensionExpr) {
var e = (ComprehensionExpr)expr;
var q = e as QuantifierExpr;
- Dictionary<TypeParameter, Type> typeMap = new Dictionary<TypeParameter, Type>();
- List<TypeParameter> copies = new List<TypeParameter>();
+ var lam = e as LambdaExpr;
+
+ var typeMap = new Dictionary<TypeParameter, Type>();
+ var copies = new List<TypeParameter>();
if (q != null) {
- copies = Map(q.TypeArgs, tp => q.Refresh(tp));
- typeMap = Dict(q.TypeArgs, Map(copies, tp => (Type)new UserDefinedType(tp)));
+ copies = Map(q.TypeArgs, tp => q.Refresh(tp, ref otherTmpVarCount));
+ typeMap = Util.Dict(q.TypeArgs, Map(copies, tp => (Type)new UserDefinedType(tp)));
}
- locals.AddRange(Map(copies, tp => new Bpl.LocalVariable(tp.tok, new TypedIdent(tp.tok, nameTypeParam(tp), predef.Ty))));
+ locals.AddRange(Map(copies,
+ tp => new Bpl.LocalVariable(tp.tok, new TypedIdent(tp.tok, nameTypeParam(tp), predef.Ty))));
var substMap = SetupBoundVarsAsLocals(e.BoundVars, builder, locals, etran, typeMap);
- Expression body = Substitute(e.Term, null, substMap, typeMap);
- if (e.Range == null) {
- CheckWellformed(body, options, locals, builder, etran);
- } else {
- Expression range = Substitute(e.Range, null, substMap);
- CheckWellformed(range, options, locals, builder, etran);
+ var s = new Substituter(null, substMap, typeMap, this);
+ var body = Substitute(e.Term, null, substMap, typeMap);
+ List<FrameExpression> reads = null;
+
+ var newOptions = options;
+ var newEtran = etran;
+ builder.Add(new Bpl.CommentCmd("Begin Comprehension WF check"));
+ BplIfIf(e.tok, lam != null, null, builder, newBuilder => {
+
+ if (lam != null) {
+ // Havoc heap, unless oneShot
+ if (!lam.OneShot) {
+ Bpl.Expr oldHeap;
+ locals.Add(BplLocalVar("$oldHeap#" + otherTmpVarCount++, predef.HeapType, out oldHeap));
+ newBuilder.Add(BplSimplestAssign(oldHeap, etran.HeapExpr));
+ newBuilder.Add(new HavocCmd(expr.tok, Singleton((Bpl.IdentifierExpr)etran.HeapExpr)));
+ newBuilder.Add(new AssumeCmd(expr.tok,
+ FunctionCall(expr.tok, BuiltinFunction.IsGoodHeap, null, etran.HeapExpr)));
+ newBuilder.Add(new AssumeCmd(expr.tok, HeapSameOrSucc(oldHeap, etran.HeapExpr)));
+ }
- Bpl.StmtListBuilder b = new Bpl.StmtListBuilder();
- CheckWellformed(body, options, locals, b, etran);
- builder.Add(new Bpl.IfCmd(expr.tok, etran.TrExpr(range), b.Collect(expr.tok), null, null));
- }
+ // Set up a new frame
+ var frameName = "$_Frame#l" + otherTmpVarCount++;
+ reads = lam.Reads.ConvertAll(s.SubstFrameExpr);
+ DefineFrame(e.tok, reads, newBuilder, locals, frameName);
+ newEtran = new ExpressionTranslator(newEtran, frameName);
+
+ // Check frame WF and that it read covers itself
+ newOptions = new WFOptions(options.SelfCallsAllowance, true /* check reads clauses */, true /* delay reads checks */);
+
+ CheckFrameWellFormed(newOptions, reads, locals, newBuilder, newEtran);
+
+ // new options now contains the delayed reads checks
+ locals.AddRange(newOptions.Locals);
+ // assign locals to true, but at a scope above
+ Contract.Assert(newBuilder != builder);
+ foreach (var a in newOptions.AssignLocals) {
+ builder.Add(a);
+ }
+
+ // add asserts to the current builder (right after frame WF)
+ foreach (var a in newOptions.Asserts) {
+ newBuilder.Add(a);
+ }
+
+ // continue doing reads checks, but don't delay them
+ newOptions = new WFOptions(options.SelfCallsAllowance, true, false);
+ }
+
+ // check requires/range
+ Bpl.Expr guard = null;
+ if (e.Range != null) {
+ var range = Substitute(e.Range, null, substMap);
+ CheckWellformed(range, newOptions, locals, newBuilder, newEtran);
+ guard = etran.TrExpr(range);
+ }
+
+ BplIfIf(e.tok, guard != null, guard, newBuilder, b => {
+ CheckWellformed(body, newOptions, locals, b, newEtran);
+ });
+
+ if (lam != null && !lam.OneShot) {
+ // assume false (heap was havoced inside an if)
+ Contract.Assert(newBuilder != builder);
+ newBuilder.Add(new AssumeCmd(e.tok, Bpl.Expr.False));
+ }
+ });
+ builder.Add(new Bpl.CommentCmd("End Comprehension WF check"));
} else if (expr is StmtExpr) {
var e = (StmtExpr)expr;
@@ -4034,6 +4297,18 @@ namespace Microsoft.Dafny {
}
}
+ void CheckFunctionSelectWF(string what, StmtListBuilder builder, ExpressionTranslator etran, Expression e, string hint) {
+ Function fn = null;
+ var sel = e as MemberSelectExpr;
+ if (sel != null) {
+ fn = sel.Member as Function;
+ }
+ if (fn != null) {
+ builder.Add(Assert(e.tok, Bpl.Expr.Not(etran.HeightContext(fn)),
+ "cannot use " + what + " in recursive setting." + hint));
+ }
+ }
+
void CloneVariableAsBoundVar(IToken tok, IVariable iv, string prefix, out BoundVar bv, out IdentifierExpr ie) {
Contract.Requires(tok != null);
Contract.Requires(iv != null);
@@ -4060,7 +4335,7 @@ namespace Microsoft.Dafny {
}
// Takes a Bpl.Constant, which typically will be one from GetClass,
- // or some built-in type which has a class name, like Arrays.
+ // or some built-in type which has a class name, like Arrays or Arrows.
// Note: Prefer to call ClassTyCon or TypeToTy instead.
private string GetClassTyCon(TopLevelDecl dl) {
Contract.Requires(dl != null);
@@ -4069,86 +4344,482 @@ namespace Microsoft.Dafny {
if (classConstants.TryGetValue(dl, out name)) {
Contract.Assert(name != null);
} else {
- var inner_name = GetClass(dl).TypedIdent.Name;
- name = "T" + inner_name;
+ name = AddTyAxioms(dl);
classConstants.Add(dl, name);
- var tok = dl.tok;
+ }
+ return name;
+ }
+
+ public string Handle(int arity) {
+ return "Handle" + arity;
+ }
+
+ public string Apply(int arity) {
+ return "Apply" + arity;
+ }
+
+ public string Requires(int arity) {
+ return "Requires" + arity;
+ }
+
+ public string Reads(int arity) {
+ return "Reads" + arity;
+ }
+
+ public string RequiresName(Function f) {
+ return f.FullSanitizedName + "#requires";
+ }
+
+ public string FunctionHandle(Function f) {
+ Contract.Requires(f != null);
+ string name;
+ if (functionHandles.TryGetValue(f, out name)) {
+ Contract.Assert(name != null);
+ } else {
+ name = f.FullSanitizedName + "#Handle";
+ functionHandles[f] = name;
+ var args = new List<Bpl.Expr>();
+ var vars = MkTyParamBinders(GetTypeParams(f), out args);
+ var formals = MkTyParamFormals(GetTypeParams(f), false);
+ var tyargs = new List<Bpl.Expr>();
+ foreach (var fm in f.Formals) {
+ tyargs.Add(TypeToTy(fm.Type));
+ }
+ tyargs.Add(TypeToTy(f.ResultType));
+ if (f.IsRecursive) {
+ Bpl.Expr ly; vars.Add(BplBoundVar("$ly", predef.LayerType, out ly)); args.Add(ly);
+ formals.Add(BplFormalVar(null, predef.LayerType, true));
+ }
+
+ var enclosingArrow = f.EnclosingClass as ArrowType.ArrowTypeDecl;
+ var fromArrowType = enclosingArrow != null;
+
+ Func<List<Bpl.Expr>, List<Bpl.Expr>> SnocSelf = x => x;
+ Expression selfExpr = null;
+ Dictionary<IVariable, Expression> rhs_dict = null;
+ if (!f.IsStatic) {
+ var selfTy = fromArrowType ? predef.HandleType : predef.RefType;
+ var self = BplBoundVar("$self", selfTy, vars);
+ formals.Add(BplFormalVar(null, selfTy, true));
+ SnocSelf = xs => Snoc(xs, self);
+ selfExpr = new BoogieWrapper(self, fromArrowType ? f.Type : new ObjectType());
+ // ^ is this an ok type for this wrapper?
+ rhs_dict = new Dictionary<IVariable, Expression>();
+ }
+
+ // F#Handle(Ty, .., Ty, LayerType, ref) : HandleType
+ sink.TopLevelDeclarations.Add(
+ new Bpl.Function(f.tok, name, formals, BplFormalVar(null, predef.HandleType, false)));
+
+ var bvars = new List<Bpl.Variable>();
+ var lhs_args = new List<Bpl.Expr>();
+ var rhs_args = new List<Bpl.Expr>();
+
+ var i = 0;
+ foreach (var fm in f.Formals) {
+ var fe = BplBoundVar("x#" + i++, predef.BoxType, bvars);
+ lhs_args.Add(fe);
+ var be = UnboxIfBoxed(fe, fm.Type);
+ rhs_args.Add(be);
+ if (rhs_dict != null) {
+ rhs_dict[fm] = new BoogieWrapper(be, fm.Type);
+ }
+ }
+
+ var h = BplBoundVar("$heap", predef.HeapType, vars);
+
+ int arity = f.Formals.Count;
- // Create the type constructor
{
- Bpl.Variable tyVarOut = BplFormalVar(null, predef.Ty, false);
- List<Bpl.Variable> args = new List<Bpl.Variable>(
- Enumerable.Range(0, n).Select(i =>
- (Bpl.Variable)BplFormalVar(null, predef.Ty, true)));
- var func = new Bpl.Function(tok, name, args, tyVarOut);
- sink.TopLevelDeclarations.Add(func);
- }
-
- // Helper action to create variables and the function call.
- Action<Action<List<Bpl.Expr>, List<Bpl.Variable>, Bpl.Expr>> Helper = K => {
- List<Bpl.Expr> argExprs; var args = MkTyParamBinders(dl.TypeArgs, out argExprs);
- var inner = FunctionCall(tok, name, predef.Ty, argExprs);
- K(argExprs, args, inner);
+ // Apply(Ty.., F#Handle( Ty1, ..., TyN, Layer, self), Heap, arg1, ..., argN)
+ // = [Box] F(Ty1, .., TyN, Layer, Heap, self, [Unbox] arg1, .., [Unbox] argN)
+
+ var fhandle = FunctionCall(f.tok, name, predef.HandleType, SnocSelf(args));
+ var lhs = FunctionCall(f.tok, Apply(arity), TrType(f.ResultType), Concat(tyargs, Cons(fhandle, Cons(h, lhs_args))));
+ var rhs = FunctionCall(f.tok, f.FullSanitizedName, TrType(f.ResultType), Concat(SnocSelf(Snoc(args, h)), rhs_args));
+ var rhs_boxed = BoxIfUnboxed(rhs, f.ResultType);
+
+ sink.TopLevelDeclarations.Add(new Axiom(f.tok,
+ BplForall(Concat(vars, bvars), BplTrigger(lhs), Bpl.Expr.Eq(lhs, rhs_boxed))));
+ }
+
+ {
+ // Requires(Ty.., F#Handle( Ty1, ..., TyN, Layer, self), Heap, arg1, ..., argN)
+ // = F#Requires(Ty1, .., TyN, Layer, Heap, self, [Unbox] arg1, .., [Unbox] argN)
+ // || Scramble(...)
+
+ var fhandle = FunctionCall(f.tok, name, predef.HandleType, SnocSelf(args));
+ var lhs = FunctionCall(f.tok, Requires(arity), Bpl.Type.Bool, Concat(tyargs, Cons(fhandle, Cons(h, lhs_args))));
+ var rhs = BplOr(
+ FunctionCall(f.tok, RequiresName(f), Bpl.Type.Bool, Concat(SnocSelf(Snoc(args, h)), rhs_args)),
+ MakeScrambler(f.tok, f.FullSanitizedName + "#lessReq", Concat(vars, bvars)));
+
+ // In case this is the /requires/ or /reads/ function, then there is no precondition
+ if (fromArrowType) {
+ rhs = Bpl.Expr.True;
+ }
+
+ sink.TopLevelDeclarations.Add(new Axiom(f.tok,
+ BplForall(Concat(vars, bvars), BplTrigger(lhs), Bpl.Expr.Eq(lhs, rhs))));
+ }
+
+ {
+ // Reads(Ty.., F#Handle( Ty1, ..., TyN, Layer, self), Heap, arg1, ..., argN)[Box(o)]
+ // = $Frame_F(args...)[o]
+ // && Scramble(...)
+
+ var fhandle = FunctionCall(f.tok, name, predef.HandleType, SnocSelf(args));
+ Bpl.Expr o; var oVar = BplBoundVar("o", predef.RefType, out o);
+ Bpl.Expr lhs_inner = FunctionCall(f.tok, Reads(arity), Bpl.Type.Bool, Concat(tyargs, Cons(fhandle, Cons(h, lhs_args))));
+ Bpl.Expr lhs = new Bpl.NAryExpr(f.tok, new Bpl.MapSelect(f.tok, 1),
+ new List<Bpl.Expr> { lhs_inner, FunctionCall(f.tok, BuiltinFunction.Box, null, o) });
+
+ var et = new ExpressionTranslator(this, predef, h);
+ var rhs = BplAnd(InRWClause(f.tok, o, null, f.Reads, et, selfExpr, rhs_dict),
+ MakeScrambler(f.tok, f.FullSanitizedName + "#extraReads", Cons(oVar, Concat(vars, bvars))));
+
+ sink.TopLevelDeclarations.Add(new Axiom(f.tok,
+ BplForall(Cons(oVar, Concat(vars, bvars)), BplTrigger(lhs), Bpl.Expr.Eq(lhs, rhs))));
+ }
+ }
+ return name;
+ }
+
+ public Bpl.Expr MakeScrambler(IToken tk, string name, List<Variable> bvars) {
+ var f = new Bpl.Function(tk, name,
+ bvars.ConvertAll(bv => (Bpl.Variable)BplFormalVar(null, bv.TypedIdent.Type, true)),
+ BplFormalVar(null, Bpl.Type.Bool, false));
+
+ sink.TopLevelDeclarations.Add(f);
+ return FunctionCall(tk, name, Bpl.Type.Bool, bvars.ConvertAll(bv => (Bpl.Expr)new Bpl.IdentifierExpr(tk, bv)));
+ }
+
+ private void AddArrowTypeAxioms(ArrowType.ArrowTypeDecl ad) {
+ var arity = ad.Arity;
+ var tok = ad.tok;
+
+ // [Heap, Box, ..., Box]
+ var map_args = Cons(predef.HeapType, Map(Enumerable.Range(0, arity), i => predef.BoxType));
+ // [Heap, Box, ..., Box] Box
+ var apply_ty = new Bpl.MapType(tok, new List<Bpl.TypeVariable>(), map_args, predef.BoxType);
+ // [Heap, Box, ..., Box] Bool
+ var requires_ty = new Bpl.MapType(tok, new List<Bpl.TypeVariable>(), map_args, Bpl.Type.Bool);
+ // Set Box
+ var objset_ty = TrType(new SetType(new ObjectType()));
+ // [Heap, Box, ..., Box] (Set Box)
+ var reads_ty = new Bpl.MapType(tok, new List<Bpl.TypeVariable>(), map_args, objset_ty);
+
+ {
+ // function HandleN([Heap, Box, ..., Box] Box, [Heap, Box, ..., Box] Bool) : HandleType
+ var res = BplFormalVar(null, predef.HandleType, true);
+ var arg = new List<Bpl.Variable> {
+ BplFormalVar(null, apply_ty, true),
+ BplFormalVar(null, requires_ty, true),
+ BplFormalVar(null, reads_ty, true)
};
+ sink.TopLevelDeclarations.Add(new Bpl.Function(Token.NoToken, Handle(arity), arg, res));
+ }
- // Create the Tag and calling Tag on this type constructor
- /*
- const unique TagList: TyTag;
- axiom (forall t0: Ty :: { List(t0) } Tag(List(t0)) == TagList);
- */
- Helper((argExprs, args, inner) => {
- Bpl.TypedIdent tag_id = new Bpl.TypedIdent(tok, "Tag" + inner_name, predef.TyTag);
- Bpl.Constant tag = new Bpl.Constant(tok, tag_id, true);
- Bpl.Expr tag_expr = new Bpl.IdentifierExpr(tok, tag);
- Bpl.Expr tag_call = FunctionCall(tok, "Tag", predef.TyTag, inner);
- Bpl.Expr qq = BplForall(args, BplTrigger(inner), Bpl.Expr.Eq(tag_call, tag_expr));
- sink.TopLevelDeclarations.Add(new Axiom(tok, qq, dl + " Tag"));
- sink.TopLevelDeclarations.Add(tag);
- });
+ Action<string, Bpl.Type> SelectorFunction = (s, t) => {
+ var args = new List<Bpl.Variable>();
+ MapM(Enumerable.Range(0, arity + 1), i => args.Add(BplFormalVar(null, predef.Ty, true)));
+ args.Add(BplFormalVar(null, predef.HandleType, true));
+ args.Add(BplFormalVar(null, predef.HeapType, true));
+ MapM(Enumerable.Range(0, arity), i => args.Add(BplFormalVar(null, predef.BoxType, true)));
+ sink.TopLevelDeclarations.Add(new Bpl.Function(Token.NoToken, s, args, BplFormalVar(null, t, false)));
+ };
- // Create the injectivity axiom and its function
- /*
- function List_0(Ty) : Ty;
- axiom (forall t0: Ty :: { List(t0) } List_0(List(t0)) == t0);
- */
- for (int i = 0; i < n; i++) {
- Helper((argExprs, args, inner) => {
- Bpl.Variable tyVarIn = BplFormalVar(null, predef.Ty, true);
- Bpl.Variable tyVarOut = BplFormalVar(null, predef.Ty, false);
- var injname = name + "_" + i;
- var injfunc = new Bpl.Function(tok, injname, Singleton(tyVarIn), tyVarOut);
- var outer = FunctionCall(tok, injname, args[i].TypedIdent.Type, inner);
- Bpl.Expr qq = BplForall(args, BplTrigger(inner), Bpl.Expr.Eq(outer, argExprs[i]));
- sink.TopLevelDeclarations.Add(new Axiom(tok, qq, dl + " injectivity " + i));
- sink.TopLevelDeclarations.Add(injfunc);
- });
+ // function ApplyN(Ty, ... Ty, HandleType, Heap, Box, ..., Box) : Box
+ SelectorFunction(Apply(arity), predef.BoxType);
+ // function RequiresN(Ty, ... Ty, HandleType, Heap, Box, ..., Box) : Bool
+ SelectorFunction(Requires(arity), Bpl.Type.Bool);
+ // function ReadsN(Ty, ... Ty, HandleType, Heap, Box, ..., Box) : Set Box
+ SelectorFunction(Reads(arity), objset_ty);
+
+ {
+ // forall t1, .., tN+1 : Ty, p: [Heap, Box, ..., Box] Box, heap : Heap, b1, ..., bN : Box
+ // :: RequriesN(...) ==> ApplyN(t1, .. tN+1, HandleN(h, r, rd), heap, b1, ..., bN) = h[heap, b1, ..., bN]
+ //
+ // no precondition for these, but:
+ // for requires, we add: RequiresN(...) <== r[heap, b1, ..., bN]
+ // for reads, we could: ReadsN(...)[bx] ==> rd[heap, b1, ..., bN][bx]
+ Action<string, Bpl.Type, string, Bpl.Type, string, Bpl.Type> SelectorSemantics = (selector, selectorTy, selectorVar, selectorVarTy, precond, precondTy) => {
+ Contract.Assert((precond == null) == (precondTy == null));
+ var bvars = new List<Bpl.Variable>();
+
+ var types = Map(Enumerable.Range(0, arity + 1), i => BplBoundVar("t" + i, predef.Ty, bvars));
+
+ var heap = BplBoundVar("heap", predef.HeapType, bvars);
+
+ var handleargs = new List<Bpl.Expr> {
+ BplBoundVar("h", apply_ty, bvars),
+ BplBoundVar("r", requires_ty, bvars),
+ BplBoundVar("rd", reads_ty, bvars)
+ };
+
+ var boxes = Map(Enumerable.Range(0, arity), i => BplBoundVar("bx" + i, predef.BoxType, bvars));
+
+ var lhsargs = Concat(types, Cons(FunctionCall(tok, Handle(arity), predef.HandleType, handleargs), Cons(heap, boxes)));
+ Bpl.Expr lhs = FunctionCall(tok, selector, selectorTy, lhsargs);
+ Func<Bpl.Expr, Bpl.Expr> pre = x => x;
+ if (precond != null) {
+ pre = x => FunctionCall(tok, precond, precondTy, lhsargs);
+ }
+
+ Bpl.Expr rhs = new Bpl.NAryExpr(tok, new Bpl.MapSelect(tok, arity + 1),
+ Cons(new Bpl.IdentifierExpr(tok, selectorVar, selectorVarTy), Cons(heap, boxes)));
+ Func<Bpl.Expr, Bpl.Expr, Bpl.Expr> op = Bpl.Expr.Eq;
+ if (selectorVar == "rd") {
+ var bx = BplBoundVar("bx", predef.BoxType, bvars);
+ lhs = new Bpl.NAryExpr(tok, new Bpl.MapSelect(tok, 1), new List<Bpl.Expr> { lhs, bx });
+ rhs = new Bpl.NAryExpr(tok, new Bpl.MapSelect(tok, 1), new List<Bpl.Expr> { rhs, bx });
+ op = Bpl.Expr.Imp;
+ }
+ if (selectorVar == "r") {
+ op = (u, v) => Bpl.Expr.Imp(v, u);
+ }
+ sink.TopLevelDeclarations.Add(new Axiom(tok,
+ BplForall(bvars, BplTrigger(lhs), op(lhs, rhs))));
+ };
+ SelectorSemantics(Apply(arity), predef.BoxType, "h", apply_ty, Requires(arity), requires_ty);
+ SelectorSemantics(Requires(arity), Bpl.Type.Bool, "r", requires_ty, null, null);
+ SelectorSemantics(Reads(arity), objset_ty, "rd", reads_ty, null, null);
+
+ // function {:inline true}
+ // FuncN._requires(G...G G: Ty, H:Heap, f:Handle, x ... x :Box): bool
+ // { RequiresN(f, H, x...x) }
+ // function {:inline true}
+ // FuncN._requires#canCall(G...G G: Ty, H:Heap, f:Handle, x ... x :Box): bool
+ // { true }
+ // + similar for Reads
+ Action<string, Function> UserSelectorFunction = (fname, f) => {
+ var formals = new List<Bpl.Variable>();
+ var rhsargs = new List<Bpl.Expr>();
+
+ MapM(Enumerable.Range(0, arity + 1), i => rhsargs.Add(BplFormalVar("t" + i, predef.Ty, true, formals)));
+
+ var heap = BplFormalVar("heap", predef.HeapType, true, formals);
+ rhsargs.Add(BplFormalVar("f", predef.HandleType, true, formals));
+ rhsargs.Add(heap);
+
+ MapM(Enumerable.Range(0, arity), i => rhsargs.Add(BplFormalVar("bx" + i, predef.BoxType, true, formals)));
+
+ Action<string, Bpl.Type, Bpl.Expr> sink_function = (nm, res_ty, body) =>
+ sink.TopLevelDeclarations.Add(
+ new Bpl.Function(f.tok, nm, new List<TypeVariable>(), formals,
+ BplFormalVar(null, res_ty, false), null,
+ new QKeyValue(f.tok, "inline", new List<object> { Bpl.Expr.True }, null)) {
+ Body = body
+ });
+
+ sink_function(f.FullSanitizedName, TrType(f.ResultType), FunctionCall(f.tok, fname, Bpl.Type.Bool, rhsargs));
+ sink_function(f.FullSanitizedName + "#canCall", Bpl.Type.Bool, Bpl.Expr.True);
+ };
+
+ UserSelectorFunction(Requires(ad.Arity), ad.Requires);
+ UserSelectorFunction(Reads(ad.Arity), ad.Reads);
+
+ // frame axiom
+ /*
+
+ forall t0..tN+1 : Ty, h0, h1 : Heap, f : Handle, bx1 .. bxN : Box,
+ HeapSucc(h0, h1) && GoodHeap(h0) && GoodHeap(h1)
+ && Is&IsAllocBox(bxI, tI, h0) // in h0, not hN
+ && Is&IsAlloc(f, Func(t1,..,tN, tN+1), h0) // in h0, not hN
+ &&
+ (forall o : ref::
+ o != null && h0[o, alloc] && h1[o, alloc] &&
+ Reads(h,hN,bxs)[Box(o)] // for hN in h0 and h1
+ ==> h0[o,field] == h1[o,field])
+ ==> Reads(..h0..) == Reads(..h1..)
+ AND Requires(f,h0,bxs) == Requires(f,h1,bxs) // which is needed for the next
+ AND Apply(f,h0,bxs) == Apply(f,h0,bxs)
+
+ */
+ {
+ var bvars = new List<Bpl.Variable>();
+
+ var types = Map(Enumerable.Range(0, arity + 1), i => BplBoundVar("t" + i, predef.Ty, bvars));
+
+ var h0 = BplBoundVar("h0", predef.HeapType, bvars);
+ var h1 = BplBoundVar("h1", predef.HeapType, bvars);
+ var heapSucc = FunctionCall(tok, BuiltinFunction.HeapSucc, null, h0, h1);
+ var goodHeaps = BplAnd(
+ FunctionCall(tok, BuiltinFunction.IsGoodHeap, null, h0),
+ FunctionCall(tok, BuiltinFunction.IsGoodHeap, null, h1));
+
+ var f = BplBoundVar("f", predef.HandleType, bvars);
+ var boxes = Map(Enumerable.Range(0, arity), i => BplBoundVar("bx" + i, predef.BoxType, bvars));
+
+ var isness = BplAnd(
+ Snoc(Map(Enumerable.Range(0, arity), i =>
+ BplAnd(MkIs(boxes[i], types[i], true),
+ MkIsAlloc(boxes[i], types[i], h0, true))),
+ BplAnd(MkIs(f, ClassTyCon(ad, types)),
+ MkIsAlloc(f, ClassTyCon(ad, types), h0))));
+
+ Action<Bpl.Expr, string> AddFrameForFunction = (hN, fname) => {
+
+ // inner forall vars
+ var ivars = new List<Bpl.Variable>();
+ var o = BplBoundVar("o", predef.RefType, ivars);
+ var a = new TypeVariable(tok, "a");
+ var fld = BplBoundVar("fld", predef.FieldName(tok, a), ivars);
+
+ var inner_forall = new Bpl.ForallExpr(tok, Singleton(a), ivars, BplImp(
+ BplAnd(new List<Expr> {
+ Bpl.Expr.Neq(o, predef.Null),
+ IsAlloced(tok, h0, o),
+ IsAlloced(tok, h1, o),
+ new Bpl.NAryExpr(tok, new Bpl.MapSelect(tok, 1), new List<Bpl.Expr> {
+ FunctionCall(tok, Reads(ad.Arity), objset_ty, Concat(types, Cons(f, Cons(hN, boxes)))),
+ FunctionCall(tok, BuiltinFunction.Box, null, o)
+ })
+ }),
+ Bpl.Expr.Eq(ReadHeap(tok, h0, o, fld), ReadHeap(tok, h1, o, fld))));
+
+ Func<Bpl.Expr, Bpl.Expr> fn = h => FunctionCall(tok, fname, Bpl.Type.Bool, Concat(types, Cons(f, Cons<Bpl.Expr>(h, boxes))));
+
+ sink.TopLevelDeclarations.Add(new Axiom(tok,
+ BplForall(bvars,
+ new Bpl.Trigger(tok, true, new List<Bpl.Expr> {heapSucc, fn(h1)}),
+ BplImp(
+ BplAnd(BplAnd(BplAnd(heapSucc, goodHeaps), isness), inner_forall),
+ Bpl.Expr.Eq(fn(h0), fn(h1))))));
+ };
+
+ AddFrameForFunction(h0, Reads(ad.Arity));
+ AddFrameForFunction(h1, Reads(ad.Arity));
+ AddFrameForFunction(h0, Requires(ad.Arity));
+ AddFrameForFunction(h1, Requires(ad.Arity));
+ AddFrameForFunction(h0, Apply(ad.Arity));
+ AddFrameForFunction(h1, Apply(ad.Arity));
}
- // Boxing axiom (important for the properties of unbox)
+ // consequence axiom
/*
- axiom (forall T: Ty, bx: Box ::
- { $IsBox(bx, List(T)) }
- $IsBox(bx, List(T))
- ==> $Box($Unbox(bx): DatatypeType) == bx
- && $Is($Unbox(bx): DatatypeType, List(T)));
- */
- Helper((argExprs, args, _inner) => {
- Bpl.Expr bx; var bxVar = BplBoundVar("bx", predef.BoxType, out bx);
- var ty = ClassTyCon(dl, argExprs);
- var ty_repr = dl is DatatypeDecl ? predef.DatatypeType : predef.RefType;
- var unbox = FunctionCall(dl.tok, BuiltinFunction.Unbox, ty_repr, bx);
- var box_is = MkIs(bx, ty, true);
- var unbox_is = MkIs(unbox, ty, false);
- var box_unbox = FunctionCall(dl.tok, BuiltinFunction.Box, null, unbox);
- sink.TopLevelDeclarations.Add(
- new Axiom(dl.tok,
- BplForall(Snoc(args, bxVar), BplTrigger(box_is),
- BplImp(box_is, BplAnd(Bpl.Expr.Eq(box_unbox, bx), unbox_is))),
- "Box/unbox axiom for " + dl));
+
+ forall t0..tN+1 : Ty, h : Heap, f : Handle, bx1 .. bxN : Box,
+ GoodHeap(h)
+ && Is&IsAllocBox(bxI, tI, h)
+ && Is&IsAlloc(f, Func(t1,..,tN, tN+1), h)
+ ==> Is&IsAllocBox(Apply(f,h0,bxs)))
+
+ */
+ {
+ var bvars = new List<Bpl.Variable>();
+
+ var types = Map(Enumerable.Range(0, arity + 1), i => BplBoundVar("t" + i, predef.Ty, bvars));
+
+ var h = BplBoundVar("h", predef.HeapType, bvars);
+ var goodHeap = FunctionCall(tok, BuiltinFunction.IsGoodHeap, null, h);
+
+ var f = BplBoundVar("f", predef.HandleType, bvars);
+ var boxes = Map(Enumerable.Range(0, arity), i => BplBoundVar("bx" + i, predef.BoxType, bvars));
+
+ var isness = BplAnd(
+ Snoc(Map(Enumerable.Range(0, arity), i =>
+ BplAnd(MkIs(boxes[i], types[i], true),
+ MkIsAlloc(boxes[i], types[i], h, true))),
+ BplAnd(MkIs(f, ClassTyCon(ad, types)),
+ MkIsAlloc(f, ClassTyCon(ad, types), h))));
+
+ var applied = FunctionCall(tok, Apply(ad.Arity), predef.BoxType, Concat(types, Cons(f, Cons<Bpl.Expr>(h, boxes))));
+
+ var applied_is = BplAnd(MkIs(applied, types[ad.Arity], true), MkIsAlloc(applied, types[ad.Arity], h, true));
+
+ sink.TopLevelDeclarations.Add(new Axiom(tok,
+ BplForall(bvars,
+ new Bpl.Trigger(tok, true, new List<Bpl.Expr> {applied}),
+ BplImp(BplAnd(goodHeap, isness), applied_is))));
+ }
+ }
+ }
+
+ private string AddTyAxioms(TopLevelDecl td) {
+ IToken tok = td.tok;
+ var ty_repr =
+ td is ArrowType.ArrowTypeDecl ? predef.HandleType :
+ td is DatatypeDecl ? predef.DatatypeType :
+ predef.RefType;
+ var arity = td.TypeArgs.Count;
+ var inner_name = GetClass(td).TypedIdent.Name;
+ string name = "T" + inner_name;
+ // Create the type constructor
+ {
+ Bpl.Variable tyVarOut = BplFormalVar(null, predef.Ty, false);
+ List<Bpl.Variable> args = new List<Bpl.Variable>(
+ Enumerable.Range(0, arity).Select(i =>
+ (Bpl.Variable)BplFormalVar(null, predef.Ty, true)));
+ var func = new Bpl.Function(tok, name, args, tyVarOut);
+ sink.TopLevelDeclarations.Add(func);
+ }
+
+ // Helper action to create variables and the function call.
+ Action<Action<List<Bpl.Expr>, List<Bpl.Variable>, Bpl.Expr>> Helper = K => {
+ List<Bpl.Expr> argExprs;
+ var args = MkTyParamBinders(td.TypeArgs, out argExprs);
+ var inner = FunctionCall(tok, name, predef.Ty, argExprs);
+ K(argExprs, args, inner);
+ };
+
+ // Create the Tag and calling Tag on this type constructor
+ /*
+ const unique TagList: TyTag;
+ axiom (forall t0: Ty :: { List(t0) } Tag(List(t0)) == TagList);
+ */
+ Helper((argExprs, args, inner) => {
+ Bpl.TypedIdent tag_id = new Bpl.TypedIdent(tok, "Tag" + inner_name, predef.TyTag);
+ Bpl.Constant tag = new Bpl.Constant(tok, tag_id, true);
+ Bpl.Expr tag_expr = new Bpl.IdentifierExpr(tok, tag);
+ Bpl.Expr tag_call = FunctionCall(tok, "Tag", predef.TyTag, inner);
+ Bpl.Expr qq = BplForall(args, BplTrigger(inner), Bpl.Expr.Eq(tag_call, tag_expr));
+ sink.TopLevelDeclarations.Add(new Axiom(tok, qq, name + " Tag"));
+ sink.TopLevelDeclarations.Add(tag);
+ });
+
+ // Create the injectivity axiom and its function
+ /*
+ function List_0(Ty) : Ty;
+ axiom (forall t0: Ty :: { List(t0) } List_0(List(t0)) == t0);
+ */
+ for (int i = 0; i < arity; i++) {
+ Helper((argExprs, args, inner) => {
+ Bpl.Variable tyVarIn = BplFormalVar(null, predef.Ty, true);
+ Bpl.Variable tyVarOut = BplFormalVar(null, predef.Ty, false);
+ var injname = name + "_" + i;
+ var injfunc = new Bpl.Function(tok, injname, Singleton(tyVarIn), tyVarOut);
+ var outer = FunctionCall(tok, injname, args[i].TypedIdent.Type, inner);
+ Bpl.Expr qq = BplForall(args, BplTrigger(inner), Bpl.Expr.Eq(outer, argExprs[i]));
+ sink.TopLevelDeclarations.Add(new Axiom(tok, qq, name + " injectivity " + i));
+ sink.TopLevelDeclarations.Add(injfunc);
});
}
+
+ // Boxing axiom (important for the properties of unbox)
+ /*
+ axiom (forall T: Ty, bx: Box ::
+ { $IsBox(bx, List(T)) }
+ $IsBox(bx, List(T))
+ ==> $Box($Unbox(bx): DatatypeType) == bx
+ && $Is($Unbox(bx): DatatypeType, List(T)));
+ */
+ Helper((argExprs, args, _inner) => {
+ Bpl.Expr bx; var bxVar = BplBoundVar("bx", predef.BoxType, out bx);
+ var ty = FunctionCall(tok, name, predef.Ty, argExprs);
+ var unbox = FunctionCall(tok, BuiltinFunction.Unbox, ty_repr, bx);
+ var box_is = MkIs(bx, ty, true);
+ var unbox_is = MkIs(unbox, ty, false);
+ var box_unbox = FunctionCall(tok, BuiltinFunction.Box, null, unbox);
+ sink.TopLevelDeclarations.Add(
+ new Axiom(tok,
+ BplForall(Snoc(args, bxVar), BplTrigger(box_is),
+ BplImp(box_is, BplAnd(Bpl.Expr.Eq(box_unbox, bx), unbox_is))),
+ "Box/unbox axiom for " + name));
+ });
+
return name;
- }
+ }
Bpl.Constant GetClass(TopLevelDecl cl)
{
@@ -4256,13 +4927,13 @@ namespace Microsoft.Dafny {
return ff;
}
- Bpl.Expr GetField(FieldSelectExpr fse)
+ Bpl.Expr GetField(MemberSelectExpr fse)
{
Contract.Requires(fse != null);
- Contract.Requires(fse.Field != null && fse.Field.IsMutable);
+ Contract.Requires(fse.Member != null && fse.Member is Field && ((Field)(fse.Member)).IsMutable);
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
- return new Bpl.IdentifierExpr(fse.tok, GetField(fse.Field));
+ return new Bpl.IdentifierExpr(fse.tok, GetField((Field)fse.Member));
}
/// <summary>
@@ -4929,6 +5600,8 @@ namespace Microsoft.Dafny {
return Bpl.Type.Real;
} else if (type is IteratorDecl.EverIncreasingType) {
return Bpl.Type.Int;
+ } else if (type is ArrowType) {
+ return predef.HandleType;
} else if (type.IsTypeParameter) {
return predef.BoxType;
} else if (type.IsRefType) {
@@ -4994,6 +5667,30 @@ namespace Microsoft.Dafny {
}
}
+ /// <summary>
+ /// If the type is not normally boxed, insert a box around it.
+ /// For lambda functions.
+ /// </summary>
+ public Bpl.Expr BoxIfUnboxed(Bpl.Expr e, Type t) {
+ if (!ModeledAsBoxType(t)) {
+ return FunctionCall(e.tok, BuiltinFunction.Box, null, e);
+ } else {
+ return e;
+ }
+ }
+
+ /// <summary>
+ /// If the expression is boxed, but the type is not boxed, this unboxes it.
+ /// For lambda functions.
+ /// </summary>
+ public Bpl.Expr UnboxIfBoxed(Bpl.Expr e, Type t) {
+ if (!ModeledAsBoxType(t)) {
+ return FunctionCall(e.tok, BuiltinFunction.Unbox, TrType(t), e);
+ } else {
+ return e;
+ }
+ }
+
public static bool ModeledAsBoxType(Type t) {
Contract.Requires(t != null);
t = t.NormalizeExpand();
@@ -5001,10 +5698,9 @@ namespace Microsoft.Dafny {
// unresolved proxy
return false;
}
- return t.IsTypeParameter;
- }
-
- void BoxAxiom(Bpl.Type repr, TopLevelDecl tc, List<TypeParameter> tyArgs) {
+ var res = t.IsTypeParameter;
+ Contract.Assert(t is ArrowType ? !res : true);
+ return res;
}
// ----- Statement ----------------------------------------------------------------------------
@@ -5196,11 +5892,11 @@ namespace Microsoft.Dafny {
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 dafnyY = new MemberSelectExpr(s.Tok, th, y.Name);
+ dafnyY.Member = 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 dafnyYs = new MemberSelectExpr(s.Tok, th, ys.Name);
+ dafnyYs.Member = 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);
@@ -5672,11 +6368,11 @@ namespace Microsoft.Dafny {
// 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
+ var rds = new MemberSelectExpr(tok, th, iter.Member_Reads.Name);
+ rds.Member = 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
+ var nw = new MemberSelectExpr(tok, th, iter.Member_New.Name);
+ nw.Member = 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) },
@@ -5772,6 +6468,7 @@ namespace Microsoft.Dafny {
var lit = new LiteralExpr(x.tok, Basetypes.BigDec.ZERO);
lit.Type = Type.Real; // resolve here
yield return lit;
+
}
var missingBounds = new List<BoundVar>();
@@ -5911,8 +6608,8 @@ namespace Microsoft.Dafny {
TrStmt_CheckWellformed(rhs, definedness, locals, etran, false);
// check nat restrictions for the RHS
Type lhsType;
- if (lhs is FieldSelectExpr) {
- lhsType = ((FieldSelectExpr)lhs).Type;
+ if (lhs is MemberSelectExpr) {
+ lhsType = ((MemberSelectExpr)lhs).Type;
} else if (lhs is SeqSelectExpr) {
lhsType = ((SeqSelectExpr)lhs).Type;
} else {
@@ -5920,9 +6617,11 @@ namespace Microsoft.Dafny {
}
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);
+ if (lhs is MemberSelectExpr) {
+ var fse = (MemberSelectExpr)lhs;
+ var field = fse.Member as Field;
+ Contract.Assert(field != null);
+ Check_NewRestrictions(fse.tok, obj, field, translatedRhs, definedness, etran);
}
}
@@ -5993,10 +6692,10 @@ namespace Microsoft.Dafny {
// 0: forall i | R(i) { F(i).f := E(i); }
// 1: forall i | R(i) { A[F(i)] := E(i); }
// 2: forall i | R(i) { F(i)[N] := E(i); }
- if (lhs is FieldSelectExpr) {
- var ll = (FieldSelectExpr)lhs;
+ if (lhs is MemberSelectExpr) {
+ var ll = (MemberSelectExpr)lhs;
Fi = ll.Obj;
- lhsBuilder = e => { var l = new FieldSelectExpr(ll.tok, e, ll.FieldName); l.Field = ll.Field; l.Type = ll.Type; return l; };
+ lhsBuilder = e => { var l = new MemberSelectExpr(ll.tok, e, ll.MemberName); l.Member = ll.Member; l.Type = ll.Type; return l; };
} else if (lhs is SeqSelectExpr) {
var ll = (SeqSelectExpr)lhs;
Contract.Assert(ll.SelectOne);
@@ -6071,7 +6770,7 @@ namespace Microsoft.Dafny {
GetObjFieldDetails(lhs, prevEtran, out obj, out field);
var xHeapOF = ExpressionTranslator.ReadHeap(tok, etran.HeapExpr, obj, field);
- Type lhsType = lhs is FieldSelectExpr ? ((FieldSelectExpr)lhs).Type : null;
+ Type lhsType = lhs is MemberSelectExpr ? ((MemberSelectExpr)lhs).Type : null;
g = CondApplyBox(rhs.tok, g, rhs.Type, lhsType);
Trigger tr = lhsAsTrigger ? new Trigger(tok, true, new List<Bpl.Expr>() { xHeapOF }) : null;
@@ -6466,8 +7165,8 @@ namespace Microsoft.Dafny {
private string GetObjFieldDetails(Expression lhs, ExpressionTranslator etran, out Bpl.Expr obj, out Bpl.Expr F) {
string description;
- if (lhs is FieldSelectExpr) {
- var fse = (FieldSelectExpr)lhs;
+ if (lhs is MemberSelectExpr) {
+ var fse = (MemberSelectExpr)lhs;
obj = etran.TrExpr(fse.Obj);
F = GetField(fse);
description = "an object field";
@@ -6739,9 +7438,11 @@ namespace Microsoft.Dafny {
Type lhsType = null;
if (lhs is IdentifierExpr) {
lhsType = lhs.Type;
- } else if (lhs is FieldSelectExpr) {
- var fse = (FieldSelectExpr)lhs;
- lhsType = fse.Field.Type;
+ } else if (lhs is MemberSelectExpr) {
+ var fse = (MemberSelectExpr)lhs;
+ var field = fse.Member as Field;
+ Contract.Assert(field != null);
+ lhsType = field.Type;
}
Bpl.Expr bRhs = bLhss[i]; // the RHS (bRhs) of the assignment to the actual call-LHS (lhs) was a LHS (bLhss[i]) in the Boogie call statement
@@ -7143,6 +7844,8 @@ namespace Microsoft.Dafny {
return u is MultiSetType;
} else if (t is MapType) {
return u is MapType;
+ } else if (t is ArrowType) {
+ return u is ArrowType;
} else {
Contract.Assert(t.IsTypeParameter);
return false; // don't consider any type parameters to be the same (since we have no comparison function for them anyway)
@@ -7240,6 +7943,13 @@ namespace Microsoft.Dafny {
less = ProperMultiset(tok, e0, e1);
atmost = FunctionCall(tok, BuiltinFunction.MultiSetSubset, null, e0, e1);
+ } else if (ty0 is ArrowType) {
+ // TODO: ComputeLessEq for arrow types
+ // what!?
+ eq = Bpl.Expr.False;
+ less = Bpl.Expr.False;
+ atmost = Bpl.Expr.False;
+
} else {
// reference type
Contract.Assert(ty0.IsRefType); // otherwise, unexpected type
@@ -7325,7 +8035,7 @@ namespace Microsoft.Dafny {
}
}
- string nameTypeParam(TypeParameter x) {
+ static string nameTypeParam(TypeParameter x) {
Contract.Requires(x != null);
if (x.Parent != null) {
return x.Parent.FullName + "$" + x.Name;
@@ -7409,8 +8119,6 @@ namespace Microsoft.Dafny {
Bpl.Expr GetWhereClause(IToken tok, Bpl.Expr x, Type type, ExpressionTranslator etran) {
- // I had to change these from Requires to Assert or the compiler barfed at them
- // Afterwards, I coulid rechange them to Requires and it compiled. :'(
Contract.Requires(tok != null);
Contract.Requires(x != null);
Contract.Requires(type != null);
@@ -7432,6 +8140,10 @@ namespace Microsoft.Dafny {
} else if (type is BoolType || type is IntType || type is RealType) {
// nothing to do
return null;
+ /* } else if (type is ArrowType) {
+ // dubious, but nothing to do?!
+ return null;
+ */
} else {
return BplAnd(MkIs(x, type), MkIsAlloc(x, type, etran.HeapExpr));
}
@@ -7501,9 +8213,11 @@ namespace Microsoft.Dafny {
Type lhsType = null;
if (lhs is IdentifierExpr) {
lhsType = lhs.Type;
- } else if (lhs is FieldSelectExpr) {
- var fse = (FieldSelectExpr)lhs;
- lhsType = fse.Field.Type;
+ } else if (lhs is MemberSelectExpr) {
+ var fse = (MemberSelectExpr)lhs;
+ var field = fse.Member as Field;
+ Contract.Assert(field != null);
+ lhsType = field.Type;
}
var bRhs = TrAssignmentRhs(rhss[i].Tok, bLhss[i], lhsType, rhss[i], lhs.Type, builder, locals, etran);
if (bRhs != bLhss[i]) {
@@ -7540,9 +8254,11 @@ namespace Microsoft.Dafny {
Type lhsType = null;
if (lhs is IdentifierExpr) {
lhsType = lhs.Type;
- } else if (lhs is FieldSelectExpr) {
- var fse = (FieldSelectExpr)lhs;
- lhsType = fse.Field.Type;
+ } else if (lhs is MemberSelectExpr) {
+ var fse = (MemberSelectExpr)lhs;
+ var field = fse.Member as Field;
+ Contract.Assert(field != null);
+ lhsType = field.Type;
}
var bRhs = TrAssignmentRhs(rhss[i].Tok, null, lhsType, rhss[i], lhs.Type, builder, locals, etran);
finalRhss.Add(bRhs);
@@ -7570,12 +8286,15 @@ namespace Microsoft.Dafny {
builder.Add(Assert(tok, Bpl.Expr.Imp(Bpl.Expr.True, Bpl.Expr.Eq(rhs[i], rhs[j])), string.Format("when left-hand sides {0} and {1} refer to the same location, they must be assigned the same value", j, i)));
}
}
- } else if (lhs is FieldSelectExpr) {
- var fse = (FieldSelectExpr)lhs;
+ } else if (lhs is MemberSelectExpr) {
+ var fse = (MemberSelectExpr)lhs;
// check that this LHS is not the same as any previous LHSs
for (int j = 0; j < i; j++) {
- var prev = lhss[j] as FieldSelectExpr;
- if (prev != null && prev.Field == fse.Field) {
+ var prev = lhss[j] as MemberSelectExpr;
+ var field = fse.Member as Field;
+ Contract.Assert(field != null);
+ var prevField = prev == null ? null : prev.Member as Field;
+ if (prev != null && prevField == field) {
builder.Add(Assert(tok, Bpl.Expr.Imp(Bpl.Expr.Eq(objs[j], objs[i]), Bpl.Expr.Eq(rhs[i], rhs[j])), string.Format("when left-hand sides {0} and {1} refer to the same location, they must be assigned the same value", j, i)));
}
}
@@ -7662,9 +8381,10 @@ namespace Microsoft.Dafny {
bldr.Add(Bpl.Cmd.SimpleAssign(tok, bLhs, rhs));
});
- } else if (lhs is FieldSelectExpr) {
- var fse = (FieldSelectExpr)lhs;
- Contract.Assert(fse.Field != null);
+ } else if (lhs is MemberSelectExpr) {
+ var fse = (MemberSelectExpr)lhs;
+ var field = fse.Member as Field;
+ Contract.Assert(field != null);
var obj = SaveInTemp(etran.TrExpr(fse.Obj), rhsCanAffectPreviouslyKnownExpressions,
"$obj" + i, predef.RefType, builder, locals);
prevObj[i] = obj;
@@ -7674,8 +8394,9 @@ namespace Microsoft.Dafny {
if (checkDistinctness) {
// check that this LHS is not the same as any previous LHSs
for (int j = 0; j < i; j++) {
- var prev = lhss[j] as FieldSelectExpr;
- if (prev != null && prev.Field == fse.Field) {
+ var prev = lhss[j] as MemberSelectExpr;
+ var prevField = prev == null ? null : prev.Member as Field;
+ if (prevField != null && prevField == field) {
builder.Add(Assert(tok, Bpl.Expr.Neq(prevObj[j], obj), string.Format("left-hand sides {0} and {1} may refer to the same location", j, i)));
}
}
@@ -7683,9 +8404,11 @@ 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 fseField = fse.Member as Field;
+ Contract.Assert(fseField != null);
+ Check_NewRestrictions(tok, obj, fseField, 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));
+ Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(tok, h, ExpressionTranslator.UpdateHeap(tok, h, obj, new Bpl.IdentifierExpr(tok, GetField(fseField)), rhs));
bldr.Add(cmd);
// assume $IsGoodHeap($Heap);
bldr.Add(AssumeGoodHeap(tok, et));
@@ -7886,7 +8609,7 @@ namespace Microsoft.Dafny {
if (tp is NatType) {
return MkIs(bRhs, tp);
} else {
- return Bpl.Expr.True;
+ return Bpl.Expr.True;
}
}
@@ -8149,14 +8872,14 @@ namespace Microsoft.Dafny {
Contract.Requires(translator != null);
var vv = new List<Variable>();
// first, add the type variables
- vv.AddRange(Map(FTVs, tp => NewVar(translator.nameTypeParam(tp), translator.predef.Ty, wantFormals)));
+ vv.AddRange(Map(FTVs, tp => NewVar(nameTypeParam(tp), translator.predef.Ty, wantFormals)));
typeAntecedents = Bpl.Expr.True;
if (UsesHeap) {
var nv = NewVar("$heap", translator.predef.HeapType, wantFormals);
vv.Add(nv);
if (etran != null) {
var isGoodHeap = translator.FunctionCall(Tok, BuiltinFunction.IsGoodHeap, null, new Bpl.IdentifierExpr(Tok, nv));
- typeAntecedents = translator.BplAnd(typeAntecedents, isGoodHeap);
+ typeAntecedents = BplAnd(typeAntecedents, isGoodHeap);
}
}
if (UsesOldHeap) {
@@ -8164,7 +8887,7 @@ namespace Microsoft.Dafny {
vv.Add(nv);
if (etran != null) {
var isGoodHeap = translator.FunctionCall(Tok, BuiltinFunction.IsGoodHeap, null, new Bpl.IdentifierExpr(Tok, nv));
- typeAntecedents = translator.BplAnd(typeAntecedents, isGoodHeap);
+ typeAntecedents = BplAnd(typeAntecedents, isGoodHeap);
}
}
if (ThisType != null) {
@@ -8172,10 +8895,10 @@ namespace Microsoft.Dafny {
vv.Add(nv);
if (etran != null) {
var th = new Bpl.IdentifierExpr(Tok, nv);
- typeAntecedents = translator.BplAnd(typeAntecedents, Bpl.Expr.Neq(th, translator.predef.Null));
+ typeAntecedents = BplAnd(typeAntecedents, Bpl.Expr.Neq(th, translator.predef.Null));
var wh = translator.GetWhereClause(Tok, th, ThisType, etran);
if (wh != null) {
- typeAntecedents = translator.BplAnd(typeAntecedents, wh);
+ typeAntecedents = BplAnd(typeAntecedents, wh);
}
}
}
@@ -8185,7 +8908,7 @@ namespace Microsoft.Dafny {
if (etran != null) {
var wh = translator.GetWhereClause(Tok, new Bpl.IdentifierExpr(Tok, nv), v.Type, etran);
if (wh != null) {
- typeAntecedents = translator.BplAnd(typeAntecedents, wh);
+ typeAntecedents = BplAnd(typeAntecedents, wh);
}
}
}
@@ -8318,7 +9041,11 @@ namespace Microsoft.Dafny {
this.This = thisVar;
this.applyLimited_CurrentFunction = applyLimited_CurrentFunction;
this.layerInterCluster = layerInterCluster;
- this.layerIntraCluster = layerIntraCluster;
+ if (layerIntraCluster == null) {
+ this.layerIntraCluster = layerInterCluster;
+ } else {
+ this.layerIntraCluster = layerIntraCluster;
+ }
this.modifiesFrame = modifiesFrame;
}
@@ -8356,6 +9083,13 @@ namespace Microsoft.Dafny {
Contract.Requires(thisVar != null);
}
+ public ExpressionTranslator(ExpressionTranslator etran, Bpl.Expr heap)
+ : this(etran.translator, etran.predef, heap, etran.This, etran.applyLimited_CurrentFunction, etran.layerInterCluster, etran.layerIntraCluster, etran.modifiesFrame)
+ {
+ Contract.Requires(etran != null);
+ Contract.Requires(heap != null);
+ }
+
public ExpressionTranslator(ExpressionTranslator etran, string modifiesFrame)
: this(etran.translator, etran.predef, etran.HeapExpr, etran.This, etran.applyLimited_CurrentFunction, etran.layerInterCluster, etran.layerIntraCluster, modifiesFrame) {
Contract.Requires(etran != null);
@@ -8381,12 +9115,20 @@ namespace Microsoft.Dafny {
}
}
+ public ExpressionTranslator WithLayer(Bpl.Expr layerArgument)
+ {
+ Contract.Requires(layerArgument != null);
+ Contract.Ensures(Contract.Result<ExpressionTranslator>() != null);
+
+ return new ExpressionTranslator(translator, predef, HeapExpr, This, null, layerArgument, layerArgument, modifiesFrame);
+ }
+
public ExpressionTranslator LimitedFunctions(Function applyLimited_CurrentFunction, Bpl.Expr layerArgument) {
Contract.Requires(applyLimited_CurrentFunction != null);
Contract.Requires(layerArgument != null);
Contract.Ensures(Contract.Result<ExpressionTranslator>() != null);
- return new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, layerInterCluster, layerArgument, modifiesFrame);
+ return new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, /* layerArgument */ layerInterCluster, layerArgument, modifiesFrame);
}
public ExpressionTranslator LayerOffset(int offset) {
@@ -8578,22 +9320,36 @@ namespace Microsoft.Dafny {
}
return s;
- } else if (expr is FieldSelectExpr) {
- FieldSelectExpr e = (FieldSelectExpr)expr;
- Contract.Assert(e.Field != null);
- Bpl.Expr obj = TrExpr(e.Obj);
- Bpl.Expr result;
- if (e.Field.IsMutable) {
- result = ReadHeap(expr.tok, HeapExpr, obj, new Bpl.IdentifierExpr(expr.tok, translator.GetField(e.Field)));
- return translator.CondApplyUnbox(expr.tok, result, e.Field.Type, expr.Type);
- } else {
- result = new Bpl.NAryExpr(expr.tok, new Bpl.FunctionCall(translator.GetReadonlyField(e.Field)), new List<Bpl.Expr> { obj });
- result = translator.CondApplyUnbox(expr.tok, result, e.Field.Type, expr.Type);
- if (translator.IsLit(obj)) {
- result = translator.Lit(result, translator.TrType(expr.Type));
- }
- return result;
- }
+ } else if (expr is MemberSelectExpr) {
+ var e = (MemberSelectExpr)expr;
+ return e.MemberSelectCase(
+ field => {
+ Bpl.Expr obj = TrExpr(e.Obj);
+ Bpl.Expr result;
+ if (field.IsMutable) {
+ result = ReadHeap(expr.tok, HeapExpr, obj, new Bpl.IdentifierExpr(expr.tok, translator.GetField(field)));
+ return translator.CondApplyUnbox(expr.tok, result, field.Type, expr.Type);
+ } else {
+ result = new Bpl.NAryExpr(expr.tok, new Bpl.FunctionCall(translator.GetReadonlyField(field)),
+ new List<Bpl.Expr> {obj});
+ result = translator.CondApplyUnbox(expr.tok, result, field.Type, expr.Type);
+ if (translator.IsLit(obj)) {
+ result = translator.Lit(result, translator.TrType(expr.Type));
+ }
+ return result;
+ }
+ },
+ fn => {
+ var args = new List<Bpl.Expr>();
+ args.AddRange(e.TypeApplication.ConvertAll(translator.TypeToTy));
+ if (fn.IsRecursive) {
+ args.Add(layerInterCluster);
+ }
+ if (!fn.IsStatic) {
+ args.Add(/* translator.BoxIfUnboxed */(TrExpr(e.Obj)/*, e.Type */));
+ }
+ return translator.FunctionCall(e.tok, translator.FunctionHandle(fn), predef.HandleType, args);
+ });
} else if (expr is SeqSelectExpr) {
SeqSelectExpr e = (SeqSelectExpr)expr;
Bpl.Expr seq = TrExpr(e.Seq);
@@ -8693,6 +9449,7 @@ namespace Microsoft.Dafny {
throw new cce.UnreachableException();
}
}
+
} else if (expr is MultiSelectExpr) {
MultiSelectExpr e = (MultiSelectExpr)expr;
Type elmtType = UserDefinedType.ArrayElementType(e.Array.Type);;
@@ -8705,6 +9462,21 @@ namespace Microsoft.Dafny {
}
return x;
+ } else if (expr is ApplyExpr) {
+ ApplyExpr e = (ApplyExpr)expr;
+ int arity = e.Args.Count;
+ var tt = e.Receiver.Type as ArrowType;
+ Contract.Assert(tt != null);
+ Contract.Assert(tt.Arity == arity);
+
+ Func<Expression, Bpl.Expr> TrArg = arg => translator.BoxIfUnboxed(TrExpr(arg), arg.Type);
+
+ var applied = translator.FunctionCall(expr.tok, translator.Apply(arity), predef.BoxType,
+ Concat(Map(tt.TypeArgs,translator.TypeToTy),
+ Cons(TrExpr(e.Receiver), Cons(HeapExpr, e.Args.ConvertAll(arg => TrArg(arg))))));
+
+ return translator.UnboxIfBoxed(applied, tt.Result);
+
} else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
Bpl.Expr layerArgument;
@@ -9021,12 +9793,12 @@ namespace Microsoft.Dafny {
case BinaryExpr.ResolvedOpcode.RankLt:
return Bpl.Expr.Binary(expr.tok, BinaryOperator.Opcode.Lt,
- translator.FunctionCall(expr.tok, BuiltinFunction.DtRank, null, e0),
+ translator.FunctionCall(expr.tok, e.E0.Type.IsDatatype ? BuiltinFunction.DtRank : BuiltinFunction.BoxRank, null, e0),
translator.FunctionCall(expr.tok, BuiltinFunction.DtRank, null, e1));
case BinaryExpr.ResolvedOpcode.RankGt:
return Bpl.Expr.Binary(expr.tok, BinaryOperator.Opcode.Gt,
translator.FunctionCall(expr.tok, BuiltinFunction.DtRank, null, e0),
- translator.FunctionCall(expr.tok, BuiltinFunction.DtRank, null, e1));
+ translator.FunctionCall(expr.tok, e.E1.Type.IsDatatype ? BuiltinFunction.DtRank: BuiltinFunction.BoxRank, null, e1));
default:
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected binary expression
@@ -9072,18 +9844,33 @@ namespace Microsoft.Dafny {
QuantifierExpr e = (QuantifierExpr)expr;
List<Variable> tyvars = translator.MkTyParamBinders(e.TypeArgs);
List<Variable> bvars = new List<Variable>();
- Bpl.Expr typeAntecedent = TrBoundVariables(e.BoundVars, bvars);
- Bpl.QKeyValue kv = TrAttributes(e.Attributes, "trigger");
- Bpl.Trigger tr = null;
- ExpressionTranslator bodyEtran = this;
+
+ var initEtran = this;
+ var bodyEtran = this;
bool _scratch = true;
+
+ Bpl.Expr antecedent = Bpl.Expr.True;
+
if (Attributes.ContainsBool(e.Attributes, "layerQuantifier", ref _scratch)) {
// If this is a layer quantifier, quantify over layers here, and use $LS(ly) layers in the translation of the body
- Bpl.Expr ly; var lyVar = BplBoundVar(e.Refresh("$ly"), predef.LayerType, out ly);
- bvars.Add(lyVar);
+ var ly = BplBoundVar(e.Refresh("$ly", ref translator.otherTmpVarCount), predef.LayerType, bvars);
Expr layer = translator.LayerSucc(ly);
bodyEtran = new ExpressionTranslator(translator, predef, HeapExpr, This, applyLimited_CurrentFunction, layer, layer, modifiesFrame);
}
+ if (Attributes.ContainsBool(e.Attributes, "heapQuantifier", ref _scratch)) {
+ var h = BplBoundVar(e.Refresh("$heap", ref translator.otherTmpVarCount), predef.HeapType, bvars);
+ bodyEtran = new ExpressionTranslator(bodyEtran, h);
+ antecedent = BplAnd(new List<Bpl.Expr> {
+ antecedent,
+ translator.FunctionCall(e.tok, BuiltinFunction.IsGoodHeap, null, h),
+ translator.HeapSameOrSucc(initEtran.HeapExpr, h)
+ });
+ }
+
+ antecedent = BplAnd(antecedent, bodyEtran.TrBoundVariables(e.BoundVars, bvars));
+
+ Bpl.QKeyValue kv = TrAttributes(e.Attributes, "trigger");
+ Bpl.Trigger tr = null;
for (Attributes aa = e.Attributes; aa != null; aa = aa.Prev) {
if (aa.Name == "trigger") {
List<Bpl.Expr> tt = new List<Bpl.Expr>();
@@ -9097,9 +9884,8 @@ namespace Microsoft.Dafny {
tr = new Bpl.Trigger(expr.tok, true, tt, tr);
}
}
- var antecedent = typeAntecedent;
if (e.Range != null) {
- antecedent = Bpl.Expr.And(antecedent, bodyEtran.TrExpr(e.Range));
+ antecedent = BplAnd(antecedent, bodyEtran.TrExpr(e.Range));
}
Bpl.Expr body = bodyEtran.TrExpr(e.Term);
@@ -9122,7 +9908,7 @@ namespace Microsoft.Dafny {
Bpl.Expr y = new Bpl.IdentifierExpr(expr.tok, yVar);
var eq = Bpl.Expr.Eq(y, BoxIfNecessary(expr.tok, TrExpr(e.Term), e.Term.Type));
- var ebody = Bpl.Expr.And(translator.BplAnd(typeAntecedent, TrExpr(e.Range)), eq);
+ var ebody = Bpl.Expr.And(BplAnd(typeAntecedent, TrExpr(e.Range)), eq);
var exst = new Bpl.ExistsExpr(expr.tok, bvars, ebody);
return new Bpl.LambdaExpr(expr.tok, new List<TypeVariable>(), new List<Variable> { yVar }, kv, exst);
@@ -9141,15 +9927,14 @@ namespace Microsoft.Dafny {
var yVar = new Bpl.BoundVariable(expr.tok, new Bpl.TypedIdent(expr.tok, "$y#" + translator.otherTmpVarCount, predef.BoxType));
translator.otherTmpVarCount++;
- Bpl.Expr unboxy = !ModeledAsBoxType(bv.Type) ? translator.FunctionCall(e.tok, BuiltinFunction.Unbox, translator.TrType(bv.Type), new Bpl.IdentifierExpr(expr.tok, yVar))
- : (Bpl.Expr)(new Bpl.IdentifierExpr(expr.tok, yVar));
+ Bpl.Expr unboxy = translator.UnboxIfBoxed(new Bpl.IdentifierExpr(expr.tok, yVar), bv.Type);
Bpl.Expr typeAntecedent = translator.GetWhereClause(bv.tok, unboxy, bv.Type, this);
Dictionary<IVariable, Expression> subst = new Dictionary<IVariable,Expression>();
subst.Add(e.BoundVars[0], new BoogieWrapper(unboxy,e.BoundVars[0].Type));
- var ebody = translator.BplAnd(typeAntecedent ?? Bpl.Expr.True, TrExpr(translator.Substitute(e.Range, null, subst)));
+ var ebody = BplAnd(typeAntecedent ?? Bpl.Expr.True, TrExpr(translator.Substitute(e.Range, null, subst)));
Bpl.Expr l1 = new Bpl.LambdaExpr(e.tok, new List<TypeVariable>(), new List<Variable> { yVar }, kv, ebody);
ebody = TrExpr(translator.Substitute(e.Term, null, subst));
Bpl.Expr l2 = new Bpl.LambdaExpr(e.tok, new List<TypeVariable>(), new List<Variable> { yVar }, kv, BoxIfNecessary(expr.tok, ebody, e.Term.Type));
@@ -9157,6 +9942,10 @@ namespace Microsoft.Dafny {
return translator.FunctionCall(e.tok, BuiltinFunction.MapGlue, null, l1, l2);
+ } else if (expr is LambdaExpr) {
+ var e = (LambdaExpr)expr;
+
+ return TrLambdaExpr(e);
} else if (expr is StmtExpr) {
var e = (StmtExpr)expr;
return TrExpr(e.E);
@@ -9190,6 +9979,58 @@ namespace Microsoft.Dafny {
}
}
+ private Expr TrLambdaExpr(LambdaExpr e) {
+ var bvars = new List<Bpl.Variable>();
+ var bargs = new List<Bpl.Expr>();
+
+ var heap = BplBoundVar(e.MkName("heap"), predef.HeapType, bvars);
+ bargs.Add(heap);
+
+ var subst = new Dictionary<IVariable, Expression>();
+ foreach (var bv in e.BoundVars) {
+ var ve = BplBoundVar(e.MkName(bv.Name), predef.BoxType, bvars);
+ bargs.Add(ve);
+
+ Bpl.Expr unboxy = translator.UnboxIfBoxed(ve, bv.Type);
+
+ subst[bv] = new BoogieWrapper(unboxy, bv.Type);
+ }
+ var su = new Substituter(null, subst, new Dictionary<TypeParameter, Type>(), translator);
+
+ var et = new ExpressionTranslator(this, heap);
+ var lvars = new List<Bpl.Variable>();
+ var ly = BplBoundVar(e.MkName("ly"), predef.LayerType, lvars);
+ et = et.WithLayer(ly);
+
+ var ebody = et.TrExpr(translator.Substitute(e.Body, null, subst));
+ ebody = translator.BoxIfUnboxed(ebody, e.Body.Type);
+
+ Bpl.Expr reqbody = Bpl.Expr.True;
+ if (e.Range != null) {
+ reqbody = et.TrExpr(translator.Substitute(e.Range, null, subst));
+ }
+ if (e.OneShot) {
+ reqbody = BplAnd(reqbody, Bpl.Expr.Eq(HeapExpr, heap));
+ }
+
+ var rdvars = new List<Bpl.Variable>();
+ var o = translator.UnboxIfBoxed(BplBoundVar(e.MkName("o"), predef.BoxType, rdvars), new ObjectType());
+
+ Bpl.Expr ante = Bpl.Expr.And(Bpl.Expr.Neq(o, predef.Null), et.IsAlloced(e.tok, o));
+ Bpl.Expr consequent = translator.InRWClause(e.tok, o, null, e.Reads.ConvertAll(su.SubstFrameExpr), et, null, null);
+ Bpl.Expr rdbody =
+ new Bpl.LambdaExpr(e.tok, new List<TypeVariable>(), rdvars, null,
+ BplImp(ante, consequent));
+
+ return translator.FunctionCall(e.tok, BuiltinFunction.AtLayer, predef.HandleType,
+ new Bpl.LambdaExpr(e.tok, new List<TypeVariable>(), lvars, null,
+ translator.FunctionCall(e.tok, translator.Handle(e.BoundVars.Count), predef.BoxType,
+ new Bpl.LambdaExpr(e.tok, new List<TypeVariable>(), bvars, null, ebody),
+ new Bpl.LambdaExpr(e.tok, new List<TypeVariable>(), bvars, null, reqbody),
+ new Bpl.LambdaExpr(e.tok, new List<TypeVariable>(), bvars, null, rdbody)))
+ , layerIntraCluster ?? layerInterCluster );
+ }
+
public Expression DesugarMatchExpr(MatchExpr e) {
Contract.Requires(e != null);
// Translate:
@@ -9216,8 +10057,8 @@ namespace Microsoft.Dafny {
foreach (var bv in mc.Arguments) {
if (!LocalVariable.HasWildcardName(bv)) {
var dtor = mc.Ctor.Destructors[argIndex];
- var dv = new FieldSelectExpr(bv.tok, e.Source, dtor.Name);
- dv.Field = dtor; // resolve here
+ var dv = new MemberSelectExpr(bv.tok, e.Source, dtor.Name);
+ dv.Member = dtor; // resolve here
dv.Type = bv.Type; // resolve here
substMap.Add(bv, dv);
}
@@ -9227,8 +10068,8 @@ namespace Microsoft.Dafny {
if (r == null) {
r = c;
} else {
- var test = new FieldSelectExpr(mc.tok, e.Source, mc.Ctor.QueryField.Name);
- test.Field = mc.Ctor.QueryField; // resolve here
+ var test = new MemberSelectExpr(mc.tok, e.Source, mc.Ctor.QueryField.Name);
+ test.Member = mc.Ctor.QueryField; // resolve here
test.Type = Type.Bool; // resolve here
var ite = new ITEExpr(mc.tok, test, c, r);
ite.Type = e.Type;
@@ -9258,7 +10099,7 @@ namespace Microsoft.Dafny {
bvars.Add(bvar);
Bpl.Expr wh = translator.GetWhereClause(bv.tok, new Bpl.IdentifierExpr(bv.tok, bvar), bv.Type, this);
if (wh != null) {
- typeAntecedent = translator.BplAnd(typeAntecedent, wh);
+ typeAntecedent = BplAnd(typeAntecedent, wh);
}
}
return typeAntecedent;
@@ -9280,7 +10121,7 @@ namespace Microsoft.Dafny {
var bIe = new Bpl.IdentifierExpr(bvar.tok, bvar);
Bpl.Expr wh = translator.GetWhereClause(bv.tok, bIe, newBoundVar.Type, this);
if (wh != null) {
- typeAntecedent = translator.BplAnd(typeAntecedent, wh);
+ typeAntecedent = BplAnd(typeAntecedent, wh);
}
}
return typeAntecedent;
@@ -9588,9 +10429,11 @@ namespace Microsoft.Dafny {
DatatypeCtorId,
DtRank,
-// DtAlloc,
+ BoxRank,
GenericAlloc,
+
+ AtLayer
}
Bpl.Expr Lit(Bpl.Expr expr, Bpl.Type typ) {
@@ -9932,18 +10775,21 @@ namespace Microsoft.Dafny {
Contract.Assert(args.Length == 1);
Contract.Assert(typeInstantiation == null);
return FunctionCall(tok, "DtRank", Bpl.Type.Int, args);
- /*
- case BuiltinFunction.DtAlloc:
- Contract.Assert(args.Length == 2);
+ case BuiltinFunction.BoxRank:
+ Contract.Assert(args.Length == 1);
Contract.Assert(typeInstantiation == null);
- return FunctionCall(tok, "DtAlloc", Bpl.Type.Bool, args);
- */
+ return FunctionCall(tok, "BoxRank", Bpl.Type.Int, args);
case BuiltinFunction.GenericAlloc:
Contract.Assert(args.Length == 2);
Contract.Assert(typeInstantiation == null);
return FunctionCall(tok, "GenericAlloc", Bpl.Type.Bool, args);
+ case BuiltinFunction.AtLayer:
+ Contract.Assert(args.Length == 2);
+ Contract.Assert(typeInstantiation != null);
+ return FunctionCall(tok, "AtLayer", typeInstantiation, args);
+
default:
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected built-in function
}
@@ -10827,7 +11673,7 @@ namespace Microsoft.Dafny {
if (subUsesHeap) {
usesOldHeap = true;
}
- } else if (expr is FieldSelectExpr) {
+ } else if (expr is MemberSelectExpr) {
usesHeap = true;
} else if (expr is SeqSelectExpr) {
var e = (SeqSelectExpr)expr;
@@ -11004,15 +11850,15 @@ namespace Microsoft.Dafny {
if (anyChanges) {
newExpr = new MapDisplayExpr(expr.tok, elmts);
}
- } else if (expr is FieldSelectExpr) {
- FieldSelectExpr fse = (FieldSelectExpr)expr;
+ } else if (expr is MemberSelectExpr) {
+ MemberSelectExpr fse = (MemberSelectExpr)expr;
Expression substE = Substitute(fse.Obj);
- if (substE != fse.Obj) {
- FieldSelectExpr fseNew = new FieldSelectExpr(fse.tok, substE, fse.FieldName);
- fseNew.Field = fse.Field; // resolve on the fly (and fseNew.Type is set at end of method)
- newExpr = fseNew;
- }
-
+ MemberSelectExpr fseNew = new MemberSelectExpr(fse.tok, substE, fse.MemberName);
+ fseNew.Member = fse.Member;
+ fseNew.TypeApplication = fse.TypeApplication == null
+ ? null
+ : fse.TypeApplication.ConvertAll(t => Resolver.SubstType(t, typeMap));
+ newExpr = fseNew;
} else if (expr is SeqSelectExpr) {
SeqSelectExpr sse = (SeqSelectExpr)expr;
Expression seq = Substitute(sse.Seq);
@@ -11060,6 +11906,12 @@ namespace Microsoft.Dafny {
newExpr = newFce;
}
+ } else if (expr is ApplyExpr) {
+ ApplyExpr e = (ApplyExpr)expr;
+ Expression receiver = Substitute(e.Receiver);
+ List<Expression> args = SubstituteExprList(e.Args);
+ newExpr = new ApplyExpr(e.tok, e.OpenParen, receiver, args);
+
} else if (expr is DatatypeValue) {
DatatypeValue dtv = (DatatypeValue)expr;
List<Expression> newArgs = SubstituteExprList(dtv.Arguments);
@@ -11219,6 +12071,9 @@ namespace Microsoft.Dafny {
newExpr = new ForallExpr(expr.tok, ((QuantifierExpr)expr).TypeArgs, newBoundVars, newRange, newTerm, newAttrs);
} else if (expr is ExistsExpr) {
newExpr = new ExistsExpr(expr.tok, ((QuantifierExpr)expr).TypeArgs, newBoundVars, newRange, newTerm, newAttrs);
+ } else if (expr is LambdaExpr) {
+ var l = (LambdaExpr)expr;
+ newExpr = new LambdaExpr(e.tok, l.OneShot, newBoundVars, newRange, l.Reads.ConvertAll(SubstFrameExpr), newTerm);
} else {
Contract.Assert(false); // unexpected ComprehensionExpr
}
@@ -11568,7 +12423,7 @@ namespace Microsoft.Dafny {
return new Specification<FrameExpression>(ee, SubstAttributes(frame.Attributes));
}
- protected FrameExpression SubstFrameExpr(FrameExpression frame) {
+ public FrameExpression SubstFrameExpr(FrameExpression frame) {
Contract.Requires(frame != null);
return new FrameExpression(frame.tok, Substitute(frame.E), frame.FieldName);
}
@@ -11671,10 +12526,16 @@ namespace Microsoft.Dafny {
}
}
+ Bpl.Expr HeapSameOrSucc(Bpl.Expr oldHeap, Bpl.Expr newHeap) {
+ return Bpl.Expr.Or(
+ Bpl.Expr.Eq(oldHeap, newHeap),
+ FunctionCall(newHeap.tok, BuiltinFunction.HeapSucc, null, oldHeap, newHeap));
+ }
+
// Bpl-making-utilities
- Bpl.Expr BplForall(IEnumerable<Bpl.Variable> args_in, Bpl.Expr body) {
- List<Bpl.Variable> args = new List<Bpl.Variable>(args_in);
+ static Bpl.Expr BplForall(IEnumerable<Bpl.Variable> args_in, Bpl.Expr body) {
+ var args = new List<Bpl.Variable>(args_in);
if (args.Count == 0) {
return body;
} else {
@@ -11683,11 +12544,11 @@ namespace Microsoft.Dafny {
}
// Note: if the trigger is null, makes a forall without any triggers
- Bpl.Expr BplForall(IEnumerable<Bpl.Variable> args_in, Bpl.Trigger trg, Bpl.Expr body) {
+ static Bpl.Expr BplForall(IEnumerable<Bpl.Variable> args_in, Bpl.Trigger trg, Bpl.Expr body) {
if (trg == null) {
return BplForall(args_in, body);
} else {
- List<Bpl.Variable> args = new List<Bpl.Variable>(args_in);
+ var args = new List<Bpl.Variable>(args_in);
if (args.Count == 0) {
return body;
} else {
@@ -11696,11 +12557,11 @@ namespace Microsoft.Dafny {
}
}
- Bpl.Expr BplForall(Bpl.Variable arg, Bpl.Trigger trg, Bpl.Expr body) {
+ static Bpl.Expr BplForall(Bpl.Variable arg, Bpl.Trigger trg, Bpl.Expr body) {
return BplForall(Singleton(arg), trg, body);
}
- Bpl.Expr BplAnd(IEnumerable<Bpl.Expr> conjuncts) {
+ static Bpl.Expr BplAnd(IEnumerable<Bpl.Expr> conjuncts) {
Contract.Requires(conjuncts != null);
Bpl.Expr eq = Bpl.Expr.True;
foreach (var c in conjuncts) {
@@ -11709,7 +12570,7 @@ namespace Microsoft.Dafny {
return eq;
}
- Bpl.Expr BplAnd(Bpl.Expr a, Bpl.Expr b) {
+ static Bpl.Expr BplAnd(Bpl.Expr a, Bpl.Expr b) {
Contract.Requires(a != null);
Contract.Requires(b != null);
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
@@ -11723,7 +12584,7 @@ namespace Microsoft.Dafny {
}
}
- Bpl.Expr BplOr(IEnumerable<Bpl.Expr> disjuncts) {
+ static Bpl.Expr BplOr(IEnumerable<Bpl.Expr> disjuncts) {
Contract.Requires(disjuncts != null);
Bpl.Expr eq = Bpl.Expr.False;
foreach (var d in disjuncts) {
@@ -11732,7 +12593,7 @@ namespace Microsoft.Dafny {
return eq;
}
- Bpl.Expr BplOr(Bpl.Expr a, Bpl.Expr b) {
+ static Bpl.Expr BplOr(Bpl.Expr a, Bpl.Expr b) {
Contract.Requires(a != null);
Contract.Requires(b != null);
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
@@ -11760,12 +12621,12 @@ namespace Microsoft.Dafny {
}
}
- Bpl.Expr BplImp(Bpl.Expr a, Bpl.Expr b) {
+ static Bpl.Expr BplImp(Bpl.Expr a, Bpl.Expr b) {
Contract.Requires(a != null);
Contract.Requires(b != null);
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
- if (a == Bpl.Expr.True || b == Bpl.Expr.True) {
+ if (a == Bpl.Expr.True || b == Bpl.Expr.True || b == Bpl.Expr.False) {
return b;
} else if (a == Bpl.Expr.False) {
return Bpl.Expr.True;
@@ -11774,15 +12635,49 @@ namespace Microsoft.Dafny {
}
}
+ private static void BplIfIf(IToken tk, bool yes, Bpl.Expr guard, Bpl.StmtListBuilder builder, Action<Bpl.StmtListBuilder> k) {
+ if (yes) {
+ var newBuilder = new Bpl.StmtListBuilder();
+ k(newBuilder);
+ builder.Add(new Bpl.IfCmd(tk, guard, newBuilder.Collect(tk), null, null));
+ } else {
+ k(builder);
+ }
+ }
+
+ /// <summary>
+ /// lhs should be a Bpl.IdentifierExpr.
+ /// Creates lhs := rhs;
+ /// </summary>
+ static Bpl.Cmd BplSimplestAssign(Bpl.Expr lhs, Bpl.Expr rhs) {
+ Contract.Requires(lhs is Bpl.IdentifierExpr);
+ return new Bpl.AssignCmd(rhs.tok,
+ Singleton((AssignLhs)new SimpleAssignLhs(rhs.tok, (Bpl.IdentifierExpr)lhs)),
+ Singleton(rhs));
+ }
+
/// Makes a simple trigger
- Bpl.Trigger BplTrigger(Bpl.Expr e) {
+ static Bpl.Trigger BplTrigger(Bpl.Expr e) {
return new Trigger(e.tok, true, new List<Bpl.Expr> { e });
}
- Bpl.Axiom BplAxiom(Bpl.Expr e) {
+ static Bpl.Axiom BplAxiom(Bpl.Expr e) {
return new Bpl.Axiom(e.tok, e);
}
+ static Bpl.Expr BplLocalVar(string name, Bpl.Type ty, List<Bpl.Variable> lvars) {
+ Bpl.Expr v;
+ lvars.Add(BplLocalVar(name, ty, out v));
+ return v;
+ }
+
+ static Bpl.LocalVariable BplLocalVar(string name, Bpl.Type ty, out Bpl.Expr e) {
+ Contract.Requires(ty != null);
+ var v = new Bpl.LocalVariable(ty.tok, new Bpl.TypedIdent(ty.tok, name, ty));
+ e = new Bpl.IdentifierExpr(ty.tok, name, ty);
+ return v;
+ }
+
/* This function allows you to replace, for example:
Bpl.BoundVariable iVar = new Bpl.BoundVariable(e.tok, new Bpl.TypedIdent(e.tok, "$i", Bpl.Type.Int));
@@ -11796,17 +12691,22 @@ namespace Microsoft.Dafny {
Contract.Requires(ty != null);
var v = new Bpl.BoundVariable(ty.tok, new Bpl.TypedIdent(ty.tok, name, ty));
e = new Bpl.IdentifierExpr(ty.tok, name, ty);
- // e = new Bpl.IdentifierExpr(ty.tok, v);
return v;
}
+ static Bpl.Expr BplBoundVar(string name, Bpl.Type ty, List<Bpl.Variable> bvars) {
+ Bpl.Expr e;
+ bvars.Add(BplBoundVar(name, ty, out e));
+ return e;
+ }
+
// Makes a formal variable
- Bpl.Formal BplFormalVar(string name, Bpl.Type ty, bool incoming) {
+ static Bpl.Formal BplFormalVar(string name, Bpl.Type ty, bool incoming) {
Bpl.Expr _scratch;
return BplFormalVar(name, ty, incoming, out _scratch);
}
- Bpl.Formal BplFormalVar(string name, Bpl.Type ty, bool incoming, out Bpl.Expr e) {
+ static Bpl.Formal BplFormalVar(string name, Bpl.Type ty, bool incoming, out Bpl.Expr e) {
Bpl.Formal res;
if (name == null) {
name = Bpl.TypedIdent.NoName;
@@ -11816,6 +12716,12 @@ namespace Microsoft.Dafny {
return res;
}
+ static Bpl.Expr BplFormalVar(string name, Bpl.Type ty, bool incoming, List<Bpl.Variable> fvars) {
+ Bpl.Expr e;
+ fvars.Add(BplFormalVar(name, ty, incoming, out e));
+ return e;
+ }
+
List<Bpl.Variable> MkTyParamBinders(List<TypeParameter> args) {
List<Bpl.Expr> _scratch;
return MkTyParamBinders(args, out _scratch);
@@ -11853,50 +12759,32 @@ namespace Microsoft.Dafny {
// Utilities for lists and dicts...
static List<A> Singleton<A>(A x) {
- return new List<A> { x };
+ return Util.Singleton(x);
+ }
+
+ static List<A> Cons<A>(A x, List<A> xs) {
+ return Util.Cons(x, xs);
}
static List<A> Snoc<A>(List<A> xs, A x) {
- List<A> cpy = new List<A>(xs);
- cpy.Add(x);
- return cpy;
+ return Util.Snoc(xs, x);
}
static List<A> Concat<A>(List<A> xs, List<A> ys) {
- List<A> cpy = new List<A>(xs);
- cpy.AddRange(ys);
- return cpy;
+ return Util.Concat(xs, ys);
}
- public static List<B> Map<A,B>(IEnumerable<A> xs, Func<A,B> f)
- {
- List<B> ys = new List<B>();
- foreach (A x in xs) {
- ys.Add(f(x));
- }
- return ys;
+
+ static List<B> Map<A,B>(IEnumerable<A> xs, Func<A,B> f) {
+ return Util.Map(xs, f);
}
- public static void MapM<A>(IEnumerable<A> xs, Action<A> K)
- {
+ static void MapM<A>(IEnumerable<A> xs, Action<A> K) {
foreach (A x in xs) {
K(x);
}
}
- public static readonly List<Boolean> Bools = new List<Boolean> { false, true };
-
- public static Dictionary<A,B> Dict<A,B>(IEnumerable<A> xs, IEnumerable<B> ys) {
- return Dict<A,B>(xs.Zip(ys));
- }
-
- public static Dictionary<A,B> Dict<A,B>(IEnumerable<Tuple<A,B>> xys) {
- Dictionary<A,B> res = new Dictionary<A,B>();
- foreach (var p in xys) {
- res[p.Item1] = p.Item2;
- }
- return res;
- }
-
+ static readonly List<Boolean> Bools = new List<Boolean> { false, true };
}
}
diff --git a/Source/Dafny/Util.cs b/Source/Dafny/Util.cs
index 30258092..61004ddd 100644
--- a/Source/Dafny/Util.cs
+++ b/Source/Dafny/Util.cs
@@ -3,11 +3,17 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
+using Microsoft.Boogie;
+
+
namespace Microsoft.Dafny {
class Util
{
- public delegate string ToString<T>(T t);
- public static string Comma<T>(string comma, IEnumerable<T> l, ToString<T> f) {
+ public static string Comma<T>(IEnumerable<T> l, Func<T, string> f) {
+ return Comma(",", l, f);
+ }
+
+ public static string Comma<T>(string comma, IEnumerable<T> l, Func<T,string> f) {
string res = "";
string c = "";
foreach(var t in l) {
@@ -16,5 +22,49 @@ namespace Microsoft.Dafny {
}
return res;
}
+
+ public static List<B> Map<A,B>(IEnumerable<A> xs, Func<A,B> f)
+ {
+ List<B> ys = new List<B>();
+ foreach (A x in xs) {
+ ys.Add(f(x));
+ }
+ return ys;
+ }
+
+ public static List<A> Nil<A>() {
+ return new List<A>();
+ }
+
+ public static List<A> Singleton<A>(A x) {
+ return new List<A> { x };
+ }
+
+ public static List<A> Cons<A>(A x, List<A> xs) {
+ return Concat(Singleton(x), xs);
+ }
+
+ public static List<A> Snoc<A>(List<A> xs, A x) {
+ return Concat(xs, Singleton(x));
+ }
+
+ public static List<A> Concat<A>(List<A> xs, List<A> ys) {
+ List<A> cpy = new List<A>(xs);
+ cpy.AddRange(ys);
+ return cpy;
+ }
+
+ public static Dictionary<A,B> Dict<A,B>(IEnumerable<A> xs, IEnumerable<B> ys) {
+ return Dict<A,B>(xs.Zip(ys));
+ }
+
+ public static Dictionary<A,B> Dict<A,B>(IEnumerable<Tuple<A,B>> xys) {
+ Dictionary<A,B> res = new Dictionary<A,B>();
+ foreach (var p in xys) {
+ res[p.Item1] = p.Item2;
+ }
+ return res;
+ }
+
}
}
diff --git a/Source/DafnyExtension/IdentifierTagger.cs b/Source/DafnyExtension/IdentifierTagger.cs
index 4cf752fb..beab8303 100644
--- a/Source/DafnyExtension/IdentifierTagger.cs
+++ b/Source/DafnyExtension/IdentifierTagger.cs
@@ -243,9 +243,12 @@ namespace DafnyLanguage
} else if (expr is IdentifierExpr) {
var e = (IdentifierExpr)expr;
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, e.Type, "field", false, module);
+ } else if (expr is MemberSelectExpr) {
+ var e = (MemberSelectExpr)expr;
+ var field = e.Member as Field;
+ if (field != null) {
+ IdRegion.Add(regions, e.tok, field, e.Type, "field", false, module);
+ }
} else if (expr is LetExpr) {
var e = (LetExpr)expr;
foreach (var bv in e.BoundVars) {
diff --git a/Test/VSI-Benchmarks/b6.dfy b/Test/VSI-Benchmarks/b6.dfy
index 660fe85c..7ef30235 100644
--- a/Test/VSI-Benchmarks/b6.dfy
+++ b/Test/VSI-Benchmarks/b6.dfy
@@ -4,28 +4,28 @@
class Collection<T> {
ghost var footprint:set<object>;
var elements:seq<T>;
-
+
function Valid():bool
reads this, footprint;
{
this in footprint
}
-
+
method GetCount() returns (c:int)
requires Valid();
ensures 0<=c;
{
c:=|elements|;
}
-
+
method Init()
modifies this;
ensures Valid() && fresh(footprint -{this});
{
elements := [];
- footprint := {this};
+ footprint := {this};
}
-
+
method GetItem(i:int ) returns (x:T)
requires Valid();
requires 0<=i && i<|elements|;
@@ -33,7 +33,7 @@ class Collection<T> {
{
x:=elements[i];
}
-
+
method Add(x:T )
requires Valid();
modifies footprint;
@@ -42,7 +42,7 @@ class Collection<T> {
{
elements:= elements + [x];
}
-
+
method GetIterator() returns (iter:Iterator<T>)
requires Valid();
ensures iter != null && iter.Valid();
@@ -51,22 +51,22 @@ class Collection<T> {
{
iter:= new Iterator<T>.Init(this);
}
-
+
}
class Iterator<T> {
-
+
var c:Collection<T>;
var pos:int;
-
+
ghost var footprint:set<object>;
-
+
function Valid():bool
reads this, footprint;
{
this in footprint && c != null && -1 <= pos && null !in footprint
}
-
+
method Init(coll:Collection<T>)
requires coll != null;
modifies this;
@@ -75,9 +75,9 @@ class Iterator<T> {
{
c := coll;
pos := -1;
- footprint := {this};
+ footprint := {this};
}
-
+
method MoveNext() returns (b:bool)
requires Valid();
modifies footprint;
@@ -87,21 +87,21 @@ class Iterator<T> {
pos := pos+1;
b := pos < |c.elements|;
}
-
+
function HasCurrent():bool //???
requires Valid();
- reads this, c;
+ reads this, c, footprint;
{
0 <= pos && pos < |c.elements|
}
-
+
method GetCurrent() returns (x:T)
requires Valid() && HasCurrent();
ensures c.elements[pos] == x;
{
x := c.elements[pos];
}
-}
+}
class Client
{
@@ -112,26 +112,26 @@ class Client
c.Add(33);
c.Add(45);
c.Add(78);
-
+
var s := [];
-
+
var iter := c.GetIterator();
var b := iter.MoveNext();
-
+
while (b)
invariant iter.Valid() && b == iter.HasCurrent() && fresh(iter.footprint);
invariant c.Valid() && fresh(c.footprint) && iter.footprint !! c.footprint; //disjoint footprints
invariant 0 <= iter.pos && iter.pos <=|c.elements| && s == c.elements[..iter.pos] ;
invariant iter.c == c;
decreases |c.elements| - iter.pos;
- {
+ {
var x := iter.GetCurrent();
s := s + [x];
b := iter.MoveNext();
}
-
+
assert s == c.elements; //verifies that the iterator returns the correct things
c.Add(100);
}
-
+
}
diff --git a/Test/dafny0/Definedness.dfy b/Test/dafny0/Definedness.dfy
index 67cfa710..fc724097 100644
--- a/Test/dafny0/Definedness.dfy
+++ b/Test/dafny0/Definedness.dfy
@@ -59,7 +59,7 @@ class SoWellformed {
modifies s;
ensures next.xyz < 100; // error: may not be well-defined (if this in s and body sets next to null)
{
-
+
}
method R(a: SoWellformed, s: set<SoWellformed>) returns (c: bool, d: SoWellformed)
requires next != null && this !in s;
@@ -220,14 +220,14 @@ function Postie1(c: Mountain): Mountain
}
function Postie2(c: Mountain): Mountain
- requires c != null && c.x == 5;
+ requires c != null && c.x == 5; reads c;
ensures Postie2(c).x == 5; // error: well-formedness error (null dereference)
{
c
}
function Postie3(c: Mountain): Mountain // all is cool
- requires c != null && c.x == 5;
+ requires c != null && c.x == 5; reads c;
ensures Postie3(c) != null && Postie3(c).x < 10;
ensures Postie3(c).x == 5;
{
@@ -235,7 +235,7 @@ function Postie3(c: Mountain): Mountain // all is cool
}
function Postie4(c: Mountain): Mountain
- requires c != null && c.x <= 5;
+ requires c != null && c.x <= 5; reads c;
ensures Postie4(c) != null && Postie4(c).x < 10;
ensures Postie4(c).x == 5; // error: postcondition might not hold
{
diff --git a/Test/dafny0/Modules0.dfy b/Test/dafny0/Modules0.dfy
index c47bb756..ac466af2 100644
--- a/Test/dafny0/Modules0.dfy
+++ b/Test/dafny0/Modules0.dfy
@@ -53,8 +53,8 @@ module X0 {
class MyClass0 {
method Down() {
}
- method Up(x1: MyClass1, // error: MyClass1 is not in scope
- x2: MyClass2) { // error: MyClass2 is not in scope
+ method Up<S>(x1: MyClass1, // error: MyClass1 is not in scope
+ x2: MyClass2) { // error: MyClass2 is not in scope
}
}
}
@@ -65,7 +65,7 @@ module X1 {
method Down(x0: X0'.MyClass0) {
x0.Down();
}
- method Up(x2: MyClass2) { // error: class MyClass2 is not in scope
+ method Up<T>(x2: MyClass2) { // error: class MyClass2 is not in scope
}
}
}
@@ -89,7 +89,7 @@ module X2 {
module YY {
class MyClassY {
method M() { }
- method P(g: ClassG) { // error: ClassG is not in scope
+ method P<R>(g: ClassG) { // error: ClassG is not in scope
}
}
}
diff --git a/Test/dafny0/Reads.dfy b/Test/dafny0/Reads.dfy
new file mode 100644
index 00000000..645494cb
--- /dev/null
+++ b/Test/dafny0/Reads.dfy
@@ -0,0 +1,57 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// Checking that the reads clause also is checked over requires
+
+class C { var u : int; }
+
+function nope1(c : C):()
+ requires c != null && c.u > 0;
+{()}
+
+function ok1(c : C):()
+ requires c != null && c.u > 0;
+ reads c;
+{()}
+
+function nope2(c : C):()
+ requires c != null && c.u > 0;
+ reads if c != null then {} else {c};
+{()}
+
+function ok2(c : C):()
+ requires c != null && c.u > 0;
+ reads if c != null then {c} else {};
+{()}
+
+function nope3(xs : seq<C>):()
+ requires |xs| > 0 && xs[0] != null && xs[0].u > 0;
+{()}
+
+function ok3(xs : seq<C>):()
+ requires |xs| > 0 && xs[0] != null && xs[0].u > 0;
+ reads xs;
+{()}
+
+function nope4(c : C, xs : set<C>):()
+ requires c != null && c !in xs ==> c.u > 0;
+ reads xs;
+{()}
+
+function ok4(c : C, xs : set<C>):()
+ requires c != null && c in xs ==> c.u > 0;
+ reads xs;
+{()}
+
+// reads over itself
+
+class R { var r : R; }
+
+function nope5(r : R):()
+ reads if r != null then {r.r} else {};
+{()}
+
+function ok5(r : R):()
+ reads if r != null then {r, r.r} else {};
+{()}
+
diff --git a/Test/dafny0/Reads.dfy.expect b/Test/dafny0/Reads.dfy.expect
new file mode 100644
index 00000000..090cf99d
--- /dev/null
+++ b/Test/dafny0/Reads.dfy.expect
@@ -0,0 +1,26 @@
+Reads.dfy(9,30): Error: insufficient reads clause to read field
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Then
+Reads.dfy(18,30): Error: insufficient reads clause to read field
+Execution trace:
+ (0,0): anon0
+ (0,0): anon11_Then
+ (0,0): anon12_Then
+Reads.dfy(28,50): Error: insufficient reads clause to read field
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Then
+ (0,0): anon8_Then
+Reads.dfy(37,43): Error: insufficient reads clause to read field
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Then
+ (0,0): anon8_Then
+Reads.dfy(51,30): Error: insufficient reads clause to read field
+Execution trace:
+ (0,0): anon0
+ (0,0): anon9_Then
+ (0,0): anon3
+
+Dafny program verifier finished with 5 verified, 5 errors
diff --git a/Test/dafny0/SmallTests.dfy b/Test/dafny0/SmallTests.dfy
index 703cbaf1..a208b1b6 100644
--- a/Test/dafny0/SmallTests.dfy
+++ b/Test/dafny0/SmallTests.dfy
@@ -65,7 +65,7 @@ class Node {
requires if next == null then true else 0 <= 5/x; // error: ill-defined then branch
requires if next.next == null then true else true; // error: ill-defined guard
requires 10/x != 8; // this is well-defined, because we get here only if x is non-0
- reads this;
+ reads this, next;
{
12
}
diff --git a/Test/dafny0/Termination.dfy b/Test/dafny0/Termination.dfy
index f484c397..377865fe 100644
--- a/Test/dafny0/Termination.dfy
+++ b/Test/dafny0/Termination.dfy
@@ -346,21 +346,21 @@ class DefaultDecreasesFunction {
}
function F(x: int): int
requires Valid();
- reads Repr;
+ reads this, Repr;
// the default reads clause is: decreases Repr, x
{
if next == null || x < 0 then x else next.F(x + data)
}
function G(x: int): int
requires Valid();
- reads Repr;
+ reads this, Repr;
decreases x;
{
if next == null || x < 0 then x else next.G(x + data) // error: failure to reduce 'decreases' measure
}
function H(x: int): int
requires Valid() && 0 <= x;
- reads Repr;
+ reads this, Repr;
// the default reads clause is: decreases Repr, x
{
if next != null then
diff --git a/Test/dafny1/PriorityQueue.dfy b/Test/dafny1/PriorityQueue.dfy
index 4b2b2283..94223cba 100644
--- a/Test/dafny1/PriorityQueue.dfy
+++ b/Test/dafny1/PriorityQueue.dfy
@@ -8,14 +8,14 @@ class PriorityQueue {
var a: array<int>; // private implementation of PriorityQueue
- predicate Valid
+ predicate Valid()
reads this, Repr;
{
- MostlyValid &&
+ MostlyValid() &&
(forall j :: 2 <= j && j <= n ==> a[j/2] <= a[j])
}
- predicate MostlyValid
+ predicate MostlyValid()
reads this, Repr;
{
this in Repr && a in Repr &&
@@ -26,7 +26,7 @@ class PriorityQueue {
method Init(capacity: int)
requires 0 <= capacity;
modifies this;
- ensures Valid && fresh(Repr - {this});
+ ensures Valid() && fresh(Repr - {this});
ensures N == capacity;
{
N := capacity;
@@ -37,9 +37,9 @@ class PriorityQueue {
}
method Insert(x: int)
- requires Valid && n < N;
+ requires Valid() && n < N;
modifies this, a;
- ensures Valid && fresh(Repr - old(Repr));
+ ensures Valid() && fresh(Repr - old(Repr));
ensures n == old(n) + 1 && N == old(N);
{
n := n + 1;
@@ -49,16 +49,16 @@ class PriorityQueue {
method SiftUp(k: int)
requires 1 <= k && k <= n;
- requires MostlyValid;
+ requires MostlyValid();
requires (forall j :: 2 <= j && j <= n && j != k ==> a[j/2] <= a[j]);
requires (forall j :: 1 <= j && j <= n ==> j/2 != k); // k is a leaf
modifies a;
- ensures Valid;
+ ensures Valid();
{
var i := k;
- assert MostlyValid;
+ assert MostlyValid();
while (1 < i)
- invariant i <= k && MostlyValid;
+ invariant i <= k && MostlyValid();
invariant (forall j :: 2 <= j && j <= n && j != i ==> a[j/2] <= a[j]);
invariant (forall j :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
{
@@ -71,9 +71,9 @@ class PriorityQueue {
}
method RemoveMin() returns (x: int)
- requires Valid && 1 <= n;
+ requires Valid() && 1 <= n;
modifies this, a;
- ensures Valid && fresh(Repr - old(Repr));
+ ensures Valid() && fresh(Repr - old(Repr));
ensures n == old(n) - 1;
{
x := a[1];
@@ -84,17 +84,17 @@ class PriorityQueue {
method SiftDown(k: int)
requires 1 <= k;
- requires MostlyValid;
+ requires MostlyValid();
requires (forall j :: 2 <= j && j <= n && j/2 != k ==> a[j/2] <= a[j]);
requires (forall j :: 2 <= j && j <= n && 1 <= j/2/2 && j/2/2 != k ==> a[j/2/2] <= a[j]);
// Alternatively, the line above can be expressed as:
// requires (forall j :: 1 <= k/2 && j/2 == k && j <= n ==> a[j/2/2] <= a[j]);
modifies a;
- ensures Valid;
+ ensures Valid();
{
var i := k;
while (2*i <= n) // while i is not a leaf
- invariant 1 <= i && MostlyValid;
+ invariant 1 <= i && MostlyValid();
invariant (forall j :: 2 <= j && j <= n && j/2 != i ==> a[j/2] <= a[j]);
invariant (forall j :: 2 <= j && j <= n && 1 <= j/2/2 && j/2/2 != i ==> a[j/2/2] <= a[j]);
{
@@ -123,14 +123,14 @@ class PriorityQueue_Alternative {
var a: array<int>; // private implementation of PriorityQueue
- predicate Valid
+ predicate Valid()
reads this, Repr;
{
- MostlyValid &&
+ MostlyValid() &&
(forall j :: 2 <= j && j <= n ==> a[j/2] <= a[j])
}
- predicate MostlyValid
+ predicate MostlyValid()
reads this, Repr;
{
this in Repr && a in Repr &&
@@ -141,7 +141,7 @@ class PriorityQueue_Alternative {
method Init(capacity: int)
requires 0 <= capacity;
modifies this;
- ensures Valid && fresh(Repr - {this});
+ ensures Valid() && fresh(Repr - {this});
ensures N == capacity;
{
N := capacity;
@@ -152,9 +152,9 @@ class PriorityQueue_Alternative {
}
method Insert(x: int)
- requires Valid && n < N;
+ requires Valid() && n < N;
modifies this, a;
- ensures Valid && fresh(Repr - old(Repr));
+ ensures Valid() && fresh(Repr - old(Repr));
ensures n == old(n) + 1 && N == old(N);
{
n := n + 1;
@@ -163,15 +163,15 @@ class PriorityQueue_Alternative {
}
method SiftUp()
- requires MostlyValid;
+ requires MostlyValid();
requires (forall j :: 2 <= j && j <= n && j != n ==> a[j/2] <= a[j]);
modifies a;
- ensures Valid;
+ ensures Valid();
{
var i := n;
- assert MostlyValid;
+ assert MostlyValid();
while (1 < i)
- invariant i <= n && MostlyValid;
+ invariant i <= n && MostlyValid();
invariant (forall j :: 2 <= j && j <= n && j != i ==> a[j/2] <= a[j]);
invariant (forall j :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
{
@@ -184,9 +184,9 @@ class PriorityQueue_Alternative {
}
method RemoveMin() returns (x: int)
- requires Valid && 1 <= n;
+ requires Valid() && 1 <= n;
modifies this, a;
- ensures Valid && fresh(Repr - old(Repr));
+ ensures Valid() && fresh(Repr - old(Repr));
ensures n == old(n) - 1;
{
x := a[1];
@@ -196,14 +196,14 @@ class PriorityQueue_Alternative {
}
method SiftDown()
- requires MostlyValid;
+ requires MostlyValid();
requires (forall j :: 4 <= j && j <= n ==> a[j/2] <= a[j]);
modifies a;
- ensures Valid;
+ ensures Valid();
{
var i := 1;
while (2*i <= n) // while i is not a leaf
- invariant 1 <= i && MostlyValid;
+ invariant 1 <= i && MostlyValid();
invariant (forall j :: 2 <= j && j <= n && j/2 != i ==> a[j/2] <= a[j]);
invariant (forall j :: 1 <= j/2/2 && j/2 == i && j <= n ==> a[j/2/2] <= a[j]);
{
diff --git a/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy b/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy
index 75a7822e..c752bd38 100644
--- a/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy
+++ b/Test/dafny2/COST-verif-comp-2011-2-MaxTree-class.dfy
@@ -91,7 +91,7 @@ class Tree {
function method IsEmpty(): bool
requires Valid();
- reads Repr;
+ reads this, Repr;
ensures IsEmpty() <==> Contents == [];
{
left == this
diff --git a/Test/demo/tmap.dfy b/Test/demo/tmap.dfy
new file mode 100644
index 00000000..d09863b9
--- /dev/null
+++ b/Test/demo/tmap.dfy
@@ -0,0 +1,31 @@
+
+datatype List<A> = Nil | Cons(A, List<A>)
+
+datatype Tree<A> = Branch(A, trees: List<Tree<A>>)
+
+function ListData(xs: List<A>): set<A>
+ // ensures forall x :: x in ListData(xs) ==> x < xs;
+{
+ match xs
+ case Nil => {}
+ case Cons(x,xs) => {x} + ListData(xs)
+}
+
+function TreeData(t0: Tree<A>): set<A>
+{
+ var Branch(x, ts) := t0;
+ {x} + set t, y | t in ListData(ts) && y in TreeData(t) :: y
+}
+
+function Map(xs : List<A>, f : A -> B): List<B>
+{
+ match xs
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),Map(xs,f))
+}
+
+function TMap(t0 : Tree<A>, f : A -> B): Tree<B>
+{
+ var Branch(x, ts) := t0;
+ Branch(f(x), Map(ts, t => TMap(t,f)))
+}
diff --git a/Test/hofs/Apply.dfy b/Test/hofs/Apply.dfy
new file mode 100644
index 00000000..bdd102c2
--- /dev/null
+++ b/Test/hofs/Apply.dfy
@@ -0,0 +1,29 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+
+method Apply(x : int) returns (i : int)
+ ensures i == x;
+{
+ i := (x => x)(x);
+}
+
+function method Const<A,B>(a : A) : B -> A {
+ b => a
+}
+
+method Test(m : map<int, int -> int -> int>)
+{
+ assume forall i :: i in m;
+ assume forall i, x :: m[i].requires(x);
+ assume forall i, x, y :: m[i](x).requires(y);
+ assume m[1](2)(3) > 5;
+ assert ((m[1])(2))(3) > 4;
+}
+
+method Main() {
+ assert forall x : int, y : int :: Const(x)(y) == (Const(x))(y);
+ assert (a => b => a) == (u : int) => (v : int) => u;
+ assert Const == (u : int) => (v : int) => u;
+}
+
diff --git a/Test/hofs/Apply.dfy.expect b/Test/hofs/Apply.dfy.expect
new file mode 100644
index 00000000..fad1fe33
--- /dev/null
+++ b/Test/hofs/Apply.dfy.expect
@@ -0,0 +1,7 @@
+Apply.dfy(27,16): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Apply.dfy(26,35): anon15_Else
+ Apply.dfy(27,27): anon17_Else
+
+Dafny program verifier finished with 6 verified, 1 error
diff --git a/Test/hofs/Classes.dfy b/Test/hofs/Classes.dfy
new file mode 100644
index 00000000..91d7e384
--- /dev/null
+++ b/Test/hofs/Classes.dfy
@@ -0,0 +1,50 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+
+class C {
+ static function method Static() : bool
+ {
+ true
+ }
+}
+
+method K() {
+ var f := C.Static;
+ var o : object;
+ assert o !in f.reads();
+ assert f.requires();
+ assert f();
+}
+
+
+class T {
+ var h : int -> int;
+}
+
+function B(t : T) : int -> int
+ requires t != null;
+ reads t;
+{
+ t.h
+}
+
+function J(t : T) : int
+ requires t != null;
+ requires t.h.reads(0) == {};
+ reads t;
+ reads if t != null then t.h.reads(0) else {};
+{
+ if t.h.requires(0) then
+ B(t)(0)
+ else
+ B(t)(0) // fail
+}
+
+method U(t : T)
+ requires t != null;
+ modifies t;
+{
+ t.h := x => x;
+ assert J(t) == 0; // ok
+}
diff --git a/Test/hofs/Classes.dfy.expect b/Test/hofs/Classes.dfy.expect
new file mode 100644
index 00000000..84a0417e
--- /dev/null
+++ b/Test/hofs/Classes.dfy.expect
@@ -0,0 +1,10 @@
+Classes.dfy(41,5): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ (0,0): anon11_Then
+ (0,0): anon3
+ (0,0): anon12_Then
+ (0,0): anon13_Else
+ (0,0): anon14_Else
+
+Dafny program verifier finished with 6 verified, 1 error
diff --git a/Test/hofs/Consequence.dfy b/Test/hofs/Consequence.dfy
new file mode 100644
index 00000000..35934470
--- /dev/null
+++ b/Test/hofs/Consequence.dfy
@@ -0,0 +1,9 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Check() {
+ var f : nat -> nat;
+ assume f.requires(0);
+ var i : nat := f(0);
+}
+
diff --git a/Test/hofs/Consequence.dfy.expect b/Test/hofs/Consequence.dfy.expect
new file mode 100644
index 00000000..069e7767
--- /dev/null
+++ b/Test/hofs/Consequence.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 2 verified, 0 errors
diff --git a/Test/hofs/Examples.dfy b/Test/hofs/Examples.dfy
new file mode 100644
index 00000000..c31b68da
--- /dev/null
+++ b/Test/hofs/Examples.dfy
@@ -0,0 +1,59 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function Apply(f: A -> B, x: A): B
+ reads f.reads(x);
+ requires f.requires(x);
+{
+ f(x)
+}
+
+function Apply'(f: A -> B) : A -> B
+{
+ x reads f.reads(x)
+ requires f.requires(x)
+ => f(x)
+}
+
+
+function Compose(f: B -> C, g:A -> B): A -> C
+{
+ x reads g.reads(x)
+ reads if g.requires(x) then f.reads(g(x)) else {}
+ requires g.requires(x)
+ requires f.requires(g(x))
+ => f(g(x))
+}
+
+function W(f : (A,A) -> A): A -> A
+{
+ x requires f.requires(x,x)
+ reads f.reads(x,x)
+ => f(x,x)
+}
+
+function Curry(f : (A,B) -> C) : A -> B -> C
+{
+ x => y requires f.requires(x,y)
+ reads f.reads(x,y)
+ => f(x,y)
+}
+
+function Uncurry(f : A -> B -> C) : (A,B) -> C
+{
+ (x,y) requires f.requires(x)
+ requires f(x).requires(y)
+ reads f.reads(x)
+ reads if f.requires(x) then f(x).reads(y) else {}
+ => f(x)(y)
+}
+
+function S(f : (A,B) -> C, g : A -> B): A -> C
+{
+ x requires g.requires(x)
+ requires f.requires(x,g(x))
+ reads g.reads(x)
+ reads if g.requires(x) then f.reads(x,g(x)) else {}
+ => f(x,g(x))
+}
+
diff --git a/Test/hofs/Examples.dfy.expect b/Test/hofs/Examples.dfy.expect
new file mode 100644
index 00000000..76f19e0d
--- /dev/null
+++ b/Test/hofs/Examples.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 7 verified, 0 errors
diff --git a/Test/hofs/Field.dfy b/Test/hofs/Field.dfy
new file mode 100644
index 00000000..6d3412d7
--- /dev/null
+++ b/Test/hofs/Field.dfy
@@ -0,0 +1,23 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+// calling fields should not make a resolution error:
+
+class Ref<A> {
+ var val: A;
+}
+
+method Nope() {
+ var f := new Ref<int -> bool>;
+ assert f.val(0);
+}
+
+class FnRef<A,B> {
+ var fn: A -> B;
+}
+
+method Nope2() {
+ var f := new FnRef<int,bool>;
+ assert f.fn(0);
+}
+
diff --git a/Test/hofs/Field.dfy.expect b/Test/hofs/Field.dfy.expect
new file mode 100644
index 00000000..927d8b06
--- /dev/null
+++ b/Test/hofs/Field.dfy.expect
@@ -0,0 +1,14 @@
+Field.dfy(12,10): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Field.dfy(12,12): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+Field.dfy(21,10): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Field.dfy(21,12): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 2 verified, 4 errors
diff --git a/Test/hofs/FnRef.dfy b/Test/hofs/FnRef.dfy
new file mode 100644
index 00000000..fb8136b7
--- /dev/null
+++ b/Test/hofs/FnRef.dfy
@@ -0,0 +1,70 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+
+class Ref<A> {
+ var val: A;
+}
+
+method Nope() {
+ var f : Ref<int -> bool>;
+ var g : int -> bool;
+
+ f := new Ref<int -> bool>;
+
+ f.val := x => true;
+
+ g := x reads f reads f.val.reads(x) => !f.val(x);
+}
+
+method M() {
+ var f : Ref<int -> bool>;
+ var g : int -> bool;
+
+ f := new Ref<int -> bool>;
+
+ f.val := x => true;
+
+ g := x reads f reads f.val.reads(x) requires f.val.requires(x) => !f.val(x);
+
+ f.val := g;
+
+ if (!g(0)) {
+ assert !g(0);
+ } else {
+ assert g(0);
+ }
+}
+
+
+method L() {
+ var f : Ref<() -> bool>;
+ f := new Ref<() -> bool>;
+ f.val := () reads f reads f.val.reads() requires !f.val.requires() => true;
+
+ if (f.val.requires()) {
+ assert !f.val.requires();
+ } else {
+ assert f.val.requires();
+ }
+}
+
+method LRead() {
+ var o : object;
+ var f : Ref<() -> bool>;
+ f := new Ref<() -> bool>;
+ f.val := () reads f
+ reads f.val.reads()
+ reads if o in f.val.reads() then {} else {o}
+ => true;
+
+ assume o != null;
+ assert o != f;
+
+ if (o in f.val.reads()) {
+ assert o !in f.val.reads();
+ } else {
+ assert o in f.val.reads();
+ }
+}
+
diff --git a/Test/hofs/FnRef.dfy.expect b/Test/hofs/FnRef.dfy.expect
new file mode 100644
index 00000000..5185c21c
--- /dev/null
+++ b/Test/hofs/FnRef.dfy.expect
@@ -0,0 +1,27 @@
+FnRef.dfy(17,45): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ FnRef.dfy(15,12): anon5_Else
+ (0,0): anon6_Then
+FnRef.dfy(32,8): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ FnRef.dfy(26,12): anon9_Else
+ FnRef.dfy(28,8): anon10_Else
+FnRef.dfy(46,12): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ FnRef.dfy(43,13): anon7_Else
+ (0,0): anon9_Then
+FnRef.dfy(65,14): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ FnRef.dfy(56,13): anon8_Else
+ (0,0): anon10_Then
+FnRef.dfy(67,14): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ FnRef.dfy(56,13): anon8_Else
+ (0,0): anon10_Else
+
+Dafny program verifier finished with 4 verified, 5 errors
diff --git a/Test/hofs/Frame.dfy b/Test/hofs/Frame.dfy
new file mode 100644
index 00000000..891435ba
--- /dev/null
+++ b/Test/hofs/Frame.dfy
@@ -0,0 +1,128 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+
+class C { var u : int; }
+
+method M(f : int -> int)
+ requires f.requires(0);
+{
+ var init := f(0);
+ var o := new C;
+ assert init == f(0);
+}
+
+method M2()
+{
+ var c := new C;
+ c.u := 0;
+ var f := () reads c => c.u;
+ var init := f();
+ c.u := 1;
+ if * {
+ assert f() == init; // should fail
+ } else {
+ assert f() == 1;
+ }
+}
+
+method M3()
+{
+ var c := new C;
+ c.u := 0;
+ var f := () reads c => c.u;
+ assert f() == 0;
+ c.u := 1;
+ assert f() == 1;
+ assert f() == 0; // should fail
+ assert false; // should fail
+}
+
+method Main() {
+ var x := 2;
+ var getX := () => x;
+ assert getX() == 2;
+ x := 3;
+ assert getX() == 2; // the value is copied
+}
+
+method Refs() {
+ var a := new int[1];
+ a[0] := 2;
+ var get;
+ if * {
+
+ get := () reads a => a[0]; // OK
+ assert get() == 2;
+
+ a[0] := 3;
+ assert get() == 3; // OK, the ref is copied, but not the entire array
+
+ a := new int[0];
+ assert get() == 3; // OK, still 3
+ assert get() == 0 || get() == 2; // fail: is three!
+
+ } else if * {
+ get := () => a[0]; // fail: Not enough read
+ } else {
+ get := () reads {} => a[0]; // fail: Not enough read
+ }
+}
+
+method Fiddling(k : int -> int)
+{
+
+ var mkGet := (arr : array<int>) =>
+ () reads arr requires arr != null requires arr.Length > 0 => arr[0];
+
+ var a := new int[1];
+ var b := new int[1];
+
+ var get := mkGet(a);
+
+ a[0] := 0;
+ b[0] := 10;
+
+ assert get() == a[0];
+
+ b[0] := 20;
+
+ assert get() == a[0];
+}
+
+method HeapSucc0(k : int -> int)
+ requires k.requires(0);
+{
+ var init := k(0);
+ var a := new object;
+ assert k(0) == init;
+}
+
+method HeapSucc1(k : int -> int, c : C)
+ requires k.requires(0);
+ requires c !in k.reads(0);
+ modifies c;
+{
+ var init := k(0);
+ if ( c != null ) {
+ c.u := c.u + 1;
+ assert k(0) == init;
+ }
+}
+
+method HeapSucc2(k : int -> int, c : C)
+ requires k.requires(0);
+ modifies c;
+{
+ var init := k(0);
+ if ( c != null ) {
+ c.u := c.u + 1;
+ if ( c !in k.reads(0) ) {
+ assert k(0) == init;
+ } else {
+ assert k(0) == init; // Fail
+ }
+ }
+}
+
+
diff --git a/Test/hofs/Frame.dfy.expect b/Test/hofs/Frame.dfy.expect
new file mode 100644
index 00000000..a4d10c47
--- /dev/null
+++ b/Test/hofs/Frame.dfy.expect
@@ -0,0 +1,38 @@
+Frame.dfy(23,16): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Frame.dfy(19,13): anon5_Else
+ (0,0): anon6_Then
+Frame.dfy(37,14): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Frame.dfy(33,13): anon3_Else
+Frame.dfy(63,23): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon13_Then
+ Frame.dfy(55,13): anon14_Else
+ (0,0): anon15_Then
+ (0,0): anon5
+Frame.dfy(66,19): Error: insufficient reads clause to read array element
+Execution trace:
+ (0,0): anon0
+ (0,0): anon16_Then
+ (0,0): anon17_Then
+Frame.dfy(68,28): Error: insufficient reads clause to read array element
+Execution trace:
+ (0,0): anon0
+ (0,0): anon16_Else
+ (0,0): anon18_Then
+Frame.dfy(123,14): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Then
+ (0,0): anon6_Else
+Frame.dfy(123,19): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Then
+ (0,0): anon6_Else
+
+Dafny program verifier finished with 14 verified, 7 errors
diff --git a/Test/hofs/Lambda.dfy b/Test/hofs/Lambda.dfy
new file mode 100644
index 00000000..44adb4ce
--- /dev/null
+++ b/Test/hofs/Lambda.dfy
@@ -0,0 +1,60 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+
+method M<A>() {
+ var f1 : A -> A := x => x;
+ var f2 : A -> A := (x) => x;
+ var f3 : () -> () := () => ();
+ var tt : () := ();
+ var f4 : (A, A) -> (A, A) := (x, y) => (y, x);
+ var f5 := (x : int) => x;
+
+ var f6 := x requires x != 0 requires x != 1 => x;
+ var f7 := x requires 0 != x requires x != 1 => x;
+ assert f6(2) == f7(2);
+
+ var u := 0;
+ var f8 := () requires u == 0 => true;
+ assert f8();
+ u := 1;
+ assert f8(); // ok, u value is copied at creation of f8
+
+ var f9 := () requires u == 0 => true;
+ assert !f9.requires();
+
+}
+
+datatype List<A> = Cons(A,List<A>) | Nil
+
+method J(xs : List<int>) returns (z : int) {
+ match xs
+ case Cons(y,ys) => z := y;
+ case Nil => z := 0;
+
+ if {
+ case true => z := z;
+ case true => z := 1;
+ }
+}
+
+function Adder() : (int, int) -> int
+ ensures forall x, y :: Adder().requires(x, y);
+ ensures forall x, y :: (Adder())(x, y) == x + y;
+{
+ (x, y) => x + y
+}
+
+function MkId<A>() : A -> A
+{
+ x => x
+}
+
+
+// storage and references to functions
+method T() {
+ var f := x => x + 1;
+ f := u => if u > 0 then f(u) else u;
+ assert f(1) == 2 && f(0) == 0;
+}
+
diff --git a/Test/hofs/Lambda.dfy.expect b/Test/hofs/Lambda.dfy.expect
new file mode 100644
index 00000000..a32c27ff
--- /dev/null
+++ b/Test/hofs/Lambda.dfy.expect
@@ -0,0 +1,14 @@
+Lambda.dfy(24,12): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Lambda.dfy(6,24): anon31_Else
+ Lambda.dfy(7,26): anon32_Else
+ Lambda.dfy(8,27): anon33_Else
+ Lambda.dfy(10,39): anon34_Else
+ Lambda.dfy(11,23): anon35_Else
+ Lambda.dfy(13,15): anon36_Else
+ Lambda.dfy(14,15): anon39_Else
+ Lambda.dfy(18,16): anon42_Else
+ Lambda.dfy(23,16): anon44_Else
+
+Dafny program verifier finished with 7 verified, 1 error
diff --git a/Test/hofs/LambdaParsefail.dfy b/Test/hofs/LambdaParsefail.dfy
new file mode 100644
index 00000000..1d864d73
--- /dev/null
+++ b/Test/hofs/LambdaParsefail.dfy
@@ -0,0 +1,33 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method Fails() {
+ var g1 := x.x => x; // fail
+ var g2 := x() => x; // fail
+ var g3 := ((x)) => x; // fail
+
+}
+
+method Fail() {
+ var g8 := x : int => x; // not ok!
+}
+
+function f():() {
+ a.b(x); a.b(x)
+}
+
+method M() {
+ g := a.b(x);
+}
+
+method M() {
+ g := y => a(y);
+}
+
+method M() {
+ g := y => a.b(y);
+}
+
+function f():() {
+ (u => a.b(x); a(x))(); a(x)
+}
diff --git a/Test/hofs/LambdaParsefail.dfy.expect b/Test/hofs/LambdaParsefail.dfy.expect
new file mode 100644
index 00000000..b1334b85
--- /dev/null
+++ b/Test/hofs/LambdaParsefail.dfy.expect
@@ -0,0 +1,5 @@
+LambdaParsefail.dfy(5,17): error: Invalid variable binding in lambda.
+LambdaParsefail.dfy(6,16): error: Expected variable binding.
+LambdaParsefail.dfy(7,16): error: Expected variable binding.
+LambdaParsefail.dfy(12,17): error: semi expected
+4 parse errors detected in LambdaParsefail.dfy
diff --git a/Test/hofs/LambdaParsefail2.dfy b/Test/hofs/LambdaParsefail2.dfy
new file mode 100644
index 00000000..148fc03c
--- /dev/null
+++ b/Test/hofs/LambdaParsefail2.dfy
@@ -0,0 +1,8 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+
+method Fail2() {
+ var g4 := (x, y : A) => (y, x : B); // RHS should fail!
+}
+
diff --git a/Test/hofs/LambdaParsefail2.dfy.expect b/Test/hofs/LambdaParsefail2.dfy.expect
new file mode 100644
index 00000000..8bbf643c
--- /dev/null
+++ b/Test/hofs/LambdaParsefail2.dfy.expect
@@ -0,0 +1,2 @@
+LambdaParsefail2.dfy(6,33): error: Type specification not allowed here, comma separator was expected.
+1 parse errors detected in LambdaParsefail2.dfy
diff --git a/Test/hofs/Map.dfy b/Test/hofs/Map.dfy
new file mode 100644
index 00000000..a55be2be
--- /dev/null
+++ b/Test/hofs/Map.dfy
@@ -0,0 +1,117 @@
+
+datatype List<A> = Nil | Cons(hd: A,tl: List<A>);
+
+function method Map<A,B>(f : A -> B, xs : List<A>) : List<B>
+ requires forall x :: f.requires(x);
+ reads *;
+ decreases xs;
+{
+ match xs
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),Map(f,xs))
+}
+
+function method Id<A>(x : A) : A { x }
+
+method Test() {
+ assert Map(Id, Cons(1,Nil)) == Cons(1,Nil);
+ var inc := x => x + 1;
+ assert Map(inc, Cons(1,Nil)) == Cons(2,Nil);
+ assert Map(x => x + 1, Cons(1,Nil)) == Cons(2,Nil);
+ assert Map((x) requires x > 0 => x + 1, Nil) == Nil;
+}
+
+function CanCall<A,B>(f : A -> B, xs : List<A>) : bool
+ decreases xs;
+ reads *;
+{
+ match xs
+ case Nil => true
+ case Cons(x,xs) => f.requires(x) && CanCall(f, xs)
+}
+
+function method MegaMap<A,B>(f : A -> B, xs : List<A>) : List<B>
+ requires CanCall(f, xs);
+ reads *;
+ decreases xs;
+{
+ match xs
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),MegaMap(f,xs))
+}
+
+method Test2() {
+ assert MegaMap((x) requires x != 0 => 100 / x, Cons(2, Nil)).hd == 50;
+}
+
+function All<A>(p : A -> bool, xs : List<A>) : bool
+ requires forall x :: p.requires(x) /* && p.reads(x) == {} */;
+ reads *;
+ decreases xs;
+{
+ match xs
+ case Nil => true
+ case Cons(x,xs) => p(x) && All(p,xs)
+}
+
+/*
+function UnionMap(i : A -> set<B>, ys : List<A>): set<B>
+ requires forall x :: i.requires(x) && i.reads(x) == {};
+ decreases ys;
+{
+ match ys
+ case Nil => {}
+ case Cons(x,xs) => i(x) + UnionMap(i,xs)
+}
+*/
+
+function method NinjaMap<A,B>(f : A -> B, ys : List<A>) : List<B>
+ requires All(f.requires, ys);
+// reads UnionMap(f.reads, ys);
+ reads *;
+ decreases ys;
+{
+ match ys
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),NinjaMap(f,xs))
+}
+
+function method Compose(f : B -> C, g : A -> B) : A -> C
+{
+ x requires g.requires(x) && f.requires(g(x))
+ reads g.reads(x) + f.reads(g(x))
+ => f(g(x))
+}
+
+lemma {:induction 0} MapCompose(f : B -> C, g : A -> B, xs : List<A>)
+ requires All(g.requires, xs);
+ requires All(f.requires, NinjaMap(g,xs));
+ requires All(Compose(f,g).requires, xs);
+
+ decreases xs;
+ ensures NinjaMap(f,NinjaMap(g,xs)) == NinjaMap(Compose(f,g),xs);
+{
+ match xs
+ case Nil =>
+ case Cons(x,xs) =>
+ calc {
+ NinjaMap(f,NinjaMap(g,Cons(x,xs)));
+ == NinjaMap(f,Cons(g(x),NinjaMap(g,xs)));
+ == Cons(f(g(x)),NinjaMap(f,NinjaMap(g,xs)));
+ == { MapCompose(f,g,xs); }
+ Cons(f(g(x)),NinjaMap(Compose(f,g),xs));
+ == Cons(Compose(f,g)(x),NinjaMap(Compose(f,g),xs));
+ == NinjaMap(Compose(f,g),Cons(x,xs));
+ }
+}
+
+// auto-mode
+lemma MapCompose2(f : B -> C, g : A -> B, xs : List<A>)
+ requires All(g.requires, xs);
+ requires All(f.requires, NinjaMap(g,xs));
+ requires All(Compose(f,g).requires, xs);
+ decreases xs;
+ ensures NinjaMap(f,NinjaMap(g,xs)) == NinjaMap(Compose(f,g),xs);
+{
+}
+
diff --git a/Test/hofs/MutableField.dfy b/Test/hofs/MutableField.dfy
new file mode 100644
index 00000000..fa0a1f50
--- /dev/null
+++ b/Test/hofs/MutableField.dfy
@@ -0,0 +1,15 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+
+class C {
+ function method f(x : int) : int { x }
+
+ var g : int -> int;
+
+ method M() modifies this;
+ {
+ f := g; // not ok
+ }
+}
+
diff --git a/Test/hofs/MutableField.dfy.expect b/Test/hofs/MutableField.dfy.expect
new file mode 100644
index 00000000..1ffdc239
--- /dev/null
+++ b/Test/hofs/MutableField.dfy.expect
@@ -0,0 +1,2 @@
+MutableField.dfy(12,4): Error: LHS of assignment must denote a mutable field
+1 resolution/type errors detected in MutableField.dfy
diff --git a/Test/hofs/Naked.dfy b/Test/hofs/Naked.dfy
new file mode 100644
index 00000000..17aa828a
--- /dev/null
+++ b/Test/hofs/Naked.dfy
@@ -0,0 +1,51 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+module Functions {
+ function f(x: nat): nat
+ {
+ if x == 0 then 0 else
+ if var b: bool :| true; b then
+ var h := f;
+ h(x-1)
+ else
+ (f)(x-1)
+ }
+
+ function f1(x: nat): nat { if x == 0 then 0 else f2(x - 1) }
+
+ function f2(x: nat): nat { if x == 0 then 0 else (f1)(x - 1) }
+}
+
+module Requires {
+ function t(x: nat): nat
+ requires !t.requires(x);
+ { x }
+
+ function g(x: nat): nat
+ requires !(g).requires(x);
+ { x }
+
+ function g2(x: int): int { h(x) }
+
+ function h(x: int): int
+ requires !g2.requires(x);
+ { x }
+}
+
+module Reads {
+ function t(x: nat): nat
+ reads t.reads(x);
+ { x }
+
+ function g(x: nat): nat
+ reads (g).reads(x);
+ { x }
+
+ function g2(x: int): int { h(x) }
+
+ function h(x: int): int
+ reads g2.reads(x);
+ { x }
+}
+
diff --git a/Test/hofs/Naked.dfy.expect b/Test/hofs/Naked.dfy.expect
new file mode 100644
index 00000000..62c035b2
--- /dev/null
+++ b/Test/hofs/Naked.dfy.expect
@@ -0,0 +1,50 @@
+Naked.dfy(9,16): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Else
+ (0,0): anon9_Then
+Naked.dfy(12,8): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+ (0,0): anon7_Else
+ (0,0): anon8_Else
+ (0,0): anon9_Else
+Naked.dfy(17,53): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Else
+ (0,0): anon6_Else
+Naked.dfy(22,13): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+Naked.dfy(26,14): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+Naked.dfy(29,30): Error: cannot prove termination; try supplying a decreases clause
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+Naked.dfy(29,30): Error: possible violation of function precondition
+Naked.dfy(32,14): Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+Naked.dfy(32,15): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+Naked.dfy(38,9): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+Naked.dfy(42,10): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+Naked.dfy(45,30): Error: cannot prove termination; try supplying a decreases clause
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+Naked.dfy(48,11): Error: cannot use naked function in recursive setting. Possible solution: eta expansion.
+Execution trace:
+ (0,0): anon0
+
+Dafny program verifier finished with 1 verified, 12 errors
diff --git a/Test/hofs/OneShot.dfy b/Test/hofs/OneShot.dfy
new file mode 100644
index 00000000..73b08fe2
--- /dev/null
+++ b/Test/hofs/OneShot.dfy
@@ -0,0 +1,25 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+class Ref<A> {
+ var val : A;
+}
+
+method OneShot() {
+ var g : () -> bool;
+ var i : Ref<int>;
+ i := new Ref;
+
+ g := () -> true;
+
+ assert g();
+
+ i.val := i.val + 1; // heap changes
+
+ if * {
+ assert g(); // should fail
+ } else {
+ assert !g(); // should fail
+ }
+}
+
diff --git a/Test/hofs/OneShot.dfy.expect b/Test/hofs/OneShot.dfy.expect
new file mode 100644
index 00000000..78a9864b
--- /dev/null
+++ b/Test/hofs/OneShot.dfy.expect
@@ -0,0 +1,20 @@
+OneShot.dfy(20,12): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Then
+ OneShot.dfy(13,9): anon5_Else
+ (0,0): anon6_Then
+OneShot.dfy(22,12): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Then
+ OneShot.dfy(13,9): anon5_Else
+ (0,0): anon6_Else
+OneShot.dfy(22,13): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Then
+ OneShot.dfy(13,9): anon5_Else
+ (0,0): anon6_Else
+
+Dafny program verifier finished with 1 verified, 3 errors
diff --git a/Test/hofs/Quant.dfy b/Test/hofs/Quant.dfy
new file mode 100644
index 00000000..70d15902
--- /dev/null
+++ b/Test/hofs/Quant.dfy
@@ -0,0 +1,132 @@
+
+module QuantReads {
+
+ function All<A>(p : A -> bool) : bool
+ reads set x : A, y : object | y in p.reads(x) :: y;
+ requires forall x : A :: p.requires(x);
+ {
+ forall x : A :: p(x)
+ }
+
+ lemma AllQuant<A>(p : A -> bool)
+ requires All.requires(p);
+ requires All(p);
+ ensures forall x : A :: p(x);
+ {
+ }
+
+}
+
+module Forall {
+
+ function All<A>(p : A -> bool) : bool
+ {
+ forall x :: p.requires(x) && p(x)
+ }
+
+ function CallMe(f : int -> int) : int
+ requires All(f.requires);
+ {
+ f(1) + f(2)
+ }
+
+}
+
+module Quant {
+
+ function All<A>(p : A -> bool) : bool
+ requires forall x : A :: p.requires(x);
+ {
+ forall x : A :: p(x)
+ }
+
+ lemma AllBool(p : bool -> bool)
+ requires forall x : bool :: p.requires(x);
+ requires All(p);
+ ensures p(true) && p(false);
+ {
+ }
+
+ method Boo()
+ requires All(x => x);
+ ensures false;
+ {
+ AllBool(x => x);
+ }
+
+ lemma AllQuant<A>(p : A -> bool)
+ requires All.requires(p);
+ requires All(p);
+ ensures forall x : A :: p(x);
+ {
+ }
+
+ method Boo2()
+ requires All(x => x);
+ ensures false;
+ {
+ assert (x => x)(false);
+ }
+
+
+ method Koo(s : set<int>, t : set<int>)
+ requires All(x => (x in s ==> x in t) && (x in t ==> x in s));
+ ensures All(x => x in s <==> x in t);
+ {
+ }
+
+}
+
+module ReadAll {
+
+ datatype List<A> = Nil | Cons(A,List<A>);
+
+ function All(p : A -> bool, xs : List) : bool
+ reads (set x, y | y in p.reads(x) :: y);
+ requires forall x :: p.reads(x) == {} && p.requires(x);
+ decreases xs;
+ {
+ match xs
+ case Nil => true
+ case Cons(x,xs) => p(x) && All(p,xs)
+ }
+
+ function Div(xs : List<int>) : List<int>
+ requires All(x => x > 0, xs);
+ {
+ match xs
+ case Nil => Nil
+ case Cons(x,xs) => Cons(100 / x,Div(xs))
+ }
+
+}
+
+module Requires {
+
+ method SmallTest(f : int -> int)
+ requires f.requires(0);
+ {
+ print f(0);
+ }
+
+ datatype List<A> = Nil | Cons(hd: A,tl: List<A>);
+
+ function All<A>(p : A -> bool, xs : List<A>) : bool
+ requires forall x :: p.requires(x);
+ decreases xs;
+ {
+ match xs
+ case Nil => true
+ case Cons(x,xs) => p(x) && All(p,xs)
+ }
+
+ function method Map<A,B>(f : A -> B, ys : List<A>) : List<B>
+ requires All(f.requires, ys);
+ decreases ys;
+ {
+ match ys
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),Map(f,xs))
+ }
+
+}
diff --git a/Test/hofs/ReadsReads.dfy b/Test/hofs/ReadsReads.dfy
new file mode 100644
index 00000000..bc80713d
--- /dev/null
+++ b/Test/hofs/ReadsReads.dfy
@@ -0,0 +1,59 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function MyReadsOk(f : A -> B, a : A) : set<object>
+ reads f.reads(a);
+{
+ f.reads(a)
+}
+
+function MyReadsOk2(f : A -> B, a : A) : set<object>
+ reads f.reads(a);
+{
+ (f.reads)(a)
+}
+
+function MyReadsOk3(f : A -> B, a : A) : set<object>
+ reads (f.reads)(a);
+{
+ f.reads(a)
+}
+
+function MyReadsOk4(f : A -> B, a : A) : set<object>
+ reads (f.reads)(a);
+{
+ (f.reads)(a)
+}
+
+function MyReadsBad(f : A -> B, a : A) : set<object>
+{
+ f.reads(a)
+}
+
+function MyReadsBad2(f : A -> B, a : A) : set<object>
+{
+ (f.reads)(a)
+}
+
+function MyReadsOk'(f : A -> B, a : A, o : object) : bool
+ reads f.reads(a);
+{
+ o in f.reads(a)
+}
+
+function MyReadsBad'(f : A -> B, a : A, o : object) : bool
+{
+ o in f.reads(a)
+}
+
+function MyRequiresOk(f : A -> B, a : A) : bool
+ reads f.reads(a);
+{
+ f.requires(a)
+}
+
+function MyRequiresBad(f : A -> B, a : A) : bool
+{
+ f.requires(a)
+}
+
diff --git a/Test/hofs/ReadsReads.dfy.expect b/Test/hofs/ReadsReads.dfy.expect
new file mode 100644
index 00000000..50f74728
--- /dev/null
+++ b/Test/hofs/ReadsReads.dfy.expect
@@ -0,0 +1,18 @@
+ReadsReads.dfy(30,5): Error: insufficient reads clause to invoke function
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+ReadsReads.dfy(35,3): Error: insufficient reads clause to invoke function
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+ReadsReads.dfy(46,10): Error: insufficient reads clause to invoke function
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+ReadsReads.dfy(57,5): Error: insufficient reads clause to invoke function
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Else
+
+Dafny program verifier finished with 6 verified, 4 errors
diff --git a/Test/hofs/Renaming.dfy b/Test/hofs/Renaming.dfy
new file mode 100644
index 00000000..7a3f69a5
--- /dev/null
+++ b/Test/hofs/Renaming.dfy
@@ -0,0 +1,25 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function OnId(f : (bool -> bool) -> int) : int
+ reads f.reads(x => x);
+ requires f.requires(y => y);
+{
+ f(z => z)
+}
+
+method Equal() {
+ var id1 : bool -> bool := x => x;
+ var id2 := y => y;
+ assert forall x :: id1(x) == id2(x);
+ assert id1 == id2;
+}
+
+method K<A,B>(P : (A -> A) -> bool)
+{
+ assume P.requires(x => x);
+ assume P(y => y);
+ assert P(z => z);
+ assert (x => y => x) == ((a : A) => (b : B) => a);
+}
+
diff --git a/Test/hofs/Renaming.dfy.expect b/Test/hofs/Renaming.dfy.expect
new file mode 100644
index 00000000..790f6509
--- /dev/null
+++ b/Test/hofs/Renaming.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 5 verified, 0 errors
diff --git a/Test/hofs/ResolveError.dfy b/Test/hofs/ResolveError.dfy
new file mode 100644
index 00000000..7df4bbb3
--- /dev/null
+++ b/Test/hofs/ResolveError.dfy
@@ -0,0 +1,51 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+
+method ResolutionErrors() {
+ var x;
+ var g5 := x, y => (y, x); // fail at resolution
+ var g6 := x, (y => (y, x)); // fail at resolution
+}
+
+// cannot assign functions
+
+class Apa {
+ function f() : int {
+ 0
+ }
+}
+
+method Nope3() {
+ var apa := new Apa;
+ apa.f := () => 2;
+}
+
+method RequiresFail(f : int -> int)
+ // ok
+ requires f(0) == 0;
+ requires f.requires(0);
+ requires f.reads(0) == {};
+
+ // fail
+ requires f(0) == true;
+ requires f(1,2) == 0;
+ requires f(true) == 0;
+ requires f.requires(true);
+ requires f.requires(1) == 0;
+ requires f.requires(1,2);
+ requires f.reads(true) == {};
+ requires f.reads(1) == 0;
+ requires f.reads(1,2) == {};
+{
+}
+
+predicate method Bool()
+{
+ true
+}
+
+method Bla() {
+ assert Bool;
+}
+
diff --git a/Test/hofs/ResolveError.dfy.expect b/Test/hofs/ResolveError.dfy.expect
new file mode 100644
index 00000000..acc01b73
--- /dev/null
+++ b/Test/hofs/ResolveError.dfy.expect
@@ -0,0 +1,14 @@
+ResolveError.dfy(7,11): Error: the number of left-hand sides (1) and right-hand sides (2) must match for a multi-assignment
+ResolveError.dfy(8,11): Error: the number of left-hand sides (1) and right-hand sides (2) must match for a multi-assignment
+ResolveError.dfy(21,6): Error: LHS of assignment must denote a mutable field
+ResolveError.dfy(31,16): Error: arguments must have the same type (got int and bool)
+ResolveError.dfy(32,12): Error: cannot apply arguments with types int,int to expression with type int -> int
+ResolveError.dfy(33,12): Error: cannot apply arguments with types bool to expression with type int -> int
+ResolveError.dfy(34,13): Error: incorrect type of function argument 0 (expected int, got bool)
+ResolveError.dfy(35,25): Error: arguments must have the same type (got bool and int)
+ResolveError.dfy(36,13): Error: wrong number of function arguments (got 2, expected 1)
+ResolveError.dfy(37,13): Error: incorrect type of function argument 0 (expected int, got bool)
+ResolveError.dfy(38,22): Error: arguments must have the same type (got set<object> and int)
+ResolveError.dfy(39,13): Error: wrong number of function arguments (got 2, expected 1)
+ResolveError.dfy(49,9): Error: condition is expected to be of type bool, but is () -> bool
+13 resolution/type errors detected in ResolveError.dfy
diff --git a/Test/hofs/Simple.dfy b/Test/hofs/Simple.dfy
new file mode 100644
index 00000000..4bb58078
--- /dev/null
+++ b/Test/hofs/Simple.dfy
@@ -0,0 +1,90 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function method MkId<A>() : A -> A {
+ x => x
+}
+
+function method IntId() : int -> int {
+ y => y
+}
+
+function method DivZero() : int -> int
+{
+ z => 5 / z // div by zero
+}
+
+function method DivZeroWithReq() : int -> int
+{
+ (z) requires z != 0 => 5 / z
+}
+
+function method DivZero2() : (int, int) -> int {
+ (x, y) requires y != 0 => x / y
+}
+
+function method DivZero3() : int -> int {
+ z => z / 0 // div by zero
+}
+
+function method Shadow() : int -> real -> real {
+ x => x => x
+}
+
+method Reqs() {
+ var fn := (u) requires u => u;
+ print fn(true);
+ print fn(false); // precond violation
+}
+
+method Main() {
+ var id := IntId();
+ print id(5);
+ var polyid : int -> int := MkId();
+ print polyid(5);
+ assert id(2) == polyid(2);
+ assert id(3) != 4 && 5 != polyid(6);
+ var divvy := DivZero2();
+ print divvy(2,5);
+ print divvy(2,0); // precond violation
+}
+
+function method succ(x : int) : int
+ requires x > 0;
+{
+ x + 1
+}
+
+method Main2() {
+ var suc := succ;
+ assert suc(3) == succ(3);
+ assert suc(-1) == 0; // precond violation
+}
+
+function method Id<A>(x : A) : A {
+ x
+}
+
+
+method Main3() {
+ var id := Id;
+ assert id(3) == 3;
+ assert forall x :: (Id(id))(x) == (y => y)(x);
+ assert forall x :: (Id(id))(x) == (y => y)(2); // should fail
+}
+
+
+function P(f: A -> B, x : A): B
+ reads (f.reads)(x);
+ requires (f.requires)(x);
+{
+ f(x)
+}
+
+function Q(f: U -> V, x : U): V
+ reads (f.reads)(x); // would be nice to be able to write P.reads(f,x)
+ requires (f.requires)(x);
+{
+ P(f,x)
+}
+
diff --git a/Test/hofs/Simple.dfy.expect b/Test/hofs/Simple.dfy.expect
new file mode 100644
index 00000000..76871e06
--- /dev/null
+++ b/Test/hofs/Simple.dfy.expect
@@ -0,0 +1,32 @@
+Simple.dfy(14,10): Error: possible division by zero
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Else
+ (0,0): anon6_Then
+Simple.dfy(27,10): Error: possible division by zero
+Execution trace:
+ (0,0): anon0
+ (0,0): anon5_Else
+ (0,0): anon6_Then
+Simple.dfy(37,9): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ Simple.dfy(35,15): anon5_Else
+Simple.dfy(49,9): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+ (0,0): anon2
+Simple.dfy(61,10): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+Simple.dfy(61,18): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+Simple.dfy(73,10): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Simple.dfy(72,38): anon5_Else
+ Simple.dfy(73,38): anon6_Else
+
+Dafny program verifier finished with 13 verified, 7 errors
diff --git a/Test/hofs/TreeMap.dfy b/Test/hofs/TreeMap.dfy
new file mode 100644
index 00000000..95b07590
--- /dev/null
+++ b/Test/hofs/TreeMap.dfy
@@ -0,0 +1,215 @@
+
+datatype List<A> = Nil | Cons(head: A,tail: List<A>);
+
+datatype Tree<A> = Branch(val: A,trees: List<Tree<A>>);
+
+function Set(xs : List) : set
+ ensures forall x :: x in Set(xs) ==> x < xs;
+{
+ match xs
+ case Nil => {}
+ case Cons(x,xs) => {x} + Set(xs)
+}
+
+function TSet(t0 : Tree) : set
+ ensures forall t :: t in TSet(t0) ==> t < t0;
+{
+ match t0 case Branch(x,ts) => {x} + set t, y | t in Set(ts) && y in TSet(t) :: y
+}
+
+// reads {}
+
+function ReadNothingMap(f : A -> B, xs: List<A>): List<B>
+ requires forall x :: x in Set(xs) ==> f.requires(x);
+ requires forall x :: f.reads(x) == {};
+ decreases xs;
+{
+ match xs
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),ReadNothingMap(f,xs))
+}
+
+function TReadNothingMap(f: A -> B, t0: Tree<A>): Tree<B>
+ requires forall x {:heapQuantifier} :: f.requires(x);
+ requires forall x {:heapQuantifier} :: f.reads(x) == {};
+ decreases t0;
+{
+ var Branch(x,ts) := t0;
+ Branch(f(x), ReadNothingMap(t requires t in Set(ts) => TReadNothingMap(f,t), ts))
+}
+
+function TReadNothingMap2(f: A -> B, t0: Tree<A>): Tree<B>
+ requires forall x :: f.requires(x);
+ requires forall x :: f.reads(x) == {};
+ decreases t0;
+{
+ var Branch(x,ts) := t0;
+ Branch(f(x), ReadNothingMap(t requires t in Set(ts) -> TReadNothingMap2(f,t), ts))
+}
+
+function TReadNothingMap3(f: A -> B, t0: Tree<A>): Tree<B>
+ requires forall x :: f.requires(x);
+ requires forall x :: f.reads(x) == {};
+ decreases t0;
+{
+ var Branch(x,ts) := t0;
+ Branch(f(x), ReadNothingMap(
+ t requires t in Set(ts)
+ requires (forall x :: x in TSet(t) ==> f.requires(x))
+ => TReadNothingMap(f,t), ts))
+}
+
+method TestReadNothingStar() {
+ assert TReadNothingMap(x => x + 1, Branch(1,Nil)).Branch?;
+
+ assert TReadNothingMap(x => x + 1, Branch(0,Nil)) == Branch(1,Nil);
+
+ assert TReadNothingMap(x => x + 1, Branch(1,Cons(Branch(0,Nil),Nil)))
+ == Branch(2,Cons(Branch(1,Nil),Nil));
+
+ assert TReadNothingMap2(x -> x + 1, Branch(1,Nil)).Branch?;
+
+ assert TReadNothingMap2(x -> x + 1, Branch(0,Nil)) == Branch(1,Nil);
+
+ assert TReadNothingMap2(x -> x + 1, Branch(1,Cons(Branch(0,Nil),Nil)))
+ == Branch(2,Cons(Branch(1,Nil),Nil));
+}
+
+/// reads *
+
+function ReadStarMap(f : A -> B, xs: List<A>): List<B>
+ requires forall x :: x in Set(xs) ==> f.requires(x);
+ reads *;
+ decreases xs;
+{
+ match xs
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),ReadStarMap(f,xs))
+}
+
+function TReadStarMap(f: A -> B, t0: Tree<A>): Tree<B>
+ requires forall x {:heapQuantifier} :: f.requires(x);
+ reads *;
+ decreases t0;
+{
+ var Branch(x,ts) := t0;
+ Branch(f(x), ReadStarMap(t reads * requires t in Set(ts) => TReadStarMap(f,t), ts))
+}
+
+function TReadStarMap2(f: A -> B, t0: Tree<A>): Tree<B>
+ requires forall x :: f.requires(x);
+ reads *;
+ decreases t0;
+{
+ var Branch(x,ts) := t0;
+ Branch(f(x), ReadStarMap(t reads * requires t in Set(ts) -> TReadStarMap2(f,t), ts))
+}
+
+lemma LitTReadStarMap2(f : A -> B, x : A, ts: List<Tree<A>>)
+ requires forall u :: f.requires(u);
+ ensures TReadStarMap2(f, Branch(x,ts)) ==
+ Branch(f(x), ReadStarMap(t reads * requires t in Set(ts) -> TReadStarMap2(f,t), ts));
+{
+ assert TReadStarMap2(f, Branch(x,ts)).val == f(x);
+ if (ts.Nil?) {
+ assert TReadStarMap2(f, Branch(x,ts)).trees ==
+ ReadStarMap(t reads * requires t in Set(ts) -> TReadStarMap2(f,t),ts);
+ } else {
+ assert TReadStarMap2(f, Branch(x,ts)).trees ==
+ ReadStarMap(t reads * requires t in Set(ts) -> TReadStarMap2(f,t),ts);
+ }
+}
+
+method TestReadStar() {
+ assert TReadStarMap(x => x + 1, Branch(1,Nil)).Branch?;
+
+ assert TReadStarMap(x => x + 1, Branch(0,Nil)) == Branch(1,Nil);
+
+ assert ReadStarMap(t reads * requires t in Set(Cons(Branch(0,Nil),Nil)) -> TReadStarMap(x => x + 1,t)
+ , Cons(Branch(0,Nil),Nil))
+ == Cons(Branch(1,Nil),Nil);
+
+ assert TReadStarMap(x => x + 1, Branch(1,Cons(Branch(0,Nil),Nil))).Branch?;
+
+ assert TReadStarMap(x => x + 1, Branch(1,Cons(Branch(0,Nil),Nil))).val == 2;
+
+ assert TReadStarMap(x => x + 1, Branch(1,Cons(Branch(0,Nil),Nil))).trees == Cons(Branch(1,Nil),Nil);
+
+ assert TReadStarMap(x => x + 1, Branch(1,Cons(Branch(0,Nil),Nil)))
+ == Branch(2,Cons(Branch(1,Nil),Nil));
+
+ assert TReadStarMap2(x -> x + 1, Branch(1,Nil)).Branch?;
+
+ assert TReadStarMap2(x -> x + 1, Branch(0,Nil)) == Branch(1,Nil);
+
+ assert TReadStarMap2(x -> x + 1, Branch(1,Cons(Branch(0,Nil),Nil)))
+ == Branch(2,Cons(Branch(1,Nil),Nil));
+}
+
+/// reads exact
+
+function Map(f : A -> B, xs: List<A>): List<B>
+ requires forall x :: x in Set(xs) ==> f.requires(x);
+ reads set x, y | x in Set(xs) && y in f.reads(x) :: y;
+ decreases xs;
+{
+ match xs
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),Map(f,xs))
+}
+
+function TMap(f : A -> B, t0: Tree<A>): Tree<B>
+ requires forall t :: t in TSet(t0) ==> f.requires(t);
+ reads set x, y | x in TSet(t0) && y in f.reads(x) :: y;
+ decreases t0;
+{
+ var Branch(x,ts) := t0;
+ Branch(
+ f(x),
+ Map( t requires t in Set(ts)
+ reads set x, y | x in TSet(t) && y in f.reads(x) :: y
+ -> TMap(f,t)
+ , ts)
+ )
+}
+
+lemma LitTMap(f : A -> B,x : A, ts: List<Tree<A>>)
+ requires f.requires(x);
+ requires forall t, u :: t in Set(ts) && u in TSet(t) ==> f.requires(u);
+ ensures TMap(f, Branch(x,ts)) ==
+ Branch(f(x),
+ Map( t requires t in Set(ts)
+ reads set x, y | x in TSet(t) && y in f.reads(x) :: y
+ -> TMap(f,t),ts));
+{
+ assert TMap(f, Branch(x,ts)).val == f(x);
+ assert TMap(f, Branch(x,ts)).trees ==
+ Map(t requires t in Set(ts)
+ reads set x, y | x in TSet(t) && y in f.reads(x) :: y
+ -> TMap(f,t),ts);
+}
+
+method Test() {
+ assert TMap(x -> x + 1, Branch(1,Nil)).Branch?;
+
+ assert TMap(x -> x + 1, Branch(0,Nil)) == Branch(1,Nil);
+
+ calc {
+ TMap(x -> x + 1, Branch(1,Cons(Branch(0,Nil),Nil)));
+ == { LitTMap(x -> x + 1,1, Cons(Branch(0,Nil),Nil)); }
+ Branch((x -> x + 1)(1),Map(t -> TMap(x -> x + 1,t),Cons(Branch(0,Nil),Nil)));
+ ==
+ Branch(2,Map(t -> TMap(x -> x + 1,t),Cons(Branch(0,Nil),Nil)));
+ ==
+ Branch(2,Map(t -> TMap(x -> x + 1,t),Cons(Branch(0,Nil),Nil)));
+ ==
+ Branch(2,Cons(TMap(x -> x + 1,Branch(0,Nil)),Nil));
+ ==
+ Branch(2,Cons(Branch((x -> x + 1)(0),Nil),Nil));
+ ==
+ Branch(2,Cons(Branch(1,Nil),Nil));
+ }
+
+ assert TMap(x -> x + 1, Branch(1,Cons(Branch(0,Nil),Nil)))
+ == Branch(2,Cons(Branch(1,Nil),Nil));
+}
diff --git a/Test/hofs/TreeMapSimple.dfy b/Test/hofs/TreeMapSimple.dfy
new file mode 100644
index 00000000..3ba4ffd6
--- /dev/null
+++ b/Test/hofs/TreeMapSimple.dfy
@@ -0,0 +1,49 @@
+// RUN: %dafny /compile:0 "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+datatype List<A> = Nil | Cons(head: A,tail: List<A>);
+
+datatype Tree<A> = Branch(val: A,trees: List<Tree<A>>);
+
+function ListData(xs : List) : set
+ ensures forall x :: x in ListData(xs) ==> x < xs;
+{
+ match xs
+ case Nil => {}
+ case Cons(x,xs) => {x} + ListData(xs)
+}
+
+function TreeData(t0 : Tree) : set
+ ensures forall t :: t in TreeData(t0) ==> t < t0;
+{
+ var Branch(x,ts) := t0;
+ {x} + set t, y | t in ListData(ts) && y in TreeData(t) :: y
+}
+
+function Pre(f : A -> B, s : set<A>) : bool
+ reads (set x, y | x in s && y in f.reads(x) :: y);
+{
+ forall x :: x in s ==> f.reads(x) == {} && f.requires(x)
+}
+
+function method Map(xs : List<A>, f : A -> B): List<B>
+ reads (set x, y | x in ListData(xs) && y in f.reads(x) :: y);
+ requires Pre(f, ListData(xs));
+ decreases xs;
+{
+ match xs
+ case Nil => Nil
+ case Cons(x,xs) => Cons(f(x),Map(xs,f))
+}
+
+function method TMap(t0 : Tree<A>, f : A -> B) : Tree<B>
+ reads (set x, y | x in TreeData(t0) && y in f.reads(x) :: y);
+ requires Pre(f, TreeData(t0));
+ decreases t0;
+{
+ var Branch(x,ts) := t0;
+ Branch(f(x),Map(ts, t requires t in ListData(ts)
+ requires Pre(f, TreeData(t))
+ => TMap(t,f)))
+}
+
diff --git a/Test/hofs/TreeMapSimple.dfy.expect b/Test/hofs/TreeMapSimple.dfy.expect
new file mode 100644
index 00000000..790f6509
--- /dev/null
+++ b/Test/hofs/TreeMapSimple.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 5 verified, 0 errors
diff --git a/Test/hofs/Twice.dfy b/Test/hofs/Twice.dfy
new file mode 100644
index 00000000..2178db9f
--- /dev/null
+++ b/Test/hofs/Twice.dfy
@@ -0,0 +1,38 @@
+// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+function method Twice(f : A -> A): A -> A
+{
+ x requires f.requires(x) && f.requires(f(x))
+ reads f.reads(x) reads if f.requires(x) then f.reads(f(x)) else {}
+ => f(f(x))
+}
+
+method Simple() {
+ assert Twice(x => x + 1)(0) == 2;
+ assert Twice(Twice(x => x + 1))(0) == 4;
+
+ // why does these fail? need requires/reads for literals?
+ // assert Twice(Twice)(x => x + 1)(0) == 4;
+ // assert Twice(Twice)(Twice)(x => x + 1)(0) == 16;
+}
+
+method WithReads() {
+ var a : array<int> := new int[1];
+ a[0] := 1;
+ var f := x reads a => x + a[0];
+ assert Twice(f)(0) == 2;
+ a[0] := 2;
+ assert Twice(f)(0) == 4;
+ assert Twice(f)(0) == 2; // should fail
+ assert false; // should fail
+}
+
+
+function method Twice_bad(f : A -> A): A -> A
+{
+ x requires f.requires(x) && f.requires(f(x))
+ reads f.reads(x) + f.reads(f(x))
+ => f(f(x))
+}
+
diff --git a/Test/hofs/Twice.dfy.expect b/Test/hofs/Twice.dfy.expect
new file mode 100644
index 00000000..5ba4b47b
--- /dev/null
+++ b/Test/hofs/Twice.dfy.expect
@@ -0,0 +1,11 @@
+Twice.dfy(27,22): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ Twice.dfy(23,12): anon3_Else
+Twice.dfy(35,32): Error: possible violation of function precondition
+Execution trace:
+ (0,0): anon0
+ (0,0): anon9_Else
+ (0,0): anon10_Then
+
+Dafny program verifier finished with 4 verified, 2 errors
diff --git a/Test/hofs/Types.dfy b/Test/hofs/Types.dfy
new file mode 100644
index 00000000..9f62763a
--- /dev/null
+++ b/Test/hofs/Types.dfy
@@ -0,0 +1,20 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+method FnEqGhost<A>() {
+ ghost var f : A -> A -> A;
+ ghost var g : A -> (A -> A);
+ ghost var h : (A -> A) -> A;
+ ghost var b1 := f == g; // type checking should be ok
+ ghost var b2 := f == h; // type checking should fail
+
+ ghost var z;
+ ghost var b3 := f == z; // unify in progress
+ ghost var b4 := g == z; // should now be ok
+ ghost var b5 := h == z; // should now fail
+
+ ghost var zz;
+ ghost var b6 := h == zz; // unify in progress
+ ghost var b7 := g == zz; // should fail
+}
+
diff --git a/Test/hofs/Types.dfy.expect b/Test/hofs/Types.dfy.expect
new file mode 100644
index 00000000..11d74db0
--- /dev/null
+++ b/Test/hofs/Types.dfy.expect
@@ -0,0 +1,4 @@
+Types.dfy(9,20): Error: arguments must have the same type (got A -> A -> A and (A -> A) -> A)
+Types.dfy(14,20): Error: arguments must have the same type (got (A -> A) -> A and A -> A -> A)
+Types.dfy(18,20): Error: arguments must have the same type (got A -> A -> A and (A -> A) -> A)
+3 resolution/type errors detected in Types.dfy
diff --git a/Test/hofs/WhileLoop.dfy b/Test/hofs/WhileLoop.dfy
new file mode 100644
index 00000000..dd95cc76
--- /dev/null
+++ b/Test/hofs/WhileLoop.dfy
@@ -0,0 +1,50 @@
+// RUN: %dafny /compile:0 /print:"%t.print" "%s" > "%t"
+// RUN: %diff "%s.expect" "%t"
+
+class Ref<A> {
+ var val: A;
+}
+
+method Nice(n: int) {
+ var f : int -> int := x => x;
+ var i := new Ref<int>;
+ i.val := 0;
+ while (i.val < n)
+ invariant forall u :: f.requires(u);
+ invariant forall u :: f.reads(u) == {};
+ invariant forall u :: f(u) == u + i.val;
+ {
+ i.val := i.val + 1;
+ f := x => f(x) + 1;
+ }
+}
+
+
+method OneShot(n: int) {
+ var f : int -> int := x => x;
+ var i := 0;
+ while (i < n)
+ invariant forall u :: f.requires(u);
+ invariant forall u :: f(u) == u + i;
+ {
+ i := i + 1;
+ f := x reads f.reads(x) -> f(x) + 1;
+ }
+}
+
+method HeapQuant(n: int) {
+ var f : int -> int := x => x;
+ var i := new Ref<int>;
+ ghost var r := 0;
+ i.val := 0;
+ while (i.val < n)
+ invariant forall u {:heapQuantifier} :: f.requires(u);
+ invariant forall u {:heapQuantifier} :: f.reads(u) == {};
+ invariant r == i.val;
+ invariant forall u {:heapQuantifier} :: f(u) == u + r;
+ {
+ i.val, r := i.val + 1, r + 1;
+ f := x => f(x) + 1;
+ }
+}
+
diff --git a/Test/hofs/WhileLoop.dfy.expect b/Test/hofs/WhileLoop.dfy.expect
new file mode 100644
index 00000000..4ef2de53
--- /dev/null
+++ b/Test/hofs/WhileLoop.dfy.expect
@@ -0,0 +1,2 @@
+
+Dafny program verifier finished with 6 verified, 0 errors
diff --git a/Test/scratch/Reads.dfy b/Test/scratch/Reads.dfy
new file mode 100644
index 00000000..336de9d6
--- /dev/null
+++ b/Test/scratch/Reads.dfy
@@ -0,0 +1,26 @@
+class Test {
+ ghost var Repr: set<object>;
+ function Ok() : bool
+ reads this, Repr;
+ { true }
+
+ function Bad(x: int) : bool
+ reads Repr;
+ { true }
+}
+
+
+class C { var c : C; }
+
+function Nope(c : C) : bool
+ reads c.c;
+{ true }
+
+function Okay(c : C) : bool
+ reads c, if c != null then {c.c} else {};
+{ true }
+
+function Okay'(c : C) : bool
+ reads {c} + if c != null then {c.c} else {};
+{ true }
+