summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BCT/BCT.sln14
-rw-r--r--BCT/BytecodeTranslator/BytecodeTranslator.csproj8
-rw-r--r--BCT/BytecodeTranslator/ExpressionTraverser.cs5
-rw-r--r--BCT/BytecodeTranslator/HeapFactory.cs6
-rw-r--r--BCT/BytecodeTranslator/MetadataTraverser.cs6
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs138
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs319
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs285
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneURIDeclarationsTraverser.cs9
-rw-r--r--BCT/BytecodeTranslator/Phone/stubs.bpl41
-rw-r--r--BCT/BytecodeTranslator/Program.cs20
-rw-r--r--BCT/BytecodeTranslator/Sink.cs79
-rw-r--r--BCT/BytecodeTranslator/StatementTraverser.cs181
-rw-r--r--BCT/BytecodeTranslator/TraverserFactory.cs4
-rw-r--r--BCT/PhoneControlsExtractor/PhoneControlsExtractor.py164
-rw-r--r--BCT/RegressionTests/TranslationTest/GeneralHeapInput.txt584
-rw-r--r--BCT/RegressionTests/TranslationTest/SplitFieldsHeapInput.txt600
-rw-r--r--BCT/RegressionTests/TranslationTest/UnitTest0.cs2
-rw-r--r--BCT/TranslationPlugins/PhoneControlsPlugin.cs237
-rw-r--r--BCT/TranslationPlugins/Properties/AssemblyInfo.cs36
-rw-r--r--BCT/TranslationPlugins/TranslationPlugin.cs10
-rw-r--r--BCT/TranslationPlugins/TranslationPlugins.csproj55
-rw-r--r--Binaries/DafnyPrelude.bpl6
-rw-r--r--Binaries/DafnyRuntime.cs36
-rw-r--r--Chalice/src/Parser.scala48
-rw-r--r--Chalice/src/Resolver.scala13
-rw-r--r--Chalice/src/Translator.scala26
-rw-r--r--Chalice/tests/examples/Solver.chalice44
-rw-r--r--Chalice/tests/examples/Solver.output.txt4
-rw-r--r--Chalice/tests/permission-model/permission_arithmetic.output.txt6
-rw-r--r--Chalice/tests/runalltests.bat32
-rw-r--r--Chalice/tests/test-scripts/reg_test.bat11
-rw-r--r--Chalice/tests/test-scripts/reg_test_all.bat23
-rw-r--r--Jennisys/Jennisys.sln21
-rw-r--r--Jennisys/Jennisys/Analyzer.fs737
-rw-r--r--Jennisys/Jennisys/Ast.fs51
-rw-r--r--Jennisys/Jennisys/AstUtils.fs839
-rw-r--r--Jennisys/Jennisys/CodeGen.fs285
-rw-r--r--Jennisys/Jennisys/DafnyModelUtils.fs345
-rw-r--r--Jennisys/Jennisys/DafnyPrinter.fs34
-rw-r--r--Jennisys/Jennisys/Jennisys.fs75
-rw-r--r--Jennisys/Jennisys/Jennisys.fsproj16
-rw-r--r--Jennisys/Jennisys/Lexer.fsl1
-rw-r--r--Jennisys/Jennisys/Logger.fs8
-rw-r--r--Jennisys/Jennisys/Options.fs113
-rw-r--r--Jennisys/Jennisys/Parser.fsy37
-rw-r--r--Jennisys/Jennisys/PipelineUtils.fs89
-rw-r--r--Jennisys/Jennisys/Printer.fs70
-rw-r--r--Jennisys/Jennisys/Resolver.fs113
-rw-r--r--Jennisys/Jennisys/TypeChecker.fs32
-rw-r--r--Jennisys/Jennisys/Utils.fs114
-rw-r--r--Jennisys/Jennisys/examples/List.jen6
-rw-r--r--Jennisys/Jennisys/examples/List3.jen2
-rw-r--r--Jennisys/Jennisys/examples/Number.jen40
-rw-r--r--Jennisys/Jennisys/examples/Set.jen52
-rw-r--r--Jennisys/Jennisys/scripts/StartDafny-jen.bat1
-rw-r--r--Source/Core/AbsyCmd.cs4
-rw-r--r--Source/Core/BoogiePL.atg32
-rw-r--r--Source/Core/CommandLineOptions.cs82
-rw-r--r--Source/Core/Parser.cs312
-rw-r--r--Source/Core/Scanner.cs9
-rw-r--r--Source/Dafny/Compiler.cs131
-rw-r--r--Source/Dafny/Dafny.atg184
-rw-r--r--Source/Dafny/DafnyAst.cs20
-rw-r--r--Source/Dafny/DafnyMain.cs14
-rw-r--r--Source/Dafny/DafnyPipeline.csproj6
-rw-r--r--Source/Dafny/Parser.cs466
-rw-r--r--Source/Dafny/Printer.cs126
-rw-r--r--Source/Dafny/Resolver.cs262
-rw-r--r--Source/Dafny/Scanner.cs9
-rw-r--r--Source/Dafny/SccGraph.cs54
-rw-r--r--Source/Dafny/Translator.cs420
-rw-r--r--Source/DafnyDriver/DafnyDriver.cs98
-rw-r--r--Source/DafnyDriver/DafnyDriver.csproj6
-rw-r--r--Source/Model/Model.cs1
-rw-r--r--Source/Provers/Z3/TypeDeclCollector.cs7
-rw-r--r--Test/VSI-Benchmarks/b3.dfy9
-rw-r--r--Test/VSI-Benchmarks/b7.dfy8
-rw-r--r--Test/VSI-Benchmarks/b8.dfy30
-rw-r--r--Test/bitvectors/Answer3
-rw-r--r--Test/bitvectors/bv10.bpl10
-rw-r--r--Test/bitvectors/runtest.bat2
-rw-r--r--Test/dafny0/Answer2
-rw-r--r--Test/dafny0/Basics.dfy14
-rw-r--r--Test/dafny0/Definedness.dfy8
-rw-r--r--Test/dafny0/NatTypes.dfy2
-rw-r--r--Test/dafny0/Termination.dfy2
-rw-r--r--Test/dafny0/TypeAntecedents.dfy2
-rw-r--r--Test/dafny0/TypeParameters.dfy10
-rw-r--r--Test/dafny1/Celebrity.dfy2
-rw-r--r--Test/dafny1/Rippling.dfy4
-rw-r--r--Test/dafny1/UltraFilter.dfy2
92 files changed, 5576 insertions, 2910 deletions
diff --git a/BCT/BCT.sln b/BCT/BCT.sln
index c822a0bb..308706e2 100644
--- a/BCT/BCT.sln
+++ b/BCT/BCT.sln
@@ -42,6 +42,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContractExtractor", "..\..\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Contracts", "..\..\CCICodePlex\Ast\Metadata\Sources\Microsoft.Contracts\Microsoft.Contracts.csproj", "{B114E5FF-F2A2-4BE7-8AF1-936FC87030F0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TranslationPlugins", "TranslationPlugins\TranslationPlugins.csproj", "{8C242D42-9714-440F-884D-F64F09E78C7B}"
+EndProject
Global
GlobalSection(TestCaseManagementSettings) = postSolution
CategoryFile = BCT.vsmdi
@@ -247,6 +249,18 @@ Global
{B114E5FF-F2A2-4BE7-8AF1-936FC87030F0}.NightlyRelease|Any CPU.Build.0 = Release|Any CPU
{B114E5FF-F2A2-4BE7-8AF1-936FC87030F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B114E5FF-F2A2-4BE7-8AF1-936FC87030F0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.CompilerOnly|Any CPU.ActiveCfg = Release|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.CompilerOnly|Any CPU.Build.0 = Release|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.FastpathSim|Any CPU.ActiveCfg = Release|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.FastpathSim|Any CPU.Build.0 = Release|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.NightlyDebug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.NightlyDebug|Any CPU.Build.0 = Debug|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.NightlyRelease|Any CPU.ActiveCfg = Release|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.NightlyRelease|Any CPU.Build.0 = Release|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8C242D42-9714-440F-884D-F64F09E78C7B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/BCT/BytecodeTranslator/BytecodeTranslator.csproj b/BCT/BytecodeTranslator/BytecodeTranslator.csproj
index e4575480..e9b8be83 100644
--- a/BCT/BytecodeTranslator/BytecodeTranslator.csproj
+++ b/BCT/BytecodeTranslator/BytecodeTranslator.csproj
@@ -125,6 +125,10 @@
<Compile Include="Heap.cs" />
<Compile Include="HeapFactory.cs" />
<Compile Include="MetadataTraverser.cs" />
+ <Compile Include="Phone\PhoneCodeHelper.cs" />
+ <Compile Include="Phone\PhoneInitializationTraverser.cs" />
+ <Compile Include="Phone\PhoneNavigationTraverser.cs" />
+ <Compile Include="Phone\PhoneURIDeclarationsTraverser.cs" />
<Compile Include="Prelude.cs" />
<Compile Include="ExpressionTraverser.cs" />
<Compile Include="Sink.cs" />
@@ -179,6 +183,10 @@
<Project>{319E150C-8F33-49E7-81CA-30F02F9BA90A}</Project>
<Name>MutableCodeModel</Name>
</ProjectReference>
+ <ProjectReference Include="..\TranslationPlugins\TranslationPlugins.csproj">
+ <Project>{8C242D42-9714-440F-884D-F64F09E78C7B}</Project>
+ <Name>TranslationPlugins</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
diff --git a/BCT/BytecodeTranslator/ExpressionTraverser.cs b/BCT/BytecodeTranslator/ExpressionTraverser.cs
index b53eccef..7e7de866 100644
--- a/BCT/BytecodeTranslator/ExpressionTraverser.cs
+++ b/BCT/BytecodeTranslator/ExpressionTraverser.cs
@@ -1294,7 +1294,10 @@ namespace BytecodeTranslator
base.Visit(checkIfInstance.Operand);
var exp = TranslatedExpressions.Pop();
var dynTypeOfOperand = this.sink.Heap.DynamicType(exp);
- TranslatedExpressions.Push(Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, dynTypeOfOperand, e));
+ var subtype = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Subtype, dynTypeOfOperand, e);
+ var notnull = Bpl.Expr.Neq(exp, Bpl.Expr.Ident(this.sink.Heap.NullRef));
+ var and = Bpl.Expr.And(notnull, subtype);
+ TranslatedExpressions.Push(and);
return;
}
diff --git a/BCT/BytecodeTranslator/HeapFactory.cs b/BCT/BytecodeTranslator/HeapFactory.cs
index 579ce648..fa46fe34 100644
--- a/BCT/BytecodeTranslator/HeapFactory.cs
+++ b/BCT/BytecodeTranslator/HeapFactory.cs
@@ -34,7 +34,7 @@ namespace BytecodeTranslator {
/// on its type based on the heap representation. I.e., the value of this
/// variable represents the value of the expression "typeof(type)".
/// </summary>
- Bpl.Variable CreateTypeVariable(ITypeReference type);
+ Bpl.Variable CreateTypeVariable(ITypeReference type, List<Bpl.ConstantParent> parents);
Bpl.Variable CreateEventVariable(IEventDefinition e);
@@ -230,13 +230,13 @@ namespace BytecodeTranslator {
/// on its type based on the heap representation. I.e., the value of this
/// variable represents the value of the expression "typeof(type)".
/// </summary>
- public Bpl.Variable CreateTypeVariable(ITypeReference type)
+ public Bpl.Variable CreateTypeVariable(ITypeReference type, List<Bpl.ConstantParent> parents)
{
string typename = TypeHelper.GetTypeName(type);
typename = TranslationHelper.TurnStringIntoValidIdentifier(typename);
Bpl.IToken tok = type.Token();
Bpl.TypedIdent tident = new Bpl.TypedIdent(tok, typename, this.TypeType);
- Bpl.Constant v = new Bpl.Constant(tok, tident, true);
+ Bpl.Constant v = new Bpl.Constant(tok, tident, true /*unique*/, parents, false, null);
return v;
}
diff --git a/BCT/BytecodeTranslator/MetadataTraverser.cs b/BCT/BytecodeTranslator/MetadataTraverser.cs
index c187444f..d4a125e1 100644
--- a/BCT/BytecodeTranslator/MetadataTraverser.cs
+++ b/BCT/BytecodeTranslator/MetadataTraverser.cs
@@ -343,7 +343,7 @@ namespace BytecodeTranslator {
}
decl.AddAttribute(attrName, args);
}
- } catch (InvalidCastException e) {
+ } catch (InvalidCastException) {
Console.WriteLine("Warning: Cannot translate custom attributes for method\n '{0}':",
MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
Console.WriteLine(" >>Skipping attributes, continuing with method translation");
@@ -355,9 +355,6 @@ namespace BytecodeTranslator {
if (helperTypes != null) {
this.privateTypes.AddRange(helperTypes);
}
- //method.Body.Dispatch(stmtTraverser);
- stmtTraverser.StmtBuilder.Add(new Bpl.ReturnCmd(Bpl.Token.NoToken));
- stmtTraverser.GenerateDispatchContinuation();
#endregion
#region Create Local Vars For Implementation
@@ -370,7 +367,6 @@ namespace BytecodeTranslator {
vars.Add(v);
}
vars.Add(procInfo.LocalExcVariable);
- vars.Add(procInfo.FinallyStackVariable);
vars.Add(procInfo.LabelVariable);
Bpl.VariableSeq vseq = new Bpl.VariableSeq(vars.ToArray());
#endregion
diff --git a/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs b/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs
new file mode 100644
index 00000000..74ad2140
--- /dev/null
+++ b/BCT/BytecodeTranslator/Phone/PhoneCodeHelper.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Cci;
+
+namespace BytecodeTranslator.Phone {
+ public enum StaticURIMode {
+ NOT_STATIC, STATIC_URI_CREATION_ONSITE, STATIC_URI_ROOT_CREATION_ONSITE,
+ }
+
+ public static class PhoneCodeHelper {
+ // TODO ensure this name is unique in the program code, although it is esoteric enough
+ private const string IL_BOOGIE_VAR_PREFIX = "@__BOOGIE_";
+ public const string IL_CURRENT_NAVIGATION_URI_VARIABLE = IL_BOOGIE_VAR_PREFIX + "CurrentNavigationURI__";
+
+ public static bool isCreateObjectInstance(this IExpression expr) {
+ ICreateObjectInstance createObjExpr = expr as ICreateObjectInstance;
+ return (createObjExpr != null);
+ }
+
+ public static bool isClass(this ITypeReference typeRef, ITypeReference targetTypeRef) {
+ while (typeRef != null) {
+ if (typeRef.ResolvedType.Equals(targetTypeRef.ResolvedType))
+ return true;
+
+ typeRef = typeRef.ResolvedType.BaseClasses.FirstOrDefault();
+ }
+
+ return false;
+ }
+
+ public static bool isStringClass(this ITypeReference typeRef, MetadataReaderHost host) {
+ ITypeReference targetType = host.PlatformType.SystemString;
+ return typeRef.isClass(targetType);
+ }
+
+ public static bool isURIClass (this ITypeReference typeRef, MetadataReaderHost host) {
+ Microsoft.Cci.Immutable.PlatformType platformType = host.PlatformType as Microsoft.Cci.Immutable.PlatformType;
+ if (platformType == null)
+ return false;
+
+ IAssemblyReference coreRef = platformType.CoreAssemblyRef;
+ AssemblyIdentity systemAssemblyId = new AssemblyIdentity(host.NameTable.GetNameFor("System"), "", coreRef.Version, coreRef.PublicKeyToken, "");
+ IAssemblyReference systemAssembly = host.FindAssembly(systemAssemblyId);
+
+ ITypeReference uriTypeRef= platformType.CreateReference(systemAssembly, "System", "Uri");
+ return typeRef.isClass(uriTypeRef);
+ }
+
+
+ public static bool isPhoneApplicationClass(this ITypeReference typeRef, MetadataReaderHost host) {
+ Microsoft.Cci.Immutable.PlatformType platform = host.PlatformType as Microsoft.Cci.Immutable.PlatformType;
+ IAssemblyReference coreAssemblyRef = platform.CoreAssemblyRef;
+ AssemblyIdentity MSPhoneSystemWindowsAssemblyId =
+ new AssemblyIdentity(host.NameTable.GetNameFor("System.Windows"), coreAssemblyRef.Culture, coreAssemblyRef.Version,
+ coreAssemblyRef.PublicKeyToken, "");
+
+ IAssemblyReference systemAssembly = host.FindAssembly(MSPhoneSystemWindowsAssemblyId);
+ ITypeReference applicationClass = platform.CreateReference(systemAssembly, "System", "Windows", "Application");
+
+ return typeRef.isClass(applicationClass);
+ }
+
+ public static bool isPhoneApplicationPageClass(ITypeReference typeDefinition, MetadataReaderHost host) {
+ Microsoft.Cci.Immutable.PlatformType platform = host.PlatformType as Microsoft.Cci.Immutable.PlatformType;
+ AssemblyIdentity MSPhoneAssemblyId =
+ new AssemblyIdentity(host.NameTable.GetNameFor("Microsoft.Phone"), "", new Version("7.0.0.0"),
+ new byte[] { 0x24, 0xEE, 0xC0, 0xD8, 0xC8, 0x6C, 0xDA, 0x1E }, "");
+
+ IAssemblyReference phoneAssembly = host.FindAssembly(MSPhoneAssemblyId);
+ ITypeReference phoneApplicationPageTypeRef = platform.CreateReference(phoneAssembly, "Microsoft", "Phone", "Controls", "PhoneApplicationPage");
+
+ ITypeReference baseClass = typeDefinition.ResolvedType.BaseClasses.FirstOrDefault();
+ while (baseClass != null) {
+ if (baseClass.ResolvedType.Equals(phoneApplicationPageTypeRef.ResolvedType)) {
+ return true;
+ }
+ baseClass = baseClass.ResolvedType.BaseClasses.FirstOrDefault();
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// checks whether a static URI root (a definite page base) can be extracted from the expression
+ /// </summary>
+ /// <param name="expr"></param>
+ /// <returns></returns>
+ public static bool IsStaticURIRootExtractable(this IExpression expr, out string uri) {
+ // Pre expr.type == string
+ IMethodCall stringConcatExpr = expr as IMethodCall;
+ uri = null;
+ if (stringConcatExpr == null)
+ return false;
+
+ if (stringConcatExpr.MethodToCall.Name.Value != "Concat")
+ return false;
+
+ IList<string> constantStrings = new List<string>();
+
+ // TODO this misses so many static strings, but let's start with this for now
+ IExpression leftOp= stringConcatExpr.Arguments.FirstOrDefault();
+ while (leftOp != null && leftOp is ICompileTimeConstant) {
+ ICompileTimeConstant strConst= leftOp as ICompileTimeConstant;
+ constantStrings.Add(strConst.Value as string);
+ if (stringConcatExpr.Arguments.ToList()[1] is IMethodCall) {
+ stringConcatExpr = stringConcatExpr.Arguments.ToList()[1] as IMethodCall;
+ leftOp = stringConcatExpr.Arguments.FirstOrDefault();
+ } else if (stringConcatExpr.Arguments.ToList()[1] is ICompileTimeConstant) {
+ constantStrings.Add((stringConcatExpr.Arguments.ToList()[1] as ICompileTimeConstant).Value as string);
+ break;
+ } else {
+ break;
+ }
+ }
+
+ uri= constantStrings.Aggregate((aggr, elem) => aggr + elem);
+ return Uri.IsWellFormedUriString(uri, UriKind.RelativeOrAbsolute);
+ }
+
+ /// <summary>
+ /// uri is a valid URI but possibly partial (incomplete ?arg= values) and overspecified (complete ?arg=values)
+ /// This method returns a base URI
+ /// </summary>
+ /// <param name="uri"></param>
+ /// <returns></returns>
+ public static string getURIBase(string uri) {
+ // I need to build an absolute URI just to call getComponents() ...
+ Uri mockBaseUri = new Uri("mock://mock/", UriKind.RelativeOrAbsolute);
+ Uri realUri = new Uri(mockBaseUri, uri);
+
+ string str= realUri.GetComponents(UriComponents.Path|UriComponents.StrongAuthority|UriComponents.Scheme, UriFormat.UriEscaped);
+ Uri mockStrippedUri = new Uri(str);
+ return mockBaseUri.MakeRelativeUri(mockStrippedUri).ToString();
+ }
+ }
+}
diff --git a/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs
new file mode 100644
index 00000000..fd24ff65
--- /dev/null
+++ b/BCT/BytecodeTranslator/Phone/PhoneInitializationTraverser.cs
@@ -0,0 +1,319 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All Rights Reserved.
+//
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Microsoft.Cci;
+using Microsoft.Cci.MetadataReader;
+using Microsoft.Cci.MutableCodeModel;
+using Microsoft.Cci.Contracts;
+
+using Bpl = Microsoft.Boogie;
+using System.Diagnostics.Contracts;
+using TranslationPlugins;
+
+
+namespace BytecodeTranslator.Phone {
+
+ /// <summary>
+ /// Traverse code looking for phone specific points of interest, possibly injecting necessary code in-between
+ /// </summary>
+ public class PhoneInitializationCodeTraverser : BaseCodeTraverser {
+ private readonly IMethodDefinition methodBeingTraversed;
+ private static bool initializationFound= false;
+ private PhoneControlsPlugin phonePlugin;
+ private MetadataReaderHost host;
+
+ private IAssemblyReference coreAssemblyRef;
+ private IAssemblyReference phoneAssembly;
+ private IAssemblyReference phoneSystemWindowsAssembly;
+ private INamespaceTypeReference checkBoxType;
+ private INamespaceTypeReference radioButtonType;
+ private INamespaceTypeReference buttonType;
+ private INamespaceTypeReference buttonBaseType;
+ private INamespaceTypeReference toggleButtonType;
+ private INamespaceTypeReference controlType;
+ private INamespaceTypeReference uiElementType;
+
+ private CompileTimeConstant trueConstant;
+ private CompileTimeConstant falseConstant;
+
+ private IMethodReference isEnabledSetter;
+ private IMethodReference isEnabledGetter;
+ private IMethodReference isCheckedSetter;
+ private IMethodReference isCheckedGetter;
+ private IMethodReference visibilitySetter;
+ private IMethodReference visibilityGetter;
+ private IMethodReference clickHandlerAdder;
+ private IMethodReference clickHandlerRemover;
+ private IMethodReference checkedHandlerAdder;
+ private IMethodReference checkedHandlerRemover;
+ private IMethodReference uncheckedHandlerAdder;
+ private IMethodReference uncheckedHandlerRemover;
+
+ private ITypeReference getTypeForClassname(String classname) {
+ if (classname == "Button") {
+ return buttonType;
+ } else if (classname == "RadioButton") {
+ return radioButtonType;
+ } else if (classname == "CheckBox") {
+ return checkBoxType;
+ } else {
+ // TODO avoid throwing exceptions, just log
+ throw new NotImplementedException("Type " + classname + " is not being monitored yet for phone controls");
+ }
+ }
+
+ public PhoneInitializationCodeTraverser(MetadataReaderHost host, IMethodDefinition traversedMethod, PhoneControlsPlugin phonePlugin) : base() {
+ this.methodBeingTraversed = traversedMethod;
+ this.phonePlugin = phonePlugin;
+ this.host = host;
+ InitializeTraverser();
+ }
+
+ private void InitializeTraverser() {
+ Microsoft.Cci.Immutable.PlatformType platform = host.PlatformType as Microsoft.Cci.Immutable.PlatformType;
+ coreAssemblyRef = platform.CoreAssemblyRef;
+
+ // TODO obtain version, culture and signature data dynamically
+ AssemblyIdentity MSPhoneAssemblyId =
+ new AssemblyIdentity(host.NameTable.GetNameFor("Microsoft.Phone"), "", new Version("7.0.0.0"),
+ new byte[] { 0x24, 0xEE, 0xC0, 0xD8, 0xC8, 0x6C, 0xDA, 0x1E }, "");
+ AssemblyIdentity MSPhoneSystemWindowsAssemblyId =
+ new AssemblyIdentity(host.NameTable.GetNameFor("System.Windows"), coreAssemblyRef.Culture, coreAssemblyRef.Version,
+ coreAssemblyRef.PublicKeyToken, "");
+
+ phoneAssembly = host.FindAssembly(MSPhoneAssemblyId);
+ phoneSystemWindowsAssembly = host.FindAssembly(MSPhoneSystemWindowsAssemblyId);
+
+ // TODO determine the needed types dynamically
+ checkBoxType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "CheckBox");
+ radioButtonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "RadioButton");
+ buttonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Button");
+ buttonBaseType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Primitives", "ButtonBase");
+ toggleButtonType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Primitives", "ToggleButton");
+ controlType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Controls", "Control");
+ uiElementType = platform.CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "UIElement");
+
+ trueConstant = new CompileTimeConstant() {
+ Type = platform.SystemBoolean,
+ Value = true
+ };
+ falseConstant = new CompileTimeConstant() {
+ Type = platform.SystemBoolean,
+ Value = false
+ };
+
+ IEnumerable<IPropertyDefinition> controlProperties = controlType.ResolvedType.Properties;
+ IEnumerable<IPropertyDefinition> toggleButtonProperties = toggleButtonType.ResolvedType.Properties;
+ IEnumerable<IPropertyDefinition> uiElementProperties = uiElementType.ResolvedType.Properties;
+
+ IPropertyDefinition prop = controlProperties.Single(p => p.Name.Value == "IsEnabled");
+ isEnabledSetter = prop.Setter;
+ isEnabledGetter = prop.Getter;
+ prop = toggleButtonProperties.Single(p => p.Name.Value == "IsChecked");
+ isCheckedSetter = prop.Setter;
+ isCheckedGetter = prop.Getter;
+ prop = uiElementProperties.Single(p => p.Name.Value == "Visibility");
+ visibilitySetter = prop.Setter;
+ visibilityGetter = prop.Getter;
+
+ IEnumerable<IEventDefinition> buttonBaseEvents = buttonBaseType.ResolvedType.Events;
+ IEnumerable<IEventDefinition> toggleButtonEvents = toggleButtonType.ResolvedType.Events;
+ IEventDefinition evt = buttonBaseEvents.Single(e => e.Name.Value == "Click");
+ clickHandlerAdder = evt.Adder;
+ clickHandlerRemover = evt.Remover;
+ evt = toggleButtonEvents.Single(e => e.Name.Value == "Checked");
+ checkedHandlerAdder = evt.Adder;
+ checkedHandlerRemover = evt.Remover;
+ evt = toggleButtonEvents.Single(e => e.Name.Value == "Unchecked");
+ uncheckedHandlerAdder = evt.Adder;
+ uncheckedHandlerRemover = evt.Remover;
+ }
+
+ public void injectPhoneControlsCode(BlockStatement block) {
+ this.Visit(block);
+ }
+
+ private void injectPhoneInitializationCode(BlockStatement block, Statement statementAfter) {
+ // TODO check page name against container name
+ IEnumerable<ControlInfoStructure> controls= phonePlugin.getControlsForPage(methodBeingTraversed.Container.ToString());
+ IEnumerable<IStatement> injectedStatements = new List<IStatement>();
+ foreach (ControlInfoStructure controlInfo in controls) {
+ injectedStatements = injectedStatements.Concat(getCodeForSettingEnabledness(controlInfo));
+ injectedStatements = injectedStatements.Concat(getCodeForSettingCheckedState(controlInfo));
+ injectedStatements = injectedStatements.Concat(getCodeForSettingVisibility(controlInfo));
+ injectedStatements = injectedStatements.Concat(getCodeForSettingEventHandlers(controlInfo, "Click"));
+ injectedStatements = injectedStatements.Concat(getCodeForSettingEventHandlers(controlInfo, "Checked"));
+ injectedStatements = injectedStatements.Concat(getCodeForSettingEventHandlers(controlInfo, "Unchecked"));
+ }
+
+ int stmtPos= block.Statements.IndexOf(statementAfter);
+ block.Statements.InsertRange(stmtPos+1, injectedStatements);
+ }
+
+ private BoundExpression makeBoundControlFromControlInfo(ControlInfoStructure controlInfo) {
+ return new BoundExpression() {
+ Definition = new FieldDefinition() {
+ ContainingTypeDefinition = methodBeingTraversed.Container,
+ Name = host.NameTable.GetNameFor(controlInfo.Name),
+ Type = getTypeForClassname(controlInfo.ClassName),
+ IsStatic = false,
+ },
+ Instance = new ThisReference() { Type = methodBeingTraversed.Container },
+ };
+ }
+
+ private IEnumerable<IStatement> getCodeForSettingVisibility(ControlInfoStructure controlInfo) {
+ // TODO I do not want to import System.Windows into this project...and using the underlying uint won't work
+ /*
+ IList<IStatement> code = new List<IStatement>();
+ BoundExpression boundControl = makeBoundControlFromControlInfo(controlInfo);
+ MethodCall setVisibilityCall= new MethodCall() {
+ IsStaticCall = false,
+ IsVirtualCall = true,
+ IsTailCall = false,
+ Type = ((Microsoft.Cci.Immutable.PlatformType) host.PlatformType).SystemVoid,
+ MethodToCall = visibilitySetter,
+ ThisArgument = boundControl,
+ };
+
+ ITypeReference visibilityType= ((Microsoft.Cci.Immutable.PlatformType) host.PlatformType).CreateReference(phoneSystemWindowsAssembly, "System", "Windows", "Visibility");
+
+ switch (controlInfo.Visible) {
+ case Visibility.Visible:
+ setVisibilityCall.Arguments.Add(new CompileTimeConstant() {
+ Type = visibilityType,
+ Value = 0,
+ } ); // Visible
+ break;
+ case Visibility.Collapsed:
+ setVisibilityCall.Arguments.Add(new CompileTimeConstant() {
+ Type = visibilityType,
+ Value = 1,
+ } ); // Collapsed
+ break;
+ default:
+ throw new ArgumentException("Invalid visibility value for control " + controlInfo.Name + ": " + controlInfo.Visible);
+ }
+
+ ExpressionStatement callStmt = new ExpressionStatement() {
+ Expression = setVisibilityCall,
+ };
+ code.Add(callStmt);
+ return code;
+ * */
+ return new List<IStatement>();
+ }
+
+ private IEnumerable<IStatement> getCodeForSettingEnabledness(ControlInfoStructure controlInfo) {
+ IList<IStatement> code = new List<IStatement>();
+ BoundExpression boundControl = makeBoundControlFromControlInfo(controlInfo);
+ MethodCall setEnablednessCall = new MethodCall() {
+ IsStaticCall = false,
+ IsVirtualCall = true,
+ IsTailCall = false,
+ Type = ((Microsoft.Cci.Immutable.PlatformType) host.PlatformType).SystemVoid,
+ MethodToCall = isEnabledSetter,
+ ThisArgument = boundControl,
+ };
+
+ setEnablednessCall.Arguments.Add(controlInfo.IsEnabled ? trueConstant : falseConstant);
+ ExpressionStatement callStmt = new ExpressionStatement() {
+ Expression = setEnablednessCall,
+ };
+ code.Add(callStmt);
+ return code;
+ }
+
+ private IEnumerable<IStatement> getCodeForSettingCheckedState(ControlInfoStructure controlInfo) {
+ // TODO not implemented yet
+ return new List<IStatement>();
+ }
+
+ // TODO should stop propagating the string event name
+ private IEnumerable<IStatement> getCodeForSettingEventHandlers(ControlInfoStructure controlInfo, string eventName) {
+ // TODO not implemented yet
+ return new List<IStatement>();
+ }
+
+ public override void Visit(IBlockStatement block) {
+ foreach (IStatement statement in block.Statements) {
+ this.Visit(statement);
+ if (initializationFound) {
+ injectPhoneInitializationCode(block as BlockStatement, statement as Statement);
+ initializationFound = false;
+ break;
+ }
+ }
+ }
+
+ public override void Visit(IMethodCall methodCall) {
+ if (methodCall.IsStaticCall ||
+ !methodCall.MethodToCall.ContainingType.ResolvedType.Equals(methodBeingTraversed.Container) ||
+ methodCall.MethodToCall.Name.Value != "InitializeComponent" ||
+ methodCall.Arguments.Any())
+ return;
+
+ initializationFound= true;
+ }
+ }
+
+ /// <summary>
+ /// Traverse metadata looking only for PhoneApplicationPage's constructors
+ /// </summary>
+ public class PhoneInitializationMetadataTraverser : BaseMetadataTraverser {
+ private PhoneControlsPlugin phoneControlsInfo;
+ private MetadataReaderHost host;
+
+ public PhoneInitializationMetadataTraverser(PhoneControlsPlugin phonePlugin, MetadataReaderHost host)
+ : base() {
+ this.phoneControlsInfo = phonePlugin;
+ this.host = host;
+ }
+
+ public override void Visit(IModule module) {
+ base.Visit(module);
+ }
+
+ public override void Visit(IAssembly assembly) {
+ base.Visit(assembly);
+ }
+
+ /// <summary>
+ /// Check if the type being defined is a PhoneApplicationPage, uninteresting otherwise
+ /// </summary>
+ ///
+ public override void Visit(ITypeDefinition typeDefinition) {
+ if (typeDefinition.IsClass && PhoneCodeHelper.isPhoneApplicationPageClass(typeDefinition, host)) {
+ base.Visit(typeDefinition);
+ }
+ }
+
+ /// <summary>
+ /// Check if it is traversing a constructor. If so, place necessary code after InitializeComponent() call
+ /// </summary>
+ public override void Visit(IMethodDefinition method) {
+ if (!method.IsConstructor)
+ return;
+
+ PhoneInitializationCodeTraverser codeTraverser = new PhoneInitializationCodeTraverser(host, method, phoneControlsInfo);
+ var methodBody = method.Body as SourceMethodBody;
+ if (methodBody == null)
+ return;
+ var block = methodBody.Block as BlockStatement;
+ codeTraverser.injectPhoneControlsCode(block);
+ }
+
+ public void InjectPhoneCodeAssemblies(IEnumerable<IUnit> assemblies) {
+ foreach (var a in assemblies) {
+ a.Dispatch(this);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs
new file mode 100644
index 00000000..b702e78b
--- /dev/null
+++ b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs
@@ -0,0 +1,285 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Cci;
+using Microsoft.Cci.MutableCodeModel;
+using TranslationPlugins;
+
+namespace BytecodeTranslator.Phone {
+ public class PhoneNavigationCodeTraverser : BaseCodeTraverser {
+ private MetadataReaderHost host;
+ private ITypeReference navigationSvcType;
+ private ITypeReference typeTraversed;
+ private PhoneControlsPlugin phonePlugin;
+
+ private static readonly string[] NAV_CALLS = { "GoBack", "GoForward", "Navigate", "StopLoading" };
+
+ public PhoneNavigationCodeTraverser(PhoneControlsPlugin plugin, MetadataReaderHost host, ITypeReference typeTraversed) : base() {
+ this.host = host;
+ this.typeTraversed = typeTraversed;
+ this.phonePlugin = plugin;
+ Microsoft.Cci.Immutable.PlatformType platform = host.PlatformType as Microsoft.Cci.Immutable.PlatformType;
+
+ // TODO obtain version, culture and signature data dynamically
+ AssemblyIdentity MSPhoneAssemblyId =
+ new AssemblyIdentity(host.NameTable.GetNameFor("Microsoft.Phone"), "", new Version("7.0.0.0"),
+ new byte[] { 0x24, 0xEE, 0xC0, 0xD8, 0xC8, 0x6C, 0xDA, 0x1E }, "");
+
+ IAssembly phoneAssembly = host.FindAssembly(MSPhoneAssemblyId);
+
+ // TODO determine the needed types dynamically
+ navigationSvcType = platform.CreateReference(phoneAssembly, "System", "Windows", "Navigation", "NavigationService");
+ }
+
+ public override void Visit(IMethodDefinition method) {
+ if (method.IsConstructor && PhoneCodeHelper.isPhoneApplicationClass(typeTraversed, host)) {
+ // TODO initialize current navigation URI to mainpage, using a placeholder for now.
+ // TODO BUG doing this is generating a fresh variable definition somewhere that the BCT then translates into two different (identical) declarations
+ string mainPageUri = phonePlugin.getMainPageXAML();
+ SourceMethodBody sourceBody = method.Body as SourceMethodBody;
+ if (sourceBody != null) {
+ BlockStatement bodyBlock = sourceBody.Block as BlockStatement;
+ if (bodyBlock != null) {
+ Assignment uriInitAssign = new Assignment() {
+ Source = new CompileTimeConstant() {
+ Type = host.PlatformType.SystemString,
+ Value = mainPageUri,
+ },
+ Type = host.PlatformType.SystemString,
+ Target = new TargetExpression() {
+ Type = host.PlatformType.SystemString,
+ Definition = new FieldReference() {
+ ContainingType= typeTraversed,
+ IsStatic=true,
+ Type=host.PlatformType.SystemString,
+ Name=host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
+ },
+ },
+ };
+ Statement uriInitStmt= new ExpressionStatement() {
+ Expression= uriInitAssign,
+ };
+ bodyBlock.Statements.Insert(0, uriInitStmt);
+ }
+ }
+ }
+ base.Visit(method);
+ }
+
+
+ private bool navCallFound=false;
+ private StaticURIMode currentStaticMode= StaticURIMode.NOT_STATIC;
+ private string unpurifiedFoundURI="";
+
+ public override void Visit(IBlockStatement block) {
+ IList<Tuple<IStatement,StaticURIMode,string>> navStmts = new List<Tuple<IStatement,StaticURIMode,string>>();
+ foreach (IStatement statement in block.Statements) {
+ navCallFound = false;
+ this.Visit(statement);
+ if (navCallFound) {
+ navStmts.Add(new Tuple<IStatement, StaticURIMode, string>(statement, currentStaticMode, unpurifiedFoundURI));
+ }
+ }
+
+ injectNavigationUpdateCode(block, navStmts);
+ }
+
+ public override void Visit(IMethodCall methodCall) {
+ // check whether it is a NavigationService call
+ IMethodReference methodToCall= methodCall.MethodToCall;
+ ITypeReference callType= methodToCall.ContainingType;
+ if (!callType.ResolvedType.Equals(navigationSvcType.ResolvedType))
+ return;
+
+ string methodToCallName= methodToCall.Name.Value;
+ if (!NAV_CALLS.Contains(methodToCallName))
+ return;
+
+ // TODO check what to do with these
+ if (methodToCallName == "GoForward" || methodToCallName == "StopLoading") {
+ // TODO forward navigation is not supported by the phone
+ // TODO StopLoading is very async, I don't think we may verify this behaviour
+ // TODO possibly log
+ return;
+ } else {
+ bool isStatic=false;
+ currentStaticMode = StaticURIMode.NOT_STATIC;
+
+ if (methodToCallName == "GoBack")
+ isStatic= true;
+ else { // Navigate()
+ // check for different static patterns that we may be able to verify
+ IExpression uriArg= methodCall.Arguments.First();
+ if (isArgumentURILocallyCreatedStatic(uriArg, out unpurifiedFoundURI)) {
+ isStatic = true;
+ currentStaticMode = StaticURIMode.STATIC_URI_CREATION_ONSITE;
+ } else if (isArgumentURILocallyCreatedStaticRoot(uriArg, out unpurifiedFoundURI)) {
+ isStatic = true;
+ currentStaticMode = StaticURIMode.STATIC_URI_ROOT_CREATION_ONSITE;
+ } else {
+ // get reason
+ //ICreateObjectInstance creationSite = methodCall.Arguments.First() as ICreateObjectInstance;
+ //if (creationSite == null)
+ // notStaticReason = "URI not created at call site";
+ //else
+ // notStaticReason = "URI not initialized as a static string";
+ }
+ }
+
+ if (isStatic)
+ navCallFound = true;
+
+ //Console.Write("Page navigation event found. Target is static? " + (isStatic ? "YES" : "NO"));
+ //if (!isStatic) {
+ // Console.WriteLine(" -- Reason: " + notStaticReason);
+ //} else {
+ // Console.WriteLine("");
+ //}
+ }
+ }
+
+ /// <summary>
+ /// checks if argument is locally created URI with static URI target
+ /// </summary>
+ /// <param name="arg"></param>
+ /// <returns></returns>
+ private bool isArgumentURILocallyCreatedStatic(IExpression arg, out string uri) {
+ uri = null;
+ if (!arg.isCreateObjectInstance())
+ return false;
+
+ if (!arg.Type.isURIClass(host))
+ return false;
+
+ ICreateObjectInstance creationSite = arg as ICreateObjectInstance;
+ IExpression uriTargetArg= creationSite.Arguments.First();
+
+ if (!uriTargetArg.Type.isStringClass(host))
+ return false;
+
+ ICompileTimeConstant staticURITarget = uriTargetArg as ICompileTimeConstant;
+ if (staticURITarget == null)
+ return false;
+
+ uri= staticURITarget.Value as string;
+ return true;
+ }
+
+ /// <summary>
+ /// checks if argument is locally created URI where target has statically created URI root
+ /// </summary>
+ /// <param name="arg"></param>
+ /// <returns></returns>
+ private bool isArgumentURILocallyCreatedStaticRoot(IExpression arg, out string uri) {
+ // Pre: !isArgumentURILocallyCreatedStatic
+ uri = null;
+ if (!arg.isCreateObjectInstance())
+ return false;
+
+ if (!arg.Type.isURIClass(host))
+ return false;
+
+ ICreateObjectInstance creationSite = arg as ICreateObjectInstance;
+ IExpression uriTargetArg = creationSite.Arguments.First();
+
+ if (!uriTargetArg.Type.isStringClass(host))
+ return false;
+
+ if (!uriTargetArg.IsStaticURIRootExtractable(out uri))
+ return false;
+
+ return true;
+ }
+
+ private void injectNavigationUpdateCode(IBlockStatement block, IEnumerable<Tuple<IStatement,StaticURIMode, string>> stmts) {
+ // TODO Here there is the STRONG assumption that a given method will only navigate at most once per method call
+ // TODO (or at most will re-navigate to the same page). Quick "page flipping" on the same method
+ // TODO would not be captured correctly
+ foreach (Tuple<IStatement, StaticURIMode, string> entry in stmts) {
+ int ndx= block.Statements.ToList().IndexOf(entry.Item1, 0);
+ if (ndx == -1) {
+ // can't be
+ throw new IndexOutOfRangeException("Statement must exist in original block");
+ }
+
+ Assignment currentURIAssign = new Assignment() {
+ Source = new CompileTimeConstant() {
+ Type = host.PlatformType.SystemString,
+ Value = PhoneCodeHelper.getURIBase(entry.Item3),
+ },
+ Type = host.PlatformType.SystemString,
+ Target = new TargetExpression() {
+ Type = host.PlatformType.SystemString,
+ Definition = new FieldReference() {
+ ContainingType = typeTraversed,
+ IsStatic = true,
+ Type = host.PlatformType.SystemString,
+ Name = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
+ },
+ },
+ };
+ Statement uriInitStmt = new ExpressionStatement() {
+ Expression = currentURIAssign,
+ };
+ block.Statements.ToList().Insert(ndx+1, uriInitStmt);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Traverse metadata looking only for PhoneApplicationPage's constructors
+ /// </summary>
+ public class PhoneNavigationMetadataTraverser : BaseMetadataTraverser {
+ private MetadataReaderHost host;
+ private ITypeDefinition typeBeingTraversed;
+ private PhoneControlsPlugin phonePlugin;
+
+ public PhoneNavigationMetadataTraverser(PhoneControlsPlugin plugin, MetadataReaderHost host)
+ : base() {
+ this.host = host;
+ this.phonePlugin = plugin;
+ }
+
+ public override void Visit(IModule module) {
+ base.Visit(module);
+ }
+
+ public override void Visit(IAssembly assembly) {
+ base.Visit(assembly);
+ }
+
+ // TODO can we avoid visiting every type? Are there only a few, identifiable, types that may perform navigation?
+ public override void Visit(ITypeDefinition typeDefinition) {
+ typeBeingTraversed = typeDefinition;
+ if (typeDefinition.isPhoneApplicationClass(host)) {
+ NamespaceTypeDefinition mutableTypeDef = typeDefinition as NamespaceTypeDefinition;
+ if (mutableTypeDef != null) {
+ FieldDefinition fieldDef = new FieldDefinition() {
+ ContainingTypeDefinition= mutableTypeDef,
+ InternFactory= host.InternFactory,
+ IsStatic= true,
+ Name= host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
+ Type= host.PlatformType.SystemString,
+ Visibility= TypeMemberVisibility.Public,
+ };
+ mutableTypeDef.Fields.Add(fieldDef);
+ }
+ }
+ base.Visit(typeDefinition);
+ }
+
+ // TODO same here. Are there specific methods (and ways to identfy those) that can perform navigation?
+ public override void Visit(IMethodDefinition method) {
+
+ PhoneNavigationCodeTraverser codeTraverser = new PhoneNavigationCodeTraverser(phonePlugin, host, typeBeingTraversed);
+ codeTraverser.Visit(method);
+ }
+
+ public void InjectPhoneCodeAssemblies(IEnumerable<IUnit> assemblies) {
+ foreach (var a in assemblies) {
+ a.Dispatch(this);
+ }
+ }
+ }
+}
diff --git a/BCT/BytecodeTranslator/Phone/PhoneURIDeclarationsTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneURIDeclarationsTraverser.cs
new file mode 100644
index 00000000..fa330439
--- /dev/null
+++ b/BCT/BytecodeTranslator/Phone/PhoneURIDeclarationsTraverser.cs
@@ -0,0 +1,9 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BytecodeTranslator.Phone {
+ class PhoneURIDeclarationsTraverser {
+ }
+}
diff --git a/BCT/BytecodeTranslator/Phone/stubs.bpl b/BCT/BytecodeTranslator/Phone/stubs.bpl
new file mode 100644
index 00000000..ae97e03f
--- /dev/null
+++ b/BCT/BytecodeTranslator/Phone/stubs.bpl
@@ -0,0 +1,41 @@
+function isControlEnabled(Ref) : bool;
+function isControlChecked(Ref) : bool;
+
+procedure System.String.op_Equality$System.String$System.String(a$in: Ref, b$in: Ref) returns ($result: bool);
+procedure System.String.op_Inequality$System.String$System.String(a$in: Ref, b$in: Ref) returns ($result: bool);
+
+implementation System.String.op_Equality$System.String$System.String(a$in: Ref, b$in: Ref) returns ($result: bool) {
+ $result := (a$in == b$in);
+}
+
+implementation System.String.op_Inequality$System.String$System.String(a$in: Ref, b$in: Ref) returns ($result: bool) {
+ $result := (a$in != b$in);
+}
+
+procedure System.Windows.Controls.Control.set_IsEnabled$System.Boolean($this: Ref, value$in: bool);
+implementation System.Windows.Controls.Control.set_IsEnabled$System.Boolean($this: Ref, value$in: bool) {
+ assume isControlEnabled($this) == value$in;
+}
+
+procedure System.Windows.Controls.Control.get_IsEnabled($this: Ref) returns ($result: Ref);
+implementation System.Windows.Controls.Control.get_IsEnabled($this: Ref) returns ($result: Ref) {
+ var enabledness: bool;
+ enabledness := isControlEnabled($this);
+ $result := Box2Ref(Bool2Box(enabledness));
+}
+
+procedure System.Windows.Controls.Primitives.ToggleButton.set_IsChecked$System.Nullable$System.Boolean$($this: Ref, value$in: Ref);
+implementation System.Windows.Controls.Primitives.ToggleButton.set_IsChecked$System.Nullable$System.Boolean$($this: Ref, value$in: Ref) {
+ var check: bool;
+
+ check := Box2Bool(Ref2Box(value$in));
+ assume isControlChecked($this) == check;
+}
+
+procedure System.Windows.Controls.Primitives.ToggleButton.get_IsChecked($this: Ref) returns ($result: Ref);
+implementation System.Windows.Controls.Primitives.ToggleButton.get_IsChecked($this: Ref) returns ($result: Ref) {
+ var isChecked: bool;
+ isChecked := isControlChecked($this);
+ $result := Box2Ref(Bool2Box(isChecked));
+}
+
diff --git a/BCT/BytecodeTranslator/Program.cs b/BCT/BytecodeTranslator/Program.cs
index cb0836f2..14d0a466 100644
--- a/BCT/BytecodeTranslator/Program.cs
+++ b/BCT/BytecodeTranslator/Program.cs
@@ -17,6 +17,8 @@ using Microsoft.Cci.MutableContracts;
using Bpl = Microsoft.Boogie;
using System.Diagnostics.Contracts;
using Microsoft.Cci.MutableCodeModel.Contracts;
+using TranslationPlugins;
+using BytecodeTranslator.Phone;
namespace BytecodeTranslator {
@@ -41,6 +43,9 @@ namespace BytecodeTranslator {
[OptionDescription("Stub assembly", ShortForm = "s")]
public List<string>/*?*/ stub = null;
+ [OptionDescription("Phone translation controls configuration")]
+ public string phoneControls = null;
+
}
public class BCT {
@@ -91,7 +96,7 @@ namespace BytecodeTranslator {
return 1;
}
- result = TranslateAssembly(assemblyNames, heap, options.libpaths, options.wholeProgram, options.stub);
+ result = TranslateAssembly(assemblyNames, heap, options.libpaths, options.wholeProgram, options.stub, options.phoneControls);
} catch (Exception e) { // swallow everything and just return an error code
Console.WriteLine("The byte-code translator failed: {0}", e.Message);
@@ -101,7 +106,7 @@ namespace BytecodeTranslator {
return result;
}
- public static int TranslateAssembly(List<string> assemblyNames, HeapFactory heapFactory, List<string>/*?*/ libPaths, bool wholeProgram, List<string>/*?*/ stubAssemblies) {
+ public static int TranslateAssembly(List<string> assemblyNames, HeapFactory heapFactory, List<string>/*?*/ libPaths, bool wholeProgram, List<string>/*?*/ stubAssemblies, string phoneControlsConfigFile) {
Contract.Requires(assemblyNames != null);
Contract.Requires(heapFactory != null);
@@ -171,15 +176,22 @@ namespace BytecodeTranslator {
var primaryModule = modules[0];
+ if (phoneControlsConfigFile != null && phoneControlsConfigFile != "") {
+ PhoneControlsPlugin phonePlugin = new PhoneControlsPlugin(phoneControlsConfigFile);
+ PhoneInitializationMetadataTraverser initTr = new PhoneInitializationMetadataTraverser(phonePlugin, host);
+ initTr.InjectPhoneCodeAssemblies(modules);
+ PhoneNavigationMetadataTraverser navTr = new PhoneNavigationMetadataTraverser(phonePlugin, host);
+ navTr.InjectPhoneCodeAssemblies(modules);
+ }
+
TraverserFactory traverserFactory;
if (wholeProgram)
traverserFactory = new WholeProgram();
else
traverserFactory = new CLRSemantics();
- var sink = new Sink(host, traverserFactory, heapFactory);
+ Sink sink= new Sink(host, traverserFactory, heapFactory);
TranslationHelper.tmpVarCounter = 0;
-
MetadataTraverser translator = traverserFactory.MakeMetadataTraverser(sink, contractExtractors, pdbReaders);
translator.TranslateAssemblies(modules);
diff --git a/BCT/BytecodeTranslator/Sink.cs b/BCT/BytecodeTranslator/Sink.cs
index 8629190d..97d3cea4 100644
--- a/BCT/BytecodeTranslator/Sink.cs
+++ b/BCT/BytecodeTranslator/Sink.cs
@@ -70,12 +70,6 @@ namespace BytecodeTranslator {
return info.LocalExcVariable;
}
}
- public Bpl.LocalVariable FinallyStackCounterVariable {
- get {
- ProcedureInfo info = FindOrCreateProcedure(this.methodBeingTranslated);
- return info.FinallyStackVariable;
- }
- }
public Bpl.LocalVariable LabelVariable {
get {
ProcedureInfo info = FindOrCreateProcedure(this.methodBeingTranslated);
@@ -348,7 +342,6 @@ namespace BytecodeTranslator {
private Bpl.Formal thisVariable;
private Bpl.Formal returnVariable;
private Bpl.LocalVariable localExcVariable;
- private Bpl.LocalVariable finallyStackVariable;
private Bpl.LocalVariable labelVariable;
private List<Bpl.Formal> typeParameters;
private List<Bpl.Formal> methodParameters;
@@ -359,7 +352,6 @@ namespace BytecodeTranslator {
this.returnVariable = null;
this.thisVariable = null;
this.localExcVariable = null;
- this.finallyStackVariable = null;
this.labelVariable = null;
this.typeParameters = null;
this.methodParameters = null;
@@ -383,14 +375,12 @@ namespace BytecodeTranslator {
Bpl.Formal returnVariable,
Bpl.Formal thisVariable,
Bpl.LocalVariable localExcVariable,
- Bpl.LocalVariable finallyStackVariable,
Bpl.LocalVariable labelVariable,
List<Bpl.Formal> typeParameters,
List<Bpl.Formal> methodParameters)
: this(decl, formalMap, returnVariable) {
this.thisVariable = thisVariable;
this.localExcVariable = localExcVariable;
- this.finallyStackVariable = finallyStackVariable;
this.labelVariable = labelVariable;
this.typeParameters = typeParameters;
this.methodParameters = methodParameters;
@@ -401,7 +391,6 @@ namespace BytecodeTranslator {
public Bpl.Formal ThisVariable { get { return thisVariable; } }
public Bpl.Formal ReturnVariable { get { return returnVariable; } }
public Bpl.LocalVariable LocalExcVariable { get { return localExcVariable; } }
- public Bpl.LocalVariable FinallyStackVariable { get { return finallyStackVariable; } }
public Bpl.LocalVariable LabelVariable { get { return labelVariable; } }
public Bpl.Formal TypeParameter(int index) { return typeParameters[index]; }
public Bpl.Formal MethodParameter(int index) { return methodParameters[index]; }
@@ -418,7 +407,6 @@ namespace BytecodeTranslator {
Bpl.Formal thisVariable = null;
Bpl.Formal retVariable = null;
Bpl.LocalVariable localExcVariable = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "$localExc", this.Heap.RefType));
- Bpl.LocalVariable finallyStackVariable = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "$finallyStackCounter", Bpl.Type.Int));
Bpl.LocalVariable labelVariable = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "$label", Bpl.Type.Int));
int in_count = 0;
@@ -533,7 +521,7 @@ namespace BytecodeTranslator {
} else {
this.TranslatedProgram.TopLevelDeclarations.Add(decl);
}
- procInfo = new ProcedureInfo(decl, formalMap, retVariable, thisVariable, localExcVariable, finallyStackVariable, labelVariable, typeParameters, methodParameters);
+ procInfo = new ProcedureInfo(decl, formalMap, retVariable, thisVariable, localExcVariable, labelVariable, typeParameters, methodParameters);
this.declaredMethods.Add(key, procInfo);
// Can't visit the method's contracts until the formalMap and procedure are added to the
@@ -692,6 +680,8 @@ namespace BytecodeTranslator {
// also, should it return true for properties and all of the other things the tools
// consider pure?
private bool IsPure(IMethodDefinition method) {
+ // TODO:
+ // This needs to wait until we get function bodies sorted out.
//bool isPropertyGetter = method.IsSpecialName && method.Name.Value.StartsWith("get_");
//if (isPropertyGetter) return true;
@@ -878,8 +868,16 @@ namespace BytecodeTranslator {
Bpl.Variable t;
var key = type.InternedKey;
if (!this.declaredTypeConstants.TryGetValue(key, out t)) {
- t = this.Heap.CreateTypeVariable(type);
+ List<ITypeReference> structuralParents;
+ var parents = GetParents(type.ResolvedType, out structuralParents);
+ t = this.Heap.CreateTypeVariable(type, parents);
this.declaredTypeConstants.Add(key, t);
+ foreach (var p in structuralParents) {
+ var p_prime = FindOrCreateType(p);
+ var e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Subtype, Bpl.Expr.Ident(t), p_prime);
+ var a = new Bpl.Axiom(Bpl.Token.NoToken, e);
+ //this.TranslatedProgram.TopLevelDeclarations.Add(a);
+ }
this.TranslatedProgram.TopLevelDeclarations.Add(t);
if (isExtern) {
var attrib = new Bpl.QKeyValue(Bpl.Token.NoToken, "extern", new List<object>(1), null);
@@ -889,6 +887,29 @@ namespace BytecodeTranslator {
return Bpl.Expr.Ident(t);
}
}
+
+ private List<Bpl.ConstantParent> GetParents(ITypeDefinition typeDefinition, out List<ITypeReference> structuralParents) {
+ var parents = new List<Bpl.ConstantParent>();
+ structuralParents = new List<ITypeReference>();
+ foreach (var p in typeDefinition.BaseClasses) {
+ if (p is IGenericTypeInstanceReference) {
+ structuralParents.Add(p);
+ } else {
+ var v = (Bpl.IdentifierExpr)FindOrCreateType(p);
+ parents.Add(new Bpl.ConstantParent(v, true));
+ }
+ }
+ foreach (var j in typeDefinition.Interfaces) {
+ if (j is IGenericTypeInstanceReference) {
+ structuralParents.Add(j);
+ } else {
+ var v = (Bpl.IdentifierExpr)FindOrCreateType(j);
+ parents.Add(new Bpl.ConstantParent(v, false));
+ }
+ }
+ return parents;
+ }
+
/// <summary>
/// The keys to the table are the interned key of the type.
/// </summary>
@@ -948,18 +969,30 @@ namespace BytecodeTranslator {
}
return "continuation" + id;
}
- public string FindOrCreateDispatchContinuationLabel(ITryCatchFinallyStatement stmt) {
- int id;
- if (!tryCatchFinallyIdentifiers.TryGetValue(stmt, out id)) {
- id = tryCatchFinallyIdentifiers.Count;
- tryCatchFinallyIdentifiers[stmt] = id;
- }
- return "DispatchContinuation" + id;
- }
MostNestedTryStatementTraverser mostNestedTryStatementTraverser;
public ITryCatchFinallyStatement MostNestedTryStatement(IName label) {
return mostNestedTryStatementTraverser.MostNestedTryStatement(label);
}
+ Dictionary<ITryCatchFinallyStatement, List<string>> escapingGotoEdges;
+ public void AddEscapingEdge(ITryCatchFinallyStatement tryCatchFinallyStatement, out int labelId, out string label) {
+ List<string> edges = null;
+ if (!escapingGotoEdges.ContainsKey(tryCatchFinallyStatement)) {
+ escapingGotoEdges[tryCatchFinallyStatement] = new List<string>();
+ }
+ edges = escapingGotoEdges[tryCatchFinallyStatement];
+ label = this.FindOrCreateFinallyLabel(tryCatchFinallyStatement) + "_" + edges.Count;
+ labelId = edges.Count;
+ edges.Add(label);
+ }
+ public List<string> EscapingEdges(ITryCatchFinallyStatement tryCatchFinallyStatement) {
+ if (!escapingGotoEdges.ContainsKey(tryCatchFinallyStatement)) {
+ escapingGotoEdges[tryCatchFinallyStatement] = new List<string>();
+ }
+ return escapingGotoEdges[tryCatchFinallyStatement];
+ }
+ public enum TryCatchFinallyContext { InTry, InCatch, InFinally };
+ public List<Tuple<ITryCatchFinallyStatement, TryCatchFinallyContext>> nestedTryCatchFinallyStatements;
+
IMethodDefinition methodBeingTranslated;
public void BeginMethod(IMethodDefinition method) {
this.BeginMethod(method.ContainingType);
@@ -967,6 +1000,8 @@ namespace BytecodeTranslator {
this.cciLabels = new Dictionary<IName, int>();
this.tryCatchFinallyIdentifiers = new Dictionary<ITryCatchFinallyStatement, int>();
mostNestedTryStatementTraverser = new MostNestedTryStatementTraverser();
+ escapingGotoEdges = new Dictionary<ITryCatchFinallyStatement, List<string>>();
+ nestedTryCatchFinallyStatements = new List<Tuple<ITryCatchFinallyStatement, TryCatchFinallyContext>>();
mostNestedTryStatementTraverser.Visit(method.Body);
}
diff --git a/BCT/BytecodeTranslator/StatementTraverser.cs b/BCT/BytecodeTranslator/StatementTraverser.cs
index 6bc399c1..89a258ea 100644
--- a/BCT/BytecodeTranslator/StatementTraverser.cs
+++ b/BCT/BytecodeTranslator/StatementTraverser.cs
@@ -59,14 +59,6 @@ namespace BytecodeTranslator
this.factory = sink.Factory;
PdbReader = pdbReader;
this.contractContext = contractContext;
- this.nestedTryCatchFinallyStatements = new List<Tuple<ITryCatchFinallyStatement, TryCatchFinallyContext>>();
- }
- public StatementTraverser(Sink sink, PdbReader/*?*/ pdbReader, bool contractContext, List<Tuple<ITryCatchFinallyStatement,TryCatchFinallyContext>> nestedTryCatchFinallyStatements) {
- this.sink = sink;
- this.factory = sink.Factory;
- PdbReader = pdbReader;
- this.contractContext = contractContext;
- this.nestedTryCatchFinallyStatements = nestedTryCatchFinallyStatements;
}
#endregion
@@ -93,22 +85,6 @@ namespace BytecodeTranslator
this.Visit(methodBody);
return newTypes;
}
-
- public void GenerateDispatchContinuation() {
- foreach (ITryCatchFinallyStatement stmt in sink.tryCatchFinallyIdentifiers.Keys) {
- // Iterate over all labels in sink.cciLabels and generate dispatch based on sink.LabelVariable
- this.StmtBuilder.AddLabelCmd(sink.FindOrCreateDispatchContinuationLabel(stmt));
- Bpl.IfCmd elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(true), TranslationHelper.BuildStmtList(new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(false))), null, null);
- Bpl.IdentifierExpr labelExpr = Bpl.Expr.Ident(this.sink.LabelVariable);
- foreach (IName name in sink.cciLabels.Keys) {
- Bpl.GotoCmd gotoCmd = new Bpl.GotoCmd(Bpl.Token.NoToken, new Bpl.StringSeq(name.Value));
- Bpl.Expr targetExpr = Bpl.Expr.Literal(sink.cciLabels[name]);
- elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, labelExpr, targetExpr), TranslationHelper.BuildStmtList(gotoCmd), elseIfCmd, null);
- }
- this.StmtBuilder.Add(elseIfCmd);
- this.StmtBuilder.Add(new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(false)));
- }
- }
#endregion
//public override void Visit(ISourceMethodBody methodBody) {
@@ -193,8 +169,8 @@ namespace BytecodeTranslator
/// <remarks>(mschaef) Works, but still a stub</remarks>
/// <param name="conditionalStatement"></param>
public override void Visit(IConditionalStatement conditionalStatement) {
- StatementTraverser thenTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext, this.nestedTryCatchFinallyStatements);
- StatementTraverser elseTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext, this.nestedTryCatchFinallyStatements);
+ StatementTraverser thenTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
+ StatementTraverser elseTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
ExpressionTraverser condTraverser = this.factory.MakeExpressionTraverser(this.sink, this, this.contractContext);
condTraverser.Visit(conditionalStatement.Condition);
@@ -248,6 +224,53 @@ namespace BytecodeTranslator
throw new TranslationException("Continue statements are not handled");
}
+ public override void Visit(ISwitchStatement switchStatement) {
+ var eTraverser = this.factory.MakeExpressionTraverser(this.sink, this, this.contractContext);
+ eTraverser.Visit(switchStatement.Expression);
+ var conditionExpr = eTraverser.TranslatedExpressions.Pop();
+
+ // Can't depend on default case existing or its index in the collection.
+ var switchCases = new List<ISwitchCase>();
+ ISwitchCase defaultCase = null;
+ foreach (var switchCase in switchStatement.Cases) {
+ if (switchCase.IsDefault) {
+ defaultCase = switchCase;
+ } else {
+ switchCases.Add(switchCase);
+ }
+ }
+ Bpl.StmtList defaultStmts = null;
+ if (defaultCase != null) {
+ var defaultBodyTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
+ defaultBodyTraverser.Visit(defaultCase.Body);
+ defaultStmts = defaultBodyTraverser.StmtBuilder.Collect(defaultCase.Token());
+ }
+
+ Bpl.IfCmd ifCmd = null;
+
+ for (int i = switchCases.Count-1; 0 <= i; i--) {
+
+ var switchCase = switchCases[i];
+
+ var scTraverser = this.factory.MakeExpressionTraverser(this.sink, this, this.contractContext);
+ scTraverser.Visit(switchCase.Expression);
+ var scConditionExpr = scTraverser.TranslatedExpressions.Pop();
+ var condition = Bpl.Expr.Eq(conditionExpr, scConditionExpr);
+
+ var scBodyTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
+ scBodyTraverser.Visit(switchCase.Body);
+
+ ifCmd = new Bpl.IfCmd(switchCase.Token(),
+ condition,
+ scBodyTraverser.StmtBuilder.Collect(switchCase.Token()),
+ ifCmd,
+ defaultStmts);
+ defaultStmts = null; // default body goes only into the innermost if-then-else
+
+ }
+ StmtBuilder.Add(ifCmd);
+ }
+
/// <summary>
/// If the local declaration has an initial value, then generate the
/// statement "loc := e" from it. Otherwise ignore it.
@@ -320,33 +343,25 @@ namespace BytecodeTranslator
#region Goto and Labels
- /// <summary>
- ///
- /// </summary>
- /// <remarks> STUB </remarks>
- /// <param name="gotoStatement"></param>
public override void Visit(IGotoStatement gotoStatement) {
IName target = gotoStatement.TargetStatement.Label;
- ITryCatchFinallyStatement targetContext = this.sink.MostNestedTryStatement(target);
+ ITryCatchFinallyStatement targetStatement = this.sink.MostNestedTryStatement(target);
int count = 0;
- while (count < this.nestedTryCatchFinallyStatements.Count) {
- int index = this.nestedTryCatchFinallyStatements.Count - count - 1;
- ITryCatchFinallyStatement nestedContext = this.nestedTryCatchFinallyStatements[index].Item1;
- if (targetContext == nestedContext)
+ while (count < this.sink.nestedTryCatchFinallyStatements.Count) {
+ int index = this.sink.nestedTryCatchFinallyStatements.Count - count - 1;
+ ITryCatchFinallyStatement nestedStatement = this.sink.nestedTryCatchFinallyStatements[index].Item1;
+ if (targetStatement == nestedStatement)
break;
- count++;
- }
- System.Diagnostics.Debug.Assert((count == nestedTryCatchFinallyStatements.Count) == (targetContext == null));
- if (count > 0) {
- int id = this.sink.FindOrCreateCciLabelIdentifier(target);
- StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(id)));
- StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.FinallyStackCounterVariable), Bpl.Expr.Literal(count-1)));
- string finallyLabel = this.sink.FindOrCreateFinallyLabel(this.nestedTryCatchFinallyStatements[this.nestedTryCatchFinallyStatements.Count - 1].Item1);
+ int labelId;
+ string label;
+ this.sink.AddEscapingEdge(nestedStatement, out labelId, out label);
+ StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(labelId)));
+ string finallyLabel = this.sink.FindOrCreateFinallyLabel(nestedStatement);
StmtBuilder.Add(new Bpl.GotoCmd(gotoStatement.Token(), new Bpl.StringSeq(finallyLabel)));
+ StmtBuilder.AddLabelCmd(label);
+ count++;
}
- else {
- StmtBuilder.Add(new Bpl.GotoCmd(gotoStatement.Token(), new Bpl.StringSeq(target.Value)));
- }
+ StmtBuilder.Add(new Bpl.GotoCmd(gotoStatement.Token(), new Bpl.StringSeq(target.Value)));
}
/// <summary>
@@ -377,21 +392,34 @@ namespace BytecodeTranslator
#endregion
- public enum TryCatchFinallyContext { InTry, InCatch, InFinally };
- List<Tuple<ITryCatchFinallyStatement, TryCatchFinallyContext>> nestedTryCatchFinallyStatements;
-
+ public void GenerateDispatchContinuation(ITryCatchFinallyStatement tryCatchFinallyStatement) {
+ string continuationLabel = this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement);
+ Bpl.IfCmd elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(true),
+ TranslationHelper.BuildStmtList(new Bpl.GotoCmd(Bpl.Token.NoToken, new Bpl.StringSeq(continuationLabel))), null, null);
+ List<string> edges = sink.EscapingEdges(tryCatchFinallyStatement);
+ Bpl.IdentifierExpr labelExpr = Bpl.Expr.Ident(this.sink.LabelVariable);
+ for (int i = 0; i < edges.Count; i++) {
+ string label = edges[i];
+ Bpl.GotoCmd gotoCmd = new Bpl.GotoCmd(Bpl.Token.NoToken, new Bpl.StringSeq(label));
+ Bpl.Expr targetExpr = Bpl.Expr.Literal(i);
+ elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, labelExpr, targetExpr),
+ TranslationHelper.BuildStmtList(gotoCmd), elseIfCmd, null);
+ }
+ this.StmtBuilder.Add(elseIfCmd);
+ }
+
private void RaiseExceptionHelper(Bpl.StmtListBuilder builder) {
- int count = nestedTryCatchFinallyStatements.Count;
+ int count = this.sink.nestedTryCatchFinallyStatements.Count;
if (count == 0) {
builder.Add(new Bpl.ReturnCmd(Bpl.Token.NoToken));
}
else {
- Tuple<ITryCatchFinallyStatement, TryCatchFinallyContext> topOfStack = nestedTryCatchFinallyStatements[count - 1];
+ Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext> topOfStack = this.sink.nestedTryCatchFinallyStatements[count - 1];
string exceptionTarget;
- if (topOfStack.Item2 == TryCatchFinallyContext.InTry) {
+ if (topOfStack.Item2 == Sink.TryCatchFinallyContext.InTry) {
exceptionTarget = this.sink.FindOrCreateCatchLabel(topOfStack.Item1);
}
- else if (topOfStack.Item2 == TryCatchFinallyContext.InCatch) {
+ else if (topOfStack.Item2 == Sink.TryCatchFinallyContext.InCatch) {
builder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)));
exceptionTarget = this.sink.FindOrCreateFinallyLabel(topOfStack.Item1);
}
@@ -414,21 +442,21 @@ namespace BytecodeTranslator
}
public override void Visit(ITryCatchFinallyStatement tryCatchFinallyStatement) {
- nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, TryCatchFinallyContext>(tryCatchFinallyStatement, TryCatchFinallyContext.InTry));
+ this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InTry));
this.Visit(tryCatchFinallyStatement.TryBody);
StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)));
StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new Bpl.StringSeq(this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement))));
- nestedTryCatchFinallyStatements.RemoveAt(nestedTryCatchFinallyStatements.Count - 1);
+ this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);
StmtBuilder.AddLabelCmd(this.sink.FindOrCreateCatchLabel(tryCatchFinallyStatement));
StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LocalExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)));
StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef)));
List<Bpl.StmtList> catchStatements = new List<Bpl.StmtList>();
List<Bpl.Expr> typeReferences = new List<Bpl.Expr>();
- this.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, TryCatchFinallyContext>(tryCatchFinallyStatement, TryCatchFinallyContext.InCatch));
+ this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InCatch));
foreach (ICatchClause catchClause in tryCatchFinallyStatement.CatchClauses) {
typeReferences.Insert(0, this.sink.FindOrCreateType(catchClause.ExceptionType));
- StatementTraverser catchTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext, this.nestedTryCatchFinallyStatements);
+ StatementTraverser catchTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
if (catchClause.ExceptionContainer != Dummy.LocalVariable) {
Bpl.Variable catchClauseVariable = this.sink.FindOrCreateLocalVariable(catchClause.ExceptionContainer);
catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(catchClauseVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
@@ -447,49 +475,21 @@ namespace BytecodeTranslator
this.StmtBuilder.Add(elseIfCmd);
this.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
RaiseException();
- nestedTryCatchFinallyStatements.RemoveAt(nestedTryCatchFinallyStatements.Count - 1);
+ this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);
this.StmtBuilder.AddLabelCmd(this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement));
if (tryCatchFinallyStatement.FinallyBody != null) {
- nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, TryCatchFinallyContext>(tryCatchFinallyStatement, TryCatchFinallyContext.InFinally));
+ this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InFinally));
Bpl.Variable savedExcVariable = this.sink.CreateFreshLocal(this.sink.Heap.RefType);
Bpl.Variable savedLabelVariable = this.sink.CreateFreshLocal(Bpl.Type.Int);
- Bpl.Variable savedFinallyStackCounterVariable = this.sink.CreateFreshLocal(Bpl.Type.Int);
StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)));
StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedLabelVariable), Bpl.Expr.Ident(this.sink.LabelVariable)));
- StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedFinallyStackCounterVariable), Bpl.Expr.Ident(this.sink.FinallyStackCounterVariable)));
Visit(tryCatchFinallyStatement.FinallyBody);
StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(savedExcVariable)));
StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Ident(savedLabelVariable)));
- StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.FinallyStackCounterVariable), Bpl.Expr.Ident(savedFinallyStackCounterVariable)));
- nestedTryCatchFinallyStatements.RemoveAt(nestedTryCatchFinallyStatements.Count - 1);
- }
- Bpl.GotoCmd dispatchCmd = new Bpl.GotoCmd(Bpl.Token.NoToken, new Bpl.StringSeq(this.sink.FindOrCreateDispatchContinuationLabel(tryCatchFinallyStatement)));
- Bpl.GotoCmd continuationCmd = new Bpl.GotoCmd(Bpl.Token.NoToken, new Bpl.StringSeq(this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement)));
- Bpl.IfCmd ifCmd = new Bpl.IfCmd(
- Bpl.Token.NoToken,
- Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)),
- TranslationHelper.BuildStmtList(continuationCmd),
- new Bpl.IfCmd(
- Bpl.Token.NoToken,
- Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, Bpl.Expr.Ident(this.sink.FinallyStackCounterVariable), Bpl.Expr.Literal(0)),
- TranslationHelper.BuildStmtList(dispatchCmd),
- null,
- null),
- null);
- this.StmtBuilder.Add(ifCmd);
- int count = this.nestedTryCatchFinallyStatements.Count;
- if (count == 0) {
- this.StmtBuilder.Add(new Bpl.AssertCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(false)));
- }
- else {
- Bpl.IdentifierExpr fsv = Bpl.Expr.Ident(this.sink.FinallyStackCounterVariable);
- Bpl.AssignCmd decrementCmd = TranslationHelper.BuildAssignCmd(fsv, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Sub, fsv, Bpl.Expr.Literal(1)));
- this.StmtBuilder.Add(decrementCmd);
- string parentFinallyLabel = this.sink.FindOrCreateFinallyLabel(this.nestedTryCatchFinallyStatements[count - 1].Item1);
- Bpl.GotoCmd parentCmd = new Bpl.GotoCmd(Bpl.Token.NoToken, new Bpl.StringSeq(parentFinallyLabel));
- this.StmtBuilder.Add(parentCmd);
+ this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);
}
+ GenerateDispatchContinuation(tryCatchFinallyStatement);
StmtBuilder.AddLabelCmd(this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement));
Bpl.Expr raiseExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef));
RaiseException(raiseExpr);
@@ -506,6 +506,7 @@ namespace BytecodeTranslator
StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
RaiseException();
}
+
}
}
diff --git a/BCT/BytecodeTranslator/TraverserFactory.cs b/BCT/BytecodeTranslator/TraverserFactory.cs
index 4685427f..78c818bd 100644
--- a/BCT/BytecodeTranslator/TraverserFactory.cs
+++ b/BCT/BytecodeTranslator/TraverserFactory.cs
@@ -27,10 +27,6 @@ namespace BytecodeTranslator {
public virtual StatementTraverser MakeStatementTraverser(Sink sink, PdbReader/*?*/ pdbReader, bool contractContext) {
return new StatementTraverser(sink, pdbReader, contractContext);
}
- public virtual StatementTraverser MakeStatementTraverser(Sink sink, PdbReader/*?*/ pdbReader, bool contractContext,
- List<Tuple<ITryCatchFinallyStatement,StatementTraverser.TryCatchFinallyContext>> nestedTryCatchFinallyStatements) {
- return new StatementTraverser(sink, pdbReader, contractContext, nestedTryCatchFinallyStatements);
- }
public virtual ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext) {
return new ExpressionTraverser(sink, statementTraverser, contractContext);
}
diff --git a/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py b/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py
new file mode 100644
index 00000000..89cc0c31
--- /dev/null
+++ b/BCT/PhoneControlsExtractor/PhoneControlsExtractor.py
@@ -0,0 +1,164 @@
+import sys
+import getopt
+import os
+from xml.dom import minidom
+import xml.dom
+
+CONTROL_NAMES= ["Button", "CheckBox", "RadioButton"]
+
+# TODO maybe a control is enabled but its parent is not, must take this into account
+# TODO a possible solution is to tie the enabled value to that of the parent in the app until it is either overriden
+# TODO (by directly manipulating the control's enabled value) or the parent becomes enabled
+
+CONTAINER_CONTROL_NAMES= ["Canvas", "Grid", "StackPanel"]
+
+staticControlsMap= {}
+mainPageXAML= None
+
+def showUsage():
+ print "PhoneControlsExtractor -- extract control information from phone application pages"
+ print "Usage:"
+ print "\tPhoneControlsExtractor --pages <application_directory> --output <info_output_file>\n"
+ print "Options:"
+ print "\t--pages <application_directory>: point to location of .xaml files detailing pages. Short form: -p"
+ print "\t--output <info_output_file>: file to write with control info. Short form: -o\n"
+
+def isPageFile(file):
+ # not the best way, find out the actual exceptions
+ try:
+ minidom.parse(file)
+ file.seek(0)
+ return True
+ except Exception:
+ return False
+
+def removeBlankElements(xmlNode):
+ blankNodes= []
+ for child in xmlNode.childNodes:
+ if child.nodeType == xml.dom.Node.TEXT_NODE and child.data.strip() == "":
+ blankNodes.append(child)
+ elif child.hasChildNodes():
+ removeBlankElements(child)
+
+ for node in blankNodes:
+ node.parentNode.removeChild(node)
+ node.unlink()
+
+def getControlNodes(xmlNode):
+ controlNodes= []
+ if (xmlNode.nodeType == xml.dom.Node.ELEMENT_NODE and xmlNode.localName in CONTROL_NAMES):
+ controlNodes.insert(0,xmlNode)
+
+ for child in xmlNode.childNodes:
+ controlNodes= controlNodes + getControlNodes(child)
+
+ return controlNodes
+
+def addControlToMap(pageXAML, parentPage, controlNode):
+ pageControls=[]
+ newControl={}
+ try:
+ pageControls= staticControlsMap[parentPage]
+ except KeyError:
+ pass
+
+ newControl["Type"]= controlNode.localName
+ newControl["Name"]= controlNode.getAttribute("Name")
+ if (controlNode.hasAttribute("IsEnabled")):
+ newControl["IsEnabled"]= controlNode.getAttribute("IsEnabled")
+ else:
+ newControl["IsEnabled"]= "true"
+
+ if (controlNode.hasAttribute("Visibility")):
+ newControl["Visibility"]= controlNode.getAttribute("Visibility")
+ else:
+ newControl["Visibility"]= "Visible"
+
+ # TODO it is possible that more events are of interest, we should add as we discover them in existing applications
+ newControl["Click"] = controlNode.getAttribute("Click")
+ newControl["Checked"] = controlNode.getAttribute("Checked")
+ newControl["Unchecked"] = controlNode.getAttribute("Unchecked")
+ newControl["XAML"]= pageXAML
+ pageControls.append(newControl)
+ staticControlsMap[parentPage]= pageControls
+
+def extractPhoneControlsFromPage(pageXAML):
+ # maybe it is not a page file
+ pageFile= open(pageXAML, "r")
+ if not isPageFile(pageFile):
+ return
+ pageFileXML= minidom.parse(pageFile)
+ pageFile.close()
+ removeBlankElements(pageFileXML)
+ controls= getControlNodes(pageFileXML)
+ ownerPage = None
+ for control in controls:
+ parent= control
+ while not parent == None and ownerPage == None:
+ if parent.localName == "PhoneApplicationPage":
+ ownerPage= parent.getAttribute("x:Class")
+ parent= parent.parentNode
+ addControlToMap(pageXAML, ownerPage, control)
+
+def outputPhoneControls(outputFileName):
+ outputFile= open(outputFileName, "w")
+
+ # Output format is first line containing only the main page, and then one line per
+ # <pageClassName>,<page.xaml file>,<controlClassName>,<controlName (as in field name)>,<IsEnabledValue>,<VisibilityValue>,<ClickValue>,<CheckedValue>,<UncheckedValue>
+ outputFile.write(mainPageXAML + "\n")
+ for page in staticControlsMap.keys():
+ for control in staticControlsMap[page]:
+ isEnabled= control["IsEnabled"]
+ visibility= control["Visibility"]
+ click= control["Click"]
+ checked= control["Checked"]
+ unchecked= control["Unchecked"]
+ pageXAML= control["XAML"]
+ outputFile.write(page + "," + os.path.basename(pageXAML) + "," + control["Type"] + "," + control["Name"] + "," + isEnabled + "," + visibility + "," + click + "," + checked + "," + unchecked + "\n")
+
+ outputFile.close()
+
+def getMainPageXAMLFromManifest(filename):
+ file= open(filename, "r");
+ manifest= minidom.parse(file)
+ file.close()
+ # interesting XPath location /App/Tasks/DefaultTask/@NavigationPage
+ return manifest.getElementsByTagName("DefaultTask")[0].getAttribute("NavigationPage")
+
+def extractPhoneControls(sourceDir):
+ global mainPageXAML
+ fileList= [os.path.join(sourceDir, fileName) for fileName in os.listdir(sourceDir) if os.path.splitext(fileName)[1] == ".xaml" or os.path.splitext(fileName)[1] == ".xml"]
+ for fileName in fileList:
+ if os.path.splitext(fileName)[1] == ".xml" and os.path.splitext(os.path.split(fileName)[1])[0].lower() == "wmappmanifest":
+ mainPageXAML= getMainPageXAMLFromManifest(fileName)
+ break
+
+ for fileName in fileList:
+ extractPhoneControlsFromPage(fileName)
+
+def main():
+ pagesDir= ""
+ outputFile= ""
+ try:
+ opts, args= getopt.getopt(sys.argv[1:], "p:o:", ["pages=","output="])
+ except geopt.error, msg:
+ print msg
+ showUsage()
+ sys.exit(2)
+
+ if not len(opts) == 2:
+ print "Missing options"
+ showUsage()
+ sys.exit(2)
+
+ for o, a in opts:
+ if o in ["-p","--pages"]:
+ pagesDir= a
+ if o in ["-o", "--output"]:
+ outputFile= a
+
+ extractPhoneControls(pagesDir)
+ outputPhoneControls(outputFile)
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/BCT/RegressionTests/TranslationTest/GeneralHeapInput.txt b/BCT/RegressionTests/TranslationTest/GeneralHeapInput.txt
index 9ad72923..32242dcd 100644
--- a/BCT/RegressionTests/TranslationTest/GeneralHeapInput.txt
+++ b/BCT/RegressionTests/TranslationTest/GeneralHeapInput.txt
@@ -1,8 +1,6 @@
// Copyright (c) 2010, Microsoft Corp.
// Bytecode Translator prelude
-type Struct = Ref;
-
type HeapType = [Ref][Field]Box;
var $Alloc: [Ref]bool;
@@ -20,19 +18,9 @@ implementation Alloc() returns (x: Ref)
-axiom Box2Int($DefaultBox) == 0;
-
-axiom Box2Bool($DefaultBox) == false;
-
-axiom Box2Ref($DefaultBox) == null;
-
-axiom (forall x: int :: { Int2Box(x) } Box2Int(Int2Box(x)) == x);
-
-axiom (forall x: bool :: { Bool2Box(x) } Box2Bool(Bool2Box(x)) == x);
-
-axiom (forall x: Ref :: { Ref2Box(x) } Box2Ref(Ref2Box(x)) == x);
+function $TypeOfInv(Ref) : Type;
-axiom (forall x: Struct :: { Struct2Box(x) } Box2Struct(Struct2Box(x)) == x);
+axiom (forall t: Type :: { $TypeOf(t) } $TypeOfInv($TypeOf(t)) == t);
procedure {:inline 1} System.Object.GetType(this: Ref) returns ($result: Ref);
@@ -45,9 +33,17 @@ implementation System.Object.GetType(this: Ref) returns ($result: Ref)
-function $TypeOfInv(Ref) : Type;
+axiom Box2Int($DefaultBox) == 0;
-axiom (forall t: Type :: { $TypeOf(t) } $TypeOfInv($TypeOf(t)) == t);
+axiom Box2Bool($DefaultBox) == false;
+
+axiom Box2Ref($DefaultBox) == null;
+
+axiom (forall x: int :: { Int2Box(x) } Box2Int(Int2Box(x)) == x);
+
+axiom (forall x: bool :: { Bool2Box(x) } Box2Bool(Bool2Box(x)) == x);
+
+axiom (forall x: Ref :: { Ref2Box(x) } Box2Ref(Ref2Box(x)) == x);
function $ThreadDelegate(Ref) : Ref;
@@ -68,7 +64,19 @@ procedure {:inline 1} System.Threading.Thread.Start$System.Object(this: Ref, par
implementation System.Threading.Thread.Start$System.Object(this: Ref, parameter$in: Ref)
{
- call {:async} System.Threading.ParameterizedThreadStart.Invoke$System.Object($ThreadDelegate(this), parameter$in);
+ call {:async} Wrapper_System.Threading.ParameterizedThreadStart.Invoke$System.Object($ThreadDelegate(this), parameter$in);
+}
+
+
+
+procedure {:inline 1} Wrapper_System.Threading.ParameterizedThreadStart.Invoke$System.Object(this: Ref, obj$in: Ref);
+
+
+
+implementation Wrapper_System.Threading.ParameterizedThreadStart.Invoke$System.Object(this: Ref, obj$in: Ref)
+{
+ $Exception := null;
+ call System.Threading.ParameterizedThreadStart.Invoke$System.Object(this, obj$in);
}
@@ -94,7 +102,19 @@ procedure {:inline 1} System.Threading.Thread.Start(this: Ref);
implementation System.Threading.Thread.Start(this: Ref)
{
- call {:async} System.Threading.ThreadStart.Invoke($ThreadDelegate(this));
+ call {:async} Wrapper_System.Threading.ThreadStart.Invoke($ThreadDelegate(this));
+}
+
+
+
+procedure {:inline 1} Wrapper_System.Threading.ThreadStart.Invoke(this: Ref);
+
+
+
+implementation Wrapper_System.Threading.ThreadStart.Invoke(this: Ref)
+{
+ $Exception := null;
+ call System.Threading.ThreadStart.Invoke(this);
}
@@ -260,6 +280,8 @@ implementation DelegateRemoveHelper(oldi: Ref, m: int, o: Ref) returns (i: Ref)
+const unique $BoxField: Field;
+
var $Heap: HeapType;
function {:inline true} Read(H: HeapType, o: Ref, f: Field) : Box
@@ -288,27 +310,21 @@ const unique null: Ref;
type Type;
-const unique $DefaultStruct: [Field]Box;
-
type Real;
const unique $DefaultReal: Real;
-function Box2Int(Box) : int;
-
function Box2Bool(Box) : bool;
-function Box2Struct(Box) : Struct;
+function Box2Int(Box) : int;
function Box2Ref(Box) : Ref;
function Box2Real(Box) : Real;
-function Int2Box(int) : Box;
-
function Bool2Box(bool) : Box;
-function Struct2Box(Struct) : Box;
+function Int2Box(int) : Box;
function Ref2Box(Ref) : Box;
@@ -319,19 +335,9 @@ function {:inline true} Box2Box(b: Box) : Box
b
}
-function Struct2Ref(Struct) : Ref;
-
-function Int2Ref(int) : Ref;
-
-function Bool2Ref(bool) : Ref;
+function Int2Real(int) : Real;
-function Int2Real(int, Type, Type) : Real;
-
-function Real2Int(Real, Type, Type) : Real;
-
-function Ref2Real(Ref, Type, Type) : Real;
-
-function Real2Ref(Real, Type, Type) : Ref;
+function Real2Int(Real) : int;
function RealPlus(Real, Real) : Real;
@@ -341,6 +347,14 @@ function RealTimes(Real, Real) : Real;
function RealDivide(Real, Real) : Real;
+function RealLessThan(Real, Real) : bool;
+
+function RealLessThanOrEqual(Real, Real) : bool;
+
+function RealGreaterThan(Real, Real) : bool;
+
+function RealGreaterThanOrEqual(Real, Real) : bool;
+
function BitwiseAnd(int, int) : int;
function BitwiseOr(int, int) : int;
@@ -349,10 +363,6 @@ function BitwiseExclusiveOr(int, int) : int;
function BitwiseNegation(int) : int;
-function Ref2Int(Ref, Type, Type) : int;
-
-function Ref2Bool(Ref, Type, Type) : bool;
-
function $DynamicType(Ref) : Type;
function $TypeOf(Type) : Ref;
@@ -367,9 +377,13 @@ var $Method: [Ref][Ref]int;
var $Receiver: [Ref][Ref]Ref;
-const unique RegressionTestInput.RealNumbers: Type;
+var {:thread_local} $Exception: Ref;
-procedure RegressionTestInput.RealNumbers.WriteDouble$System.Double(this: Ref, d$in: Real);
+const {:extern} unique System.Object: Type extends;
+
+const unique RegressionTestInput.RealNumbers: Type extends unique System.Object;
+
+procedure RegressionTestInput.RealNumbers.WriteDouble$System.Double($this: Ref, d$in: Real);
@@ -377,41 +391,51 @@ procedure {:extern} System.Console.WriteLine$System.Double(value$in: Real);
-implementation RegressionTestInput.RealNumbers.WriteDouble$System.Double(this: Ref, d$in: Real)
+implementation RegressionTestInput.RealNumbers.WriteDouble$System.Double($this: Ref, d$in: Real)
{
var d: Real;
+ var $localExc: Ref;
+ var $label: int;
d := d$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 162} true;
call System.Console.WriteLine$System.Double(d);
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 163} true;
return;
}
-procedure RegressionTestInput.RealNumbers.ObjectToDouble$System.Object(this: Ref, o$in: Ref);
-
-
+procedure RegressionTestInput.RealNumbers.ObjectToDouble$System.Object($this: Ref, o$in: Ref);
-const {:extern} unique System.Object: Type;
-const {:extern} unique System.Double: Type;
-implementation RegressionTestInput.RealNumbers.ObjectToDouble$System.Object(this: Ref, o$in: Ref)
+implementation RegressionTestInput.RealNumbers.ObjectToDouble$System.Object($this: Ref, o$in: Ref)
{
var o: Ref;
+ var $localExc: Ref;
+ var $label: int;
o := o$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 165} true;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, Ref2Real(o, System.Object, System.Double));
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, Box2Real(Read($Heap, o, $BoxField)));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 166} true;
return;
}
-procedure RegressionTestInput.RealNumbers.RealOperations(this: Ref);
+procedure RegressionTestInput.RealNumbers.RealOperations($this: Ref);
@@ -419,43 +443,70 @@ const unique $real_literal_3_0: Real;
const unique $real_literal_4_0: Real;
-implementation RegressionTestInput.RealNumbers.RealOperations(this: Ref)
+implementation RegressionTestInput.RealNumbers.RealOperations($this: Ref)
{
var local_0: Real;
var local_1: Real;
- var $tmp0: Real;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 168} true;
local_0 := $real_literal_3_0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 169} true;
local_1 := $real_literal_4_0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 170} true;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, RealPlus(local_0, local_1));
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, RealPlus(local_0, local_1));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 171} true;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, RealMinus(local_0, local_1));
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, RealMinus(local_0, local_1));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 172} true;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, RealTimes(local_0, local_1));
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, RealTimes(local_0, local_1));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 173} true;
- $tmp0 := local_1;
- assert $tmp0 != 0;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, local_0 / $tmp0);
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, RealDivide(local_0, local_1));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 174} true;
return;
}
-procedure RegressionTestInput.RealNumbers.#ctor(this: Ref);
+procedure RegressionTestInput.RealNumbers.#ctor($this: Ref);
-procedure {:extern} System.Object.#ctor(this: Ref);
+procedure {:extern} System.Object.#ctor($this: Ref);
-implementation RegressionTestInput.RealNumbers.#ctor(this: Ref)
+implementation RegressionTestInput.RealNumbers.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -471,35 +522,46 @@ implementation RegressionTestInput.RealNumbers.#cctor()
-const unique RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap: Type;
+const unique RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap: Type extends unique System.Object;
const unique RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x: Field;
const unique RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y: Field;
-procedure RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.M(this: Ref);
+procedure RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.M($this: Ref);
-implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.M(this: Ref)
+implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.M($this: Ref)
{
+ var $localExc: Ref;
+ var $label: int;
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 130} true;
- $Heap := Write($Heap, this, RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y, Int2Box(Box2Int(Read($Heap, this, RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x))));
+ $Heap := Write($Heap, $this, RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y, Int2Box(Box2Int(Read($Heap, $this, RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x))));
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 131} true;
return;
}
-procedure RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#ctor(this: Ref);
+procedure RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#ctor($this: Ref);
-implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#ctor(this: Ref)
+implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#ctor($this: Ref)
{
- $Heap := Write($Heap, this, RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x, Int2Box(0));
- $Heap := Write($Heap, this, RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y, Int2Box(0));
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ $Heap := Write($Heap, $this, RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x, Int2Box(0));
+ $Heap := Write($Heap, $this, RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y, Int2Box(0));
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -515,9 +577,9 @@ implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#cctor()
-const unique RegressionTestInput.CreateStruct: Type;
+const unique RegressionTestInput.CreateStruct: Type extends unique System.Object;
-procedure RegressionTestInput.CreateStruct.Create(this: Ref) returns ($result: Ref);
+procedure RegressionTestInput.CreateStruct.Create($this: Ref) returns ($result: Ref);
@@ -525,22 +587,26 @@ procedure RegressionTestInput.S.#default_ctor(this: Ref);
-const unique RegressionTestInput.S: Type;
+const {:extern} unique System.ValueType: Type extends unique System.Object;
+
+const unique RegressionTestInput.S: Type extends unique System.ValueType;
const unique RegressionTestInput.S.x: Field;
const unique RegressionTestInput.S.b: Field;
-implementation RegressionTestInput.CreateStruct.Create(this: Ref) returns ($result: Ref)
+implementation RegressionTestInput.CreateStruct.Create($this: Ref) returns ($result: Ref)
{
- var $tmp1: Ref;
+ var $tmp0: Ref;
var local_0: Ref;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 141} true;
- call $tmp1 := Alloc();
- call RegressionTestInput.S.#default_ctor($tmp1);
- assume $DynamicType($tmp1) == RegressionTestInput.S;
- local_0 := $tmp1;
+ call $tmp0 := Alloc();
+ call RegressionTestInput.S.#default_ctor($tmp0);
+ assume $DynamicType($tmp0) == RegressionTestInput.S;
+ local_0 := $tmp0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 142} true;
assert Box2Int(Read($Heap, local_0, RegressionTestInput.S.x)) == 0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 143} true;
@@ -552,13 +618,15 @@ implementation RegressionTestInput.CreateStruct.Create(this: Ref) returns ($resu
-procedure RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTestInput.S(this: Ref, s$in: Ref) returns ($result: Ref);
+procedure RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTestInput.S($this: Ref, s$in: Ref) returns ($result: Ref);
-implementation RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTestInput.S(this: Ref, s$in: Ref) returns ($result: Ref)
+implementation RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTestInput.S($this: Ref, s$in: Ref) returns ($result: Ref)
{
var s: Ref;
+ var $localExc: Ref;
+ var $label: int;
s := s$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 147} true;
@@ -572,13 +640,21 @@ implementation RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTes
-procedure RegressionTestInput.CreateStruct.#ctor(this: Ref);
+procedure RegressionTestInput.CreateStruct.#ctor($this: Ref);
-implementation RegressionTestInput.CreateStruct.#ctor(this: Ref)
+implementation RegressionTestInput.CreateStruct.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -594,7 +670,7 @@ implementation RegressionTestInput.CreateStruct.#cctor()
-const unique RegressionTestInput.ClassWithArrayTypes: Type;
+const unique RegressionTestInput.ClassWithArrayTypes: Type extends unique System.Object;
var RegressionTestInput.ClassWithArrayTypes.s: Ref;
@@ -607,28 +683,30 @@ procedure RegressionTestInput.ClassWithArrayTypes.Main1();
implementation RegressionTestInput.ClassWithArrayTypes.Main1()
{
var local_0: Ref;
- var $tmp2: Ref;
+ var $tmp1: Ref;
var local_1: Ref;
- var $tmp3: Ref;
+ var $tmp2: Ref;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 86} true;
- call $tmp2 := Alloc();
- assume $ArrayLength($tmp2) == 1 * 5;
- local_0 := $tmp2;
+ call $tmp1 := Alloc();
+ assume $ArrayLength($tmp1) == 1 * 5;
+ local_0 := $tmp1;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 87} true;
$ArrayContents := $ArrayContents[local_0 := $ArrayContents[local_0][0 := Int2Box(2)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 88} true;
- assert local_0 == 2;
+ assert Box2Int($ArrayContents[local_0][0]) == 2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 90} true;
- call $tmp3 := Alloc();
- assume $ArrayLength($tmp3) == 1 * 4;
- local_1 := $tmp3;
+ call $tmp2 := Alloc();
+ assume $ArrayLength($tmp2) == 1 * 4;
+ local_1 := $tmp2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 91} true;
$ArrayContents := $ArrayContents[local_1 := $ArrayContents[local_1][0 := Int2Box(1)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 92} true;
- assert local_1 == 1;
+ assert Box2Int($ArrayContents[local_1][0]) == 1;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 94} true;
- assert local_0 == 2;
+ assert Box2Int($ArrayContents[local_0][0]) == 2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 95} true;
return;
}
@@ -641,72 +719,85 @@ procedure RegressionTestInput.ClassWithArrayTypes.Main2();
implementation RegressionTestInput.ClassWithArrayTypes.Main2()
{
- var $tmp4: Ref;
+ var $tmp3: Ref;
var local_0: Ref;
- var $tmp5: Ref;
+ var $tmp4: Ref;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 100} true;
- call $tmp4 := Alloc();
- assume $ArrayLength($tmp4) == 1 * 5;
- RegressionTestInput.ClassWithArrayTypes.s := $tmp4;
+ call $tmp3 := Alloc();
+ assume $ArrayLength($tmp3) == 1 * 5;
+ RegressionTestInput.ClassWithArrayTypes.s := $tmp3;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 101} true;
$ArrayContents := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.s := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.s][0 := Int2Box(2)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 102} true;
- assert RegressionTestInput.ClassWithArrayTypes.s == 2;
+ assert Box2Int($ArrayContents[RegressionTestInput.ClassWithArrayTypes.s][0]) == 2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 104} true;
- call $tmp5 := Alloc();
- assume $ArrayLength($tmp5) == 1 * 4;
- local_0 := $tmp5;
+ call $tmp4 := Alloc();
+ assume $ArrayLength($tmp4) == 1 * 4;
+ local_0 := $tmp4;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 105} true;
$ArrayContents := $ArrayContents[local_0 := $ArrayContents[local_0][0 := Int2Box(1)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 106} true;
- assert local_0 == 1;
+ assert Box2Int($ArrayContents[local_0][0]) == 1;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 108} true;
- assert RegressionTestInput.ClassWithArrayTypes.s == 2;
+ assert Box2Int($ArrayContents[RegressionTestInput.ClassWithArrayTypes.s][0]) == 2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 109} true;
return;
}
-procedure RegressionTestInput.ClassWithArrayTypes.Main3$System.Int32(this: Ref, x$in: int);
+procedure RegressionTestInput.ClassWithArrayTypes.Main3$System.Int32($this: Ref, x$in: int);
-implementation RegressionTestInput.ClassWithArrayTypes.Main3$System.Int32(this: Ref, x$in: int)
+implementation RegressionTestInput.ClassWithArrayTypes.Main3$System.Int32($this: Ref, x$in: int)
{
var x: int;
- var _loc0: int;
- var _loc1: int;
+ var _loc0: Ref;
+ var _loc1: Ref;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 114} true;
- $ArrayContents := $ArrayContents[Box2Ref(Read($Heap, this, RegressionTestInput.ClassWithArrayTypes.a)) := $ArrayContents[Box2Ref(Read($Heap, this, RegressionTestInput.ClassWithArrayTypes.a))][x := Int2Box(42)]];
+ $ArrayContents := $ArrayContents[Box2Ref(Read($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a)) := $ArrayContents[Box2Ref(Read($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a))][x := Int2Box(42)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 115} true;
- $ArrayContents := $ArrayContents[Box2Ref(Read($Heap, this, RegressionTestInput.ClassWithArrayTypes.a)) := $ArrayContents[Box2Ref(Read($Heap, this, RegressionTestInput.ClassWithArrayTypes.a))][x + 1 := Int2Box(43)]];
+ $ArrayContents := $ArrayContents[Box2Ref(Read($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a)) := $ArrayContents[Box2Ref(Read($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a))][x + 1 := Int2Box(43)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 116} true;
- _loc0 := Box2Ref(Read($Heap, this, RegressionTestInput.ClassWithArrayTypes.a));
- _loc1 := Box2Ref(Read($Heap, this, RegressionTestInput.ClassWithArrayTypes.a));
- assert _loc0 == _loc1 + 1;
+ _loc0 := Box2Ref(Read($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a));
+ _loc1 := Box2Ref(Read($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a));
+ assert Box2Int($ArrayContents[_loc0][x + 1]) == Box2Int($ArrayContents[_loc1][x]) + 1;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 117} true;
return;
}
-procedure RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array(this: Ref, xs$in: Ref);
+procedure RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array($this: Ref, xs$in: Ref);
-implementation RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array(this: Ref, xs$in: Ref)
+implementation RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array($this: Ref, xs$in: Ref)
{
var xs: Ref;
+ var $localExc: Ref;
+ var $label: int;
xs := xs$in;
- if (!(!(xs != null) || $ArrayLength(xs) <= 0))
+ if (xs != null)
+ {
+ }
+ else
+ {
+ }
+
+ if (!(if xs != null then $ArrayLength(xs) <= 0 else true))
{
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 121} true;
- $ArrayContents := $ArrayContents[Box2Ref(Read($Heap, this, RegressionTestInput.ClassWithArrayTypes.a)) := $ArrayContents[Box2Ref(Read($Heap, this, RegressionTestInput.ClassWithArrayTypes.a))][0 := Int2Box(xs)]];
+ $ArrayContents := $ArrayContents[Box2Ref(Read($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a)) := $ArrayContents[Box2Ref(Read($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a))][0 := Int2Box(Box2Int($ArrayContents[xs][0]))]];
}
else
{
@@ -718,14 +809,22 @@ implementation RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array(t
-procedure RegressionTestInput.ClassWithArrayTypes.#ctor(this: Ref);
+procedure RegressionTestInput.ClassWithArrayTypes.#ctor($this: Ref);
-implementation RegressionTestInput.ClassWithArrayTypes.#ctor(this: Ref)
+implementation RegressionTestInput.ClassWithArrayTypes.#ctor($this: Ref)
{
- $Heap := Write($Heap, this, RegressionTestInput.ClassWithArrayTypes.a, Ref2Box(null));
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ $Heap := Write($Heap, $this, RegressionTestInput.ClassWithArrayTypes.a, Ref2Box(null));
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -742,16 +841,18 @@ implementation RegressionTestInput.ClassWithArrayTypes.#cctor()
-const unique RegressionTestInput.BitwiseOperations: Type;
+const unique RegressionTestInput.BitwiseOperations: Type extends unique System.Object;
-procedure RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int);
+procedure RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int);
-implementation RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int)
+implementation RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int)
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -762,14 +863,16 @@ implementation RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$Sys
-procedure RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int);
+procedure RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int);
-implementation RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int)
+implementation RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int)
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -780,14 +883,16 @@ implementation RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$Syst
-procedure RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int);
+procedure RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int);
-implementation RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int)
+implementation RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int)
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -798,13 +903,15 @@ implementation RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$Sy
-procedure RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int32(this: Ref, x$in: int) returns ($result: int);
+procedure RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int32($this: Ref, x$in: int) returns ($result: int);
-implementation RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int32(this: Ref, x$in: int) returns ($result: int)
+implementation RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int32($this: Ref, x$in: int) returns ($result: int)
{
var x: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 181} true;
@@ -814,13 +921,21 @@ implementation RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int3
-procedure RegressionTestInput.BitwiseOperations.#ctor(this: Ref);
+procedure RegressionTestInput.BitwiseOperations.#ctor($this: Ref);
-implementation RegressionTestInput.BitwiseOperations.#ctor(this: Ref)
+implementation RegressionTestInput.BitwiseOperations.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -836,19 +951,31 @@ implementation RegressionTestInput.BitwiseOperations.#cctor()
-const unique RegressionTestInput.AsyncAttribute: Type;
+const {:extern} unique System.Runtime.InteropServices._Attribute: Type extends;
+
+const {:extern} unique System.Attribute: Type extends unique System.Object, System.Runtime.InteropServices._Attribute;
-procedure RegressionTestInput.AsyncAttribute.#ctor(this: Ref);
+const unique RegressionTestInput.AsyncAttribute: Type extends unique System.Attribute;
+procedure RegressionTestInput.AsyncAttribute.#ctor($this: Ref);
-procedure {:extern} System.Attribute.#ctor(this: Ref);
+procedure {:extern} System.Attribute.#ctor($this: Ref);
-implementation RegressionTestInput.AsyncAttribute.#ctor(this: Ref)
+
+implementation RegressionTestInput.AsyncAttribute.#ctor($this: Ref)
{
- call System.Attribute.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Attribute.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -864,7 +991,7 @@ implementation RegressionTestInput.AsyncAttribute.#cctor()
-const unique RegressionTestInput.RefParameters: Type;
+const unique RegressionTestInput.RefParameters: Type extends unique System.Object;
procedure RegressionTestInput.RefParameters.M$System.Int32$(x$in: int) returns (x$out: int);
@@ -872,6 +999,9 @@ procedure RegressionTestInput.RefParameters.M$System.Int32$(x$in: int) returns (
implementation RegressionTestInput.RefParameters.M$System.Int32$(x$in: int) returns (x$out: int)
{
+ var $localExc: Ref;
+ var $label: int;
+
x$out := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 156} true;
x$out := x$out + 1;
@@ -881,13 +1011,21 @@ implementation RegressionTestInput.RefParameters.M$System.Int32$(x$in: int) retu
-procedure RegressionTestInput.RefParameters.#ctor(this: Ref);
+procedure RegressionTestInput.RefParameters.#ctor($this: Ref);
-implementation RegressionTestInput.RefParameters.#ctor(this: Ref)
+implementation RegressionTestInput.RefParameters.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -923,7 +1061,7 @@ implementation {:inline 1} RegressionTestInput.S.#copy_ctor(this: Ref, other: Re
-const unique RegressionTestInput.Class0: Type;
+const unique RegressionTestInput.Class0: Type extends unique System.Object;
var RegressionTestInput.Class0.StaticInt: int;
@@ -934,6 +1072,8 @@ procedure RegressionTestInput.Class0.StaticMethod$System.Int32(x$in: int) return
implementation RegressionTestInput.Class0.StaticMethod$System.Int32(x$in: int) returns ($result: int)
{
var x: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 18} true;
@@ -943,25 +1083,31 @@ implementation RegressionTestInput.Class0.StaticMethod$System.Int32(x$in: int) r
-procedure RegressionTestInput.Class0.M$System.Int32(this: Ref, x$in: int);
+procedure RegressionTestInput.Class0.M$System.Int32($this: Ref, x$in: int);
-implementation RegressionTestInput.Class0.M$System.Int32(this: Ref, x$in: int)
+implementation RegressionTestInput.Class0.M$System.Int32($this: Ref, x$in: int)
{
var x: int;
var __temp_1: int;
- var $tmp6: int;
var local_0: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
- $tmp6 := x;
- assert $tmp6 != 0;
- __temp_1 := 5 / $tmp6;
+ __temp_1 := 5 / x;
x := 3;
local_0 := __temp_1 + 3;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 22} true;
- assert x == 3 && local_0 <= 8;
+ if (x == 3)
+ {
+ }
+ else
+ {
+ }
+
+ assert (if x == 3 then local_0 <= 8 else false);
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 23} true;
RegressionTestInput.Class0.StaticInt := local_0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 24} true;
@@ -972,14 +1118,16 @@ implementation RegressionTestInput.Class0.M$System.Int32(this: Ref, x$in: int)
-procedure RegressionTestInput.Class0.M$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int);
+procedure RegressionTestInput.Class0.M$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int);
-implementation RegressionTestInput.Class0.M$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int)
+implementation RegressionTestInput.Class0.M$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int)
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -989,13 +1137,15 @@ implementation RegressionTestInput.Class0.M$System.Int32$System.Int32(this: Ref,
-procedure RegressionTestInput.Class0.M$System.Boolean(this: Ref, b$in: bool);
+procedure RegressionTestInput.Class0.M$System.Boolean($this: Ref, b$in: bool);
-implementation RegressionTestInput.Class0.M$System.Boolean(this: Ref, b$in: bool)
+implementation RegressionTestInput.Class0.M$System.Boolean($this: Ref, b$in: bool)
{
var b: bool;
+ var $localExc: Ref;
+ var $label: int;
b := b$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 29} true;
@@ -1004,13 +1154,15 @@ implementation RegressionTestInput.Class0.M$System.Boolean(this: Ref, b$in: bool
-procedure RegressionTestInput.Class0.M$RegressionTestInput.Class0(this: Ref, c$in: Ref);
+procedure RegressionTestInput.Class0.M$RegressionTestInput.Class0($this: Ref, c$in: Ref);
-implementation RegressionTestInput.Class0.M$RegressionTestInput.Class0(this: Ref, c$in: Ref)
+implementation RegressionTestInput.Class0.M$RegressionTestInput.Class0($this: Ref, c$in: Ref)
{
var c: Ref;
+ var $localExc: Ref;
+ var $label: int;
c := c$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 30} true;
@@ -1019,28 +1171,38 @@ implementation RegressionTestInput.Class0.M$RegressionTestInput.Class0(this: Ref
-procedure RegressionTestInput.Class0.NonVoid(this: Ref) returns ($result: int);
+procedure RegressionTestInput.Class0.NonVoid($this: Ref) returns ($result: int);
-implementation RegressionTestInput.Class0.NonVoid(this: Ref) returns ($result: int)
+implementation RegressionTestInput.Class0.NonVoid($this: Ref) returns ($result: int)
{
- var $tmp7: int;
+ var $tmp5: int;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 34} true;
- call $tmp7 := RegressionTestInput.Class0.StaticMethod$System.Int32(3);
- $result := 3 + RegressionTestInput.Class0.StaticInt + $tmp7;
+ call $tmp5 := RegressionTestInput.Class0.StaticMethod$System.Int32(3);
+ if ($Exception != null)
+ {
+ return;
+ }
+
+ $result := 3 + RegressionTestInput.Class0.StaticInt + $tmp5;
return;
}
-procedure RegressionTestInput.Class0.OutParam$System.Int32$(this: Ref, x$in: int) returns (x$out: int, $result: int);
+procedure RegressionTestInput.Class0.OutParam$System.Int32$($this: Ref, x$in: int) returns (x$out: int, $result: int);
-implementation RegressionTestInput.Class0.OutParam$System.Int32$(this: Ref, x$in: int) returns (x$out: int, $result: int)
+implementation RegressionTestInput.Class0.OutParam$System.Int32$($this: Ref, x$in: int) returns (x$out: int, $result: int)
{
+ var $localExc: Ref;
+ var $label: int;
+
x$out := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 37} true;
x$out := 3 + RegressionTestInput.Class0.StaticInt;
@@ -1051,12 +1213,15 @@ implementation RegressionTestInput.Class0.OutParam$System.Int32$(this: Ref, x$in
-procedure RegressionTestInput.Class0.RefParam$System.Int32$(this: Ref, x$in: int) returns (x$out: int, $result: int);
+procedure RegressionTestInput.Class0.RefParam$System.Int32$($this: Ref, x$in: int) returns (x$out: int, $result: int);
-implementation RegressionTestInput.Class0.RefParam$System.Int32$(this: Ref, x$in: int) returns (x$out: int, $result: int)
+implementation RegressionTestInput.Class0.RefParam$System.Int32$($this: Ref, x$in: int) returns (x$out: int, $result: int)
{
+ var $localExc: Ref;
+ var $label: int;
+
x$out := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 42} true;
x$out := x$out + 1;
@@ -1069,13 +1234,15 @@ implementation RegressionTestInput.Class0.RefParam$System.Int32$(this: Ref, x$in
-procedure RegressionTestInput.Class0.AssignToInParam$System.Int32(this: Ref, x$in: int) returns ($result: int);
+procedure RegressionTestInput.Class0.AssignToInParam$System.Int32($this: Ref, x$in: int) returns ($result: int);
-implementation RegressionTestInput.Class0.AssignToInParam$System.Int32(this: Ref, x$in: int) returns ($result: int)
+implementation RegressionTestInput.Class0.AssignToInParam$System.Int32($this: Ref, x$in: int) returns ($result: int)
{
var x: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 48} true;
@@ -1089,13 +1256,15 @@ implementation RegressionTestInput.Class0.AssignToInParam$System.Int32(this: Ref
-procedure {:RegressionTestInput.Async} RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32(this: Ref, x$in: int) returns ($result: int);
+procedure {:RegressionTestInput.Async} RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32($this: Ref, x$in: int) returns ($result: int);
-implementation RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32(this: Ref, x$in: int) returns ($result: int)
+implementation RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32($this: Ref, x$in: int) returns ($result: int)
{
var x: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 56} true;
@@ -1105,31 +1274,46 @@ implementation RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMetho
-procedure RegressionTestInput.Class0.CallAsyncMethod$System.Int32(this: Ref, y$in: int) returns ($result: int);
+procedure RegressionTestInput.Class0.CallAsyncMethod$System.Int32($this: Ref, y$in: int) returns ($result: int);
-implementation RegressionTestInput.Class0.CallAsyncMethod$System.Int32(this: Ref, y$in: int) returns ($result: int)
+implementation RegressionTestInput.Class0.CallAsyncMethod$System.Int32($this: Ref, y$in: int) returns ($result: int)
{
var y: int;
- var $tmp8: int;
+ var $tmp6: int;
+ var $localExc: Ref;
+ var $label: int;
y := y$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 60} true;
- call {:async} $tmp8 := RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32(this, y);
- $result := $tmp8;
+ call {:async} $tmp6 := RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32($this, y);
+ if ($Exception != null)
+ {
+ return;
+ }
+
+ $result := $tmp6;
return;
}
-procedure RegressionTestInput.Class0.#ctor(this: Ref);
+procedure RegressionTestInput.Class0.#ctor($this: Ref);
-implementation RegressionTestInput.Class0.#ctor(this: Ref)
+implementation RegressionTestInput.Class0.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -1146,7 +1330,7 @@ implementation RegressionTestInput.Class0.#cctor()
-const unique RegressionTestInput.ClassWithBoolTypes: Type;
+const unique RegressionTestInput.ClassWithBoolTypes: Type extends unique System.Object;
var RegressionTestInput.ClassWithBoolTypes.staticB: bool;
@@ -1160,6 +1344,8 @@ implementation RegressionTestInput.ClassWithBoolTypes.M$System.Int32$System.Int3
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -1170,20 +1356,27 @@ implementation RegressionTestInput.ClassWithBoolTypes.M$System.Int32$System.Int3
-procedure RegressionTestInput.ClassWithBoolTypes.#ctor$System.Boolean(this: Ref, z$in: bool);
+procedure RegressionTestInput.ClassWithBoolTypes.#ctor$System.Boolean($this: Ref, z$in: bool);
-implementation RegressionTestInput.ClassWithBoolTypes.#ctor$System.Boolean(this: Ref, z$in: bool)
+implementation RegressionTestInput.ClassWithBoolTypes.#ctor$System.Boolean($this: Ref, z$in: bool)
{
var z: bool;
+ var $localExc: Ref;
+ var $label: int;
z := z$in;
- $Heap := Write($Heap, this, RegressionTestInput.ClassWithBoolTypes.b, Bool2Box(false));
+ $Heap := Write($Heap, $this, RegressionTestInput.ClassWithBoolTypes.b, Bool2Box(false));
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 72} true;
- call System.Object.#ctor(this);
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 73} true;
- $Heap := Write($Heap, this, RegressionTestInput.ClassWithBoolTypes.b, Bool2Box(z));
+ $Heap := Write($Heap, $this, RegressionTestInput.ClassWithBoolTypes.b, Bool2Box(z));
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 74} true;
if (z)
{
@@ -1205,10 +1398,17 @@ procedure RegressionTestInput.ClassWithBoolTypes.Main();
implementation RegressionTestInput.ClassWithBoolTypes.Main()
{
- var $tmp9: bool;
+ var $tmp7: bool;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 78} true;
- call $tmp9 := RegressionTestInput.ClassWithBoolTypes.M$System.Int32$System.Int32(3, 4);
+ call $tmp7 := RegressionTestInput.ClassWithBoolTypes.M$System.Int32$System.Int32(3, 4);
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 79} true;
return;
}
diff --git a/BCT/RegressionTests/TranslationTest/SplitFieldsHeapInput.txt b/BCT/RegressionTests/TranslationTest/SplitFieldsHeapInput.txt
index 989ccfb9..19d98a28 100644
--- a/BCT/RegressionTests/TranslationTest/SplitFieldsHeapInput.txt
+++ b/BCT/RegressionTests/TranslationTest/SplitFieldsHeapInput.txt
@@ -1,12 +1,6 @@
// Copyright (c) 2010, Microsoft Corp.
// Bytecode Translator prelude
-type Struct = [Field]Box;
-
-type HeapType = [Ref,Field]Box;
-
-var $Heap: HeapType;
-
var $Alloc: [Ref]bool;
procedure {:inline 1} Alloc() returns (x: Ref);
@@ -22,19 +16,9 @@ implementation Alloc() returns (x: Ref)
-axiom Box2Int($DefaultBox) == 0;
-
-axiom Box2Bool($DefaultBox) == false;
-
-axiom Box2Ref($DefaultBox) == null;
-
-axiom (forall x: int :: { Int2Box(x) } Box2Int(Int2Box(x)) == x);
-
-axiom (forall x: bool :: { Bool2Box(x) } Box2Bool(Bool2Box(x)) == x);
-
-axiom (forall x: Ref :: { Ref2Box(x) } Box2Ref(Ref2Box(x)) == x);
+function $TypeOfInv(Ref) : Type;
-axiom (forall x: Struct :: { Struct2Box(x) } Box2Struct(Struct2Box(x)) == x);
+axiom (forall t: Type :: { $TypeOf(t) } $TypeOfInv($TypeOf(t)) == t);
procedure {:inline 1} System.Object.GetType(this: Ref) returns ($result: Ref);
@@ -47,9 +31,17 @@ implementation System.Object.GetType(this: Ref) returns ($result: Ref)
-function $TypeOfInv(Ref) : Type;
+axiom Box2Int($DefaultBox) == 0;
-axiom (forall t: Type :: { $TypeOf(t) } $TypeOfInv($TypeOf(t)) == t);
+axiom Box2Bool($DefaultBox) == false;
+
+axiom Box2Ref($DefaultBox) == null;
+
+axiom (forall x: int :: { Int2Box(x) } Box2Int(Int2Box(x)) == x);
+
+axiom (forall x: bool :: { Bool2Box(x) } Box2Bool(Bool2Box(x)) == x);
+
+axiom (forall x: Ref :: { Ref2Box(x) } Box2Ref(Ref2Box(x)) == x);
function $ThreadDelegate(Ref) : Ref;
@@ -70,7 +62,19 @@ procedure {:inline 1} System.Threading.Thread.Start$System.Object(this: Ref, par
implementation System.Threading.Thread.Start$System.Object(this: Ref, parameter$in: Ref)
{
- call {:async} System.Threading.ParameterizedThreadStart.Invoke$System.Object($ThreadDelegate(this), parameter$in);
+ call {:async} Wrapper_System.Threading.ParameterizedThreadStart.Invoke$System.Object($ThreadDelegate(this), parameter$in);
+}
+
+
+
+procedure {:inline 1} Wrapper_System.Threading.ParameterizedThreadStart.Invoke$System.Object(this: Ref, obj$in: Ref);
+
+
+
+implementation Wrapper_System.Threading.ParameterizedThreadStart.Invoke$System.Object(this: Ref, obj$in: Ref)
+{
+ $Exception := null;
+ call System.Threading.ParameterizedThreadStart.Invoke$System.Object(this, obj$in);
}
@@ -96,7 +100,19 @@ procedure {:inline 1} System.Threading.Thread.Start(this: Ref);
implementation System.Threading.Thread.Start(this: Ref)
{
- call {:async} System.Threading.ThreadStart.Invoke($ThreadDelegate(this));
+ call {:async} Wrapper_System.Threading.ThreadStart.Invoke($ThreadDelegate(this));
+}
+
+
+
+procedure {:inline 1} Wrapper_System.Threading.ThreadStart.Invoke(this: Ref);
+
+
+
+implementation Wrapper_System.Threading.ThreadStart.Invoke(this: Ref)
+{
+ $Exception := null;
+ call System.Threading.ThreadStart.Invoke(this);
}
@@ -262,6 +278,8 @@ implementation DelegateRemoveHelper(oldi: Ref, m: int, o: Ref) returns (i: Ref)
+var $BoxField: [Ref]Box;
+
var $ArrayContents: [Ref][int]Box;
function $ArrayLength(Ref) : int;
@@ -278,27 +296,21 @@ const unique null: Ref;
type Type;
-const unique $DefaultStruct: [Field]Box;
-
type Real;
const unique $DefaultReal: Real;
-function Box2Int(Box) : int;
-
function Box2Bool(Box) : bool;
-function Box2Struct(Box) : Struct;
+function Box2Int(Box) : int;
function Box2Ref(Box) : Ref;
function Box2Real(Box) : Real;
-function Int2Box(int) : Box;
-
function Bool2Box(bool) : Box;
-function Struct2Box(Struct) : Box;
+function Int2Box(int) : Box;
function Ref2Box(Ref) : Box;
@@ -309,19 +321,9 @@ function {:inline true} Box2Box(b: Box) : Box
b
}
-function Struct2Ref(Struct) : Ref;
-
-function Int2Ref(int) : Ref;
+function Int2Real(int) : Real;
-function Bool2Ref(bool) : Ref;
-
-function Int2Real(int, Type, Type) : Real;
-
-function Real2Int(Real, Type, Type) : Real;
-
-function Ref2Real(Ref, Type, Type) : Real;
-
-function Real2Ref(Real, Type, Type) : Ref;
+function Real2Int(Real) : int;
function RealPlus(Real, Real) : Real;
@@ -331,6 +333,14 @@ function RealTimes(Real, Real) : Real;
function RealDivide(Real, Real) : Real;
+function RealLessThan(Real, Real) : bool;
+
+function RealLessThanOrEqual(Real, Real) : bool;
+
+function RealGreaterThan(Real, Real) : bool;
+
+function RealGreaterThanOrEqual(Real, Real) : bool;
+
function BitwiseAnd(int, int) : int;
function BitwiseOr(int, int) : int;
@@ -339,10 +349,6 @@ function BitwiseExclusiveOr(int, int) : int;
function BitwiseNegation(int) : int;
-function Ref2Int(Ref, Type, Type) : int;
-
-function Ref2Bool(Ref, Type, Type) : bool;
-
function $DynamicType(Ref) : Type;
function $TypeOf(Type) : Ref;
@@ -357,9 +363,13 @@ var $Method: [Ref][Ref]int;
var $Receiver: [Ref][Ref]Ref;
-const unique RegressionTestInput.RealNumbers: Type;
+var {:thread_local} $Exception: Ref;
+
+const {:extern} unique System.Object: Type extends;
+
+const unique RegressionTestInput.RealNumbers: Type extends unique System.Object;
-procedure RegressionTestInput.RealNumbers.WriteDouble$System.Double(this: Ref, d$in: Real);
+procedure RegressionTestInput.RealNumbers.WriteDouble$System.Double($this: Ref, d$in: Real);
@@ -367,41 +377,51 @@ procedure {:extern} System.Console.WriteLine$System.Double(value$in: Real);
-implementation RegressionTestInput.RealNumbers.WriteDouble$System.Double(this: Ref, d$in: Real)
+implementation RegressionTestInput.RealNumbers.WriteDouble$System.Double($this: Ref, d$in: Real)
{
var d: Real;
+ var $localExc: Ref;
+ var $label: int;
d := d$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 162} true;
call System.Console.WriteLine$System.Double(d);
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 163} true;
return;
}
-procedure RegressionTestInput.RealNumbers.ObjectToDouble$System.Object(this: Ref, o$in: Ref);
-
+procedure RegressionTestInput.RealNumbers.ObjectToDouble$System.Object($this: Ref, o$in: Ref);
-const {:extern} unique System.Object: Type;
-const {:extern} unique System.Double: Type;
-
-implementation RegressionTestInput.RealNumbers.ObjectToDouble$System.Object(this: Ref, o$in: Ref)
+implementation RegressionTestInput.RealNumbers.ObjectToDouble$System.Object($this: Ref, o$in: Ref)
{
var o: Ref;
+ var $localExc: Ref;
+ var $label: int;
o := o$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 165} true;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, Ref2Real(o, System.Object, System.Double));
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, Box2Real($BoxField[o]));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 166} true;
return;
}
-procedure RegressionTestInput.RealNumbers.RealOperations(this: Ref);
+procedure RegressionTestInput.RealNumbers.RealOperations($this: Ref);
@@ -409,43 +429,70 @@ const unique $real_literal_3_0: Real;
const unique $real_literal_4_0: Real;
-implementation RegressionTestInput.RealNumbers.RealOperations(this: Ref)
+implementation RegressionTestInput.RealNumbers.RealOperations($this: Ref)
{
var local_0: Real;
var local_1: Real;
- var $tmp0: Real;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 168} true;
local_0 := $real_literal_3_0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 169} true;
local_1 := $real_literal_4_0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 170} true;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, RealPlus(local_0, local_1));
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, RealPlus(local_0, local_1));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 171} true;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, RealMinus(local_0, local_1));
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, RealMinus(local_0, local_1));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 172} true;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, RealTimes(local_0, local_1));
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, RealTimes(local_0, local_1));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 173} true;
- $tmp0 := local_1;
- assert $tmp0 != 0;
- call RegressionTestInput.RealNumbers.WriteDouble$System.Double(this, local_0 / $tmp0);
+ call RegressionTestInput.RealNumbers.WriteDouble$System.Double($this, RealDivide(local_0, local_1));
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 174} true;
return;
}
-procedure RegressionTestInput.RealNumbers.#ctor(this: Ref);
+procedure RegressionTestInput.RealNumbers.#ctor($this: Ref);
-procedure {:extern} System.Object.#ctor(this: Ref);
+procedure {:extern} System.Object.#ctor($this: Ref);
-implementation RegressionTestInput.RealNumbers.#ctor(this: Ref)
+implementation RegressionTestInput.RealNumbers.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -461,35 +508,46 @@ implementation RegressionTestInput.RealNumbers.#cctor()
-const unique RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap: Type;
+const unique RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap: Type extends unique System.Object;
var RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x: [Ref]int;
var RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y: [Ref]int;
-procedure RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.M(this: Ref);
+procedure RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.M($this: Ref);
-implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.M(this: Ref)
+implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.M($this: Ref)
{
+ var $localExc: Ref;
+ var $label: int;
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 130} true;
- RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y[this] := RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x[this];
+ RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y[$this] := RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x[$this];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 131} true;
return;
}
-procedure RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#ctor(this: Ref);
+procedure RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#ctor($this: Ref);
-implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#ctor(this: Ref)
+implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#ctor($this: Ref)
{
- RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x[this] := 0;
- RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y[this] := 0;
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.x[$this] := 0;
+ RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.y[$this] := 0;
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -505,9 +563,9 @@ implementation RegressionTestInput.WriteToTheHeapAValueReadFromTheHeap.#cctor()
-const unique RegressionTestInput.CreateStruct: Type;
+const unique RegressionTestInput.CreateStruct: Type extends unique System.Object;
-procedure RegressionTestInput.CreateStruct.Create(this: Ref) returns ($result: Ref);
+procedure RegressionTestInput.CreateStruct.Create($this: Ref) returns ($result: Ref);
@@ -515,26 +573,30 @@ procedure RegressionTestInput.S.#default_ctor(this: Ref);
-const unique RegressionTestInput.S: Type;
+const {:extern} unique System.ValueType: Type extends unique System.Object;
+
+const unique RegressionTestInput.S: Type extends unique System.ValueType;
var RegressionTestInput.S.x: [Ref]int;
var RegressionTestInput.S.b: [Ref]bool;
-implementation RegressionTestInput.CreateStruct.Create(this: Ref) returns ($result: Ref)
+implementation RegressionTestInput.CreateStruct.Create($this: Ref) returns ($result: Ref)
{
- var $tmp1: Ref;
+ var $tmp0: Ref;
var local_0: Ref;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 141} true;
- call $tmp1 := Alloc();
- call RegressionTestInput.S.#default_ctor($tmp1);
- assume $DynamicType($tmp1) == RegressionTestInput.S;
- local_0 := $tmp1;
+ call $tmp0 := Alloc();
+ call RegressionTestInput.S.#default_ctor($tmp0);
+ assume $DynamicType($tmp0) == RegressionTestInput.S;
+ local_0 := $tmp0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 142} true;
- assert Box2Int(local_0[RegressionTestInput.S.x]) == 0;
+ assert RegressionTestInput.S.x[local_0] == 0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 143} true;
- assert !Box2Bool(local_0[RegressionTestInput.S.b]);
+ assert !RegressionTestInput.S.b[local_0];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 145} true;
$result := local_0;
return;
@@ -542,19 +604,21 @@ implementation RegressionTestInput.CreateStruct.Create(this: Ref) returns ($resu
-procedure RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTestInput.S(this: Ref, s$in: Ref) returns ($result: Ref);
+procedure RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTestInput.S($this: Ref, s$in: Ref) returns ($result: Ref);
-implementation RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTestInput.S(this: Ref, s$in: Ref) returns ($result: Ref)
+implementation RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTestInput.S($this: Ref, s$in: Ref) returns ($result: Ref)
{
var s: Ref;
+ var $localExc: Ref;
+ var $label: int;
s := s$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 147} true;
- s[RegressionTestInput.S.x] := Int2Box(3);
+ RegressionTestInput.S.x[s] := 3;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 148} true;
- assert Box2Int(s[RegressionTestInput.S.x]) == 3;
+ assert RegressionTestInput.S.x[s] == 3;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 150} true;
$result := s;
return;
@@ -562,13 +626,21 @@ implementation RegressionTestInput.CreateStruct.AssignThreeToSDotX$RegressionTes
-procedure RegressionTestInput.CreateStruct.#ctor(this: Ref);
+procedure RegressionTestInput.CreateStruct.#ctor($this: Ref);
-implementation RegressionTestInput.CreateStruct.#ctor(this: Ref)
+implementation RegressionTestInput.CreateStruct.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -584,7 +656,7 @@ implementation RegressionTestInput.CreateStruct.#cctor()
-const unique RegressionTestInput.ClassWithArrayTypes: Type;
+const unique RegressionTestInput.ClassWithArrayTypes: Type extends unique System.Object;
var RegressionTestInput.ClassWithArrayTypes.s: Ref;
@@ -597,28 +669,30 @@ procedure RegressionTestInput.ClassWithArrayTypes.Main1();
implementation RegressionTestInput.ClassWithArrayTypes.Main1()
{
var local_0: Ref;
- var $tmp2: Ref;
+ var $tmp1: Ref;
var local_1: Ref;
- var $tmp3: Ref;
+ var $tmp2: Ref;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 86} true;
- call $tmp2 := Alloc();
- assume $ArrayLength($tmp2) == 1 * 5;
- local_0 := $tmp2;
+ call $tmp1 := Alloc();
+ assume $ArrayLength($tmp1) == 1 * 5;
+ local_0 := $tmp1;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 87} true;
$ArrayContents := $ArrayContents[local_0 := $ArrayContents[local_0][0 := Int2Box(2)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 88} true;
- assert local_0 == 2;
+ assert Box2Int($ArrayContents[local_0][0]) == 2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 90} true;
- call $tmp3 := Alloc();
- assume $ArrayLength($tmp3) == 1 * 4;
- local_1 := $tmp3;
+ call $tmp2 := Alloc();
+ assume $ArrayLength($tmp2) == 1 * 4;
+ local_1 := $tmp2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 91} true;
$ArrayContents := $ArrayContents[local_1 := $ArrayContents[local_1][0 := Int2Box(1)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 92} true;
- assert local_1 == 1;
+ assert Box2Int($ArrayContents[local_1][0]) == 1;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 94} true;
- assert local_0 == 2;
+ assert Box2Int($ArrayContents[local_0][0]) == 2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 95} true;
return;
}
@@ -631,72 +705,85 @@ procedure RegressionTestInput.ClassWithArrayTypes.Main2();
implementation RegressionTestInput.ClassWithArrayTypes.Main2()
{
- var $tmp4: Ref;
+ var $tmp3: Ref;
var local_0: Ref;
- var $tmp5: Ref;
+ var $tmp4: Ref;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 100} true;
- call $tmp4 := Alloc();
- assume $ArrayLength($tmp4) == 1 * 5;
- RegressionTestInput.ClassWithArrayTypes.s := $tmp4;
+ call $tmp3 := Alloc();
+ assume $ArrayLength($tmp3) == 1 * 5;
+ RegressionTestInput.ClassWithArrayTypes.s := $tmp3;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 101} true;
$ArrayContents := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.s := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.s][0 := Int2Box(2)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 102} true;
- assert RegressionTestInput.ClassWithArrayTypes.s == 2;
+ assert Box2Int($ArrayContents[RegressionTestInput.ClassWithArrayTypes.s][0]) == 2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 104} true;
- call $tmp5 := Alloc();
- assume $ArrayLength($tmp5) == 1 * 4;
- local_0 := $tmp5;
+ call $tmp4 := Alloc();
+ assume $ArrayLength($tmp4) == 1 * 4;
+ local_0 := $tmp4;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 105} true;
$ArrayContents := $ArrayContents[local_0 := $ArrayContents[local_0][0 := Int2Box(1)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 106} true;
- assert local_0 == 1;
+ assert Box2Int($ArrayContents[local_0][0]) == 1;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 108} true;
- assert RegressionTestInput.ClassWithArrayTypes.s == 2;
+ assert Box2Int($ArrayContents[RegressionTestInput.ClassWithArrayTypes.s][0]) == 2;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 109} true;
return;
}
-procedure RegressionTestInput.ClassWithArrayTypes.Main3$System.Int32(this: Ref, x$in: int);
+procedure RegressionTestInput.ClassWithArrayTypes.Main3$System.Int32($this: Ref, x$in: int);
-implementation RegressionTestInput.ClassWithArrayTypes.Main3$System.Int32(this: Ref, x$in: int)
+implementation RegressionTestInput.ClassWithArrayTypes.Main3$System.Int32($this: Ref, x$in: int)
{
var x: int;
- var _loc0: int;
- var _loc1: int;
+ var _loc0: Ref;
+ var _loc1: Ref;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 114} true;
- $ArrayContents := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[this] := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[this]][x := Int2Box(42)]];
+ $ArrayContents := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[$this] := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[$this]][x := Int2Box(42)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 115} true;
- $ArrayContents := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[this] := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[this]][x + 1 := Int2Box(43)]];
+ $ArrayContents := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[$this] := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[$this]][x + 1 := Int2Box(43)]];
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 116} true;
- _loc0 := RegressionTestInput.ClassWithArrayTypes.a[this];
- _loc1 := RegressionTestInput.ClassWithArrayTypes.a[this];
- assert _loc0 == _loc1 + 1;
+ _loc0 := RegressionTestInput.ClassWithArrayTypes.a[$this];
+ _loc1 := RegressionTestInput.ClassWithArrayTypes.a[$this];
+ assert Box2Int($ArrayContents[_loc0][x + 1]) == Box2Int($ArrayContents[_loc1][x]) + 1;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 117} true;
return;
}
-procedure RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array(this: Ref, xs$in: Ref);
+procedure RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array($this: Ref, xs$in: Ref);
-implementation RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array(this: Ref, xs$in: Ref)
+implementation RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array($this: Ref, xs$in: Ref)
{
var xs: Ref;
+ var $localExc: Ref;
+ var $label: int;
xs := xs$in;
- if (!(!(xs != null) || $ArrayLength(xs) <= 0))
+ if (xs != null)
+ {
+ }
+ else
+ {
+ }
+
+ if (!(if xs != null then $ArrayLength(xs) <= 0 else true))
{
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 121} true;
- $ArrayContents := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[this] := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[this]][0 := Int2Box(xs)]];
+ $ArrayContents := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[$this] := $ArrayContents[RegressionTestInput.ClassWithArrayTypes.a[$this]][0 := Int2Box(Box2Int($ArrayContents[xs][0]))]];
}
else
{
@@ -708,14 +795,22 @@ implementation RegressionTestInput.ClassWithArrayTypes.Main4$System.Int32array(t
-procedure RegressionTestInput.ClassWithArrayTypes.#ctor(this: Ref);
+procedure RegressionTestInput.ClassWithArrayTypes.#ctor($this: Ref);
-implementation RegressionTestInput.ClassWithArrayTypes.#ctor(this: Ref)
+implementation RegressionTestInput.ClassWithArrayTypes.#ctor($this: Ref)
{
- RegressionTestInput.ClassWithArrayTypes.a[this] := null;
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ RegressionTestInput.ClassWithArrayTypes.a[$this] := null;
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -732,16 +827,18 @@ implementation RegressionTestInput.ClassWithArrayTypes.#cctor()
-const unique RegressionTestInput.BitwiseOperations: Type;
+const unique RegressionTestInput.BitwiseOperations: Type extends unique System.Object;
-procedure RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int);
+procedure RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int);
-implementation RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int)
+implementation RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int)
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -752,14 +849,16 @@ implementation RegressionTestInput.BitwiseOperations.BitwiseAnd$System.Int32$Sys
-procedure RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int);
+procedure RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int);
-implementation RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int)
+implementation RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int)
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -770,14 +869,16 @@ implementation RegressionTestInput.BitwiseOperations.BitwiseOr$System.Int32$Syst
-procedure RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int);
+procedure RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int);
-implementation RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int) returns ($result: int)
+implementation RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int) returns ($result: int)
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -788,13 +889,15 @@ implementation RegressionTestInput.BitwiseOperations.ExclusiveOr$System.Int32$Sy
-procedure RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int32(this: Ref, x$in: int) returns ($result: int);
+procedure RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int32($this: Ref, x$in: int) returns ($result: int);
-implementation RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int32(this: Ref, x$in: int) returns ($result: int)
+implementation RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int32($this: Ref, x$in: int) returns ($result: int)
{
var x: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 181} true;
@@ -804,13 +907,21 @@ implementation RegressionTestInput.BitwiseOperations.BitwiseNegation$System.Int3
-procedure RegressionTestInput.BitwiseOperations.#ctor(this: Ref);
+procedure RegressionTestInput.BitwiseOperations.#ctor($this: Ref);
-implementation RegressionTestInput.BitwiseOperations.#ctor(this: Ref)
+implementation RegressionTestInput.BitwiseOperations.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -826,19 +937,31 @@ implementation RegressionTestInput.BitwiseOperations.#cctor()
-const unique RegressionTestInput.AsyncAttribute: Type;
+const {:extern} unique System.Runtime.InteropServices._Attribute: Type extends;
+
+const {:extern} unique System.Attribute: Type extends unique System.Object, System.Runtime.InteropServices._Attribute;
-procedure RegressionTestInput.AsyncAttribute.#ctor(this: Ref);
+const unique RegressionTestInput.AsyncAttribute: Type extends unique System.Attribute;
+procedure RegressionTestInput.AsyncAttribute.#ctor($this: Ref);
-procedure {:extern} System.Attribute.#ctor(this: Ref);
+procedure {:extern} System.Attribute.#ctor($this: Ref);
-implementation RegressionTestInput.AsyncAttribute.#ctor(this: Ref)
+
+implementation RegressionTestInput.AsyncAttribute.#ctor($this: Ref)
{
- call System.Attribute.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Attribute.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -854,7 +977,7 @@ implementation RegressionTestInput.AsyncAttribute.#cctor()
-const unique RegressionTestInput.RefParameters: Type;
+const unique RegressionTestInput.RefParameters: Type extends unique System.Object;
procedure RegressionTestInput.RefParameters.M$System.Int32$(x$in: int) returns (x$out: int);
@@ -862,6 +985,9 @@ procedure RegressionTestInput.RefParameters.M$System.Int32$(x$in: int) returns (
implementation RegressionTestInput.RefParameters.M$System.Int32$(x$in: int) returns (x$out: int)
{
+ var $localExc: Ref;
+ var $label: int;
+
x$out := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 156} true;
x$out := x$out + 1;
@@ -871,13 +997,21 @@ implementation RegressionTestInput.RefParameters.M$System.Int32$(x$in: int) retu
-procedure RegressionTestInput.RefParameters.#ctor(this: Ref);
+procedure RegressionTestInput.RefParameters.#ctor($this: Ref);
-implementation RegressionTestInput.RefParameters.#ctor(this: Ref)
+implementation RegressionTestInput.RefParameters.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -907,13 +1041,13 @@ procedure RegressionTestInput.S.#copy_ctor(this: Ref, other: Ref);
implementation {:inline 1} RegressionTestInput.S.#copy_ctor(this: Ref, other: Ref)
{
- other[RegressionTestInput.S.x] := Int2Box(Box2Int(this[RegressionTestInput.S.x]));
- other[RegressionTestInput.S.b] := Bool2Box(Box2Bool(this[RegressionTestInput.S.b]));
+ RegressionTestInput.S.x[other] := RegressionTestInput.S.x[this];
+ RegressionTestInput.S.b[other] := RegressionTestInput.S.b[this];
}
-const unique RegressionTestInput.Class0: Type;
+const unique RegressionTestInput.Class0: Type extends unique System.Object;
var RegressionTestInput.Class0.StaticInt: int;
@@ -924,6 +1058,8 @@ procedure RegressionTestInput.Class0.StaticMethod$System.Int32(x$in: int) return
implementation RegressionTestInput.Class0.StaticMethod$System.Int32(x$in: int) returns ($result: int)
{
var x: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 18} true;
@@ -933,25 +1069,31 @@ implementation RegressionTestInput.Class0.StaticMethod$System.Int32(x$in: int) r
-procedure RegressionTestInput.Class0.M$System.Int32(this: Ref, x$in: int);
+procedure RegressionTestInput.Class0.M$System.Int32($this: Ref, x$in: int);
-implementation RegressionTestInput.Class0.M$System.Int32(this: Ref, x$in: int)
+implementation RegressionTestInput.Class0.M$System.Int32($this: Ref, x$in: int)
{
var x: int;
var __temp_1: int;
- var $tmp6: int;
var local_0: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
- $tmp6 := x;
- assert $tmp6 != 0;
- __temp_1 := 5 / $tmp6;
+ __temp_1 := 5 / x;
x := 3;
local_0 := __temp_1 + 3;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 22} true;
- assert x == 3 && local_0 <= 8;
+ if (x == 3)
+ {
+ }
+ else
+ {
+ }
+
+ assert (if x == 3 then local_0 <= 8 else false);
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 23} true;
RegressionTestInput.Class0.StaticInt := local_0;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 24} true;
@@ -962,14 +1104,16 @@ implementation RegressionTestInput.Class0.M$System.Int32(this: Ref, x$in: int)
-procedure RegressionTestInput.Class0.M$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int);
+procedure RegressionTestInput.Class0.M$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int);
-implementation RegressionTestInput.Class0.M$System.Int32$System.Int32(this: Ref, x$in: int, y$in: int)
+implementation RegressionTestInput.Class0.M$System.Int32$System.Int32($this: Ref, x$in: int, y$in: int)
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -979,13 +1123,15 @@ implementation RegressionTestInput.Class0.M$System.Int32$System.Int32(this: Ref,
-procedure RegressionTestInput.Class0.M$System.Boolean(this: Ref, b$in: bool);
+procedure RegressionTestInput.Class0.M$System.Boolean($this: Ref, b$in: bool);
-implementation RegressionTestInput.Class0.M$System.Boolean(this: Ref, b$in: bool)
+implementation RegressionTestInput.Class0.M$System.Boolean($this: Ref, b$in: bool)
{
var b: bool;
+ var $localExc: Ref;
+ var $label: int;
b := b$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 29} true;
@@ -994,13 +1140,15 @@ implementation RegressionTestInput.Class0.M$System.Boolean(this: Ref, b$in: bool
-procedure RegressionTestInput.Class0.M$RegressionTestInput.Class0(this: Ref, c$in: Ref);
+procedure RegressionTestInput.Class0.M$RegressionTestInput.Class0($this: Ref, c$in: Ref);
-implementation RegressionTestInput.Class0.M$RegressionTestInput.Class0(this: Ref, c$in: Ref)
+implementation RegressionTestInput.Class0.M$RegressionTestInput.Class0($this: Ref, c$in: Ref)
{
var c: Ref;
+ var $localExc: Ref;
+ var $label: int;
c := c$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 30} true;
@@ -1009,28 +1157,38 @@ implementation RegressionTestInput.Class0.M$RegressionTestInput.Class0(this: Ref
-procedure RegressionTestInput.Class0.NonVoid(this: Ref) returns ($result: int);
+procedure RegressionTestInput.Class0.NonVoid($this: Ref) returns ($result: int);
-implementation RegressionTestInput.Class0.NonVoid(this: Ref) returns ($result: int)
+implementation RegressionTestInput.Class0.NonVoid($this: Ref) returns ($result: int)
{
- var $tmp7: int;
+ var $tmp5: int;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 34} true;
- call $tmp7 := RegressionTestInput.Class0.StaticMethod$System.Int32(3);
- $result := 3 + RegressionTestInput.Class0.StaticInt + $tmp7;
+ call $tmp5 := RegressionTestInput.Class0.StaticMethod$System.Int32(3);
+ if ($Exception != null)
+ {
+ return;
+ }
+
+ $result := 3 + RegressionTestInput.Class0.StaticInt + $tmp5;
return;
}
-procedure RegressionTestInput.Class0.OutParam$System.Int32$(this: Ref, x$in: int) returns (x$out: int, $result: int);
+procedure RegressionTestInput.Class0.OutParam$System.Int32$($this: Ref, x$in: int) returns (x$out: int, $result: int);
-implementation RegressionTestInput.Class0.OutParam$System.Int32$(this: Ref, x$in: int) returns (x$out: int, $result: int)
+implementation RegressionTestInput.Class0.OutParam$System.Int32$($this: Ref, x$in: int) returns (x$out: int, $result: int)
{
+ var $localExc: Ref;
+ var $label: int;
+
x$out := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 37} true;
x$out := 3 + RegressionTestInput.Class0.StaticInt;
@@ -1041,12 +1199,15 @@ implementation RegressionTestInput.Class0.OutParam$System.Int32$(this: Ref, x$in
-procedure RegressionTestInput.Class0.RefParam$System.Int32$(this: Ref, x$in: int) returns (x$out: int, $result: int);
+procedure RegressionTestInput.Class0.RefParam$System.Int32$($this: Ref, x$in: int) returns (x$out: int, $result: int);
-implementation RegressionTestInput.Class0.RefParam$System.Int32$(this: Ref, x$in: int) returns (x$out: int, $result: int)
+implementation RegressionTestInput.Class0.RefParam$System.Int32$($this: Ref, x$in: int) returns (x$out: int, $result: int)
{
+ var $localExc: Ref;
+ var $label: int;
+
x$out := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 42} true;
x$out := x$out + 1;
@@ -1059,13 +1220,15 @@ implementation RegressionTestInput.Class0.RefParam$System.Int32$(this: Ref, x$in
-procedure RegressionTestInput.Class0.AssignToInParam$System.Int32(this: Ref, x$in: int) returns ($result: int);
+procedure RegressionTestInput.Class0.AssignToInParam$System.Int32($this: Ref, x$in: int) returns ($result: int);
-implementation RegressionTestInput.Class0.AssignToInParam$System.Int32(this: Ref, x$in: int) returns ($result: int)
+implementation RegressionTestInput.Class0.AssignToInParam$System.Int32($this: Ref, x$in: int) returns ($result: int)
{
var x: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 48} true;
@@ -1079,13 +1242,15 @@ implementation RegressionTestInput.Class0.AssignToInParam$System.Int32(this: Ref
-procedure {:RegressionTestInput.Async} RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32(this: Ref, x$in: int) returns ($result: int);
+procedure {:RegressionTestInput.Async} RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32($this: Ref, x$in: int) returns ($result: int);
-implementation RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32(this: Ref, x$in: int) returns ($result: int)
+implementation RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32($this: Ref, x$in: int) returns ($result: int)
{
var x: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 56} true;
@@ -1095,31 +1260,46 @@ implementation RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMetho
-procedure RegressionTestInput.Class0.CallAsyncMethod$System.Int32(this: Ref, y$in: int) returns ($result: int);
+procedure RegressionTestInput.Class0.CallAsyncMethod$System.Int32($this: Ref, y$in: int) returns ($result: int);
-implementation RegressionTestInput.Class0.CallAsyncMethod$System.Int32(this: Ref, y$in: int) returns ($result: int)
+implementation RegressionTestInput.Class0.CallAsyncMethod$System.Int32($this: Ref, y$in: int) returns ($result: int)
{
var y: int;
- var $tmp8: int;
+ var $tmp6: int;
+ var $localExc: Ref;
+ var $label: int;
y := y$in;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 60} true;
- call {:async} $tmp8 := RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32(this, y);
- $result := $tmp8;
+ call {:async} $tmp6 := RegressionTestInput.Class0.MethodThatRepresentsAnAynchronousMethod$System.Int32($this, y);
+ if ($Exception != null)
+ {
+ return;
+ }
+
+ $result := $tmp6;
return;
}
-procedure RegressionTestInput.Class0.#ctor(this: Ref);
+procedure RegressionTestInput.Class0.#ctor($this: Ref);
-implementation RegressionTestInput.Class0.#ctor(this: Ref)
+implementation RegressionTestInput.Class0.#ctor($this: Ref)
{
- call System.Object.#ctor(this);
+ var $localExc: Ref;
+ var $label: int;
+
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
return;
}
@@ -1136,7 +1316,7 @@ implementation RegressionTestInput.Class0.#cctor()
-const unique RegressionTestInput.ClassWithBoolTypes: Type;
+const unique RegressionTestInput.ClassWithBoolTypes: Type extends unique System.Object;
var RegressionTestInput.ClassWithBoolTypes.staticB: bool;
@@ -1150,6 +1330,8 @@ implementation RegressionTestInput.ClassWithBoolTypes.M$System.Int32$System.Int3
{
var x: int;
var y: int;
+ var $localExc: Ref;
+ var $label: int;
x := x$in;
y := y$in;
@@ -1160,20 +1342,27 @@ implementation RegressionTestInput.ClassWithBoolTypes.M$System.Int32$System.Int3
-procedure RegressionTestInput.ClassWithBoolTypes.#ctor$System.Boolean(this: Ref, z$in: bool);
+procedure RegressionTestInput.ClassWithBoolTypes.#ctor$System.Boolean($this: Ref, z$in: bool);
-implementation RegressionTestInput.ClassWithBoolTypes.#ctor$System.Boolean(this: Ref, z$in: bool)
+implementation RegressionTestInput.ClassWithBoolTypes.#ctor$System.Boolean($this: Ref, z$in: bool)
{
var z: bool;
+ var $localExc: Ref;
+ var $label: int;
z := z$in;
- RegressionTestInput.ClassWithBoolTypes.b[this] := false;
+ RegressionTestInput.ClassWithBoolTypes.b[$this] := false;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 72} true;
- call System.Object.#ctor(this);
+ call System.Object.#ctor($this);
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 73} true;
- RegressionTestInput.ClassWithBoolTypes.b[this] := z;
+ RegressionTestInput.ClassWithBoolTypes.b[$this] := z;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 74} true;
if (z)
{
@@ -1195,10 +1384,17 @@ procedure RegressionTestInput.ClassWithBoolTypes.Main();
implementation RegressionTestInput.ClassWithBoolTypes.Main()
{
- var $tmp9: bool;
+ var $tmp7: bool;
+ var $localExc: Ref;
+ var $label: int;
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 78} true;
- call $tmp9 := RegressionTestInput.ClassWithBoolTypes.M$System.Int32$System.Int32(3, 4);
+ call $tmp7 := RegressionTestInput.ClassWithBoolTypes.M$System.Int32$System.Int32(3, 4);
+ if ($Exception != null)
+ {
+ return;
+ }
+
assert {:sourceFile "C:\dev\BoogieCodePlex\BCT\RegressionTests\RegressionTestInput\Class1.cs"} {:sourceLine 79} true;
return;
}
diff --git a/BCT/RegressionTests/TranslationTest/UnitTest0.cs b/BCT/RegressionTests/TranslationTest/UnitTest0.cs
index 99b6e680..94fdcba8 100644
--- a/BCT/RegressionTests/TranslationTest/UnitTest0.cs
+++ b/BCT/RegressionTests/TranslationTest/UnitTest0.cs
@@ -61,7 +61,7 @@ namespace TranslationTest {
#endregion
private string ExecuteTest(string assemblyName, HeapFactory heapFactory) {
- BCT.TranslateAssembly(new List<string>{assemblyName}, heapFactory, null, false, null);
+ BCT.TranslateAssembly(new List<string>{assemblyName}, heapFactory, null, false, null, null);
var fileName = Path.ChangeExtension(assemblyName, "bpl");
var s = File.ReadAllText(fileName);
return s;
diff --git a/BCT/TranslationPlugins/PhoneControlsPlugin.cs b/BCT/TranslationPlugins/PhoneControlsPlugin.cs
new file mode 100644
index 00000000..8c7294ec
--- /dev/null
+++ b/BCT/TranslationPlugins/PhoneControlsPlugin.cs
@@ -0,0 +1,237 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+
+namespace TranslationPlugins {
+ public enum Visibility { Visible, Collapsed };
+
+ public enum Event { Click, Checked, Unchecked };
+
+ public class HandlerSignature {
+ public static string[] getParameterTypesForHandler(Event controlEvent) {
+ switch (controlEvent) {
+ case Event.Checked:
+ case Event.Unchecked:
+ case Event.Click:
+ return new string[] { "object", "System.WindowsRoutedventArgs" };
+ default:
+ throw new NotImplementedException("Handlers for event: " + controlEvent + " not supported yet");
+ }
+ }
+ // TODO it would be nice to be dynamic on handler names and parameters
+ // TODO for now you just have to know the handler signature for each event at load time, and for now we only handle a handful of default control events
+ public string Name;
+ public string[] ParameterTypes;
+ }
+
+ public class ControlInfoStructure {
+ public string Name;
+ public string ClassName;
+ public bool IsEnabled;
+ public Visibility Visible;
+ private IDictionary<Event, IList<HandlerSignature>> handlers;
+
+ public ControlInfoStructure() {
+ handlers = new Dictionary<Event, IList<HandlerSignature>>();
+ }
+
+ public void setHandler(Event p, string handler) {
+ IList<HandlerSignature> eventHandlers;
+ try {
+ eventHandlers = handlers[p];
+ } catch (KeyNotFoundException) {
+ eventHandlers= new List<HandlerSignature>();
+ }
+
+ HandlerSignature newHandler= new HandlerSignature();
+ newHandler.Name= handler;
+ newHandler.ParameterTypes= HandlerSignature.getParameterTypesForHandler(p);
+ eventHandlers.Add(newHandler);
+ }
+
+ public IList<HandlerSignature> getHandlers(Event p) {
+ try {
+ return handlers[p];
+ } catch (KeyNotFoundException) {
+ return new List<HandlerSignature>();
+ }
+ }
+ }
+
+ class PageStructure {
+ public PageStructure() {
+ controlsInfo = new Dictionary<string, ControlInfoStructure>();
+ }
+
+ public string PageClassName { get; set; }
+ public string PageXAML { get; set; }
+ public bool IsMainPage { get; set; }
+
+ private IDictionary<string, ControlInfoStructure> controlsInfo;
+ public ControlInfoStructure getControlInfo(string controlName) {
+ try {
+ return controlsInfo[controlName];
+ } catch (KeyNotFoundException) {
+ return null;
+ }
+ }
+
+ public void setControlInfo(string controlName, ControlInfoStructure controlInfo) {
+ controlsInfo[controlName] = controlInfo;
+ }
+
+ public IEnumerable<ControlInfoStructure> getAllControlsInfo() {
+ return controlsInfo.Values.AsEnumerable();
+ }
+ }
+
+ public class PhoneControlsPlugin : TranslationPlugin {
+ // TODO this will probably need a complete rewrite once it is event based, and make it more push than pull
+ // TODO but it doesn't make sense right now to make it BCT or CCI aware
+ private static int CONFIG_LINE_FIELDS= 9;
+ private static int PAGE_CLASS_FIELD= 0;
+ private static int PAGE_XAML_FIELD= 1;
+ private static int CONTROL_CLASS_FIELD= 2;
+ private static int CONTROL_NAME_FIELD= 3;
+ private static int ENABLED_FIELD= 4;
+ private static int VISIBILITY_FIELD= 5;
+ private static int CLICK_HANDLER_FIELD= 6;
+ private static int CHECKED_HANDLER_FIELD= 7;
+ private static int UNCHECKED_HANDLER_FIELD = 8;
+
+ private IDictionary<string, PageStructure> pageStructureInfo;
+
+ public static string getFullyQualifiedControlClass(string controlClass) {
+ // TODO do an actual API discovery. The problem will be differencing 7.0 apps from 7.1 apps
+ return "System.Windows.Controls." + controlClass;
+ }
+
+ public PhoneControlsPlugin(string configFile) {
+ pageStructureInfo = new Dictionary<string, PageStructure>();
+ StreamReader fileStream = null;
+ try {
+ fileStream = new StreamReader(configFile);
+ } catch (Exception e) {
+ if (e is DirectoryNotFoundException || e is FileNotFoundException || e is IOException) {
+ // TODO log, I don't want to terminate BCT because of this
+ } else if (e is ArgumentException || e is ArgumentNullException) {
+ // TODO log, I don't want to terminate BCT because of this
+ } else {
+ throw;
+ }
+ }
+
+ LoadControlStructure(fileStream);
+
+ if (fileStream != null)
+ fileStream.Close();
+ }
+
+ public string getMainPageXAML() {
+ KeyValuePair<string, PageStructure> entry= pageStructureInfo.FirstOrDefault(keyValue => keyValue.Value.IsMainPage);
+ return entry.Value.PageXAML;
+ }
+
+ private void setPageAsMainPage(string pageXAML) {
+ KeyValuePair<string,PageStructure> mainPageClass= pageStructureInfo.FirstOrDefault(keyValue => keyValue.Value.PageXAML == pageXAML);
+ if (mainPageClass.Equals(default(KeyValuePair<string, PageStructure>))) {
+ // do nothing. Pre is page was already parsed
+ } else {
+ mainPageClass.Value.IsMainPage = true;
+ }
+ }
+
+ private void LoadControlStructure(StreamReader configStream) {
+ // TODO it would be nice to have some kind of dynamic definition of config format
+ // TODO for now remember that config format is CSV
+ // TODO each line is <pageClassName>,<pageXAMLPath>,<controlClassName>,<controlName>,<IsEnabledValue>,<VisibilityValue>,<ClickValue>,<CheckedValue>,<UncheckedValue>
+ // TODO check PhoneControlsExtractor.py
+
+ // TODO the page.xaml value is saved with no directory information: if two pages exist with same name but different directories it will treat them as the same
+ // TODO I'm not handling this for now, and I won't be handling relative/absolute URI either for now
+
+ try {
+ string pageClass, pageXAML, controlClass, controlName, enabled, visibility, clickHandler, checkedHandler, uncheckedHandler;
+ string configLine = configStream.ReadLine();
+ string[] inputLine;
+ PageStructure pageStr;
+ ControlInfoStructure controlInfoStr;
+
+ // first line just states the main page xaml
+ string mainPage = configLine.Trim();
+ configLine = configStream.ReadLine();
+
+ while (configLine != null) {
+ inputLine = configLine.Split(',');
+
+ if (inputLine.Length != CONFIG_LINE_FIELDS)
+ throw new ArgumentException("Config input line contains wrong number of fields: " + inputLine.Length + ", expected " + CONFIG_LINE_FIELDS);
+
+ pageClass = inputLine[PAGE_CLASS_FIELD];
+ pageXAML = inputLine[PAGE_XAML_FIELD];
+ controlClass = inputLine[CONTROL_CLASS_FIELD];
+ controlName = inputLine[CONTROL_NAME_FIELD];
+ enabled = inputLine[ENABLED_FIELD];
+ visibility = inputLine[VISIBILITY_FIELD];
+ clickHandler = inputLine[CLICK_HANDLER_FIELD];
+ checkedHandler = inputLine[CHECKED_HANDLER_FIELD];
+ uncheckedHandler = inputLine[UNCHECKED_HANDLER_FIELD];
+
+ try {
+ pageStr = pageStructureInfo[pageClass];
+ } catch (KeyNotFoundException) {
+ pageStr = new PageStructure();
+ pageStr.PageClassName = pageClass;
+ pageStr.PageXAML = pageXAML;
+ pageStr.IsMainPage = false;
+ }
+
+ controlInfoStr= pageStr.getControlInfo(controlName);
+ if (controlInfoStr == null) {
+ controlInfoStr = new ControlInfoStructure();
+ controlInfoStr.Name = controlName;
+ controlInfoStr.ClassName = controlClass;
+ }
+ controlInfoStr.IsEnabled = Boolean.Parse(enabled);
+ controlInfoStr.Visible = visibility == "Collapsed" ? Visibility.Collapsed : Visibility.Visible;
+ controlInfoStr.setHandler(Event.Click, clickHandler);
+ controlInfoStr.setHandler(Event.Checked, checkedHandler);
+ controlInfoStr.setHandler(Event.Unchecked, uncheckedHandler);
+
+ pageStr.setControlInfo(controlName, controlInfoStr);
+ pageStructureInfo[pageClass] = pageStr;
+ configLine = configStream.ReadLine();
+
+ setPageAsMainPage(mainPage);
+ }
+ } catch (Exception) {
+ // TODO log, I don't want to terminate BCT because of this
+ }
+ }
+
+ public IEnumerable<ControlInfoStructure> getControlsForPage(string pageClass) {
+ return pageStructureInfo[pageClass].getAllControlsInfo();
+ }
+
+ public string getXAMLForPage(string pageClass) {
+ return pageStructureInfo[pageClass].PageXAML;
+ }
+
+ public bool getIsEnabled(string pageClass, string controlName) {
+ return pageStructureInfo[pageClass].getControlInfo(controlName).IsEnabled;
+ }
+
+ public Visibility getVisibility(string pageClass, string controlName) {
+ return pageStructureInfo[pageClass].getControlInfo(controlName).Visible;
+ }
+
+ public IList<HandlerSignature> getHandlers(string pageClass, string controlName, string eventName) {
+ if (eventName != "Checked" && eventName != "Unchecked" && eventName != "Click")
+ throw new NotImplementedException("Event " + eventName + " is not translated or defined for control " + controlName + " in page " + pageClass);
+
+ return pageStructureInfo[pageClass].getControlInfo(controlName).getHandlers((Event) Event.Parse(typeof(Event), eventName));
+ }
+ }
+}
diff --git a/BCT/TranslationPlugins/Properties/AssemblyInfo.cs b/BCT/TranslationPlugins/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..8158eb08
--- /dev/null
+++ b/BCT/TranslationPlugins/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TranslationPlugins")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("TranslationPlugins")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c26f68f2-14fb-4a47-8707-b7de569865cc")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/BCT/TranslationPlugins/TranslationPlugin.cs b/BCT/TranslationPlugins/TranslationPlugin.cs
new file mode 100644
index 00000000..e8907a09
--- /dev/null
+++ b/BCT/TranslationPlugins/TranslationPlugin.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TranslationPlugins {
+ public class TranslationPlugin {
+ // TODO ideally these should really work as plugins, possibly registering as callbacks to some BCT events.
+ }
+}
diff --git a/BCT/TranslationPlugins/TranslationPlugins.csproj b/BCT/TranslationPlugins/TranslationPlugins.csproj
new file mode 100644
index 00000000..9a27e949
--- /dev/null
+++ b/BCT/TranslationPlugins/TranslationPlugins.csproj
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8C242D42-9714-440F-884D-F64F09E78C7B}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>TranslationPlugins</RootNamespace>
+ <AssemblyName>TranslationPlugins</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="PhoneControlsPlugin.cs" />
+ <Compile Include="TranslationPlugin.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Binaries/DafnyPrelude.bpl b/Binaries/DafnyPrelude.bpl
index 94a8833a..dc152185 100644
--- a/Binaries/DafnyPrelude.bpl
+++ b/Binaries/DafnyPrelude.bpl
@@ -373,12 +373,12 @@ var $Tick: TickType;
// the connection between % and /
axiom (forall x:int, y:int :: {x % y} {x / y} x % y == x - x / y * y);
-// sign of denominator determines sign of remainder
+// remainder is always Euclidean Modulus.
axiom (forall x:int, y:int :: {x % y} 0 < y ==> 0 <= x % y && x % y < y);
-axiom (forall x:int, y:int :: {x % y} y < 0 ==> y < x % y && x % y <= 0);
+axiom (forall x:int, y:int :: {x % y} y < 0 ==> 0 <= x % y && x % y < -y);
// the following axiom has some unfortunate matching, but it does state a property about % that
-// is sometime useful
+// is sometimes useful
axiom (forall a: int, b: int, d: int :: { a % d, b % d } 2 <= d && a % d == b % d && a < b ==> a + d <= b);
// ---------------------------------------------------------------
diff --git a/Binaries/DafnyRuntime.cs b/Binaries/DafnyRuntime.cs
index 46a3f3df..c03ac643 100644
--- a/Binaries/DafnyRuntime.cs
+++ b/Binaries/DafnyRuntime.cs
@@ -267,5 +267,41 @@ namespace Dafny
yield return true;
}
}
+ // pre: b != 0
+ // post: result == a/b, as defined by Euclidean Division (http://en.wikipedia.org/wiki/Modulo_operation)
+ public static BigInteger EuclideanDivision(BigInteger a, BigInteger b) {
+ if (0 <= a.Sign) {
+ if (0 <= b.Sign) {
+ // +a +b: a/b
+ return BigInteger.Divide(a, b);
+ } else {
+ // +a -b: -(a/(-b))
+ return BigInteger.Negate(BigInteger.Divide(a, BigInteger.Negate(b)));
+ }
+ } else {
+ if (0 <= b.Sign) {
+ // -a +b: -((-a-1)/b) - 1
+ return BigInteger.Negate(BigInteger.Divide(BigInteger.Negate(a) - 1, b)) - 1;
+ } else {
+ // -a -b: ((-a-1)/(-b)) + 1
+ return BigInteger.Divide(BigInteger.Negate(a) - 1, BigInteger.Negate(b)) + 1;
+ }
+ }
+ }
+ // pre: b != 0
+ // post: result == a%b, as defined by Euclidean Division (http://en.wikipedia.org/wiki/Modulo_operation)
+ public static BigInteger EuclideanModulus(BigInteger a, BigInteger b) {
+ var bp = BigInteger.Abs(b);
+ if (0 <= a.Sign) {
+ // +a: a % b'
+ return BigInteger.Remainder(a, bp);
+ } else {
+ // c = ((-a) % b')
+ // -a: b' - c if c > 0
+ // -a: 0 if c == 0
+ var c = BigInteger.Remainder(BigInteger.Negate(a), bp);
+ return c.IsZero ? c : BigInteger.Subtract(bp, c);
+ }
+ }
}
}
diff --git a/Chalice/src/Parser.scala b/Chalice/src/Parser.scala
index f8824cee..4800b552 100644
--- a/Chalice/src/Parser.scala
+++ b/Chalice/src/Parser.scala
@@ -79,23 +79,32 @@ class Parser extends StandardTokenParsers {
*/
def memberDecl = {
- currentLocalVariables = Set[String]();
positioned(fieldDecl | invariantDecl | methodDecl | conditionDecl | predicateDecl | functionDecl | couplingDecl | transformDecl) // important that last one is transformDecl
}
- def fieldDecl =
- ( "var" ~> idType <~ Semi ^^ { case (id,t) => Field(id.v, t, false) }
- | "ghost" ~> "var" ~> idType <~ Semi ^^ { case (id,t) => Field(id.v, t, true) }
- )
- def invariantDecl = "invariant" ~> expression <~ Semi ^^ MonitorInvariant
- def methodDecl =
+ def fieldDecl = {
+ currentLocalVariables = Set[String]();
+ ( "var" ~> idType <~ Semi ^^ { case (id,t) => Field(id.v, t, false) }
+ | "ghost" ~> "var" ~> idType <~ Semi ^^ { case (id,t) => Field(id.v, t, true) }
+ )
+ }
+ def invariantDecl = {
+ currentLocalVariables = Set[String]();
+ "invariant" ~> expression <~ Semi ^^ MonitorInvariant
+ }
+ def methodDecl = {
+ currentLocalVariables = Set[String]();
"method" ~> ident ~ formalParameters(true) ~ ("returns" ~> formalParameters(false) ?) ~
(methodSpec*) ~ blockStatement ^^ {
case id ~ ins ~ outs ~ spec ~ body =>
Method(id, ins, outs match {case None => Nil; case Some(outs) => outs}, spec, body)
}
- def predicateDecl: Parser[Predicate] =
+ }
+ def predicateDecl: Parser[Predicate] = {
+ currentLocalVariables = Set[String]();
("predicate" ~> ident) ~ ("{" ~> expression <~ "}") ^^ { case id ~ definition => Predicate(id, definition) }
- def functionDecl =
+ }
+ def functionDecl = {
+ currentLocalVariables = Set[String]();
("unlimited" ?) ~ ("function" ~> ident) ~ formalParameters(true) ~ (":" ~> typeDecl) ~ (methodSpec*) ~ opt("{" ~> expression <~ "}") ^^ {
case u ~ id ~ ins ~ out ~ specs ~ body => {
val f = Function(id, ins, out, specs, body);
@@ -103,10 +112,14 @@ class Parser extends StandardTokenParsers {
f
}
}
- def conditionDecl =
+ }
+ def conditionDecl = {
+ currentLocalVariables = Set[String]();
"condition" ~> ident ~ ("where" ~> expression ?) <~ Semi ^^ {
case id ~ optE => Condition(id, optE) }
- def transformDecl =
+ }
+ def transformDecl = {
+ currentLocalVariables = Set[String]();
( "refines" ~> ident ~ formalParameters(true) ~ ("returns" ~> formalParameters(false) ?) ~ (methodSpec*) ~ blockStatement ^^ {
case id ~ ins ~outs ~ spec ~ body =>
MethodTransform(id, ins, outs match {case None => Nil; case Some(outs) => outs}, spec, ProgramPat(body)) }).|(
@@ -118,7 +131,11 @@ class Parser extends StandardTokenParsers {
MethodTransform(id, ins, outs match {case None => Nil; case Some(outs) => outs}, spec, AST.normalize(trans))
}
})
- def couplingDecl = ("replaces" ~> rep1sep(ident, ",") <~ "by") ~ expression <~ Semi ^^ {case ids ~ e => CouplingInvariant(ids, e)}
+ }
+ def couplingDecl = {
+ currentLocalVariables = Set[String]();
+ ("replaces" ~> rep1sep(ident, ",") <~ "by") ~ expression <~ Semi ^^ {case ids ~ e => CouplingInvariant(ids, e)}
+ }
def formalParameters(immutable: Boolean) =
"(" ~> (formalList(immutable) ?) <~ ")" ^^ {
@@ -370,6 +387,9 @@ class Parser extends StandardTokenParsers {
def expressionList =
repsep(expression, ",")
def expression = positioned(iteExpr)
+
+ def partialExpressionList =
+ repsep(expression | ("_" ^^^ VariableExpr("?")), ",")
def iteExpr: Parser[Expression] =
positioned(iffExpr ~ (("?" ~> iteExpr) ~ (":" ~> iteExpr) ?) ^^ {
@@ -442,7 +462,7 @@ class Parser extends StandardTokenParsers {
case name ~ Some(es) => { e0: Expression => FunctionApplication(e0, name, es) } }
| "." ~> "acquire" ~> exprBody ^^ { case eb => { e0: Expression => Eval(AcquireState(e0), eb) }}
| "." ~> "release" ~> exprBody ^^ { case eb => { e0: Expression => Eval(ReleaseState(e0), eb) }}
- | "." ~> "fork" ~> (callTarget ~ expressionList <~ ")") ~ exprBody ^^ {
+ | "." ~> "fork" ~> (callTarget ~ partialExpressionList <~ ")") ~ exprBody ^^ {
case MemberAccess(obj,id) ~ args ~ eb => { e0: Expression => Eval(CallState(e0, obj, id, args), eb) }}
)
def exprBody =
@@ -583,7 +603,7 @@ class Parser extends StandardTokenParsers {
(suffixExpr <~ ".") into { e =>
( "acquire" ^^^ AcquireState(e)
| "release" ^^^ ReleaseState(e)
- | "fork" ~> callTarget ~ expressionList <~ ")" ^^ {
+ | "fork" ~> callTarget ~ partialExpressionList <~ ")" ^^ {
case MemberAccess(obj,id) ~ args => CallState(e, obj, id, args) }
)}
diff --git a/Chalice/src/Resolver.scala b/Chalice/src/Resolver.scala
index efb19700..a8bdce62 100644
--- a/Chalice/src/Resolver.scala
+++ b/Chalice/src/Resolver.scala
@@ -1128,7 +1128,10 @@ object Resolver {
if( ! token.typ.IsToken) context.Error(token.pos, "joinable is only applicable to tokens");
ResolveExpr(obj, context, false, false)
CheckNoGhost(obj, context)
- args foreach { a => ResolveExpr(a, context, false, false); CheckNoGhost(a, context) }
+ args foreach { a => a match {
+ case VariableExpr("?") =>
+ case _ => ResolveExpr(a, context, false, false); CheckNoGhost(a, context)
+ }}
// lookup method
var typ: Class = IntClass
obj.typ.LookupMember(id) match {
@@ -1141,8 +1144,12 @@ object Resolver {
" (" + args.length + " instead of " + m.ins.length + ")")
else {
for((actual, formal) <- args zip m.ins){
- if(! canAssign(formal.t.typ, actual.typ))
- context.Error(actual.pos, "the type of the actual argument is not assignable to the formal parameter (expected: " + formal.t.FullName + ", found: " + actual.typ.FullName + ")")
+ actual match {
+ case VariableExpr("?") =>
+ case _ => if (!canAssign(formal.t.typ, actual.typ))
+ context.Error(actual.pos, "the type of the actual argument is not assignable to the formal parameter (expected: " + formal.t.FullName + ", found: " + actual.typ.FullName + ")")
+ }
+
}
}
case _ => context.Error(obj.pos, "call expression does not denote a method: " + obj.typ.FullName + "." + id)
diff --git a/Chalice/src/Translator.scala b/Chalice/src/Translator.scala
index 552fa906..8a9c690f 100644
--- a/Chalice/src/Translator.scala
+++ b/Chalice/src/Translator.scala
@@ -1751,10 +1751,10 @@ class ExpressionTranslator(globals: List[Boogie.Expr], preGlobals: List[Boogie.E
}
def Inhale(p: Expression, ih: Boogie.Expr, check: Boolean, currentK: Expr): List[Boogie.Stmt] = desugar(p) match {
- case pred@MemberAccess(e, p) if pred.isPredicate =>
- val chk = (if (check) {
- isDefined(e)(true) :::
- bassert(nonNull(Tr(e)), e.pos, "Receiver might be null.") :: Nil
+ case pred@MemberAccess(e, p) if pred.isPredicate =>
+ val chk = (if (check) {
+ isDefined(e)(true) :::
+ bassert(nonNull(Tr(e)), e.pos, "Receiver might be null.") :: Nil
} else Nil)
val tmp = Access(pred, Full);
tmp.pos = pred.pos;
@@ -1903,13 +1903,13 @@ class ExpressionTranslator(globals: List[Boogie.Expr], preGlobals: List[Boogie.E
stmts :::
(perm.permissionType match {
case PermissionType.Mixed =>
- bassert(f > 0 || (f == 0 && n > 0), error.pos, error.message + " The permission at " + perm.pos + " might not be positive.") ::
+ bassert(f > 0 || (f == 0 && n > 0), error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
DecPermissionBoth(obj, memberName, f, n, em, error, pos, ec)
case PermissionType.Epsilons =>
- bassert(n > 0, error.pos, error.message + " The permission at " + perm.pos + " might not be positive.") ::
+ bassert(n > 0, error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
DecPermissionEpsilon(obj, memberName, n, em, error, pos)
case PermissionType.Fraction =>
- bassert(f > 0, error.pos, error.message + " The permission at " + perm.pos + " might not be positive.") ::
+ bassert(f > 0, error.pos, error.message + " The permission at " + pos + " might not be positive.") ::
DecPermission(obj, memberName, f, em, error, pos, ec)
})
}
@@ -2124,6 +2124,14 @@ class ExpressionTranslator(globals: List[Boogie.Expr], preGlobals: List[Boogie.E
case CallState(token, obj, id, args) =>
val argsSeq = CallArgs(Heap.select(Tr(token), "joinable"));
+ var f: ((Expression, Int)) => Expr =
+ (a: (Expression, Int)) => a match {
+ case (VariableExpr("?"),_) => true: Expr
+ case _ => new MapSelect(argsSeq, a._2) ==@ Tr(a._1)
+ }
+ var ll: List[(Expression, Int)] = null
+ ll = (args zip (1 until args.length+1).toList);
+
var i = 0;
(CallHeap(Heap.select(Tr(token), "joinable")),
CallMask(Heap.select(Tr(token), "joinable")),
@@ -2134,7 +2142,9 @@ class ExpressionTranslator(globals: List[Boogie.Expr], preGlobals: List[Boogie.E
bassert(CanRead(Tr(token), "joinable"), obj.pos, "Joinable field of the token might not be readable.") ::
bassert(Heap.select(Tr(token), "joinable") !=@ 0, obj.pos, "Token might not be active."),
(new MapSelect(argsSeq, 0) ==@ Tr(obj) ) &&
- (((args zip (1 until args.length+1).toList) map { a => new MapSelect(argsSeq, a._2) ==@ Tr(a._1)}).foldLeft(true: Expr){ (a: Expr, b: Expr) => a && b})
+ ((ll map {
+ f
+ }).foldLeft(true: Expr){ (a: Expr, b: Expr) => a && b})
)
}
}
diff --git a/Chalice/tests/examples/Solver.chalice b/Chalice/tests/examples/Solver.chalice
new file mode 100644
index 00000000..0de8a987
--- /dev/null
+++ b/Chalice/tests/examples/Solver.chalice
@@ -0,0 +1,44 @@
+class Client {
+
+ method main(p: Problem, s: Solver) returns (r: int)
+ requires acc(p.f) && s != null
+ ensures acc(p.f)
+ {
+ // start randomized computations
+ var tk1: token<Solver.solve>
+ var tk2: token<Solver.solve>
+ call tk1 := s.start(p)
+ call tk2 := s.start(p)
+
+ // get the results
+ var r1: int
+ join r1 := tk1
+ var r2: int
+ join r2:= tk2
+ r := r1 > r2 ? r1 : r2
+ }
+
+}
+class Solver {
+
+ method solve(p: Problem, d: Data) returns (r: int)
+ requires rd(p.f)
+ requires acc(d.*)
+ ensures rd(p.f)
+ { /* ... */ }
+
+ method start(p: Problem)
+ returns (tk: token<Solver.solve>)
+ requires rd(p.f)
+ ensures acc(p.f, rd-rd(tk))
+ ensures acc(tk.joinable) && tk.joinable;
+ ensures eval(tk.fork this.solve(p,_), true)
+ {
+ var d: Data := new Data
+ /* .. perform some set-up/initialization and prepare the data d for the solve method */
+ fork tk := solve(p, d)
+ }
+
+}
+class Problem { var f: int }
+class Data { var f: int; var g: int }
diff --git a/Chalice/tests/examples/Solver.output.txt b/Chalice/tests/examples/Solver.output.txt
new file mode 100644
index 00000000..e88f63d9
--- /dev/null
+++ b/Chalice/tests/examples/Solver.output.txt
@@ -0,0 +1,4 @@
+Verification of Solver.chalice using parameters=""
+
+
+Boogie program verifier finished with 10 verified, 0 errors
diff --git a/Chalice/tests/permission-model/permission_arithmetic.output.txt b/Chalice/tests/permission-model/permission_arithmetic.output.txt
index afbd9be7..0b2b5335 100644
--- a/Chalice/tests/permission-model/permission_arithmetic.output.txt
+++ b/Chalice/tests/permission-model/permission_arithmetic.output.txt
@@ -1,13 +1,13 @@
Verification of permission_arithmetic.chalice using parameters=""
- 24.5: Assertion might not hold. The permission at 24.18 might not be positive.
- 40.5: The precondition at 33.14 might not hold. The permission at 33.20 might not be positive.
+ 24.5: Assertion might not hold. The permission at 24.12 might not be positive.
+ 40.5: The precondition at 33.14 might not hold. The permission at 33.14 might not be positive.
73.3: The postcondition at 75.13 might not hold. Insufficient fraction at 75.13 for Cell.x.
86.3: The postcondition at 88.13 might not hold. Insufficient epsilons at 88.22 for Cell.x.
103.20: Location might not be readable.
109.20: Location might not be readable.
145.5: Monitor invariant might not hold. Insufficient fraction at 6.13 for Cell.x.
- 162.3: The postcondition at 164.13 might not hold. The permission at 164.19 might not be positive.
+ 162.3: The postcondition at 164.13 might not hold. The permission at 164.13 might not be positive.
174.3: The postcondition at 176.13 might not hold. Insufficient fraction at 176.13 for Cell.x.
Boogie program verifier finished with 47 verified, 9 errors
diff --git a/Chalice/tests/runalltests.bat b/Chalice/tests/runalltests.bat
new file mode 100644
index 00000000..3b0df4a4
--- /dev/null
+++ b/Chalice/tests/runalltests.bat
@@ -0,0 +1,32 @@
+@echo off
+
+setlocal EnableDelayedExpansion
+
+:: no-summary command line parameter
+set nosummary=0
+if "%1"=="-no-summary" (
+ set nosummary=1
+ SHIFT
+)
+
+set t=0
+set c=0
+for %%f in (examples permission-model) do (
+ echo Running tests in %%f ...
+ echo ------------------------------------------------------
+ cd %%f
+ set tt=0
+ for %%f in (*.chalice) do set /A tt+=1
+ call reg_test_all.bat -no-summary
+ set /A c=!c!+!errorlevel!
+ set /A t=!t!+!tt!
+ cd ..
+ echo ------------------------------------------------------
+)
+
+if !nosummary!==0 (
+ echo.
+ if !c!==0 (echo SUMMARY: completed !t! tests successfully.) else (echo SUMMARY: !c! of !t! tests failed.)
+)
+
+exit /b !c!
diff --git a/Chalice/tests/test-scripts/reg_test.bat b/Chalice/tests/test-scripts/reg_test.bat
index 0e5e4dbf..530d1d19 100644
--- a/Chalice/tests/test-scripts/reg_test.bat
+++ b/Chalice/tests/test-scripts/reg_test.bat
@@ -3,6 +3,13 @@ setlocal
set chalice="%~dp0\..\..\chalice.bat"
set diff="%~dp0\diff.bat"
+:: no-diff command line parameter
+set nodiff=0
+if "%1"=="-no-diff" (
+ set nodiff=1
+ SHIFT
+)
+
if not exist "%1.chalice" goto errorNotFound
if not exist "%1.output.txt" goto errorNoRef
@@ -40,7 +47,9 @@ goto end
:failTest
echo FAIL: %1.chalice
-call %diff% "%1.output.txt" output.txt
+if %nodiff%==0 (
+ call %diff% "%1.output.txt" output.txt
+)
goto errorEnd
:errorEnd
diff --git a/Chalice/tests/test-scripts/reg_test_all.bat b/Chalice/tests/test-scripts/reg_test_all.bat
index 6bbac775..23aca316 100644
--- a/Chalice/tests/test-scripts/reg_test_all.bat
+++ b/Chalice/tests/test-scripts/reg_test_all.bat
@@ -1,9 +1,24 @@
@echo off
-set regtest="%~dp0\reg_test.bat"
+setlocal EnableDelayedExpansion
-for /F %%f in ('dir *.chalice /b') do (
- call %regtest% %%~nf %1 %2 %3 %4 %5 %6 %7 %8
+:: no-summary command line parameter
+set nosummary=0
+if "%1"=="-no-summary" (
+ set nosummary=1
+ SHIFT /1
)
-exit /b 0
+set regtest="%~dp0\reg_test.bat"
+set t=0
+set c=0
+for /F %%f in ('dir *.chalice /b') do (
+ call %regtest% -no-diff %%~nf %1 %2 %3 %4 %5 %6 %7 %8
+ set /A c=!c!+!errorlevel!
+ set /A t=!t!+1
+)
+if !nosummary!==0 (
+ echo.
+ if !c!==0 (echo SUMMARY: completed !t! tests successfully.) else (echo SUMMARY: failed !c! of !t! tests.)
+)
+exit /b !c!
diff --git a/Jennisys/Jennisys.sln b/Jennisys/Jennisys.sln
index bb45d27c..af8d8f4a 100644
--- a/Jennisys/Jennisys.sln
+++ b/Jennisys/Jennisys.sln
@@ -2,15 +2,9 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Jennisys", "Jennisys\Jennisys.fsproj", "{F2FF4B3A-2FE8-474A-88DF-6950F7D78908}"
- ProjectSection(ProjectDependencies) = postProject
- {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83} = {ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C} = {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}
- EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "..\Source\Model\Model.csproj", "{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelViewer", "..\Source\ModelViewer\ModelViewer.csproj", "{A678C6EB-B329-46A9-BBFC-7585F01ACD7C}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Checked|Any CPU = Checked|Any CPU
@@ -54,21 +48,6 @@ Global
{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}.Release|x86.ActiveCfg = Release|Any CPU
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Any CPU.ActiveCfg = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Mixed Platforms.ActiveCfg = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|Mixed Platforms.Build.0 = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|x86.ActiveCfg = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Checked|x86.Build.0 = Checked|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Any CPU.ActiveCfg = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|Mixed Platforms.Build.0 = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|x86.ActiveCfg = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Debug|x86.Build.0 = Debug|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Any CPU.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Mixed Platforms.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|Mixed Platforms.Build.0 = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|x86.ActiveCfg = Release|x86
- {A678C6EB-B329-46A9-BBFC-7585F01ACD7C}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Jennisys/Jennisys/Analyzer.fs b/Jennisys/Jennisys/Analyzer.fs
index 244b50b4..9603dd6e 100644
--- a/Jennisys/Jennisys/Analyzer.fs
+++ b/Jennisys/Jennisys/Analyzer.fs
@@ -1,295 +1,448 @@
-module Analyzer
-
-open Ast
-open AstUtils
-open CodeGen
-open DafnyModelUtils
-open PipelineUtils
-open Options
-open Printer
-open Resolver
-open DafnyPrinter
-open Utils
-
-open Microsoft.Boogie
-
-let VarsAreDifferent aa bb =
- printf "false"
- List.iter2 (fun (_,Var(a,_)) (_,Var(b,_)) -> printf " || %s != %s" a b) aa bb
-
-let Rename suffix vars =
- vars |> List.map (function Var(nm,tp) -> nm, Var(nm + suffix, tp))
-
-let ReplaceName substMap nm =
- match Map.tryFind nm substMap with
- | Some(Var(name, tp)) -> name
- | None -> nm
-
-let rec Substitute substMap = function
- | IdLiteral(s) -> IdLiteral(ReplaceName substMap s)
- | Dot(e,f) -> Dot(Substitute substMap e, ReplaceName substMap f)
- | UnaryExpr(op,e) -> UnaryExpr(op, Substitute substMap e)
- | BinaryExpr(n,op,e0,e1) -> BinaryExpr(n, op, Substitute substMap e0, Substitute substMap e1)
- | SelectExpr(e0,e1) -> SelectExpr(Substitute substMap e0, Substitute substMap e1)
- | UpdateExpr(e0,e1,e2) -> UpdateExpr(Substitute substMap e0, Substitute substMap e1, Substitute substMap e2)
- | SequenceExpr(ee) -> SequenceExpr(List.map (Substitute substMap) ee)
- | SeqLength(e) -> SeqLength(Substitute substMap e)
- | ForallExpr(vv,e) -> ForallExpr(vv, Substitute substMap e)
- | expr -> expr
-
-let GenMethodAnalysisCode comp methodName signature pre post assertion =
- " method " + methodName + "()" + newline +
- " modifies this;" + newline +
- " {" + newline +
- // print signature as local variables
- (match signature with
- | Sig(ins,outs) ->
- List.concat [ins; outs] |> List.fold (fun acc vd -> acc + (sprintf " var %s;" (PrintVarDecl vd)) + newline) "") +
- " // assume precondition" + newline +
- " assume " + (PrintExpr 0 pre) + ";" + newline +
- " // assume invariant and postcondition" + newline +
- " assume Valid();" + newline +
- " assume " + (PrintExpr 0 post) + ";" + newline +
- " // assume user defined invariant again because assuming Valid() doesn't always work" + newline +
- (GetInvariantsAsList comp |> PrintSep newline (fun e -> " assume " + (PrintExpr 0 e) + ";")) + newline +
- // if the following assert fails, the model hints at what code to generate; if the verification succeeds, an implementation would be infeasible
- " // assert false to search for a model satisfying the assumed constraints" + newline +
- " assert " + (PrintExpr 0 assertion) + ";" + newline +
- " }" + newline
-
-let MethodAnalysisPrinter onlyForThisCompMethod assertion comp mthd =
- match onlyForThisCompMethod with
- | (c,m) when c = comp && m = mthd ->
- match m with
- | Method(methodName, sign, pre, post, true) -> (GenMethodAnalysisCode comp methodName sign pre post assertion) + newline
- | _ -> ""
- | _ -> ""
-
-let rec IsArgsOnly args expr =
- match expr with
- | IdLiteral(id) -> args |> List.exists (function Var(varName,_) when varName = id -> true | _ -> false)
- | UnaryExpr(_,e) -> IsArgsOnly args e
- | BinaryExpr(_,_,e1,e2) -> (IsArgsOnly args e1) && (IsArgsOnly args e2)
- | Dot(e,_) -> IsArgsOnly args e
- | SelectExpr(e1, e2) -> (IsArgsOnly args e1) && (IsArgsOnly args e2)
- | UpdateExpr(e1, e2, e3) -> (IsArgsOnly args e1) && (IsArgsOnly args e2) && (IsArgsOnly args e3)
- | SequenceExpr(exprs) -> exprs |> List.fold (fun acc e -> acc && (IsArgsOnly args e)) true
- | SeqLength(e) -> IsArgsOnly args e
- | ForallExpr(vars,e) -> IsArgsOnly (List.concat [args; vars]) e
- | IntLiteral(_) -> true
- | Star -> true
-
-let rec GetUnifications expr args (heap,env,ctx) =
- match expr with
- | IntLiteral(_)
- | IdLiteral(_)
- | Star
- | Dot(_)
- | SelectExpr(_) // TODO: handle select expr
- | UpdateExpr(_) // TODO: handle update expr
- | SequenceExpr(_)
- | SeqLength(_)
- | ForallExpr(_) // TODO: handle forall expr
- | UnaryExpr(_) -> Set.empty
- | BinaryExpr(strength,op,e0,e1) ->
- if op = "=" then
- let v0 = Eval e0 (heap,env,ctx)
- let v1 = Eval e1 (heap,env,ctx)
- let argsOnly0 = IsArgsOnly args e0
- let argsOnly1 = IsArgsOnly args e1
- match v0,argsOnly1,argsOnly0,v1 with
- | Some(c0),true,_,_ ->
- Logger.DebugLine (" - adding unification " + (PrintConst c0) + " <--> " + (PrintExpr 0 e1));
- Set.ofList [c0, e1]
- | _,_,true,Some(c1) ->
- Logger.DebugLine (" - adding unification " + (PrintConst c1) + " <--> " + (PrintExpr 0 e0));
- Set.ofList [c1, e0]
- | _ -> Logger.TraceLine (" - couldn't unify anything from " + (PrintExpr 0 expr));
- Set.empty
- else
- GetUnifications e0 args (heap,env,ctx) |> Set.union (GetUnifications e1 args (heap,env,ctx))
-
-let rec GetArgValueUnifications args env =
- match args with
- | Var(name,_) :: rest ->
- match Map.tryFind (VarConst(name)) env with
- | Some(c) ->
- Logger.DebugLine (" - adding unification " + (PrintConst c) + " <--> " + name);
- Set.ofList [c, IdLiteral(name)] |> Set.union (GetArgValueUnifications rest env)
- | None -> failwith ("couldn't find value for argument " + name)
- | [] -> Set.empty
-
-let rec _GetObjRefExpr o (heap,env,ctx) visited =
- if Set.contains o visited then
- None
- else
- let newVisited = Set.add o visited
- let refName = PrintObjRefName o (env,ctx)
- match refName with
- | Exact "this" _ -> Some(IdLiteral(refName))
- | _ ->
- let rec __fff lst =
- match lst with
- | ((o,Var(fldName,_)),l) :: rest ->
- match _GetObjRefExpr o (heap,env,ctx) newVisited with
- | Some(expr) -> Some(Dot(expr, fldName))
- | None -> __fff rest
- | [] -> None
- let backPointers = heap |> Map.filter (fun (_,_) l -> l = o) |> Map.toList
- __fff backPointers
-
-let GetObjRefExpr o (heap,env,ctx) =
- _GetObjRefExpr o (heap,env,ctx) (Set.empty)
-
-let rec UpdateHeapEnv prog comp mthd unifs (heap,env,ctx) =
- match unifs with
- | (c,e) :: rest ->
- let restHeap,env,ctx = UpdateHeapEnv prog comp mthd rest (heap,env,ctx)
- let newHeap = restHeap |> Map.fold (fun acc (o,f) l ->
- let value = Resolve l (env,ctx)
- if value = c then
- let objRefExpr = GetObjRefExpr o (heap,env,ctx) |> Utils.ExtractOptionMsg ("Couldn't find a path from this to " + (PrintObjRefName o (env,ctx)))
- let fldName = PrintVarName f
- let assertionExpr = BinaryEq (Dot(objRefExpr, fldName)) e
- // check if the assertion follows and if so update the env
- let code = PrintDafnyCodeSkeleton prog (MethodAnalysisPrinter (comp,mthd) assertionExpr)
- Logger.Debug(" - checking assertion: " + (PrintExpr 0 assertionExpr) + " ... ")
- let ok = CheckDafnyProgram code ("unif_" + (GetMethodFullName comp mthd))
- if ok then
- Logger.DebugLine " HOLDS"
- // change the value to expression
- acc |> Map.add (o,f) (ExprConst(e))
- else
- Logger.DebugLine " DOESN'T HOLDS"
- // don't change the value
- acc |> Map.add (o,f) l
- else
- // see if it's a list, then try to match its elements
- match value with
- | SeqConst(clist) -> acc |> Map.add (o,f) l //TODO!!
- | _ ->
- // leave it as is
- acc |> Map.add (o,f) l
- ) restHeap
- (newHeap,env,ctx)
- | [] -> (heap,env,ctx)
-
-let GeneralizeSolution prog comp mthd (heap,env,ctx) =
- match mthd with
- | Method(mName,Sig(ins, outs),pre,post,_) ->
- let args = List.concat [ins; outs]
- match args with
- | [] -> (heap,env,ctx)
- | _ ->
- let unifs = GetUnifications (BinaryAnd pre post) args (heap,env,ctx)
- |> Set.union (GetArgValueUnifications args env)
- UpdateHeapEnv prog comp mthd (Set.toList unifs) (heap,env,ctx)
- | _ -> failwith ("not a method: " + mthd.ToString())
-
-// ====================================================================================
-/// Returns whether the code synthesized for the given method can be verified with Dafny
-// ====================================================================================
-let VerifySolution prog comp mthd (heap,env,ctx) =
- // print the solution to file and try to verify it with Dafny
- let solution = Map.empty |> Map.add (comp,mthd) (heap,env,ctx)
- let code = PrintImplCode prog solution (fun p -> [comp,mthd])
- CheckDafnyProgram code dafnyVerifySuffix
-
-// ============================================================================
+module Analyzer
+
+open Ast
+open AstUtils
+open CodeGen
+open DafnyModelUtils
+open PipelineUtils
+open Options
+open Printer
+open Resolver
+open DafnyPrinter
+open Utils
+
+open Microsoft.Boogie
+
+type MethodSolution = {
+ pathCond: Expr;
+ heap : Map<Const * VarDecl, Const>;
+ env : Map<Const, Const>;
+ ctx : Set<Set<Const>>;
+}
+
+let Rename suffix vars =
+ vars |> List.map (function Var(nm,tp) -> nm, Var(nm + suffix, tp))
+
+let ReplaceName substMap nm =
+ match Map.tryFind nm substMap with
+ | Some(Var(name, tp)) -> name
+ | None -> nm
+
+let rec Substitute substMap = function
+ | IdLiteral(s) -> IdLiteral(ReplaceName substMap s)
+ | Dot(e,f) -> Dot(Substitute substMap e, ReplaceName substMap f)
+ | UnaryExpr(op,e) -> UnaryExpr(op, Substitute substMap e)
+ | BinaryExpr(n,op,e0,e1) -> BinaryExpr(n, op, Substitute substMap e0, Substitute substMap e1)
+ | SelectExpr(e0,e1) -> SelectExpr(Substitute substMap e0, Substitute substMap e1)
+ | UpdateExpr(e0,e1,e2) -> UpdateExpr(Substitute substMap e0, Substitute substMap e1, Substitute substMap e2)
+ | SequenceExpr(ee) -> SequenceExpr(List.map (Substitute substMap) ee)
+ | SeqLength(e) -> SeqLength(Substitute substMap e)
+ | ForallExpr(vv,e) -> ForallExpr(vv, Substitute substMap e)
+ | expr -> expr
+
+let GenMethodAnalysisCode comp m assertion =
+ let methodName = GetMethodName m
+ let signature = GetMethodSig m
+ let ppre,ppost = GetMethodPrePost m
+ let pre = Desugar ppre
+ let post = Desugar ppost
+ " method " + methodName + "()" + newline +
+ " modifies this;" + newline +
+ " {" + newline +
+ // print signature as local variables
+ (match signature with
+ | Sig(ins,outs) ->
+ List.concat [ins; outs] |> List.fold (fun acc vd -> acc + (sprintf " var %s;" (PrintVarDecl vd)) + newline) "") +
+ " // assume precondition" + newline +
+ " assume " + (PrintExpr 0 pre) + ";" + newline +
+ " // assume invariant and postcondition" + newline +
+ " assume Valid();" + newline +
+ " assume " + (PrintExpr 0 post) + ";" + newline +
+ " // assume user defined invariant again because assuming Valid() doesn't always work" + newline +
+ (GetInvariantsAsList comp |> PrintSep newline (fun e -> " assume " + (PrintExpr 0 e) + ";")) + newline +
+ // if the following assert fails, the model hints at what code to generate; if the verification succeeds, an implementation would be infeasible
+ " // assert false to search for a model satisfying the assumed constraints" + newline +
+ " assert " + (PrintExpr 0 assertion) + ";" + newline +
+ " }" + newline
+
+let MethodAnalysisPrinter onlyForThisCompMethod assertion comp mthd =
+ match onlyForThisCompMethod with
+ | (c,m) when c = comp && m = mthd ->
+ match m with
+ | Method(methodName, sign, pre, post, true) -> (GenMethodAnalysisCode comp m assertion) + newline
+ | _ -> ""
+ | _ -> ""
+
+let rec IsArgsOnly args expr =
+ match expr with
+ | IntLiteral(_) -> true
+ | BoolLiteral(_) -> true
+ | Star -> true
+ | ObjLiteral(id) -> true
+ | VarLiteral(id)
+ | IdLiteral(id) -> args |> List.exists (function Var(varName,_) when varName = id -> true | _ -> false)
+ | UnaryExpr(_,e) -> IsArgsOnly args e
+ | BinaryExpr(_,_,e1,e2) -> (IsArgsOnly args e1) && (IsArgsOnly args e2)
+ | IteExpr(c,e1,e2) -> (IsArgsOnly args c) && (IsArgsOnly args e1) && (IsArgsOnly args e2)
+ | Dot(e,_) -> IsArgsOnly args e
+ | SelectExpr(e1, e2) -> (IsArgsOnly args e1) && (IsArgsOnly args e2)
+ | UpdateExpr(e1, e2, e3) -> (IsArgsOnly args e1) && (IsArgsOnly args e2) && (IsArgsOnly args e3)
+ | SequenceExpr(exprs) | SetExpr(exprs) -> exprs |> List.fold (fun acc e -> acc && (IsArgsOnly args e)) true
+ | SeqLength(e) -> IsArgsOnly args e
+ | ForallExpr(vars,e) -> IsArgsOnly (List.concat [args; vars]) e
+
+//TODO: unifications should probably by "Expr <--> Expr" instead of "Expr <--> Const"
+let GetUnifications indent expr args (heap,env,ctx) =
+ let idt = Indent indent
+ // - first looks if the give expression talks only about method arguments (args)
+ // - then checks if it doesn't already exist in the unification map
+ // - then it tries to evaluate it to a constant
+ // - if all of these succeed, it adds a unification rule e <--> val(e) to the given unifMap map
+ let __AddUnif e unifMap =
+ let builder = new CascadingBuilder<_>(unifMap)
+ builder {
+ let! argsOnly = IsArgsOnly args e |> Utils.BoolToOption
+ let! notAlreadyAdded = Map.tryFind e unifMap |> Utils.IsNoneOption |> Utils.BoolToOption
+ let! v = try Some(Eval (heap,env,ctx) true e |> Expr2Const) with ex -> None
+ Logger.DebugLine (idt + " - adding unification " + (PrintExpr 0 e) + " <--> " + (PrintConst v));
+ return Map.add e v unifMap
+ }
+ // just recurses on all expressions
+ let rec __GetUnifications expr args unifs =
+ let unifs = __AddUnif expr unifs
+ match expr with
+ | IntLiteral(_)
+ | BoolLiteral(_)
+ | VarLiteral(_)
+ | ObjLiteral(_)
+ | IdLiteral(_)
+ | Star -> unifs
+ | Dot(e, _)
+ | SeqLength(e)
+ | ForallExpr(_,e)
+ | UnaryExpr(_,e) -> unifs |> __GetUnifications e args
+ | SelectExpr(e1, e2)
+ | BinaryExpr(_,_,e1,e2) -> unifs |> __GetUnifications e1 args |> __GetUnifications e2 args
+ | IteExpr(e1,e2,e3)
+ | UpdateExpr(e1, e2, e3) -> unifs |> __GetUnifications e1 args |> __GetUnifications e2 args |> __GetUnifications e3 args
+ | SetExpr(elst)
+ | SequenceExpr(elst) -> elst |> List.fold (fun acc e -> acc |> __GetUnifications e args) unifs
+ (* --- function body starts here --- *)
+ __GetUnifications expr args Map.empty
+
+// =======================================================
+/// Returns a map (Expr |--> Const) containing unifications
+/// found for the given method and heap/env/ctx
+// =======================================================
+let GetUnificationsForMethod indent comp m (heap,env,ctx) =
+ let idt = Indent indent
+ let rec GetArgValueUnifications args env =
+ match args with
+ | Var(name,_) :: rest ->
+ match Map.tryFind (Unresolved(name)) env with
+ | Some(c) ->
+ Logger.DebugLine (idt + " - adding unification " + (PrintConst c) + " <--> " + name);
+ Map.ofList [VarLiteral(name), c] |> Utils.MapAddAll (GetArgValueUnifications rest env)
+ | None -> failwith ("couldn't find value for argument " + name)
+ | [] -> Map.empty
+ (* --- function body starts here --- *)
+ match m with
+ | Method(mName,Sig(ins, outs),pre,post,_) ->
+ let args = List.concat [ins; outs]
+ match args with
+ | [] -> Map.empty
+ | _ -> GetUnifications indent (BinaryAnd pre post) args (heap,env,ctx)
+ |> Utils.MapAddAll (GetArgValueUnifications args env)
+ | _ -> failwith ("not a method: " + m.ToString())
+
+// =========================================================================
+/// For a given constant "o" (which is an object, something like "gensym32"),
+/// finds a path of field references from "this".
+///
+/// Implements a backtracking search over the heap entries to find that
+/// path. It starts from the given object, and follows the backpointers
+/// until it reaches the root ("this")
+// =========================================================================
+let objRef2ExprCache = new System.Collections.Generic.Dictionary<Const, Expr>()
+let GetObjRefExpr o (heap,env,ctx) =
+ let rec __GetObjRefExpr o (heap,env,ctx) visited =
+ if Set.contains o visited then
+ None
+ else
+ let newVisited = Set.add o visited
+ let refName = PrintObjRefName o (env,ctx)
+ match refName with
+ | "this" -> Some(ObjLiteral("this"))
+ | _ ->
+ let rec __fff lst =
+ match lst with
+ | ((o,Var(fldName,_)),l) :: rest ->
+ match __GetObjRefExpr o (heap,env,ctx) newVisited with
+ | Some(expr) -> Some(Dot(expr, fldName))
+ | None -> __fff rest
+ | [] -> None
+ let backPointers = heap |> Map.filter (fun (_,_) l -> l = o) |> Map.toList
+ __fff backPointers
+ (* --- function body starts here --- *)
+ if objRef2ExprCache.ContainsKey(o) then
+ Some(objRef2ExprCache.[o])
+ else
+ let res = __GetObjRefExpr o (heap,env,ctx) (Set.empty)
+ match res with
+ | Some(e) -> objRef2ExprCache.Add(o, e)
+ | None -> ()
+ res
+
+// =======================================================
+/// Applies given unifications onto the given heap/env/ctx
+///
+/// If "conservative" is true, applies only those that
+/// can be verified to hold, otherwise applies all of them
+// =======================================================
+let rec ApplyUnifications indent prog comp mthd unifs (heap,env,ctx) conservative =
+ let idt = Indent indent
+ let __CheckUnif o f e idx =
+ if not conservative || not Options.CONFIG.checkUnifications then
+ true
+ else
+ let objRefExpr = GetObjRefExpr o (heap,env,ctx) |> Utils.ExtractOptionMsg ("Couldn't find a path from 'this' to " + (PrintObjRefName o (env,ctx)))
+ let fldName = PrintVarName f
+ let lhs = Dot(objRefExpr, fldName)
+ let assertionExpr = match f with
+ | Var(_, Some(SeqType(_))) when not (idx = -1) -> BinaryEq (SelectExpr(lhs, IntLiteral(idx))) e
+ | Var(_, Some(SetType(_))) when not (idx = -1) -> BinaryIn e lhs
+ | _ -> BinaryEq lhs e
+ // check if the assertion follows and if so update the env
+ let code = PrintDafnyCodeSkeleton prog (MethodAnalysisPrinter (comp,mthd) assertionExpr)
+ Logger.Debug (idt + " - checking assertion: " + (PrintExpr 0 assertionExpr) + " ... ")
+ let ok = CheckDafnyProgram code ("unif_" + (GetMethodFullName comp mthd))
+ if ok then
+ Logger.DebugLine " HOLDS"
+ else
+ Logger.DebugLine " DOESN'T HOLD"
+ ok
+ (* --- function body starts here --- *)
+ match unifs with
+ | (e,c) :: rest ->
+ let restHeap,env,ctx = ApplyUnifications indent prog comp mthd rest (heap,env,ctx) conservative
+ let newHeap = restHeap |> Map.fold (fun acc (o,f) l ->
+ let value = TryResolve (env,ctx) l
+ if value = c then
+ if __CheckUnif o f e -1 then
+ // change the value to expression
+ //Logger.TraceLine (sprintf "%s - applied: %s.%s --> %s" idt (PrintConst o) (GetVarName f) (PrintExpr 0 e) )
+ acc |> Map.add (o,f) (ExprConst(e))
+ else
+ // don't change the value unless "conservative = false"
+ acc |> Map.add (o,f) l
+ else
+ let rec __UnifyOverLst lst cnt =
+ match lst with
+ | lstElem :: rest when lstElem = c ->
+ if __CheckUnif o f e cnt then
+ //Logger.TraceLine (sprintf "%s - applied: %s.%s[%d] --> %s" idt (PrintConst o) (GetVarName f) cnt (PrintExpr 0 e) )
+ ExprConst(e) :: __UnifyOverLst rest (cnt+1)
+ else
+ lstElem :: __UnifyOverLst rest (cnt+1)
+ | lstElem :: rest ->
+ lstElem :: __UnifyOverLst rest (cnt+1)
+ | [] -> []
+ // see if it's a list, then try to match its elements, otherwise leave it as is
+ match value with
+ | SeqConst(clist) ->
+ let newLstConst = __UnifyOverLst clist 0
+ acc |> Map.add (o,f) (SeqConst(newLstConst))
+ | SetConst(cset) ->
+ let newLstConst = __UnifyOverLst (Set.toList cset) 0
+ acc |> Map.add (o,f) (SetConst(newLstConst |> Set.ofList))
+ | _ ->
+ acc |> Map.add (o,f) l
+ ) restHeap
+ (newHeap,env,ctx)
+ | [] -> (heap,env,ctx)
+
+// ====================================================================================
+/// Returns whether the code synthesized for the given method can be verified with Dafny
+// ====================================================================================
+let VerifySolution prog comp mthd sol =
+ // print the solution to file and try to verify it with Dafny
+ let solutions = Map.empty |> Map.add (comp,mthd) sol
+ let code = PrintImplCode prog solutions (fun p -> [comp,mthd])
+ CheckDafnyProgram code dafnyVerifySuffix
+
+// ============================================================================
/// Attempts to synthesize the initialization code for the given constructor "m"
///
-/// Returns a (heap,env,ctx) tuple
-// ============================================================================
-let AnalyzeConstructor prog comp m =
- let methodName = GetMethodName m
- // generate Dafny code for analysis first
- let code = PrintDafnyCodeSkeleton prog (MethodAnalysisPrinter (comp,m) FalseLiteral)
- Logger.InfoLine (" [*] analyzing constructor " + methodName + (PrintSig (GetMethodSig m)))
- Logger.Info " - searching for a solution ..."
- let models = RunDafnyProgram code (dafnyScratchSuffix + "_" + (GetMethodFullName comp m))
- if models.Count = 0 then
- // no models means that the "assert false" was verified, which means that the spec is inconsistent
- Logger.WarnLine " !!! SPEC IS INCONSISTENT !!!"
- None
- else
- if models.Count > 1 then
- Logger.WarnLine " FAILED "
- failwith "internal error (more than one model for a single constructor analysis)"
- Logger.InfoLine " OK "
- let model = models.[0]
- let heap,env,ctx = ReadFieldValuesFromModel model prog comp m
- |> GeneralizeSolution prog comp m
- if _opt_verifySolutions then
- Logger.InfoLine " - verifying synthesized solution ... "
- let verified = VerifySolution prog comp m (heap,env,ctx)
- Logger.Info " "
- if verified then
- Logger.InfoLine "~~~ VERIFIED ~~~"
- Some(heap,env,ctx)
- else
- Logger.InfoLine "!!! NOT VERIFIED !!!"
- Some(heap,env,ctx)
- else
- Some(heap,env,ctx)
-
-
-// ============================================================================
-/// Goes through a given list of methods of the given program and attempts to
-/// synthesize code for each one of them.
-///
-/// Returns a map from (component * method) |--> (heap,env,ctx)
-// ============================================================================
-let rec AnalyzeMethods prog members =
- match members with
- | (comp,m) :: rest ->
- match m with
- | Method(_,_,_,_,true) ->
- let solOpt = AnalyzeConstructor prog comp m
- Logger.InfoLine ""
- match solOpt with
- | Some(heap,env,ctx) -> AnalyzeMethods prog rest |> Map.add (comp,m) (heap,env,ctx)
- | None -> AnalyzeMethods prog rest
- | _ -> AnalyzeMethods prog rest
- | [] -> Map.empty
-
-let Analyze prog =
- let solutions = AnalyzeMethods prog (GetMethodsToAnalyze prog)
- use file = System.IO.File.CreateText(dafnySynthFile)
- file.AutoFlush <- true
- Logger.InfoLine "Printing synthesized code"
- let synthCode = PrintImplCode prog solutions GetMethodsToAnalyze
- fprintfn file "%s" synthCode
- ()
-
-//let AnalyzeComponent_rustan c =
-// match c with
-// | Component(Class(name,typeParams,members), Model(_,_,cVars,frame,inv), code) ->
-// let aVars = Fields members
-// let aVars0 = Rename "0" aVars
-// let aVars1 = Rename "1" aVars
-// let allVars = List.concat [aVars; List.map (fun (a,b) -> b) aVars0; List.map (fun (a,b) -> b) aVars1; cVars]
-// let inv0 = Substitute (Map.ofList aVars0) inv
-// let inv1 = Substitute (Map.ofList aVars1) inv
-// // Now print it as a Dafny program
-// printf "class %s" name
-// match typeParams with
-// | [] -> ()
-// | _ -> printf "<%s>" (typeParams |> PrintSep ", " (fun tp -> tp))
-// printfn " {"
-// // the fields: original abstract fields plus two more copies thereof, plus and concrete fields
-// allVars |> List.iter (function Var(nm,None) -> printfn " var %s;" nm | Var(nm,Some(tp)) -> printfn " var %s: %s;" nm (PrintType tp))
-// // the method
-// printfn " method %s_checkInjective() {" name
-// printf " assume " ; (VarsAreDifferent aVars0 aVars1) ; printfn ";"
-// printfn " assume %s;" (PrintExpr 0 inv0)
-// printfn " assume %s;" (PrintExpr 0 inv1)
-// printfn " assert false;" // {:msg "Two abstract states map to the same concrete state"}
-// printfn " }"
-// // generate code
-// members |> List.iter (function
-// | Constructor(methodName,signature,pre,stmts) -> printf "%s" (GenerateCode methodName signature pre stmts inv false)
-// | Method(methodName,signature,pre,stmts) -> printf "%s" (GenerateCode methodName signature pre stmts inv true)
-// | _ -> ())
-// // the end of the class
-// printfn "}"
+/// Returns a (heap,env,ctx) tuple
+// ============================================================================
+let rec AnalyzeConstructor indent prog comp m =
+ let idt = Indent indent
+ let methodName = GetMethodName m
+ let pre,post = GetMethodPrePost m
+ // generate Dafny code for analysis first
+ let code = PrintDafnyCodeSkeleton prog (MethodAnalysisPrinter (comp,m) FalseLiteral)
+ Logger.InfoLine (idt + "[*] Analyzing constructor")
+ Logger.InfoLine (idt + "------------------------------------------")
+ Logger.InfoLine (PrintMethodSignFull (indent + 4) m)
+ Logger.InfoLine (idt + "------------------------------------------")
+ Logger.Info (idt + " - searching for an instance ...")
+ let models = RunDafnyProgram code (dafnyScratchSuffix + "_" + (GetMethodFullName comp m))
+ if models.Count = 0 then
+ // no models means that the "assert false" was verified, which means that the spec is inconsistent
+ Logger.WarnLine (idt + " !!! SPEC IS INCONSISTENT !!!")
+ []
+ else
+ if models.Count > 1 then
+ Logger.WarnLine " FAILED "
+ failwith "internal error (more than one model for a single constructor analysis)"
+ Logger.InfoLine " OK "
+ let model = models.[0]
+ let heap,env,ctx = ReadFieldValuesFromModel model prog comp m
+ let unifs = GetUnificationsForMethod indent comp m (heap,env,ctx) |> Map.toList
+ let heap,env,ctx = ApplyUnifications indent prog comp m unifs (heap,env,ctx) true
+ if Options.CONFIG.verifySolutions then
+ Logger.InfoLine (idt + " - verifying synthesized solution ... ")
+ let sol = [TrueLiteral, (heap,env,ctx)]
+ let verified = VerifySolution prog comp m sol
+ Logger.Info (idt + " ")
+ if verified then
+ Logger.InfoLine "~~~ VERIFIED ~~~"
+ sol
+ else
+ Logger.InfoLine "!!! NOT VERIFIED !!!"
+ Logger.InfoLine (idt + " Strengthening the pre-condition")
+ TryInferConditionals (indent + 4) prog comp m unifs (heap,env,ctx)
+ else
+ [TrueLiteral, (heap,env,ctx)]
+and TryInferConditionals indent prog comp m unifs (heap,env,ctx) =
+ let idt = Indent indent
+ let heap2,env2,ctx2 = ApplyUnifications indent prog comp m unifs (heap,env,ctx) false
+ // get expressions to evaluate:
+ // - add pre and post conditions
+ // - go through all objects on the heap and assert its invariant
+ let pre,post = GetMethodPrePost m
+ let prepostExpr = post //TODO: do we need the "pre" here as well?
+ let heapObjs = heap |> Map.fold (fun acc (o,_) _ -> acc |> Set.add o) Set.empty
+ let expr = heapObjs |> Set.fold (fun acc o ->
+ let receiverOpt = GetObjRefExpr o (heap,env,ctx)
+ let receiver = Utils.ExtractOption receiverOpt
+ match Resolve (env,ctx) o with
+ | NewObj(_,tOpt) | ThisConst(_,tOpt) ->
+ let t = Utils.ExtractOptionMsg "Type missing for heap object" tOpt
+ let objComp = FindComponent prog (GetTypeShortName t) |> Utils.ExtractOption
+ let objInvs = GetInvariantsAsList objComp
+ let objInvsUpdated = objInvs |> List.map (ChangeThisReceiver receiver)
+ objInvsUpdated |> List.fold (fun a e -> BinaryAnd a e) acc
+ | _ -> failwith "not supposed to happen"
+ ) prepostExpr
+ //expr |> SplitIntoConjunts |> List.iter (fun e -> printfn "%s" (PrintExpr 0 e); printfn "")
+ // now evaluate and see what's left
+ let newCond = Eval (heap2,env2,ctx2) false expr
+ try
+ if newCond = TrueLiteral then
+ Logger.InfoLine (sprintf "%s - no more interesting pre-conditions" idt)
+ []
+ else
+ Logger.InfoLine (sprintf "%s - candidate pre-condition: %s" idt (PrintExpr 0 newCond))
+ let p2,c2,m2 = AddPrecondition prog comp m newCond
+ Logger.Info (idt + " - verifying partial solution ... ")
+ let sol = [newCond, (heap2,env2,ctx2)]
+ let verified = VerifySolution p2 c2 m2 sol
+ if verified then
+ Logger.InfoLine "VERIFIED"
+ let p3,c3,m3 = AddPrecondition prog comp m (UnaryNot(newCond))
+ sol.[0] :: AnalyzeConstructor (indent + 2) p3 c3 m3
+ else
+ Logger.InfoLine "NOT VERIFIED"
+ []
+ with
+ ex -> raise ex
+
+let GetMethodsToAnalyze prog =
+ let mOpt = Options.CONFIG.methodToSynth;
+ if mOpt = "*" then
+ (* all *)
+ FilterMembers prog FilterConstructorMembers
+ elif mOpt = "paramsOnly" then
+ (* only with parameters *)
+ FilterMembers prog FilterConstructorMembersWithParams
+ else
+ let allMethods,neg =
+ if mOpt.StartsWith("~") then
+ mOpt.Substring(1), true
+ else
+ mOpt, false
+ (* exactly one *)
+ let methods = allMethods.Split([|','|])
+ let lst = methods |> Array.fold (fun acc m ->
+ let compName = m.Substring(0, m.LastIndexOf("."))
+ let methName = m.Substring(m.LastIndexOf(".") + 1)
+ let c = FindComponent prog compName |> Utils.ExtractOptionMsg ("Cannot find component " + compName)
+ let mthd = FindMethod c methName |> Utils.ExtractOptionMsg ("Cannot find method " + methName + " in component " + compName)
+ (c,mthd) :: acc
+ ) []
+ if neg then
+ FilterMembers prog FilterConstructorMembers |> List.filter (fun e -> not (Utils.ListContains e lst))
+ else
+ lst
+
+
+// ============================================================================
+/// Goes through a given list of methods of the given program and attempts to
+/// synthesize code for each one of them.
+///
+/// Returns a map from (component * method) |--> (heap,env,ctx)
+// ============================================================================
+let rec AnalyzeMethods prog members =
+ match members with
+ | (comp,m) :: rest ->
+ match m with
+ | Method(_,_,_,_,true) ->
+ let solOpt = AnalyzeConstructor 2 prog comp m
+ Logger.InfoLine ""
+ AnalyzeMethods prog rest |> Map.add (comp,m) solOpt
+ | _ -> AnalyzeMethods prog rest
+ | [] -> Map.empty
+
+let Analyze prog filename =
+ let solutions = AnalyzeMethods prog (GetMethodsToAnalyze prog)
+ let progName = System.IO.Path.GetFileNameWithoutExtension(filename)
+ use file = System.IO.File.CreateText(dafnySynthFileNameTemplate.Replace("###", progName))
+ file.AutoFlush <- true
+ Logger.InfoLine "Printing synthesized code"
+ let synthCode = PrintImplCode prog solutions GetMethodsToAnalyze
+ fprintfn file "%s" synthCode
+ ()
+
+//let AnalyzeComponent_rustan c =
+// match c with
+// | Component(Class(name,typeParams,members), Model(_,_,cVars,frame,inv), code) ->
+// let aVars = Fields members
+// let aVars0 = Rename "0" aVars
+// let aVars1 = Rename "1" aVars
+// let allVars = List.concat [aVars; List.map (fun (a,b) -> b) aVars0; List.map (fun (a,b) -> b) aVars1; cVars]
+// let inv0 = Substitute (Map.ofList aVars0) inv
+// let inv1 = Substitute (Map.ofList aVars1) inv
+// // Now print it as a Dafny program
+// printf "class %s" name
+// match typeParams with
+// | [] -> ()
+// | _ -> printf "<%s>" (typeParams |> PrintSep ", " (fun tp -> tp))
+// printfn " {"
+// // the fields: original abstract fields plus two more copies thereof, plus and concrete fields
+// allVars |> List.iter (function Var(nm,None) -> printfn " var %s;" nm | Var(nm,Some(tp)) -> printfn " var %s: %s;" nm (PrintType tp))
+// // the method
+// printfn " method %s_checkInjective() {" name
+// printf " assume " ; (VarsAreDifferent aVars0 aVars1) ; printfn ";"
+// printfn " assume %s;" (PrintExpr 0 inv0)
+// printfn " assume %s;" (PrintExpr 0 inv1)
+// printfn " assert false;" // {:msg "Two abstract states map to the same concrete state"}
+// printfn " }"
+// // generate code
+// members |> List.iter (function
+// | Constructor(methodName,signature,pre,stmts) -> printf "%s" (GenerateCode methodName signature pre stmts inv false)
+// | Method(methodName,signature,pre,stmts) -> printf "%s" (GenerateCode methodName signature pre stmts inv true)
+// | _ -> ())
+// // the end of the class
+// printfn "}"
// | _ -> assert false // unexpected case \ No newline at end of file
diff --git a/Jennisys/Jennisys/Ast.fs b/Jennisys/Jennisys/Ast.fs
index bd66e688..1ddf1f31 100644
--- a/Jennisys/Jennisys/Ast.fs
+++ b/Jennisys/Jennisys/Ast.fs
@@ -1,7 +1,9 @@
-/// The AST of a Jennisy program
+// ####################################################################
+/// The AST of a Jennisy program
///
-/// author: Rustan Leino (leino@microsoft.com)
-/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+/// author: Rustan Leino (leino@microsoft.com)
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// ####################################################################
namespace Ast
@@ -13,25 +15,50 @@ type Type =
| BoolType
| SetType of Type (* type parameter *)
| SeqType of Type (* type parameter *)
- | NamedType of string
- | InstantiatedType of string * Type (* type parameter *)
+ | NamedType of string * string list (* type parameters *)
+ | InstantiatedType of string * Type list (* type parameters *)
type VarDecl =
| Var of string * Type option
+(*
+ the difference between IdLiteral and VarLiteral is that the VarLiteral is more specific,
+ it always referes to a local variable (either method parameter or quantification variable)
+
+ ObjLiteral is a concrete object, so if two ObjLiterals have different names,
+ they are different objects (as opposed to IdLiterals and VarLiterals, which can alias).
+ *)
type Expr =
| IntLiteral of int
- | IdLiteral of string
+ | BoolLiteral of bool
+ | VarLiteral of string
+ | IdLiteral of string
+ | ObjLiteral of string
| Star
| Dot of Expr * string
| UnaryExpr of string * Expr
| BinaryExpr of int * string * Expr * Expr
+ | IteExpr of (* cond *) Expr * (* thenExpr *) Expr * (* elseExpr *) Expr
| SelectExpr of Expr * Expr
| UpdateExpr of Expr * Expr * Expr
| SequenceExpr of Expr list
| SeqLength of Expr
+ | SetExpr of Expr list //TODO: maybe this should really be a set instead of a list
| ForallExpr of VarDecl list * Expr
+type Const =
+ | IntConst of int
+ | BoolConst of bool
+ | SetConst of Set<Const>
+ | SeqConst of Const list
+ | NullConst
+ | NoneConst
+ | ThisConst of (* loc id *) string * Type option
+ | VarConst of string
+ | NewObj of (* loc id *) string * Type option
+ | ExprConst of Expr
+ | Unresolved of (* loc id *) string
+
type Stmt =
| Block of Stmt list
| Assign of Expr * Expr
@@ -57,15 +84,3 @@ type Component =
type Program =
| Program of Component list
-
-type Const =
- | IntConst of int
- | BoolConst of bool
- | SetConst of Set<Const option>
- | SeqConst of (Const option) list
- | NullConst
- | ThisConst of (* loc id *) string * Type option
- | NewObj of (* loc id *) string * Type option
- | ExprConst of Expr
- | VarConst of (* varName *) string
- | Unresolved of (* loc id *) string \ No newline at end of file
diff --git a/Jennisys/Jennisys/AstUtils.fs b/Jennisys/Jennisys/AstUtils.fs
index 442dfe57..25d2a129 100644
--- a/Jennisys/Jennisys/AstUtils.fs
+++ b/Jennisys/Jennisys/AstUtils.fs
@@ -1,327 +1,210 @@
-/// Utility functions for manipulating AST elements
+// ####################################################################
+/// Utility functions for manipulating AST elements
///
-/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// ####################################################################
module AstUtils
open Ast
open Utils
-// ------------------------------- Visitor Stuff -------------------------------------------
-
-let rec VisitExpr visitorFunc expr acc =
- match expr with
- | IntLiteral(_)
- | IdLiteral(_)
- | Star -> acc |> visitorFunc expr
- | Dot(e, _) -> acc |> visitorFunc expr |> VisitExpr visitorFunc e
- | SelectExpr(e1, e2) -> acc |> visitorFunc expr |> VisitExpr visitorFunc e1 |> VisitExpr visitorFunc e2
- | UpdateExpr(e1, e2, e3) -> acc |> visitorFunc expr |> VisitExpr visitorFunc e1 |> VisitExpr visitorFunc e2 |> VisitExpr visitorFunc e3
- | SequenceExpr(exs) -> exs |> List.fold (fun acc2 e -> acc2 |> VisitExpr visitorFunc e) (visitorFunc expr acc)
- | SeqLength(e) -> acc |> visitorFunc expr |> VisitExpr visitorFunc e
- | ForallExpr(_,e) -> acc |> visitorFunc expr |> VisitExpr visitorFunc e
- | UnaryExpr(_,e) -> acc |> visitorFunc expr |> VisitExpr visitorFunc e
- | BinaryExpr(_,_,e1,e2) -> acc |> visitorFunc expr |> VisitExpr visitorFunc e1 |> VisitExpr visitorFunc e2
-
-// ------------------------------- End Visitor Stuff -------------------------------------------
-
-exception EvalFailed
-
-let rec EvalSym expr =
- match expr with
- | IntLiteral(n) -> IntConst(n)
- | IdLiteral(id) -> VarConst(id)
- | Dot(e, str) ->
- match EvalSym e with
- | VarConst(lhsName) -> VarConst(lhsName + "." + str)
- | _ -> ExprConst(expr)
- | SeqLength(e) ->
- match EvalSym e with
- | SeqConst(clist) -> IntConst(List.length clist)
- | _ -> ExprConst(expr)
- | SequenceExpr(elist) ->
- let clist = elist |> List.fold (fun acc e -> EvalSym e :: acc) [] |> List.rev |> Utils.ConvertToOptionList
- SeqConst(clist)
- | SelectExpr(lst, idx) ->
- match EvalSym lst, EvalSym idx with
- | SeqConst(clist), IntConst(n) -> clist.[n] |> Utils.ExtractOption
- | _ -> ExprConst(expr)
- | UpdateExpr(lst,idx,v) ->
- match EvalSym lst, EvalSym idx, EvalSym v with
- | SeqConst(clist), IntConst(n), (_ as c) -> SeqConst(Utils.ListSet n (Some(c)) clist)
- | _ -> ExprConst(expr)
- | BinaryExpr(_,op,e1,e2) ->
- match op with
- | Exact "=" _ ->
- match EvalSym e1, EvalSym e2 with
- | BoolConst(b1), BoolConst(b2) -> BoolConst(b1 = b2)
- | IntConst(n1), IntConst(n2) -> BoolConst(n1 = n2)
- | VarConst(v1), VarConst(v2) -> BoolConst(v1 = v2)
- | _ -> ExprConst(expr)
- | Exact "!=" _ ->
- match EvalSym e1, EvalSym e2 with
- | BoolConst(b1), BoolConst(b2) -> BoolConst(not (b1 = b2))
- | IntConst(n1), IntConst(n2) -> BoolConst(not (n1 = n2))
- | VarConst(v1), VarConst(v2) -> BoolConst(not (v1 = v2))
- | _ -> ExprConst(expr)
- | Exact "<" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> BoolConst(n1 < n2)
- | SetConst(s1), SetConst(s2) -> BoolConst((Set.count s1) < (Set.count s2))
- | SeqConst(s1), SeqConst(s2) -> BoolConst((List.length s1) < (List.length s2))
- | _ -> ExprConst(expr)
- | Exact "<=" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> BoolConst(n1 <= n2)
- | SetConst(s1), SetConst(s2) -> BoolConst((Set.count s1) <= (Set.count s2))
- | SeqConst(s1), SeqConst(s2) -> BoolConst((List.length s1) <= (List.length s2))
- | _ -> ExprConst(expr)
- | Exact ">" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> BoolConst(n1 > n2)
- | SetConst(s1), SetConst(s2) -> BoolConst((Set.count s1) > (Set.count s2))
- | SeqConst(s1), SeqConst(s2) -> BoolConst((List.length s1) > (List.length s2))
- | _ -> ExprConst(expr)
- | Exact ">=" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> BoolConst(n1 >= n2)
- | SetConst(s1), SetConst(s2) -> BoolConst((Set.count s1) >= (Set.count s2))
- | SeqConst(s1), SeqConst(s2) -> BoolConst((List.length s1) >= (List.length s2))
- | _ -> ExprConst(expr)
- | Exact "in" _ ->
- match EvalSym e1, EvalSym e2 with
- | _ as c, SetConst(s) -> BoolConst(Set.contains (Some(c)) s)
- | _ as c, SeqConst(s) -> BoolConst(Utils.ListContains (Some(c)) s)
- | _ -> ExprConst(expr)
- | Exact "!in" _ ->
- match EvalSym e1, EvalSym e2 with
- | _ as c, SetConst(s) -> BoolConst(not (Set.contains (Some(c)) s))
- | _ as c, SeqConst(s) -> BoolConst(not (Utils.ListContains (Some(c)) s))
- | _ -> ExprConst(expr)
- | Exact "+" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> IntConst(n1 + n2)
- | SeqConst(l1), SeqConst(l2) -> SeqConst(List.append l1 l2)
- | SetConst(s1), SetConst(s2) -> SetConst(Set.union s1 s2)
- | _ -> ExprConst(expr)
- | Exact "-" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> IntConst(n1 + n2)
- | SetConst(s1), SetConst(s2) -> SetConst(Set.difference s1 s2)
- | _ -> ExprConst(expr)
- | Exact "*" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> IntConst(n1 * n2)
- | _ -> ExprConst(expr)
- | Exact "div" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> IntConst(n1 / n2)
- | _ -> ExprConst(expr)
- | Exact "mod" _ ->
- match EvalSym e1, EvalSym e2 with
- | IntConst(n1), IntConst(n2) -> IntConst(n1 % n2)
- | _ -> ExprConst(expr)
- | _ -> ExprConst(expr)
- | UnaryExpr(op, e) ->
- match op with
- | Exact "!" _ ->
- match EvalSym e with
- | BoolConst(b) -> BoolConst(not b)
- | _ -> ExprConst(expr)
- | Exact "-" _ ->
- match EvalSym e with
- | IntConst(n) -> IntConst(-n)
- | _ -> ExprConst(expr)
- | _ -> ExprConst(expr)
- | _ -> ExprConst(expr)
-
-//TODO: stuff might be missing
-let rec EvalToConst expr =
- match expr with
- | IntLiteral(n) -> IntConst(n)
- | IdLiteral(id) -> raise EvalFailed //VarConst(id)
- | Dot(e, str) -> raise EvalFailed
- | SeqLength(e) ->
- match EvalToConst e with
- | SeqConst(clist) -> IntConst(List.length clist)
- | _ -> raise EvalFailed
- | SequenceExpr(elist) ->
- let clist = elist |> List.fold (fun acc e -> EvalToConst e :: acc) [] |> List.rev |> Utils.ConvertToOptionList
- SeqConst(clist)
- | SelectExpr(lst, idx) ->
- match EvalToConst lst, EvalToConst idx with
- | SeqConst(clist), IntConst(n) -> clist.[n] |> Utils.ExtractOption
- | _ -> raise EvalFailed
- | UpdateExpr(lst,idx,v) ->
- match EvalToConst lst, EvalToConst idx, EvalToConst v with
- | SeqConst(clist), IntConst(n), (_ as c) -> SeqConst(Utils.ListSet n (Some(c)) clist)
- | _ -> raise EvalFailed
- | BinaryExpr(_,op,e1,e2) ->
- match op with
- | Exact "=" _ ->
- try
- BoolConst(EvalToBool(e1) = EvalToBool(e2))
- with
- | EvalFailed -> BoolConst(EvalToInt(e1) = EvalToInt(e2))
- | Exact "!=" _ ->
- try
- BoolConst(not(EvalToBool(e1) = EvalToBool(e2)))
- with
- | EvalFailed -> BoolConst(not(EvalToInt e1 = EvalToInt e2))
- | Exact "<" _ -> BoolConst(EvalToInt e1 < EvalToInt e2) //TODO sets, seqs
- | Exact "<=" _ -> BoolConst(EvalToInt e1 <= EvalToInt e2) //TODO sets, seqs
- | Exact ">" _ -> BoolConst(EvalToInt e1 > EvalToInt e2) //TODO sets, seqs
- | Exact ">=" _ -> BoolConst(EvalToInt e1 >= EvalToInt e2) //TODO sets, seqs
- | Exact "in" _ -> raise EvalFailed //TODO
- | Exact "!in" _ -> raise EvalFailed //TODO
- | Exact "+" _ ->
- match EvalToConst e1, EvalToConst e2 with
- | IntConst(n1), IntConst(n2) -> IntConst(n1 + n2)
- | SeqConst(l1), SeqConst(l2) -> SeqConst(List.append l1 l2)
- | SetConst(s1), SetConst(s2) -> SetConst(Set.union s1 s2)
- | _ -> raise EvalFailed
- | Exact "-" _ -> IntConst(EvalToInt e1 - EvalToInt e2)
- | Exact "*" _ -> IntConst(EvalToInt e1 * EvalToInt e2)
- | Exact "div" _ -> IntConst(EvalToInt e1 / EvalToInt e2)
- | Exact "mod" _ -> IntConst(EvalToInt e1 % EvalToInt e2)
- | _ -> raise EvalFailed
- | UnaryExpr(op, e) ->
- match op with
- | Exact "!" _ -> BoolConst(not (EvalToBool e))
- | Exact "-" _ -> IntConst(-(EvalToInt e))
- | _ -> raise EvalFailed
- | _ -> raise EvalFailed
-and EvalToBool e =
- let c = EvalToConst e
- match c with
- | BoolConst(b) -> b
- | _ -> raise EvalFailed
-and EvalToInt e =
- let c = EvalToConst e
- match c with
- | IntConst(n) -> n
- | _ -> raise EvalFailed
-
-let rec Const2Expr c =
- match c with
- | IntConst(n) -> IntLiteral(n)
- | BoolConst(b) -> if b then IntLiteral(1) else IntLiteral(0) //?? BoolLiteral(b)
- | SeqConst(clist) ->
- let expList = clist |> List.fold (fun acc c -> Const2Expr (Utils.ExtractOption c) :: acc) [] |> List.rev
- SequenceExpr(expList)
- | ThisConst(_) -> IdLiteral("this")
- | VarConst(v) -> IdLiteral(v)
- | NullConst -> IdLiteral("null")
- | ExprConst(e) -> e
- | _ -> failwith "not implemented or not supported"
+// =====================
+/// Returns TRUE literal
+// =====================
+let TrueLiteral = BoolLiteral(true)
+
+// =====================
+/// Returns FALSE literal
+// =====================
+let FalseLiteral = BoolLiteral(false)
+
+let UnaryNeg sub =
+ match sub with
+ | UnaryExpr("-", s) -> s
+ | _ -> UnaryExpr("-", sub)
+
+let UnaryNot sub =
+ match sub with
+ | UnaryExpr("!", s) -> s
+ | _ -> UnaryExpr("!", sub)
// =======================================================================
/// Returns a binary AND of the two given expressions with short-circuiting
// =======================================================================
let BinaryAnd (lhs: Expr) (rhs: Expr) =
- match lhs, rhs with
- | IdLiteral("true"), _ -> rhs
- | IdLiteral("false"), _ -> IdLiteral("false")
- | _, IdLiteral("true") -> lhs
- | _, IdLiteral("false") -> IdLiteral("false")
- | _, _ -> BinaryExpr(30, "&&", lhs, rhs)
+ match lhs, rhs with
+ | BoolLiteral(true), _ -> rhs
+ | BoolLiteral(false), _ -> FalseLiteral
+ | _, BoolLiteral(true) -> lhs
+ | _, BoolLiteral(false) -> FalseLiteral
+ | _, _ -> BinaryExpr(30, "&&", lhs, rhs)
// =======================================================================
/// Returns a binary OR of the two given expressions with short-circuiting
// =======================================================================
let BinaryOr (lhs: Expr) (rhs: Expr) =
- match lhs, rhs with
- | IdLiteral("true"), _ -> IdLiteral("true")
- | IdLiteral("false"), _ -> rhs
- | _, IdLiteral("true") -> IdLiteral("true")
- | _, IdLiteral("false") -> lhs
- | _, _ -> BinaryExpr(30, "||", lhs, rhs)
+ match lhs, rhs with
+ | BoolLiteral(true), _ -> TrueLiteral
+ | BoolLiteral(false), _ -> rhs
+ | _, BoolLiteral(true) -> TrueLiteral
+ | _, BoolLiteral(false) -> lhs
+ | _, _ -> BinaryExpr(30, "||", lhs, rhs)
// ===================================================================================
-/// Returns a binary IMPLIES of the two given expressions (TODO: with short-circuiting)
+/// Returns a binary IMPLIES of the two given expressions
// ===================================================================================
-let BinaryImplies lhs rhs = BinaryExpr(20, "==>", lhs, rhs)
+let BinaryImplies lhs rhs =
+ match lhs, rhs with
+ | BoolLiteral(false), _ -> FalseLiteral
+ | BoolLiteral(true), _ -> rhs
+ | _, BoolLiteral(true) -> lhs
+ | _, BoolLiteral(false) -> UnaryNot(lhs)
+ | _ -> BinaryExpr(20, "==>", lhs, rhs)
-// =================================================
-/// Returns a binary NEQ of the two given expressions
-// =================================================
-let BinaryNeq lhs rhs = BinaryExpr(40, "!=", lhs, rhs)
-
-// =================================================
-/// Returns a binary EQ of the two given expressions
-// =================================================
-let BinaryEq lhs rhs = BinaryExpr(40, "=", lhs, rhs)
-// =====================
-/// Returns TRUE literal
-// =====================
-let TrueLiteral = IdLiteral("true")
+//let TrueLiteral = IdLiteral("true")
+//let FalseLiteral = IdLiteral("false")
+//
+//// =======================================================================
+///// Returns a binary AND of the two given expressions with short-circuiting
+//// =======================================================================
+//let BinaryAnd (lhs: Expr) (rhs: Expr) =
+// match lhs, rhs with
+// | IdLiteral("true"), _ -> rhs
+// | IdLiteral("false"), _ -> IdLiteral("false")
+// | _, IdLiteral("true") -> lhs
+// | _, IdLiteral("false") -> IdLiteral("false")
+// | _, _ -> BinaryExpr(30, "&&", lhs, rhs)
+//
+//// =======================================================================
+///// Returns a binary OR of the two given expressions with short-circuiting
+//// =======================================================================
+//let BinaryOr (lhs: Expr) (rhs: Expr) =
+// match lhs, rhs with
+// | IdLiteral("true"), _ -> IdLiteral("true")
+// | IdLiteral("false"), _ -> rhs
+// | _, IdLiteral("true") -> IdLiteral("true")
+// | _, IdLiteral("false") -> lhs
+// | _, _ -> BinaryExpr(30, "||", lhs, rhs)
+//
+//// ===================================================================================
+///// Returns a binary IMPLIES of the two given expressions (TODO: with short-circuiting)
+//// ===================================================================================
+//let BinaryImplies lhs rhs = BinaryExpr(20, "==>", lhs, rhs)
-// =====================
-/// Returns FALSE literal
-// =====================
-let FalseLiteral = IdLiteral("false")
+// =======================================================
+/// Constructors for binary EQ/NEQ of two given expressions
+// =======================================================
+let BinaryNeq lhs rhs = BinaryExpr(40, "!=", lhs, rhs)
+let BinaryEq lhs rhs = BinaryExpr(40, "=", lhs, rhs)
+// =======================================================
+/// Constructors for binary IN/!IN of two given expressions
+// =======================================================
+let BinaryIn lhs rhs = BinaryExpr(40, "in", lhs, rhs)
+let BinaryNotIn lhs rhs = BinaryExpr(40, "!in", lhs, rhs)
+
// ==========================================
/// Splits "expr" into a list of its conjuncts
-// ==========================================
-let rec SplitIntoConjunts expr =
- match expr with
- | IdLiteral("true") -> []
- | BinaryExpr(_,"&&",e0,e1) -> List.concat [SplitIntoConjunts e0 ; SplitIntoConjunts e1]
- | _ -> [expr]
-
-// ======================================
-/// Applies "f" to each conjunct of "expr"
-// ======================================
-let rec ForeachConjunct f expr =
+// ==========================================
+let rec SplitIntoConjunts expr =
+ match expr with
+ | BoolLiteral(true) -> []
+ | BinaryExpr(_,"&&",e0,e1) -> List.concat [SplitIntoConjunts e0 ; SplitIntoConjunts e1]
+ | _ -> [expr]
+
+// ======================================
+/// Applies "f" to each conjunct of "expr"
+// ======================================
+let rec ForeachConjunct f expr =
SplitIntoConjunts expr |> List.fold (fun acc e -> acc + (f e)) ""
+// =======================================
+/// Converts a given constant to expression
+// =======================================
+let rec Const2Expr c =
+ match c with
+ | IntConst(n) -> IntLiteral(n)
+ | BoolConst(b) -> BoolLiteral(b)
+ | SeqConst(clist) ->
+ let expList = clist |> List.fold (fun acc c -> Const2Expr c :: acc) [] |> List.rev
+ SequenceExpr(expList)
+ | SetConst(cset) ->
+ let expSet = cset |> Set.fold (fun acc c -> Set.add (Const2Expr c) acc) Set.empty
+ SetExpr(Set.toList expSet)
+ | VarConst(id) -> VarLiteral(id)
+ | ThisConst(name,_)
+ | NewObj(name,_) -> ObjLiteral(name)
+ | NullConst -> ObjLiteral("null")
+ | ExprConst(e) -> e
+ | Unresolved(name) -> printf "What about unresolved stuff??"; failwith "don't want to convert unresolved to expr"
+ | _ -> failwithf "not implemented or not supported: %O" c
+
+let rec Expr2Const e =
+ match e with
+ | IntLiteral(n) -> IntConst(n)
+ | BoolLiteral(b) -> BoolConst(b)
+ | ObjLiteral("this") -> ThisConst("this",None)
+ | ObjLiteral("null") -> NullConst
+ | ObjLiteral(name) -> NewObj(name, None) //TODO: or Unresolved?
+ | IdLiteral(id) -> Unresolved(id)
+ | VarLiteral(id) -> VarConst(id)
+ | SequenceExpr(elist) -> SeqConst(elist |> List.map Expr2Const)
+ | SetExpr(elist) -> SetConst(elist |> List.map Expr2Const |> Set.ofList)
+ | _ -> failwithf "Not a constant: %O" e
+
+let TryExpr2Const e =
+ try
+ Some(Expr2Const e)
+ with
+ | ex -> None
+
// --- search functions ---
// =========================================================
/// Out of all "members" returns only those that are "Field"s
-// =========================================================
-let FilterFieldMembers members =
- members |> List.choose (function Field(vd) -> Some(vd) | _ -> None)
-
-// =============================================================
-/// Out of all "members" returns only those that are constructors
-// =============================================================
-let FilterConstructorMembers members =
- members |> List.choose (function Method(_,_,_,_, true) as m -> Some(m) | _ -> None)
-
-// =============================================================
-/// Out of all "members" returns only those that are
-/// constructors and have at least one input parameter
-// =============================================================
-let FilterConstructorMembersWithParams members =
- members |> List.choose (function Method(_,Sig(ins,outs),_,_, true) as m when not (List.isEmpty ins) -> Some(m) | _ -> None)
-
-// ==========================================================
-/// Out of all "members" returns only those that are "Method"s
-// ==========================================================
-let FilterMethodMembers members =
- members |> List.choose (function Method(_,_,_,_,_) as m -> Some(m) | _ -> None)
-
-// =======================================================================
-/// Returns all members of the program "prog" that pass the filter "filter"
-// =======================================================================
-let FilterMembers prog filter =
- match prog with
- | Program(components) ->
- components |> List.fold (fun acc comp ->
- match comp with
- | Component(Class(_,_,members),_,_) -> List.concat [acc ; members |> filter |> List.choose (fun m -> Some(comp, m))]
+// =========================================================
+let FilterFieldMembers members =
+ members |> List.choose (function Field(vd) -> Some(vd) | _ -> None)
+
+// =============================================================
+/// Out of all "members" returns only those that are constructors
+// =============================================================
+let FilterConstructorMembers members =
+ members |> List.choose (function Method(_,_,_,_, true) as m -> Some(m) | _ -> None)
+
+// =============================================================
+/// Out of all "members" returns only those that are
+/// constructors and have at least one input parameter
+// =============================================================
+let FilterConstructorMembersWithParams members =
+ members |> List.choose (function Method(_,Sig(ins,outs),_,_, true) as m when not (List.isEmpty ins) -> Some(m) | _ -> None)
+
+// ==========================================================
+/// Out of all "members" returns only those that are "Method"s
+// ==========================================================
+let FilterMethodMembers members =
+ members |> List.choose (function Method(_,_,_,_,_) as m -> Some(m) | _ -> None)
+
+// =======================================================================
+/// Returns all members of the program "prog" that pass the filter "filter"
+// =======================================================================
+let FilterMembers prog filter =
+ match prog with
+ | Program(components) ->
+ components |> List.fold (fun acc comp ->
+ match comp with
+ | Component(Class(_,_,members),_,_) -> List.concat [acc ; members |> filter |> List.choose (fun m -> Some(comp, m))]
| _ -> acc) []
// =================================
/// Returns all fields of a component
// =================================
let GetAllFields comp =
- match comp with
- | Component(Class(_,_,members), Model(_,_,cVars,_,_), _) ->
- let aVars = FilterFieldMembers members
+ match comp with
+ | Component(Class(_,_,members), Model(_,_,cVars,_,_), _) ->
+ let aVars = FilterFieldMembers members
List.concat [aVars ; cVars]
| _ -> []
@@ -333,6 +216,11 @@ let GetClassName comp =
| Component(Class(name,_,_),_,_) -> name
| _ -> failwith ("unrecognized component: " + comp.ToString())
+let GetClassType comp =
+ match comp with
+ | Component(Class(name,typeParams,_),_,_) -> NamedType(name, typeParams)
+ | _ -> failwith ("unrecognized component: " + comp.ToString())
+
// ========================
/// Returns name of a method
// ========================
@@ -355,14 +243,31 @@ let GetMethodSig mthd =
| Method(_,sgn,_,_,_) -> sgn
| _ -> failwith ("not a method: " + mthd.ToString())
+let GetMethodPrePost mthd =
+ match mthd with
+ | Method(_,_,pre,post,_) -> pre,post
+ | _ -> failwith ("not a method: " + mthd.ToString())
+
// =========================================================
/// Returns all arguments of a method (both input and output)
// =========================================================
+let GetSigVars sign =
+ match sign with
+ | Sig(ins, outs) -> List.concat [ins; outs]
+
let GetMethodArgs mthd =
match mthd with
| Method(_,Sig(ins, outs),_,_,_) -> List.concat [ins; outs]
| _ -> failwith ("not a method: " + mthd.ToString())
+let rec GetTypeShortName ty =
+ match ty with
+ | IntType -> "int"
+ | BoolType -> "bool"
+ | SetType(_) -> "set"
+ | SeqType(_) -> "seq"
+ | NamedType(n,_) | InstantiatedType(n,_) -> n
+
// ==============================================================
/// Returns all invariants of a component as a list of expressions
// ==============================================================
@@ -371,7 +276,14 @@ let GetInvariantsAsList comp =
| Component(Class(_,_,members), Model(_,_,_,_,inv), _) ->
let clsInvs = members |> List.choose (function Invariant(exprList) -> Some(exprList) | _ -> None) |> List.concat
List.append (SplitIntoConjunts inv) clsInvs
- | _ -> failwith ("unexpected kinf of component: %s" + comp.ToString())
+ | _ -> failwithf "unexpected kind of component: %O" comp
+
+// ==================================
+/// Returns variable name
+// ==================================
+let GetVarName var =
+ match var with
+ | Var(name,_) -> name
// ==================================
/// Returns all members of a component
@@ -409,51 +321,354 @@ let FindVar (prog: Program) clsName fldName =
GetAllFields comp |> List.filter (function Var(name,_) when name = fldName -> true | _ -> false)
|> Utils.ListToOption
| None -> None
+
+let AddPrecondition prog comp m e =
+ match prog, comp, m with
+ | Program(clist), Component(Class(cname, ctypeParams, members), model, code), Method(mn, sgn, pre, post, cstr) ->
+ let newMthd = Method(mn, sgn, BinaryAnd pre e, post, cstr)
+ let newCls = Class(cname, ctypeParams, Utils.ListReplace m newMthd members)
+ let newComp = Component(newCls, model, code)
+ let newProg = Program(Utils.ListReplace comp newComp clist)
+ newProg, newComp, newMthd
+ | _ -> failwithf "Not a method: %O" m
+
+////////////////////
+
+exception EvalFailed of string
+
+let DefaultResolver e = e
+
+let DefaultFallbackResolver resolverFunc e =
+ match resolverFunc e with
+ | Some(e') -> e'
+ | None -> e
+
+let __CheckEqual e1 e2 =
+ match e1, e2 with
+ | BoolLiteral(b1), BoolLiteral(b2) -> Some(b1 = b2)
+ | IntLiteral(n1), IntLiteral(n2) -> Some(n1 = n2)
+ | ObjLiteral(o1), ObjLiteral(o2) -> Some(o1 = o2)
+ | SetExpr(elist1), SetExpr(elist2) -> Some(Set.ofList elist1 = Set.ofList elist2)
+ | SequenceExpr(elist1), SequenceExpr(elist2) -> Some(elist1 = elist2)
+ | UnaryExpr("-", sub1), sub2
+ | sub1, UnaryExpr("-", sub2) when sub1 = sub2 -> Some(false)
+ | UnaryExpr("-", sub1), UnaryExpr("-", sub2) when sub1 = sub2 -> Some(true)
+ | UnaryExpr("!", sub1), sub2
+ | sub1, UnaryExpr("!", sub2) when sub1 = sub2 -> Some(false)
+ | UnaryExpr("!", sub1), UnaryExpr("-", sub2) when sub1 = sub2 -> Some(true)
+ | _ when e1 = e2 -> Some(true)
+ | _ -> None
+
+let rec __EvalSym resolverFunc ctx expr =
+ match expr with
+ | IntLiteral(_) -> expr
+ | BoolLiteral(_) -> expr
+ | ObjLiteral(_) -> expr
+ | Star -> expr //TODO: can we do better?
+ | VarLiteral(id) ->
+ try
+ let _,e = ctx |> List.find (fun (v,e) -> GetVarName v = id)
+ e
+ with
+ | ex -> resolverFunc expr
+ | IdLiteral(_) -> resolverFunc expr
+ | Dot(_) -> resolverFunc expr
+ | SeqLength(e) ->
+ let e' = __EvalSym resolverFunc ctx e
+ match e' with
+ | SequenceExpr(elist) -> IntLiteral(List.length elist)
+ | _ -> SeqLength(e')
+ | SequenceExpr(elist) ->
+ let elist' = elist |> List.fold (fun acc e -> __EvalSym resolverFunc ctx e :: acc) [] |> List.rev
+ SequenceExpr(elist')
+ | SetExpr(elist) ->
+ let eset' = elist |> List.fold (fun acc e -> Set.add (__EvalSym resolverFunc ctx e) acc) Set.empty
+ SetExpr(Set.toList eset')
+ | SelectExpr(lst, idx) ->
+ let lst', idx' = __EvalSym resolverFunc ctx lst, __EvalSym resolverFunc ctx idx
+ match lst', idx' with
+ | SequenceExpr(elist), IntLiteral(n) -> elist.[n]
+ | _ -> SelectExpr(lst', idx')
+ | UpdateExpr(lst,idx,v) ->
+ let lst', idx', v' = __EvalSym resolverFunc ctx lst, __EvalSym resolverFunc ctx idx, __EvalSym resolverFunc ctx v
+ match lst', idx', v' with
+ | SequenceExpr(elist), IntLiteral(n), _ -> SequenceExpr(Utils.ListSet n v' elist)
+ | _ -> UpdateExpr(lst', idx', v')
+ | IteExpr(c, e1, e2) ->
+ let c' = __EvalSym resolverFunc ctx c
+ match c' with
+ | BoolLiteral(b) -> if b then __EvalSym resolverFunc ctx e1 else __EvalSym resolverFunc ctx e2
+ | _ -> IteExpr(c', __EvalSym resolverFunc ctx e1, __EvalSym resolverFunc ctx e2)
+ | BinaryExpr(p,op,e1,e2) ->
+ let e1' = lazy (__EvalSym resolverFunc ctx e1)
+ let e2' = lazy (__EvalSym resolverFunc ctx e2)
+ let recomposed = lazy (BinaryExpr(p, op, e1'.Force(), e2'.Force()))
+ match op with
+ | "=" ->
+ let e1'' = e1'.Force()
+ let e2'' = e2'.Force()
+ let eq = __CheckEqual e1'' e2''
+ match eq with
+ | Some(b) -> BoolLiteral(b)
+ | None -> recomposed.Force()
+ | "!=" ->
+ let e1'' = e1'.Force()
+ let e2'' = e2'.Force()
+ let eq = __CheckEqual e1'' e2''
+ match eq with
+ | Some(b) -> BoolLiteral(not b)
+ | None -> recomposed.Force()
+ | "<" ->
+ match e1'.Force(), e2'.Force() with
+ | IntLiteral(n1), IntLiteral(n2) -> BoolLiteral(n1 < n2)
+ | SetExpr(s1), SetExpr(s2) -> BoolLiteral((List.length s1) < (List.length s2))
+ | SequenceExpr(s1), SequenceExpr(s2) -> BoolLiteral((List.length s1) < (List.length s2))
+ | _ -> recomposed.Force()
+ | "<=" ->
+ let e1'' = e1'.Force()
+ let e2'' = e2'.Force()
+ let eq = __CheckEqual e1'' e2''
+ match eq with
+ | Some(true) -> TrueLiteral
+ | _ -> match e1'', e2'' with
+ | IntLiteral(n1), IntLiteral(n2) -> BoolLiteral(n1 <= n2)
+ | SetExpr(s1), SetExpr(s2) -> BoolLiteral((List.length s1) <= (List.length s2))
+ | SequenceExpr(s1), SequenceExpr(s2) -> BoolLiteral((List.length s1) <= (List.length s2))
+ | _ -> recomposed.Force()
+ | ">" ->
+ match e1'.Force(), e2'.Force() with
+ | IntLiteral(n1), IntLiteral(n2) -> BoolLiteral(n1 > n2)
+ | SetExpr(s1), SetExpr(s2) -> BoolLiteral((List.length s1) > (List.length s2))
+ | SequenceExpr(s1), SequenceExpr(s2) -> BoolLiteral((List.length s1) > (List.length s2))
+ | _ -> recomposed.Force()
+ | ">=" ->
+ let e1'' = e1'.Force()
+ let e2'' = e2'.Force()
+ let eq = __CheckEqual e1'' e2''
+ match eq with
+ | Some(true) -> TrueLiteral
+ | _ -> match e1'', e2'' with
+ | IntLiteral(n1), IntLiteral(n2) -> BoolLiteral(n1 >= n2)
+ | SetExpr(s1), SetExpr(s2) -> BoolLiteral((List.length s1) >= (List.length s2))
+ | SequenceExpr(s1), SequenceExpr(s2) -> BoolLiteral((List.length s1) >= (List.length s2))
+ | _ -> recomposed.Force()
+ | "in" ->
+ match e1'.Force(), e2'.Force() with
+ | _, SetExpr(s)
+ | _, SequenceExpr(s) -> BoolLiteral(Utils.ListContains (e1'.Force()) s)
+ | _ -> recomposed.Force()
+ | "!in" ->
+ match e1'.Force(), e2'.Force() with
+ | _, SetExpr(s)
+ | _, SequenceExpr(s) -> BoolLiteral(not (Utils.ListContains (e1'.Force()) s))
+ | _ -> recomposed.Force()
+ | "+" ->
+ let e1'' = e1'.Force();
+ let e2'' = e2'.Force();
+ match e1'', e2'' with
+ | IntLiteral(n1), IntLiteral(n2) -> IntLiteral(n1 + n2)
+ | SequenceExpr(l1), SequenceExpr(l2) -> SequenceExpr(List.append l1 l2)
+ | SetExpr(s1), SetExpr(s2) -> SetExpr(Set.union (Set.ofList s1) (Set.ofList s2) |> Set.toList)
+ | SetExpr(s), _ -> SetExpr(Set.add e2'' (Set.ofList s) |> Set.toList)
+ | _, SetExpr(s) -> SetExpr(Set.add e1'' (Set.ofList s) |> Set.toList)
+ | _ -> recomposed.Force()
+ | "-" ->
+ match e1'.Force(), e2'.Force() with
+ | IntLiteral(n1), IntLiteral(n2) -> IntLiteral(n1 - n2)
+ | SetExpr(s1), SetExpr(s2) -> SetExpr(Set.difference (Set.ofList s1) (Set.ofList s2) |> Set.toList)
+ | _ -> recomposed.Force()
+ | "*" ->
+ match e1'.Force(), e2'.Force() with
+ | IntLiteral(n1), IntLiteral(n2) -> IntLiteral(n1 * n2)
+ | _ -> recomposed.Force()
+ | "div" ->
+ match e1'.Force(), e2'.Force() with
+ | IntLiteral(n1), IntLiteral(n2) -> IntLiteral(n1 / n2)
+ | _ -> recomposed.Force()
+ | "mod" ->
+ match e1'.Force(), e2'.Force() with
+ | IntLiteral(n1), IntLiteral(n2) -> IntLiteral(n1 % n2)
+ | _ -> recomposed.Force()
+ | "&&" ->
+ // shortcircuit
+ match e1'.Force() with
+ | BoolLiteral(false) -> BoolLiteral(false)
+ | _ ->
+ match e1'.Force(), e2'.Force() with
+ | BoolLiteral(false), _ -> BoolLiteral(false)
+ | _, BoolLiteral(false) -> BoolLiteral(false)
+ | BoolLiteral(b1), BoolLiteral(b2) -> BoolLiteral(b1 && b2)
+ | _ -> BinaryAnd (e1'.Force()) (e2'.Force())
+ | "||" ->
+ // shortcircuit
+ match e1'.Force() with
+ | BoolLiteral(true) -> BoolLiteral(true)
+ | _ ->
+ match e1'.Force(), e2'.Force() with
+ | BoolLiteral(true), _ -> BoolLiteral(true)
+ | _, BoolLiteral(true) -> BoolLiteral(true)
+ | BoolLiteral(b1), BoolLiteral(b2) -> BoolLiteral(b1 || b2)
+ | _ -> BinaryOr (e1'.Force()) (e2'.Force())
+ | "==>" ->
+ // shortcircuit
+ match e1'.Force() with
+ | BoolLiteral(false) -> BoolLiteral(true)
+ | _ ->
+ match e1'.Force(), e2'.Force() with
+ | BoolLiteral(false), _ -> BoolLiteral(true)
+ | _, BoolLiteral(true) -> BoolLiteral(true)
+ | BoolLiteral(b1), BoolLiteral(b2) -> BoolLiteral((not b1) || b2)
+ | _ -> BinaryImplies (e1'.Force()) (e2'.Force())
+ | "<==>" ->
+ match e1'.Force(), e2'.Force() with
+ | BoolLiteral(b1), BoolLiteral(b2) -> BoolLiteral(b1 = b2)
+ | x, BoolLiteral(b)
+ | BoolLiteral(b), x -> if b then x else UnaryNot(x)
+ | _ -> recomposed.Force()
+ | _ -> recomposed.Force()
+ | UnaryExpr(op, e) ->
+ let e' = __EvalSym resolverFunc ctx e
+ let recomposed = UnaryExpr(op, e')
+ match op with
+ | "!" ->
+ match e' with
+ | BoolLiteral(b) -> BoolLiteral(not b)
+ | _ -> recomposed
+ | "-" ->
+ match e' with
+ | IntLiteral(n) -> IntLiteral(-n)
+ | _ -> recomposed
+ | _ -> recomposed
+ | ForallExpr(vars, e) ->
+ let rec __ExhaustVar v restV vDomain =
+ match vDomain with
+ | vv :: restD ->
+ let newCtx = (v,vv) :: ctx
+ let e = __EvalSym resolverFunc newCtx (ForallExpr(restV, e))
+ let erest = __ExhaustVar v restV restD
+ __EvalSym resolverFunc ctx (BinaryAnd e erest)
+ | [] -> BoolLiteral(true)
+ match vars with
+ | v :: restV ->
+ let vDom = GetVarDomain resolverFunc v e
+ __ExhaustVar v restV vDom
+ | [] -> __EvalSym resolverFunc ctx e
+and GetVarDomain resolverFunc var expr =
+ //TODO: don't hardcode this!!!
+ let elems = __EvalSym resolverFunc [] (Dot(ObjLiteral("this"), "elems"))
+ match elems with
+ | SetExpr(elist) -> elist
+ | _ -> failwith "this is bogus"
+
+let EvalSym resolverFunc expr =
+ __EvalSym resolverFunc [] expr
// ==========================================================
/// Desugars a given expression so that all list constructors
/// are expanded into explicit assignments to indexed elements
// ==========================================================
let rec Desugar expr =
- match expr with
- | IntLiteral(_)
- | IdLiteral(_)
- | Star
- | Dot(_)
- | SelectExpr(_)
- | SeqLength(_) -> expr
- | UpdateExpr(_) -> expr //TODO
- | SequenceExpr(exs) -> expr //TODO
- | ForallExpr(v,e) -> ForallExpr(v, Desugar e)
- | UnaryExpr(op,e) -> UnaryExpr(op, Desugar e)
+ match expr with
+ | IntLiteral(_)
+ | BoolLiteral(_)
+ | IdLiteral(_)
+ | VarLiteral(_)
+ | ObjLiteral(_)
+ | Star
+ | Dot(_)
+ | SelectExpr(_)
+ | SeqLength(_)
+ | UpdateExpr(_)
+ | SetExpr(_)
+ | SequenceExpr(_) -> expr
+ | ForallExpr(v,e) -> ForallExpr(v, Desugar e)
+ | UnaryExpr(op,e) -> UnaryExpr(op, Desugar e)
+ | IteExpr(c,e1,e2) -> IteExpr(c, Desugar e1, Desugar e2)
| BinaryExpr(p,op,e1,e2) ->
let be = BinaryExpr(p, op, Desugar e1, Desugar e2)
try
match op with
- | Exact "=" _ ->
- match EvalSym e1, EvalSym e2 with
- | VarConst(v), SeqConst(clist)
- | SeqConst(clist), VarConst(v) ->
- let rec __fff lst cnt =
- match lst with
- | fs :: rest -> BinaryEq (SelectExpr(IdLiteral(v), IntLiteral(cnt))) (Const2Expr (Utils.ExtractOption clist.[cnt])) :: __fff rest (cnt+1)
- | [] -> []
- __fff clist 0 |> List.fold (fun acc e -> BinaryAnd acc e) be
- | SeqConst(cl1), SeqConst(cl2) ->
+ | "=" ->
+ match EvalSym DefaultResolver e1, EvalSym DefaultResolver e2 with
+ | SequenceExpr(l1), SequenceExpr(l2) ->
let rec __fff lst1 lst2 cnt =
match lst1, lst2 with
- | fs1 :: rest1, fs2 :: rest2 -> BinaryEq (Const2Expr (Utils.ExtractOption cl1.[cnt])) (Const2Expr (Utils.ExtractOption cl2.[cnt])) :: __fff rest1 rest2 (cnt+1)
+ | fs1 :: rest1, fs2 :: rest2 -> BinaryEq l1.[cnt] l2.[cnt] :: __fff rest1 rest2 (cnt+1)
| [], [] -> []
| _ -> failwith "Lists are of different sizes"
- __fff cl1 cl2 0 |> List.fold (fun acc e -> BinaryAnd acc e) be
+ __fff l1 l2 0 |> List.fold (fun acc e -> BinaryAnd acc e) be
+ | e, SequenceExpr(elist)
+ | SequenceExpr(elist), e ->
+ let rec __fff lst cnt =
+ match lst with
+ | fs :: rest -> BinaryEq (SelectExpr(e, IntLiteral(cnt))) elist.[cnt] :: __fff rest (cnt+1)
+ | [] -> []
+ __fff elist 0 |> List.fold (fun acc e -> BinaryAnd acc e) be
| _ -> be
| _ -> be
with
- | EvalFailed as ex -> (* printfn "%s" (ex.StackTrace.ToString()); *) be
-
+ | EvalFailed(_) as ex -> (* printfn "%O" (ex.StackTrace); *) be
let rec DesugarLst exprLst =
match exprLst with
| expr :: rest -> Desugar expr :: DesugarLst rest
| [] -> []
+let ChangeThisReceiver receiver expr =
+ let rec __ChangeThis locals expr =
+ match expr with
+ | IntLiteral(_)
+ | BoolLiteral(_)
+ | Star
+ | VarLiteral(_) -> expr
+ | ObjLiteral("this") -> receiver
+ | ObjLiteral(_) -> expr
+ | IdLiteral("null") -> failwith "should never happen anymore" //TODO
+ | IdLiteral("this") -> failwith "should never happen anymore"
+ | IdLiteral(id) -> if Set.contains id locals then VarLiteral(id) else __ChangeThis locals (Dot(ObjLiteral("this"), id))
+ | Dot(e, id) -> Dot(__ChangeThis locals e, id)
+ | ForallExpr(vars,e) -> let newLocals = vars |> List.map (function Var(name,_) -> name) |> Set.ofList |> Set.union locals
+ ForallExpr(vars, __ChangeThis newLocals e)
+ | UnaryExpr(op,e) -> UnaryExpr(op, __ChangeThis locals e)
+ | SeqLength(e) -> SeqLength(__ChangeThis locals e)
+ | SelectExpr(e1, e2) -> SelectExpr(__ChangeThis locals e1, __ChangeThis locals e2)
+ | BinaryExpr(p,op,e1,e2) -> BinaryExpr(p, op, __ChangeThis locals e1, __ChangeThis locals e2)
+ | IteExpr(e1,e2,e3) -> IteExpr(__ChangeThis locals e1, __ChangeThis locals e2, __ChangeThis locals e3)
+ | UpdateExpr(e1,e2,e3) -> UpdateExpr(__ChangeThis locals e1, __ChangeThis locals e2, __ChangeThis locals e3)
+ | SequenceExpr(exs) -> SequenceExpr(exs |> List.map (__ChangeThis locals))
+ | SetExpr(exs) -> SetExpr(exs |> List.map (__ChangeThis locals))
+ (* function body starts here *)
+ __ChangeThis Set.empty expr
+
+let rec Rewrite rewriterFunc expr =
+ let __RewriteOrRecurse e =
+ match rewriterFunc e with
+ | Some(ee) -> ee
+ | None -> Rewrite rewriterFunc e
+ match expr with
+ | IntLiteral(_)
+ | BoolLiteral(_)
+ | Star
+ | VarLiteral(_)
+ | ObjLiteral(_)
+ | IdLiteral(_) -> match rewriterFunc expr with
+ | Some(e) -> e
+ | None -> expr
+ | Dot(e, id) -> Dot(__RewriteOrRecurse e, id)
+ | ForallExpr(vars,e) -> ForallExpr(vars, __RewriteOrRecurse e)
+ | UnaryExpr(op,e) -> UnaryExpr(op, __RewriteOrRecurse e)
+ | SeqLength(e) -> SeqLength(__RewriteOrRecurse e)
+ | SelectExpr(e1, e2) -> SelectExpr(__RewriteOrRecurse e1, __RewriteOrRecurse e2)
+ | BinaryExpr(p,op,e1,e2) -> BinaryExpr(p, op, __RewriteOrRecurse e1, __RewriteOrRecurse e2)
+ | IteExpr(e1,e2,e3) -> IteExpr(__RewriteOrRecurse e1, __RewriteOrRecurse e2, __RewriteOrRecurse e3)
+ | UpdateExpr(e1,e2,e3) -> UpdateExpr(__RewriteOrRecurse e1, __RewriteOrRecurse e2, __RewriteOrRecurse e3)
+ | SequenceExpr(exs) -> SequenceExpr(exs |> List.map __RewriteOrRecurse)
+ | SetExpr(exs) -> SetExpr(exs |> List.map __RewriteOrRecurse)
+
+let RewriteVars vars expr =
+ let __IdIsArg id = vars |> List.exists (function Var(name,_) -> name = id)
+ Rewrite (fun e ->
+ match e with
+ | IdLiteral(id) when __IdIsArg id -> Some(VarLiteral(id))
+ | _ -> None) expr
+ \ No newline at end of file
diff --git a/Jennisys/Jennisys/CodeGen.fs b/Jennisys/Jennisys/CodeGen.fs
index 7e61ec7e..5d7f8611 100644
--- a/Jennisys/Jennisys/CodeGen.fs
+++ b/Jennisys/Jennisys/CodeGen.fs
@@ -2,7 +2,7 @@
open Ast
open AstUtils
-open Utils
+open Utils
open Printer
open Resolver
open TypeChecker
@@ -18,143 +18,154 @@ let rec GetUnrolledFieldValidExpr fldExpr fldName validFunName numUnrolls : Expr
(BinaryAnd (Dot(fldExpr, validFunName))
(GetUnrolledFieldValidExpr (Dot(fldExpr, fldName)) fldName validFunName (numUnrolls-1)))
-let GetFieldValidExpr fldName validFunName numUnrolls : Expr =
- GetUnrolledFieldValidExpr (IdLiteral(fldName)) fldName validFunName numUnrolls
- //BinaryImplies (BinaryNeq (IdLiteral(fldName)) (IdLiteral("null"))) (Dot(IdLiteral(fldName), validFunName))
-
-let GetFieldsForValidExpr allFields prog : VarDecl list =
- allFields |> List.filter (function Var(name, tp) when IsUserType prog tp -> true
- | _ -> false)
-
-let GetFieldsValidExprList clsName allFields prog : Expr list =
- let fields = GetFieldsForValidExpr allFields prog
- fields |> List.map (function Var(name, t) ->
- let validFunName, numUnrolls =
- match t with
- | Some(ty) when clsName = (PrintType ty) -> "Valid_self()", numLoopUnrolls
- | _ -> "Valid()", 1
- GetFieldValidExpr name validFunName numUnrolls
- )
-
-let PrintValidFunctionCode comp prog : string =
- let clsName = GetClassName comp
- let vars = GetAllFields comp
- let allInvs = GetInvariantsAsList comp
- let fieldsValid = GetFieldsValidExprList clsName vars prog
- let idt = " "
- let PrintInvs invs =
- invs |> List.fold (fun acc e -> List.concat [acc ; SplitIntoConjunts e]) []
- |> PrintSep (" &&" + newline) (fun e -> sprintf "%s(%s)" idt (PrintExpr 0 e))
- |> fun s -> if s = "" then (idt + "true") else s
- // TODO: don't hardcode decr vars!!!
-// let decrVars = if List.choose (function Var(n,_) -> Some(n)) vars |> List.exists (fun n -> n = "next") then
-// ["list"]
-// else
-// []
-// (if List.isEmpty decrVars then "" else sprintf " decreases %s;%s" (PrintSep ", " (fun a -> a) decrVars) newline) +
- " function Valid_self(): bool" + newline +
- " reads *;" + newline +
- " {" + newline +
- (PrintInvs allInvs) + newline +
- " }" + newline +
- newline +
- " function Valid(): bool" + newline +
- " reads *;" + newline +
- " {" + newline +
- " this.Valid_self() &&" + newline +
- (PrintInvs fieldsValid) + newline +
+let GetFieldValidExpr fldName validFunName numUnrolls : Expr =
+ GetUnrolledFieldValidExpr (IdLiteral(fldName)) fldName validFunName numUnrolls
+
+let GetFieldsForValidExpr allFields prog : VarDecl list =
+ allFields |> List.filter (function Var(name, tp) when IsUserType prog tp -> true
+ | _ -> false)
+
+let GetFieldsValidExprList clsName allFields prog : Expr list =
+ let fields = GetFieldsForValidExpr allFields prog
+ fields |> List.map (function Var(name, t) ->
+ let validFunName, numUnrolls =
+ match t with
+ | Some(ty) when clsName = (GetTypeShortName ty) -> "Valid_self()", numLoopUnrolls
+ | _ -> "Valid()", 1
+ GetFieldValidExpr name validFunName numUnrolls
+ )
+
+let PrintValidFunctionCode comp prog : string =
+ let idt = " "
+ let __PrintInvs invs =
+ invs |> List.fold (fun acc e -> List.concat [acc ; SplitIntoConjunts e]) []
+ |> PrintSep (" &&" + newline) (fun e -> sprintf "%s(%s)" idt (PrintExpr 0 e))
+ |> fun s -> if s = "" then (idt + "true") else s
+ let clsName = GetClassName comp
+ let vars = GetAllFields comp
+ let allInvs = GetInvariantsAsList comp |> DesugarLst
+ let fieldsValid = GetFieldsValidExprList clsName vars prog
+
+ // TODO: don't hardcode decr vars!!!
+// let decrVars = if List.choose (function Var(n,_) -> Some(n)) vars |> List.exists (fun n -> n = "next") then
+// ["list"]
+// else
+// []
+// (if List.isEmpty decrVars then "" else sprintf " decreases %s;%s" (PrintSep ", " (fun a -> a) decrVars) newline) +
+ " function Valid_self(): bool" + newline +
+ " reads *;" + newline +
+ " {" + newline +
+ (__PrintInvs allInvs) + newline +
+ " }" + newline +
+ newline +
+ " function Valid(): bool" + newline +
+ " reads *;" + newline +
+ " {" + newline +
+ " this.Valid_self() &&" + newline +
+ (__PrintInvs fieldsValid) + newline +
" }" + newline
-let PrintDafnyCodeSkeleton prog methodPrinterFunc: string =
- match prog with
- | Program(components) -> components |> List.fold (fun acc comp ->
- match comp with
- | Component(Class(name,typeParams,members), Model(_,_,cVars,frame,inv), code) as comp ->
- let aVars = FilterFieldMembers members
- let allVars = List.concat [aVars ; cVars];
- let compMethods = FilterConstructorMembers members
- // Now print it as a Dafny program
- acc +
- (sprintf "class %s%s {" name (PrintTypeParams typeParams)) + newline +
- // the fields: original abstract fields plus concrete fields
- (sprintf "%s" (PrintFields aVars 2 true)) + newline +
- (sprintf "%s" (PrintFields cVars 2 false)) + newline +
- // generate the Valid function
- (sprintf "%s" (PrintValidFunctionCode comp prog)) + newline +
- // call the method printer function on all methods of this component
- (compMethods |> List.fold (fun acc m -> acc + (methodPrinterFunc comp m)) "") +
- // the end of the class
- "}" + newline + newline
+let PrintDafnyCodeSkeleton prog methodPrinterFunc: string =
+ match prog with
+ | Program(components) -> components |> List.fold (fun acc comp ->
+ match comp with
+ | Component(Class(name,typeParams,members), Model(_,_,cVars,frame,inv), code) as comp ->
+ let aVars = FilterFieldMembers members
+ let allVars = List.concat [aVars ; cVars];
+ let compMethods = FilterConstructorMembers members
+ // Now print it as a Dafny program
+ acc +
+ (sprintf "class %s%s {" name (PrintTypeParams typeParams)) + newline +
+ // the fields: original abstract fields plus concrete fields
+ (sprintf "%s" (PrintFields aVars 2 true)) + newline +
+ (sprintf "%s" (PrintFields cVars 2 false)) + newline +
+ // generate the Valid function
+ (sprintf "%s" (PrintValidFunctionCode comp prog)) + newline +
+ // call the method printer function on all methods of this component
+ (compMethods |> List.fold (fun acc m -> acc + (methodPrinterFunc comp m)) "") +
+ // the end of the class
+ "}" + newline + newline
| _ -> assert false; "") ""
-let PrintAllocNewObjects (heap,env,ctx) indent =
- let idt = Indent indent
- env |> Map.fold (fun acc l v ->
- match v with
- | NewObj(_,_) -> acc |> Set.add v
- | _ -> acc
- ) Set.empty
- |> Set.fold (fun acc newObjConst ->
- match newObjConst with
- | NewObj(name, Some(tp)) -> acc + (sprintf "%svar %s := new %s;%s" idt (PrintGenSym name) (PrintType tp) newline)
- | _ -> failwith ("NewObj doesn't have a type: " + newObjConst.ToString())
- ) ""
-
-let PrintObjRefName o (env,ctx) =
- match Resolve o (env,ctx) with
- | ThisConst(_,_) -> "this";
- | NewObj(name, _) -> PrintGenSym name
- | _ -> failwith ("unresolved object ref: " + o.ToString())
-
-let PrintVarAssignments (heap,env,ctx) indent =
- let idt = Indent indent
- heap |> Map.fold (fun acc (o,f) l ->
- let objRef = PrintObjRefName o (env,ctx)
- let fldName = PrintVarName f
- let value = Resolve l (env,ctx) |> PrintConst
- acc + (sprintf "%s%s.%s := %s;" idt objRef fldName value) + newline
- ) ""
-
-let PrintHeapCreationCode (heap,env,ctx) indent =
- (PrintAllocNewObjects (heap,env,ctx) indent) +
- (PrintVarAssignments (heap,env,ctx) indent)
-
-let GenConstructorCode mthd body =
- let validExpr = IdLiteral("Valid()");
- match mthd with
- | Method(methodName, sign, pre, post, _) ->
- let preExpr = BinaryAnd validExpr pre
- let postExpr = BinaryAnd validExpr post
- let PrintPrePost pfix expr = SplitIntoConjunts expr |> PrintSep newline (fun e -> pfix + (PrintExpr 0 e) + ";")
- " method " + methodName + (PrintSig sign) + newline +
- " modifies this;" + newline +
- (PrintPrePost " requires " preExpr) + newline +
- (PrintPrePost " ensures " postExpr) + newline +
- " {" + newline +
- body +
- " }" + newline
- | _ -> ""
-
-// NOTE: insert here coto to say which methods to analyze
-let GetMethodsToAnalyze prog =
- (* exactly one *)
-// let c = FindComponent prog "IntList" |> Utils.ExtractOption
-// let m = FindMethod c "Sum" |> Utils.ExtractOption
-// [c, m]
- (* all *)
- FilterMembers prog FilterConstructorMembers
- (* only with parameters *)
-// FilterMembers prog FilterConstructorMembersWithParams
-
-// solutions: (comp, constructor) |--> (heap, env, ctx)
-let PrintImplCode prog solutions methodsToPrintFunc =
- let methods = methodsToPrintFunc prog
- PrintDafnyCodeSkeleton prog (fun comp mthd ->
- if Utils.ListContains (comp,mthd) methods then
- let mthdBody = match Map.tryFind (comp,mthd) solutions with
- | Some(heap,env,ctx) -> PrintHeapCreationCode (heap,env,ctx) 4
- | _ -> " //unable to synthesize" + newline
- (GenConstructorCode mthd mthdBody) + newline
- else
- ""
- ) \ No newline at end of file
+let PrintAllocNewObjects (heap,env,ctx) indent =
+ let idt = Indent indent
+ env |> Map.fold (fun acc l v ->
+ match v with
+ | NewObj(_,_) -> acc |> Set.add v
+ | _ -> acc
+ ) Set.empty
+ |> Set.fold (fun acc newObjConst ->
+ match newObjConst with
+ | NewObj(name, Some(tp)) -> acc + (sprintf "%svar %s := new %s;%s" idt (PrintGenSym name) (PrintType tp) newline)
+ | _ -> failwithf "NewObj doesn't have a type: %O" newObjConst
+ ) ""
+
+let PrintObjRefName o (env,ctx) =
+ match Resolve (env,ctx) o with
+ | ThisConst(_,_) -> "this";
+ | NewObj(name, _) -> PrintGenSym name
+ | _ -> failwith ("unresolved object ref: " + o.ToString())
+
+let CheckUnresolved c =
+ match c with
+ | Unresolved(_) -> Logger.WarnLine "!!! There are some unresolved constants in the output file !!!"; c
+ | _ -> c
+
+let PrintVarAssignments (heap,env,ctx) indent =
+ let idt = Indent indent
+ heap |> Map.fold (fun acc (o,f) l ->
+ let objRef = PrintObjRefName o (env,ctx)
+ let fldName = PrintVarName f
+ let value = TryResolve (env,ctx) l |> CheckUnresolved |> PrintConst
+ acc + (sprintf "%s%s.%s := %s;" idt objRef fldName value) + newline
+ ) ""
+
+let rec PrintHeapCreationCode sol indent =
+ let idt = Indent indent
+ match sol with
+ | (c, (heap,env,ctx)) :: rest ->
+ if c = TrueLiteral then
+ (PrintAllocNewObjects (heap,env,ctx) indent) +
+ (PrintVarAssignments (heap,env,ctx) indent) +
+ newline +
+ (PrintHeapCreationCode rest indent)
+ else
+ if List.length rest > 0 then
+ idt + "if (" + (PrintExpr 0 c) + ") {" + newline +
+ (PrintAllocNewObjects (heap,env,ctx) (indent+2)) +
+ (PrintVarAssignments (heap,env,ctx) (indent+2)) +
+ idt + "} else {" + newline +
+ (PrintHeapCreationCode rest (indent+2)) +
+ idt + "}" + newline
+ else
+ (PrintAllocNewObjects (heap,env,ctx) indent) +
+ (PrintVarAssignments (heap,env,ctx) indent)
+ | [] -> ""
+
+let GenConstructorCode mthd body =
+ let validExpr = IdLiteral("Valid()");
+ match mthd with
+ | Method(methodName, sign, pre, post, _) ->
+ let __PrintPrePost pfix expr = SplitIntoConjunts expr |> PrintSep newline (fun e -> pfix + (PrintExpr 0 e) + ";")
+ let preExpr = pre
+ let postExpr = BinaryAnd validExpr post
+ " method " + methodName + (PrintSig sign) + newline +
+ " modifies this;" + newline +
+ (__PrintPrePost " requires " preExpr) + newline +
+ (__PrintPrePost " ensures " postExpr) + newline +
+ " {" + newline +
+ body +
+ " }" + newline
+ | _ -> ""
+
+// solutions: (comp, constructor) |--> (heap, env, ctx)
+let PrintImplCode prog solutions methodsToPrintFunc =
+ let methods = methodsToPrintFunc prog
+ PrintDafnyCodeSkeleton prog (fun comp mthd ->
+ if Utils.ListContains (comp,mthd) methods then
+ let mthdBody = match Map.tryFind (comp,mthd) solutions with
+ | Some(sol) -> PrintHeapCreationCode sol 4
+ | _ -> " //unable to synthesize" + newline
+ (GenConstructorCode mthd mthdBody) + newline
+ else
+ "") \ No newline at end of file
diff --git a/Jennisys/Jennisys/DafnyModelUtils.fs b/Jennisys/Jennisys/DafnyModelUtils.fs
index 6e78dc33..4b9b0c60 100644
--- a/Jennisys/Jennisys/DafnyModelUtils.fs
+++ b/Jennisys/Jennisys/DafnyModelUtils.fs
@@ -1,4 +1,10 @@
-module DafnyModelUtils
+// #########################################################################
+/// Utilities for reading/building models from Boogie Visual Debugger files
+///
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// #########################################################################
+
+module DafnyModelUtils
(*
The heap maps objects and fields to locations.
@@ -18,21 +24,18 @@ open AstUtils
open Utils
open Microsoft.Boogie
-
-/// special object ref constant that will hold method argument values
-let argsObjRefConst = Unresolved("*0")
-
+
let GetElemFullName (elem: Model.Element) =
- elem.Names |> Seq.filter (fun ft -> ft.Func.Arity = 0)
- |> Seq.choose (fun ft -> Some(ft.Func.Name))
+ elem.Names |> Seq.filter (fun ft -> ft.Func.Arity = 0)
+ |> Seq.choose (fun ft -> Some(ft.Func.Name))
|> Utils.SeqToOption
let GetElemName (elem: Model.Element) =
- let fullNameOpt = GetElemFullName elem
- match fullNameOpt with
- | Some(fullName) ->
- let dotIdx = fullName.LastIndexOf(".")
- let fldName = fullName.Substring(dotIdx + 1)
+ let fullNameOpt = GetElemFullName elem
+ match fullNameOpt with
+ | Some(fullName) ->
+ let dotIdx = fullName.LastIndexOf(".")
+ let fldName = fullName.Substring(dotIdx + 1)
let clsName = if dotIdx = -1 then "" else fullName.Substring(0, dotIdx)
Some(clsName, fldName)
| None -> None
@@ -60,22 +63,31 @@ let GetBool (elem: Model.Element) =
| :? Model.Boolean as bval -> bval.Value
| _ -> failwith ("not a bool element: " + elem.ToString())
-let GetType (e: Model.Element) =
+let GetType (e: Model.Element) prog =
let fNameOpt = GetElemFullName e
match fNameOpt with
| Some(fname) -> match fname with
- | Exact "intType" _ -> Some(IntType)
- | Prefix "class." clsName -> Some(NamedType(clsName))
+ | "intType" -> Some(IntType)
+ | Prefix "class." clsName ->
+ match FindComponent prog clsName with
+ | Some(comp) -> Some(GetClassType comp)
+ | None -> None
| _ -> None
| None -> None
let GetLoc (e: Model.Element) =
Unresolved(GetRefName e)
-let GetSeqFromEnv env key =
+let FindSeqInEnv env key =
match Map.find key env with
| SeqConst(lst) -> lst
| _ as x-> failwith ("not a SeqConst but: " + x.ToString())
+
+let TryFindSetInEnv env key =
+ match Map.tryFind key env with
+ | Some(SetConst(s)) -> Some(s)
+ | Some(x) -> failwith ("not a SetConst but: " + x.ToString())
+ | None -> None
let AddConstr c1 c2 ctx =
if c1 = c2 then
@@ -100,8 +112,8 @@ let rec UpdateContext lst1 lst2 ctx =
match lst1, lst2 with
| fs1 :: rest1, fs2 :: rest2 ->
match fs1, fs2 with
- | Some(c1), Some(c2) -> UpdateContext rest1 rest2 (AddConstr c1 c2 ctx)
- | _ -> UpdateContext rest1 rest2 ctx
+ | NoneConst,_ | _,NoneConst -> UpdateContext rest1 rest2 ctx
+ | _ -> UpdateContext rest1 rest2 (AddConstr fs1 fs2 ctx)
| [], [] -> ctx
| _ -> failwith "lists are not of the same length"
@@ -115,110 +127,227 @@ let UnboxIfNeeded (model: Microsoft.Boogie.Model) (e: Model.Element) =
| None -> GetLoc e
let ReadHeap (model: Microsoft.Boogie.Model) prog =
- let f_heap_select = model.MkFunc("[3]", 3)
- let values = f_heap_select.Apps
- values |> Seq.fold (fun acc ft ->
- assert (ft.Args.Length = 3)
- let ref = ft.Args.[1]
- let fld = ft.Args.[2]
- assert (Seq.length fld.Names = 1)
- let fldFullName = (Seq.nth 0 fld.Names).Func.Name
- let dotIdx = fldFullName.LastIndexOf(".")
- let fldName = fldFullName.Substring(dotIdx + 1)
- let clsName = if dotIdx = -1 then "" else fldFullName.Substring(0, dotIdx)
- let refVal = ft.Result
- let refObj = Unresolved(GetRefName ref)
- let fldVarOpt = FindVar prog clsName fldName
- match fldVarOpt with
- | Some(fldVar) ->
- let fldType = match fldVar with
- | Var(_,t) -> t
- let fldVal = ConvertValue model refVal
- acc |> Map.add (refObj, fldVar) fldVal
- | None -> acc
+ let f_heap_select = model.MkFunc("[3]", 3)
+ let values = f_heap_select.Apps
+ values |> Seq.fold (fun acc ft ->
+ assert (ft.Args.Length = 3)
+ let ref = ft.Args.[1]
+ let fld = ft.Args.[2]
+ assert (Seq.length fld.Names = 1)
+ let fldFullName = (Seq.nth 0 fld.Names).Func.Name
+ let dotIdx = fldFullName.LastIndexOf(".")
+ let fldName = fldFullName.Substring(dotIdx + 1)
+ let clsName = if dotIdx = -1 then "" else fldFullName.Substring(0, dotIdx)
+ let refVal = ft.Result
+ let refObj = Unresolved(GetRefName ref)
+ let fldVarOpt = FindVar prog clsName fldName
+ match fldVarOpt with
+ | Some(fldVar) ->
+ let fldType = match fldVar with
+ | Var(_,t) -> t
+ let fldVal = ConvertValue model refVal
+ acc |> Map.add (refObj, fldVar) fldVal
+ | None -> acc
) Map.empty
+// ====================================================================
+/// Reads values that were assigned to given arguments. Those values
+/// can be in functions with the same name as the argument name appended
+/// with an "#" and some number after it.
+// ====================================================================
let rec ReadArgValues (model: Microsoft.Boogie.Model) args =
match args with
| Var(name,_) as v :: rest ->
let farg = model.Functions |> Seq.filter (fun f -> f.Arity = 0 && f.Name.StartsWith(name + "#")) |> Utils.SeqToOption
match farg with
| Some(func) ->
- let refObj = argsObjRefConst
let fldVar = v
assert (Seq.length func.Apps = 1)
let ft = Seq.head func.Apps
let fldVal = ConvertValue model (ft.Result)
- ReadArgValues model rest |> Map.add (VarConst(name)) fldVal
+ ReadArgValues model rest |> Map.add (Unresolved(name)) fldVal
| None -> failwith ("cannot find corresponding function for parameter " + name)
| [] -> Map.empty
-let rec ReadSeqLen (model: Microsoft.Boogie.Model) (len_tuples: Model.FuncTuple list) (envMap,ctx) =
- match len_tuples with
- | ft :: rest ->
- let len = GetInt ft.Result
- let emptyList = Utils.GenList len
- let newMap = envMap |> Map.add (GetLoc ft.Args.[0]) (SeqConst(emptyList))
- ReadSeqLen model rest (newMap,ctx)
- | _ -> (envMap,ctx)
-
-let rec ReadSeqIndex (model: Microsoft.Boogie.Model) (idx_tuples: Model.FuncTuple list) (envMap,ctx) =
- match idx_tuples with
- | ft :: rest ->
- let srcLstKey = GetLoc ft.Args.[0]
- let oldLst = GetSeqFromEnv envMap srcLstKey
- let idx = GetInt ft.Args.[1]
- let lstElem = UnboxIfNeeded model ft.Result
- let newLst = Utils.ListSet idx (Some(lstElem)) oldLst
- let newCtx = UpdateContext oldLst newLst ctx
- let newEnv = envMap |> Map.add srcLstKey (SeqConst(newLst))
- ReadSeqIndex model rest (newEnv,newCtx)
- | _ -> (envMap,ctx)
-
-let rec ReadSeqBuild (model: Microsoft.Boogie.Model) (bld_tuples: Model.FuncTuple list) (envMap,ctx) =
- match bld_tuples with
- | ft :: rest ->
- let srcLstLoc = GetLoc ft.Args.[0]
- let dstLstLoc = GetLoc ft.Result
- let oldLst = GetSeqFromEnv envMap srcLstLoc
- let idx = GetInt ft.Args.[1]
- let lstElemVal = UnboxIfNeeded model ft.Args.[2]
- let dstLst = GetSeqFromEnv envMap dstLstLoc
- let newLst = Utils.ListBuild oldLst idx (Some(lstElemVal)) dstLst
- let newCtx = UpdateContext dstLst newLst ctx
- let newEnv = envMap |> Map.add dstLstLoc (SeqConst(newLst))
- ReadSeqBuild model rest (newEnv,newCtx)
- | _ -> (envMap,ctx)
-
-let rec ReadSeqAppend (model: Microsoft.Boogie.Model) (app_tuples: Model.FuncTuple list) (envMap,ctx) =
- match app_tuples with
- | ft :: rest ->
- let srcLst1Loc = GetLoc ft.Args.[0]
- let srcLst2Loc = GetLoc ft.Args.[1]
- let dstLstLoc = GetLoc ft.Result
- let oldLst1 = GetSeqFromEnv envMap srcLst1Loc
- let oldLst2 = GetSeqFromEnv envMap srcLst2Loc
- let dstLst = GetSeqFromEnv envMap dstLstLoc
- let newLst = List.append oldLst1 oldLst2
- let newCtx = UpdateContext dstLst newLst ctx
- let newEnv = envMap |> Map.add dstLstLoc (SeqConst(newLst))
- ReadSeqAppend model rest (newEnv,newCtx)
- | _ -> (envMap,ctx)
-
+// ==============================================================
+/// Reads stuff about sequences from a given model and ads it to
+/// the given "envMap" map and a "ctx" set. The relevant stuff is
+/// fetched from the following functions:
+/// Seq#Length, Seq#Index, Seq#Build, Seq#Append
+// ==============================================================
let ReadSeq (model: Microsoft.Boogie.Model) (envMap,ctx) =
+ // reads stuff from Seq#Length
+ let rec __ReadSeqLen (model: Microsoft.Boogie.Model) (len_tuples: Model.FuncTuple list) (envMap,ctx) =
+ match len_tuples with
+ | ft :: rest ->
+ let len = GetInt ft.Result
+ let emptyList = Utils.GenList len NoneConst
+ let newMap = envMap |> Map.add (GetLoc ft.Args.[0]) (SeqConst(emptyList))
+ __ReadSeqLen model rest (newMap,ctx)
+ | _ -> (envMap,ctx)
+
+ // reads stuff from Seq#Index
+ let rec __ReadSeqIndex (model: Microsoft.Boogie.Model) (idx_tuples: Model.FuncTuple list) (envMap,ctx) =
+ match idx_tuples with
+ | ft :: rest ->
+ let srcLstKey = GetLoc ft.Args.[0]
+ let oldLst = FindSeqInEnv envMap srcLstKey
+ let idx = GetInt ft.Args.[1]
+ let lstElem = UnboxIfNeeded model ft.Result
+ let newLst = Utils.ListSet idx lstElem oldLst
+ let newCtx = UpdateContext oldLst newLst ctx
+ let newEnv = envMap |> Map.add srcLstKey (SeqConst(newLst))
+ __ReadSeqIndex model rest (newEnv,newCtx)
+ | _ -> (envMap,ctx)
+
+ // reads stuff from Seq#Build
+ let rec __ReadSeqBuild (model: Microsoft.Boogie.Model) (bld_tuples: Model.FuncTuple list) (envMap,ctx) =
+ match bld_tuples with
+ | ft :: rest ->
+ let srcLstLoc = GetLoc ft.Args.[0]
+ let dstLstLoc = GetLoc ft.Result
+ let oldLst = FindSeqInEnv envMap srcLstLoc
+ let idx = GetInt ft.Args.[1]
+ let lstElemVal = UnboxIfNeeded model ft.Args.[2]
+ let dstLst = FindSeqInEnv envMap dstLstLoc
+ let newLst = Utils.ListBuild oldLst idx lstElemVal dstLst
+ let newCtx = UpdateContext dstLst newLst ctx
+ let newEnv = envMap |> Map.add dstLstLoc (SeqConst(newLst))
+ __ReadSeqBuild model rest (newEnv,newCtx)
+ | _ -> (envMap,ctx)
+
+ // reads stuff from Seq#Append
+ let rec __ReadSeqAppend (model: Microsoft.Boogie.Model) (app_tuples: Model.FuncTuple list) (envMap,ctx) =
+ match app_tuples with
+ | ft :: rest ->
+ let srcLst1Loc = GetLoc ft.Args.[0]
+ let srcLst2Loc = GetLoc ft.Args.[1]
+ let dstLstLoc = GetLoc ft.Result
+ let oldLst1 = FindSeqInEnv envMap srcLst1Loc
+ let oldLst2 = FindSeqInEnv envMap srcLst2Loc
+ let dstLst = FindSeqInEnv envMap dstLstLoc
+ let newLst = List.append oldLst1 oldLst2
+ let newCtx = UpdateContext dstLst newLst ctx
+ let newEnv = envMap |> Map.add dstLstLoc (SeqConst(newLst))
+ __ReadSeqAppend model rest (newEnv,newCtx)
+ | _ -> (envMap,ctx)
+
let f_seq_len = model.MkFunc("Seq#Length", 1)
let f_seq_idx = model.MkFunc("Seq#Index", 2)
let f_seq_bld = model.MkFunc("Seq#Build", 4)
let f_seq_app = model.MkFunc("Seq#Append", 2)
- (envMap,ctx) |> ReadSeqLen model (List.ofSeq f_seq_len.Apps)
- |> ReadSeqIndex model (List.ofSeq f_seq_idx.Apps)
- |> ReadSeqBuild model (List.ofSeq f_seq_bld.Apps)
- |> ReadSeqAppend model (List.ofSeq f_seq_app.Apps)
+ (envMap,ctx) |> __ReadSeqLen model (List.ofSeq f_seq_len.Apps)
+ |> __ReadSeqIndex model (List.ofSeq f_seq_idx.Apps)
+ |> __ReadSeqBuild model (List.ofSeq f_seq_bld.Apps)
+ |> __ReadSeqAppend model (List.ofSeq f_seq_app.Apps)
+// =====================================================
+/// Reads stuff about sets from a given model and adds it
+/// to the given "envMap" map and "ctx" set.
+// =====================================================
let ReadSet (model: Microsoft.Boogie.Model) (envMap,ctx) =
- (envMap,ctx)
+ // reads stuff from Set#Empty
+ let rec __ReadSetEmpty (empty_tuples: Model.FuncTuple list) (envMap,ctx) =
+ match empty_tuples with
+ | ft :: rest ->
+ let newMap = envMap |> Map.add (GetLoc ft.Result) (SetConst(Set.empty))
+ __ReadSetEmpty rest (newMap,ctx)
+ | [] -> (envMap,ctx)
+
+ // reads stuff from [2]
+ let rec __ReadSetMembership (set_tuples: Model.FuncTuple list) (env,ctx) =
+ match set_tuples with
+ | ft :: rest ->
+ if GetBool ft.Result then
+ let srcSetKey = GetLoc ft.Args.[0]
+ let srcSet = match TryFindSetInEnv env srcSetKey with
+ | Some(s) -> s
+ | None -> Set.empty
+ let elem = UnboxIfNeeded model ft.Args.[1]
+ let newEnv = env |> Map.add srcSetKey (SetConst(Set.add elem srcSet))
+ __ReadSetMembership rest (newEnv,ctx)
+ else
+ __ReadSetMembership rest (env,ctx)
+ | [] -> (env,ctx)
+
+ let t_set_empty = Seq.toList (model.MkFunc("Set#Empty", 1).Apps)
+ let t_set = Seq.toList (model.MkFunc("[2]", 2).Apps)
+ (envMap,ctx) |> __ReadSetEmpty t_set_empty
+ |> __ReadSetMembership t_set
+
+(* More complicated way which now doesn't seem to be necessary *)
+//let ReadSet (model: Microsoft.Boogie.Model) (envMap,ctx) =
+// // reads stuff from Set#Empty
+// let rec __ReadSetEmpty (empty_tuples: Model.FuncTuple list) (envMap,ctx) =
+// match empty_tuples with
+// | ft :: rest ->
+// let newMap = envMap |> Map.add (GetLoc ft.Result) (SetConst(Set.empty))
+// __ReadSetEmpty rest (newMap,ctx)
+// | [] -> (envMap,ctx)
+//
+// // reads stuff from Set#UnionOne and Set#Union
+// let rec __ReadSetUnions (envMap,ctx) =
+// // this one goes through a given list of "UnionOne" tuples, updates
+// // the env for those set that it was able to resolve, and returns a
+// // list of tuples for which it wasn't able to resolve sets
+// let rec ___RSU1 (tuples: Model.FuncTuple list) env unprocessed =
+// match tuples with
+// | ft :: rest ->
+// let srcSetKey = GetLoc ft.Args.[0]
+// match TryFindSetInEnv env srcSetKey with
+// | Some(oldSet) ->
+// let elem = UnboxIfNeeded model ft.Args.[1]
+// let newSet = Set.add elem oldSet
+// // update contex?
+// let newEnv = env |> Map.add (GetLoc ft.Result) (SetConst(newSet))
+// ___RSU1 rest newEnv unprocessed
+// | None -> ___RSU1 rest env (ft :: unprocessed)
+// | [] -> (env,unprocessed)
+// // this one goes through a given list of "Union" tuples, updates
+// // the env for those set that it was able to resolve, and returns a
+// // list of tuples for which it wasn't able to resolve sets
+// let rec ___RSU (tuples: Model.FuncTuple list) env unprocessed =
+// match tuples with
+// | ft :: rest ->
+// let set1Key = GetLoc ft.Args.[0]
+// let set2Key = GetLoc ft.Args.[1]
+// match TryFindSetInEnv env set1Key, TryFindSetInEnv env set2Key with
+// | Some(oldSet1), Some(oldSet2) ->
+// let newSet = Set.union oldSet1 oldSet2
+// // update contex?
+// let newEnv = env |> Map.add (GetLoc ft.Result) (SetConst(newSet))
+// ___RSU rest newEnv unprocessed
+// | _ -> ___RSU rest env (ft :: unprocessed)
+// | [] -> (env,unprocessed)
+// // this one keeps looping as loong as the list of unprocessed tuples
+// // is decreasing, it ends when if falls down to 0, or fails if
+// // the list stops decreasing
+// let rec ___RSU_until_fixpoint u1tuples utuples env =
+// let newEnv1,unprocessed1 = ___RSU1 u1tuples env []
+// let newEnv2,unprocessed2 = ___RSU utuples newEnv1 []
+// let oldLen = (List.length u1tuples) + (List.length utuples)
+// let totalUnprocLen = (List.length unprocessed1) + (List.length unprocessed2)
+// if totalUnprocLen = 0 then
+// newEnv2
+// elif totalUnprocLen < oldLen then
+// ___RSU_until_fixpoint unprocessed1 unprocessed2 newEnv2
+// else
+// failwith "cannot resolve all sets in Set#UnionOne/Set#Union"
+// // finally, just invoke the fixpoint function for UnionOne and Union tuples
+// let t_union_one = Seq.toList (model.MkFunc("Set#UnionOne", 2).Apps)
+// let t_union = Seq.toList (model.MkFunc("Set#Union", 2).Apps)
+// let newEnv = ___RSU_until_fixpoint t_union_one t_union envMap
+// (newEnv,ctx)
+//
+// let f_set_empty = model.MkFunc("Set#Empty", 1)
+// (envMap,ctx) |> __ReadSetEmpty (List.ofSeq f_set_empty.Apps)
+// |> __ReadSetUnions
+// ======================================================
+/// Reads staff about the null constant from a given model
+/// and adds it to the given "envMap" map and "ctx" set.
+// ======================================================
let ReadNull (model: Microsoft.Boogie.Model) (envMap,ctx) =
let f_null = model.MkFunc("null", 0)
assert (f_null.AppCount = 1)
@@ -226,14 +355,20 @@ let ReadNull (model: Microsoft.Boogie.Model) (envMap,ctx) =
let newEnv = envMap |> Map.add (GetLoc e) NullConst
(newEnv,ctx)
-let ReadEnv (model: Microsoft.Boogie.Model) =
- let f_dtype = model.MkFunc("dtype", 1)
+// ============================================================================================
+/// Reads the evinronment map and the context set.
+///
+/// It starts by reading the model for the "dtype" function to discover all objects on the heap,
+/// and then proceeds by reading stuff about the null constant, about sequences, and about sets.
+// ============================================================================================
+let ReadEnv (model: Microsoft.Boogie.Model) prog =
+ let f_dtype = model.MkFunc("dtype", 1)
let refs = f_dtype.Apps |> Seq.choose (fun ft -> Some(ft.Args.[0]))
let envMap = f_dtype.Apps |> Seq.fold (fun acc ft ->
let locName = GetRefName ft.Args.[0]
let elemName = GetElemFullName ft.Args.[0]
let loc = Unresolved(locName)
- let locType = GetType ft.Result
+ let locType = GetType ft.Result prog
let value = match elemName with
| Some(n) when n.StartsWith("this") -> ThisConst(locName.Replace("*", ""), locType)
| _ -> NewObj(locName.Replace("*", ""), locType)
@@ -243,8 +378,8 @@ let ReadEnv (model: Microsoft.Boogie.Model) =
|> ReadSeq model
|> ReadSet model
-let ReadFieldValuesFromModel (model: Microsoft.Boogie.Model) prog comp meth =
- let heap = ReadHeap model prog
- let env0,ctx = ReadEnv model
- let env = env0 |> Utils.MapAddAll (ReadArgValues model (GetMethodArgs meth))
+let ReadFieldValuesFromModel (model: Microsoft.Boogie.Model) prog comp meth =
+ let heap = ReadHeap model prog
+ let env0,ctx = ReadEnv model prog
+ let env = env0 |> Utils.MapAddAll (ReadArgValues model (GetMethodArgs meth))
heap,env,ctx \ No newline at end of file
diff --git a/Jennisys/Jennisys/DafnyPrinter.fs b/Jennisys/Jennisys/DafnyPrinter.fs
index 87937850..d1dc73fc 100644
--- a/Jennisys/Jennisys/DafnyPrinter.fs
+++ b/Jennisys/Jennisys/DafnyPrinter.fs
@@ -5,19 +5,23 @@ open Printer
let rec PrintType ty =
match ty with
- | IntType -> "int"
- | BoolType -> "bool"
- | NamedType(id) -> id
- | SeqType(t) -> sprintf "seq<%s>" (PrintType t)
- | SetType(t) -> sprintf "set<%s>" (PrintType t)
- | InstantiatedType(id,arg) -> sprintf "%s<%s>" id (PrintType arg)
+ | IntType -> "int"
+ | BoolType -> "bool"
+ | SeqType(t) -> sprintf "seq<%s>" (PrintType t)
+ | SetType(t) -> sprintf "set<%s>" (PrintType t)
+ | NamedType(id,args) -> if List.isEmpty args then id else sprintf "%s<%s>" id (PrintSep ", " (fun s -> s) args)
+ | InstantiatedType(id,args) -> sprintf "%s<%s>" id (PrintSep ", " (fun t -> PrintType t) args)
let rec PrintExpr ctx expr =
match expr with
- | IntLiteral(n) -> sprintf "%O" n
+ | IntLiteral(d) -> sprintf "%d" d
+ | BoolLiteral(b) -> sprintf "%b" b
+ | ObjLiteral(id)
+ | VarLiteral(id)
| IdLiteral(id) -> id
| Star -> assert false; "" // I hope this won't happen
| Dot(e,id) -> sprintf "%s.%s" (PrintExpr 100 e) id
+ | UnaryExpr(op,UnaryExpr(op2, e2)) -> sprintf "%s(%s)" op (PrintExpr 90 (UnaryExpr(op2, e2)))
| UnaryExpr(op,e) -> sprintf "%s%s" op (PrintExpr 90 e)
| BinaryExpr(strength,op,e0,e1) ->
let op =
@@ -30,16 +34,32 @@ let rec PrintExpr ctx expr =
let openParen = if needParens then "(" else ""
let closeParen = if needParens then ")" else ""
sprintf "%s%s %s %s%s" openParen (PrintExpr strength e0) op (PrintExpr strength e1) closeParen
+ | IteExpr(c,e1,e2) -> sprintf "(if %s then %s else %s)" (PrintExpr 25 c) (PrintExpr 25 e1) (PrintExpr 25 e2)
| SelectExpr(e,i) -> sprintf "%s[%s]" (PrintExpr 100 e) (PrintExpr 0 i)
| UpdateExpr(e,i,v) -> sprintf "%s[%s := %s]" (PrintExpr 100 e) (PrintExpr 0 i) (PrintExpr 0 v)
| SequenceExpr(ee) -> sprintf "[%s]" (ee |> PrintSep ", " (PrintExpr 0))
| SeqLength(e) -> sprintf "|%s|" (PrintExpr 0 e)
+ | SetExpr(ee) -> sprintf "{%s}" (ee |> PrintSep ", " (PrintExpr 0))
| ForallExpr(vv,e) ->
let needParens = true
let openParen = if needParens then "(" else ""
let closeParen = if needParens then ")" else ""
sprintf "%sforall %s :: %s%s" openParen (vv |> PrintSep ", " PrintVarDecl) (PrintExpr 0 e) closeParen
+let rec PrintConst cst =
+ match cst with
+ | IntConst(v) -> sprintf "%d" v
+ | BoolConst(b) -> sprintf "%b" b
+ | VarConst(v) -> sprintf "%s" v
+ | SetConst(cset) -> sprintf "{%s}" (PrintSep ", " (fun c -> PrintConst c) (Set.toList cset))
+ | SeqConst(cseq) -> sprintf "[%s]" (PrintSep ", " (fun c -> PrintConst c) cseq)
+ | NullConst -> "null"
+ | NoneConst -> "<none>"
+ | ThisConst(_,_) -> "this"
+ | ExprConst(e) -> PrintExpr 0 e
+ | NewObj(name,_) -> PrintGenSym name
+ | Unresolved(name) -> sprintf "Unresolved(%s)" name
+
let PrintTypeParams typeParams =
match typeParams with
| [] -> ""
diff --git a/Jennisys/Jennisys/Jennisys.fs b/Jennisys/Jennisys/Jennisys.fs
index 0337c6a2..d0a47fe1 100644
--- a/Jennisys/Jennisys/Jennisys.fs
+++ b/Jennisys/Jennisys/Jennisys.fs
@@ -10,58 +10,37 @@ open Microsoft.FSharp.Text.Lexing
open Ast
open Lexer
+open Options
open Parser
open Printer
open TypeChecker
open Analyzer
-let readAndProcess tracing analyzing (filename: string) =
- try
- printfn "// Jennisys, Copyright (c) 2011, Microsoft."
- // lex
- let f = if filename = null then Console.In else new StreamReader(filename) :> TextReader
- let lexbuf = LexBuffer<char>.FromTextReader(f)
- lexbuf.EndPos <- { pos_bol = 0;
- pos_fname=if filename = null then "stdin" else filename;
- pos_cnum=0;
- pos_lnum=1 }
- try
- // parse
- let sprog = Parser.start Lexer.tokenize lexbuf
- // print the given Jennisys program
- if tracing then
- printfn "---------- Given Jennisys program ----------"
- printfn "%s" (Print sprog)
- else ()
- match TypeCheck sprog with
- | None -> () // errors have already been reported
- | Some(prog) ->
- if analyzing then
- // output a Dafny program with the constraints to be solved
- Analyze prog
- else ()
- // that's it
- if tracing then printfn "----------" else ()
- with
- | ex ->
- let pos = lexbuf.EndPos
- printfn "%s(%d,%d): %s" pos.FileName pos.Line pos.Column ex.Message
+let readAndProcess (filename: string) =
+ printfn "// Jennisys, Copyright (c) 2011, Microsoft."
+ // lex
+ let f = if filename = null then Console.In else new StreamReader(filename) :> TextReader
+ let lexbuf = LexBuffer<char>.FromTextReader(f)
+ lexbuf.EndPos <- { pos_bol = 0;
+ pos_fname=if filename = null then "stdin" else filename;
+ pos_cnum=0;
+ pos_lnum=1 }
+// try
+ // parse
+ let sprog = Parser.start Lexer.tokenize lexbuf
+ match TypeCheck sprog with
+ | None -> () // errors have already been reported
+ | Some(prog) ->
+ Analyze prog filename
+// with
+// | ex ->
+// let pos = lexbuf.EndPos
+// printfn "%s(%d,%d): %s" pos.FileName pos.Line pos.Column ex.Message
+// printfn "%O" ex.StackTrace
- with
- | ex ->
- printfn "Unhandled Exception: %s" ex.Message
-
-let rec start n (args: string []) tracing analyzing filename =
- if n < args.Length then
- let arg = args.[n]
- if arg = "/break" then ignore (System.Diagnostics.Debugger.Launch()) else ()
- let filename = if arg.StartsWith "/" then filename else arg
- start (n+1) args (tracing || arg = "/trace") (analyzing && arg <> "/noAnalysis") filename
- else
- readAndProcess tracing analyzing filename
-
-let args = Environment.GetCommandLineArgs()
try
- start 1 args false true null
-with
- | Failure(msg) as e -> printfn "WHYYYYYYYYYYYYYYY: %s" msg; printfn "%s" e.StackTrace \ No newline at end of file
+ let args = Environment.GetCommandLineArgs()
+ ParseCmdLineArgs (List.ofArray args)
+ readAndProcess CONFIG.inputFilename
+with
+ | InvalidCmdLineOption(msg) as ex -> printfn "%s" msg; printfn "%s" ex.StackTrace \ No newline at end of file
diff --git a/Jennisys/Jennisys/Jennisys.fsproj b/Jennisys/Jennisys/Jennisys.fsproj
index 39ed1aed..5e1bea61 100644
--- a/Jennisys/Jennisys/Jennisys.fsproj
+++ b/Jennisys/Jennisys/Jennisys.fsproj
@@ -23,7 +23,7 @@
<WarningLevel>3</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<DocumentationFile>bin\Debug\Language.XML</DocumentationFile>
- <StartArguments>C:\boogie\Jennisys\Jennisys\examples\List3.jen</StartArguments>
+ <StartArguments>C:\boogie\Jennisys\Jennisys\examples\Number.jen /method:Number.Abs /checkUnifs</StartArguments>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
@@ -42,8 +42,8 @@
<FsYaccOutputFolder>$(IntermediateOutputPath)</FsYaccOutputFolder>
</PropertyGroup>
<ItemGroup>
- <Compile Include="Options.fs" />
<Compile Include="Utils.fs" />
+ <Compile Include="Options.fs" />
<Compile Include="PipelineUtils.fs" />
<Compile Include="Ast.fs" />
<Compile Include="AstUtils.fs" />
@@ -64,8 +64,8 @@
<OtherFlags>--unicode</OtherFlags>
</FsLex>
<Compile Include="Printer.fs" />
- <Compile Include="Logger.fs" />
<Compile Include="DafnyPrinter.fs" />
+ <Compile Include="Logger.fs" />
<Compile Include="TypeChecker.fs" />
<Compile Include="Resolver.fs" />
<Compile Include="CodeGen.fs" />
@@ -83,17 +83,21 @@
<Reference Include="System.Numerics" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\..\Source\ModelViewer\ModelViewer.csproj">
- <Name>ModelViewer</Name>
- <Project>{a678c6eb-b329-46a9-bbfc-7585f01acd7c}</Project>
+ <ProjectReference Include="..\..\Source\Model\Model.csproj">
+ <Name>Model</Name>
+ <Project>{acef88d5-dadd-46da-bae1-2144d63f4c83}</Project>
<Private>True</Private>
</ProjectReference>
+ </ItemGroup>
+ <!--
+ <ItemGroup>
<ProjectReference Include="..\..\Source\Model\Model.csproj">
<Name>Model</Name>
<Project>{acef88d5-dadd-46da-bae1-2144d63f4c83}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
+ -->
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/Jennisys/Jennisys/Lexer.fsl b/Jennisys/Jennisys/Lexer.fsl
index 91c3239c..9eaf7421 100644
--- a/Jennisys/Jennisys/Lexer.fsl
+++ b/Jennisys/Jennisys/Lexer.fsl
@@ -69,6 +69,7 @@ rule tokenize = parse
| ":" { COLON }
| "::" { COLONCOLON }
| "," { COMMA }
+| "?" { QMARK }
// Numberic constants
| digit+ { INTEGER (System.Convert.ToInt32(lexeme lexbuf)) }
// identifiers
diff --git a/Jennisys/Jennisys/Logger.fs b/Jennisys/Jennisys/Logger.fs
index bb784ba2..09b576fd 100644
--- a/Jennisys/Jennisys/Logger.fs
+++ b/Jennisys/Jennisys/Logger.fs
@@ -1,6 +1,8 @@
-/// Simple logging facility
+// #######################################################
+/// Simple logging facility
///
-/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// #######################################################
module Logger
@@ -14,7 +16,7 @@ let _WARN = 40
let _ERROR = 20
let _NONE = 0
-let logLevel = _ALL
+let logLevel = _DEBUG
let Log level msg =
if logLevel >= level then
diff --git a/Jennisys/Jennisys/Options.fs b/Jennisys/Jennisys/Options.fs
index 34a0422b..a03f7213 100644
--- a/Jennisys/Jennisys/Options.fs
+++ b/Jennisys/Jennisys/Options.fs
@@ -1,8 +1,113 @@
-/// This module is intended to store and handle configuration options
+// ####################################################################
+/// This module is intended to store and handle configuration options
///
-/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// ####################################################################
module Options
-/// attempt to verify synthesized code
-let _opt_verifySolutions = true \ No newline at end of file
+open Utils
+
+type Config = {
+ inputFilename: string;
+ methodToSynth: string;
+ verifySolutions: bool;
+ checkUnifications: bool;
+ timeout: int;
+}
+
+let defaultConfig: Config = {
+ inputFilename = "";
+ methodToSynth = "*";
+ verifySolutions = true;
+ checkUnifications = false;
+ timeout = 0;
+}
+
+let mutable CONFIG = defaultConfig
+
+exception InvalidCmdLineArg of string
+exception InvalidCmdLineOption of string
+
+let ParseCmdLineArgs args =
+ let __StripSwitches str =
+ match str with
+ | Prefix "--" x
+ | Prefix "-" x
+ | Prefix "/" x -> x
+ | _ -> str
+
+ let __Split (str: string) =
+ let stripped = __StripSwitches str
+ if stripped = str then
+ ("",str)
+ else
+ let splits = stripped.Split([| ':' |])
+ if splits.Length > 2 then raise (InvalidCmdLineOption("more than 2 colons in " + str))
+ if splits.Length = 2 then
+ let opt = splits.[0]
+ let value = splits.[1]
+ (opt,value)
+ else
+ let x = __StripSwitches splits.[0]
+ (x, "")
+
+ let __CheckNonEmpty value optName =
+ if value = "" then raise (InvalidCmdLineArg("A value for option " + optName + " must not be empty"))
+
+ let __CheckInt value optName =
+ try
+ System.Int32.Parse value
+ with
+ | ex -> raise (InvalidCmdLineArg("A value for option " + optName + " must be a boolean"))
+
+ let __CheckBool value optName =
+ if value = "" then
+ true
+ else
+ try
+ System.Boolean.Parse value
+ with
+ | ex -> raise (InvalidCmdLineArg("A value for option " + optName + " must be an integer"))
+
+ let rec __Parse args cfg =
+ match args with
+ | fs :: rest ->
+ let opt,value = __Split fs
+ match opt with
+ | "method" ->
+ __CheckNonEmpty value opt
+ __Parse rest { cfg with methodToSynth = value }
+ | "verifySol" ->
+ let b = __CheckBool value opt
+ __Parse rest { cfg with verifySolutions = b }
+ | "noVerifySol" ->
+ let b = __CheckBool value opt
+ __Parse rest { cfg with verifySolutions = not b }
+ | "checkUnifs" ->
+ let b = __CheckBool value opt
+ __Parse rest { cfg with checkUnifications = b }
+ | "noCheckUnifs" ->
+ let b = __CheckBool value opt
+ __Parse rest { cfg with checkUnifications = not b }
+ | "timeout" ->
+ let t = __CheckInt value opt
+ __Parse rest { cfg with timeout = t }
+ | "" ->
+ __Parse rest { cfg with inputFilename = value }
+ | _ ->
+ raise (InvalidCmdLineOption("Unknown option: " + opt))
+ | [] -> cfg
+
+ let __CheckBool value optName =
+ if value = "" then
+ true
+ else
+ try
+ System.Boolean.Parse value
+ with
+ | ex -> raise (InvalidCmdLineArg("Option " + optName " must be boolean"))
+
+ (* --- function body starts here --- *)
+ CONFIG <- __Parse args defaultConfig
+
diff --git a/Jennisys/Jennisys/Parser.fsy b/Jennisys/Jennisys/Parser.fsy
index 21e2c83e..c683e84c 100644
--- a/Jennisys/Jennisys/Parser.fsy
+++ b/Jennisys/Jennisys/Parser.fsy
@@ -6,7 +6,7 @@ open AstUtils
let rec MyFold ee acc =
match ee with
| [] -> acc
- | x::rest -> BinaryAnd (Desugar x) (MyFold rest acc)
+ | x::rest -> BinaryAnd x (MyFold rest acc)
%}
@@ -26,7 +26,7 @@ let rec MyFold ee acc =
%token IMPLIES
%token IFF
%token LPAREN RPAREN LBRACKET RBRACKET LCURLY RCURLY VERTBAR
-%token GETS COLON COLONCOLON COMMA
+%token GETS COLON COLONCOLON COMMA QMARK
%token CLASS MODEL CODE
%token VAR CONSTRUCTOR METHOD FRAME INVARIANT RETURNS REQUIRES ENSURES FORALL
%token INTTYPE BOOLTYPE SEQTYPE SETTYPE
@@ -69,11 +69,11 @@ Signature:
| LPAREN VarDeclList RPAREN RETURNS LPAREN VarDeclList RPAREN { Sig($2, $6) }
Pre:
- | { IdLiteral "true" }
+ | { TrueLiteral }
| REQUIRES Expr Pre { BinaryAnd $2 $3 }
Post:
- | { IdLiteral "true" }
+ | { TrueLiteral }
| ENSURES Expr Post { BinaryAnd $2 $3 }
StmtList:
@@ -89,12 +89,12 @@ BlockStmt:
Member:
| VAR VarDecl { Field($2) }
- | CONSTRUCTOR ID Signature Pre Post { Method($2, $3, (Desugar $4), (Desugar $5), true) }
- | METHOD ID Signature Pre Post { Method($2, $3, (Desugar $4), (Desugar $5), false) }
- | INVARIANT ExprList { Invariant(DesugarLst $2) }
+ | CONSTRUCTOR ID Signature Pre Post { Method($2, $3, RewriteVars (GetSigVars $3) $4, RewriteVars (GetSigVars $3) $5, true) }
+ | METHOD ID Signature Pre Post { Method($2, $3, $4, $5, false) }
+ | INVARIANT ExprList { Invariant($2) }
FrameMembers:
- | { [], [], IdLiteral("true") }
+ | { [], [], TrueLiteral }
| VAR VarDecl FrameMembers { match $3 with (vv,fr,inv) -> $2 :: vv, fr, inv }
| FRAME FrameMembers { $2 }
| FRAME FramePartitionList FrameMembers { match $3 with (vv,fr,inv) -> vv, List.append $2 fr, inv }
@@ -116,10 +116,10 @@ VarDecl:
Type:
| INTTYPE { IntType }
| BOOLTYPE { BoolType }
- | ID { NamedType($1) }
+ | ID { NamedType($1, []) }
| SEQTYPE LBRACKET Type RBRACKET { SeqType($3) }
| SETTYPE LBRACKET Type RBRACKET { SetType($3) }
- | ID LBRACKET Type RBRACKET { InstantiatedType($1, $3) }
+ | ID LBRACKET Type RBRACKET { InstantiatedType($1, [$3]) }
ExprList:
| { [] }
@@ -134,9 +134,12 @@ Expr10:
| Expr10 IFF Expr20 { BinaryExpr(10,"<==>",$1,$3) }
Expr20:
- | Expr30 { $1 }
- | Expr30 IMPLIES Expr20 { BinaryExpr(20,"==>",$1,$3) }
+ | Expr25 { $1 }
+ | Expr25 IMPLIES Expr20 { BinaryExpr(20,"==>",$1,$3) }
+Expr25:
+ | Expr30 { $1 }
+ | Expr30 QMARK Expr25 COLON Expr25 { IteExpr($1,$3,$5) }
Expr30:
| Expr40 { $1 }
| Expr40 AND Expr30and { BinaryAnd $1 $3 }
@@ -177,14 +180,20 @@ Expr90:
Expr100:
| INTEGER { IntLiteral($1) }
- | ID { IdLiteral($1) }
+ | ID { if $1 = "this" then
+ ObjLiteral("this")
+ elif $1 = "null" then
+ ObjLiteral("null")
+ else
+ IdLiteral($1) }
| Expr100 DOT ID { Dot($1, $3) }
| Expr100 LBRACKET StarExpr RBRACKET { SelectExpr($1, $3) }
| Expr100 LBRACKET Expr GETS Expr RBRACKET { UpdateExpr($1, $3, $5) }
| LPAREN Expr RPAREN { $2 }
| LBRACKET ExprList RBRACKET { SequenceExpr($2) }
+ | LCURLY ExprList RCURLY { SetExpr($2) }
| VERTBAR Expr VERTBAR { SeqLength($2) }
- | FORALL VarDeclList COLONCOLON Expr { ForallExpr($2, $4) }
+ | FORALL VarDeclList COLONCOLON Expr { ForallExpr($2, RewriteVars $2 $4) }
StarExpr:
| STAR { Star }
diff --git a/Jennisys/Jennisys/PipelineUtils.fs b/Jennisys/Jennisys/PipelineUtils.fs
index 686452b6..1439018a 100644
--- a/Jennisys/Jennisys/PipelineUtils.fs
+++ b/Jennisys/Jennisys/PipelineUtils.fs
@@ -1,54 +1,59 @@
-/// Utility functions for executing shell commands and
-/// running Dafny in particular
+// ####################################################################
+/// Utility functions for executing shell commands and
+/// running Dafny in particular
///
-/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// ####################################################################
module PipelineUtils
-
-let dafnyScratchSuffix = "scratch"
-let dafnyVerifySuffix = "verify"
-let dafnyUnifSuffix = "unif"
-let dafnySynthFile = @"c:\tmp\jennisys-synth.dfy"
-
-let CreateEmptyModelFile modelFile =
- use mfile = System.IO.File.CreateText(modelFile)
- fprintf mfile ""
-
-// =======================================================
-/// Runs Dafny on the given "inputFile" and prints
-/// the resulting model to the given "modelFile"
-// =======================================================
+
+let dafnyScratchSuffix = "scratch"
+let dafnyVerifySuffix = "verify"
+let dafnyUnifSuffix = "unif"
+let dafnySynthFileNameTemplate = @"c:\tmp\jennisys-synth_###.dfy"
+
+let mutable lastDafnyExitCode = 0 //TODO: how to avoid this muttable state?
+
+let CreateEmptyModelFile modelFile =
+ use mfile = System.IO.File.CreateText(modelFile)
+ fprintf mfile ""
+
+// =======================================================
+/// Runs Dafny on the given "inputFile" and prints
+/// the resulting model to the given "modelFile"
+// =======================================================
let RunDafny inputFile modelFile =
CreateEmptyModelFile modelFile
async {
use proc = new System.Diagnostics.Process()
proc.StartInfo.FileName <- @"c:\tmp\StartDafny-jen.bat"
- proc.StartInfo.Arguments <- "/mv:" + modelFile + " " + inputFile
+ proc.StartInfo.Arguments <- (sprintf "/mv:%s /timeLimit:%d %s" modelFile Options.CONFIG.timeout inputFile)
+ proc.StartInfo.WindowStyle <- System.Diagnostics.ProcessWindowStyle.Hidden
assert proc.Start()
proc.WaitForExit()
+ lastDafnyExitCode <- proc.ExitCode
} |> Async.RunSynchronously
-// =======================================================
-/// Runs Dafny on the given "dafnyCode" and returns models
-// =======================================================
-let RunDafnyProgram dafnyProgram suffix =
- let inFileName = @"c:\tmp\jennisys-" + suffix + ".dfy"
- let modelFileName = @"c:\tmp\jennisys-" + suffix + ".bvd"
- use file = System.IO.File.CreateText(inFileName)
- file.AutoFlush <- true
- fprintfn file "%s" dafnyProgram
- file.Close()
- // run Dafny
- RunDafny inFileName modelFileName
- // read models from the model file
- use modelFile = System.IO.File.OpenText(modelFileName)
- Microsoft.Boogie.Model.ParseModels modelFile
-
-// =======================================================
-/// Checks whether the given dafny program verifies
-// =======================================================
-let CheckDafnyProgram dafnyProgram suffix =
- // TODO: also check whether Dafny produced any other errors (e.g. compilation errors, etc.)
- let models = RunDafnyProgram dafnyProgram suffix
- // if there are no models, verification was successful
- models.Count = 0
+// =======================================================
+/// Runs Dafny on the given "dafnyCode" and returns models
+// =======================================================
+let RunDafnyProgram dafnyProgram suffix =
+ let inFileName = @"c:\tmp\jennisys-" + suffix + ".dfy"
+ let modelFileName = @"c:\tmp\jennisys-" + suffix + ".bvd"
+ use file = System.IO.File.CreateText(inFileName)
+ file.AutoFlush <- true
+ fprintfn file "%s" dafnyProgram
+ file.Close()
+ // run Dafny
+ RunDafny inFileName modelFileName
+ // read models from the model file
+ use modelFile = System.IO.File.OpenText(modelFileName)
+ Microsoft.Boogie.Model.ParseModels modelFile
+
+// =======================================================
+/// Checks whether the given dafny program verifies
+// =======================================================
+let CheckDafnyProgram dafnyProgram suffix =
+ let models = RunDafnyProgram dafnyProgram suffix
+ // if there are no models, verification was successful
+ lastDafnyExitCode = 0 && models.Count = 0
diff --git a/Jennisys/Jennisys/Printer.fs b/Jennisys/Jennisys/Printer.fs
index eb70acbd..e051492f 100644
--- a/Jennisys/Jennisys/Printer.fs
+++ b/Jennisys/Jennisys/Printer.fs
@@ -16,12 +16,12 @@ let rec PrintSep sep f list =
let rec PrintType ty =
match ty with
- | IntType -> "int"
- | BoolType -> "bool"
- | NamedType(id) -> id
- | SeqType(t) -> sprintf "seq[%s]" (PrintType t)
- | SetType(t) -> sprintf "set[%s]" (PrintType t)
- | InstantiatedType(id,arg) -> sprintf "%s[%s]" id (PrintType arg)
+ | IntType -> "int"
+ | BoolType -> "bool"
+ | NamedType(id, args) -> if List.isEmpty args then id else (PrintSep ", " (fun s -> s) args)
+ | SeqType(t) -> sprintf "seq[%s]" (PrintType t)
+ | SetType(t) -> sprintf "set[%s]" (PrintType t)
+ | InstantiatedType(id,args) -> sprintf "%s[%s]" id (PrintSep ", " (fun a -> PrintType a) args)
let PrintVarDecl vd =
match vd with
@@ -34,26 +34,46 @@ let PrintVarName vd =
let rec PrintExpr ctx expr =
match expr with
- | IntLiteral(n) -> sprintf "%O" n
+ | IntLiteral(d) -> sprintf "%d" d
+ | BoolLiteral(b) -> sprintf "%b" b
+ | ObjLiteral(id)
+ | VarLiteral(id)
| IdLiteral(id) -> id
| Star -> "*"
| Dot(e,id) -> sprintf "%s.%s" (PrintExpr 100 e) id
+ | UnaryExpr(op,UnaryExpr(op2, e2)) -> sprintf "%s(%s)" op (PrintExpr 90 (UnaryExpr(op2, e2)))
| UnaryExpr(op,e) -> sprintf "%s%s" op (PrintExpr 90 e)
| BinaryExpr(strength,op,e0,e1) ->
let needParens = strength <= ctx
let openParen = if needParens then "(" else ""
let closeParen = if needParens then ")" else ""
sprintf "%s%s %s %s%s" openParen (PrintExpr strength e0) op (PrintExpr strength e1) closeParen
+ | IteExpr(c,e1,e2) -> sprintf "%s ? %s : %s" (PrintExpr 25 c) (PrintExpr 25 e1) (PrintExpr 25 e2)
| SelectExpr(e,i) -> sprintf "%s[%s]" (PrintExpr 100 e) (PrintExpr 0 i)
| UpdateExpr(e,i,v) -> sprintf "%s[%s := %s]" (PrintExpr 100 e) (PrintExpr 0 i) (PrintExpr 0 v)
- | SequenceExpr(ee) -> sprintf "[%s]" (ee |> PrintSep ", " (PrintExpr 0))
+ | SequenceExpr(ee) -> sprintf "[%s]" (ee |> PrintSep " " (PrintExpr 0))
| SeqLength(e) -> sprintf "|%s|" (PrintExpr 0 e)
+ | SetExpr(ee) -> sprintf "{%s}" (ee |> PrintSep " " (PrintExpr 0))
| ForallExpr(vv,e) ->
let needParens = ctx <> 0
let openParen = if needParens then "(" else ""
let closeParen = if needParens then ")" else ""
sprintf "%sforall %s :: %s%s" openParen (vv |> PrintSep ", " PrintVarDecl) (PrintExpr 0 e) closeParen
+let rec PrintConst cst =
+ match cst with
+ | IntConst(v) -> sprintf "%d" v
+ | BoolConst(b) -> sprintf "%b" b
+ | VarConst(v) -> sprintf "%s" v
+ | SetConst(cset) -> sprintf "{%s}" (PrintSep " " (fun c -> PrintConst c) (Set.toList cset))
+ | SeqConst(cseq) -> sprintf "[%s]" (PrintSep " " (fun c -> PrintConst c) cseq)
+ | NullConst -> "null"
+ | NoneConst -> "<none>"
+ | ThisConst(_,_) -> "this"
+ | ExprConst(e) -> PrintExpr 0 e
+ | NewObj(name,_) -> PrintGenSym name
+ | Unresolved(name) -> sprintf "Unresolved(%s)" name
+
let PrintSig signature =
match signature with
| Sig(ins, outs) ->
@@ -111,26 +131,20 @@ let PrintDecl d =
| Code(id,typeParams) ->
(PrintTopLevelDeclHeader "code" id typeParams) + "}" + newline
+let PrintMethodSignFull indent m =
+ let idt = Indent indent
+ let __PrintPrePost pfix expr = SplitIntoConjunts expr |> PrintSep newline (fun e -> pfix + (PrintExpr 0 e) + ";")
+ match m with
+ | Method(methodName, sgn, pre, post, isConstr) ->
+ let mc = if isConstr then "constructor" else "method"
+ let preStr = (__PrintPrePost (idt + " requires ") pre)
+ let postStr = (__PrintPrePost (idt + " ensures ") post)
+ idt + mc + " " + methodName + (PrintSig sgn) + newline +
+ preStr + (if preStr = "" then "" else newline) +
+ postStr
+
+ | _ -> failwithf "not a method: %O" m
+
let Print prog =
match prog with
| SProgram(decls) -> List.fold (fun acc d -> acc + (PrintDecl d)) "" decls
-
-let rec PrintConst cst =
- match cst with
- | IntConst(v) -> sprintf "%d" v
- | BoolConst(b) -> sprintf "%b" b
- | SetConst(cset) -> cset.ToString() //TODO: this won't work
- | SeqConst(cseq) ->
- let seqCont = cseq |> List.fold (fun acc cOpt ->
- let sep = if acc = "" then "" else ", "
- match cOpt with
- | Some(c) -> acc + sep + (PrintConst c)
- | None -> acc + sep + "null"
- ) ""
- sprintf "[%s]" seqCont
- | NullConst -> "null"
- | ThisConst(_,_) -> "this"
- | NewObj(name,_) -> PrintGenSym name
- | ExprConst(e) -> PrintExpr 0 e
- | VarConst(name) -> name
- | Unresolved(name) -> sprintf "Unresolved(%s)" name \ No newline at end of file
diff --git a/Jennisys/Jennisys/Resolver.fs b/Jennisys/Jennisys/Resolver.fs
index f1a1f67f..af49e51a 100644
--- a/Jennisys/Jennisys/Resolver.fs
+++ b/Jennisys/Jennisys/Resolver.fs
@@ -1,18 +1,33 @@
-module Resolver
+// ####################################################################
+/// Utilities for resolving the "Unresolved" constants with respect to
+/// a given context (heap/env/ctx)
+///
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// ####################################################################
+
+module Resolver
open Ast
+open AstUtils
open Printer
open EnvUtils
// resolving values
+exception ConstResolveFailed of string
-let rec Resolve cst (env,ctx) =
+// ================================================================
+/// Resolves a given Const (cst) with respect to a given env/ctx.
+///
+/// If unable to resolve, it just delegates the task to the
+/// failResolver function
+// ================================================================
+let rec ResolveCont (env,ctx) failResolver cst =
match cst with
| Unresolved(_) as u ->
// see if it is in the env map first
let envVal = Map.tryFind cst env
match envVal with
- | Some(c) -> Resolve c (env,ctx)
+ | Some(c) -> ResolveCont (env,ctx) failResolver c
| None ->
// not found in the env map --> check the equality sets
let eq = ctx |> Set.filter (fun eqSet -> Set.contains u eqSet)
@@ -23,56 +38,54 @@ let rec Resolve cst (env,ctx) =
|> Utils.SetToOption
match cOpt with
| Some(c) -> c
- | _ -> failwith ("failed to resolve " + cst.ToString())
- | _ -> failwith ("failed to resolve " + cst.ToString())
+ | _ -> failResolver cst (env,ctx)
+ | _ -> failResolver cst (env,ctx)
| SeqConst(cseq) ->
- let resolvedLst = cseq |> List.rev |> List.fold (fun acc cOpt ->
- match cOpt with
- | Some(c) -> Some(Resolve c (env,ctx)) :: acc
- | None -> cOpt :: acc
- ) []
+ let resolvedLst = cseq |> List.rev |> List.fold (fun acc c -> ResolveCont (env,ctx) failResolver c :: acc) []
SeqConst(resolvedLst)
| SetConst(cset) ->
- let resolvedSet = cset |> Set.fold (fun acc cOpt ->
- match cOpt with
- | Some(c) -> acc |> Set.add (Some(Resolve c (env,ctx)))
- | None -> acc |> Set.add(cOpt)
- ) Set.empty
+ let resolvedSet = cset |> Set.fold (fun acc c -> acc |> Set.add (ResolveCont (env,ctx) failResolver c)) Set.empty
SetConst(resolvedSet)
| _ -> cst
-let rec EvalUnresolved expr (heap,env,ctx) =
- match expr with
- | IntLiteral(n) -> IntConst(n)
- | IdLiteral(id) when id = "this" -> GetThisLoc env
- | IdLiteral(id) -> EvalUnresolved (Dot(IdLiteral("this"), id)) (heap,env,ctx)
- | Dot(e, str) ->
- let discr = EvalUnresolved e (heap,env,ctx)
- let h2 = Map.filter (fun (loc,Var(fldName,_)) v -> loc = discr && fldName = str) heap |> Map.toList
- match h2 with
- | ((_,_),x) :: [] -> x
- | _ :: _ -> failwithf "can't evaluate expression deterministically: %s.%s resolves to multiple locations." (PrintConst discr) str
- | [] -> failwithf "can't find value for %s.%s" (PrintConst discr) str
- | SelectExpr(lst, idx) ->
- let lstC = Resolve (EvalUnresolved lst (heap,env,ctx)) (env,ctx)
- let idxC = EvalUnresolved idx (heap,env,ctx)
- match lstC, idxC with
- | SeqConst(clist), IntConst(n) -> clist.[n] |> Utils.ExtractOption
- | _ -> failwith "can't eval SelectExpr"
- | _ -> failwith "NOT IMPLEMENTED YET" //TODO finish this!
-// | Star
-// | SelectExpr(_)
-// | UpdateExpr(_)
-// | SequenceExpr(_)
-// | SeqLength(_)
-// | ForallExpr(_)
-// | UnaryExpr(_)
-// | BinaryExpr(_)
-
-// TODO: can this be implemented on top of the existing AstUtils.EvalSym?? We must!
-let Eval expr (heap,env,ctx) =
- try
- let unresolvedConst = EvalUnresolved expr (heap,env,ctx)
- Some(Resolve unresolvedConst (env,ctx))
- with
- ex -> None \ No newline at end of file
+// =====================================================================
+/// Tries to resolve a given Const (cst) with respect to a given env/ctx.
+///
+/// If unable to resolve, just returns the original Unresolved const.
+// =====================================================================
+let TryResolve (env,ctx) cst =
+ ResolveCont (env,ctx) (fun c (e,x) -> c) cst
+
+// ==============================================================
+/// Resolves a given Const (cst) with respect to a given env/ctx.
+///
+/// If unable to resolve, raises a ConstResolveFailed exception
+// ==============================================================
+let Resolve (env,ctx) cst =
+ ResolveCont (env,ctx) (fun c (e,x) -> raise (ConstResolveFailed("failed to resolve " + c.ToString()))) cst
+
+// =================================================================
+/// Evaluates a given expression with respect to a given heap/env/ctx
+// =================================================================
+let Eval (heap,env,ctx) resolveVars expr =
+ let rec __EvalResolver expr =
+ match expr with
+ | VarLiteral(id) when not resolveVars -> VarConst(id)
+ | ObjLiteral("this") -> GetThisLoc env
+ | ObjLiteral("null") -> NullConst
+ | IdLiteral("this") | IdLiteral("null") -> failwith "should never happen anymore" //TODO
+ | VarLiteral(id)
+ | IdLiteral(id) ->
+ match TryResolve (env,ctx) (Unresolved(id)) with
+ | Unresolved(_) -> __EvalResolver (Dot(ObjLiteral("this"), id))
+ | _ as c -> c
+ | Dot(e, str) ->
+ let discr = __EvalResolver e
+ let h2 = Map.filter (fun (loc,Var(fldName,_)) v -> loc = discr && fldName = str) heap |> Map.toList
+ match h2 with
+ | ((_,_),x) :: [] -> x
+ | _ :: _ -> raise (EvalFailed(sprintf "can't evaluate expression deterministically: %s.%s resolves to multiple locations" (PrintConst discr) str))
+ | [] -> raise (EvalFailed(sprintf "can't find value for %s.%s" (PrintConst discr) str))
+ | _ -> failwith ("NOT IMPLEMENTED YET: " + (PrintExpr 0 expr))
+ (* --- function body starts here --- *)
+ EvalSym (fun e -> __EvalResolver e |> Resolve (env,ctx) |> Const2Expr) expr
diff --git a/Jennisys/Jennisys/TypeChecker.fs b/Jennisys/Jennisys/TypeChecker.fs
index 7414f253..bf012a11 100644
--- a/Jennisys/Jennisys/TypeChecker.fs
+++ b/Jennisys/Jennisys/TypeChecker.fs
@@ -6,34 +6,34 @@ open System.Collections.Generic
let GetClass name decls =
match decls |> List.tryFind (function Class(n,_,_) when n = name -> true | _ -> false) with
- | Some(cl) -> cl
- | None -> Class(name,[],[])
+ | Some(cl) -> cl
+ | None -> Class(name,[],[])
let GetModel name decls =
match decls |> List.tryFind (function Model(n,_,_,_,_) when n = name -> true | _ -> false) with
- | Some(m) -> m
- | None -> Model(name,[],[],[],IdLiteral("true"))
+ | Some(m) -> m
+ | None -> Model(name,[],[],[],BoolLiteral(true))
let GetCode name decls =
match decls |> List.tryFind (function Code(n,_) when n = name -> true | _ -> false) with
- | Some(c) -> c
- | None -> Code(name,[])
+ | Some(c) -> c
+ | None -> Code(name,[])
let IsUserType prog tpo =
match tpo with
- | Some(tp) ->
- let tpname = match tp with
- | NamedType(tname) -> tname
- | InstantiatedType(tname, _) -> tname
- | _ -> ""
- match prog with
- | Program(components) -> components |> List.filter (function Component(Class(name,_,_),_,_) when name = tpname -> true
- | _ -> false) |> List.isEmpty |> not
- | None -> false
+ | Some(tp) ->
+ let tpname = match tp with
+ | NamedType(tname,_) -> tname
+ | InstantiatedType(tname, _) -> tname
+ | _ -> ""
+ match prog with
+ | Program(components) -> components |> List.filter (function Component(Class(name,_,_),_,_) when name = tpname -> true
+ | _ -> false) |> List.isEmpty |> not
+ | None -> false
let TypeCheck prog =
match prog with
- | SProgram(decls) ->
+ | SProgram(decls) ->
let componentNames = decls |> List.choose (function Class(name,_,_) -> Some(name) | _ -> None)
let clist = componentNames |> List.map (fun name -> Component(GetClass name decls, GetModel name decls, GetCode name decls))
Some(Program(clist))
diff --git a/Jennisys/Jennisys/Utils.fs b/Jennisys/Jennisys/Utils.fs
index 3cb8fee4..886d5868 100644
--- a/Jennisys/Jennisys/Utils.fs
+++ b/Jennisys/Jennisys/Utils.fs
@@ -1,6 +1,8 @@
-/// Various utility functions
+// ####################################################################
+/// Various utility functions
///
-/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+/// author: Aleksandar Milicevic (t-alekm@microsoft.com)
+// ####################################################################
module Utils
@@ -9,6 +11,28 @@ module Utils
// -------------------------------------------
// =====================================
+/// ensures: ret = b ? Some(b) : None
+// =====================================
+let BoolToOption b =
+ if b then
+ Some(b)
+ else
+ None
+
+// =====================================
+/// ensures: ret = (opt == Some(_))
+// =====================================
+let IsSomeOption opt =
+ match opt with
+ | Some(_) -> true
+ | None -> false
+
+// =====================================
+/// ensures: ret = (opt == None)
+// =====================================
+let IsNoneOption opt = IsSomeOption opt |> not
+
+// =====================================
/// requres: x = Some(a) or failswith msg
/// ensures: ret = a
// =====================================
@@ -24,21 +48,23 @@ let ExtractOptionMsg msg x =
let ExtractOption x =
ExtractOptionMsg "can't extract anything from a None" x
-// =============================
-/// requres: List.length lst <= 1
+// ==========================================================
+/// requres: List.length lst <= 1, otherwise fails with errMsg
/// ensures: if |lst| = 0 then
/// ret = None
/// else
/// ret = Some(lst[0])
-// =============================
-let ListToOption lst =
+// ==========================================================
+let ListToOptionMsg lst errMsg =
if List.length lst > 1 then
- failwith "given list contains more than one element"
+ failwith errMsg
if List.isEmpty lst then
None
else
Some(lst.[0])
+let ListToOption lst = ListToOptionMsg lst "given list contains more than one element"
+
// =============================================================
/// ensures: forall i :: 0 <= i < |lst| ==> ret[i] = Some(lst[i])
// =============================================================
@@ -47,47 +73,61 @@ let rec ConvertToOptionList lst =
| fs :: rest -> Some(fs) :: ConvertToOptionList rest
| [] -> []
-// =============================
-/// requres: Seq.length seq <= 1
+// =========================================================
+/// requres: Seq.length seq <= 1, otherwise fails with errMsg
/// ensures: if |seq| = 0 then
/// ret = None
/// else
/// ret = Some(seq[0])
-// =============================
-let SeqToOption seq =
+// =========================================================
+let SeqToOptionMsg seq errMsg =
if Seq.length seq > 1 then
- failwith "given seq contains more than one element"
+ failwith errMsg
if Seq.isEmpty seq then
None
else
Some(Seq.nth 0 seq)
-// =============================
-/// requires: Set.count set <= 1
+let SeqToOption seq = SeqToOptionMsg seq "given seq contains more than one element"
+
+// =========================================================
+/// requires: Set.count set <= 1, otherwise fails with errMsg
/// ensures: if |set| = 0 then
/// ret = None
/// else
/// ret = Some(set[0])
-// =============================
-let SetToOption set =
+// =========================================================
+let SetToOptionMsg set errMsg =
if Set.count set > 1 then
- failwith "give set contains more than one value"
+ failwith errMsg
if (Set.isEmpty set) then
None
else
Some(set |> Set.toList |> List.head)
-// ===============================================================
+let SetToOption set = SetToOptionMsg set "give set contains more than one value"
+
+// ============================================================
/// requires: n >= 0
-/// ensures: |ret| = n && forall i :: 0 <= i < n ==> ret[i] = None
-// ===============================================================
-let rec GenList n =
+/// ensures: |ret| = n && forall i :: 0 <= i < n ==> ret[i] = e
+// ============================================================
+let rec GenList n e =
if n < 0 then
failwith "n must be positive"
if n = 0 then
[]
else
- None :: (GenList (n-1))
+ e :: (GenList (n-1) e)
+
+// =======================================
+/// ensures: forall i :: 0 <= i < |lst| ==>
+/// if lst[i] = oldElem then
+/// ret[i] = newElem
+/// else
+/// ret[i] = lst[i]
+// =======================================
+let ListReplace oldElem newElem lst =
+ lst |> List.choose (fun e -> if e = oldElem then Some(newElem) else Some(e))
// ==========================
/// ensures: ret = elem in lst
@@ -164,10 +204,32 @@ let (|Prefix|_|) (p:string) (s:string) =
Some(s.Substring(p.Length))
else
None
+
+// -------------------------------------------
+// --------------- workflow ------------------
+// -------------------------------------------
-let (|Exact|_|) (p:string) (s:string) =
- if s = p then
- Some(s)
+let IfDo1 cond func1 a =
+ if cond then
+ func1 a
+ else
+ a
+
+let IfDo2 cond func2 (a1,a2) =
+ if cond then
+ func2 a1 a2
else
- None
+ a1,a2
+
+type CascadingBuilder<'a>(failVal: 'a) =
+ member this.Bind(v, f) =
+ match v with
+ | Some(x) -> f x
+ | None -> failVal
+ member this.Return(v) = v
+
+// -------------------------------------------
+// --------------- random --------------------
+// -------------------------------------------
+let Iden x = x \ No newline at end of file
diff --git a/Jennisys/Jennisys/examples/List.jen b/Jennisys/Jennisys/examples/List.jen
index 184f4947..e7f42ddc 100644
--- a/Jennisys/Jennisys/examples/List.jen
+++ b/Jennisys/Jennisys/examples/List.jen
@@ -6,6 +6,9 @@ class List[T] {
constructor Singleton(t: T)
ensures list = [t]
+
+ constructor Double(p: T, q: T)
+ ensures list = [p q]
}
model List[T] {
@@ -27,6 +30,9 @@ class Node[T] {
constructor Init(t: T)
ensures list = [t]
+
+ constructor Double(p: T, q: T)
+ ensures list = [p q]
}
model Node[T] {
diff --git a/Jennisys/Jennisys/examples/List3.jen b/Jennisys/Jennisys/examples/List3.jen
index 6bb49eb8..acb10ad5 100644
--- a/Jennisys/Jennisys/examples/List3.jen
+++ b/Jennisys/Jennisys/examples/List3.jen
@@ -33,7 +33,7 @@ model IntList {
root = null ==> |list| = 0
root != null ==> (|list| = |root.succ| + 1 &&
list[0] = root.data &&
- (forall i:int :: (0 <= i && i < |root.succ|) ==> (root.succ[i] != null && list[i+1] = root.succ[i].data)))
+ (forall i:int :: (0 < i && i <= |root.succ|) ==> (root.succ[i-1] != null && list[i] = root.succ[i-1].data)))
}
class IntNode {
diff --git a/Jennisys/Jennisys/examples/Number.jen b/Jennisys/Jennisys/examples/Number.jen
new file mode 100644
index 00000000..75417168
--- /dev/null
+++ b/Jennisys/Jennisys/examples/Number.jen
@@ -0,0 +1,40 @@
+class Number {
+ var num: int
+
+ constructor Init(p: int)
+ ensures num = p
+
+ constructor Double(p: int)
+ ensures num = 2*p
+
+ constructor Sum(a: int, b: int)
+ ensures num = a + b
+
+ constructor Min2(a: int, b: int)
+ ensures a < b ==> num = a
+ ensures a >= b ==> num = b
+
+ constructor Min22(a: int, b: int)
+ ensures num in {a b}
+ ensures num <= a && num <= b
+
+ constructor Min3(a: int, b: int, c: int)
+ ensures num in {a b c}
+ ensures num <= a && num <= b && num <= c
+
+ constructor MinSum(a: int, b: int, c: int)
+ ensures num in {a+b a+c b+c}
+ ensures num <= a+b && num <= b+c && num <= a+c
+
+ constructor Min4(a: int, b: int, c: int, d: int)
+ ensures num in {a b c d}
+ ensures num <= a && num <= b && num <= c && num <= d
+
+ constructor Abs(a: int)
+ ensures a < 0 ==> num = -a
+ ensures a >= 0 ==> num = a
+}
+
+model Number {
+
+} \ No newline at end of file
diff --git a/Jennisys/Jennisys/examples/Set.jen b/Jennisys/Jennisys/examples/Set.jen
new file mode 100644
index 00000000..6404bfd6
--- /dev/null
+++ b/Jennisys/Jennisys/examples/Set.jen
@@ -0,0 +1,52 @@
+class Set {
+ var elems: set[int]
+
+ constructor Empty()
+ ensures elems = {}
+
+ constructor Singleton(t: int)
+ ensures elems = {t}
+
+ constructor Sum(p: int, q: int)
+ ensures elems = {p + q}
+
+ constructor Double(p: int, q: int)
+ requires p != q
+ ensures elems = {p q}
+}
+
+model Set {
+ var root: SetNode
+
+ frame
+ root * root.elems[*]
+
+ invariant
+ root = null ==> elems = {}
+ root != null ==> elems = root.elems
+}
+
+class SetNode {
+ var elems: set[int]
+
+ constructor Init(t: int)
+ ensures elems = {t}
+
+ constructor Double(p: int, q: int)
+ requires p != q
+ ensures elems = {p q}
+}
+
+model SetNode {
+ var data: int
+ var left: SetNode
+ var right: SetNode
+
+ frame
+ data * left * right
+
+ invariant
+ elems = {data} + (left != null ? left.elems : {}) + (right != null ? right.elems : {})
+ left != null ==> forall e :: e in left.elems ==> e < data
+ right != null ==> forall e :: e in right.elems ==> e > data
+}
diff --git a/Jennisys/Jennisys/scripts/StartDafny-jen.bat b/Jennisys/Jennisys/scripts/StartDafny-jen.bat
index 79d39a38..6f44ec4c 100644
--- a/Jennisys/Jennisys/scripts/StartDafny-jen.bat
+++ b/Jennisys/Jennisys/scripts/StartDafny-jen.bat
@@ -1,3 +1,2 @@
@echo off
"c:/boogie/Binaries/Dafny.exe" -nologo -compile:0 /print:xxx.bpl -timeLimit:60 %* > c:\tmp\jen-doo.out
-exit 43
diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs
index 825efa21..def13f7d 100644
--- a/Source/Core/AbsyCmd.cs
+++ b/Source/Core/AbsyCmd.cs
@@ -1915,8 +1915,8 @@ namespace Microsoft.Boogie {
if (QKeyValue.FindBoolAttribute(this.Attributes, "async") && Outs.Count > 0) {
Type returnType = cce.NonNull(Outs[0]).ShallowType;
- if (!returnType.Equals(Type.Int)) {
- tc.Error(this.tok, "the return from an asynchronous call should be an integer");
+ if (!returnType.Equals(Type.Int) && !returnType.Equals(Type.GetBvType(32))) {
+ tc.Error(this.tok, "the return from an asynchronous call should be either int or bv32");
return;
}
}
diff --git a/Source/Core/BoogiePL.atg b/Source/Core/BoogiePL.atg
index 6b8bb178..b1fbd609 100644
--- a/Source/Core/BoogiePL.atg
+++ b/Source/Core/BoogiePL.atg
@@ -45,7 +45,7 @@ Contract.Requires(cce.NonNullElements(defines,true));
return ret;
}
-
+
public static int Parse (Stream stream, string/*!*/ filename, /*maybe null*/ List<string/*!*/> defines, out /*maybe null*/ Program program) /* throws System.IO.IOException */ {
Contract.Requires(stream != null);
Contract.Requires(filename != null);
@@ -341,7 +341,7 @@ Types<TypeSeq/*!*/ ts>
/*------------------------------------------------------------------------*/
-Consts<out VariableSeq/*!*/ ds>
+Consts<out VariableSeq/*!*/ ds>
= (. Contract.Ensures(Contract.ValueAtReturn(out ds) != null); IToken/*!*/ y; TypedIdentSeq/*!*/ xs;
ds = new VariableSeq();
bool u = false; QKeyValue kv = null;
@@ -415,16 +415,16 @@ ds = new DeclarationSeq(); IToken/*!*/ z;
Expr definition = null;
Expr/*!*/ tmp;
.)
- "function" { Attribute<ref kv> } Ident<out z>
+ "function" { Attribute<ref kv> } Ident<out z>
[ TypeParams<out typeParamTok, out typeParams> ]
"("
[ VarOrType<out tyd> (. arguments.Add(new Formal(tyd.tok, tyd, true)); .)
{ "," VarOrType<out tyd> (. arguments.Add(new Formal(tyd.tok, tyd, true)); .)
} ] ")"
- (
+ (
"returns" "(" VarOrType<out tyd> ")" (. retTyd = tyd; .)
- |
- ":" Type<out retTy> (. retTyd = new TypedIdent(retTy.tok, "", retTy); .)
+ |
+ ":" Type<out retTy> (. retTyd = new TypedIdent(retTy.tok, "", retTy); .)
)
( "{" Expression<out tmp> (. definition = tmp; .) "}" | ";" )
(.
@@ -587,7 +587,7 @@ Procedure<out Procedure/*!*/ proc, out /*maybe null*/ Implementation impl>
(.
// here we attach kv only to the Procedure, not its implementation
impl = new Implementation(x, x.val, typeParams,
- Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, null, this.errors);
+ Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, null, this.errors);
.)
)
(. proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv); .)
@@ -1047,12 +1047,12 @@ ImpliesExpression<bool noExplies, out Expr/*!*/ e0>
ExpliesOp (. if (noExplies)
this.SemErr("illegal mixture of ==> and <==, use parentheses to disambiguate");
x = t; .)
- LogicalExpression<out e1>
+ LogicalExpression<out e1>
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
/* loop because explies is left-associative */
{
ExpliesOp (. x = t; .)
- LogicalExpression<out e1>
+ LogicalExpression<out e1>
(. e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); .)
}
]
@@ -1211,19 +1211,19 @@ ArrayExpression<out Expr/*!*/ e>
allArgs.Add(e);
store = false; bvExtract = false; .)
[
- Expression<out index0>
+ Expression<out index0>
(. if (index0 is BvBounds)
bvExtract = true;
else
allArgs.Add(index0);
.)
- { "," Expression<out e1>
+ { "," Expression<out e1>
(. if (bvExtract || e1 is BvBounds)
this.SemErr("bitvectors only have one dimension");
allArgs.Add(e1);
.)
}
- [ ":=" Expression<out e1>
+ [ ":=" Expression<out e1>
(. if (bvExtract || e1 is BvBounds)
this.SemErr("assignment to bitvectors is not possible");
allArgs.Add(e1); store = true;
@@ -1239,7 +1239,7 @@ ArrayExpression<out Expr/*!*/ e>
((BvBounds)index0).Upper.ToIntSafe,
((BvBounds)index0).Lower.ToIntSafe);
else
- e = new NAryExpr(x, new MapSelect(x, allArgs.Length - 1), allArgs);
+ e = new NAryExpr(x, new MapSelect(x, allArgs.Length - 1), allArgs);
.)
}
.
@@ -1282,11 +1282,11 @@ AtomExpression<out Expr/*!*/ e>
(. if (typeParams.Length + ds.Length > 0)
e = new ForallExpr(x, typeParams, ds, kv, trig, e); .)
| Exists (. x = t; .)
- QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
+ QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
(. if (typeParams.Length + ds.Length > 0)
e = new ExistsExpr(x, typeParams, ds, kv, trig, e); .)
| Lambda (. x = t; .)
- QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
+ QuantifierBody<x, out typeParams, out ds, out kv, out trig, out e>
(. if (trig != null)
SemErr("triggers not allowed in lambda expressions");
if (typeParams.Length + ds.Length > 0)
@@ -1404,7 +1404,7 @@ AttributeParameter<out object/*!*/ o>
IfThenElseExpression<out Expr/*!*/ e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
IToken/*!*/ tok;
- Expr/*!*/ e0, e1, e2;
+ Expr/*!*/ e0, e1, e2;
e = dummyExpr; .)
"if" (. tok = t; .) Expression<out e0> "then" Expression<out e1> "else" Expression<out e2>
(. e = new NAryExpr(tok, new IfThenElse(tok), new ExprSeq(e0, e1, e2)); .)
diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs
index 4a9c531b..56116601 100644
--- a/Source/Core/CommandLineOptions.cs
+++ b/Source/Core/CommandLineOptions.cs
@@ -72,12 +72,12 @@ namespace Microsoft.Boogie {
}
}
- private static CommandLineOptions clo = new CommandLineOptions();
+ private static CommandLineOptions clo = new CommandLineOptions();
public static CommandLineOptions/*!*/ Clo
{
get { return clo; }
}
-
+
public string/*!*/ Environment = "";
public string/*!*/ FileName = "unknown";
@@ -450,7 +450,7 @@ namespace Microsoft.Boogie {
[Verify(false)]
private CommandLineOptions() {
- // this is just to suppress verification.
+ // this is just to suppress verification.
}
[Verify(false)]
@@ -1170,7 +1170,7 @@ namespace Microsoft.Boogie {
}
break;
case "-recursionBound":
- case "/recursionBound":
+ case "/recursionBound":
if(ps.ConfirmArgumentCount(1)){
RecursionBound = Int32.Parse(cce.NonNull(args[ps.i]));
}
@@ -1918,7 +1918,7 @@ namespace Microsoft.Boogie {
---- On axioms -------------------------------------------------------------
{:inline true}
- Works on axiom of the form:
+ Works on axiom of the form:
(forall VARS :: f(VARS) = expr(VARS))
Makes Boogie replace f(VARS) with expr(VARS) everywhere just before
doing VC generation.
@@ -1934,36 +1934,36 @@ namespace Microsoft.Boogie {
---- On implementations and procedures -------------------------------------
{:inline N}
- Inline given procedure (can be also used on implementation).
- N should be a non-negative number and represents the inlining depth.
+ Inline given procedure (can be also used on implementation).
+ N should be a non-negative number and represents the inlining depth.
With /inline:assume call is replaced with ""assume false"" once inlining depth is reached.
With /inline:assert call is replaced with ""assert false"" once inlining depth is reached.
With /inline:spec call is left as is once inlining depth is reached.
With the above three options, methods with the attribute {:inline N} are not verified.
- With /inline:none the entire attribute is ignored.
-
+ With /inline:none the entire attribute is ignored.
+
{:verify false}
Skip verification of an implementation.
-
+
{:forceBvZ3Native true}
Verify the given implementation with the native Z3 bitvector
handling. Only works if /bv:i (or /bv:z, but then it does not do
anything) is given on the command line.
-
+
{:forceBvInt true}
Use int translation for the given implementation. Only work with
/bv:z (or /bv:i).
-
+
{:vcs_max_cost N}
{:vcs_max_splits N}
{:vcs_max_keep_going_splits N}
- Per-implementation versions of
+ Per-implementation versions of
/vcsMaxCost, /vcsMaxSplits and /vcsMaxKeepGoingSplits.
{:selective_checking true}
Turn all asserts into assumes except for the ones reachable from
assumptions marked with the attribute {:start_checking_here}.
- Thus, ""assume {:start_checking_here} something;"" becomes an inverse
+ Thus, ""assume {:start_checking_here} something;"" becomes an inverse
of ""assume false;"": the first one disables all verification before
it, and the second one disables all verification after.
@@ -1971,7 +1971,7 @@ namespace Microsoft.Boogie {
{:bvbuiltin ""spec""}
Z3 specific, used only with /bv:z.
-
+
{:bvint ""fn""}
With /bv:i rewrite the function to function symbol 'fn', except if
the 'fn' is 'id', in which case just strip the function altogether.
@@ -1996,7 +1996,7 @@ namespace Microsoft.Boogie {
{:subsumption n}
Overrides the /subsumption command-line setting for this assertion.
-
+
---- The end ---------------------------------------------------------------
");
}
@@ -2099,7 +2099,7 @@ namespace Microsoft.Boogie {
t = trivial (implied by /methodology:vs)
/printModel:<n> : 0 (default) - do not print Z3's error model
1 - print Z3's error model
- 2 - print Z3's error model plus reverse mappings
+ 2 - print Z3's error model plus reverse mappings
4 - print Z3's error model in a more human readable way
/printModelToFile:<file> : print model to <file> instead of console
/mv:<file> Specify file where to save the model in BVD format
@@ -2107,7 +2107,7 @@ namespace Microsoft.Boogie {
1 - Z3 error model enhanced error messages
---- Dafny options ---------------------------------------------------------
-
+
Multiple .dfy files supplied on the command line are concatenated into one
Dafny program.
@@ -2137,7 +2137,7 @@ namespace Microsoft.Boogie {
identifies variables
/printUnstructured : with /print option, desugars all structured statements
/printDesugared : with /print option, desugars calls
-
+
/overlookTypeErrors : skip any implementation with resolution or type
checking errors
@@ -2152,7 +2152,7 @@ namespace Microsoft.Boogie {
+ @"
<flags> are as follows (missing <flags> means all)
i = intervals
- c = constant propagation
+ c = constant propagation
d = dynamic type
n = nullness
p = polyhedra for linear inequalities
@@ -2186,8 +2186,8 @@ namespace Microsoft.Boogie {
/break[:method] : break into debugger
---- Verification-condition generation options -----------------------------
-
- /liveVariableAnalysis:<c> : 0 = do not perform live variable analysis
+
+ /liveVariableAnalysis:<c> : 0 = do not perform live variable analysis
1 = perform live variable analysis (default)
2 = perform interprocedural live variable analysis
/noVerify : skip VC generation and invocation of the theorem prover
@@ -2211,25 +2211,25 @@ namespace Microsoft.Boogie {
n = none
z = native Z3 bitvectors (default)
i = unsoundly translate bitvectors to integers
- /inline:<i> : use inlining strategy <i> for procedures with the :inline
+ /inline:<i> : use inlining strategy <i> for procedures with the :inline
attribute, see /attrHelp for details:
none
assume (default)
assert
spec
- /printInlined : print the implementation after inlining calls to
+ /printInlined : print the implementation after inlining calls to
procedures with the :inline attribute (works with /inline)
/lazyInline:1 : Use the lazy inlining algorithm
/stratifiedInline:1 : Use the stratified inlining algorithm
- /recursionBound:<n> : Set the recursion bound for stratified inlining to
+ /recursionBound:<n> : Set the recursion bound for stratified inlining to
be n (default 500)
/inferLeastForUnsat:<str> : Infer the least number of constants (whose names
- are prefixed by <str>) that need to be set to
+ are prefixed by <str>) that need to be set to
true for the program to be correct. This turns
on stratified inlining.
- /smoke : Soundness Smoke Test: try to stick assert false; in some
+ /smoke : Soundness Smoke Test: try to stick assert false; in some
places in the BPL and see if we can still prove it
- /smokeTimeout:<n> : Timeout, in seconds, for a single theorem prover
+ /smokeTimeout:<n> : Timeout, in seconds, for a single theorem prover
invocation during smoke test, defaults to 10.
/causalImplies : Translate Boogie's A ==> B into prover's A ==> A && B.
/typeEncoding:<m> : how to encode types when sending VC to theorem prover
@@ -2247,38 +2247,38 @@ namespace Microsoft.Boogie {
/vcsMaxCost:<f> : VC will not be split unless the cost of a VC exceeds this
number, defaults to 2000.0. This does NOT apply in the
keep-going mode after first round of splitting.
- /vcsMaxSplits:<n> : Maximal number of VC generated per method. In keep
+ /vcsMaxSplits:<n> : Maximal number of VC generated per method. In keep
going mode only applies to the first round.
Defaults to 1.
- /vcsMaxKeepGoingSplits:<n> : If set to more than 1, activates the keep
+ /vcsMaxKeepGoingSplits:<n> : If set to more than 1, activates the keep
going mode, where after the first round of splitting,
VCs that timed out are split into <n> pieces and retried
- until we succeed proving them, or there is only one
+ until we succeed proving them, or there is only one
assertion on a single path and it timeouts (in which
- case error is reported for that assertion).
+ case error is reported for that assertion).
Defaults to 1.
/vcsKeepGoingTimeout:<n> : Timeout in seconds for a single theorem prover
invocation in keep going mode, except for the final
single-assertion case. Defaults to 1s.
- /vcsFinalAssertTimeout:<n> : Timeout in seconds for the single last
+ /vcsFinalAssertTimeout:<n> : Timeout in seconds for the single last
assertion in the keep going mode. Defaults to 30s.
/vcsPathJoinMult:<f> : If more than one path join at a block, by how much
multiply the number of paths in that block, to accomodate
for the fact that the prover will learn something on one
paths, before proceeding to another. Defaults to 0.8.
/vcsPathCostMult:<f1>
- /vcsAssumeMult:<f2> : The cost of a block is
+ /vcsAssumeMult:<f2> : The cost of a block is
(<assert-cost> + <f2>*<assume-cost>)*(1.0 + <f1>*<entering-paths>)
<f1> defaults to 1.0, <f2> defaults to 0.01.
- The cost of a single assertion or assumption is
+ The cost of a single assertion or assumption is
currently always 1.0.
- /vcsPathSplitMult:<f> : If the best path split of a VC of cost A is into
+ /vcsPathSplitMult:<f> : If the best path split of a VC of cost A is into
VCs of cost B and C, then the split is applied if
- A >= <f>*(B+C), otherwise assertion splitting will be
- applied. Defaults to 0.5 (always do path splitting if
+ A >= <f>*(B+C), otherwise assertion splitting will be
+ applied. Defaults to 0.5 (always do path splitting if
possible), set to more to do less path splitting
and more assertion splitting.
- /vcsDumpSplits For split #n dump split.n.dot and split.n.bpl.
+ /vcsDumpSplits For split #n dump split.n.dot and split.n.bpl.
Warning: Affects error reporting.
/vcsCores:<n> : Try to verify <n> VCs at once. Defaults to 1.
@@ -2292,10 +2292,10 @@ namespace Microsoft.Boogie {
1 (default) - include useful Trace labels in error output,
2 - include all Trace labels in the error output
/vcBrackets:<b> : bracket odd-charactered identifier names with |'s. <b> is:
- 0 - no (default with /prover:Z3),
+ 0 - no (default with /prover:Z3),
1 - yes (default with /prover:Simplify)
/prover:<tp> : use theorem prover <tp>, where <tp> is either the name of
- a DLL containing the prover interface located in the
+ a DLL containing the prover interface located in the
Boogie directory, or a full path to a DLL containing such
an interface. The standard interfaces shipped include:
Z3 (default)
diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs
index cab72087..9c208b86 100644
--- a/Source/Core/Parser.cs
+++ b/Source/Core/Parser.cs
@@ -64,7 +64,7 @@ Contract.Requires(cce.NonNullElements(defines,true));
return ret;
}
-
+
public static int Parse (Stream stream, string/*!*/ filename, /*maybe null*/ List<string/*!*/> defines, out /*maybe null*/ Program program) /* throws System.IO.IOException */ {
Contract.Requires(stream != null);
Contract.Requires(filename != null);
@@ -283,41 +283,41 @@ private class BvBounds : Expr {
}
bool makeClone = false;
foreach(TypedIdent/*!*/ x in xs){
- Contract.Assert(x != null);
+ Contract.Assert(x != null);
+
+ // ensure that no sharing is introduced
+ List<ConstantParent/*!*/> ParentsClone;
+ if (makeClone && Parents != null) {
+ ParentsClone = new List<ConstantParent/*!*/> ();
+ foreach (ConstantParent/*!*/ p in Parents){
+ Contract.Assert(p != null);
+ ParentsClone.Add(new ConstantParent (
+ new IdentifierExpr (p.Parent.tok, p.Parent.Name),
+ p.Unique));}
+ } else {
+ ParentsClone = Parents;
+ }
+ makeClone = true;
- // ensure that no sharing is introduced
- List<ConstantParent/*!*/> ParentsClone;
- if (makeClone && Parents != null) {
- ParentsClone = new List<ConstantParent/*!*/> ();
- foreach (ConstantParent/*!*/ p in Parents){
- Contract.Assert(p != null);
- ParentsClone.Add(new ConstantParent (
- new IdentifierExpr (p.Parent.tok, p.Parent.Name),
- p.Unique));}
- } else {
- ParentsClone = Parents;
- }
- makeClone = true;
+ ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
+ }
- ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv));
- }
-
Expect(7);
}
void Function(out DeclarationSeq/*!*/ ds) {
Contract.Ensures(Contract.ValueAtReturn(out ds) != null);
ds = new DeclarationSeq(); IToken/*!*/ z;
- IToken/*!*/ typeParamTok;
- TypeVariableSeq/*!*/ typeParams = new TypeVariableSeq();
- VariableSeq arguments = new VariableSeq();
- TypedIdent/*!*/ tyd;
- TypedIdent retTyd = null;
- Type/*!*/ retTy;
- QKeyValue kv = null;
- Expr definition = null;
- Expr/*!*/ tmp;
-
+ IToken/*!*/ typeParamTok;
+ TypeVariableSeq/*!*/ typeParams = new TypeVariableSeq();
+ VariableSeq arguments = new VariableSeq();
+ TypedIdent/*!*/ tyd;
+ TypedIdent retTyd = null;
+ Type/*!*/ retTy;
+ QKeyValue kv = null;
+ Expr definition = null;
+ Expr/*!*/ tmp;
+
Expect(23);
while (la.kind == 25) {
Attribute(ref kv);
@@ -360,78 +360,78 @@ private class BvBounds : Expr {
// construct a dummy type for the case of syntax error
tyd = new TypedIdent(t, "", new BasicType(t, SimpleType.Int));
} else {
- tyd = retTyd;
+ tyd = retTyd;
}
Function/*!*/ func = new Function(z, z.val, typeParams, arguments,
- new Formal(tyd.tok, tyd, false), null, kv);
+ new Formal(tyd.tok, tyd, false), null, kv);
Contract.Assert(func != null);
ds.Add(func);
bool allUnnamed = true;
foreach(Formal/*!*/ f in arguments){
- Contract.Assert(f != null);
- if (f.TypedIdent.Name != "") {
- allUnnamed = false;
+ Contract.Assert(f != null);
+ if (f.TypedIdent.Name != "") {
+ allUnnamed = false;
break;
- }
- }
- if (!allUnnamed) {
- Type prevType = null;
- for (int i = arguments.Length - 1; i >= 0; i--) {
- TypedIdent/*!*/ curr = cce.NonNull(arguments[i]).TypedIdent;
- if (curr.Name == "") {
- if (prevType == null) {
- this.errors.SemErr(curr.tok, "the type of the last parameter is unspecified");
- break;
- }
- Type ty = curr.Type;
- if (ty is UnresolvedTypeIdentifier &&
- cce.NonNull(ty as UnresolvedTypeIdentifier).Arguments.Length == 0) {
- curr.Name = cce.NonNull(ty as UnresolvedTypeIdentifier).Name;
- curr.Type = prevType;
- } else {
- this.errors.SemErr(curr.tok, "expecting an identifier as parameter name");
- }
+ }
+ }
+ if (!allUnnamed) {
+ Type prevType = null;
+ for (int i = arguments.Length - 1; i >= 0; i--) {
+ TypedIdent/*!*/ curr = cce.NonNull(arguments[i]).TypedIdent;
+ if (curr.Name == "") {
+ if (prevType == null) {
+ this.errors.SemErr(curr.tok, "the type of the last parameter is unspecified");
+ break;
+ }
+ Type ty = curr.Type;
+ if (ty is UnresolvedTypeIdentifier &&
+ cce.NonNull(ty as UnresolvedTypeIdentifier).Arguments.Length == 0) {
+ curr.Name = cce.NonNull(ty as UnresolvedTypeIdentifier).Name;
+ curr.Type = prevType;
} else {
- prevType = curr.Type;
+ this.errors.SemErr(curr.tok, "expecting an identifier as parameter name");
}
- }
+ } else {
+ prevType = curr.Type;
+ }
+ }
+ }
+ if (definition != null) {
+ // generate either an axiom or a function body
+ if (QKeyValue.FindBoolAttribute(kv, "inline")) {
+ func.Body = definition;
+ } else {
+ VariableSeq dummies = new VariableSeq();
+ ExprSeq callArgs = new ExprSeq();
+ int i = 0;
+ foreach(Formal/*!*/ f in arguments){
+ Contract.Assert(f != null);
+ string nm = f.TypedIdent.HasName ? f.TypedIdent.Name : "_" + i;
+ dummies.Add(new BoundVariable(f.tok, new TypedIdent(f.tok, nm, f.TypedIdent.Type)));
+ callArgs.Add(new IdentifierExpr(f.tok, nm));
+ i++;
+ }
+ TypeVariableSeq/*!*/ quantifiedTypeVars = new TypeVariableSeq ();
+ foreach(TypeVariable/*!*/ t in typeParams){
+ Contract.Assert(t != null);
+ quantifiedTypeVars.Add(new TypeVariable (Token.NoToken, t.Name));
}
- if (definition != null) {
- // generate either an axiom or a function body
- if (QKeyValue.FindBoolAttribute(kv, "inline")) {
- func.Body = definition;
- } else {
- VariableSeq dummies = new VariableSeq();
- ExprSeq callArgs = new ExprSeq();
- int i = 0;
- foreach(Formal/*!*/ f in arguments){
- Contract.Assert(f != null);
- string nm = f.TypedIdent.HasName ? f.TypedIdent.Name : "_" + i;
- dummies.Add(new BoundVariable(f.tok, new TypedIdent(f.tok, nm, f.TypedIdent.Type)));
- callArgs.Add(new IdentifierExpr(f.tok, nm));
- i++;
- }
- TypeVariableSeq/*!*/ quantifiedTypeVars = new TypeVariableSeq ();
- foreach(TypeVariable/*!*/ t in typeParams){
- Contract.Assert(t != null);
- quantifiedTypeVars.Add(new TypeVariable (Token.NoToken, t.Name));
- }
- Expr call = new NAryExpr(z, new FunctionCall(new IdentifierExpr(z, z.val)), callArgs);
- // specify the type of the function, because it might be that
- // type parameters only occur in the output type
- call = Expr.CoerceType(z, call, (Type)tyd.Type.Clone());
- Expr def = Expr.Eq(call, definition);
- if (quantifiedTypeVars.Length != 0 || dummies.Length != 0) {
- def = new ForallExpr(z, quantifiedTypeVars, dummies,
- kv,
- new Trigger(z, true, new ExprSeq(call), null),
- def);
- }
- ds.Add(new Axiom(z, def, "autogenerated definition axiom", null));
- }
- }
-
+ Expr call = new NAryExpr(z, new FunctionCall(new IdentifierExpr(z, z.val)), callArgs);
+ // specify the type of the function, because it might be that
+ // type parameters only occur in the output type
+ call = Expr.CoerceType(z, call, (Type)tyd.Type.Clone());
+ Expr def = Expr.Eq(call, definition);
+ if (quantifiedTypeVars.Length != 0 || dummies.Length != 0) {
+ def = new ForallExpr(z, quantifiedTypeVars, dummies,
+ kv,
+ new Trigger(z, true, new ExprSeq(call), null),
+ def);
+ }
+ ds.Add(new Axiom(z, def, "autogenerated definition axiom", null));
+ }
+ }
+
}
void Axiom(out Axiom/*!*/ m) {
@@ -485,11 +485,11 @@ private class BvBounds : Expr {
IdentifierExprSeq/*!*/ mods = new IdentifierExprSeq();
EnsuresSeq/*!*/ post = new EnsuresSeq();
- VariableSeq/*!*/ locals = new VariableSeq();
- StmtList/*!*/ stmtList;
- QKeyValue kv = null;
- impl = null;
-
+ VariableSeq/*!*/ locals = new VariableSeq();
+ StmtList/*!*/ stmtList;
+ QKeyValue kv = null;
+ impl = null;
+
Expect(30);
ProcSignature(true, out x, out typeParams, out ins, out outs, out kv);
if (la.kind == 7) {
@@ -503,7 +503,7 @@ private class BvBounds : Expr {
}
ImplBody(out locals, out stmtList);
impl = new Implementation(x, x.val, typeParams,
- Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, null, this.errors);
+ Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, null, this.errors);
} else SynErr(91);
proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv);
@@ -584,8 +584,8 @@ private class BvBounds : Expr {
Type(out ty);
tyds = new TypedIdentSeq();
foreach(Token/*!*/ id in ids){
- Contract.Assert(id != null);
- tyds.Add(new TypedIdent(id, id.val, ty, null));
+ Contract.Assert(id != null);
+ tyds.Add(new TypedIdent(id, id.val, ty, null));
}
}
@@ -628,7 +628,7 @@ private class BvBounds : Expr {
if (allowWhereClauses) {
wh = nne;
} else {
- this.SemErr("where clause not allowed here");
+ this.SemErr("where clause not allowed here");
}
}
@@ -670,7 +670,7 @@ private class BvBounds : Expr {
Expect(1);
x = t;
if (x.val.StartsWith("\\"))
- x.val = x.val.Substring(1);
+ x.val = x.val.Substring(1);
}
@@ -725,8 +725,8 @@ private class BvBounds : Expr {
Expect(18);
typeParams = new TypeVariableSeq ();
foreach(Token/*!*/ id in typeParamToks){
- Contract.Assert(id != null);
- typeParams.Add(new TypeVariable(id, id.val));}
+ Contract.Assert(id != null);
+ typeParams.Add(new TypeVariable(id, id.val));}
}
@@ -785,7 +785,7 @@ private class BvBounds : Expr {
cce.NonNull(ty as UnresolvedTypeIdentifier).Arguments.Length == 0) {
varName = cce.NonNull(ty as UnresolvedTypeIdentifier).Name;
} else {
- this.SemErr("expected identifier before ':'");
+ this.SemErr("expected identifier before ':'");
}
Type(out ty);
@@ -817,7 +817,7 @@ private class BvBounds : Expr {
typeParams.Add(new TypeVariable(t, t.val));}
decl = new TypeSynonymDecl(id, id.val, typeParams, body, kv);
} else {
- decl = new TypeCtorDecl(id, id.val, paramTokens.Length, kv);
+ decl = new TypeCtorDecl(id, id.val, paramTokens.Length, kv);
}
}
@@ -924,18 +924,18 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
Contract.Assert(cs != null);
cs.Add(c);
} else {
- // LabelOrCmd read a label
- Contract.Assert(label != null);
- if (startToken != null) {
- Contract.Assert(cs != null);
- // dump the built-up state into a BigBlock
- b = new BigBlock(startToken, currentLabel, cs, null, null);
- bigblocks.Add(b);
- cs = null;
- }
- startToken = label;
- currentLabel = label.val;
- cs = new CmdSeq();
+ // LabelOrCmd read a label
+ Contract.Assert(label != null);
+ if (startToken != null) {
+ Contract.Assert(cs != null);
+ // dump the built-up state into a BigBlock
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
+ cs = null;
+ }
+ startToken = label;
+ currentLabel = label.val;
+ cs = new CmdSeq();
}
} else if (la.kind == 38 || la.kind == 40 || la.kind == 43) {
@@ -961,16 +961,16 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
Expect(26);
IToken/*!*/ endCurly = t;
if (startToken == null && bigblocks.Count == 0) {
- startToken = t; cs = new CmdSeq();
+ startToken = t; cs = new CmdSeq();
}
if (startToken != null) {
- Contract.Assert(cs != null);
- b = new BigBlock(startToken, currentLabel, cs, null, null);
- bigblocks.Add(b);
+ Contract.Assert(cs != null);
+ b = new BigBlock(startToken, currentLabel, cs, null, null);
+ bigblocks.Add(b);
}
- stmtList = new StmtList(bigblocks, endCurly);
-
+ stmtList = new StmtList(bigblocks, endCurly);
+
}
void LabelOrCmd(out Cmd c, out IToken label) {
@@ -1008,8 +1008,8 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
Expect(7);
ids = new IdentifierExprSeq();
foreach(IToken/*!*/ y in xs){
- Contract.Assert(y != null);
- ids.Add(new IdentifierExpr(y, y.val));
+ Contract.Assert(y != null);
+ ids.Add(new IdentifierExpr(y, y.val));
}
c = new HavocCmd(x,ids);
@@ -1104,7 +1104,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (isFree) {
invariants.Add(new AssumeCmd(z, e));
} else {
- invariants.Add(new AssertCmd(z, e));
+ invariants.Add(new AssertCmd(z, e));
}
Expect(7);
@@ -1223,7 +1223,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (p==null) {
ids.Add(null);
} else {
- ids.Add(new IdentifierExpr(p, p.val));
+ ids.Add(new IdentifierExpr(p, p.val));
}
while (la.kind == 11) {
@@ -1232,7 +1232,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (p==null) {
ids.Add(null);
} else {
- ids.Add(new IdentifierExpr(p, p.val));
+ ids.Add(new IdentifierExpr(p, p.val));
}
}
@@ -1277,7 +1277,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (p==null) {
ids.Add(null);
} else {
- ids.Add(new IdentifierExpr(p, p.val));
+ ids.Add(new IdentifierExpr(p, p.val));
}
while (la.kind == 11) {
@@ -1286,7 +1286,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (p==null) {
ids.Add(null);
} else {
- ids.Add(new IdentifierExpr(p, p.val));
+ ids.Add(new IdentifierExpr(p, p.val));
}
}
@@ -1625,7 +1625,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
this.SemErr("arguments of extract need to be integer literals");
e = new BvBounds(x, bn, BigNum.ZERO);
} else {
- e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
+ e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum);
}
} else SynErr(117);
@@ -1650,7 +1650,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (index0 is BvBounds)
bvExtract = true;
else
- allArgs.Add(index0);
+ allArgs.Add(index0);
while (la.kind == 11) {
Get();
@@ -1678,11 +1678,11 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (store)
e = new NAryExpr(x, new MapStore(x, allArgs.Length - 2), allArgs);
else if (bvExtract)
- e = new BvExtractExpr(x, e,
- ((BvBounds)index0).Upper.ToIntSafe,
- ((BvBounds)index0).Lower.ToIntSafe);
+ e = new BvExtractExpr(x, e,
+ ((BvBounds)index0).Upper.ToIntSafe,
+ ((BvBounds)index0).Lower.ToIntSafe);
else
- e = new NAryExpr(x, new MapSelect(x, allArgs.Length - 1), allArgs);
+ e = new NAryExpr(x, new MapSelect(x, allArgs.Length - 1), allArgs);
}
}
@@ -1692,8 +1692,8 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
try {
n = BigNum.FromString(t.val);
} catch (FormatException) {
- this.SemErr("incorrectly formatted number");
- n = BigNum.ZERO;
+ this.SemErr("incorrectly formatted number");
+ n = BigNum.ZERO;
}
}
@@ -1779,7 +1779,7 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
if (trig != null)
SemErr("triggers not allowed in lambda expressions");
if (typeParams.Length + ds.Length > 0)
- e = new LambdaExpr(x, typeParams, ds, kv, e);
+ e = new LambdaExpr(x, typeParams, ds, kv, e);
} else SynErr(119);
Expect(9);
break;
@@ -1803,12 +1803,12 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
string a = t.val.Substring(0, pos);
string b = t.val.Substring(pos + 2);
try {
- n = BigNum.FromString(a);
- m = Convert.ToInt32(b);
+ n = BigNum.FromString(a);
+ m = Convert.ToInt32(b);
} catch (FormatException) {
- this.SemErr("incorrectly formatted bitvector");
- n = BigNum.ZERO;
- m = 0;
+ this.SemErr("incorrectly formatted bitvector");
+ n = BigNum.ZERO;
+ m = 0;
}
}
@@ -1825,10 +1825,10 @@ out VariableSeq/*!*/ ins, out VariableSeq/*!*/ outs, out QKeyValue kv) {
out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
Contract.Requires(q != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ds) != null); Contract.Ensures(Contract.ValueAtReturn(out body) != null);
trig = null; typeParams = new TypeVariableSeq ();
- IToken/*!*/ tok;
- kv = null;
- ds = new VariableSeq ();
-
+ IToken/*!*/ tok;
+ kv = null;
+ ds = new VariableSeq ();
+
if (la.kind == 17) {
TypeParams(out tok, out typeParams);
if (la.kind == 1) {
@@ -1863,7 +1863,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
void IfThenElseExpression(out Expr/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null);
IToken/*!*/ tok;
- Expr/*!*/ e0, e1, e2;
+ Expr/*!*/ e0, e1, e2;
e = dummyExpr;
Expect(38);
tok = t;
@@ -1909,8 +1909,8 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
Contract.Assert(label == null);
cs.Add(c);
} else {
- Contract.Assert(label != null);
- SemErr("SpecBlock's can only have one label");
+ Contract.Assert(label != null);
+ SemErr("SpecBlock's can only have one label");
}
}
@@ -1963,11 +1963,11 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
this.SemErr("the 'nopats' quantifier attribute expects a string-literal parameter");
}
} else {
- if (kv==null) {
- kv = new QKeyValue(tok, key, parameters, null);
- } else {
- kv.AddLast(new QKeyValue(tok, key, parameters, null));
- }
+ if (kv==null) {
+ kv = new QKeyValue(tok, key, parameters, null);
+ } else {
+ kv.AddLast(new QKeyValue(tok, key, parameters, null));
+ }
}
} else if (StartOf(7)) {
@@ -1981,7 +1981,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
if (trig==null) {
trig = new Trigger(tok, true, es, null);
} else {
- trig.AddLast(new Trigger(tok, true, es, null));
+ trig.AddLast(new Trigger(tok, true, es, null));
}
} else SynErr(126);
@@ -2017,6 +2017,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) {
la.val = "";
Get();
BoogiePL();
+ Expect(0);
Expect(0);
}
@@ -2219,4 +2220,5 @@ public class FatalError: Exception {
public FatalError(string m): base(m) {}
}
+
} \ No newline at end of file
diff --git a/Source/Core/Scanner.cs b/Source/Core/Scanner.cs
index 7c3522ca..e3d131e0 100644
--- a/Source/Core/Scanner.cs
+++ b/Source/Core/Scanner.cs
@@ -232,6 +232,7 @@ public class Scanner {
Token/*!*/ t; // current token
int ch; // current input character
int pos; // byte position of current character
+ int charPos;
int col; // column number of current character
int line; // line number of current character
int oldEols; // EOLs that appeared in a comment;
@@ -440,7 +441,7 @@ public class Scanner {
bool Comment0() {
- int level = 1, pos0 = pos, line0 = line, col0 = col;
+ int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
NextCh();
if (ch == '/') {
NextCh();
@@ -453,13 +454,13 @@ public class Scanner {
else NextCh();
}
} else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0;
+ buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
}
return false;
}
bool Comment1() {
- int level = 1, pos0 = pos, line0 = line, col0 = col;
+ int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
NextCh();
if (ch == '*') {
NextCh();
@@ -480,7 +481,7 @@ public class Scanner {
else NextCh();
}
} else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0;
+ buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
}
return false;
}
diff --git a/Source/Dafny/Compiler.cs b/Source/Dafny/Compiler.cs
index 920105a9..0653fe2e 100644
--- a/Source/Dafny/Compiler.cs
+++ b/Source/Dafny/Compiler.cs
@@ -19,13 +19,13 @@ namespace Microsoft.Dafny {
}
[ContractInvariantMethod]
- void ObjectInvariant()
+ void ObjectInvariant()
{
Contract.Invariant(wr!=null);
}
TextWriter wr;
-
+
public int ErrorCount;
void Error(string msg, params object[] args) {Contract.Requires(msg != null);
string s = string.Format("Compilation error: " + msg, args);
@@ -33,7 +33,7 @@ namespace Microsoft.Dafny {
wr.WriteLine("/* {0} */", s);
ErrorCount++;
}
-
+
void ReadRuntimeSystem() {
string codebase = cce.NonNull( System.IO.Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)));
string path = System.IO.Path.Combine(codebase, "DafnyRuntime.cs");
@@ -226,7 +226,7 @@ namespace Microsoft.Dafny {
Indent(indent); wr.WriteLine("}");
}
}
-
+
void CompileDatatypeStruct(DatatypeDecl dt, int indent) {
Contract.Requires(dt != null);
@@ -254,23 +254,23 @@ namespace Microsoft.Dafny {
if (dt.TypeArgs.Count != 0) {
DtT += "<" + TypeParameters(dt.TypeArgs) + ">";
}
-
+
Indent(indent);
wr.WriteLine("public struct @{0} {{", DtT);
int ind = indent + IndentAmount;
-
+
Indent(ind);
wr.WriteLine("Base_{0} d;", DtT);
-
+
Indent(ind);
wr.WriteLine("public Base_{0} _D {{", DtT);
Indent(ind + IndentAmount);
wr.WriteLine("get { if (d == null) { d = Default; } return d; }");
Indent(ind); wr.WriteLine("}");
-
+
Indent(ind);
wr.WriteLine("public @{0}(Base_{1} d) {{ this.d = d; }}", dt.Name, DtT);
-
+
Indent(ind);
wr.WriteLine("public static Base_{0} Default {{", DtT);
Indent(ind + IndentAmount);
@@ -320,7 +320,7 @@ namespace Microsoft.Dafny {
Indent(indent);
wr.WriteLine("}");
}
-
+
int WriteFormals(string sep, List<Formal/*!*/>/*!*/ formals)
{
Contract.Requires(sep != null);
@@ -336,20 +336,20 @@ namespace Microsoft.Dafny {
}
return i; // the number of formals written
}
-
+
string FormalName(Formal formal, int i) {
Contract.Requires(formal != null);
Contract.Ensures(Contract.Result<string>() != null);
return formal.HasName ? formal.Name : "_a" + i;
}
-
+
string DtCtorName(DatatypeCtor ctor) {
Contract.Requires(ctor != null);Contract.Ensures(Contract.Result<string>() != null);
return cce.NonNull(ctor.EnclosingDatatype).Name + "_" + ctor.Name;
}
-
+
void CompileClassMembers(ClassDecl c, int indent)
{
Contract.Requires(c != null);
@@ -360,7 +360,7 @@ namespace Microsoft.Dafny {
Indent(indent);
wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type), f.Name, DefaultValue(f.Type));
}
-
+
} else if (member is Function) {
Function f = (Function)member;
if (f.IsGhost) {
@@ -379,7 +379,7 @@ namespace Microsoft.Dafny {
CompileReturnBody(f.Body, indent);
Indent(indent); wr.WriteLine("}");
}
-
+
} else if (member is Method) {
Method m = (Method)member;
if (!m.IsGhost) {
@@ -483,10 +483,10 @@ namespace Microsoft.Dafny {
}
// ----- Type ---------------------------------------------------------------------------------
-
+
readonly string DafnySetClass = "Dafny.Set";
readonly string DafnySeqClass = "Dafny.Sequence";
-
+
string TypeName(Type type)
{
Contract.Requires(type != null);
@@ -503,7 +503,7 @@ namespace Microsoft.Dafny {
type = tp.T;
}
}
-
+
if (type is BoolType) {
return "bool";
} else if (type is IntType) {
@@ -558,7 +558,7 @@ namespace Microsoft.Dafny {
}
return s;
}
-
+
string/*!*/ TypeParameters(List<TypeParameter/*!*/>/*!*/ targs) {
Contract.Requires(cce.NonNullElements(targs));
Contract.Ensures(Contract.Result<string>() != null);
@@ -571,7 +571,7 @@ namespace Microsoft.Dafny {
}
return s;
}
-
+
string DefaultValue(Type type)
{
Contract.Requires(type != null);
@@ -588,7 +588,7 @@ namespace Microsoft.Dafny {
type = tp.T;
}
}
-
+
if (type is BoolType) {
return "false";
} else if (type is IntType) {
@@ -613,16 +613,16 @@ namespace Microsoft.Dafny {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type
}
}
-
+
// ----- Stmt ---------------------------------------------------------------------------------
-
+
void TrStmt(Statement stmt, int indent)
{
Contract.Requires(stmt != null);
if (stmt.IsGhost) {
return;
}
-
+
if (stmt is PrintStmt) {
PrintStmt s = (PrintStmt)stmt;
foreach (Attributes.Argument arg in s.Args) {
@@ -723,19 +723,19 @@ namespace Microsoft.Dafny {
} else {
TrRhs(null, s.Lhs, s.Rhs, indent);
}
-
+
} else if (stmt is VarDecl) {
TrVarDecl((VarDecl)stmt, true, indent);
-
+
} else if (stmt is CallStmt) {
CallStmt s = (CallStmt)stmt;
TrCallStmt(s, null, indent);
-
+
} else if (stmt is BlockStmt) {
Indent(indent); wr.WriteLine("{");
TrStmtList(((BlockStmt)stmt).Body, indent);
Indent(indent); wr.WriteLine("}");
-
+
} else if (stmt is IfStmt) {
IfStmt s = (IfStmt)stmt;
Indent(indent);
@@ -746,7 +746,7 @@ namespace Microsoft.Dafny {
TrExpr(s.Guard);
wr.WriteLine(")");
}
-
+
TrStmt(s.Thn, indent);
if (s.Els != null && s.Guard != null) {
Indent(indent); wr.WriteLine("else");
@@ -816,20 +816,20 @@ namespace Microsoft.Dafny {
tmpVarCount++;
string TType = TypeName(s.BoundVar.Type);
string RhsType = TypeName(cce.NonNull(s.BodyAssign.Lhs.Type));
-
+
Indent(indent);
wr.WriteLine("List<Pair<{0},{1}>> {2} = new List<Pair<{0},{1}>>();", TType, RhsType, pu);
-
+
Indent(indent);
wr.Write("foreach ({0} @{1} in (", TType, s.BoundVar.Name);
TrExpr(s.Collection);
wr.WriteLine(").Elements) {");
-
+
Indent(indent + IndentAmount);
wr.Write("if (");
TrExpr(s.Range);
wr.WriteLine(") {");
-
+
foreach (PredicateStmt p in s.BodyPrefix) {
TrStmt(p, indent + 2*IndentAmount);
}
@@ -842,7 +842,7 @@ namespace Microsoft.Dafny {
wr.Write(DefaultValue(s.BodyAssign.Lhs.Type));
}
wr.WriteLine("))");
-
+
Indent(indent + IndentAmount); wr.WriteLine("}");
Indent(indent); wr.WriteLine("}");
@@ -851,7 +851,7 @@ namespace Microsoft.Dafny {
FieldSelectExpr fse = (FieldSelectExpr)s.BodyAssign.Lhs;
wr.WriteLine("{0}.Car.{1} = {0}.Cdr;", pr, fse.FieldName);
Indent(indent); wr.WriteLine("}");
-
+
} else if (stmt is MatchStmt) {
MatchStmt s = (MatchStmt)stmt;
// Type source = e;
@@ -1035,16 +1035,16 @@ namespace Microsoft.Dafny {
}
Contract.Assert(j == outTmps.Count);
}
-
+
int tmpVarCount = 0;
-
+
void TrAssignmentRhs(AssignmentRhs rhs) {
Contract.Requires(rhs != null);
Contract.Requires(!(rhs is HavocRhs));
if (rhs is ExprRhs) {
ExprRhs e = (ExprRhs)rhs;
TrExpr(e.Expr);
-
+
} else {
TypeRhs tp = (TypeRhs)rhs;
if (tp.ArrayDimensions == null) {
@@ -1074,7 +1074,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
void TrStmtList(List<Statement/*!*/>/*!*/ stmts, int indent) {Contract.Requires(cce.NonNullElements(stmts));
foreach (Statement ss in stmts) {
TrStmt(ss, indent + IndentAmount);
@@ -1131,7 +1131,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
// ----- Expression ---------------------------------------------------------------------------
void TrParenExpr(string prefix, Expression expr) {
@@ -1147,7 +1147,7 @@ namespace Microsoft.Dafny {
TrExpr(expr);
wr.Write(")");
}
-
+
void TrExprList(List<Expression/*!*/>/*!*/ exprs) {
Contract.Requires(cce.NonNullElements(exprs));
wr.Write("(");
@@ -1179,26 +1179,26 @@ namespace Microsoft.Dafny {
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected literal
}
-
+
} else if (expr is ThisExpr) {
wr.Write("this");
-
+
} else if (expr is IdentifierExpr) {
IdentifierExpr e = (IdentifierExpr)expr;
wr.Write("@" + e.Var.Name);
-
+
} else if (expr is SetDisplayExpr) {
SetDisplayExpr e = (SetDisplayExpr)expr;
Type elType = cce.NonNull((SetType)e.Type).Arg;
wr.Write("{0}<{1}>.FromElements", DafnySetClass, TypeName(elType));
TrExprList(e.Elements);
-
+
} else if (expr is SeqDisplayExpr) {
SeqDisplayExpr e = (SeqDisplayExpr)expr;
Type elType = cce.NonNull((SeqType)e.Type).Arg;
wr.Write("{0}<{1}>.FromElements", DafnySeqClass, TypeName(elType));
TrExprList(e.Elements);
-
+
} else if (expr is FieldSelectExpr) {
FieldSelectExpr e = (FieldSelectExpr)expr;
SpecialField sf = e.Field as SpecialField;
@@ -1211,7 +1211,7 @@ namespace Microsoft.Dafny {
TrParenExpr(e.Obj);
wr.Write(".@{0}", e.Field.Name);
}
-
+
} else if (expr is SeqSelectExpr) {
SeqSelectExpr e = (SeqSelectExpr)expr;
TrParenExpr(e.Seq);
@@ -1233,7 +1233,7 @@ namespace Microsoft.Dafny {
TrParenExpr(".Drop", e.E0);
}
}
-
+
} else if (expr is MultiSelectExpr) {
MultiSelectExpr e = (MultiSelectExpr)expr;
TrParenExpr(e.Array);
@@ -1253,7 +1253,7 @@ namespace Microsoft.Dafny {
wr.Write(", ");
TrExpr(e.Value);
wr.Write(")");
-
+
} else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
Function f = cce.NonNull(e.Function);
@@ -1273,7 +1273,7 @@ namespace Microsoft.Dafny {
}
}
wr.Write(")");
-
+
} else if (expr is DatatypeValue) {
DatatypeValue dtv = (DatatypeValue)expr;
Contract.Assert(dtv.Ctor != null); // since dtv has been successfully resolved
@@ -1292,13 +1292,13 @@ namespace Microsoft.Dafny {
}
}
wr.Write("))");
-
+
} else if (expr is OldExpr) {
Contract.Assert(false); throw new cce.UnreachableException(); // 'old' is always a ghost (right?)
-
+
} else if (expr is FreshExpr) {
Contract.Assert(false); throw new cce.UnreachableException(); // 'fresh' is always a ghost
-
+
} else if (expr is UnaryExpr) {
UnaryExpr e = (UnaryExpr)expr;
switch (e.Op) {
@@ -1323,13 +1323,13 @@ namespace Microsoft.Dafny {
default:
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected unary expression
}
-
+
} else if (expr is BinaryExpr) {
BinaryExpr e = (BinaryExpr)expr;
string opString = null;
string preOpString = "";
string callString = null;
-
+
switch (e.ResolvedOp) {
case BinaryExpr.ResolvedOpcode.Iff:
opString = "=="; break;
@@ -1339,7 +1339,7 @@ namespace Microsoft.Dafny {
opString = "||"; break;
case BinaryExpr.ResolvedOpcode.And:
opString = "&&"; break;
-
+
case BinaryExpr.ResolvedOpcode.EqCommon: {
Type t = cce.NonNull(e.E0.Type);
if (t.IsDatatype || t.IsTypeParameter) {
@@ -1359,7 +1359,7 @@ namespace Microsoft.Dafny {
}
break;
}
-
+
case BinaryExpr.ResolvedOpcode.Lt:
opString = "<"; break;
case BinaryExpr.ResolvedOpcode.Le:
@@ -1375,10 +1375,19 @@ namespace Microsoft.Dafny {
case BinaryExpr.ResolvedOpcode.Mul:
opString = "*"; break;
case BinaryExpr.ResolvedOpcode.Div:
- opString = "/"; break;
+ wr.Write("Dafny.Helpers.EuclideanDivision(");
+ TrParenExpr(e.E0);
+ wr.Write(", ");
+ TrExpr(e.E1);
+ wr.Write(")");
+ break;
case BinaryExpr.ResolvedOpcode.Mod:
- opString = "%"; break;
-
+ wr.Write("Dafny.Helpers.EuclideanModulus(");
+ TrParenExpr(e.E0);
+ wr.Write(", ");
+ TrExpr(e.E1);
+ wr.Write(")");
+ break;
case BinaryExpr.ResolvedOpcode.SetEq:
case BinaryExpr.ResolvedOpcode.SeqEq:
callString = "Equals"; break;
@@ -1451,7 +1460,7 @@ namespace Microsoft.Dafny {
TrExpr(e.E1);
wr.Write(")");
}
-
+
} else if (expr is QuantifierExpr) {
var e = (QuantifierExpr)expr;
Contract.Assert(e.Bounds != null); // for non-ghost quantifiers, the resolver would have insisted on finding bounds
diff --git a/Source/Dafny/Dafny.atg b/Source/Dafny/Dafny.atg
index f6e40722..c0aae345 100644
--- a/Source/Dafny/Dafny.atg
+++ b/Source/Dafny/Dafny.atg
@@ -3,39 +3,29 @@
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
//-----------------------------------------------------------------------------*/
-
/*---------------------------------------------------------------------------
// Dafny
// Rustan Leino, first created 25 January 2008
//--------------------------------------------------------------------------*/
-
using System.Collections.Generic;
using System.Numerics;
using Microsoft.Boogie;
using System.IO;
using System.Text;
-
-
COMPILER Dafny
-
/*--------------------------------------------------------------------------*/
-
static List<ModuleDecl/*!*/> theModules;
static BuiltIns theBuiltIns;
-
-
static Expression/*!*/ dummyExpr = new LiteralExpr(Token.NoToken);
static FrameExpression/*!*/ dummyFrameExpr = new FrameExpression(dummyExpr, null);
static Statement/*!*/ dummyStmt = new ReturnStmt(Token.NoToken, null);
static Attributes.Argument/*!*/ dummyAttrArg = new Attributes.Argument("dummyAttrArg");
static int anonymousIds = 0;
-
struct MemberModifiers {
public bool IsGhost;
public bool IsStatic;
public bool IsUnlimited;
}
-
// helper routine for parsing call statements
private static Expression/*!*/ ConvertToLocal(Expression/*!*/ e)
{
@@ -47,7 +37,6 @@ Contract.Ensures(Contract.Result<Expression>() != null);
}
return e; // cannot convert to IdentifierExpr (or is already an IdentifierExpr)
}
-
///<summary>
/// Parses top-level things (modules, classes, datatypes, class members) from "filename"
/// and appends them in appropriate form to "modules".
@@ -68,7 +57,6 @@ public static int Parse (string/*!*/ filename, List<ModuleDecl/*!*/>/*!*/ module
}
}
}
-
///<summary>
/// Parses top-level things (modules, classes, datatypes, class members)
/// and appends them in appropriate form to "modules".
@@ -82,7 +70,6 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
Errors errors = new Errors();
return Parse(s, filename, modules, builtIns, errors);
}
-
///<summary>
/// Parses top-level things (modules, classes, datatypes, class members)
/// and appends them in appropriate form to "modules".
@@ -108,7 +95,6 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
theBuiltIns = oldBuiltIns;
return parser.errors.count;
}
-
/*--------------------------------------------------------------------------*/
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
@@ -116,25 +102,20 @@ CHARACTERS
posDigit = "123456789".
special = "'_?\\".
glyph = "`~!@#$%^&*()-_=+[{]}|;:',<.>/?\\".
-
cr = '\r'.
lf = '\n'.
tab = '\t'.
-
space = ' '.
quote = '"'.
-
nondigit = letter + special.
idchar = nondigit + digit.
nonquote = letter + digit + space + glyph.
-
/* exclude the characters in 'array' */
nondigitMinusA = nondigit - 'a'.
idcharMinusA = idchar - 'a'.
idcharMinusR = idchar - 'r'.
idcharMinusY = idchar - 'y'.
idcharMinusPosDigit = idchar - posDigit.
-
/*------------------------------------------------------------------------*/
TOKENS
ident = nondigitMinusA {idchar} /* if char 0 is not an 'a', then anything else is fine */
@@ -147,23 +128,16 @@ TOKENS
digits = digit {digit}.
arrayToken = 'a' 'r' 'r' 'a' 'y' [posDigit {digit}].
string = quote {nonquote} quote.
-
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
-
IGNORE cr + lf + tab
-
-
/*------------------------------------------------------------------------*/
PRODUCTIONS
-
Dafny
= (. ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt;
Attributes attrs; IToken/*!*/ id; List<string/*!*/> theImports;
-
List<MemberDecl/*!*/> membersDefaultClass = new List<MemberDecl/*!*/>();
ModuleDecl module;
-
// to support multiple files, create a default module only if theModules doesn't already contain one
DefaultModuleDecl defaultModule = null;
foreach (ModuleDecl mdecl in theModules) {
@@ -188,7 +162,7 @@ Dafny
theModules.Add(module); .)
| ClassDecl<defaultModule, out c> (. defaultModule.TopLevelDecls.Add(c); .)
| DatatypeDecl<defaultModule, out dt> (. defaultModule.TopLevelDecls.Add(dt); .)
- | ClassMemberDecl<membersDefaultClass>
+ | ClassMemberDecl<membersDefaultClass, false>
}
(. if (defaultModuleCreatedHere) {
defaultModule.TopLevelDecls.Add(new DefaultClassDecl(defaultModule, membersDefaultClass));
@@ -206,7 +180,6 @@ Dafny
.)
EOF
.
-
ClassDecl<ModuleDecl/*!*/ module, out ClassDecl/*!*/ c>
= (. Contract.Requires(module != null);
Contract.Ensures(Contract.ValueAtReturn(out c) != null);
@@ -225,19 +198,18 @@ ClassDecl<ModuleDecl/*!*/ module, out ClassDecl/*!*/ c>
[ "refines" Ident<out idRefined> (. optionalId = idRefined; .)
]
"{" (. bodyStart = t; .)
- { ClassMemberDecl<members>
+ { ClassMemberDecl<members, true>
}
- "}"
- (. if (optionalId == null)
+ "}"
+ (. if (optionalId == null)
c = new ClassDecl(id, id.val, module, typeArgs, members, attrs);
- else
+ else
c = new ClassRefinementDecl(id, id.val, module, typeArgs, members, attrs, optionalId);
c.BodyStartTok = bodyStart;
c.BodyEndTok = t;
.)
.
-
-ClassMemberDecl<.List<MemberDecl/*!*/>/*!*/ mm.>
+ClassMemberDecl<.List<MemberDecl/*!*/>/*!*/ mm, bool allowConstructors.>
= (. Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
Function/*!*/ f;
@@ -247,13 +219,12 @@ ClassMemberDecl<.List<MemberDecl/*!*/>/*!*/ mm.>
| "static" (. mmod.IsStatic = true; .)
| "unlimited" (. mmod.IsUnlimited = true; .)
}
- ( FieldDecl<mmod, mm>
- | FunctionDecl<mmod, out f> (. mm.Add(f); .)
- | MethodDecl<mmod, out m> (. mm.Add(m); .)
- | CouplingInvDecl<mmod, mm>
+ ( FieldDecl<mmod, mm>
+ | FunctionDecl<mmod, out f> (. mm.Add(f); .)
+ | MethodDecl<mmod, allowConstructors, out m> (. mm.Add(m); .)
+ | CouplingInvDecl<mmod, mm>
)
.
-
DatatypeDecl<ModuleDecl/*!*/ module, out DatatypeDecl/*!*/ dt>
= (. Contract.Requires(module != null);
Contract.Ensures(Contract.ValueAtReturn(out dt)!=null);
@@ -276,7 +247,6 @@ DatatypeDecl<ModuleDecl/*!*/ module, out DatatypeDecl/*!*/ dt>
dt.BodyEndTok = t;
.)
.
-
DatatypeMemberDecl<.List<DatatypeCtor/*!*/>/*!*/ ctors.>
= (. Contract.Requires(cce.NonNullElements(ctors));
Attributes attrs = null;
@@ -288,7 +258,6 @@ DatatypeMemberDecl<.List<DatatypeCtor/*!*/>/*!*/ ctors.>
[ FormalsOptionalIds<formals> ]
(. ctors.Add(new DatatypeCtor(id, id.val, formals, attrs)); .)
.
-
FieldDecl<.MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm.>
= (. Contract.Requires(cce.NonNullElements(mm));
Attributes attrs = null;
@@ -304,7 +273,6 @@ FieldDecl<.MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm.>
}
";"
.
-
CouplingInvDecl<.MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm.>
= (. Contract.Requires(cce.NonNullElements(mm));
Attributes attrs = null;
@@ -317,17 +285,15 @@ CouplingInvDecl<.MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm.>
if (mmod.IsStatic) { SemErr(t, "coupling invariants cannot be declared 'static'"); }
if (mmod.IsGhost) { SemErr(t, "coupling invariants cannot be declared 'ghost'"); }
.)
- { Attribute<ref attrs> }
+ { Attribute<ref attrs> }
Ident<out id> (. ids.Add(id); .)
{ "," Ident<out id> (. ids.Add(id); .)
}
- "by"
+ "by"
Expression<out e>
";"
- (. mm.Add(new CouplingInvariant(ids, e, attrs)); .)
+ (. mm.Add(new CouplingInvariant(ids, e, attrs)); .)
.
-
-
GIdentType<bool allowGhostKeyword, out IToken/*!*/ id, out Type/*!*/ ty, out bool isGhost>
/* isGhost always returns as false if allowGhostKeyword is false */
= (. Contract.Ensures(Contract.ValueAtReturn(out id)!=null);
@@ -337,14 +303,12 @@ GIdentType<bool allowGhostKeyword, out IToken/*!*/ id, out Type/*!*/ ty, out boo
]
IdentType<out id, out ty>
.
-
IdentType<out IToken/*!*/ id, out Type/*!*/ ty>
= (.Contract.Ensures(Contract.ValueAtReturn(out id) != null); Contract.Ensures(Contract.ValueAtReturn(out ty) != null);.)
Ident<out id>
":"
Type<out ty>
.
-
LocalIdentTypeOptional<out VarDecl/*!*/ var, bool isGhost>
= (. IToken/*!*/ id; Type/*!*/ ty; Type optType = null;
.)
@@ -353,7 +317,6 @@ LocalIdentTypeOptional<out VarDecl/*!*/ var, bool isGhost>
]
(. var = new VarDecl(id, id.val, optType == null ? new InferredTypeProxy() : optType, isGhost); .)
.
-
IdentTypeOptional<out BoundVar/*!*/ var>
= (. Contract.Ensures(Contract.ValueAtReturn(out var)!=null); IToken/*!*/ id; Type/*!*/ ty; Type optType = null;
.)
@@ -362,7 +325,6 @@ IdentTypeOptional<out BoundVar/*!*/ var>
]
(. var = new BoundVar(id, id.val, optType == null ? new InferredTypeProxy() : optType); .)
.
-
TypeIdentOptional<out IToken/*!*/ id, out string/*!*/ identName, out Type/*!*/ ty, out bool isGhost>
= (.Contract.Ensures(Contract.ValueAtReturn(out id)!=null);
Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
@@ -389,9 +351,7 @@ TypeIdentOptional<out IToken/*!*/ id, out string/*!*/ identName, out Type/*!*/ t
}
.)
.
-
/*------------------------------------------------------------------------*/
-
GenericParameters<.List<TypeParameter/*!*/>/*!*/ typeArgs.>
= (. Contract.Requires(cce.NonNullElements(typeArgs));
IToken/*!*/ id; .)
@@ -401,10 +361,8 @@ GenericParameters<.List<TypeParameter/*!*/>/*!*/ typeArgs.>
}
">"
.
-
/*------------------------------------------------------------------------*/
-
-MethodDecl<MemberModifiers mmod, out Method/*!*/ m>
+MethodDecl<MemberModifiers mmod, bool allowConstructor, out Method/*!*/ m>
= (. Contract.Ensures(Contract.ValueAtReturn(out m) !=null);
IToken/*!*/ id;
Attributes attrs = null;
@@ -422,8 +380,13 @@ MethodDecl<MemberModifiers mmod, out Method/*!*/ m>
IToken bodyEnd = Token.NoToken;
.)
( "method"
- | "constructor" (. isConstructor = true; .)
- | "refines" (. isRefinement = true; .)
+ | "constructor" (. if (allowConstructor) {
+ isConstructor = true;
+ } else {
+ SemErr(t, "constructors are only allowed in classes");
+ }
+ .)
+ | "refines" (. isRefinement = true; .)
)
(. if (mmod.IsUnlimited) { SemErr(t, "methods cannot be declared 'unlimited'"); }
if (isConstructor) {
@@ -442,11 +405,9 @@ MethodDecl<MemberModifiers mmod, out Method/*!*/ m>
[ "returns" (. if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); } .)
Formals<false, !mmod.IsGhost, outs>
]
-
- ( ";" { MethodSpec<req, mod, ens, dec> }
- | { MethodSpec<req, mod, ens, dec> } BlockStmt<out bb, out bodyStart, out bodyEnd> (. body = (BlockStmt)bb; .)
- )
-
+ { MethodSpec<req, mod, ens, dec> }
+ [ BlockStmt<out bb, out bodyStart, out bodyEnd> (. body = (BlockStmt)bb; .)
+ ]
(. if (isRefinement)
m = new MethodRefinement(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs, req, mod, ens, dec, body, attrs);
else if (isConstructor)
@@ -457,7 +418,6 @@ MethodDecl<MemberModifiers mmod, out Method/*!*/ m>
m.BodyEndTok = bodyEnd;
.)
.
-
MethodSpec<.List<MaybeFreeExpression/*!*/>/*!*/ req, List<FrameExpression/*!*/>/*!*/ mod, List<MaybeFreeExpression/*!*/>/*!*/ ens,
List<Expression/*!*/>/*!*/ decreases.>
= (. Contract.Requires(cce.NonNullElements(req)); Contract.Requires(cce.NonNullElements(mod)); Contract.Requires(cce.NonNullElements(ens)); Contract.Requires(cce.NonNullElements(decreases));
@@ -475,8 +435,7 @@ MethodSpec<.List<MaybeFreeExpression/*!*/>/*!*/ req, List<FrameExpression/*!*/>/
| "decreases" DecreasesList<decreases, false> ";"
)
.
-
-Formals<.bool incoming, bool allowGhostKeyword, List<Formal/*!*/>/*!*/ formals.>
+Formals<.bool incoming, bool allowGhostKeyword, List<Formal/*!*/>/*!*/ formals.>
= (. Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; bool isGhost; .)
"("
[
@@ -486,8 +445,7 @@ Formals<.bool incoming, bool allowGhostKeyword, List<Formal/*!*/>/*!*/ formals.>
]
")"
.
-
-FormalsOptionalIds<.List<Formal/*!*/>/*!*/ formals.>
+FormalsOptionalIds<.List<Formal/*!*/>/*!*/ formals.>
= (. Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost; .)
"("
[
@@ -497,14 +455,11 @@ FormalsOptionalIds<.List<Formal/*!*/>/*!*/ formals.>
]
")"
.
-
/*------------------------------------------------------------------------*/
-
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>
= (. 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;
@@ -518,7 +473,6 @@ TypeAndToken<out IToken/*!*/ tok, out Type/*!*/ ty>
}
ty = new SetType(gt[0]);
.)
-
| "seq" (. tok = t; gt = new List<Type/*!*/>(); .)
GenericInstantiation<gt> (. if (gt.Count != 1) {
SemErr("seq type expects exactly one type argument");
@@ -528,7 +482,6 @@ TypeAndToken<out IToken/*!*/ tok, out Type/*!*/ ty>
| ReferenceType<out tok, out ty>
)
.
-
ReferenceType<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*/
@@ -549,7 +502,6 @@ ReferenceType<out IToken/*!*/ tok, out Type/*!*/ ty>
[ GenericInstantiation<gt> ] (. ty = new UserDefinedType(tok, tok.val, gt); .)
)
.
-
GenericInstantiation<.List<Type/*!*/>/*!*/ gt.>
= (. Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty; .)
"<"
@@ -558,9 +510,7 @@ GenericInstantiation<.List<Type/*!*/>/*!*/ gt.>
}
">"
.
-
/*------------------------------------------------------------------------*/
-
FunctionDecl<MemberModifiers mmod, out Function/*!*/ f>
= (. Contract.Ensures(Contract.ValueAtReturn(out f)!=null);
Attributes attrs = null;
@@ -583,22 +533,19 @@ FunctionDecl<MemberModifiers mmod, out Function/*!*/ f>
(. if (mmod.IsGhost) { SemErr(t, "functions cannot be declared 'ghost' (they are ghost by default)"); }
.)
{ Attribute<ref attrs> }
- Ident<out id>
+ Ident<out id>
[ GenericParameters<typeArgs> ]
Formals<true, isFunctionMethod, formals>
":"
Type<out returnType>
- ( ";"
- { FunctionSpec<reqs, reads, ens, decreases> }
- | { FunctionSpec<reqs, reads, ens, decreases> }
- FunctionBody<out bb, out bodyStart, out bodyEnd> (. body = bb; .)
- )
+ { FunctionSpec<reqs, reads, ens, decreases> }
+ [ FunctionBody<out bb, out bodyStart, out bodyEnd> (. body = bb; .)
+ ]
(. f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, formals, returnType, reqs, reads, ens, decreases, body, attrs);
f.BodyStartTok = bodyStart;
f.BodyEndTok = bodyEnd;
.)
.
-
FunctionSpec<.List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ reads, List<Expression/*!*/>/*!*/ ens, List<Expression/*!*/>/*!*/ decreases.>
= (. Contract.Requires(cce.NonNullElements(reqs)); Contract.Requires(cce.NonNullElements(reads)); Contract.Requires(cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe; .)
@@ -611,7 +558,6 @@ FunctionSpec<.List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ r
| "decreases" DecreasesList<decreases, false> ";"
)
.
-
PossiblyWildExpression<out Expression/*!*/ e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e)!=null);
e = dummyExpr; .)
@@ -622,7 +568,6 @@ PossiblyWildExpression<out Expression/*!*/ e>
| Expression<out e>
)
.
-
PossiblyWildFrameExpression<out FrameExpression/*!*/ fe>
= (. Contract.Ensures(Contract.ValueAtReturn(out fe) != null); fe = dummyFrameExpr; .)
/* A reads clause can list a wildcard, which allows the enclosing function to
@@ -635,7 +580,6 @@ PossiblyWildFrameExpression<out FrameExpression/*!*/ fe>
| FrameExpression<out fe>
)
.
-
FrameExpression<out FrameExpression/*!*/ fe>
= (. Contract.Ensures(Contract.ValueAtReturn(out fe) != null); Expression/*!*/ e; IToken/*!*/ id; string fieldName = null; .)
Expression<out e>
@@ -643,16 +587,13 @@ FrameExpression<out FrameExpression/*!*/ fe>
]
(. fe = new FrameExpression(e, fieldName); .)
.
-
FunctionBody<out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); e = dummyExpr; .)
"{" (. bodyStart = t; .)
Expression<out e>
"}" (. bodyEnd = t; .)
.
-
/*------------------------------------------------------------------------*/
-
BlockStmt<out Statement/*!*/ block, out IToken bodyStart, out IToken bodyEnd>
= (. Contract.Ensures(Contract.ValueAtReturn(out block) != null);
List<Statement/*!*/> body = new List<Statement/*!*/>();
@@ -663,13 +604,11 @@ BlockStmt<out Statement/*!*/ block, out IToken bodyStart, out IToken bodyEnd>
"}" (. bodyEnd = t;
block = new BlockStmt(bodyStart, body); .)
.
-
Stmt<.List<Statement/*!*/>/*!*/ ss.>
= (. Statement/*!*/ s;
.)
OneStmt<out s> (. ss.Add(s); .)
.
-
OneStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; IToken/*!*/ id; string label = null;
s = dummyStmt; /* to please the compiler */
@@ -699,7 +638,6 @@ OneStmt<out Statement/*!*/ s>
| ReturnStmt<out s>
)
.
-
ReturnStmt<out Statement/*!*/ s>
= (.
IToken returnTok = null;
@@ -735,7 +673,6 @@ UpdateStmt<out Statement/*!*/ s>
)
(. s = new UpdateStmt(x, lhss, rhss); .)
.
-
Rhs<out AssignmentRhs r, Expression receiverForInitCall>
= (. IToken/*!*/ x, newToken; Expression/*!*/ e;
List<Expression> ee = null;
@@ -763,17 +700,13 @@ Rhs<out AssignmentRhs r, Expression receiverForInitCall>
r = new TypeRhs(newToken, ty, initCall);
}
.)
-
/* One day, the choose expression should be treated just as a special case of a method call. */
| "choose" (. x = t; .)
Expression<out e> (. r = new ExprRhs(new UnaryExpr(x, UnaryExpr.Opcode.SetChoose, e)); .)
-
| "*" (. r = new HavocRhs(t); .)
-
| Expression<out e> (. r = new ExprRhs(e); .)
)
.
-
VarDeclStatement<.out Statement/*!*/ s.>
= (. IToken x = null, assignTok = null; bool isGhost = false;
VarDecl/*!*/ d;
@@ -807,7 +740,6 @@ VarDeclStatement<.out Statement/*!*/ s.>
s = new VarDeclStmt(x, lhss, update);
.)
.
-
IfStmt<out Statement/*!*/ ifStmt>
= (. Contract.Ensures(Contract.ValueAtReturn(out ifStmt) != null); IToken/*!*/ x;
Expression guard;
@@ -833,7 +765,6 @@ IfStmt<out Statement/*!*/ ifStmt>
(. ifStmt = new AlternativeStmt(x, alternatives); .)
)
.
-
AlternativeBlock<.out List<GuardedAlternative> alternatives.>
= (. alternatives = new List<GuardedAlternative>();
IToken x;
@@ -850,7 +781,6 @@ AlternativeBlock<.out List<GuardedAlternative> alternatives.>
}
"}"
.
-
WhileStmt<out Statement/*!*/ stmt>
= (. Contract.Ensures(Contract.ValueAtReturn(out stmt) != null); IToken/*!*/ x;
Expression guard;
@@ -874,7 +804,6 @@ WhileStmt<out Statement/*!*/ stmt>
(. stmt = new AlternativeLoopStmt(x, invariants, decreases, mod, alternatives); .)
)
.
-
LoopSpec<.out List<MaybeFreeExpression/*!*/> invariants, out List<Expression/*!*/> decreases, out List<FrameExpression/*!*/> mod.>
= (. bool isFree; Expression/*!*/ e; FrameExpression/*!*/ fe;
invariants = new List<MaybeFreeExpression/*!*/>();
@@ -895,7 +824,6 @@ LoopSpec<.out List<MaybeFreeExpression/*!*/> invariants, out List<Expression/*!*
] ";"
}
.
-
DecreasesList<.List<Expression/*!*/> decreases, bool allowWildcard.>
= (. Expression/*!*/ e; .)
PossiblyWildExpression<out e> (. if (!allowWildcard && e is WildcardExpr) {
@@ -912,7 +840,6 @@ DecreasesList<.List<Expression/*!*/> decreases, bool allowWildcard.>
.)
}
.
-
Guard<out Expression e> /* null represents demonic-choice */
= (. Expression/*!*/ ee; e = null; .)
"("
@@ -921,7 +848,6 @@ Guard<out Expression e> /* null represents demonic-choice */
)
")"
.
-
MatchStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null);
Token x; Expression/*!*/ e; MatchCaseStmt/*!*/ c;
@@ -934,7 +860,6 @@ MatchStmt<out Statement/*!*/ s>
"}"
(. s = new MatchStmt(x, e, cases); .)
.
-
CaseStatement<out MatchCaseStmt/*!*/ c>
= (. Contract.Ensures(Contract.ValueAtReturn(out c) != null);
IToken/*!*/ x, id, arg;
@@ -952,9 +877,7 @@ CaseStatement<out MatchCaseStmt/*!*/ c>
{ Stmt<body> }
(. c = new MatchCaseStmt(x, id.val, arguments, body); .)
.
-
/*------------------------------------------------------------------------*/
-
ForeachStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null);
IToken/*!*/ x, boundVar;
@@ -985,19 +908,16 @@ ForeachStmt<out Statement/*!*/ s>
}
.)
.
-
AssertStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Expression/*!*/ e; .)
"assert" (. x = t; .)
Expression<out e> ";" (. s = new AssertStmt(x, e); .)
.
-
AssumeStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Expression/*!*/ e; .)
"assume" (. x = t; .)
Expression<out e> ";" (. s = new AssumeStmt(x, e); .)
.
-
PrintStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Attributes.Argument/*!*/ arg;
List<Attributes.Argument/*!*/> args = new List<Attributes.Argument/*!*/>();
@@ -1008,13 +928,11 @@ PrintStmt<out Statement/*!*/ s>
}
";" (. s = new PrintStmt(x, args); .)
.
-
/*------------------------------------------------------------------------*/
Expression<out Expression/*!*/ e>
=
EquivExpression<out e>
.
-
/*------------------------------------------------------------------------*/
EquivExpression<out Expression/*!*/ e0>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; .)
@@ -1023,9 +941,7 @@ EquivExpression<out Expression/*!*/ e0>
ImpliesExpression<out e1> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Iff, e0, e1); .)
}
.
-
EquivOp = "<==>" | '\u21d4'.
-
/*------------------------------------------------------------------------*/
ImpliesExpression<out Expression/*!*/ e0>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; .)
@@ -1034,9 +950,7 @@ ImpliesExpression<out Expression/*!*/ e0>
ImpliesExpression<out e1> (. e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); .)
]
.
-
ImpliesOp = "==>" | '\u21d2'.
-
/*------------------------------------------------------------------------*/
LogicalExpression<out Expression/*!*/ e0>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; .)
@@ -1053,10 +967,8 @@ LogicalExpression<out Expression/*!*/ e0>
}
]
.
-
AndOp = "&&" | '\u2227'.
OrOp = "||" | '\u2228'.
-
/*------------------------------------------------------------------------*/
RelationalExpression<out Expression/*!*/ e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
@@ -1140,7 +1052,6 @@ RelationalExpression<out Expression/*!*/ e>
}
.)
.
-
RelOp<out IToken/*!*/ x, out BinaryExpr.Opcode op>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/; .)
( "==" (. x = t; op = BinaryExpr.Opcode.Eq; .)
@@ -1157,7 +1068,6 @@ RelOp<out IToken/*!*/ x, out BinaryExpr.Opcode op>
| '\u2265' (. x = t; op = BinaryExpr.Opcode.Ge; .)
)
.
-
/*------------------------------------------------------------------------*/
Term<out Expression/*!*/ e0>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op; .)
@@ -1166,14 +1076,12 @@ Term<out Expression/*!*/ e0>
Factor<out e1> (. e0 = new BinaryExpr(x, op, e0, e1); .)
}
.
-
AddOp<out IToken/*!*/ x, out BinaryExpr.Opcode op>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryExpr.Opcode.Add/*(dummy)*/; .)
( "+" (. x = t; op = BinaryExpr.Opcode.Add; .)
| "-" (. x = t; op = BinaryExpr.Opcode.Sub; .)
)
.
-
/*------------------------------------------------------------------------*/
Factor<out Expression/*!*/ e0>
= (. Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op; .)
@@ -1182,7 +1090,6 @@ Factor<out Expression/*!*/ e0>
UnaryExpression<out e1> (. e0 = new BinaryExpr(x, op, e0, e1); .)
}
.
-
MulOp<out IToken/*!*/ x, out BinaryExpr.Opcode op>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/; .)
( "*" (. x = t; op = BinaryExpr.Opcode.Mul; .)
@@ -1190,7 +1097,6 @@ MulOp<out IToken/*!*/ x, out BinaryExpr.Opcode op>
| "%" (. x = t; op = BinaryExpr.Opcode.Mod; .)
)
.
-
/*------------------------------------------------------------------------*/
UnaryExpression<out Expression/*!*/ e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; e = dummyExpr; .)
@@ -1206,7 +1112,6 @@ UnaryExpression<out Expression/*!*/ e>
{ Suffix<ref e> }
)
.
-
Lhs<out Expression e>
= (. e = null; // to please the compiler
.)
@@ -1217,9 +1122,7 @@ Lhs<out Expression e>
{ Suffix<ref e> }
)
.
-
NegOp = "!" | '\u00ac'.
-
/* A ConstAtomExpression is never an l-value. Also, a ConstAtomExpression is never followed by
* 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.)
@@ -1248,7 +1151,6 @@ ConstAtomExpression<out Expression/*!*/ e>
")"
)
.
-
DisplayExpr<out Expression e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null);
IToken/*!*/ x; List<Expression/*!*/>/*!*/ elements;
@@ -1262,7 +1164,6 @@ DisplayExpr<out Expression e>
"]"
)
.
-
EndlessExpression<out Expression e>
= (. IToken/*!*/ x;
Expression e0, e1;
@@ -1277,7 +1178,6 @@ EndlessExpression<out Expression e>
| ComprehensionExpr<out e>
)
.
-
MatchExpression<out Expression/*!*/ e>
= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; MatchCaseExpr/*!*/ c;
List<MatchCaseExpr/*!*/> cases = new List<MatchCaseExpr/*!*/>();
@@ -1291,7 +1191,6 @@ MatchExpression<out Expression/*!*/ e>
}
(. e = new MatchExpr(x, e, cases); .)
.
-
CaseExpression<out MatchCaseExpr/*!*/ c>
= (. Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken/*!*/ x, id, arg;
List<BoundVar/*!*/> arguments = new List<BoundVar/*!*/>();
@@ -1307,9 +1206,7 @@ CaseExpression<out MatchCaseExpr/*!*/ c>
"=>"
Expression<out body> (. c = new MatchCaseExpr(x, id.val, arguments, body); .)
.
-
/*------------------------------------------------------------------------*/
-
DottedIdentifiersAndFunction<out Expression e>
= (. IToken id; IToken openParen = null;
List<Expression> args = null;
@@ -1325,7 +1222,6 @@ DottedIdentifiersAndFunction<out Expression e>
]
(. e = new IdentifierSequence(idents, openParen, args); .)
.
-
Suffix<ref Expression/*!*/ e>
= (. Contract.Requires(e != null); Contract.Ensures(e!=null); IToken/*!*/ id, x; List<Expression/*!*/>/*!*/ args;
Expression e0 = null; Expression e1 = null; Expression/*!*/ ee; bool anyDots = false;
@@ -1338,7 +1234,6 @@ Suffix<ref Expression/*!*/ e>
[ Expressions<args> ]
")" (. e = new FunctionCallExpr(id, id.val, e, args); .)
] (. if (!func) { e = new FieldSelectExpr(id, e, id.val); } .)
-
| "[" (. x = t; .)
( Expression<out ee> (. e0 = ee; .)
( ".." (. anyDots = true; .)
@@ -1381,9 +1276,7 @@ Suffix<ref Expression/*!*/ e>
"]"
)
.
-
/*------------------------------------------------------------------------*/
-
QuantifierGuts<out Expression/*!*/ q>
= (. Contract.Ensures(Contract.ValueAtReturn(out q) != null); IToken/*!*/ x = Token.NoToken;
bool univ = false;
@@ -1414,11 +1307,9 @@ QuantifierGuts<out Expression/*!*/ q>
}
.)
.
-
Forall = "forall" | '\u2200'.
Exists = "exists" | '\u2203'.
QSep = "::" | '\u2022'.
-
ComprehensionExpr<out Expression/*!*/ q>
= (. Contract.Ensures(Contract.ValueAtReturn(out q) != null);
IToken/*!*/ x = Token.NoToken;
@@ -1441,22 +1332,18 @@ ComprehensionExpr<out Expression/*!*/ q>
q = new SetComprehension(x, bvars, range, body);
.)
.
-
Expressions<.List<Expression/*!*/>/*!*/ args.>
= (. Contract.Requires(cce.NonNullElements(args)); Expression/*!*/ e; .)
Expression<out e> (. args.Add(e); .)
{ "," Expression<out e> (. args.Add(e); .)
}
.
-
/*------------------------------------------------------------------------*/
-
Attribute<ref Attributes attrs>
= "{"
AttributeBody<ref attrs>
"}"
.
-
AttributeBody<ref Attributes attrs>
= (. string aName;
List<Attributes.Argument/*!*/> aArgs = new List<Attributes.Argument/*!*/>();
@@ -1468,14 +1355,12 @@ AttributeBody<ref Attributes attrs>
}
] (. attrs = new Attributes(aName, aArgs, attrs); .)
.
-
AttributeArg<out Attributes.Argument/*!*/ arg>
= (. Contract.Ensures(Contract.ValueAtReturn(out arg) != null); Expression/*!*/ e; arg = dummyAttrArg; .)
( string (. arg = new Attributes.Argument(t.val.Substring(1, t.val.Length-2)); .)
| Expression<out e> (. arg = new Attributes.Argument(e); .)
)
.
-
AttributeOrTrigger<ref Attributes attrs, ref Triggers trigs>
= (. List<Expression/*!*/> es = new List<Expression/*!*/>();
.)
@@ -1486,21 +1371,17 @@ AttributeOrTrigger<ref Attributes attrs, ref Triggers trigs>
)
"}"
.
-
/*------------------------------------------------------------------------*/
-
Idents<.List<string/*!*/>/*!*/ ids.>
= (. IToken/*!*/ id; .)
Ident<out id> (. ids.Add(id.val); .)
{ "," Ident<out id> (. ids.Add(id.val); .)
}
.
-
Ident<out IToken/*!*/ x>
= (. Contract.Ensures(Contract.ValueAtReturn(out x) != null); .)
ident (. x = t; .)
.
-
Nat<out BigInteger n>
=
digits
@@ -1510,7 +1391,6 @@ Nat<out BigInteger n>
SemErr("incorrectly formatted number");
n = BigInteger.Zero;
}
- .)
+ .)
.
-
-END Dafny. \ No newline at end of file
+END Dafny.
diff --git a/Source/Dafny/DafnyAst.cs b/Source/Dafny/DafnyAst.cs
index 4868be10..8bb381ea 100644
--- a/Source/Dafny/DafnyAst.cs
+++ b/Source/Dafny/DafnyAst.cs
@@ -400,13 +400,13 @@ namespace Microsoft.Dafny {
/// <summary>
/// This proxy stands for any type.
- /// </summary>
+ /// </summary>
public class InferredTypeProxy : UnrestrictedTypeProxy {
}
/// <summary>
/// This proxy stands for any type, but it originates from an instantiated type parameter.
- /// </summary>
+ /// </summary>
public class ParamTypeProxy : UnrestrictedTypeProxy {
TypeParameter orig;
[ContractInvariantMethod]
@@ -432,7 +432,7 @@ namespace Microsoft.Dafny {
/// <summary>
/// This proxy stands for any datatype.
- /// </summary>
+ /// </summary>
public class DatatypeProxy : RestrictedTypeProxy {
public override int OrderID {
get {
@@ -443,7 +443,7 @@ namespace Microsoft.Dafny {
/// <summary>
/// This proxy stands for object or any class/array type.
- /// </summary>
+ /// </summary>
public class ObjectTypeProxy : RestrictedTypeProxy {
public override int OrderID {
get {
@@ -491,7 +491,7 @@ namespace Microsoft.Dafny {
/// if AllowSeq, or:
/// int or set
/// if !AllowSeq.
- /// </summary>
+ /// </summary>
public class OperationTypeProxy : RestrictedTypeProxy {
public readonly bool AllowSeq;
public OperationTypeProxy(bool allowSeq) {
@@ -675,7 +675,7 @@ namespace Microsoft.Dafny {
public class ClassRefinementDecl : ClassDecl {
public readonly IToken/*!*/ RefinedClass;
- public ClassDecl Refined; // filled in during resolution
+ public ClassDecl Refined; // filled in during resolution
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(RefinedClass != null);
@@ -720,7 +720,7 @@ namespace Microsoft.Dafny {
Dims = dims;
}
}
-
+
public class DatatypeDecl : TopLevelDecl {
public readonly List<DatatypeCtor/*!*/>/*!*/ Ctors;
[ContractInvariantMethod]
@@ -1685,7 +1685,7 @@ namespace Microsoft.Dafny {
Contract.Invariant(Mod == null || cce.NonNullElements(Mod));
}
public LoopStmt(IToken tok, List<MaybeFreeExpression/*!*/>/*!*/ invariants, List<Expression/*!*/>/*!*/ decreases, List<FrameExpression/*!*/>/*!*/ mod)
- : base(tok)
+ : base(tok)
{
Contract.Requires(tok != null);
Contract.Requires(cce.NonNullElements(invariants));
@@ -2511,7 +2511,7 @@ namespace Microsoft.Dafny {
public List<BoundedPool> Bounds; // initialized and filled in by resolver
// invariant Bounds == null || Bounds.Count == BoundVars.Count;
- public List<BoundVar> MissingBounds; // filled in during resolution; remains "null" if bounds can be found
+ public List<BoundVar> MissingBounds; // filled in during resolution; remains "null" if bounds can be found
// invariant Bounds == null || MissingBounds == null;
public ComprehensionExpr(IToken/*!*/ tok, List<BoundVar/*!*/>/*!*/ bvars, Expression range, Expression/*!*/ term, Attributes attrs)
@@ -2529,7 +2529,7 @@ namespace Microsoft.Dafny {
public override IEnumerable<Expression> SubExpressions {
get {
if (Range != null) { yield return Range; }
- yield return Term;
+ yield return Term;
}
}
}
diff --git a/Source/Dafny/DafnyMain.cs b/Source/Dafny/DafnyMain.cs
index a18ea938..3f0b6e97 100644
--- a/Source/Dafny/DafnyMain.cs
+++ b/Source/Dafny/DafnyMain.cs
@@ -27,21 +27,21 @@ namespace Microsoft.Dafny {
if (Bpl.CommandLineOptions.Clo.XmlSink != null && Bpl.CommandLineOptions.Clo.XmlSink.IsOpen) {
Bpl.CommandLineOptions.Clo.XmlSink.WriteFileFragment(dafnyFileName);
}
- if (Bpl.CommandLineOptions.Clo.Trace)
+ if (Bpl.CommandLineOptions.Clo.Trace)
{
Console.WriteLine("Parsing " + dafnyFileName);
}
int errorCount;
- try
+ try
{
errorCount = Dafny.Parser.Parse(dafnyFileName, modules, builtIns);
- if (errorCount != 0)
+ if (errorCount != 0)
{
return string.Format("{0} parse errors detected in {1}", errorCount, dafnyFileName);
}
- }
- catch (IOException e)
+ }
+ catch (IOException e)
{
return string.Format("Error opening file \"{0}\": {1}", dafnyFileName, e.Message);
}
@@ -61,7 +61,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
if (Bpl.CommandLineOptions.Clo.NoResolve || Bpl.CommandLineOptions.Clo.NoTypecheck) { return null; }
Dafny.Resolver r = new Dafny.Resolver(program);
@@ -73,4 +73,4 @@ namespace Microsoft.Dafny {
return null; // success
}
}
-} \ No newline at end of file
+}
diff --git a/Source/Dafny/DafnyPipeline.csproj b/Source/Dafny/DafnyPipeline.csproj
index 7f063c2c..6a15b1f7 100644
--- a/Source/Dafny/DafnyPipeline.csproj
+++ b/Source/Dafny/DafnyPipeline.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -147,11 +147,11 @@
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
-</Project> \ No newline at end of file
+</Project>
diff --git a/Source/Dafny/Parser.cs b/Source/Dafny/Parser.cs
index e12ab7e3..8fcb6bb0 100644
--- a/Source/Dafny/Parser.cs
+++ b/Source/Dafny/Parser.cs
@@ -5,8 +5,6 @@ using System.IO;
using System.Text;
-
-
using System;
using System.Diagnostics.Contracts;
@@ -35,20 +33,16 @@ public class Parser {
static List<ModuleDecl/*!*/> theModules;
static BuiltIns theBuiltIns;
-
-
static Expression/*!*/ dummyExpr = new LiteralExpr(Token.NoToken);
static FrameExpression/*!*/ dummyFrameExpr = new FrameExpression(dummyExpr, null);
static Statement/*!*/ dummyStmt = new ReturnStmt(Token.NoToken, null);
static Attributes.Argument/*!*/ dummyAttrArg = new Attributes.Argument("dummyAttrArg");
static int anonymousIds = 0;
-
struct MemberModifiers {
public bool IsGhost;
public bool IsStatic;
public bool IsUnlimited;
}
-
// helper routine for parsing call statements
private static Expression/*!*/ ConvertToLocal(Expression/*!*/ e)
{
@@ -60,7 +54,6 @@ Contract.Ensures(Contract.Result<Expression>() != null);
}
return e; // cannot convert to IdentifierExpr (or is already an IdentifierExpr)
}
-
///<summary>
/// Parses top-level things (modules, classes, datatypes, class members) from "filename"
/// and appends them in appropriate form to "modules".
@@ -81,7 +74,6 @@ public static int Parse (string/*!*/ filename, List<ModuleDecl/*!*/>/*!*/ module
}
}
}
-
///<summary>
/// Parses top-level things (modules, classes, datatypes, class members)
/// and appends them in appropriate form to "modules".
@@ -95,7 +87,6 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
Errors errors = new Errors();
return Parse(s, filename, modules, builtIns, errors);
}
-
///<summary>
/// Parses top-level things (modules, classes, datatypes, class members)
/// and appends them in appropriate form to "modules".
@@ -121,7 +112,6 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
theBuiltIns = oldBuiltIns;
return parser.errors.count;
}
-
/*--------------------------------------------------------------------------*/
@@ -196,22 +186,20 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
void Dafny() {
ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt;
Attributes attrs; IToken/*!*/ id; List<string/*!*/> theImports;
+ List<MemberDecl/*!*/> membersDefaultClass = new List<MemberDecl/*!*/>();
+ ModuleDecl module;
+ // to support multiple files, create a default module only if theModules doesn't already contain one
+ DefaultModuleDecl defaultModule = null;
+ foreach (ModuleDecl mdecl in theModules) {
+ defaultModule = mdecl as DefaultModuleDecl;
+ if (defaultModule != null) { break; }
+ }
+ bool defaultModuleCreatedHere = false;
+ if (defaultModule == null) {
+ defaultModuleCreatedHere = true;
+ defaultModule = new DefaultModuleDecl();
+ }
- List<MemberDecl/*!*/> membersDefaultClass = new List<MemberDecl/*!*/>();
- ModuleDecl module;
-
- // to support multiple files, create a default module only if theModules doesn't already contain one
- DefaultModuleDecl defaultModule = null;
- foreach (ModuleDecl mdecl in theModules) {
- defaultModule = mdecl as DefaultModuleDecl;
- if (defaultModule != null) { break; }
- }
- bool defaultModuleCreatedHere = false;
- if (defaultModule == null) {
- defaultModuleCreatedHere = true;
- defaultModule = new DefaultModuleDecl();
- }
-
while (StartOf(1)) {
if (la.kind == 5) {
Get();
@@ -246,21 +234,21 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
DatatypeDecl(defaultModule, out dt);
defaultModule.TopLevelDecls.Add(dt);
} else {
- ClassMemberDecl(membersDefaultClass);
+ ClassMemberDecl(membersDefaultClass, false);
}
}
if (defaultModuleCreatedHere) {
defaultModule.TopLevelDecls.Add(new DefaultClassDecl(defaultModule, membersDefaultClass));
theModules.Add(defaultModule);
} else {
- // find the default class in the default module, then append membersDefaultClass to its member list
- foreach (TopLevelDecl topleveldecl in defaultModule.TopLevelDecls) {
- DefaultClassDecl defaultClass = topleveldecl as DefaultClassDecl;
- if (defaultClass != null) {
- defaultClass.Members.AddRange(membersDefaultClass);
- break;
- }
- }
+ // find the default class in the default module, then append membersDefaultClass to its member list
+ foreach (TopLevelDecl topleveldecl in defaultModule.TopLevelDecls) {
+ DefaultClassDecl defaultClass = topleveldecl as DefaultClassDecl;
+ if (defaultClass != null) {
+ defaultClass.Members.AddRange(membersDefaultClass);
+ break;
+ }
+ }
}
Expect(0);
@@ -316,13 +304,13 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
Expect(7);
bodyStart = t;
while (StartOf(2)) {
- ClassMemberDecl(members);
+ ClassMemberDecl(members, true);
}
Expect(8);
- if (optionalId == null)
+ if (optionalId == null)
c = new ClassDecl(id, id.val, module, typeArgs, members, attrs);
- else
- c = new ClassRefinementDecl(id, id.val, module, typeArgs, members, attrs, optionalId);
+ else
+ c = new ClassRefinementDecl(id, id.val, module, typeArgs, members, attrs, optionalId);
c.BodyStartTok = bodyStart;
c.BodyEndTok = t;
@@ -359,7 +347,7 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
}
- void ClassMemberDecl(List<MemberDecl/*!*/>/*!*/ mm) {
+ void ClassMemberDecl(List<MemberDecl/*!*/>/*!*/ mm, bool allowConstructors) {
Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
Function/*!*/ f;
@@ -383,7 +371,7 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
FunctionDecl(mmod, out f);
mm.Add(f);
} else if (la.kind == 10 || la.kind == 25 || la.kind == 26) {
- MethodDecl(mmod, out m);
+ MethodDecl(mmod, allowConstructors, out m);
mm.Add(m);
} else if (la.kind == 20) {
CouplingInvDecl(mmod, mm);
@@ -459,25 +447,20 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
Formals(true, isFunctionMethod, formals);
Expect(22);
Type(out returnType);
- if (la.kind == 17) {
- Get();
- while (StartOf(3)) {
- FunctionSpec(reqs, reads, ens, decreases);
- }
- } else if (StartOf(4)) {
- while (StartOf(3)) {
- FunctionSpec(reqs, reads, ens, decreases);
- }
+ while (StartOf(3)) {
+ FunctionSpec(reqs, reads, ens, decreases);
+ }
+ if (la.kind == 7) {
FunctionBody(out bb, out bodyStart, out bodyEnd);
body = bb;
- } else SynErr(106);
+ }
f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, formals, returnType, reqs, reads, ens, decreases, body, attrs);
f.BodyStartTok = bodyStart;
f.BodyEndTok = bodyEnd;
}
- void MethodDecl(MemberModifiers mmod, out Method/*!*/ m) {
+ void MethodDecl(MemberModifiers mmod, bool allowConstructor, out Method/*!*/ m) {
Contract.Ensures(Contract.ValueAtReturn(out m) !=null);
IToken/*!*/ id;
Attributes attrs = null;
@@ -498,19 +481,24 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
Get();
} else if (la.kind == 26) {
Get();
- isConstructor = true;
+ if (allowConstructor) {
+ isConstructor = true;
+ } else {
+ SemErr(t, "constructors are only allowed in classes");
+ }
+
} else if (la.kind == 10) {
Get();
isRefinement = true;
- } else SynErr(107);
+ } else SynErr(106);
if (mmod.IsUnlimited) { SemErr(t, "methods cannot be declared 'unlimited'"); }
if (isConstructor) {
- if (mmod.IsGhost) {
- SemErr(t, "constructors cannot be declared 'ghost'");
- }
- if (mmod.IsStatic) {
- SemErr(t, "constructors cannot be declared 'static'");
- }
+ if (mmod.IsGhost) {
+ SemErr(t, "constructors cannot be declared 'ghost'");
+ }
+ if (mmod.IsStatic) {
+ SemErr(t, "constructors cannot be declared 'static'");
+ }
}
while (la.kind == 7) {
@@ -526,24 +514,19 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); }
Formals(false, !mmod.IsGhost, outs);
}
- if (la.kind == 17) {
- Get();
- while (StartOf(5)) {
- MethodSpec(req, mod, ens, dec);
- }
- } else if (StartOf(6)) {
- while (StartOf(5)) {
- MethodSpec(req, mod, ens, dec);
- }
+ while (StartOf(4)) {
+ MethodSpec(req, mod, ens, dec);
+ }
+ if (la.kind == 7) {
BlockStmt(out bb, out bodyStart, out bodyEnd);
body = (BlockStmt)bb;
- } else SynErr(108);
+ }
if (isRefinement)
m = new MethodRefinement(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs, req, mod, ens, dec, body, attrs);
else if (isConstructor)
- m = new Constructor(id, id.val, typeArgs, ins, req, mod, ens, dec, body, attrs);
+ m = new Constructor(id, id.val, typeArgs, ins, req, mod, ens, dec, body, attrs);
else
- m = new Method(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs, req, mod, ens, dec, body, attrs);
+ m = new Method(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs, req, mod, ens, dec, body, attrs);
m.BodyStartTok = bodyStart;
m.BodyEndTok = bodyEnd;
@@ -596,7 +579,7 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
void FormalsOptionalIds(List<Formal/*!*/>/*!*/ formals) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost;
Expect(33);
- if (StartOf(7)) {
+ if (StartOf(5)) {
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
while (la.kind == 19) {
@@ -673,9 +656,9 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
Get();
UserDefinedType udt = ty as UserDefinedType;
if (udt != null && udt.TypeArgs.Count == 0) {
- name = udt.Name;
+ name = udt.Name;
} else {
- SemErr(id, "invalid formal-parameter name in datatype constructor");
+ SemErr(id, "invalid formal-parameter name in datatype constructor");
}
Type(out ty);
@@ -683,7 +666,7 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
if (name != null) {
identName = name;
} else {
- identName = "#" + anonymousIds++;
+ identName = "#" + anonymousIds++;
}
}
@@ -734,7 +717,7 @@ public static int Parse (string/*!*/ s, string/*!*/ filename, List<ModuleDecl/*!
ReferenceType(out tok, out ty);
break;
}
- default: SynErr(109); break;
+ default: SynErr(107); break;
}
}
@@ -760,7 +743,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (la.kind == 28) {
Get();
- if (StartOf(8)) {
+ if (StartOf(6)) {
FrameExpression(out fe);
mod.Add(fe);
while (la.kind == 19) {
@@ -785,12 +768,12 @@ List<Expression/*!*/>/*!*/ decreases) {
Expression(out e);
Expect(17);
ens.Add(new MaybeFreeExpression(e, isFree));
- } else SynErr(110);
+ } else SynErr(108);
} else if (la.kind == 32) {
Get();
DecreasesList(decreases, false);
Expect(17);
- } else SynErr(111);
+ } else SynErr(109);
}
void BlockStmt(out Statement/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
@@ -799,7 +782,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Expect(7);
bodyStart = t;
- while (StartOf(9)) {
+ while (StartOf(7)) {
Stmt(body);
}
Expect(8);
@@ -824,7 +807,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (!allowWildcard && e is WildcardExpr) {
SemErr(e.tok, "'decreases *' is only allowed on loops");
} else {
- decreases.Add(e);
+ decreases.Add(e);
}
while (la.kind == 19) {
@@ -833,7 +816,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (!allowWildcard && e is WildcardExpr) {
SemErr(e.tok, "'decreases *' is only allowed on loops");
} else {
- decreases.Add(e);
+ decreases.Add(e);
}
}
@@ -869,7 +852,7 @@ List<Expression/*!*/>/*!*/ decreases) {
}
int dims = 1;
if (tok.val.Length != 5) {
- dims = int.Parse(tok.val.Substring(5));
+ dims = int.Parse(tok.val.Substring(5));
}
ty = theBuiltIns.ArrayType(tok, dims, gt[0], true);
@@ -880,7 +863,7 @@ List<Expression/*!*/>/*!*/ decreases) {
GenericInstantiation(gt);
}
ty = new UserDefinedType(tok, tok.val, gt);
- } else SynErr(112);
+ } else SynErr(110);
}
void FunctionSpec(List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ reads, List<Expression/*!*/>/*!*/ ens, List<Expression/*!*/>/*!*/ decreases) {
@@ -893,7 +876,7 @@ List<Expression/*!*/>/*!*/ decreases) {
reqs.Add(e);
} else if (la.kind == 42) {
Get();
- if (StartOf(10)) {
+ if (StartOf(8)) {
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
while (la.kind == 19) {
@@ -912,7 +895,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
DecreasesList(decreases, false);
Expect(17);
- } else SynErr(113);
+ } else SynErr(111);
}
void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) {
@@ -929,9 +912,9 @@ List<Expression/*!*/>/*!*/ decreases) {
if (la.kind == 43) {
Get();
fe = new FrameExpression(new WildcardExpr(t), null);
- } else if (StartOf(8)) {
+ } else if (StartOf(6)) {
FrameExpression(out fe);
- } else SynErr(114);
+ } else SynErr(112);
}
void PossiblyWildExpression(out Expression/*!*/ e) {
@@ -940,9 +923,9 @@ List<Expression/*!*/>/*!*/ decreases) {
if (la.kind == 43) {
Get();
e = new WildcardExpr(t);
- } else if (StartOf(8)) {
+ } else if (StartOf(6)) {
Expression(out e);
- } else SynErr(115);
+ } else SynErr(113);
}
void Stmt(List<Statement/*!*/>/*!*/ ss) {
@@ -1019,7 +1002,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
breakCount++;
}
- } else SynErr(116);
+ } else SynErr(114);
Expect(17);
s = label != null ? new BreakStmt(x, label) : new BreakStmt(x, breakCount);
break;
@@ -1028,7 +1011,7 @@ List<Expression/*!*/>/*!*/ decreases) {
ReturnStmt(out s);
break;
}
- default: SynErr(117); break;
+ default: SynErr(115); break;
}
}
@@ -1099,7 +1082,7 @@ List<Expression/*!*/>/*!*/ decreases) {
} else if (la.kind == 22) {
Get();
SemErr(t, "invalid statement (did you forget the 'label' keyword?)");
- } else SynErr(118);
+ } else SynErr(116);
s = new UpdateStmt(x, lhss, rhss);
}
@@ -1137,13 +1120,13 @@ List<Expression/*!*/>/*!*/ decreases) {
Expect(17);
UpdateStmt update;
if (rhss.Count == 0) {
- update = null;
+ update = null;
} else {
- var ies = new List<Expression>();
- foreach (var lhs in lhss) {
- ies.Add(new AutoGhostIdentifierExpr(lhs.Tok, lhs.Name));
- }
- update = new UpdateStmt(assignTok, ies, rhss);
+ var ies = new List<Expression>();
+ foreach (var lhs in lhss) {
+ ies.Add(new AutoGhostIdentifierExpr(lhs.Tok, lhs.Name));
+ }
+ update = new UpdateStmt(assignTok, ies, rhss);
}
s = new VarDeclStmt(x, lhss, update);
@@ -1172,13 +1155,13 @@ List<Expression/*!*/>/*!*/ decreases) {
} else if (la.kind == 7) {
BlockStmt(out s, out bodyStart, out bodyEnd);
els = s;
- } else SynErr(119);
+ } else SynErr(117);
}
ifStmt = new IfStmt(x, guard, thn, els);
} else if (la.kind == 7) {
AlternativeBlock(out alternatives);
ifStmt = new AlternativeStmt(x, alternatives);
- } else SynErr(120);
+ } else SynErr(118);
}
void WhileStmt(out Statement/*!*/ stmt) {
@@ -1200,11 +1183,11 @@ List<Expression/*!*/>/*!*/ decreases) {
LoopSpec(out invariants, out decreases, out mod);
BlockStmt(out body, out bodyStart, out bodyEnd);
stmt = new WhileStmt(x, guard, invariants, decreases, mod, body);
- } else if (StartOf(11)) {
+ } else if (StartOf(9)) {
LoopSpec(out invariants, out decreases, out mod);
AlternativeBlock(out alternatives);
stmt = new AlternativeLoopStmt(x, invariants, decreases, mod, alternatives);
- } else SynErr(121);
+ } else SynErr(119);
}
void MatchStmt(out Statement/*!*/ s) {
@@ -1266,7 +1249,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (bodyAssign != null) {
s = new ForeachStmt(x, new BoundVar(boundVar, boundVar.val, ty), collection, range, bodyPrefix, bodyAssign);
} else {
- s = dummyStmt; // some error occurred in parsing the bodyAssign
+ s = dummyStmt; // some error occurred in parsing the bodyAssign
}
}
@@ -1278,7 +1261,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Expect(47);
returnTok = t;
- if (StartOf(12)) {
+ if (StartOf(10)) {
Rhs(out r, null);
rhss = new List<AssignmentRhs>(); rhss.Add(r);
while (la.kind == 19) {
@@ -1316,7 +1299,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Ident(out x);
Expect(33);
args = new List<Expression/*!*/>();
- if (StartOf(8)) {
+ if (StartOf(6)) {
Expressions(args);
}
Expect(34);
@@ -1327,7 +1310,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (ee != null) {
r = new TypeRhs(newToken, ty, ee);
} else {
- r = new TypeRhs(newToken, ty, initCall);
+ r = new TypeRhs(newToken, ty, initCall);
}
} else if (la.kind == 53) {
@@ -1338,10 +1321,10 @@ List<Expression/*!*/>/*!*/ decreases) {
} else if (la.kind == 43) {
Get();
r = new HavocRhs(t);
- } else if (StartOf(8)) {
+ } else if (StartOf(6)) {
Expression(out e);
r = new ExprRhs(e);
- } else SynErr(122);
+ } else SynErr(120);
}
void Lhs(out Expression e) {
@@ -1352,13 +1335,13 @@ List<Expression/*!*/>/*!*/ decreases) {
while (la.kind == 50 || la.kind == 52) {
Suffix(ref e);
}
- } else if (StartOf(13)) {
+ } else if (StartOf(11)) {
ConstAtomExpression(out e);
Suffix(ref e);
while (la.kind == 50 || la.kind == 52) {
Suffix(ref e);
}
- } else SynErr(123);
+ } else SynErr(121);
}
void Expressions(List<Expression/*!*/>/*!*/ args) {
@@ -1378,10 +1361,10 @@ List<Expression/*!*/>/*!*/ decreases) {
if (la.kind == 43) {
Get();
e = null;
- } else if (StartOf(8)) {
+ } else if (StartOf(6)) {
Expression(out ee);
e = ee;
- } else SynErr(124);
+ } else SynErr(122);
Expect(34);
}
@@ -1398,7 +1381,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Expression(out e);
Expect(57);
body = new List<Statement>();
- while (StartOf(9)) {
+ while (StartOf(7)) {
Stmt(body);
}
alternatives.Add(new GuardedAlternative(x, e, body));
@@ -1412,7 +1395,7 @@ List<Expression/*!*/>/*!*/ decreases) {
decreases = new List<Expression/*!*/>();
mod = null;
- while (StartOf(14)) {
+ while (StartOf(12)) {
if (la.kind == 29 || la.kind == 59) {
isFree = false;
if (la.kind == 29) {
@@ -1430,7 +1413,7 @@ List<Expression/*!*/>/*!*/ decreases) {
} else {
Get();
mod = mod ?? new List<FrameExpression>();
- if (StartOf(8)) {
+ if (StartOf(6)) {
FrameExpression(out fe);
mod.Add(fe);
while (la.kind == 19) {
@@ -1465,7 +1448,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Expect(34);
}
Expect(57);
- while (StartOf(9)) {
+ while (StartOf(7)) {
Stmt(body);
}
c = new MatchCaseStmt(x, id.val, arguments, body);
@@ -1476,10 +1459,10 @@ List<Expression/*!*/>/*!*/ decreases) {
if (la.kind == 4) {
Get();
arg = new Attributes.Argument(t.val.Substring(1, t.val.Length-2));
- } else if (StartOf(8)) {
+ } else if (StartOf(6)) {
Expression(out e);
arg = new Attributes.Argument(e);
- } else SynErr(125);
+ } else SynErr(123);
}
void EquivExpression(out Expression/*!*/ e0) {
@@ -1509,13 +1492,13 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
} else if (la.kind == 67) {
Get();
- } else SynErr(126);
+ } else SynErr(124);
}
void LogicalExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
RelationalExpression(out e0);
- if (StartOf(15)) {
+ if (StartOf(13)) {
if (la.kind == 70 || la.kind == 71) {
AndOp();
x = t;
@@ -1547,7 +1530,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
} else if (la.kind == 69) {
Get();
- } else SynErr(127);
+ } else SynErr(125);
}
void RelationalExpression(out Expression/*!*/ e) {
@@ -1556,23 +1539,23 @@ List<Expression/*!*/>/*!*/ decreases) {
List<Expression> chain = null;
List<BinaryExpr.Opcode> ops = null;
int kind = 0; // 0 ("uncommitted") indicates chain of ==, possibly with one !=
- // 1 ("ascending") indicates chain of ==, <, <=, possibly with one !=
- // 2 ("descending") indicates chain of ==, >, >=, possibly with one !=
- // 3 ("illegal") indicates illegal chain
- // 4 ("disjoint") indicates chain of disjoint set operators
+ // 1 ("ascending") indicates chain of ==, <, <=, possibly with one !=
+ // 2 ("descending") indicates chain of ==, >, >=, possibly with one !=
+ // 3 ("illegal") indicates illegal chain
+ // 4 ("disjoint") indicates chain of disjoint set operators
bool hasSeenNeq = false;
Term(out e0);
e = e0;
- if (StartOf(16)) {
+ if (StartOf(14)) {
RelOp(out x, out op);
firstOpTok = x;
Term(out e1);
e = new BinaryExpr(x, op, e0, e1);
if (op == BinaryExpr.Opcode.Disjoint)
- acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, e0, e1); // accumulate first two operands.
+ acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, e0, e1); // accumulate first two operands.
- while (StartOf(16)) {
+ while (StartOf(14)) {
if (chain == null) {
chain = new List<Expression>();
ops = new List<BinaryExpr.Opcode>();
@@ -1603,36 +1586,35 @@ List<Expression/*!*/>/*!*/ decreases) {
break;
case BinaryExpr.Opcode.Neq:
if (hasSeenNeq) { SemErr(x, "a chain cannot have more than one != operator"); }
- if (kind != 0 && kind != 1 && kind != 2) { SemErr(x, "this operator cannot continue this chain"); }
- hasSeenNeq = true; break;
- case BinaryExpr.Opcode.Lt:
- case BinaryExpr.Opcode.Le:
- if (kind == 0) { kind = 1; }
- else if (kind != 1) { SemErr(x, "this operator chain cannot continue with an ascending operator"); }
- break;
- case BinaryExpr.Opcode.Gt:
- case BinaryExpr.Opcode.Ge:
- if (kind == 0) { kind = 2; }
- else if (kind != 2) { SemErr(x, "this operator chain cannot continue with a descending operator"); }
- break;
- case BinaryExpr.Opcode.Disjoint:
- if (kind != 4) { SemErr(x, "can only chain disjoint (!!) with itself."); kind = 3; }
- break;
- default:
- SemErr(x, "this operator cannot be part of a chain");
- kind = 3; break;
- }
-
+ if (kind != 0 && kind != 1 && kind != 2) { SemErr(x, "this operator cannot continue this chain"); }
+ hasSeenNeq = true; break;
+ case BinaryExpr.Opcode.Lt:
+ case BinaryExpr.Opcode.Le:
+ if (kind == 0) { kind = 1; }
+ else if (kind != 1) { SemErr(x, "this operator chain cannot continue with an ascending operator"); }
+ break;
+ case BinaryExpr.Opcode.Gt:
+ case BinaryExpr.Opcode.Ge:
+ if (kind == 0) { kind = 2; }
+ else if (kind != 2) { SemErr(x, "this operator chain cannot continue with a descending operator"); }
+ break;
+ case BinaryExpr.Opcode.Disjoint:
+ if (kind != 4) { SemErr(x, "can only chain disjoint (!!) with itself."); kind = 3; }
+ break;
+ default:
+ SemErr(x, "this operator cannot be part of a chain");
+ kind = 3; break;
+ }
+
Term(out e1);
ops.Add(op); chain.Add(e1);
- if (op == BinaryExpr.Opcode.Disjoint)
- {
- e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, acc, e1));
- acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, acc, e1); //e0 has already been added.
- }
- else
- e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, e0, e1));
-
+ if (op == BinaryExpr.Opcode.Disjoint) {
+ e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, acc, e1));
+ acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, acc, e1); //e0 has already been added.
+ }
+ else
+ e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, e0, e1));
+
}
}
if (chain != null) {
@@ -1646,7 +1628,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
} else if (la.kind == 71) {
Get();
- } else SynErr(128);
+ } else SynErr(126);
}
void OrOp() {
@@ -1654,7 +1636,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
} else if (la.kind == 73) {
Get();
- } else SynErr(129);
+ } else SynErr(127);
}
void Term(out Expression/*!*/ e0) {
@@ -1730,7 +1712,7 @@ List<Expression/*!*/>/*!*/ decreases) {
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- default: SynErr(130); break;
+ default: SynErr(128); break;
}
}
@@ -1752,7 +1734,7 @@ List<Expression/*!*/>/*!*/ decreases) {
} else if (la.kind == 84) {
Get();
x = t; op = BinaryExpr.Opcode.Sub;
- } else SynErr(131);
+ } else SynErr(129);
}
void UnaryExpression(out Expression/*!*/ e) {
@@ -1794,7 +1776,7 @@ List<Expression/*!*/>/*!*/ decreases) {
}
break;
}
- default: SynErr(132); break;
+ default: SynErr(130); break;
}
}
@@ -1809,7 +1791,7 @@ List<Expression/*!*/>/*!*/ decreases) {
} else if (la.kind == 86) {
Get();
x = t; op = BinaryExpr.Opcode.Mod;
- } else SynErr(133);
+ } else SynErr(131);
}
void NegOp() {
@@ -1817,7 +1799,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
} else if (la.kind == 88) {
Get();
- } else SynErr(134);
+ } else SynErr(132);
}
void EndlessExpression(out Expression e) {
@@ -1836,11 +1818,11 @@ List<Expression/*!*/>/*!*/ decreases) {
e = new ITEExpr(x, e, e0, e1);
} else if (la.kind == 60) {
MatchExpression(out e);
- } else if (StartOf(17)) {
+ } else if (StartOf(15)) {
QuantifierGuts(out e);
} else if (la.kind == 38) {
ComprehensionExpr(out e);
- } else SynErr(135);
+ } else SynErr(133);
}
void DottedIdentifiersAndFunction(out Expression e) {
@@ -1858,7 +1840,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (la.kind == 33) {
Get();
openParen = t; args = new List<Expression>();
- if (StartOf(8)) {
+ if (StartOf(6)) {
Expressions(args);
}
Expect(34);
@@ -1878,7 +1860,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (la.kind == 33) {
Get();
args = new List<Expression/*!*/>(); func = true;
- if (StartOf(8)) {
+ if (StartOf(6)) {
Expressions(args);
}
Expect(34);
@@ -1888,13 +1870,13 @@ List<Expression/*!*/>/*!*/ decreases) {
} else if (la.kind == 50) {
Get();
x = t;
- if (StartOf(8)) {
+ if (StartOf(6)) {
Expression(out ee);
e0 = ee;
if (la.kind == 97) {
Get();
anyDots = true;
- if (StartOf(8)) {
+ if (StartOf(6)) {
Expression(out ee);
e1 = ee;
}
@@ -1913,36 +1895,36 @@ List<Expression/*!*/>/*!*/ decreases) {
multipleIndices.Add(ee);
}
- } else SynErr(136);
+ } else SynErr(134);
} else if (la.kind == 97) {
Get();
Expression(out ee);
anyDots = true; e1 = ee;
- } else SynErr(137);
+ } else SynErr(135);
if (multipleIndices != null) {
e = new MultiSelectExpr(x, e, multipleIndices);
// make sure an array class with this dimensionality exists
UserDefinedType tmp = theBuiltIns.ArrayType(x, multipleIndices.Count, new IntType(), true);
} else {
- if (!anyDots && e0 == null) {
- /* a parsing error occurred */
- e0 = dummyExpr;
- }
- Contract.Assert(anyDots || e0 != null);
- if (anyDots) {
- Contract.Assert(e0 != null || e1 != null);
- e = new SeqSelectExpr(x, false, e, e0, e1);
- } else if (e1 == null) {
- Contract.Assert(e0 != null);
- e = new SeqSelectExpr(x, true, e, e0, null);
- } else {
- Contract.Assert(e0 != null);
- e = new SeqUpdateExpr(x, e, e0, e1);
- }
+ if (!anyDots && e0 == null) {
+ /* a parsing error occurred */
+ e0 = dummyExpr;
+ }
+ Contract.Assert(anyDots || e0 != null);
+ if (anyDots) {
+ Contract.Assert(e0 != null || e1 != null);
+ e = new SeqSelectExpr(x, false, e, e0, e1);
+ } else if (e1 == null) {
+ Contract.Assert(e0 != null);
+ e = new SeqSelectExpr(x, true, e, e0, null);
+ } else {
+ Contract.Assert(e0 != null);
+ e = new SeqUpdateExpr(x, e, e0, e1);
+ }
}
Expect(51);
- } else SynErr(138);
+ } else SynErr(136);
}
void DisplayExpr(out Expression e) {
@@ -1953,7 +1935,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (la.kind == 7) {
Get();
x = t; elements = new List<Expression/*!*/>();
- if (StartOf(8)) {
+ if (StartOf(6)) {
Expressions(elements);
}
e = new SetDisplayExpr(x, elements);
@@ -1961,12 +1943,12 @@ List<Expression/*!*/>/*!*/ decreases) {
} else if (la.kind == 50) {
Get();
x = t; elements = new List<Expression/*!*/>();
- if (StartOf(8)) {
+ if (StartOf(6)) {
Expressions(elements);
}
e = new SeqDisplayExpr(x, elements);
Expect(51);
- } else SynErr(139);
+ } else SynErr(137);
}
void ConstAtomExpression(out Expression/*!*/ e) {
@@ -2043,7 +2025,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Expect(34);
break;
}
- default: SynErr(140); break;
+ default: SynErr(138); break;
}
}
@@ -2052,8 +2034,8 @@ List<Expression/*!*/>/*!*/ decreases) {
try {
n = BigInteger.Parse(t.val);
} catch (System.FormatException) {
- SemErr("incorrectly formatted number");
- n = BigInteger.Zero;
+ SemErr("incorrectly formatted number");
+ n = BigInteger.Zero;
}
}
@@ -2088,7 +2070,7 @@ List<Expression/*!*/>/*!*/ decreases) {
} else if (la.kind == 100 || la.kind == 101) {
Exists();
x = t;
- } else SynErr(141);
+ } else SynErr(139);
IdentTypeOptional(out bv);
bvars.Add(bv);
while (la.kind == 19) {
@@ -2108,7 +2090,7 @@ List<Expression/*!*/>/*!*/ decreases) {
if (univ) {
q = new ForallExpr(x, bvars, range, body, trigs, attrs);
} else {
- q = new ExistsExpr(x, bvars, range, body, trigs, attrs);
+ q = new ExistsExpr(x, bvars, range, body, trigs, attrs);
}
}
@@ -2170,7 +2152,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
} else if (la.kind == 99) {
Get();
- } else SynErr(142);
+ } else SynErr(140);
}
void Exists() {
@@ -2178,7 +2160,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
} else if (la.kind == 101) {
Get();
- } else SynErr(143);
+ } else SynErr(141);
}
void AttributeOrTrigger(ref Attributes attrs, ref Triggers trigs) {
@@ -2187,11 +2169,11 @@ List<Expression/*!*/>/*!*/ decreases) {
Expect(7);
if (la.kind == 22) {
AttributeBody(ref attrs);
- } else if (StartOf(8)) {
+ } else if (StartOf(6)) {
es = new List<Expression/*!*/>();
Expressions(es);
trigs = new Triggers(es, trigs);
- } else SynErr(144);
+ } else SynErr(142);
Expect(8);
}
@@ -2200,7 +2182,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Get();
} else if (la.kind == 103) {
Get();
- } else SynErr(145);
+ } else SynErr(143);
}
void AttributeBody(ref Attributes attrs) {
@@ -2211,7 +2193,7 @@ List<Expression/*!*/>/*!*/ decreases) {
Expect(22);
Expect(1);
aName = t.val;
- if (StartOf(18)) {
+ if (StartOf(16)) {
AttributeArg(out aArg);
aArgs.Add(aArg);
while (la.kind == 19) {
@@ -2230,6 +2212,7 @@ List<Expression/*!*/>/*!*/ decreases) {
la.val = "";
Get();
Dafny();
+ Expect(0);
Expect(0);
}
@@ -2239,9 +2222,7 @@ List<Expression/*!*/>/*!*/ decreases) {
{x,x,x,x, x,T,x,x, x,T,T,T, T,T,T,x, x,x,T,x, T,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,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,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
{x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,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,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,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,T,x,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,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,x, x,x,x,x, x,x},
{x,T,T,x, x,x,x,T, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,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, T,x,x,T, T,T,T,T, T,T,T,T, x,x,T,T, T,T,x,x, x,x},
{x,T,T,x, x,x,x,T, x,x,x,T, x,x,x,x, T,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,T,T,T, x,x,x,x, x,x,T,x, x,x,T,x, T,T,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,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x},
@@ -2384,46 +2365,44 @@ public class Errors {
case 103: s = "\"\\u2022\" expected"; break;
case 104: s = "??? expected"; break;
case 105: s = "invalid ClassMemberDecl"; break;
- case 106: s = "invalid FunctionDecl"; break;
- case 107: s = "invalid MethodDecl"; break;
- case 108: s = "invalid MethodDecl"; break;
- case 109: s = "invalid TypeAndToken"; break;
- case 110: s = "invalid MethodSpec"; break;
- case 111: s = "invalid MethodSpec"; break;
- case 112: s = "invalid ReferenceType"; break;
- case 113: s = "invalid FunctionSpec"; break;
- case 114: s = "invalid PossiblyWildFrameExpression"; break;
- case 115: s = "invalid PossiblyWildExpression"; break;
- case 116: s = "invalid OneStmt"; break;
- case 117: s = "invalid OneStmt"; break;
- case 118: s = "invalid UpdateStmt"; break;
- case 119: s = "invalid IfStmt"; break;
- case 120: s = "invalid IfStmt"; break;
- case 121: s = "invalid WhileStmt"; break;
- case 122: s = "invalid Rhs"; break;
- case 123: s = "invalid Lhs"; break;
- case 124: s = "invalid Guard"; break;
- case 125: s = "invalid AttributeArg"; break;
- case 126: s = "invalid EquivOp"; break;
- case 127: s = "invalid ImpliesOp"; break;
- case 128: s = "invalid AndOp"; break;
- case 129: s = "invalid OrOp"; break;
- case 130: s = "invalid RelOp"; break;
- case 131: s = "invalid AddOp"; break;
- case 132: s = "invalid UnaryExpression"; break;
- case 133: s = "invalid MulOp"; break;
- case 134: s = "invalid NegOp"; break;
- case 135: s = "invalid EndlessExpression"; break;
+ case 106: s = "invalid MethodDecl"; break;
+ case 107: s = "invalid TypeAndToken"; break;
+ case 108: s = "invalid MethodSpec"; break;
+ case 109: s = "invalid MethodSpec"; break;
+ case 110: s = "invalid ReferenceType"; break;
+ case 111: s = "invalid FunctionSpec"; break;
+ case 112: s = "invalid PossiblyWildFrameExpression"; break;
+ case 113: s = "invalid PossiblyWildExpression"; break;
+ case 114: s = "invalid OneStmt"; break;
+ case 115: s = "invalid OneStmt"; break;
+ case 116: s = "invalid UpdateStmt"; break;
+ case 117: s = "invalid IfStmt"; break;
+ case 118: s = "invalid IfStmt"; break;
+ case 119: s = "invalid WhileStmt"; break;
+ case 120: s = "invalid Rhs"; break;
+ case 121: s = "invalid Lhs"; break;
+ case 122: s = "invalid Guard"; break;
+ case 123: s = "invalid AttributeArg"; break;
+ case 124: s = "invalid EquivOp"; break;
+ case 125: s = "invalid ImpliesOp"; break;
+ case 126: s = "invalid AndOp"; break;
+ case 127: s = "invalid OrOp"; break;
+ case 128: s = "invalid RelOp"; break;
+ case 129: s = "invalid AddOp"; break;
+ case 130: s = "invalid UnaryExpression"; break;
+ case 131: s = "invalid MulOp"; break;
+ case 132: s = "invalid NegOp"; break;
+ case 133: s = "invalid EndlessExpression"; break;
+ case 134: s = "invalid Suffix"; break;
+ case 135: s = "invalid Suffix"; break;
case 136: s = "invalid Suffix"; break;
- case 137: s = "invalid Suffix"; break;
- case 138: s = "invalid Suffix"; break;
- case 139: s = "invalid DisplayExpr"; break;
- case 140: s = "invalid ConstAtomExpression"; break;
- case 141: s = "invalid QuantifierGuts"; break;
- case 142: s = "invalid Forall"; break;
- case 143: s = "invalid Exists"; break;
- case 144: s = "invalid AttributeOrTrigger"; break;
- case 145: s = "invalid QSep"; break;
+ case 137: s = "invalid DisplayExpr"; break;
+ case 138: s = "invalid ConstAtomExpression"; break;
+ case 139: s = "invalid QuantifierGuts"; break;
+ case 140: s = "invalid Forall"; break;
+ case 141: s = "invalid Exists"; break;
+ case 142: s = "invalid AttributeOrTrigger"; break;
+ case 143: s = "invalid QSep"; break;
default: s = "error " + n; break;
}
@@ -2453,4 +2432,5 @@ public class FatalError: Exception {
public FatalError(string m): base(m) {}
}
+
} \ No newline at end of file
diff --git a/Source/Dafny/Printer.cs b/Source/Dafny/Printer.cs
index e49ce6e9..ba9963c7 100644
--- a/Source/Dafny/Printer.cs
+++ b/Source/Dafny/Printer.cs
@@ -14,7 +14,7 @@ namespace Microsoft.Dafny {
class Printer {
TextWriter wr;
[ContractInvariantMethod]
- void ObjectInvariant()
+ void ObjectInvariant()
{
Contract.Invariant(wr!=null);
}
@@ -23,7 +23,7 @@ namespace Microsoft.Dafny {
Contract.Requires(wr != null);
this.wr = wr;
}
-
+
public void PrintProgram(Program prog) {
Contract.Requires(prog != null);
if (Bpl.CommandLineOptions.Clo.ShowEnv != Bpl.CommandLineOptions.ShowEnvironment.Never) {
@@ -56,7 +56,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
public void PrintTopLevelDecls(List<TopLevelDecl> classes, int indent) {
Contract.Requires(classes!= null);
int i = 0;
@@ -79,7 +79,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
public void PrintClass(ClassDecl c, int indent) {
Contract.Requires(c != null);
Indent(indent);
@@ -97,12 +97,12 @@ namespace Microsoft.Dafny {
wr.WriteLine("}");
}
}
-
+
public void PrintClass_Members(ClassDecl c, int indent)
{
Contract.Requires(c != null);
Contract.Requires( c.Members.Count != 0);
-
+
int state = 0; // 0 - no members yet; 1 - previous member was a field; 2 - previous member was non-field
foreach (MemberDecl m in c.Members) {
if (m is Method) {
@@ -126,7 +126,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
void PrintClassMethodHelper(string kind, Attributes attrs, string name, List<TypeParameter> typeArgs) {
Contract.Requires(kind != null);
Contract.Requires(name != null);
@@ -147,7 +147,7 @@ namespace Microsoft.Dafny {
wr.Write(">");
}
}
-
+
public void PrintDatatype(DatatypeDecl dt, int indent) {
Contract.Requires(dt != null);
Indent(indent);
@@ -164,17 +164,17 @@ namespace Microsoft.Dafny {
}
wr.WriteLine(";");
}
-
+
public void PrintAttributes(Attributes a) {
if (a != null) {
PrintAttributes(a.Prev);
-
+
wr.Write("{{:{0}", a.Name);
PrintAttributeArgs(a.Args);
wr.Write("} ");
}
}
-
+
public void PrintAttributeArgs(List<Attributes.Argument> args) {
Contract.Requires(args != null);
string prefix = " ";
@@ -190,7 +190,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
public void PrintField(Field field, int indent) {
Contract.Requires(field != null);
Indent(indent);
@@ -203,7 +203,7 @@ namespace Microsoft.Dafny {
PrintType(field.Type);
wr.WriteLine(";");
}
-
+
public void PrintCouplingInvariant(CouplingInvariant inv, int indent) {
Contract.Requires(inv != null);
Indent(indent);
@@ -218,7 +218,7 @@ namespace Microsoft.Dafny {
PrintExpression(inv.Expr);
wr.WriteLine(";");
}
-
+
public void PrintFunction(Function f, int indent) {
Contract.Requires(f != null);
Indent(indent);
@@ -230,7 +230,7 @@ namespace Microsoft.Dafny {
PrintFormals(f.Formals);
wr.Write(": ");
PrintType(f.ResultType);
- wr.WriteLine(f.Body == null ? ";" : "");
+ wr.WriteLine();
int ind = indent + IndentAmount;
PrintSpec("requires", f.Req, ind);
@@ -245,20 +245,20 @@ namespace Microsoft.Dafny {
wr.WriteLine("}");
}
}
-
+
// ----------------------------- PrintMethod -----------------------------
const int IndentAmount = 2;
const string BunchaSpaces = " ";
void Indent(int amount)
{ Contract.Requires( 0 <= amount);
-
+
while (0 < amount) {
wr.Write(BunchaSpaces.Substring(0, amount));
amount -= BunchaSpaces.Length;
}
}
-
+
public void PrintMethod(Method method, int indent) {
Contract.Requires(method != null);
Indent(indent);
@@ -277,21 +277,21 @@ namespace Microsoft.Dafny {
}
PrintFormals(method.Outs);
}
- wr.WriteLine(method.Body == null ? ";" : "");
+ wr.WriteLine();
int ind = indent + IndentAmount;
PrintSpec("requires", method.Req, ind);
PrintFrameSpecLine("modifies", method.Mod, ind);
PrintSpec("ensures", method.Ens, ind);
PrintSpecLine("decreases", method.Decreases, ind);
-
+
if (method.Body != null) {
Indent(indent);
PrintStatement(method.Body, indent);
wr.WriteLine();
}
}
-
+
void PrintFormals(List<Formal> ff) {
Contract.Requires(ff!=null);
wr.Write("(");
@@ -304,7 +304,7 @@ namespace Microsoft.Dafny {
}
wr.Write(")");
}
-
+
void PrintFormal(Formal f) {
Contract.Requires(f != null);
if (f.IsGhost) {
@@ -315,7 +315,7 @@ namespace Microsoft.Dafny {
}
PrintType(f.Type);
}
-
+
void PrintSpec(string kind, List<Expression> ee, int indent) {
Contract.Requires(kind != null);
Contract.Requires(ee != null);
@@ -363,7 +363,7 @@ namespace Microsoft.Dafny {
}
// ----------------------------- PrintType -----------------------------
-
+
public void PrintType(Type ty) {
Contract.Requires(ty != null);
wr.Write(ty.ToString());
@@ -379,7 +379,7 @@ namespace Microsoft.Dafny {
}
// ----------------------------- PrintStatement -----------------------------
-
+
/// <summary>
/// Prints from the current position of the current line.
/// If the statement requires several lines, subsequent lines are indented at "indent".
@@ -393,23 +393,23 @@ namespace Microsoft.Dafny {
Indent(indent);
}
}
-
+
if (stmt is AssertStmt) {
wr.Write("assert ");
PrintExpression(((AssertStmt)stmt).Expr);
wr.Write(";");
-
+
} else if (stmt is AssumeStmt) {
wr.Write("assume ");
PrintExpression(((AssumeStmt)stmt).Expr);
wr.Write(";");
-
+
} else if (stmt is PrintStmt) {
PrintStmt s = (PrintStmt)stmt;
wr.Write("print");
PrintAttributeArgs(s.Args);
wr.Write(";");
-
+
} else if (stmt is BreakStmt) {
BreakStmt s = (BreakStmt)stmt;
if (s.TargetLabel != null) {
@@ -422,7 +422,7 @@ namespace Microsoft.Dafny {
}
wr.Write(";");
}
-
+
} else if (stmt is ReturnStmt) {
var s = (ReturnStmt) stmt;
wr.Write("return");
@@ -435,14 +435,14 @@ namespace Microsoft.Dafny {
}
}
wr.Write(";");
-
+
} else if (stmt is AssignStmt) {
AssignStmt s = (AssignStmt)stmt;
PrintExpression(s.Lhs);
wr.Write(" := ");
PrintRhs(s.Rhs);
wr.Write(";");
-
+
} else if (stmt is VarDecl) {
VarDecl s = (VarDecl)stmt;
if (s.IsGhost) {
@@ -451,7 +451,7 @@ namespace Microsoft.Dafny {
wr.Write("var {0}", s.Name);
PrintType(": ", s.OptionalType);
wr.Write(";");
-
+
} else if (stmt is CallStmt) {
CallStmt s = (CallStmt)stmt;
wr.Write("call ");
@@ -471,7 +471,7 @@ namespace Microsoft.Dafny {
wr.Write("{0}(", s.MethodName);
PrintExpressionList(s.Args);
wr.Write(");");
-
+
} else if (stmt is BlockStmt) {
wr.WriteLine("{");
int ind = indent + IndentAmount;
@@ -482,7 +482,7 @@ namespace Microsoft.Dafny {
}
Indent(indent);
wr.Write("}");
-
+
} else if (stmt is IfStmt) {
IfStmt s = (IfStmt)stmt;
while (true) {
@@ -508,7 +508,7 @@ namespace Microsoft.Dafny {
PrintAlternatives(indent, s.Alternatives);
Indent(indent);
wr.Write("}");
-
+
} else if (stmt is WhileStmt) {
WhileStmt s = (WhileStmt)stmt;
wr.Write("while (");
@@ -556,7 +556,7 @@ namespace Microsoft.Dafny {
wr.WriteLine();
Indent(indent);
wr.Write("}");
-
+
} else if (stmt is MatchStmt) {
MatchStmt s = (MatchStmt)stmt;
wr.Write("match ");
@@ -644,7 +644,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
void PrintRhs(AssignmentRhs rhs) {
Contract.Requires(rhs != null);
if (rhs is ExprRhs) {
@@ -673,7 +673,7 @@ namespace Microsoft.Dafny {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected RHS
}
}
-
+
void PrintGuard(Expression guard) {
if (guard == null) {
wr.Write("*");
@@ -681,7 +681,7 @@ namespace Microsoft.Dafny {
PrintExpression(guard);
}
}
-
+
// ----------------------------- PrintExpression -----------------------------
public void PrintExtendedExpr(Expression expr, int indent, bool isRightmost, bool endWithCloseParen) {
@@ -739,12 +739,12 @@ namespace Microsoft.Dafny {
wr.WriteLine(endWithCloseParen ? ")" : "");
}
}
-
+
public void PrintExpression(Expression expr) {
Contract.Requires(expr != null);
PrintExpr(expr, 0, false, true, -1);
}
-
+
/// <summary>
/// An indent of -1 means print the entire expression on one line.
/// </summary>
@@ -752,7 +752,7 @@ namespace Microsoft.Dafny {
Contract.Requires(expr != null);
PrintExpr(expr, 0, false, true, indent);
}
-
+
/// <summary>
/// An indent of -1 means print the entire expression on one line.
/// </summary>
@@ -770,13 +770,13 @@ namespace Microsoft.Dafny {
} else {
wr.Write((BigInteger)e.Value);
}
-
+
} else if (expr is ThisExpr) {
wr.Write("this");
-
+
} else if (expr is IdentifierExpr) {
wr.Write(((IdentifierExpr)expr).Name);
-
+
} else if (expr is DatatypeValue) {
DatatypeValue dtv = (DatatypeValue)expr;
wr.Write("#{0}.{1}", dtv.DatatypeName, dtv.MemberName);
@@ -785,13 +785,13 @@ namespace Microsoft.Dafny {
PrintExpressionList(dtv.Arguments);
wr.Write(")");
}
-
+
} else if (expr is DisplayExpression) {
DisplayExpression e = (DisplayExpression)expr;
wr.Write(e is SetDisplayExpr ? "{" : "[");
PrintExpressionList(e.Elements);
wr.Write(e is SetDisplayExpr ? "}" : "]");
-
+
} else if (expr is FieldSelectExpr) {
FieldSelectExpr e = (FieldSelectExpr)expr;
// determine if parens are needed
@@ -799,7 +799,7 @@ namespace Microsoft.Dafny {
bool parensNeeded = !(e.Obj is ImplicitThisExpr) &&
opBindingStrength < contextBindingStrength ||
(fragileContext && opBindingStrength == contextBindingStrength);
-
+
if (parensNeeded) { wr.Write("("); }
if (!(e.Obj is ImplicitThisExpr)) {
PrintExpr(e.Obj, opBindingStrength, false, false, -1);
@@ -814,7 +814,7 @@ namespace Microsoft.Dafny {
int opBindingStrength = 0x70;
bool parensNeeded = opBindingStrength < contextBindingStrength ||
(fragileContext && opBindingStrength == contextBindingStrength);
-
+
if (parensNeeded) { wr.Write("("); }
PrintExpr(e.Seq, 0x00, false, false, indent); // BOGUS: fix me
wr.Write("[");
@@ -858,7 +858,7 @@ namespace Microsoft.Dafny {
int opBindingStrength = 0x70;
bool parensNeeded = opBindingStrength < contextBindingStrength ||
(fragileContext && opBindingStrength == contextBindingStrength);
-
+
if (parensNeeded) { wr.Write("("); }
PrintExpr(e.Seq, 00, false, false, indent); // BOGUS: fix me
wr.Write("[");
@@ -867,7 +867,7 @@ namespace Microsoft.Dafny {
PrintExpression(e.Value);
wr.Write("]");
if (parensNeeded) { wr.Write(")"); }
-
+
} else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
// determine if parens are needed
@@ -875,7 +875,7 @@ namespace Microsoft.Dafny {
bool parensNeeded = !(e.Receiver is ImplicitThisExpr) &&
opBindingStrength < contextBindingStrength ||
(fragileContext && opBindingStrength == contextBindingStrength);
-
+
if (parensNeeded) { wr.Write("("); }
if (!(e.Receiver is ImplicitThisExpr)) {
PrintExpr(e.Receiver, opBindingStrength, false, false, -1);
@@ -886,12 +886,12 @@ namespace Microsoft.Dafny {
PrintExpressionList(e.Args);
wr.Write(")");
if (parensNeeded) { wr.Write(")"); }
-
+
} else if (expr is OldExpr) {
wr.Write("old(");
PrintExpression(((OldExpr)expr).E);
wr.Write(")");
-
+
} else if (expr is FreshExpr) {
wr.Write("fresh(");
PrintExpression(((FreshExpr)expr).E);
@@ -929,14 +929,14 @@ namespace Microsoft.Dafny {
PrintExpr(e.E, opBindingStrength, false, parensNeeded || isRightmost, -1);
if (parensNeeded) { wr.Write(")"); }
}
-
+
} else if (expr is BinaryExpr) {
BinaryExpr e = (BinaryExpr)expr;
// determine if parens are needed
int opBindingStrength;
bool fragileLeftContext = false; // false means "allow same binding power on left without parens"
bool fragileRightContext = false; // false means "allow same binding power on right without parens"
- switch (e.Op)
+ switch (e.Op)
{
case BinaryExpr.Opcode.Add:
opBindingStrength = 0x40; break;
@@ -1064,7 +1064,7 @@ namespace Microsoft.Dafny {
} else if (expr is WildcardExpr) {
wr.Write("*");
-
+
} else if (expr is ITEExpr) {
ITEExpr ite = (ITEExpr)expr;
bool parensNeeded = !isRightmost;
@@ -1076,7 +1076,7 @@ namespace Microsoft.Dafny {
wr.Write(" else ");
PrintExpression(ite.Els);
if (parensNeeded) { wr.Write(")"); }
-
+
} else if (expr is ParensExpression) {
var e = (ParensExpression)expr;
// printing of parentheses is done optimally, not according to the parentheses in the given program
@@ -1094,24 +1094,24 @@ namespace Microsoft.Dafny {
PrintExpressionList(e.Arguments);
wr.Write(")");
}
-
+
} else if (expr is MatchExpr) {
Contract.Assert(false); throw new cce.UnreachableException(); // MatchExpr is an extended expression and should be printed only using PrintExtendedExpr
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected expression
}
}
-
+
void PrintTriggers(Triggers trigs) {
if (trigs != null) {
PrintTriggers(trigs.Prev);
-
+
wr.Write("{ ");
PrintExpressionList(trigs.Terms);
wr.Write(" } ");
}
}
-
+
void PrintExpressionList(List<Expression> exprs) {
Contract.Requires(exprs != null);
string sep = "";
diff --git a/Source/Dafny/Resolver.cs b/Source/Dafny/Resolver.cs
index 197a603e..8ec5d4c1 100644
--- a/Source/Dafny/Resolver.cs
+++ b/Source/Dafny/Resolver.cs
@@ -67,7 +67,7 @@ namespace Microsoft.Dafny {
}
bool checkRefinements = true; // used to indicate a cycle in refinements
-
+
public void ResolveProgram(Program prog) {
Contract.Requires(prog != null);
// register modules
@@ -119,15 +119,15 @@ namespace Microsoft.Dafny {
}
}
- // resolve top-level declarations of refinements
- foreach (ModuleDecl m in prog.Modules)
- foreach (TopLevelDecl decl in m.TopLevelDecls)
+ // resolve top-level declarations of refinements
+ foreach (ModuleDecl m in prog.Modules)
+ foreach (TopLevelDecl decl in m.TopLevelDecls)
if (decl is ClassRefinementDecl) {
ClassRefinementDecl rdecl = (ClassRefinementDecl) decl;
ResolveTopLevelRefinement(rdecl);
if (rdecl.Refined != null) refines.AddEdge(rdecl, rdecl.Refined);
}
-
+
// attempt finding refinement cycles
List<TopLevelDecl> refinesCycle = refines.TryFindCycle();
if (refinesCycle != null) {
@@ -139,8 +139,8 @@ namespace Microsoft.Dafny {
}
Error(refinesCycle[0], "Detected a cyclic refinement declaration: {0}", cy);
checkRefinements = false;
- }
-
+ }
+
// resolve top-level declarations
Graph<DatatypeDecl> datatypeDependencies = new Graph<DatatypeDecl>();
foreach (ModuleDecl m in prog.Modules) {
@@ -168,7 +168,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
public void RegisterTopLevelDecls(List<TopLevelDecl> declarations) {
Contract.Requires(declarations != null);
foreach (TopLevelDecl d in declarations) {
@@ -209,7 +209,7 @@ namespace Microsoft.Dafny {
// ... and of the other members
Dictionary<string, MemberDecl> members = new Dictionary<string, MemberDecl>();
datatypeMembers.Add(dt, members);
-
+
foreach (DatatypeCtor ctor in dt.Ctors) {
if (ctor.Name.EndsWith("?")) {
Error(ctor, "a datatype constructor name is not allowed to end with '?'");
@@ -224,7 +224,7 @@ namespace Microsoft.Dafny {
query.EnclosingClass = dt; // resolve here
members.Add(queryName, query);
ctor.QueryField = query;
-
+
// also register the constructor name globally
Tuple<DatatypeCtor, bool> pair;
if (allDatatypeCtors.TryGetValue(ctor.Name, out pair)) {
@@ -268,9 +268,9 @@ namespace Microsoft.Dafny {
}
decl.Refined = cce.NonNull((ClassDecl) a);
// TODO: copy over remaining members of a
- }
- }
-
+ }
+ }
+
public void ResolveTopLevelDecls_Signatures(List<TopLevelDecl/*!*/>/*!*/ declarations, Graph<DatatypeDecl/*!*/>/*!*/ datatypeDependencies) {
Contract.Requires(declarations != null);
Contract.Requires(cce.NonNullElements(datatypeDependencies));
@@ -286,7 +286,7 @@ namespace Microsoft.Dafny {
allTypeParameters.PopMarker();
}
}
-
+
public void ResolveTopLevelDecls_Meat(List<TopLevelDecl/*!*/>/*!*/ declarations, Graph<DatatypeDecl/*!*/>/*!*/ datatypeDependencies) {
Contract.Requires(declarations != null);
Contract.Requires(cce.NonNullElements(datatypeDependencies));
@@ -306,7 +306,7 @@ namespace Microsoft.Dafny {
allTypeParameters.PopMarker();
}
}
-
+
ClassDecl currentClass;
Function currentFunction;
readonly Scope<TypeParameter>/*!*/ allTypeParameters = new Scope<TypeParameter>();
@@ -314,7 +314,7 @@ namespace Microsoft.Dafny {
readonly Scope<Statement>/*!*/ labeledStatements = new Scope<Statement>();
readonly List<Statement> loopStack = new List<Statement>(); // the enclosing loops (from which it is possible to break out)
readonly Dictionary<Statement, bool> inSpecOnlyContext = new Dictionary<Statement, bool>(); // invariant: domain contain union of the domains of "labeledStatements" and "loopStack"
-
+
/// <summary>
/// Assumes type parameters have already been pushed
/// </summary>
@@ -323,13 +323,13 @@ namespace Microsoft.Dafny {
Contract.Requires(cl != null);
Contract.Requires(currentClass == null);
Contract.Ensures(currentClass == null);
-
+
currentClass = cl;
foreach (MemberDecl member in cl.Members) {
member.EnclosingClass = cl;
if (member is Field) {
ResolveType(member.tok, ((Field)member).Type);
-
+
} else if (member is Function) {
Function f = (Function)member;
allTypeParameters.PushMarker();
@@ -343,15 +343,15 @@ namespace Microsoft.Dafny {
ResolveTypeParameters(m.TypeArgs, true, m);
ResolveMethodSignature(m);
allTypeParameters.PopMarker();
-
+
} else if (member is CouplingInvariant) {
CouplingInvariant inv = (CouplingInvariant)member;
- if (currentClass is ClassRefinementDecl) {
+ if (currentClass is ClassRefinementDecl) {
ClassDecl refined = ((ClassRefinementDecl)currentClass).Refined;
if (refined != null) {
Contract.Assert(classMembers.ContainsKey(refined));
Dictionary<string,MemberDecl> members = classMembers[refined];
-
+
// resolve abstracted fields in the refined class
List<Field> fields = new List<Field>();
foreach (IToken tok in inv.Toks) {
@@ -359,29 +359,29 @@ namespace Microsoft.Dafny {
Error(tok, "Refined class does not declare a field: {0}", tok.val);
else {
MemberDecl field = members[tok.val];
- if (!(field is Field))
+ if (!(field is Field))
Error(tok, "Coupling invariant refers to a non-field member: {0}", tok.val);
else if (fields.Contains(cce.NonNull((Field)field)))
Error(tok, "Duplicate reference to a field in the refined class: {0}", tok.val);
else
fields.Add(cce.NonNull((Field)field));
- }
- }
+ }
+ }
inv.Refined = fields;
}
-
+
} else {
Error(member, "Coupling invariants can only be declared in refinement classes");
}
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected member type
}
-
- if (currentClass is ClassRefinementDecl) {
+
+ if (currentClass is ClassRefinementDecl) {
ClassDecl refined = ((ClassRefinementDecl)currentClass).Refined;
if (refined != null) {
Contract.Assert(classMembers.ContainsKey(refined));
-
+
// there is a member with the same name in refined class if and only if the member is a refined method
if ((member is MethodRefinement) != (classMembers[refined].ContainsKey(member.Name)))
Error(member, "Refined class has a member with the same name as in the refinement class: {0}", member.Name);
@@ -399,14 +399,14 @@ namespace Microsoft.Dafny {
Contract.Requires(cl != null);
Contract.Requires(currentClass == null);
Contract.Ensures(currentClass == null);
-
+
ResolveAttributes(cl.Attributes, false);
currentClass = cl;
foreach (MemberDecl member in cl.Members) {
ResolveAttributes(member.Attributes, false);
if (member is Field) {
// nothing more to do
-
+
} else if (member is Function) {
Function f = (Function)member;
allTypeParameters.PushMarker();
@@ -420,13 +420,13 @@ namespace Microsoft.Dafny {
ResolveTypeParameters(m.TypeArgs, false, m);
ResolveMethod(m);
allTypeParameters.PopMarker();
-
+
// check if signature of the refined method matches the refinement method
if (member is MethodRefinement) {
MethodRefinement mf = (MethodRefinement)member;
if (currentClass is ClassRefinementDecl) {
// should have already been resolved
- if (((ClassRefinementDecl)currentClass).Refined != null) {
+ if (((ClassRefinementDecl)currentClass).Refined != null) {
MemberDecl d = classMembers[((ClassRefinementDecl)currentClass).Refined][mf.Name];
if (d is Method) {
mf.Refined = (Method)d;
@@ -434,18 +434,18 @@ namespace Microsoft.Dafny {
Error(mf, "Different number of input variables");
if (mf.Outs.Count != mf.Refined.Outs.Count)
Error(mf, "Different number of output variables");
- if (mf.IsStatic || mf.Refined.IsStatic)
+ if (mf.IsStatic || mf.Refined.IsStatic)
Error(mf, "Refined methods cannot be static");
} else {
Error(member, "Refined class has a non-method member with the same name: {0}", member.Name);
- }
+ }
}
} else {
Error(member, "Refinement methods can only be declared in refinement classes: {0}", member.Name);
}
}
-
- } else if (member is CouplingInvariant) {
+
+ } else if (member is CouplingInvariant) {
CouplingInvariant inv = (CouplingInvariant)member;
if (inv.Refined != null) {
inv.Formals = new List<Formal>();
@@ -460,7 +460,7 @@ namespace Microsoft.Dafny {
}
ResolveExpression(inv.Expr, false);
scope.PopMarker();
- }
+ }
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected member type
}
@@ -476,13 +476,13 @@ namespace Microsoft.Dafny {
Contract.Requires(dt != null);
Contract.Requires(cce.NonNullElements(dependencies));
foreach (DatatypeCtor ctor in dt.Ctors) {
-
+
ctor.EnclosingDatatype = dt;
allTypeParameters.PushMarker();
ResolveCtorSignature(ctor);
allTypeParameters.PopMarker();
-
+
foreach (Formal p in ctor.Formals) {
DatatypeDecl dependee = p.Type.AsDatatype;
if (dependee != null) {
@@ -497,7 +497,7 @@ namespace Microsoft.Dafny {
/// datatype has some value that can be constructed from datatypes in lower stratospheres only.
/// The algorithm used here is quadratic in the number of datatypes in the SCC. Since that number is
/// deemed to be rather small, this seems okay.
- /// </summary>
+ /// </summary>
void SccStratosphereCheck(DatatypeDecl startingPoint, Graph<DatatypeDecl/*!*/>/*!*/ dependencies)
{
Contract.Requires(startingPoint != null);
@@ -573,7 +573,7 @@ namespace Microsoft.Dafny {
ResolveAttributeArgs(attrs.Args, twoState);
}
}
-
+
void ResolveAttributeArgs(List<Attributes.Argument/*!*/>/*!*/ args, bool twoState) {
Contract.Requires(args != null);
foreach (Attributes.Argument aa in args) {
@@ -583,7 +583,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
void ResolveTriggers(Triggers trigs, bool twoState) {
// order does not matter for resolution, so resolve them in reverse order
for (; trigs != null; trigs = trigs.Prev) {
@@ -592,9 +592,9 @@ namespace Microsoft.Dafny {
}
}
}
-
+
void ResolveTypeParameters(List<TypeParameter/*!*/>/*!*/ tparams, bool emitErrors, TypeParameter.ParentType/*!*/ parent) {
-
+
Contract.Requires(tparams != null);
Contract.Requires(parent != null);
// push type arguments of the refined class
@@ -603,7 +603,7 @@ namespace Microsoft.Dafny {
if (refined != null)
ResolveTypeParameters(refined.TypeArgs, false, refined);
}
-
+
// push non-duplicated type parameter names
foreach (TypeParameter tp in tparams) {
Contract.Assert(tp != null);
@@ -616,7 +616,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
/// <summary>
/// Assumes type parameters have already been pushed
/// </summary>
@@ -683,7 +683,7 @@ namespace Microsoft.Dafny {
currentFunction = null;
scope.PopMarker();
}
-
+
void ResolveFrameExpression(FrameExpression fe, string kind) {
Contract.Requires(fe != null);
Contract.Requires(kind != null);
@@ -717,7 +717,7 @@ namespace Microsoft.Dafny {
Error(fe.E, "a {0}-clause expression must denote an object or a collection of objects (instead got {1})", kind, fe.E.Type);
}
}
-
+
/// <summary>
/// Assumes type parameters have already been pushed
/// </summary>
@@ -740,7 +740,7 @@ namespace Microsoft.Dafny {
}
scope.PopMarker();
}
-
+
/// <summary>
/// Assumes type parameters have already been pushed
/// </summary>
@@ -754,7 +754,7 @@ namespace Microsoft.Dafny {
foreach (Formal p in m.Ins) {
scope.Push(p.Name, p);
}
-
+
// Start resolving specification...
foreach (MaybeFreeExpression e in m.Req) {
ResolveExpression(e.E, false);
@@ -770,7 +770,7 @@ namespace Microsoft.Dafny {
ResolveExpression(e, false);
// any type is fine
}
-
+
// Add out-parameters to a new scope that will also include the outermost-level locals of the body
// Don't care about any duplication errors among the out-parameters, since they have already been reported
scope.PushMarker();
@@ -786,16 +786,16 @@ namespace Microsoft.Dafny {
Error(e.E, "Postcondition must be a boolean (got {0})", e.E.Type);
}
}
-
+
// Resolve body
if (m.Body != null) {
ResolveBlockStatement(m.Body, m.IsGhost, m);
}
-
+
scope.PopMarker(); // for the out-parameters and outermost-level locals
scope.PopMarker(); // for the in-parameters
}
-
+
void ResolveCtorSignature(DatatypeCtor ctor) {
Contract.Requires(ctor != null);
foreach (Formal p in ctor.Formals) {
@@ -839,18 +839,18 @@ namespace Microsoft.Dafny {
Error(t.tok, "Wrong number of type arguments ({0} instead of {1}) passed to class/datatype: {2}", t.TypeArgs.Count, d.TypeArgs.Count, t.Name);
}
}
-
+
} else if (type is TypeProxy) {
TypeProxy t = (TypeProxy)type;
if (t.T != null) {
ResolveType(tok, t.T);
}
-
+
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type
}
}
-
+
public bool UnifyTypes(Type a, Type b) {
Contract.Requires(a != null);
Contract.Requires(b != null);
@@ -866,7 +866,7 @@ namespace Microsoft.Dafny {
a = proxy.T;
}
}
-
+
while (b is TypeProxy) {
TypeProxy proxy = (TypeProxy)b;
if (proxy.T == null) {
@@ -876,7 +876,7 @@ namespace Microsoft.Dafny {
b = proxy.T;
}
}
-
+
#if !NO_CHEAP_OBJECT_WORKAROUND
if (a is ObjectType || b is ObjectType) { // TODO: remove this temporary hack
var other = a is ObjectType ? b : a;
@@ -888,7 +888,7 @@ namespace Microsoft.Dafny {
}
#endif
// Now, a and b are non-proxies and stand for the same things as the original a and b, respectively.
-
+
if (a is BoolType) {
return b is BoolType;
} else if (a is IntType) {
@@ -923,12 +923,12 @@ namespace Microsoft.Dafny {
// something is wrong; either aa or bb wasn't properly resolved, or they don't unify
return false;
}
-
+
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type
}
}
-
+
bool AssignProxy(TypeProxy proxy, Type t){
Contract.Requires(proxy != null);
Contract.Requires(t != null);
@@ -939,15 +939,15 @@ namespace Microsoft.Dafny {
if (proxy == t) {
// they are already in the same equivalence class
return true;
-
+
} else if (proxy is UnrestrictedTypeProxy) {
// it's fine to redirect proxy to t (done below)
-
+
} else if (t is UnrestrictedTypeProxy) {
// merge proxy and t by redirecting t to proxy, rather than the other way around
((TypeProxy)t).T = proxy;
return true;
-
+
} else if (t is RestrictedTypeProxy) {
// Both proxy and t are restricted type proxies. To simplify unification, order proxy and t
// according to their types.
@@ -958,7 +958,7 @@ namespace Microsoft.Dafny {
} else {
return AssignRestrictedProxies(r1, r0);
}
-
+
// In the remaining cases, proxy is a restricted proxy and t is a non-proxy
} else if (proxy is DatatypeProxy) {
if (t.IsDatatype) {
@@ -966,14 +966,14 @@ namespace Microsoft.Dafny {
} else {
return false;
}
-
+
} else if (proxy is ObjectTypeProxy) {
if (t is ObjectType || UserDefinedType.DenotesClass(t) != null) {
// all is fine, proxy can be redirected to t
} else {
return false;
}
-
+
} else if (proxy is ObjectsTypeProxy) {
if (t is ObjectType || UserDefinedType.DenotesClass(t) != null) {
// all is good
@@ -981,7 +981,7 @@ namespace Microsoft.Dafny {
proxy.T = new CollectionTypeProxy(new ObjectTypeProxy());
return UnifyTypes(proxy.T, t);
}
-
+
} else if (proxy is CollectionTypeProxy) {
CollectionTypeProxy collProxy = (CollectionTypeProxy)proxy;
if (t is CollectionType) {
@@ -991,7 +991,7 @@ namespace Microsoft.Dafny {
} else {
return false;
}
-
+
} else if (proxy is OperationTypeProxy) {
OperationTypeProxy opProxy = (OperationTypeProxy)proxy;
if (t is IntType || t is SetType || (opProxy.AllowSeq && t is SeqType)) {
@@ -1014,11 +1014,11 @@ namespace Microsoft.Dafny {
} else {
return false;
}
-
+
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected proxy type
}
-
+
// do the merge, but never infer a subrange type
if (t is NatType) {
proxy.T = Type.Int;
@@ -1027,7 +1027,7 @@ namespace Microsoft.Dafny {
}
return true;
}
-
+
bool AssignRestrictedProxies(RestrictedTypeProxy a, RestrictedTypeProxy b)
{ Contract.Requires(a != null);
Contract.Requires(b != null);
@@ -1036,7 +1036,7 @@ namespace Microsoft.Dafny {
Contract.Requires(a.OrderID <= b.OrderID);
//modifies a.T, b.T;
Contract.Ensures(Contract.Result<bool>() || a.T != null || b.T != null);
-
+
if (a is DatatypeProxy) {
if (b is DatatypeProxy) {
// all is fine
@@ -1062,7 +1062,7 @@ namespace Microsoft.Dafny {
} else {
return false;
}
-
+
} else if (a is ObjectsTypeProxy) {
if (b is ObjectsTypeProxy) {
// fine
@@ -1093,7 +1093,7 @@ namespace Microsoft.Dafny {
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected restricted-proxy type
}
-
+
} else if (a is CollectionTypeProxy) {
if (b is CollectionTypeProxy) {
a.T = b;
@@ -1117,7 +1117,7 @@ namespace Microsoft.Dafny {
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected restricted-proxy type
}
-
+
} else if (a is OperationTypeProxy) {
OperationTypeProxy pa = (OperationTypeProxy)a;
if (b is OperationTypeProxy) {
@@ -1138,12 +1138,12 @@ namespace Microsoft.Dafny {
return false;
}
}
-
+
} else if (a is IndexableTypeProxy) {
Contract.Assert(b is IndexableTypeProxy); // else we have unexpected restricted-proxy type
a.T = b;
return UnifyTypes(((IndexableTypeProxy)a).Arg, ((IndexableTypeProxy)b).Arg);
-
+
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected restricted-proxy type
}
@@ -1164,14 +1164,14 @@ namespace Microsoft.Dafny {
if (!UnifyTypes(s.Expr.Type, Type.Bool)) {
Error(s.Expr, "condition is expected to be of type {0}, but is {1}", Type.Bool, s.Expr.Type);
}
-
+
} else if (stmt is PrintStmt) {
PrintStmt s = (PrintStmt)stmt;
ResolveAttributeArgs(s.Args, false);
if (specContextOnly) {
Error(stmt, "print statement is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)");
}
-
+
} else if (stmt is BreakStmt) {
var s = (BreakStmt)stmt;
if (s.TargetLabel != null) {
@@ -1322,7 +1322,7 @@ namespace Microsoft.Dafny {
} else {
Error(stmt, "LHS of assignment must denote a mutable variable or field");
}
-
+
s.IsGhost = lvalueIsGhost;
Type lhsType = s.Lhs.Type;
if (lhs is SeqSelectExpr && !((SeqSelectExpr)lhs).SelectOne) {
@@ -1362,7 +1362,7 @@ namespace Microsoft.Dafny {
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected RHS
}
-
+
} else if (stmt is VarDecl) {
VarDecl s = (VarDecl)stmt;
if (s.OptionalType != null) {
@@ -1377,16 +1377,16 @@ namespace Microsoft.Dafny {
// a local variable in a specification-only context might as well be ghost
s.IsGhost = true;
}
-
+
} else if (stmt is CallStmt) {
CallStmt s = (CallStmt)stmt;
ResolveCallStmt(s, specContextOnly, method, null);
-
+
} else if (stmt is BlockStmt) {
scope.PushMarker();
ResolveBlockStatement((BlockStmt)stmt, specContextOnly, method);
scope.PopMarker();
-
+
} else if (stmt is IfStmt) {
IfStmt s = (IfStmt)stmt;
bool branchesAreSpecOnly = specContextOnly;
@@ -1480,20 +1480,20 @@ namespace Microsoft.Dafny {
if (!UnifyTypes(s.Collection.Type, new CollectionTypeProxy(s.BoundVar.Type))) {
Error(s.Collection, "The type is expected to be a collection of {0} (instead got {1})", s.BoundVar.Type, s.Collection.Type);
}
-
+
scope.PushMarker();
bool b = scope.Push(s.BoundVar.Name, s.BoundVar);
Contract.Assert(b); // since we just pushed a marker, we expect the Push to succeed
ResolveType(s.BoundVar.tok, s.BoundVar.Type);
int prevErrorCount = ErrorCount;
-
+
ResolveExpression(s.Range, true);
Contract.Assert(s.Range.Type != null); // follows from postcondition of ResolveExpression
if (!UnifyTypes(s.Range.Type, Type.Bool)) {
Error(s.Range, "range condition is expected to be of type {0}, but is {1}", Type.Bool, s.Range.Type);
}
bool successfullyResolvedCollectionAndRange = ErrorCount == prevErrorCount;
-
+
foreach (PredicateStmt ss in s.BodyPrefix) {
ResolveStatement(ss, specContextOnly, method);
}
@@ -1527,7 +1527,7 @@ namespace Microsoft.Dafny {
}
scope.PopMarker();
-
+
} else if (stmt is MatchStmt) {
MatchStmt s = (MatchStmt)stmt;
bool bodyIsSpecOnly = specContextOnly;
@@ -1553,14 +1553,14 @@ namespace Microsoft.Dafny {
Contract.Assert(sourceType != null); // dtd and sourceType are set together above
ctors = datatypeCtors[dtd];
Contract.Assert(ctors != null); // dtd should have been inserted into datatypeCtors during a previous resolution stage
-
+
// build the type-parameter substitution map for this use of the datatype
for (int i = 0; i < dtd.TypeArgs.Count; i++) {
subst.Add(dtd.TypeArgs[i], sourceType.TypeArgs[i]);
}
}
s.IsGhost = bodyIsSpecOnly;
-
+
Dictionary<string,object> memberNamesUsed = new Dictionary<string,object>(); // this is really a set
foreach (MatchCaseStmt mc in s.Cases) {
DatatypeCtor ctor = null;
@@ -1615,8 +1615,8 @@ namespace Microsoft.Dafny {
}
Contract.Assert(memberNamesUsed.Count + s.MissingCases.Count == dtd.Ctors.Count);
}
-
-
+
+
} else {
Contract.Assert(false); throw new cce.UnreachableException();
}
@@ -2183,7 +2183,7 @@ namespace Microsoft.Dafny {
}
/// <summary>
- /// "matchVarContext" says which variables are allowed to be used as the source expression in a "match" expression;
+ /// "matchVarContext" says which variables are allowed to be used as the source expression in a "match" expression;
/// if null, no "match" expression will be allowed.
/// </summary>
void ResolveExpression(Expression expr, bool twoState, List<IVariable> matchVarContext) {
@@ -2194,7 +2194,7 @@ namespace Microsoft.Dafny {
// expression has already been resovled
return;
}
-
+
// The following cases will resolve the subexpressions and will attempt to assign a type of expr. However, if errors occur
// and it cannot be determined what the type of expr is, then it is fine to leave expr.Type as null. In that case, the end
// of this method will assign proxy type to the expression, which reduces the number of error messages that are produced
@@ -2227,13 +2227,13 @@ namespace Microsoft.Dafny {
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected literal type
}
-
+
} else if (expr is ThisExpr) {
if (!scope.AllowInstance) {
Error(expr, "'this' is not allowed in a 'static' context");
}
expr.Type = GetThisType(expr.tok, currentClass); // do this regardless of scope.AllowInstance, for better error reporting
-
+
} else if (expr is IdentifierExpr) {
IdentifierExpr e = (IdentifierExpr)expr;
e.Var = scope.Find(e.Name);
@@ -2242,7 +2242,7 @@ namespace Microsoft.Dafny {
} else {
expr.Type = e.Var.Type;
}
-
+
} else if (expr is DatatypeValue) {
DatatypeValue dtv = (DatatypeValue)expr;
TopLevelDecl d;
@@ -2263,7 +2263,7 @@ namespace Microsoft.Dafny {
}
expr.Type = new UserDefinedType(dtv.tok, dtv.DatatypeName, gt);
ResolveType(expr.tok, expr.Type);
-
+
DatatypeCtor ctor;
if (!datatypeCtors[dt].TryGetValue(dtv.MemberName, out ctor)) {
Error(expr.tok, "undeclared constructor {0} in datatype {1}", dtv.MemberName, dtv.DatatypeName);
@@ -2288,7 +2288,7 @@ namespace Microsoft.Dafny {
j++;
}
}
-
+
} else if (expr is DisplayExpression) {
DisplayExpression e = (DisplayExpression)expr;
Type elementType = new InferredTypeProxy();
@@ -2304,7 +2304,7 @@ namespace Microsoft.Dafny {
} else {
expr.Type = new SeqType(elementType);
}
-
+
} else if (expr is FieldSelectExpr) {
var e = (FieldSelectExpr)expr;
ResolveExpression(e.Obj, twoState);
@@ -2331,7 +2331,7 @@ namespace Microsoft.Dafny {
}
e.Type = SubstType(e.Field.Type, subst);
}
-
+
} else if (expr is SeqSelectExpr) {
SeqSelectExpr e = (SeqSelectExpr)expr;
ResolveSeqSelectExpr(e, twoState, false);
@@ -2380,11 +2380,11 @@ namespace Microsoft.Dafny {
if (!seqErr) {
expr.Type = e.Seq.Type;
}
-
+
} else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
ResolveFunctionCallExpr(e, twoState, false);
-
+
} else if (expr is OldExpr) {
OldExpr e = (OldExpr)expr;
if (!twoState) {
@@ -2392,7 +2392,7 @@ namespace Microsoft.Dafny {
}
ResolveExpression(e.E, twoState);
expr.Type = e.E.Type;
-
+
} else if (expr is FreshExpr) {
FreshExpr e = (FreshExpr)expr;
if (!twoState) {
@@ -2447,7 +2447,7 @@ namespace Microsoft.Dafny {
default:
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected unary operator
}
-
+
} else if (expr is BinaryExpr) {
BinaryExpr e = (BinaryExpr)expr;
ResolveExpression(e.E0, twoState);
@@ -2467,7 +2467,7 @@ namespace Microsoft.Dafny {
}
expr.Type = Type.Bool;
break;
-
+
case BinaryExpr.Opcode.Eq:
case BinaryExpr.Opcode.Neq:
if (!UnifyTypes(e.E0.Type, e.E1.Type)) {
@@ -2475,7 +2475,7 @@ namespace Microsoft.Dafny {
}
expr.Type = Type.Bool;
break;
-
+
case BinaryExpr.Opcode.Disjoint:
if (!UnifyTypes(e.E0.Type, new SetType(new InferredTypeProxy()))) {
Error(expr, "arguments must be of a set type (got {0})", e.E0.Type);
@@ -2485,7 +2485,7 @@ namespace Microsoft.Dafny {
}
expr.Type = Type.Bool;
break;
-
+
case BinaryExpr.Opcode.Lt:
case BinaryExpr.Opcode.Le:
case BinaryExpr.Opcode.Add:
@@ -2513,7 +2513,7 @@ namespace Microsoft.Dafny {
}
}
break;
-
+
case BinaryExpr.Opcode.Sub:
case BinaryExpr.Opcode.Mul:
case BinaryExpr.Opcode.Gt:
@@ -2550,7 +2550,7 @@ namespace Microsoft.Dafny {
}
expr.Type = Type.Bool;
break;
-
+
case BinaryExpr.Opcode.Div:
case BinaryExpr.Opcode.Mod:
if (!UnifyTypes(e.E0.Type, Type.Int)) {
@@ -2561,12 +2561,12 @@ namespace Microsoft.Dafny {
}
expr.Type = Type.Int;
break;
-
+
default:
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected operator
}
e.ResolvedOp = ResolveOp(e.Op, e.E1.Type);
-
+
} else if (expr is QuantifierExpr) {
QuantifierExpr e = (QuantifierExpr)expr;
int prevErrorCount = ErrorCount;
@@ -2639,7 +2639,7 @@ namespace Microsoft.Dafny {
} else if (expr is WildcardExpr) {
expr.Type = new SetType(new ObjectType());
-
+
} else if (expr is ITEExpr) {
ITEExpr e = (ITEExpr)expr;
ResolveExpression(e.Test, twoState);
@@ -2656,7 +2656,7 @@ namespace Microsoft.Dafny {
} else {
Error(expr, "the two branches of an if-then-else expression must have the same type (got {0} and {1})", e.Thn.Type, e.Els.Type);
}
-
+
} else if (expr is MatchExpr) {
MatchExpr me = (MatchExpr)expr;
Contract.Assert(!twoState); // currently, match expressions are allowed only at the outermost level of function bodies
@@ -2682,7 +2682,7 @@ namespace Microsoft.Dafny {
Contract.Assert(sourceType != null); // dtd and sourceType are set together above
ctors = datatypeCtors[dtd];
Contract.Assert(ctors != null); // dtd should have been inserted into datatypeCtors during a previous resolution stage
-
+
IdentifierExpr ie = me.Source.Resolved as IdentifierExpr;
if (ie == null || !(ie.Var is Formal || ie.Var is BoundVar)) {
Error(me.Source.tok, "match source expression must be a formal parameter of the enclosing function or an enclosing match expression");
@@ -2691,13 +2691,13 @@ namespace Microsoft.Dafny {
} else {
goodMatchVariable = ie.Var;
}
-
+
// build the type-parameter substitution map for this use of the datatype
for (int i = 0; i < dtd.TypeArgs.Count; i++) {
subst.Add(dtd.TypeArgs[i], sourceType.TypeArgs[i]);
}
}
-
+
Dictionary<string,object> memberNamesUsed = new Dictionary<string,object>(); // this is really a set
expr.Type = new InferredTypeProxy();
foreach (MatchCaseExpr mc in me.Cases) {
@@ -2760,7 +2760,7 @@ namespace Microsoft.Dafny {
}
Contract.Assert(memberNamesUsed.Count + me.MissingCases.Count == dtd.Ctors.Count);
}
-
+
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected expression
}
@@ -3479,13 +3479,13 @@ namespace Microsoft.Dafny {
return s == null ? new HashSet<IVariable>() : s;
}
}
-
+
void ResolveReceiver(Expression expr, bool twoState)
{
Contract.Requires(expr != null);
Contract.Requires(currentClass != null);
Contract.Ensures(expr.Type != null);
-
+
if (expr is ThisExpr) {
// Allow 'this' here, regardless of scope.AllowInstance. The caller is responsible for
// making sure 'this' does not really get used when it's not available.
@@ -3494,7 +3494,7 @@ namespace Microsoft.Dafny {
ResolveExpression(expr, twoState);
}
}
-
+
void ResolveSeqSelectExpr(SeqSelectExpr e, bool twoState, bool allowNonUnitArraySelection) {
Contract.Requires(e != null);
if (e.Type != null) {
@@ -3538,7 +3538,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
/// <summary>
/// Note: this method is allowed to be called even if "type" does not make sense for "op", as might be the case if
/// resolution of the binary expression failed. If so, an arbitrary resolved opcode is returned.
@@ -3647,7 +3647,7 @@ namespace Microsoft.Dafny {
{
Contract.Requires(expr != null);
Contract.Requires(currentClass != null);
-
+
if (expr is LiteralExpr) {
return false;
} else if (expr is ThisExpr) {
@@ -3723,7 +3723,7 @@ namespace Microsoft.Dafny {
[Rep] readonly List<string> names = new List<string>(); // a null means a marker
[Rep] readonly List<Thing> things = new List<Thing>();
[ContractInvariantMethod]
- void ObjectInvariant()
+ void ObjectInvariant()
{
Contract.Invariant(names != null);
Contract.Invariant(things != null);
@@ -3732,7 +3732,7 @@ namespace Microsoft.Dafny {
}
int scopeSizeWhereInstancesWereDisallowed = -1;
-
+
public bool AllowInstance {
get { return scopeSizeWhereInstancesWereDisallowed == -1; }
set
@@ -3745,7 +3745,7 @@ namespace Microsoft.Dafny {
names.Add(null);
things.Add(null);
}
-
+
public void PopMarker() {
int n = names.Count;
while (true) {
@@ -3760,7 +3760,7 @@ namespace Microsoft.Dafny {
scopeSizeWhereInstancesWereDisallowed = -1;
}
}
-
+
// Pushes name-->thing association and returns "true", if name has not already been pushed since the last marker.
// If name already has been pushed since the last marker, does nothing and returns "false".
public bool Push(string name, Thing thing) {
@@ -3774,7 +3774,7 @@ namespace Microsoft.Dafny {
return true;
}
}
-
+
Thing Find(string name, bool topScopeOnly) {
Contract.Requires(name != null);
for (int n = names.Count; 0 <= --n; ) {
@@ -3790,7 +3790,7 @@ namespace Microsoft.Dafny {
}
return null; // not present
}
-
+
public Thing Find(string name) {
Contract.Requires(name != null);
return Find(name, false);
diff --git a/Source/Dafny/Scanner.cs b/Source/Dafny/Scanner.cs
index 81f556c8..37c08ddc 100644
--- a/Source/Dafny/Scanner.cs
+++ b/Source/Dafny/Scanner.cs
@@ -232,6 +232,7 @@ public class Scanner {
Token/*!*/ t; // current token
int ch; // current input character
int pos; // byte position of current character
+ int charPos;
int col; // column number of current character
int line; // line number of current character
int oldEols; // EOLs that appeared in a comment;
@@ -439,7 +440,7 @@ public class Scanner {
bool Comment0() {
- int level = 1, pos0 = pos, line0 = line, col0 = col;
+ int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
NextCh();
if (ch == '/') {
NextCh();
@@ -452,13 +453,13 @@ public class Scanner {
else NextCh();
}
} else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0;
+ buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
}
return false;
}
bool Comment1() {
- int level = 1, pos0 = pos, line0 = line, col0 = col;
+ int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
NextCh();
if (ch == '*') {
NextCh();
@@ -479,7 +480,7 @@ public class Scanner {
else NextCh();
}
} else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0;
+ buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
}
return false;
}
diff --git a/Source/Dafny/SccGraph.cs b/Source/Dafny/SccGraph.cs
index 9f4b22c5..4ae1c185 100644
--- a/Source/Dafny/SccGraph.cs
+++ b/Source/Dafny/SccGraph.cs
@@ -12,14 +12,14 @@ namespace Microsoft.Dafny {
public readonly List<Vertex/*!*/>/*!*/ Successors = new List<Vertex/*!*/>();
public List<Vertex/*!*/> SccMembers; // non-null only for the representative of the SCC
[ContractInvariantMethod]
- void ObjectInvariant()
+ void ObjectInvariant()
{
Contract.Invariant(cce.NonNullElements(Successors));
Contract.Invariant(SccMembers==null || cce.NonNullElements(SccMembers));
}
public Vertex SccRepresentative; // null if not computed
-
+
public int SccId; // valid only for SCC representatives; indicates position of this representative vertex in the graph's topological sort
// the following field is used during the computation of SCCs and of reachability
public VisitedStatus Visited;
@@ -28,7 +28,7 @@ namespace Microsoft.Dafny {
public int LowLink;
// the following field is used during a Reaches computation
public int Gen; // generation <= Gen means this vertex has been visited in the current generation
-
+
public Vertex(Node n) {
N = n;
}
@@ -40,7 +40,7 @@ namespace Microsoft.Dafny {
[ContractInvariantMethod]
- void ObjectInvariant()
+ void ObjectInvariant()
{
Contract.Invariant(vertices!=null);
Contract.Invariant(cce.NonNullElements(vertices.Values));
@@ -51,7 +51,7 @@ namespace Microsoft.Dafny {
Dictionary<Node, Vertex/*!*/>/*!*/ vertices = new Dictionary<Node, Vertex/*!*/>();
bool sccComputed = false;
List<Vertex/*!*/> topologicallySortedRepresentatives; // computed by the SCC computation
-
+
public int SccCount {
get {
ComputeSCCs();
@@ -60,11 +60,11 @@ namespace Microsoft.Dafny {
}
}
int generation = 0;
-
+
public Graph()
{
}
-
+
/// <summary>
/// Idempotently adds a vertex 'n' to the graph.
/// </summary>
@@ -74,7 +74,7 @@ namespace Microsoft.Dafny {
/// <summary>
/// Idempotently adds a vertex 'n' to the graph and then returns the Vertex for it.
- /// </summary>
+ /// </summary>
Vertex GetVertex(Node n) {
Contract.Ensures(Contract.Result<Vertex>() != null);
@@ -93,7 +93,7 @@ namespace Microsoft.Dafny {
}
return v;
}
-
+
/// <summary>
/// Returns the vertex for 'n' if 'n' is in the graph. Otherwise, returns null.
/// </summary>
@@ -117,7 +117,7 @@ namespace Microsoft.Dafny {
v0.AddSuccessor(v1);
sccComputed = false; // the addition of an edge may invalidate any previous computation of the graph's SCCs
}
-
+
/// <summary>
/// Idempotently adds 'n' as a vertex and then returns a Node that is the representative element of the
/// strongly connected component containing 'n'.
@@ -125,7 +125,7 @@ namespace Microsoft.Dafny {
public Node GetSCCRepresentative(Node n) {
return GetSCCRepr(n).N;
}
-
+
/// <summary>
/// Idempotently adds 'n' as a vertex. Then, returns the number of SCCs before the SCC of 'n' in the
/// topologically sorting of SCCs.
@@ -133,7 +133,7 @@ namespace Microsoft.Dafny {
public int GetSCCRepresentativeId(Node n) {
return GetSCCRepr(n).SccId;
}
-
+
Vertex GetSCCRepr(Node n) {
Contract.Ensures(Contract.Result<Vertex>() != null);
@@ -142,7 +142,7 @@ namespace Microsoft.Dafny {
Contract.Assert(v.SccRepresentative != null); // follows from what ComputeSCCs does
return v.SccRepresentative;
}
-
+
/// <summary>
/// Returns a list of the topologically sorted SCCs, each represented in the list by its representative node.
/// </summary>
@@ -172,21 +172,21 @@ namespace Microsoft.Dafny {
}
return nn;
}
-
+
/// <summary>
/// Idempotently adds 'n' as a vertex and then returns the size of the set of Node's in the strongly connected component
/// that contains 'n'.
/// </summary>
public int GetSCCSize(Node n){
Contract.Ensures(1 <= Contract.Result<int>());
-
+
Vertex v = GetVertex(n);
ComputeSCCs();
Vertex repr = v.SccRepresentative;
Contract.Assert(repr != null && repr.SccMembers != null); // follows from postcondition of ComputeSCCs
return repr.SccMembers.Count;
}
-
+
/// <summary>
/// This method sets the SccRepresentative fields of the graph's vertices so that two
/// vertices have the same representative iff they are in the same strongly connected
@@ -197,7 +197,7 @@ namespace Microsoft.Dafny {
void ComputeSCCs()
{
Contract.Ensures(sccComputed);
-
+
if (sccComputed) { return; } // check if already computed
// reset all SCC information
@@ -217,7 +217,7 @@ namespace Microsoft.Dafny {
sccComputed = true;
}
-
+
/// <summary>
/// This is the 'SearchC' procedure from the Aho, Hopcroft, and Ullman book 'The Design and Analysis of Computer Algorithms'.
/// </summary>
@@ -227,13 +227,13 @@ namespace Microsoft.Dafny {
Contract.Requires(v.Visited == VisitedStatus.Unvisited);
Contract.Requires(topologicallySortedRepresentatives != null);
Contract.Ensures(v.Visited != VisitedStatus.Unvisited);
-
+
v.DfNumber = cnt;
cnt++;
v.LowLink = v.DfNumber;
stack.Push(v);
v.Visited = VisitedStatus.OnStack;
-
+
foreach (Vertex w in v.Successors) {
if (w.Visited == VisitedStatus.Unvisited) {
SearchC(w, stack, ref cnt);
@@ -243,7 +243,7 @@ namespace Microsoft.Dafny {
v.LowLink = Math.Min(v.LowLink, w.DfNumber);
}
}
-
+
if (v.LowLink == v.DfNumber) {
// The SCC containing 'v' has now been computed.
v.SccId = topologicallySortedRepresentatives.Count;
@@ -258,7 +258,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
/// <summary>
/// Returns null if the graph has no cycles. If the graph does contain some cycle, returns the list of
/// vertices on one such cycle.
@@ -268,7 +268,7 @@ namespace Microsoft.Dafny {
foreach (Vertex v in vertices.Values) {
v.Visited = VisitedStatus.Unvisited;
}
-
+
foreach (Vertex v in vertices.Values) {
Contract.Assert(v.Visited != VisitedStatus.OnStack);
if (v.Visited == VisitedStatus.Unvisited) {
@@ -284,7 +284,7 @@ namespace Microsoft.Dafny {
}
return null; // there are no cycles
}
-
+
/// <summary>
/// A return of null means there are no cycles involving any vertex in the subtree rooted at v.
/// A non-null return means a cycle has been found. Then:
@@ -300,7 +300,7 @@ namespace Microsoft.Dafny {
Contract.Ensures(v.Visited != VisitedStatus.Unvisited);
Contract.Ensures(Contract.Result<List<Vertex>>() != null || v.Visited == VisitedStatus.Visited);
Contract.Ensures(Contract.Result<List<Vertex>>() == null || Contract.Result<List<Vertex>>().Count != 0);
-
+
v.Visited = VisitedStatus.OnStack;
foreach (Vertex succ in v.Successors) {
// todo: I would use a 'switch' statement, but there seems to be a bug in the Spec# compiler's type checking.
@@ -337,7 +337,7 @@ namespace Microsoft.Dafny {
v.Visited = VisitedStatus.Visited; // there are no cycles from here on
return null;
}
-
+
/// <summary>
/// Returns whether or not 'source' reaches 'sink' in the graph.
/// 'source' and 'sink' need not be in the graph; if neither is, the return value
@@ -352,7 +352,7 @@ namespace Microsoft.Dafny {
generation++;
return ReachSearch(a, b);
}
-
+
bool ReachSearch(Vertex source, Vertex sink) {
Contract.Requires(source != null);
Contract.Requires(sink != null);
diff --git a/Source/Dafny/Translator.cs b/Source/Dafny/Translator.cs
index d1c77122..74d33479 100644
--- a/Source/Dafny/Translator.cs
+++ b/Source/Dafny/Translator.cs
@@ -21,14 +21,14 @@ namespace Microsoft.Dafny {
predef = FindPredefinedDecls(boogieProgram);
}
}
-
+
// translation state
readonly Dictionary<TopLevelDecl/*!*/,Bpl.Constant/*!*/>/*!*/ classes = new Dictionary<TopLevelDecl/*!*/,Bpl.Constant/*!*/>();
readonly Dictionary<Field/*!*/,Bpl.Constant/*!*/>/*!*/ fields = new Dictionary<Field/*!*/,Bpl.Constant/*!*/>();
readonly Dictionary<Field/*!*/, Bpl.Function/*!*/>/*!*/ fieldFunctions = new Dictionary<Field/*!*/, Bpl.Function/*!*/>();
[ContractInvariantMethod]
- void ObjectInvariant()
+ void ObjectInvariant()
{
Contract.Invariant(cce.NonNullDictionaryAndValues(classes));
Contract.Invariant(cce.NonNullDictionaryAndValues(fields));
@@ -77,14 +77,14 @@ namespace Microsoft.Dafny {
return new Bpl.TypeSynonymAnnotation(Token.NoToken, setTypeCtor, new Bpl.TypeSeq(ty));
}
-
+
public Bpl.Type SeqType(IToken tok, Bpl.Type ty) {
Contract.Requires(tok != null);
Contract.Requires(ty != null);
Contract.Ensures(Contract.Result<Bpl.Type>() != null);
return new Bpl.CtorType(Token.NoToken, seqTypeCtor, new Bpl.TypeSeq(ty));
}
-
+
public Bpl.Type FieldName(IToken tok, Bpl.Type ty) {
Contract.Requires(tok != null);
Contract.Requires(ty != null);
@@ -92,7 +92,7 @@ namespace Microsoft.Dafny {
return new Bpl.CtorType(tok, fieldName, new Bpl.TypeSeq(ty));
}
-
+
public Bpl.IdentifierExpr Alloc(IToken tok) {
Contract.Requires(tok != null);
Contract.Ensures(Contract.Result<Bpl.IdentifierExpr>() != null);
@@ -135,14 +135,14 @@ namespace Microsoft.Dafny {
this.Null = new Bpl.IdentifierExpr(Token.NoToken, "null", refT);
}
}
-
+
static PredefinedDecls FindPredefinedDecls(Bpl.Program prog) {
Contract.Requires(prog != null);
if (prog.Resolve() != 0) {
Console.WriteLine("Error: resolution errors encountered in Dafny prelude");
return null;
}
-
+
Bpl.TypeCtorDecl refType = null;
Bpl.TypeSynonymDecl setTypeCtor = null;
Bpl.TypeCtorDecl seqTypeCtor = null;
@@ -220,7 +220,7 @@ namespace Microsoft.Dafny {
}
return null;
}
-
+
static Bpl.Program ReadPrelude() {
string preludePath = Bpl.CommandLineOptions.Clo.DafnyPrelude;
if (preludePath == null)
@@ -229,7 +229,7 @@ namespace Microsoft.Dafny {
string codebase = cce.NonNull(System.IO.Path.GetDirectoryName(cce.NonNull(System.Reflection.Assembly.GetExecutingAssembly().Location)));
preludePath = System.IO.Path.Combine(codebase, "DafnyPrelude.bpl");
}
-
+
Bpl.Program prelude;
int errorCount = Bpl.Parser.Parse(preludePath, null, out prelude);
if (prelude == null || errorCount > 0) {
@@ -237,7 +237,7 @@ namespace Microsoft.Dafny {
} else {
return prelude;
}
-/*
+/*
List<string!> defines = new List<string!>();
using (System.IO.Stream stream = new System.IO.FileStream(preludePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
@@ -251,9 +251,9 @@ namespace Microsoft.Dafny {
return prelude;
}
}
-*/
+*/
}
-
+
public Bpl.Program Translate(Program program) {
Contract.Requires(program != null);
Contract.Ensures(Contract.Result<Bpl.Program>() != null);
@@ -282,13 +282,13 @@ namespace Microsoft.Dafny {
}
return sink;
}
-
+
void AddDatatype(DatatypeDecl dt)
{
Contract.Requires(dt != null);
Contract.Requires(sink != null && predef != null);
sink.TopLevelDeclarations.Add(GetClass(dt));
-
+
foreach (DatatypeCtor ctor in dt.Ctors) {
// Add: function #dt.ctor(paramTypes) returns (DatatypeType);
Bpl.VariableSeq argTypes = new Bpl.VariableSeq();
@@ -348,7 +348,7 @@ namespace Microsoft.Dafny {
fn.Body = Bpl.Expr.Eq(lhs, new Bpl.IdentifierExpr(ctor.tok, cid)); // this uses the "cid" defined for the previous axiom
sink.TopLevelDeclarations.Add(fn);
- // Add: axiom (forall params, h: HeapType ::
+ // Add: axiom (forall params, h: HeapType ::
// { DtAlloc(#dt.ctor(params), h) }
// $IsGoodHeap(h) ==>
// (DtAlloc(#dt.ctor(params), h) <==> ...each param has its expected type...));
@@ -440,7 +440,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
void CreateBoundVariables(List<Formal/*!*/>/*!*/ formals, out Bpl.VariableSeq/*!*/ bvs, out List<Bpl.Expr/*!*/>/*!*/ args)
{
Contract.Requires(formals != null);
@@ -459,13 +459,13 @@ namespace Microsoft.Dafny {
args.Add(new Bpl.IdentifierExpr(arg.tok, bv));
}
}
-
+
void AddClassMembers(ClassDecl c)
{
Contract.Requires(sink != null && predef != null);
Contract.Requires(c != null);
sink.TopLevelDeclarations.Add(GetClass(c));
-
+
foreach (MemberDecl member in c.Members) {
if (member is Field) {
Field f = (Field)member;
@@ -478,7 +478,7 @@ namespace Microsoft.Dafny {
}
AddAllocationAxiom(f);
-
+
} else if (member is Function) {
Function f = (Function)member;
AddFunction(f);
@@ -500,7 +500,7 @@ namespace Microsoft.Dafny {
}
AddFrameAxiom(f);
AddWellformednessCheck(f);
-
+
} else if (member is Method) {
Method m = (Method)member;
// wellformedness check for method specification
@@ -514,14 +514,14 @@ namespace Microsoft.Dafny {
// ...and its implementation
AddMethodImpl(m, proc, false);
}
-
+
// refinement condition
if (member is MethodRefinement) {
AddMethodRefinement((MethodRefinement)member);
}
-
+
} else if (member is CouplingInvariant) {
- // TODO: define a well-foundedness condition to check
+ // TODO: define a well-foundedness condition to check
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected member
@@ -616,9 +616,9 @@ namespace Microsoft.Dafny {
Contract.Requires(layerOffset == 0 || (layerOffset == 1 && f.IsRecursive && !f.IsUnlimited));
Contract.Requires(predef != null);
Contract.Requires(f.EnclosingClass != null);
-
+
ExpressionTranslator etran = new ExpressionTranslator(this, predef, f.tok);
-
+
// axiom
// mh < ModuleContextHeight ||
// (mh == ModuleContextHeight && (fh <= FunctionContextHeight || InMethodContext))
@@ -659,7 +659,7 @@ namespace Microsoft.Dafny {
args.Add(new Bpl.IdentifierExpr(f.tok, bv));
// ante: $IsHeap($Heap) && this != null && formals-have-the-expected-types &&
Bpl.Expr ante = FunctionCall(f.tok, BuiltinFunction.IsGoodHeap, null, etran.HeapExpr);
-
+
Bpl.BoundVariable bvThis;
Bpl.Expr bvThisIdExpr;
if (f.IsStatic) {
@@ -711,7 +711,7 @@ namespace Microsoft.Dafny {
Bpl.Expr.Or(
Bpl.Expr.Le(Bpl.Expr.Literal(mod.CallGraph.GetSCCRepresentativeId(f)), etran.FunctionContextHeight()),
etran.InMethodContext())));
-
+
var substMap = new Dictionary<IVariable, Expression>();
if (specialization != null) {
substMap = specialization.SubstMap;
@@ -770,7 +770,7 @@ namespace Microsoft.Dafny {
}
return new Bpl.Axiom(f.tok, Bpl.Expr.Imp(activate, ax), comment);
}
-
+
void AddLimitedAxioms(Function f, int fromLayer) {
Contract.Requires(f != null);
Contract.Requires(f.IsRecursive && !f.IsUnlimited);
@@ -807,7 +807,7 @@ namespace Microsoft.Dafny {
Bpl.Expr origFuncAppl = new Bpl.NAryExpr(f.tok, origFuncID, args);
Bpl.FunctionCall limitedFuncID = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.tok, FunctionName(f, fromLayer-1), TrType(f.ResultType)));
Bpl.Expr limitedFuncAppl = new Bpl.NAryExpr(f.tok, limitedFuncID, args);
-
+
Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(f.TypeArgs);
Bpl.Trigger tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(origFuncAppl));
@@ -833,7 +833,7 @@ namespace Microsoft.Dafny {
}
return name;
}
-
+
/// <summary>
/// Generate:
/// axiom (forall h: [ref, Field x]x, o: ref ::
@@ -844,13 +844,13 @@ namespace Microsoft.Dafny {
{
Contract.Requires(f != null);
Contract.Requires(sink != null && predef != null);
-
+
Bpl.BoundVariable hVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$h", predef.HeapType));
Bpl.Expr h = new Bpl.IdentifierExpr(f.tok, hVar);
ExpressionTranslator etran = new ExpressionTranslator(this, predef, h);
Bpl.BoundVariable oVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$o", predef.RefType));
Bpl.Expr o = new Bpl.IdentifierExpr(f.tok, oVar);
-
+
// h[o,f]
Bpl.Expr oDotF;
if (f.IsMutable) {
@@ -894,7 +894,7 @@ namespace Microsoft.Dafny {
}
return Bpl.Expr.And(lower, upper);
}
-
+
Method currentMethod = null; // the method whose implementation is currently being translated
int loopHeapVarCount = 0;
int otherTmpVarCount = 0;
@@ -927,7 +927,7 @@ namespace Microsoft.Dafny {
return GetTmpVar_IdExpr(tok, "$prevHeap", predef.HeapType, locals);
}
-
+
Bpl.IdentifierExpr GetNewVar_IdExpr(IToken tok, Bpl.VariableSeq locals) // local variable that's shared between statements that need it
{
Contract.Requires(tok != null);
@@ -970,7 +970,7 @@ namespace Microsoft.Dafny {
Contract.Requires(wellformednessProc || m.Body != null);
Contract.Requires(currentMethod == null && loopHeapVarCount == 0 && _tmpIEs.Count == 0);
Contract.Ensures(currentMethod == null && loopHeapVarCount == 0 && _tmpIEs.Count == 0);
-
+
currentMethod = m;
Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(m.TypeArgs);
@@ -1032,7 +1032,7 @@ namespace Microsoft.Dafny {
typeParams, inParams, outParams,
localVariables, stmts);
sink.TopLevelDeclarations.Add(impl);
-
+
currentMethod = null;
loopHeapVarCount = 0;
otherTmpVarCount = 0;
@@ -1047,7 +1047,7 @@ namespace Microsoft.Dafny {
Contract.Requires(builder != null);
Contract.Requires(localVariables != null);
Contract.Requires(predef != null);
-
+
// set up the information used to verify the method's modifies clause
DefineFrame(m.tok, m.Mod, builder, localVariables, null);
}
@@ -1064,14 +1064,14 @@ namespace Microsoft.Dafny {
Contract.Ensures(Contract.Result<Bpl.Cmd>() != null);
return CaptureState(tok, null);
}
-
+
void DefineFrame(IToken/*!*/ tok, List<FrameExpression/*!*/>/*!*/ frameClause, Bpl.StmtListBuilder/*!*/ builder, Bpl.VariableSeq/*!*/ localVariables, string name){
Contract.Requires(tok != null);
Contract.Requires(cce.NonNullElements(frameClause));
Contract.Requires(builder != null);
Contract.Requires(cce.NonNullElements(localVariables));
Contract.Requires(predef != null);
-
+
ExpressionTranslator 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 of the $_Frame variable
@@ -1088,7 +1088,7 @@ namespace Microsoft.Dafny {
Bpl.Expr consequent = InRWClause(tok, o, f, frameClause, etran, null, null);
Bpl.Expr lambda = new Bpl.LambdaExpr(tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fVar), null,
Bpl.Expr.Imp(ante, consequent));
-
+
builder.Add(Bpl.Cmd.SimpleAssign(tok, new Bpl.IdentifierExpr(tok, frame), lambda));
}
@@ -1119,7 +1119,7 @@ namespace Microsoft.Dafny {
Bpl.Expr.Imp(Bpl.Expr.And(ante, oInCallee), inEnclosingFrame));
builder.Add(Assert(tok, q, errorMessage, kv));
}
-
+
/// <summary>
/// Generates:
/// axiom (forall h0: HeapType, h1: HeapType, formals... ::
@@ -1141,18 +1141,18 @@ namespace Microsoft.Dafny {
{
Contract.Requires(f != null);
Contract.Requires(sink != null && predef != null);
-
+
Bpl.BoundVariable h0Var = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$h0", predef.HeapType));
Bpl.BoundVariable h1Var = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$h1", predef.HeapType));
Bpl.Expr h0 = new Bpl.IdentifierExpr(f.tok, h0Var);
Bpl.Expr h1 = new Bpl.IdentifierExpr(f.tok, h1Var);
ExpressionTranslator etran0 = new ExpressionTranslator(this, predef, h0);
ExpressionTranslator etran1 = new ExpressionTranslator(this, predef, h1);
-
+
Bpl.Expr wellFormed = Bpl.Expr.And(
FunctionCall(f.tok, BuiltinFunction.IsGoodHeap, null, etran0.HeapExpr),
FunctionCall(f.tok, BuiltinFunction.IsGoodHeap, null, etran1.HeapExpr));
-
+
Bpl.TypeVariable alpha = new Bpl.TypeVariable(f.tok, "alpha");
Bpl.BoundVariable oVar = new Bpl.BoundVariable(f.tok, new Bpl.TypedIdent(f.tok, "$o", predef.RefType));
Bpl.Expr o = new Bpl.IdentifierExpr(f.tok, oVar);
@@ -1161,12 +1161,12 @@ namespace Microsoft.Dafny {
Bpl.Expr oNotNull = Bpl.Expr.Neq(o, predef.Null);
Bpl.Expr oNotNullAlloced = Bpl.Expr.And(oNotNull, Bpl.Expr.And(etran0.IsAlloced(f.tok, o), etran1.IsAlloced(f.tok, o)));
Bpl.Expr unchanged = Bpl.Expr.Eq(ExpressionTranslator.ReadHeap(f.tok, h0, o, field), ExpressionTranslator.ReadHeap(f.tok, h1, o, field));
-
+
Bpl.Expr heapSucc = FunctionCall(f.tok, BuiltinFunction.HeapSucc, null, h0, h1);
Bpl.Expr r0 = InRWClause(f.tok, o, field, f.Reads, etran0, null, null);
Bpl.Expr q0 = new Bpl.ForallExpr(f.tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fieldVar),
Bpl.Expr.Imp(Bpl.Expr.And(oNotNullAlloced, r0), unchanged));
-
+
// bvars: h0, h1, formals
// f0args: h0, formals
// f1args: h1, formals
@@ -1200,7 +1200,7 @@ namespace Microsoft.Dafny {
wh = GetWhereClause(p.tok, formal, p.Type, etran1);
if (wh != null) { wellFormed = Bpl.Expr.And(wellFormed, wh); }
}
-
+
string axiomComment = "frame axiom for " + f.FullName;
Bpl.FunctionCall fn = new Bpl.FunctionCall(new Bpl.IdentifierExpr(f.tok, f.FullName, TrType(f.ResultType)));
while (fn != null) {
@@ -1208,7 +1208,7 @@ namespace Microsoft.Dafny {
Bpl.Expr F1 = new Bpl.NAryExpr(f.tok, fn, f1args);
Bpl.Expr eq = Bpl.Expr.Eq(F0, F1);
Bpl.Trigger tr = new Bpl.Trigger(f.tok, true, new Bpl.ExprSeq(heapSucc, F1));
-
+
Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(f.TypeArgs);
Bpl.Expr ax = new Bpl.ForallExpr(f.tok, typeParams, bvars, null, tr,
Bpl.Expr.Imp(Bpl.Expr.And(wellFormed, heapSucc),
@@ -1222,7 +1222,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
Bpl.Expr/*!*/ InRWClause(IToken/*!*/ tok, Bpl.Expr/*!*/ o, Bpl.Expr/*!*/ f, List<FrameExpression/*!*/>/*!*/ rw, ExpressionTranslator/*!*/ etran,
Expression receiverReplacement, Dictionary<IVariable,Expression/*!*/> substMap) {
Contract.Requires(tok != null);
@@ -1237,7 +1237,7 @@ namespace Microsoft.Dafny {
// requires o to denote an expression of type RefType
// "rw" is is allowed to contain a WildcardExpr
-
+
Bpl.Expr disjunction = null;
foreach (FrameExpression rwComponent in rw) {
Expression e = rwComponent.E;
@@ -1280,12 +1280,12 @@ namespace Microsoft.Dafny {
return disjunction;
}
}
-
+
void AddWellformednessCheck(Function f) {
Contract.Requires(f != null);
Contract.Requires(sink != null && predef != null);
Contract.Requires(f.EnclosingClass != null);
-
+
ExpressionTranslator etran = new ExpressionTranslator(this, predef, f.tok);
// parameters of the procedure
Bpl.VariableSeq inParams = new Bpl.VariableSeq();
@@ -1317,7 +1317,7 @@ namespace Microsoft.Dafny {
VariableSeq implInParams = Bpl.Formal.StripWhereClauses(proc.InParams);
Bpl.VariableSeq locals = new Bpl.VariableSeq();
Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder();
-
+
// check well-formedness of the preconditions (including termination, but no reads checks), and then
// assume each one of them
foreach (Expression p in f.Req) {
@@ -1423,7 +1423,7 @@ namespace Microsoft.Dafny {
Contract.Requires(expr != null);Contract.Requires(etran != null);
Contract.Requires(predef != null);
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
-
+
if (expr is LiteralExpr || expr is ThisExpr || expr is IdentifierExpr || expr is WildcardExpr || expr is BoogieWrapper) {
return Bpl.Expr.True;
} else if (expr is DisplayExpression) {
@@ -1586,7 +1586,7 @@ namespace Microsoft.Dafny {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected expression
}
}
-
+
Bpl.Expr/*!*/ IsTotal(List<Expression/*!*/>/*!*/ exprs, ExpressionTranslator/*!*/ etran) {
Contract.Requires(etran != null);
Contract.Requires(exprs != null);
@@ -1746,7 +1746,7 @@ namespace Microsoft.Dafny {
return Bpl.Expr.And(a, b);
}
}
-
+
Bpl.Expr BplImp(Bpl.Expr a, Bpl.Expr b) {
Contract.Requires(a != null);
Contract.Requires(b != null);
@@ -1758,14 +1758,14 @@ namespace Microsoft.Dafny {
return Bpl.Expr.Imp(a, b);
}
}
-
+
void CheckNonNull(IToken tok, Expression e, Bpl.StmtListBuilder builder, ExpressionTranslator etran, Bpl.QKeyValue kv) {
Contract.Requires(tok != null);
Contract.Requires(e != null);
Contract.Requires(builder != null);
Contract.Requires(etran != null);
Contract.Requires(predef != null);
-
+
if (e is ThisExpr) {
// already known to be non-null
} else {
@@ -1840,7 +1840,7 @@ namespace Microsoft.Dafny {
Contract.Requires(builder != null);
Contract.Requires(etran != null);
Contract.Requires(predef != null);
-
+
if (expr is LiteralExpr || expr is ThisExpr || expr is IdentifierExpr || expr is WildcardExpr || expr is BoogieWrapper) {
// always allowed
} else if (expr is DisplayExpression) {
@@ -2084,7 +2084,7 @@ namespace Microsoft.Dafny {
CheckWellformed(e.Thn, options, locals, bThen, etran);
CheckWellformed(e.Els, options, locals, bElse, etran);
builder.Add(new Bpl.IfCmd(expr.tok, etran.TrExpr(e.Test), bThen.Collect(expr.tok), null, bElse.Collect(expr.tok)));
-
+
} else if (expr is MatchExpr) {
MatchExpr me = (MatchExpr)expr;
CheckWellformed(me.Source, options, locals, builder, etran);
@@ -2308,7 +2308,7 @@ namespace Microsoft.Dafny {
return s;
}
}
-
+
Bpl.Constant GetClass(TopLevelDecl cl)
{
Contract.Requires(cl != null);
@@ -2324,7 +2324,7 @@ namespace Microsoft.Dafny {
}
return cc;
}
-
+
Bpl.Expr GetTypeExpr(IToken tok, Type type)
{
Contract.Requires(tok != null);
@@ -2373,13 +2373,13 @@ namespace Microsoft.Dafny {
return t;
}
}
-
+
Bpl.Constant GetField(Field f)
{
Contract.Requires(f != null && f.IsMutable);
Contract.Requires(sink != null && predef != null);
Contract.Ensures(Contract.Result<Bpl.Constant>() != null);
-
+
Bpl.Constant fc;
if (fields.TryGetValue(f, out fc)) {
Contract.Assert(fc != null);
@@ -2434,13 +2434,13 @@ namespace Microsoft.Dafny {
Contract.Requires(fse != null);
Contract.Requires(fse.Field != null && fse.Field.IsMutable);
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
-
+
return new Bpl.IdentifierExpr(fse.tok, GetField(fse.Field));
}
/// <summary>
/// This method is expected to be called just once for each function in the program.
- /// </summary>
+ /// </summary>
void AddFunction(Function f)
{
Contract.Requires(f != null);
@@ -2457,7 +2457,7 @@ namespace Microsoft.Dafny {
Bpl.Formal res = new Bpl.Formal(f.tok, new Bpl.TypedIdent(f.tok, Bpl.TypedIdent.NoName, TrType(f.ResultType)), false);
Bpl.Function func = new Bpl.Function(f.tok, f.FullName, typeParams, args, res);
sink.TopLevelDeclarations.Add(func);
-
+
if (f.IsRecursive && !f.IsUnlimited) {
sink.TopLevelDeclarations.Add(new Bpl.Function(f.tok, FunctionName(f, 0), args, res));
sink.TopLevelDeclarations.Add(new Bpl.Function(f.tok, FunctionName(f, 2), args, res));
@@ -2467,12 +2467,12 @@ namespace Microsoft.Dafny {
Bpl.Function canCallF = new Bpl.Function(f.tok, f.FullName + "#canCall", args, res);
sink.TopLevelDeclarations.Add(canCallF);
}
-
+
/// <summary>
/// This method is expected to be called just twice for each procedure in the program (once with
/// wellformednessProc set to true, once with wellformednessProc set to false).
/// In addition, it is used once to generate refinement conditions.
- /// </summary>
+ /// </summary>
Bpl.Procedure AddMethod(Method m, bool wellformednessProc, bool skipEnsures)
{
Contract.Requires(m != null);
@@ -2482,7 +2482,7 @@ namespace Microsoft.Dafny {
Contract.Ensures(Contract.Result<Bpl.Procedure>() != null);
ExpressionTranslator etran = new ExpressionTranslator(this, predef, m.tok);
-
+
Bpl.VariableSeq inParams = new Bpl.VariableSeq();
Bpl.VariableSeq outParams = new Bpl.VariableSeq();
if (!m.IsStatic) {
@@ -2502,7 +2502,7 @@ namespace Microsoft.Dafny {
Bpl.Expr wh = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
outParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, wh), false));
}
-
+
Bpl.RequiresSeq req = new Bpl.RequiresSeq();
Bpl.IdentifierExprSeq mod = new Bpl.IdentifierExprSeq();
Bpl.EnsuresSeq ens = new Bpl.EnsuresSeq();
@@ -2513,7 +2513,7 @@ namespace Microsoft.Dafny {
req.Add(Requires(m.tok, true, context, null, null));
mod.Add(etran.HeapExpr);
mod.Add(etran.Tick());
-
+
if (!wellformednessProc) {
string comment = "user-defined preconditions";
foreach (MaybeFreeExpression p in m.Req) {
@@ -2551,54 +2551,54 @@ namespace Microsoft.Dafny {
return proc;
}
- #region Refinement extension
-
- void AddMethodRefinement(MethodRefinement m)
+ #region Refinement extension
+
+ void AddMethodRefinement(MethodRefinement m)
{
Contract.Requires(m != null);
Contract.Requires(sink != null && predef != null);
- // r is abstract, m is concrete
+ // r is abstract, m is concrete
Method r = m.Refined;
Contract.Assert(r != null);
Contract.Assert(m.EnclosingClass != null);
string name = "Refinement$$" + m.FullName;
string that = "that";
-
+
Bpl.IdentifierExpr heap = new Bpl.IdentifierExpr(m.tok, predef.HeapVarName, predef.HeapType);
ExpressionTranslator etran = new ExpressionTranslator(this, predef, heap, that);
-
+
// TODO: this straight inlining does not handle recursive calls
- // TODO: we assume frame allows anything to be changed -- we don't include post-conditions in the refinement procedure, or check refinement of frames
-
+ // TODO: we assume frame allows anything to be changed -- we don't include post-conditions in the refinement procedure, or check refinement of frames
+
// generate procedure declaration with pre-condition wp(r, true)
Bpl.Procedure proc = AddMethod(r, false, true);
proc.Name = name;
-
+
// create "that" for m
Bpl.Expr wh = Bpl.Expr.And(
Bpl.Expr.Neq(new Bpl.IdentifierExpr(m.tok, that, predef.RefType), predef.Null),
etran.GoodRef(m.tok, new Bpl.IdentifierExpr(m.tok, that, predef.RefType), Resolver.GetReceiverType(m.tok, m)));
Bpl.Formal thatVar = new Bpl.Formal(m.tok, new Bpl.TypedIdent(m.tok, that, predef.RefType, wh), true);
proc.InParams.Add(thatVar);
-
- // add outs of m to the outs of the refinement procedure
+
+ // add outs of m to the outs of the refinement procedure
foreach (Formal p in m.Outs) {
Bpl.Type varType = TrType(p.Type);
Bpl.Expr w = GetWhereClause(p.tok, new Bpl.IdentifierExpr(p.tok, p.UniqueName, varType), p.Type, etran);
proc.OutParams.Add(new Bpl.Formal(p.tok, new Bpl.TypedIdent(p.tok, p.UniqueName, varType, w), false));
}
sink.TopLevelDeclarations.Add(proc);
-
- // generate procedure implementation:
+
+ // generate procedure implementation:
Bpl.TypeVariableSeq typeParams = TrTypeParamDecls(m.TypeArgs);
Bpl.VariableSeq inParams = Bpl.Formal.StripWhereClauses(proc.InParams);
Bpl.VariableSeq outParams = Bpl.Formal.StripWhereClauses(proc.OutParams);
Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder();
Bpl.VariableSeq localVariables = new Bpl.VariableSeq();
-
+
Contract.Assert(m.Body != null);
Contract.Assert(r.Body != null);
-
+
// declare a frame variable that allows anything to be changed (not checking modifies clauses)
Bpl.IdentifierExpr theFrame = etran.TheFrame(m.tok);
Contract.Assert(theFrame.Type != null);
@@ -2610,12 +2610,12 @@ namespace Microsoft.Dafny {
Bpl.BoundVariable fVar = new Bpl.BoundVariable(m.tok, new Bpl.TypedIdent(m.tok, "$f", predef.FieldName(m.tok, alpha)));
Bpl.Expr lambda = new Bpl.LambdaExpr(m.tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fVar), null, Bpl.Expr.True);
builder.Add(Bpl.Cmd.SimpleAssign(m.tok, new Bpl.IdentifierExpr(m.tok, frame), lambda));
-
- // assume I($Heap, $Heap)
+
+ // assume I($Heap, $Heap)
builder.Add(new Bpl.AssumeCmd(m.tok, TrCouplingInvariant(m, heap, "this", heap, that)));
-
+
// assign input formals of m (except "this")
- for (int i = 0; i < m.Ins.Count; i++) {
+ for (int i = 0; i < m.Ins.Count; i++) {
Bpl.LocalVariable arg = new Bpl.LocalVariable(m.tok, new Bpl.TypedIdent(m.tok, m.Ins[i].UniqueName, TrType(m.Ins[i].Type)));
localVariables.Add(arg);
Bpl.Variable var = inParams[i+1];
@@ -2628,7 +2628,7 @@ namespace Microsoft.Dafny {
loopHeapVarCount = 0;
otherTmpVarCount = 0;
_tmpIEs.Clear();
-
+
// call inlined m;
TrStmt(m.Body, builder, localVariables, etran);
@@ -2636,10 +2636,10 @@ namespace Microsoft.Dafny {
Bpl.LocalVariable heap2 = new Bpl.LocalVariable(m.tok, new Bpl.TypedIdent(m.tok, heap.Name+"2", predef.HeapType));
localVariables.Add(heap2);
builder.Add(Bpl.Cmd.SimpleAssign(m.tok, new Bpl.IdentifierExpr(m.tok, heap2), etran.HeapExpr));
-
+
// $Heap := old($Heap);
builder.Add(Bpl.Cmd.SimpleAssign(m.tok, heap, new Bpl.OldExpr(m.tok, heap)));
-
+
// call inlined r;
currentMethod = r;
etran = new ExpressionTranslator(this, predef, heap);
@@ -2650,7 +2650,7 @@ namespace Microsoft.Dafny {
loopHeapVarCount = 0;
otherTmpVarCount = 0;
_tmpIEs.Clear();
-
+
// assert output variables of r and m are pairwise equal
Contract.Assert(outParams.Length % 2 == 0);
int k = outParams.Length / 2;
@@ -2658,21 +2658,21 @@ namespace Microsoft.Dafny {
Bpl.Variable rOut = outParams[i];
Bpl.Variable mOut = outParams[i+k];
Contract.Assert(rOut != null && mOut != null);
- builder.Add(Assert(m.tok, Bpl.Expr.Eq(new Bpl.IdentifierExpr(m.tok, mOut), new Bpl.IdentifierExpr(m.tok, rOut)),
+ builder.Add(Assert(m.tok, Bpl.Expr.Eq(new Bpl.IdentifierExpr(m.tok, mOut), new Bpl.IdentifierExpr(m.tok, rOut)),
"Refinement method may not produce the same value for output variable " + m.Outs[i].Name));
}
-
- // assert I($Heap1, $Heap)
+
+ // assert I($Heap1, $Heap)
builder.Add(Assert(m.tok, TrCouplingInvariant(m, heap, "this", new Bpl.IdentifierExpr(m.tok, heap2), that),
"Refinement method may not preserve the coupling invariant"));
-
+
Bpl.StmtList stmts = builder.Collect(m.tok);
Bpl.Implementation impl = new Bpl.Implementation(m.tok, proc.Name,
typeParams, inParams, outParams,
localVariables, stmts);
sink.TopLevelDeclarations.Add(impl);
}
-
+
private sealed class NominalSubstituter : Duplicator
{
private readonly Dictionary<string,Bpl.Expr> subst;
@@ -2686,7 +2686,7 @@ namespace Microsoft.Dafny {
Contract.Invariant(cce.NonNullDictionaryAndValues(subst));
}
-
+
public override Expr VisitIdentifierExpr(Bpl.IdentifierExpr node)
{
Contract.Requires(node != null);
@@ -2694,7 +2694,7 @@ namespace Microsoft.Dafny {
if (subst.ContainsKey(node.Name))
return subst[node.Name];
- else
+ else
return base.VisitIdentifierExpr(node);
}
}
@@ -2711,32 +2711,32 @@ namespace Microsoft.Dafny {
ClassRefinementDecl c = m.EnclosingClass as ClassRefinementDecl;
Contract.Assert(c != null);
ExpressionTranslator etran = new ExpressionTranslator(this, predef, conHeap, conThis);
-
- foreach (MemberDecl d in c.Members)
+
+ foreach (MemberDecl d in c.Members)
if (d is CouplingInvariant) {
CouplingInvariant inv = (CouplingInvariant)d;
Contract.Assert(inv.Refined != null);
Contract.Assert(inv.Formals != null);
-
- // replace formals with field dereferences
+
+ // replace formals with field dereferences
Dictionary<string,Bpl.Expr> map = new Dictionary<string,Bpl.Expr>();
Bpl.Expr absVar = new Bpl.IdentifierExpr(d.tok, absThis, predef.RefType);
- for (int i = 0; i < inv.Refined.Count; i++) {
+ for (int i = 0; i < inv.Refined.Count; i++) {
// TODO: boxing/unboxing?
Bpl.Expr result = ExpressionTranslator.ReadHeap(inv.Toks[i], absHeap, absVar, new Bpl.IdentifierExpr(inv.Toks[i], GetField(cce.NonNull(inv.Refined[i]))));
map.Add(inv.Formals[i].UniqueName, result);
}
-
+
Bpl.Expr e = new NominalSubstituter(map).VisitExpr(etran.TrExpr(inv.Expr));
cond = Bpl.Expr.And(cond, e);
}
-
+
return cond;
}
-
+
#endregion
-
+
class BoilerplateTriple { // a triple that is now a quintuple
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -2764,7 +2764,7 @@ namespace Microsoft.Dafny {
Comment = comment;
}
}
-
+
/// <summary>
/// There are 3 states of interest when generating two-state boilerplate:
/// S0. the beginning of the method or loop, which is where the modifies clause is interpreted
@@ -2781,17 +2781,17 @@ namespace Microsoft.Dafny {
Contract.Ensures(cce.NonNullElements(Contract.Result<List<BoilerplateTriple>>()));
List<BoilerplateTriple> boilerplate = new List<BoilerplateTriple>();
-
+
// the frame condition, which is free since it is checked with every heap update and call
boilerplate.Add(new BoilerplateTriple(tok, true, FrameCondition(tok, modifiesClause, etranPre, etran, etranMod), null, "frame condition"));
// HeapSucc(S1, S2)
Bpl.Expr heapSucc = FunctionCall(tok, BuiltinFunction.HeapSucc, null, etranPre.HeapExpr, etran.HeapExpr);
boilerplate.Add(new BoilerplateTriple(tok, true, heapSucc, null, "boilerplate"));
-
+
return boilerplate;
}
-
+
/// <summary>
/// There are 3 states of interest when generating a frame condition:
/// S0. the beginning of the method/loop, which is where the modifies clause is interpreted
@@ -2823,9 +2823,9 @@ namespace Microsoft.Dafny {
Bpl.Expr preHeapOF = ExpressionTranslator.ReadHeap(tok, etranPre.HeapExpr, o, f);
Bpl.Expr ante = Bpl.Expr.And(Bpl.Expr.Neq(o, predef.Null), etranMod.IsAlloced(tok, o));
Bpl.Expr consequent = Bpl.Expr.Eq(heapOF, preHeapOF);
-
+
consequent = Bpl.Expr.Or(consequent, InRWClause(tok, o, f, modifiesClause, etranMod, null, null));
-
+
Bpl.Trigger tr = new Bpl.Trigger(tok, true, new Bpl.ExprSeq(heapOF));
return new Bpl.ForallExpr(tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fVar), null, tr, Bpl.Expr.Imp(ante, consequent));
}
@@ -2857,15 +2857,15 @@ namespace Microsoft.Dafny {
Bpl.Trigger tr = new Bpl.Trigger(tok, true, new Bpl.ExprSeq(heapOF));
return new Bpl.ForallExpr(tok, new Bpl.TypeVariableSeq(alpha), new Bpl.VariableSeq(oVar, fVar), null, tr, Bpl.Expr.Imp(ante, consequent));
- }
+ }
// ----- Type ---------------------------------------------------------------------------------
-
+
Bpl.Type TrType(Type type)
{
Contract.Requires(type != null);
Contract.Requires(predef != null);
Contract.Ensures(Contract.Result<Bpl.Type>() != null);
-
+
while (true) {
TypeProxy tp = type as TypeProxy;
if (tp == null) {
@@ -2877,7 +2877,7 @@ namespace Microsoft.Dafny {
type = tp.T;
}
}
-
+
if (type is BoolType) {
return Bpl.Type.Bool;
} else if (type is IntType) {
@@ -2897,7 +2897,7 @@ namespace Microsoft.Dafny {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type
}
}
-
+
Bpl.TypeVariableSeq TrTypeParamDecls(List<TypeParameter/*!*/>/*!*/ tps)
{
Contract.Requires(cce.NonNullElements(tps));
@@ -2908,7 +2908,7 @@ namespace Microsoft.Dafny {
}
// ----- Statement ----------------------------------------------------------------------------
-
+
Bpl.AssertCmd Assert(Bpl.IToken tok, Bpl.Expr condition, string errorMessage)
{
Contract.Requires(tok != null);
@@ -2978,10 +2978,10 @@ namespace Microsoft.Dafny {
Contract.Requires(etran != null);
Contract.Requires(currentMethod != null && predef != null);
Contract.Ensures(Contract.Result<Bpl.StmtList>() != null);
-
+
return TrStmt2StmtList(new Bpl.StmtListBuilder(), block, locals, etran);
}
-
+
Bpl.StmtList TrStmt2StmtList(Bpl.StmtListBuilder builder, Statement block, Bpl.VariableSeq locals, ExpressionTranslator etran)
{
Contract.Requires(builder != null);
@@ -2990,11 +2990,11 @@ namespace Microsoft.Dafny {
Contract.Requires(etran != null);
Contract.Requires(currentMethod != null && predef != null);
Contract.Ensures(Contract.Result<Bpl.StmtList>() != null);
-
+
TrStmt(block, builder, locals, etran);
return builder.Collect(block.Tok); // TODO: would be nice to have an end-curly location for "block"
}
-
+
void TrStmt(Statement stmt, Bpl.StmtListBuilder builder, Bpl.VariableSeq locals, ExpressionTranslator etran)
{
Contract.Requires(stmt != null);
@@ -3035,7 +3035,7 @@ namespace Microsoft.Dafny {
TrStmt_CheckWellformed(arg.E, builder, locals, etran, false);
}
}
-
+
} else if (stmt is BreakStmt) {
AddComment(builder, stmt, "break statement");
var s = (BreakStmt)stmt;
@@ -3254,7 +3254,7 @@ namespace Microsoft.Dafny {
Bpl.Expr qqq = new Bpl.ForallExpr(stmt.Tok, new Bpl.VariableSeq(oVar), bbb);
builder.Add(AssertNS(rhsExpr.Expr.tok, qqq, "RHS of assignment must be well defined")); // totality check
}
-
+
// Here comes: assert (forall o: ref :: o != null && o in S && Range(o) ==> $_Frame[o,F]);
Bpl.Expr body = Bpl.Expr.Imp(oInS, Bpl.Expr.Select(etran.TheFrame(stmt.Tok), o, GetField((FieldSelectExpr)s.BodyAssign.Lhs)));
Bpl.Expr qq = new Bpl.ForallExpr(stmt.Tok, new Bpl.VariableSeq(oVar), body);
@@ -3288,14 +3288,14 @@ namespace Microsoft.Dafny {
qq = new Bpl.ForallExpr(stmt.Tok, new Bpl.VariableSeq(oVar), body);
builder.Add(new Bpl.AssumeCmd(stmt.Tok, qq));
}
-
+
builder.Add(CaptureState(stmt.Tok));
-
+
} else if (stmt is MatchStmt) {
var s = (MatchStmt)stmt;
TrStmt_CheckWellformed(s.Source, builder, locals, etran, true);
Bpl.Expr source = etran.TrExpr(s.Source);
-
+
var b = new Bpl.StmtListBuilder();
b.Add(new Bpl.AssumeCmd(stmt.Tok, Bpl.Expr.False));
Bpl.StmtList els = b.Collect(stmt.Tok);
@@ -3450,7 +3450,7 @@ namespace Microsoft.Dafny {
}
// add a free invariant which says that the heap hasn't changed outside of the modifies clause.
invariants.Add(new Bpl.AssumeCmd(s.Tok, FrameConditionUsingDefinedFrame(s.Tok, etranPreLoop, etran, updatedFrameEtran)));
-
+
// include a free invariant that says that all completed iterations so far have only decreased the termination metric
if (initDecr != null) {
List<IToken> toks = new List<IToken>();
@@ -3607,7 +3607,7 @@ namespace Microsoft.Dafny {
Contract.Requires(builder != null);
Contract.Requires(locals != null);
Contract.Requires(etran != null);
-
+
Expression receiver = bReceiver == null ? dafnyReceiver : new BoogieWrapper(bReceiver);
Bpl.ExprSeq ins = new Bpl.ExprSeq();
if (!method.IsStatic) {
@@ -3692,7 +3692,7 @@ namespace Microsoft.Dafny {
}
}
}
-
+
static Expression CreateIntLiteral(IToken tok, int n)
{
Contract.Requires(tok != null);
@@ -3706,13 +3706,13 @@ namespace Microsoft.Dafny {
return CreateIntSub(tok, CreateIntLiteral(tok, 0), CreateIntLiteral(tok, -n));
}
}
-
+
static Expression CreateIntSub(IToken tok, Expression e0, Expression e1)
{
Contract.Requires(tok != null);
Contract.Requires(e0 != null);
Contract.Requires(e1 != null);
-
+
Contract.Requires(e0.Type is IntType && e1.Type is IntType);
Contract.Ensures(Contract.Result<Expression>() != null);
@@ -3721,7 +3721,7 @@ namespace Microsoft.Dafny {
s.Type = Type.Int; // resolve here
return s;
}
-
+
static Expression CreateIntITE(IToken tok, Expression test, Expression e0, Expression e1)
{
Contract.Requires(tok != null);
@@ -3735,7 +3735,7 @@ namespace Microsoft.Dafny {
ite.Type = Type.Int; // resolve here
return ite;
}
-
+
public IEnumerable<Expression> Conjuncts(Expression expr)
{
Contract.Requires(expr != null);
@@ -3773,7 +3773,7 @@ namespace Microsoft.Dafny {
// record value of each decreases expression at beginning of the loop iteration
Bpl.Cmd cmd = Bpl.Cmd.SimpleAssign(e.tok, bf, etran.TrExpr(e));
builder.Add(cmd);
-
+
c++;
}
return oldBfs;
@@ -3825,7 +3825,7 @@ namespace Microsoft.Dafny {
}
builder.Add(Assert(tok, decrExpr, inferredDecreases ? "cannot prove termination; try supplying a decreases clause" : "failure to decrease termination measure"));
}
-
+
/// <summary>
/// Returns the expression that says whether or not the decreases function has gone down (if !allowNoChange)
/// or has gone down or stayed the same (if allowNoChange).
@@ -3846,7 +3846,7 @@ namespace Microsoft.Dafny {
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
int N = types.Count;
-
+
// compute eq and less for each component of the lexicographic pair
List<Bpl.Expr> Eq = new List<Bpl.Expr>(N);
List<Bpl.Expr> Less = new List<Bpl.Expr>(N);
@@ -3913,7 +3913,7 @@ namespace Microsoft.Dafny {
return false; // don't consider any type parameters to be the same (since we have no comparison function for them anyway)
}
}
-
+
void ComputeLessEq(IToken/*!*/ tok, Type/*!*/ ty, Bpl.Expr/*!*/ e0, Bpl.Expr/*!*/ e1, out Bpl.Expr/*!*/ less, out Bpl.Expr/*!*/ atmost, out Bpl.Expr/*!*/ eq,
ExpressionTranslator/*!*/ etran, bool includeLowerBound)
{
@@ -3926,7 +3926,7 @@ namespace Microsoft.Dafny {
Contract.Ensures(Contract.ValueAtReturn(out less)!=null);
Contract.Ensures(Contract.ValueAtReturn(out atmost)!=null);
Contract.Ensures(Contract.ValueAtReturn(out eq)!=null);
-
+
if (ty is BoolType) {
eq = Bpl.Expr.Iff(e0, e1);
less = Bpl.Expr.And(Bpl.Expr.Not(e0), e1);
@@ -3955,7 +3955,7 @@ namespace Microsoft.Dafny {
eq = Bpl.Expr.Eq(b0, b1);
less = Bpl.Expr.Lt(b0, b1);
atmost = Bpl.Expr.Le(b0, b1);
-
+
} else {
// reference type
Bpl.Expr b0 = Bpl.Expr.Neq(e0, predef.Null);
@@ -3965,14 +3965,14 @@ namespace Microsoft.Dafny {
atmost = Bpl.Expr.Imp(b0, b1);
}
}
-
+
void AddComment(Bpl.StmtListBuilder builder, Statement stmt, string comment) {
Contract.Requires(builder != null);
Contract.Requires(stmt != null);
Contract.Requires(comment != null);
builder.Add(new Bpl.CommentCmd(string.Format("----- {0} ----- {1}({2},{3})", comment, stmt.Tok.filename, stmt.Tok.line, stmt.Tok.col)));
- }
-
+ }
+
Bpl.Expr GetWhereClause(IToken tok, Bpl.Expr x, Type type, ExpressionTranslator etran)
{
Contract.Requires(tok != null);
@@ -4001,7 +4001,7 @@ namespace Microsoft.Dafny {
} else if (type is BoolType || type is IntType) {
// nothing todo
-
+
} else if (type is SetType) {
SetType st = (SetType)type;
// (forall t: BoxType :: { x[t] } x[t] ==> Unbox(t)-has-the-expected-type)
@@ -4016,7 +4016,7 @@ namespace Microsoft.Dafny {
Bpl.Trigger tr = new Bpl.Trigger(tok, true, new Bpl.ExprSeq(xSubT));
return new Bpl.ForallExpr(tok, new Bpl.VariableSeq(tVar), tr, Bpl.Expr.Imp(xSubT, wh));
}
-
+
} else if (type is SeqType) {
SeqType st = (SeqType)type;
// (forall i: int :: { Seq#Index(x,i) }
@@ -4053,7 +4053,7 @@ namespace Microsoft.Dafny {
} else if (type.IsTypeParameter) {
return FunctionCall(tok, BuiltinFunction.GenericAlloc, null, x, etran.HeapExpr);
-
+
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected type
}
@@ -4244,7 +4244,7 @@ namespace Microsoft.Dafny {
var obj = SaveInTemp(etran.TrExpr(mse.Array), rhsCanAffectPreviouslyKnownExpressions,
"$obj" + i, predef.RefType, builder, locals);
- var fieldName = SaveInTemp(etran.GetArrayIndexFieldName(mse.tok, mse.Indices), rhsCanAffectPreviouslyKnownExpressions,
+ var fieldName = SaveInTemp(etran.GetArrayIndexFieldName(mse.tok, mse.Indices), rhsCanAffectPreviouslyKnownExpressions,
"$index" + i, predef.FieldName(mse.tok, predef.BoxType), builder, locals);
prevObj[i] = obj;
prevIndex[i] = fieldName;
@@ -4434,7 +4434,7 @@ namespace Microsoft.Dafny {
readonly int layerOffset = 0;
public int Statistics_FunctionCount = 0;
[ContractInvariantMethod]
- void ObjectInvariant()
+ void ObjectInvariant()
{
Contract.Invariant(HeapExpr != null);
Contract.Invariant(predef != null);
@@ -4453,7 +4453,7 @@ namespace Microsoft.Dafny {
this.HeapExpr = new Bpl.IdentifierExpr(heapToken, predef.HeapVarName, predef.HeapType);
this.This = "this";
}
-
+
public ExpressionTranslator(Translator translator, PredefinedDecls predef, Bpl.Expr heap) {
Contract.Requires(translator != null);
Contract.Requires(predef != null);
@@ -4463,7 +4463,7 @@ namespace Microsoft.Dafny {
this.HeapExpr = heap;
this.This = "this";
}
-
+
public ExpressionTranslator(Translator translator, PredefinedDecls predef, Bpl.Expr heap, string thisVar) {
Contract.Requires(translator != null);
Contract.Requires(predef != null);
@@ -4521,7 +4521,7 @@ namespace Microsoft.Dafny {
return HeapExpr is Bpl.OldExpr;
}
}
-
+
public ExpressionTranslator LimitedFunctions(Function applyLimited_CurrentFunction) {
Contract.Requires(applyLimited_CurrentFunction != null);
Contract.Ensures(Contract.Result<ExpressionTranslator>() != null);
@@ -4596,10 +4596,10 @@ namespace Microsoft.Dafny {
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected literal
}
-
+
} else if (expr is ThisExpr) {
return new Bpl.IdentifierExpr(expr.tok, This, predef.RefType);
-
+
} else if (expr is IdentifierExpr) {
IdentifierExpr e = (IdentifierExpr)expr;
return TrVar(expr.tok, cce.NonNull(e.Var));
@@ -4607,7 +4607,7 @@ namespace Microsoft.Dafny {
} else if (expr is BoogieWrapper) {
var e = (BoogieWrapper)expr;
return e.Expr;
-
+
} else if (expr is SetDisplayExpr) {
SetDisplayExpr e = (SetDisplayExpr)expr;
Bpl.Expr s = translator.FunctionCall(expr.tok, BuiltinFunction.SetEmpty, predef.BoxType);
@@ -4616,7 +4616,7 @@ namespace Microsoft.Dafny {
s = translator.FunctionCall(expr.tok, BuiltinFunction.SetUnionOne, predef.BoxType, s, ss);
}
return s;
-
+
} else if (expr is SeqDisplayExpr) {
SeqDisplayExpr e = (SeqDisplayExpr)expr;
Bpl.Expr s = translator.FunctionCall(expr.tok, BuiltinFunction.SeqEmpty, predef.BoxType);
@@ -4627,7 +4627,7 @@ namespace Microsoft.Dafny {
i++;
}
return s;
-
+
} else if (expr is FieldSelectExpr) {
FieldSelectExpr e = (FieldSelectExpr)expr;
Contract.Assert(e.Field != null);
@@ -4639,7 +4639,7 @@ namespace Microsoft.Dafny {
result = new Bpl.NAryExpr(expr.tok, new Bpl.FunctionCall(translator.GetReadonlyField(e.Field)), new Bpl.ExprSeq(obj));
}
return CondApplyUnbox(expr.tok, result, e.Field.Type, cce.NonNull(expr.Type));
-
+
} else if (expr is SeqSelectExpr) {
SeqSelectExpr e = (SeqSelectExpr)expr;
Bpl.Expr seq = TrExpr(e.Seq);
@@ -4676,7 +4676,7 @@ namespace Microsoft.Dafny {
}
return seq;
}
-
+
} else if (expr is SeqUpdateExpr) {
SeqUpdateExpr e = (SeqUpdateExpr)expr;
Bpl.Expr seq = TrExpr(e.Seq);
@@ -4714,7 +4714,7 @@ namespace Microsoft.Dafny {
Bpl.ExprSeq args = FunctionInvocationArguments(e);
Bpl.Expr result = new Bpl.NAryExpr(expr.tok, new Bpl.FunctionCall(id), args);
return CondApplyUnbox(expr.tok, result, e.Function.ResultType, expr.Type);
-
+
} else if (expr is DatatypeValue) {
DatatypeValue dtv = (DatatypeValue)expr;
Contract.Assert(dtv.Ctor != null); // since dtv has been successfully resolved
@@ -4727,11 +4727,11 @@ namespace Microsoft.Dafny {
}
Bpl.IdentifierExpr id = new Bpl.IdentifierExpr(dtv.tok, dtv.Ctor.FullName, predef.DatatypeType);
return new Bpl.NAryExpr(dtv.tok, new Bpl.FunctionCall(id), args);
-
+
} else if (expr is OldExpr) {
OldExpr e = (OldExpr)expr;
return new Bpl.OldExpr(expr.tok, TrExpr(e.E));
-
+
} else if (expr is FreshExpr) {
FreshExpr e = (FreshExpr)expr;
Bpl.Expr oldHeap = new Bpl.OldExpr(expr.tok, HeapExpr);
@@ -4789,7 +4789,7 @@ namespace Microsoft.Dafny {
default:
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected unary expression
}
-
+
} else if (expr is BinaryExpr) {
BinaryExpr e = (BinaryExpr)expr;
Bpl.Expr e0 = TrExpr(e.E0);
@@ -4810,12 +4810,12 @@ namespace Microsoft.Dafny {
bOpcode = BinaryOperator.Opcode.And; break;
case BinaryExpr.ResolvedOpcode.Or:
bOpcode = BinaryOperator.Opcode.Or; break;
-
+
case BinaryExpr.ResolvedOpcode.EqCommon:
bOpcode = BinaryOperator.Opcode.Eq; break;
case BinaryExpr.ResolvedOpcode.NeqCommon:
bOpcode = BinaryOperator.Opcode.Neq; break;
-
+
case BinaryExpr.ResolvedOpcode.Lt:
bOpcode = BinaryOperator.Opcode.Lt; break;
case BinaryExpr.ResolvedOpcode.Le:
@@ -4892,12 +4892,12 @@ namespace Microsoft.Dafny {
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));
-
+
default:
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected binary expression
}
return Bpl.Expr.Binary(expr.tok, bOpcode, e0, e1);
-
+
} else if (expr is QuantifierExpr) {
QuantifierExpr e = (QuantifierExpr)expr;
Bpl.VariableSeq bvars = new Bpl.VariableSeq();
@@ -4916,7 +4916,7 @@ namespace Microsoft.Dafny {
antecedent = Bpl.Expr.And(antecedent, TrExpr(e.Range));
}
Bpl.Expr body = TrExpr(e.Term);
-
+
if (e is ForallExpr) {
return new Bpl.ForallExpr(expr.tok, new Bpl.TypeVariableSeq(), bvars, kv, tr, Bpl.Expr.Imp(antecedent, body));
} else {
@@ -4955,11 +4955,11 @@ namespace Microsoft.Dafny {
} else if (expr is BoxingCastExpr) {
BoxingCastExpr e = (BoxingCastExpr)expr;
return CondApplyBox(e.tok, TrExpr(e.E), e.FromType, e.ToType);
-
+
} else if (expr is UnboxingCastExpr) {
UnboxingCastExpr e = (UnboxingCastExpr)expr;
return CondApplyUnbox(e.tok, TrExpr(e.E), e.FromType, e.ToType);
-
+
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected expression
}
@@ -4968,7 +4968,7 @@ namespace Microsoft.Dafny {
public Bpl.Expr TrBoundVariables(List<BoundVar/*!*/> boundVars, Bpl.VariableSeq bvars) {
Contract.Requires(boundVars != null);
Contract.Ensures(Contract.Result<Bpl.Expr>() != null);
-
+
Bpl.Expr typeAntecedent = Bpl.Expr.True;
foreach (BoundVar bv in boundVars) {
Bpl.Variable bvar = new Bpl.BoundVariable(bv.tok, new Bpl.TypedIdent(bv.tok, bv.UniqueName, translator.TrType(bv.Type)));
@@ -5047,7 +5047,7 @@ namespace Microsoft.Dafny {
return e;
}
}
-
+
public Bpl.Expr BoxIfNecessary(IToken tok, Bpl.Expr e, Type fromType) {
Contract.Requires(tok != null);
Contract.Requires(e != null);
@@ -5056,7 +5056,7 @@ namespace Microsoft.Dafny {
return CondApplyBox(tok, e, fromType, null);
}
-
+
public Bpl.Expr CondApplyUnbox(IToken tok, Bpl.Expr e, Type fromType, Type toType) {
Contract.Requires(tok != null);
Contract.Requires(e != null);
@@ -5070,7 +5070,7 @@ namespace Microsoft.Dafny {
return e;
}
}
-
+
public static bool ModeledAsBoxType(Type t) {
Contract.Requires(t != null);
while (true) {
@@ -5173,7 +5173,7 @@ namespace Microsoft.Dafny {
}
return Bpl.Expr.SelectTok(tok, TrExpr(s), BoxIfNecessary(tok, elmt, elmtType));
}
-
+
Bpl.QKeyValue TrAttributes(Attributes attrs) {
Bpl.QKeyValue kv = null;
while (attrs != null) {
@@ -5190,7 +5190,7 @@ namespace Microsoft.Dafny {
}
return kv;
}
-
+
// --------------- help routines ---------------
public Bpl.Expr IsAlloced(IToken tok, Bpl.Expr e) {
@@ -5200,7 +5200,7 @@ namespace Microsoft.Dafny {
return IsAlloced(tok, e, HeapExpr);
}
-
+
Bpl.Expr IsAlloced(IToken tok, Bpl.Expr e, Bpl.Expr heap) {
Contract.Requires(tok != null);
Contract.Requires(e != null);
@@ -5209,7 +5209,7 @@ namespace Microsoft.Dafny {
return ReadHeap(tok, heap, e, predef.Alloc(tok));
}
-
+
public Bpl.Expr GoodRef(IToken tok, Bpl.Expr e, Type type) {
Contract.Requires(tok != null);
Contract.Requires(e != null);
@@ -5224,7 +5224,7 @@ namespace Microsoft.Dafny {
return IsAlloced(tok, e);
}
}
-
+
public Bpl.Expr GoodRef_Class(IToken tok, Bpl.Expr e, UserDefinedType type, bool isNew)
{
Contract.Requires(tok != null);
@@ -5246,12 +5246,12 @@ namespace Microsoft.Dafny {
if (isNew) {
r = Bpl.Expr.Not(r); // use the conjunct: !Heap[e, alloc]
}
-
+
// dtype(e) == C
Bpl.Expr dtypeFunc = translator.FunctionCall(tok, BuiltinFunction.DynamicType, null, e);
Bpl.Expr dtype = Bpl.Expr.Eq(dtypeFunc, type);
r = r == null ? dtype : Bpl.Expr.And(r, dtype);
-
+
// TypeParams(e, #) == T
int n = 0;
foreach (Type arg in typeArgs) {
@@ -5262,7 +5262,7 @@ namespace Microsoft.Dafny {
}
n++;
}
-
+
return r;
}
@@ -5290,7 +5290,7 @@ namespace Microsoft.Dafny {
return r;
}
}
-
+
enum BuiltinFunction {
SetEmpty,
SetUnionOne,
@@ -5301,7 +5301,7 @@ namespace Microsoft.Dafny {
SetSubset,
SetDisjoint,
SetChoose,
-
+
SeqLength,
SeqEmpty,
SeqBuild,
@@ -5313,17 +5313,17 @@ namespace Microsoft.Dafny {
SeqTake,
SeqEqual,
SeqSameUntil,
-
+
IndexField,
MultiIndexField,
-
+
Box,
Unbox,
IsCanonicalBoolBox,
-
+
IsGoodHeap,
HeapSucc,
-
+
DynamicType, // allocated type (of object reference)
DtType, // type of datatype value
TypeParams, // type parameters of allocated type
@@ -5338,7 +5338,7 @@ namespace Microsoft.Dafny {
GenericAlloc,
}
-
+
// The "typeInstantiation" argument is passed in to help construct the result type of the function.
Bpl.NAryExpr FunctionCall(IToken tok, BuiltinFunction f, Bpl.Type typeInstantiation, params Bpl.Expr[] args)
{
@@ -5433,7 +5433,7 @@ namespace Microsoft.Dafny {
Contract.Assert(args.Length == 3);
Contract.Assert(typeInstantiation == null);
return FunctionCall(tok, "Seq#SameUntil", Bpl.Type.Bool, args);
-
+
case BuiltinFunction.IndexField:
Contract.Assert(args.Length == 1);
Contract.Assert(typeInstantiation == null);
@@ -5516,7 +5516,7 @@ namespace Microsoft.Dafny {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected built-in function
}
}
-
+
Bpl.NAryExpr FunctionCall(IToken tok, string function, Bpl.Type returnType, params Bpl.Expr[] args)
{
Contract.Requires(tok != null);
@@ -5984,7 +5984,7 @@ namespace Microsoft.Dafny {
for (int i = 0; i < dt.TypeArgs.Count; i++) {
subst.Add(dt.TypeArgs[i], instantiatedType.TypeArgs[i]);
}
-
+
foreach (DatatypeCtor ctor in dt.Ctors) {
Bpl.VariableSeq bvs;
List<Bpl.Expr> args;
@@ -6037,7 +6037,7 @@ namespace Microsoft.Dafny {
newExpr = new SeqDisplayExpr(expr.tok, newElements);
}
}
-
+
} else if (expr is FieldSelectExpr) {
FieldSelectExpr fse = (FieldSelectExpr)expr;
Expression substE = Substitute(fse.Obj, receiverReplacement, substMap);
@@ -6046,7 +6046,7 @@ namespace Microsoft.Dafny {
fseNew.Field = fse.Field; // resolve on the fly (and fseExpr.Type is set at end of method)
newExpr = fseNew;
}
-
+
} else if (expr is SeqSelectExpr) {
SeqSelectExpr sse = (SeqSelectExpr)expr;
Expression seq = Substitute(sse.Seq, receiverReplacement, substMap);
@@ -6055,7 +6055,7 @@ namespace Microsoft.Dafny {
if (seq != sse.Seq || e0 != sse.E0 || e1 != sse.E1) {
newExpr = new SeqSelectExpr(sse.tok, sse.SelectOne, seq, e0, e1);
}
-
+
} else if (expr is SeqUpdateExpr) {
SeqUpdateExpr sse = (SeqUpdateExpr)expr;
Expression seq = Substitute(sse.Seq, receiverReplacement, substMap);
@@ -6082,7 +6082,7 @@ namespace Microsoft.Dafny {
newFce.Function = e.Function; // resolve on the fly (and set newFce.Type below, at end)
newExpr = newFce;
}
-
+
} else if (expr is DatatypeValue) {
DatatypeValue dtv = (DatatypeValue)expr;
List<Expression> newArgs = SubstituteExprList(dtv.Arguments, receiverReplacement, substMap);
@@ -6125,7 +6125,7 @@ namespace Microsoft.Dafny {
newBin.ResolvedOp = e.ResolvedOp; // part of what needs to be done to resolve on the fly (newBin.Type is set below, at end)
newExpr = newBin;
}
-
+
} else if (expr is ComprehensionExpr) {
var e = (ComprehensionExpr)expr;
Expression newRange = e.Range == null ? null : Substitute(e.Range, receiverReplacement, substMap);
@@ -6148,7 +6148,7 @@ namespace Microsoft.Dafny {
} else {
Contract.Assume(false); // unexpected ComprehensionExpr
}
-
+
} else if (expr is ITEExpr) {
ITEExpr e = (ITEExpr)expr;
Expression test = Substitute(e.Test, receiverReplacement, substMap);
@@ -6162,7 +6162,7 @@ namespace Microsoft.Dafny {
var e = (ConcreteSyntaxExpression)expr;
return Substitute(e.ResolvedExpression, receiverReplacement, substMap);
}
-
+
if (newExpr == null) {
return expr;
} else {
@@ -6170,18 +6170,18 @@ namespace Microsoft.Dafny {
return newExpr;
}
}
-
+
static List<Expression/*!*/>/*!*/ SubstituteExprList(List<Expression/*!*/>/*!*/ elist,
Expression receiverReplacement, Dictionary<IVariable,Expression/*!*/>/*!*/ substMap) {
Contract.Requires(cce.NonNullElements(elist));
Contract.Requires((receiverReplacement == null) == (substMap == null));
Contract.Requires(substMap == null || cce.NonNullDictionaryAndValues(substMap));
Contract.Ensures(cce.NonNullElements(Contract.Result<List<Expression>>()));
-
+
List<Expression> newElist = null; // initialized lazily
for (int i = 0; i < elist.Count; i++)
{cce.LoopInvariant( newElist == null || newElist.Count == i);
-
+
Expression substE = Substitute(elist[i], receiverReplacement, substMap);
if (substE != elist[i] && newElist == null) {
newElist = new List<Expression>();
@@ -6199,7 +6199,7 @@ namespace Microsoft.Dafny {
return newElist;
}
}
-
+
static Triggers SubstTriggers(Triggers trigs, Expression receiverReplacement, Dictionary<IVariable,Expression/*!*/>/*!*/ substMap) {
Contract.Requires(cce.NonNullDictionaryAndValues(substMap));
if (trigs != null) {
@@ -6231,7 +6231,7 @@ namespace Microsoft.Dafny {
if (!anyArgSubst) {
newArgs = attrs.Args;
}
-
+
Attributes prev = SubstAttributes(attrs.Prev, receiverReplacement, substMap);
if (newArgs != attrs.Args || prev != attrs.Prev) {
return new Attributes(attrs.Name, newArgs, prev);
@@ -6239,6 +6239,6 @@ namespace Microsoft.Dafny {
}
return attrs;
}
-
+
}
-} \ No newline at end of file
+}
diff --git a/Source/DafnyDriver/DafnyDriver.cs b/Source/DafnyDriver/DafnyDriver.cs
index 73f7fc71..d8d0e0e0 100644
--- a/Source/DafnyDriver/DafnyDriver.cs
+++ b/Source/DafnyDriver/DafnyDriver.cs
@@ -8,7 +8,7 @@
// - main program for taking a Dafny program and verifying it
//---------------------------------------------------------------------------------------------
-namespace Microsoft.Boogie
+namespace Microsoft.Boogie
{
using System;
using System.IO;
@@ -22,7 +22,7 @@ namespace Microsoft.Boogie
using VC;
using AI = Microsoft.AbstractInterpretationFramework;
-/*
+/*
The following assemblies are referenced because they are needed at runtime, not at compile time:
BaseTypes
Provers.Z3
@@ -33,24 +33,28 @@ namespace Microsoft.Boogie
{
// ------------------------------------------------------------------------
// Main
-
- public static void Main (string[] args)
+
+ public static int Main (string[] args)
{Contract.Requires(cce.NonNullElements(args));
//assert forall{int i in (0:args.Length); args[i] != null};
+ ExitValue exitValue = ExitValue.VERIFIED;
CommandLineOptions.Clo.RunningBoogieFromCommandLine = true;
if (CommandLineOptions.Clo.Parse(args) != 1)
{
+ exitValue = ExitValue.PREPROCESSING_ERROR;
goto END;
}
if (CommandLineOptions.Clo.Files.Count == 0)
{
ErrorWriteLine("*** Error: No input files were specified.");
+ exitValue = ExitValue.PREPROCESSING_ERROR;
goto END;
}
if (CommandLineOptions.Clo.XmlSink != null) {
string errMsg = CommandLineOptions.Clo.XmlSink.Open();
if (errMsg != null) {
ErrorWriteLine("*** Error: " + errMsg);
+ exitValue = ExitValue.PREPROCESSING_ERROR;
goto END;
}
}
@@ -58,17 +62,17 @@ namespace Microsoft.Boogie
{
Console.WriteLine(CommandLineOptions.Clo.Version);
}
- if (CommandLineOptions.Clo.ShowEnv == CommandLineOptions.ShowEnvironment.Always)
+ if (CommandLineOptions.Clo.ShowEnv == CommandLineOptions.ShowEnvironment.Always)
{
Console.WriteLine("---Command arguments");
- foreach (string arg in args)
+ foreach (string arg in args)
{Contract.Assert(arg != null);
Console.WriteLine(arg);
}
Console.WriteLine("--------------------");
}
- foreach (string file in CommandLineOptions.Clo.Files)
+ foreach (string file in CommandLineOptions.Clo.Files)
{Contract.Assert(file != null);
string extension = Path.GetExtension(file);
if (extension != null) { extension = extension.ToLower(); }
@@ -76,21 +80,23 @@ namespace Microsoft.Boogie
{
ErrorWriteLine("*** Error: '{0}': Filename extension '{1}' is not supported. Input files must be Dafny programs (.dfy).", file,
extension == null ? "" : extension);
+ exitValue = ExitValue.PREPROCESSING_ERROR;
goto END;
}
}
CommandLineOptions.Clo.RunningBoogieOnSsc = false;
- ProcessFiles(CommandLineOptions.Clo.Files);
+ exitValue = ProcessFiles(CommandLineOptions.Clo.Files);
END:
if (CommandLineOptions.Clo.XmlSink != null) {
CommandLineOptions.Clo.XmlSink.Close();
}
- if (CommandLineOptions.Clo.Wait)
+ if (CommandLineOptions.Clo.Wait)
{
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
+ return (int)exitValue;
}
public static void ErrorWriteLine(string s) {Contract.Requires(s != null);
@@ -98,7 +104,7 @@ namespace Microsoft.Boogie
Console.WriteLine(s);
return;
}
-
+
// split the string up into its first line and the remaining lines
string remaining = null;
int i = s.IndexOf('\r');
@@ -109,12 +115,12 @@ namespace Microsoft.Boogie
}
s = s.Substring(0, i);
}
-
+
ConsoleColor col = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(s);
Console.ForegroundColor = col;
-
+
if (remaining != null) {
Console.WriteLine(remaining);
}
@@ -136,19 +142,21 @@ namespace Microsoft.Boogie
enum FileType { Unknown, Cil, Bpl, Dafny };
- static void ProcessFiles (List<string/*!*/>/*!*/ fileNames)
+ static ExitValue ProcessFiles (List<string/*!*/>/*!*/ fileNames)
{
Contract.Requires(cce.NonNullElements(fileNames));
+ ExitValue exitValue = ExitValue.VERIFIED;
using (XmlFileScope xf = new XmlFileScope(CommandLineOptions.Clo.XmlSink, fileNames[fileNames.Count-1])) {
Dafny.Program dafnyProgram;
string programName = fileNames.Count == 1 ? fileNames[0] : "the program";
string err = Dafny.Main.ParseCheck(fileNames, programName, out dafnyProgram);
if (err != null) {
+ exitValue = ExitValue.DAFNY_ERROR;
ErrorWriteLine(err);
} else if (dafnyProgram != null && !CommandLineOptions.Clo.NoResolve && !CommandLineOptions.Clo.NoTypecheck) {
Dafny.Translator translator = new Dafny.Translator();
Program boogieProgram = translator.Translate(dafnyProgram);
- if (CommandLineOptions.Clo.PrintFile != null)
+ if (CommandLineOptions.Clo.PrintFile != null)
{
PrintBplFile(CommandLineOptions.Clo.PrintFile, boogieProgram, false);
}
@@ -164,10 +172,11 @@ namespace Microsoft.Boogie
int errorCount, verified, inconclusives, timeOuts, outOfMemories;
PipelineOutcome oc = BoogiePipelineWithRerun(boogieProgram, bplFilename, out errorCount, out verified, out inconclusives, out timeOuts, out outOfMemories);
+ bool allOk = errorCount == 0 && inconclusives == 0 && timeOuts == 0 && outOfMemories == 0;
switch (oc) {
case PipelineOutcome.VerificationCompleted:
WriteTrailer(verified, errorCount, inconclusives, timeOuts, outOfMemories);
- if ((CommandLineOptions.Clo.Compile && errorCount == 0 && inconclusives == 0 && timeOuts == 0 && outOfMemories == 0) || CommandLineOptions.Clo.ForceCompile)
+ if ((CommandLineOptions.Clo.Compile && allOk) || CommandLineOptions.Clo.ForceCompile)
CompileDafnyProgram(dafnyProgram);
break;
case PipelineOutcome.Done:
@@ -179,8 +188,10 @@ namespace Microsoft.Boogie
// error has already been reported to user
break;
}
+ exitValue = allOk ? ExitValue.VERIFIED : ExitValue.NOT_VERIFIED;
}
}
+ return exitValue;
}
private static void CompileDafnyProgram(Dafny.Program dafnyProgram)
@@ -197,7 +208,7 @@ namespace Microsoft.Boogie
}
}
}
-
+
static void PrintBplFile (string filename, Program program, bool allowPrintDesugaring)
{
Contract.Requires(filename != null);
@@ -217,17 +228,17 @@ namespace Microsoft.Boogie
}
CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaring;
}
-
-
+
+
static bool ProgramHasDebugInfo (Program program)
{
Contract.Requires(program != null);
// We inspect the last declaration because the first comes from the prelude and therefore always has source context.
- return program.TopLevelDeclarations.Count > 0 &&
+ return program.TopLevelDeclarations.Count > 0 &&
cce.NonNull(program.TopLevelDeclarations[program.TopLevelDeclarations.Count - 1]).tok.IsValid;
}
-
-
+
+
/// <summary>
/// Inform the user about something and proceed with translation normally.
/// Print newline after the message.
@@ -254,7 +265,7 @@ namespace Microsoft.Boogie
Console.Out.Flush();
}
-
+
static void ReportBplError(IToken tok, string message, bool error)
{
@@ -324,7 +335,7 @@ namespace Microsoft.Boogie
return program;
}
}
-
+
/// <summary>
/// Resolve, type check, infer invariants for, and verify the given Boogie program.
/// The intention is that this Boogie program has been produced by translation from something
@@ -338,14 +349,14 @@ namespace Microsoft.Boogie
{Contract.Requires(program != null);
Contract.Requires(bplFileName != null);
Contract.Ensures(0 <= Contract.ValueAtReturn(out inconclusives) && 0 <= Contract.ValueAtReturn(out timeOuts));
-
-
+
+
errorCount = verified = inconclusives = timeOuts = outOfMemories = 0;
PipelineOutcome oc = ResolveAndTypecheck(program, bplFileName);
switch (oc) {
case PipelineOutcome.Done:
return oc;
-
+
case PipelineOutcome.ResolutionError:
case PipelineOutcome.TypeCheckingError:
{
@@ -365,7 +376,7 @@ namespace Microsoft.Boogie
case PipelineOutcome.ResolvedAndTypeChecked:
return InferAndVerify(program, out errorCount, out verified, out inconclusives, out timeOuts, out outOfMemories);
-
+
default:
Contract.Assert(false);throw new cce.UnreachableException(); // unexpected outcome
}
@@ -373,7 +384,8 @@ namespace Microsoft.Boogie
enum PipelineOutcome { Done, ResolutionError, TypeCheckingError, ResolvedAndTypeChecked, FatalError, VerificationCompleted }
-
+ enum ExitValue { VERIFIED = 0, PREPROCESSING_ERROR, DAFNY_ERROR, NOT_VERIFIED }
+
/// <summary>
/// Resolves and type checks the given Boogie program. Any errors are reported to the
/// console. Returns:
@@ -397,16 +409,16 @@ namespace Microsoft.Boogie
}
// ---------- Type check ------------------------------------------------------------
-
+
if (CommandLineOptions.Clo.NoTypecheck) { return PipelineOutcome.Done; }
-
+
errorCount = program.Typecheck();
if (errorCount != 0) {
Console.WriteLine("{0} type checking errors detected in {1}", errorCount, bplFileName);
return PipelineOutcome.TypeCheckingError;
}
-
- if (CommandLineOptions.Clo.PrintFile != null && CommandLineOptions.Clo.PrintDesugarings)
+
+ if (CommandLineOptions.Clo.PrintFile != null && CommandLineOptions.Clo.PrintDesugarings)
{
// if PrintDesugaring option is engaged, print the file here, after resolution and type checking
PrintBplFile(CommandLineOptions.Clo.PrintFile, program, true);
@@ -414,7 +426,7 @@ namespace Microsoft.Boogie
return PipelineOutcome.ResolvedAndTypeChecked;
}
-
+
/// <summary>
/// Given a resolved and type checked Boogie program, infers invariants for the program
/// and then attempts to verify it. Returns:
@@ -427,14 +439,14 @@ namespace Microsoft.Boogie
out int errorCount, out int verified, out int inconclusives, out int timeOuts, out int outOfMemories)
{Contract.Requires(program != null);
Contract.Ensures(0 <= Contract.ValueAtReturn(out inconclusives) && 0 <= Contract.ValueAtReturn(out timeOuts));
-
+
errorCount = verified = inconclusives = timeOuts = outOfMemories = 0;
-
+
// ---------- Infer invariants --------------------------------------------------------
-
+
// Abstract interpretation -> Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch)
Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program);
-
+
if (CommandLineOptions.Clo.LoopUnrollCount != -1) {
program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount);
}
@@ -451,9 +463,9 @@ namespace Microsoft.Boogie
// ---------- Verify ------------------------------------------------------------
if (!CommandLineOptions.Clo.Verify) { return PipelineOutcome.Done; }
-
+
#region Verify each implementation
-
+
#if ROB_DEBUG
string now = DateTime.Now.ToString().Replace(' ','-').Replace('/','-').Replace(':','-');
System.IO.StreamWriter w = new System.IO.StreamWriter(@"\temp\batch_"+now+".bpl");
@@ -470,7 +482,7 @@ namespace Microsoft.Boogie
} else
{
vcgen = new VCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend);
- }
+ }
}
catch (ProverException e)
{
@@ -636,7 +648,7 @@ namespace Microsoft.Boogie
else
{
// for ErrorTrace == 1 restrict the output;
- // do not print tokens with -17:-4 as their location because they have been
+ // do not print tokens with -17:-4 as their location because they have been
// introduced in the translation and do not give any useful feedback to the user
if (!(CommandLineOptions.Clo.ErrorTrace == 1 && b.tok.line == -17 && b.tok.col == -4))
{
@@ -670,9 +682,9 @@ namespace Microsoft.Boogie
cce.NonNull(CommandLineOptions.Clo.TheProverFactory).Close();
#endregion
-
+
return PipelineOutcome.VerificationCompleted;
}
-
+
}
}
diff --git a/Source/DafnyDriver/DafnyDriver.csproj b/Source/DafnyDriver/DafnyDriver.csproj
index fb68eefd..cf88eed4 100644
--- a/Source/DafnyDriver/DafnyDriver.csproj
+++ b/Source/DafnyDriver/DafnyDriver.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -140,11 +140,11 @@
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
-</Project> \ No newline at end of file
+</Project>
diff --git a/Source/Model/Model.cs b/Source/Model/Model.cs
index 50a8f45c..06f680fa 100644
--- a/Source/Model/Model.cs
+++ b/Source/Model/Model.cs
@@ -776,6 +776,5 @@ namespace Microsoft.Boogie
p.Run();
return p.resModels;
}
-
}
}
diff --git a/Source/Provers/Z3/TypeDeclCollector.cs b/Source/Provers/Z3/TypeDeclCollector.cs
index 2e695215..19c88409 100644
--- a/Source/Provers/Z3/TypeDeclCollector.cs
+++ b/Source/Provers/Z3/TypeDeclCollector.cs
@@ -193,7 +193,12 @@ void ObjectInvariant()
// there are a couple cases where operators have to be
// registered by generating appropriate Z3 statements
- if (node.Op is VCExprBvConcatOp) {
+ if (node.Op is VCExprBvOp) {
+ if (NativeBv) {
+ RegisterType(node[0].Type);
+ RegisterType(node.Type);
+ }
+ } else if (node.Op is VCExprBvConcatOp) {
//
if (NativeBv) {
RegisterType(node[0].Type);
diff --git a/Test/VSI-Benchmarks/b3.dfy b/Test/VSI-Benchmarks/b3.dfy
index 3de94555..7cf3de07 100644
--- a/Test/VSI-Benchmarks/b3.dfy
+++ b/Test/VSI-Benchmarks/b3.dfy
@@ -12,13 +12,13 @@
class Queue<T> {
var contents: seq<T>;
- method Init();
+ method Init()
modifies this;
ensures |contents| == 0;
- method Enqueue(x: T);
+ method Enqueue(x: T)
modifies this;
ensures contents == old(contents) + [x];
- method Dequeue() returns (x: T);
+ method Dequeue() returns (x: T)
requires 0 < |contents|;
modifies this;
ensures contents == old(contents)[1..] && x == old(contents)[0];
@@ -33,7 +33,7 @@ class Queue<T> {
}
class Comparable {
- function AtMost(c: Comparable): bool;
+ function AtMost(c: Comparable): bool
reads this, c;
}
@@ -96,7 +96,6 @@ class Benchmark3 {
}
-
method RemoveMin(q: Queue<int>) returns (m: int, k: int) //m is the min, k is m's index in q
requires q != null && |q.contents| != 0;
modifies q;
diff --git a/Test/VSI-Benchmarks/b7.dfy b/Test/VSI-Benchmarks/b7.dfy
index f34f5c00..d6759c5f 100644
--- a/Test/VSI-Benchmarks/b7.dfy
+++ b/Test/VSI-Benchmarks/b7.dfy
@@ -8,13 +8,13 @@
class Queue<T> {
var contents: seq<T>;
- method Init();
+ method Init()
modifies this;
ensures |contents| == 0;
- method Enqueue(x: T);
+ method Enqueue(x: T)
modifies this;
ensures contents == old(contents) + [x];
- method Dequeue() returns (x: T);
+ method Dequeue() returns (x: T)
requires 0 < |contents|;
modifies this;
ensures contents == old(contents)[1..] && x == old(contents)[0];
@@ -101,7 +101,7 @@ class Stream {
class Client {
- method Sort(q: Queue<int>) returns (r: Queue<int>, perm:seq<int>);
+ method Sort(q: Queue<int>) returns (r: Queue<int>, perm:seq<int>)
requires q != null;
modifies q;
ensures r != null && fresh(r);
diff --git a/Test/VSI-Benchmarks/b8.dfy b/Test/VSI-Benchmarks/b8.dfy
index 0c9d1186..383bccfd 100644
--- a/Test/VSI-Benchmarks/b8.dfy
+++ b/Test/VSI-Benchmarks/b8.dfy
@@ -6,13 +6,13 @@
class Queue<T> {
var contents: seq<T>;
- method Init();
+ method Init()
modifies this;
ensures |contents| == 0;
- method Enqueue(x: T);
+ method Enqueue(x: T)
modifies this;
ensures contents == old(contents) + [x];
- method Dequeue() returns (x: T);
+ method Dequeue() returns (x: T)
requires 0 < |contents|;
modifies this;
ensures contents == old(contents)[1..] && x == old(contents)[0];
@@ -28,7 +28,7 @@ class Queue<T> {
class Glossary {
- method Sort(q: Queue<Word>) returns (r: Queue<Word>, perm:seq<int>);
+ method Sort(q: Queue<Word>) returns (r: Queue<Word>, perm:seq<int>)
requires q != null;
modifies q;
ensures r != null && fresh(r);
@@ -149,29 +149,29 @@ class Glossary {
class Word
{
- function AtMost(w:Word) :bool;
+ function AtMost(w: Word): bool
}
class ReaderStream {
- ghost var footprint:set<object>;
- var isOpen:bool;
+ ghost var footprint: set<object>;
+ var isOpen: bool;
- function Valid():bool
- reads this, footprint;
+ function Valid(): bool
+ reads this, footprint;
{
null !in footprint && this in footprint && isOpen
}
method Open() //reading
- modifies this;
- ensures Valid() && fresh(footprint -{this});
+ modifies this;
+ ensures Valid() && fresh(footprint -{this});
{
footprint := {this};
isOpen :=true;
}
- method GetWord()returns(x:Word)
- requires Valid() ;
+ method GetWord() returns (x: Word)
+ requires Valid();
modifies footprint;
ensures Valid() && fresh(footprint - old(footprint));
{
@@ -190,8 +190,8 @@ class WriterStream {
var stream:seq<int>;
var isOpen:bool;
- function Valid():bool
- reads this, footprint;
+ function Valid(): bool
+ reads this, footprint;
{
null !in footprint && this in footprint && isOpen
}
diff --git a/Test/bitvectors/Answer b/Test/bitvectors/Answer
index 6f4068c6..f0f65b04 100644
--- a/Test/bitvectors/Answer
+++ b/Test/bitvectors/Answer
@@ -49,6 +49,9 @@ Boogie program verifier finished with 0 verified, 1 error
-------------------- bv8.bpl --------------------
Boogie program verifier finished with 2 verified, 0 errors
+-------------------- bv10.bpl --------------------
+
+Boogie program verifier finished with 1 verified, 0 errors
-------------------- bv9.bpl /bv:z /proverOpt:OPTIMIZE_FOR_BV=true --------------------
Boogie program verifier finished with 1 verified, 0 errors
diff --git a/Test/bitvectors/bv10.bpl b/Test/bitvectors/bv10.bpl
new file mode 100644
index 00000000..7c325d95
--- /dev/null
+++ b/Test/bitvectors/bv10.bpl
@@ -0,0 +1,10 @@
+var x: bv32;
+
+procedure main()
+modifies x;
+{
+
+ x := 0bv32;
+ assume x == 1bv32;
+ assert false;
+}
diff --git a/Test/bitvectors/runtest.bat b/Test/bitvectors/runtest.bat
index fd5136f5..a0480645 100644
--- a/Test/bitvectors/runtest.bat
+++ b/Test/bitvectors/runtest.bat
@@ -11,7 +11,7 @@ for %%f in (arrays.bpl bv0.bpl bv1.bpl bv2.bpl bv3.bpl bv4.bpl bv7.bpl) do (
echo -------------------- bv4.bpl - /bv:n --------------------
%BGEXE% /bv:n %* /logPrefix:-1 bv4.bpl
-for %%f in (bv5.bpl bv6.bpl bv8.bpl) do (
+for %%f in (bv5.bpl bv6.bpl bv8.bpl bv10.bpl) do (
echo -------------------- %%f --------------------
%BGEXE% %* %%f
)
diff --git a/Test/dafny0/Answer b/Test/dafny0/Answer
index a29c64fa..7a972f22 100644
--- a/Test/dafny0/Answer
+++ b/Test/dafny0/Answer
@@ -657,7 +657,7 @@ Execution trace:
(0,0): anon8
(0,0): anon14_Then
-Dafny program verifier finished with 16 verified, 11 errors
+Dafny program verifier finished with 19 verified, 11 errors
-------------------- ControlStructures.dfy --------------------
ControlStructures.dfy(5,3): Error: missing case in case statement: Blue
diff --git a/Test/dafny0/Basics.dfy b/Test/dafny0/Basics.dfy
index 1ae5b9c4..6aa1e34d 100644
--- a/Test/dafny0/Basics.dfy
+++ b/Test/dafny0/Basics.dfy
@@ -171,3 +171,17 @@ method SwapEm(a: int, b: int) returns (x: int, y: int)
{
x, y := b, a;
}
+
+function method abs(a:int): int
+{
+ if a <= 0 then -a else a
+}
+// test of verifier using euclidean division.
+method EuclideanTest(a: int, b: int)
+ requires b != 0;
+{
+ var q, r := a / b, a % b;
+ assert 0 <= r < abs(b);
+ assert a == b * q + r;
+ assert (a/b) * b + a % b == a;
+} \ No newline at end of file
diff --git a/Test/dafny0/Definedness.dfy b/Test/dafny0/Definedness.dfy
index 8df1a7c5..2063eec4 100644
--- a/Test/dafny0/Definedness.dfy
+++ b/Test/dafny0/Definedness.dfy
@@ -44,17 +44,17 @@ class SoWellformed {
c := true;
}
- method P(a: SoWellformed, b: int) returns (c: bool, d: SoWellformed);
+ method P(a: SoWellformed, b: int) returns (c: bool, d: SoWellformed)
requires next != null;
modifies this;
ensures next.xyz < 100; // error: may not be well-defined (if body sets next to null)
- method Q(a: SoWellformed, s: set<SoWellformed>) returns (c: bool, d: SoWellformed);
+ method Q(a: SoWellformed, s: set<SoWellformed>) returns (c: bool, d: SoWellformed)
requires next != null;
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);
+ method R(a: SoWellformed, s: set<SoWellformed>) returns (c: bool, d: SoWellformed)
requires next != null && this !in s;
modifies s;
ensures next.xyz < 100; // fine
@@ -175,7 +175,7 @@ class StatementTwoShoes {
}
function G(w: int): int { 5 }
- function method H(x: int): int;
+ function method H(x: int): int
method V(s: set<StatementTwoShoes>, a: int, b: int)
modifies s;
diff --git a/Test/dafny0/NatTypes.dfy b/Test/dafny0/NatTypes.dfy
index 53d3bf03..e56b4122 100644
--- a/Test/dafny0/NatTypes.dfy
+++ b/Test/dafny0/NatTypes.dfy
@@ -42,7 +42,7 @@ method Generic<T>(i: int, t0: T, t1: T) returns (r: T) {
r := t1;
}
-function method FenEric<T>(t0: T, t1: T): T;
+function method FenEric<T>(t0: T, t1: T): T
datatype Pair<T> = Pr(T, T);
diff --git a/Test/dafny0/Termination.dfy b/Test/dafny0/Termination.dfy
index d4d1dfcf..f31935af 100644
--- a/Test/dafny0/Termination.dfy
+++ b/Test/dafny0/Termination.dfy
@@ -87,7 +87,7 @@ class Termination {
}
}
- method Traverse<T>(a: List<T>) returns (val: T, b: List<T>);
+ method Traverse<T>(a: List<T>) returns (val: T, b: List<T>)
requires a != List.Nil;
ensures a == List.Cons(val, b);
}
diff --git a/Test/dafny0/TypeAntecedents.dfy b/Test/dafny0/TypeAntecedents.dfy
index 2bedd37d..710e9838 100644
--- a/Test/dafny0/TypeAntecedents.dfy
+++ b/Test/dafny0/TypeAntecedents.dfy
@@ -88,7 +88,7 @@ method N() returns (k: MyClass)
k := new MyClass;
}
-function NF(): MyClass;
+function NF(): MyClass
function TakesADatatype(a: List): int { 12 }
diff --git a/Test/dafny0/TypeParameters.dfy b/Test/dafny0/TypeParameters.dfy
index a3698dc0..8f3f8b87 100644
--- a/Test/dafny0/TypeParameters.dfy
+++ b/Test/dafny0/TypeParameters.dfy
@@ -17,7 +17,7 @@ class C<U> {
assert kz && (G() || !G());
}
- function G<Y>(): Y;
+ function G<Y>(): Y
}
class SetTest {
@@ -99,7 +99,7 @@ class CClient {
// -------------------------
-static function IsCelebrity<Person>(c: Person, people: set<Person>): bool;
+static function IsCelebrity<Person>(c: Person, people: set<Person>): bool
requires c == c || c in people;
method FindCelebrity3(people: set<int>, ghost c: int)
@@ -110,7 +110,7 @@ method FindCelebrity3(people: set<int>, ghost c: int)
b := F(c, people);
}
-static function F(c: int, people: set<int>): bool;
+static function F(c: int, people: set<int>): bool
requires IsCelebrity(c, people);
function RogerThat<G>(g: G): G
@@ -153,8 +153,8 @@ method LoopyRoger(n: int)
class TyKn_C<T> {
var x: T;
- function G(): T;
- method M() returns (t: T);
+ function G(): T
+ method M() returns (t: T)
}
class TyKn_K {
diff --git a/Test/dafny1/Celebrity.dfy b/Test/dafny1/Celebrity.dfy
index 74512e01..21b895aa 100644
--- a/Test/dafny1/Celebrity.dfy
+++ b/Test/dafny1/Celebrity.dfy
@@ -1,6 +1,6 @@
// Celebrity example, inspired by the Rodin tutorial
-static function method Knows<Person>(a: Person, b: Person): bool;
+static function method Knows<Person>(a: Person, b: Person): bool
requires a != b; // forbid asking about the reflexive case
static function IsCelebrity<Person>(c: Person, people: set<Person>): bool
diff --git a/Test/dafny1/Rippling.dfy b/Test/dafny1/Rippling.dfy
index fdce6dc7..39e14ea5 100644
--- a/Test/dafny1/Rippling.dfy
+++ b/Test/dafny1/Rippling.dfy
@@ -163,7 +163,7 @@ function mapF(xs: List): List
case Nil => Nil
case Cons(y, ys) => Cons(HardcodedUninterpretedFunction(y), mapF(ys))
}
-function HardcodedUninterpretedFunction(n: Nat): Nat;
+function HardcodedUninterpretedFunction(n: Nat): Nat
function takeWhileAlways(hardcodedResultOfP: Bool, xs: List): List
{
@@ -195,7 +195,7 @@ function filterP(xs: List): List
then Cons(y, filterP(ys))
else filterP(ys)
}
-function HardcodedUninterpretedPredicate(n: Nat): Bool;
+function HardcodedUninterpretedPredicate(n: Nat): Bool
function insort(n: Nat, xs: List): List
{
diff --git a/Test/dafny1/UltraFilter.dfy b/Test/dafny1/UltraFilter.dfy
index 189ff2b5..c8419890 100644
--- a/Test/dafny1/UltraFilter.dfy
+++ b/Test/dafny1/UltraFilter.dfy
@@ -29,7 +29,7 @@ class UltraFilter<G> {
}
// Dafny currently does not have a set comprehension expression, so this method stub will have to do
- method H(f: set<set<G>>, S: set<G>, M: set<G>) returns (h: set<set<G>>);
+ method H(f: set<set<G>>, S: set<G>, M: set<G>) returns (h: set<set<G>>)
ensures (forall X :: X in h <==> M + X in f);
method Lemma_HIsFilter(h: set<set<G>>, f: set<set<G>>, S: set<G>, M: set<G>)