Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Java mocking #2024

Open
wants to merge 92 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 79 commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
da26977
Add devcontainer for vscode
ericmercer Sep 28, 2021
e783f00
Remove the pre-commit hook installation
ericmercer Sep 28, 2021
5709c42
Add /generateTestBoogie command to elegantly print boogie
matt4530 Oct 9, 2021
c4112b9
Separate modifications into different files
matt4530 Oct 9, 2021
82ccbd9
Flush output to dump entire boogie string instead of just 2kb.
matt4530 Oct 9, 2021
20ddd04
revert comments
matt4530 Oct 14, 2021
74acfa1
Merge pull request #1 from UnknownGuardian/byu-dafny
ericmercer Oct 14, 2021
aa1cdcb
Mocking for {:test} attribute
Dargones Oct 21, 2021
7ab10f0
Fix accidental change
Dargones Oct 21, 2021
c307c4e
A different test and a fix
Dargones Oct 21, 2021
4300897
fix(semanticCommit): learning new things every day also removed that …
Dargones Oct 21, 2021
a3405f7
fix: making the pr semantic
Dargones Oct 21, 2021
a832b13
Merge branch 'dafny-lang:master' into counterexamples
Dargones Nov 2, 2021
b6e2df4
Mocks using extern
Dargones Nov 2, 2021
f61a3a3
Dummy commit
Dargones Jan 25, 2022
9648bb6
Merge branch 'dafny-lang:master' into testFrameworkCSharp
Dargones Jan 25, 2022
9d69721
Mocking First Steps
Dargones Jan 27, 2022
58c47ba
Basic Argument Matching
Dargones Jan 29, 2022
c9fab47
Mock Fields
Dargones Jan 30, 2022
bf8ab5f
MockWriter class
Dargones Jan 30, 2022
6f5c75b
Merge branch 'dafny-lang:master' into testFrameworkCSharp
Dargones Jan 30, 2022
2237bd3
Improve Readability
Dargones Jan 30, 2022
e96574e
Merge branch 'testFrameworkCSharp' of https://github.com/Dargones/daf…
Dargones Jan 30, 2022
dbe04a0
Merge branch 'dafny-lang:master' into testFrameworkCSharp
Dargones Feb 10, 2022
1b20628
Compiler style changes
Dargones Feb 10, 2022
67bb487
Merge branch 'testFrameworkCSharp' of https://github.com/Dargones/daf…
Dargones Feb 10, 2022
d643d70
More tests
Dargones Feb 10, 2022
1eddfc7
Unique Identifiers
Dargones Feb 10, 2022
e812b43
Arbitrary Argument Order
Dargones Feb 10, 2022
5f4aa99
More detailed documentation
Dargones Feb 10, 2022
28df976
compileMocks attribute
Dargones Feb 10, 2022
1af8f55
CrossReferencing
Dargones Feb 10, 2022
de0945f
Add basic support for mocking in Java
cassidywaldrip Feb 11, 2022
651b360
inject xunit method source glue code
tbean79 Feb 15, 2022
22772ea
Merge branch 'testFrameworkCSharp' of https://github.com/Dargones/daf…
tbean79 Feb 15, 2022
5ea83e0
Performance and code style
Dargones Feb 17, 2022
a251c4c
Move mockign to separate file
Dargones Feb 17, 2022
3493053
List import fix
Dargones Feb 18, 2022
52dcf8e
Merge branch 'master' into testFrameworkCSharp
keyboardDrummer Feb 21, 2022
361dd56
compiles param tests to java
tbean79 Feb 23, 2022
33625f4
name structure converter dependent on method name
tbean79 Feb 24, 2022
b1244f2
Merge branch 'testFrameworkCSharp' of https://github.com/Dargones/daf…
tbean79 Feb 24, 2022
2551cd2
Merge branch 'paramTests' of https://github.com/Dargones/dafny into p…
tbean79 Mar 3, 2022
e4116c0
Add support for Java mocking
cassidywaldrip Mar 7, 2022
cf3b1cb
Merge branch 'java-mocks' of https://github.com/Dargones/dafny into j…
tbean79 Mar 7, 2022
0949bc3
add documentation and styling
tbean79 Mar 9, 2022
a3e1e7a
inject test annotation for java
tbean79 Mar 9, 2022
0f50c74
use whitespace
tbean79 Mar 9, 2022
1c202bd
Merge pull request #10 from byu-dafny/paramTests
tbean79 Mar 9, 2022
7b8780e
update dotnet version
tbean79 Mar 9, 2022
8ed8a08
Merge branch 'master' into java-mocks
tbean79 Mar 9, 2022
260f7c3
Merge pull request #9 from byu-dafny/java-mocks
tbean79 Mar 9, 2022
ce3155b
qualify console var
tbean79 Mar 9, 2022
de9ea45
downgrade dotnet version
tbean79 Mar 9, 2022
39516ce
update attr docs
tbean79 Mar 15, 2022
f0b61ed
remove global.json
tbean79 Mar 15, 2022
8948da3
make param docs clearer
tbean79 Mar 18, 2022
eebea9c
fix underscore names
tbean79 Mar 23, 2022
f0cfb42
Merge pull request #11 from byu-dafny/fix-underscores
tbean79 Mar 23, 2022
e58560d
Delete unneccessary comment
cassidywaldrip Mar 30, 2022
3fbe9b6
Fix merge conflicts
cassidywaldrip Mar 30, 2022
67fcc38
Add support for fresh
cassidywaldrip Apr 3, 2022
469d5fd
Pass in mock or fresh as arguments
cassidywaldrip Apr 3, 2022
724a22f
omit param test code
tbean79 Apr 5, 2022
40e8932
Clean up files
cassidywaldrip Apr 15, 2022
05b61d9
Merge branch 'merge-mocking-changes' of github.com:byu-dafny/dafny in…
cassidywaldrip Apr 15, 2022
650345a
Update Source/Dafny/Compilers/Compiler-python.cs
cassidywaldrip Apr 20, 2022
0735512
Update Source/Dafny/Compilers/Synthesizer-Java.cs
cassidywaldrip Apr 20, 2022
71e57e6
Get up to date with Dafny
cassidywaldrip Apr 21, 2022
666174c
Fix TestGenerationOptions
cassidywaldrip Apr 21, 2022
341a42e
Remove unnecessary comment in Compiler-Csharp.cs
cassidywaldrip May 2, 2022
987de0c
Update Compiler-cpp.cs
cassidywaldrip May 2, 2022
a526e4d
Remove unnecessary comment in Compiler-go.cs
cassidywaldrip May 2, 2022
9bd1499
Remove unnecessary comment in Compiler-js.cs
cassidywaldrip May 2, 2022
5aa376a
Update Source/Dafny/Compilers/SinglePassCompiler.cs
cassidywaldrip May 2, 2022
b5ecf63
Add fresh to C#
cassidywaldrip May 2, 2022
5026caa
Add mock and fresh annotations to unit tests
cassidywaldrip Jun 21, 2022
7a66575
Merge remote-tracking branch 'origin/master' into merge-mocking-changes
cassidywaldrip Jul 13, 2022
9b6b2fb
Remove devcontainer, complete requested changes
cassidywaldrip Jul 13, 2022
be0b653
Get up to date with master
cassidywaldrip Sep 15, 2022
0016a75
Merge pull request #12 from dafny-lang/master
cassidywaldrip Sep 16, 2022
04da7c4
Change from mocks to spys
cassidywaldrip Sep 16, 2022
eb491e8
Merge branch 'master' into merge-mocking-changes
cassidywaldrip Sep 16, 2022
90eded1
Merge branch 'master' into merge-mocking-changes
cassidywaldrip Sep 20, 2022
5bb3719
Merge branch 'dafny-lang:master' into master
cassidywaldrip Sep 20, 2022
b8681f1
Merge branch 'master' into merge-mocking-changes
cassidywaldrip Sep 20, 2022
938d7f5
Merge branch 'dafny-lang:master' into master
cassidywaldrip Sep 22, 2022
e2b9c91
Merge branch 'merge-mocking-changes' of github.com:byu-dafny/dafny in…
cassidywaldrip Sep 22, 2022
ec88434
Get merge-mocking-changes up to date with master
cassidywaldrip Sep 22, 2022
ee85070
Make requested changes
cassidywaldrip Sep 22, 2022
0ca44d7
Add Synthesizer base class
cassidywaldrip Oct 6, 2022
d7def3b
Remove synthesis from Java unsupported features
cassidywaldrip Oct 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,10 @@ Source/.vs

node_modules/
package.json
package-lock.json
package-lock.json


lecture_programs
natural_doc
natural_config
Working\ Data
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure?

cassidywaldrip marked this conversation as resolved.
Show resolved Hide resolved
17 changes: 17 additions & 0 deletions Scripts/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

# find the source directory for this script even if it's been symlinked [issue #185]
# from https://stackoverflow.com/questions/59895/
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
DAFNY_ROOT="$( cd -P "$( dirname $( dirname "$SOURCE" ))" && pwd )"

cd $DAFNY_ROOT
# pre-commit install
npm install bignumber.js
cd $DAFNY_ROOT/Binaries
ln -s /opt/z3/z3-4.8.5-x64-ubuntu-16.04/ z3
cassidywaldrip marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions Source/Dafny.sln
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9542E008-355F-4A62-B262-A8DA314DA8C1}"
ProjectSection(SolutionItems) = preProject
version.cs = version.cs
global.json = global.json
cassidywaldrip marked this conversation as resolved.
Show resolved Hide resolved
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTests", "IntegrationTests\IntegrationTests.csproj", "{A4BC2C77-3A48-4917-AA22-41978DFFE24E}"
Expand Down
4 changes: 4 additions & 0 deletions Source/Dafny/Compilers/Compiler-Csharp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,10 @@ public ConcreteSyntaxTree SynthesizeMethod(Method method, List<TypeArgumentInsta
return csharpSynthesizer.SynthesizeMethod(method, typeArgs, createBody, Writer(method.IsStatic, createBody, method), forBodyInheritance, lookasideBody);
}

public ConcreteSyntaxTree CreateFreshMethod(Method m) {
return csharpSynthesizer.CreateFreshMethod(m, Writer(m.IsStatic, true, m));
}

public ConcreteSyntaxTree /*?*/ CreateFunction(string name, List<TypeArgumentInstantiation> typeArgs, List<Formal> formals, Type resultType, Bpl.IToken tok, bool isStatic, bool createBody, MemberDecl member, bool forBodyInheritance, bool lookasideBody) {
return Compiler.CreateFunction(name, typeArgs, formals, resultType, tok, isStatic, createBody, member, Writer(isStatic, createBody, member), forBodyInheritance, lookasideBody);
}
Expand Down
4 changes: 4 additions & 0 deletions Source/Dafny/Compilers/Compiler-cpp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,10 @@ public ConcreteSyntaxTree SynthesizeMethod(Method m, List<TypeArgumentInstantiat
throw new UnsupportedFeatureException(m.tok, Feature.MethodSynthesis);
}

public ConcreteSyntaxTree CreateFreshMethod(Method m) {
throw new NotImplementedException();
}

public ConcreteSyntaxTree/*?*/ CreateFunction(string name, List<TypeArgumentInstantiation>/*?*/ typeArgs, List<Formal> formals, Type resultType, Bpl.IToken tok, bool isStatic, bool createBody, MemberDecl member, bool forBodyInheritance, bool lookasideBody) {
return Compiler.CreateFunction(member.EnclosingClass.CompileName, member.EnclosingClass.TypeArgs, name, typeArgs, formals, resultType, tok, isStatic, createBody, member, MethodDeclWriter, MethodWriter, lookasideBody);
}
Expand Down
4 changes: 4 additions & 0 deletions Source/Dafny/Compilers/Compiler-go.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,10 @@ public ConcreteSyntaxTree SynthesizeMethod(Method m, List<TypeArgumentInstantiat
throw new UnsupportedFeatureException(m.tok, Feature.MethodSynthesis);
}

public ConcreteSyntaxTree CreateFreshMethod(Method m) {
throw new NotImplementedException();
}

public ConcreteSyntaxTree/*?*/ CreateFunction(string name, List<TypeArgumentInstantiation> typeArgs, List<Formal> formals, Type resultType, Bpl.IToken tok, bool isStatic, bool createBody, MemberDecl member, bool forBodyInheritance, bool lookasideBody) {
return Compiler.CreateFunction(name, typeArgs, formals, resultType, tok, isStatic, createBody, member, ClassName, AbstractMethodWriter, ConcreteMethodWriter, forBodyInheritance, lookasideBody);
}
Expand Down
78 changes: 74 additions & 4 deletions Source/Dafny/Compilers/Compiler-java.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public override void OnPreCompile(ErrorReporter reporter, ReadOnlyCollection<str

public override string TargetLanguage => "Java";
public override string TargetExtension => "java";

// True if the most recently visited AST has a method annotated with {:synthesize}:
protected bool Synthesize = false;
public override string TargetBasename(string dafnyProgramName) =>
TransformToClassName(base.TargetBasename(dafnyProgramName));
public override string TargetBaseDir(string dafnyProgramName) =>
Expand Down Expand Up @@ -182,6 +185,22 @@ protected override void DeclareSpecificOutCollector(string collectorVarName, Con
wr.Write($"{returnedTypes[0]} {collectorVarName} = ");
}
}

/// <summary>
/// Return true if the AST contains a method annotated with an attribute
/// </summary>
private static bool ProgramHasMethodsWithAttr(Program p, String attr) {
foreach (var module in p.Modules()) {
foreach (ICallable callable in ModuleDefinition.AllCallables(
module.TopLevelDecls)) {
if ((callable is Method method) &&
Attributes.Contains(method.Attributes, attr)) {
return true;
}
}
}
return false;
}
protected override void EmitCastOutParameterSplits(string outCollector, List<string> lhsNames,
ConcreteSyntaxTree wr, List<Type> formalTypes, List<Type> lhsTypes, Bpl.IToken tok) {
var wOuts = new List<ConcreteSyntaxTree>();
Expand Down Expand Up @@ -322,6 +341,7 @@ protected override void EmitHeader(Program program, ConcreteSyntaxTree wr) {
wr.WriteLine($"// Dafny program {program.Name} compiled into Java");
ModuleName = program.MainMethod != null ? "main" : Path.GetFileNameWithoutExtension(program.Name);
wr.WriteLine();
Synthesize = ProgramHasMethodsWithAttr(program, "synthesize");
// Keep the import writers so that we can import subsequent modules into the main one
EmitImports(wr, out RootImportWriter);
wr.WriteLine();
Expand Down Expand Up @@ -411,6 +431,7 @@ protected class ClassWriter : IClassWriter {
public readonly ConcreteSyntaxTree InstanceMemberWriter;
public readonly ConcreteSyntaxTree StaticMemberWriter;
public readonly ConcreteSyntaxTree CtorBodyWriter;
private readonly JavaSynthesizer javaSynthesizer;

public ClassWriter(JavaCompiler compiler, ConcreteSyntaxTree instanceMemberWriter, ConcreteSyntaxTree ctorBodyWriter, ConcreteSyntaxTree staticMemberWriter = null) {
Contract.Requires(compiler != null);
Expand All @@ -419,6 +440,7 @@ public ClassWriter(JavaCompiler compiler, ConcreteSyntaxTree instanceMemberWrite
this.InstanceMemberWriter = instanceMemberWriter;
this.CtorBodyWriter = ctorBodyWriter;
this.StaticMemberWriter = staticMemberWriter ?? instanceMemberWriter;
this.javaSynthesizer = new JavaSynthesizer(Compiler, ErrorWriter());
}

public ConcreteSyntaxTree Writer(bool isStatic, bool createBody, MemberDecl/*?*/ member) {
Expand All @@ -434,8 +456,13 @@ public ConcreteSyntaxTree Writer(bool isStatic, bool createBody, MemberDecl/*?*/
return Compiler.CreateMethod(m, typeArgs, createBody, Writer(m.IsStatic, createBody, m), forBodyInheritance, lookasideBody);
}

public ConcreteSyntaxTree SynthesizeMethod(Method m, List<TypeArgumentInstantiation> typeArgs, bool createBody, bool forBodyInheritance, bool lookasideBody) {
throw new UnsupportedFeatureException(m.tok, Feature.MethodSynthesis);
public ConcreteSyntaxTree CreateFreshMethod(Method m) {
return javaSynthesizer.CreateFreshMethod(m, Writer(m.IsStatic, true, m));
}

public ConcreteSyntaxTree SynthesizeMethod(Method method, List<TypeArgumentInstantiation> typeArgs, bool createBody, bool forBodyInheritance,
bool lookasideBody) {
return javaSynthesizer.SynthesizeMethod(method, typeArgs, createBody, Writer(method.IsStatic, createBody, method), forBodyInheritance, lookasideBody);
}

public ConcreteSyntaxTree/*?*/ CreateFunction(string name, List<TypeArgumentInstantiation> typeArgs, List<Formal> formals, Type resultType, Bpl.IToken tok, bool isStatic, bool createBody, MemberDecl member, bool forBodyInheritance, bool lookasideBody) {
Expand Down Expand Up @@ -501,6 +528,7 @@ protected override void DeclareLocalVar(string name, Type /*?*/ type, Bpl.IToken
}
return wGet;
}

protected ConcreteSyntaxTree CreateMethod(Method m, List<TypeArgumentInstantiation> typeArgs, bool createBody, ConcreteSyntaxTree wr, bool forBodyInheritance, bool lookasideBody) {
if (m.IsExtern(out _, out _) && (m.IsStatic || m is Constructor)) {
// No need for an abstract version of a static method or a constructor
Expand All @@ -522,7 +550,7 @@ protected ConcreteSyntaxTree CreateMethod(Method m, List<TypeArgumentInstantiati
}
var customReceiver = createBody && !forBodyInheritance && NeedsCustomReceiver(m);
var receiverType = UserDefinedType.FromTopLevelDecl(m.tok, m.EnclosingClass);
wr.Write("public {0}{1}", !createBody && !(m.EnclosingClass is TraitDecl) ? "abstract " : "", m.IsStatic || customReceiver ? "static " : "");
wr.Write("public {0}{1}", !createBody && m.EnclosingClass is not TraitDecl ? "abstract " : "", m.IsStatic || customReceiver ? "static " : "");
wr.Write(TypeParameters(TypeArgumentInstantiation.ToFormals(ForTypeParameters(typeArgs, m, lookasideBody)), " "));
wr.Write("{0} {1}", targetReturnTypeReplacement ?? "void", IdName(m));
wr.Write("(");
Expand All @@ -541,6 +569,48 @@ protected ConcreteSyntaxTree CreateMethod(Method m, List<TypeArgumentInstantiati
}
}

internal string Keywords(bool isPublic = false, bool isStatic = false, bool isExtern = false) {
return (isPublic ? "public " : "") + (isStatic ? "static " : "") + (isExtern ? "extern " : "") + (Synthesize && !isStatic && isPublic ? "virtual " : "");
}

internal ConcreteSyntaxTree GetMethodParameters(Method m, List<TypeArgumentInstantiation> typeArgs, bool lookasideBody, bool customReceiver, string returnType) {
//var parameters = GetFunctionParameters(m.Ins, m, typeArgs, lookasideBody, customReceiver);
var parameters = new ConcreteSyntaxTree();
var sep = "";
WriteRuntimeTypeDescriptorsFormals(m, ForTypeDescriptors(typeArgs, m, lookasideBody), parameters, ref sep, tp => $"{DafnyTypeDescriptor}<{tp.CompileName}> {FormatTypeDescriptorVariable(tp)}");
if (customReceiver) {
var nt = m.EnclosingClass;
var receiverType = UserDefinedType.FromTopLevelDecl(m.tok, nt);
DeclareFormal(sep, "_this", receiverType, m.tok, true, parameters);
sep = ", ";
}
WriteFormals(sep, m.Ins, parameters);
if (returnType == "void") {
WriteFormals(parameters.Nodes.Any() ? ", " : "", m.Outs, parameters);
}
return parameters;
}

internal string GetTargetReturnTypeReplacement(Method m, ConcreteSyntaxTree wr) {
string targetReturnTypeReplacement = null;
int nonGhostOuts = 0;
int nonGhostIndex = 0;
for (int i = 0; i < m.Outs.Count; i++) {
if (!m.Outs[i].IsGhost) {
nonGhostOuts += 1;
nonGhostIndex = i;
}
}
if (nonGhostOuts == 1) {
targetReturnTypeReplacement = TypeName(m.Outs[nonGhostIndex].Type, wr, m.Outs[nonGhostIndex].tok);
} else if (nonGhostOuts > 1) {
targetReturnTypeReplacement = DafnyTupleClass(nonGhostOuts);
}

targetReturnTypeReplacement ??= "void";
return targetReturnTypeReplacement;
}

protected override ConcreteSyntaxTree EmitMethodReturns(Method m, ConcreteSyntaxTree wr) {
int nonGhostOuts = 0;
foreach (var t in m.Outs) {
Expand Down Expand Up @@ -614,7 +684,7 @@ private void EmitSuppression(ConcreteSyntaxTree wr) {
wr.WriteLine("@SuppressWarnings({\"unchecked\", \"deprecation\"})");
}

string TypeParameters(List<TypeParameter>/*?*/ targs, string suffix = "") {
internal string TypeParameters(List<TypeParameter>/*?*/ targs, string suffix = "") {
Contract.Requires(targs == null || cce.NonNullElements(targs));
Contract.Ensures(Contract.Result<string>() != null);

Expand Down
4 changes: 4 additions & 0 deletions Source/Dafny/Compilers/Compiler-js.cs
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,10 @@ public ConcreteSyntaxTree SynthesizeMethod(Method m, List<TypeArgumentInstantiat
throw new UnsupportedFeatureException(m.tok, Feature.MethodSynthesis);
}

public ConcreteSyntaxTree CreateFreshMethod(Method m) {
throw new NotImplementedException();
}

public ConcreteSyntaxTree/*?*/ CreateFunction(string name, List<TypeArgumentInstantiation> typeArgs, List<Formal> formals, Type resultType, Bpl.IToken tok, bool isStatic, bool createBody, MemberDecl member, bool forBodyInheritance, bool lookasideBody) {
return Compiler.CreateFunction(name, typeArgs, formals, resultType, tok, isStatic, createBody, member, MethodWriter, forBodyInheritance, lookasideBody);
}
Expand Down
4 changes: 4 additions & 0 deletions Source/Dafny/Compilers/Compiler-python.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ public ConcreteSyntaxTree SynthesizeMethod(Method m, List<TypeArgumentInstantiat
throw new UnsupportedFeatureException(Token.NoToken, Feature.MethodSynthesis);
}

public ConcreteSyntaxTree CreateFreshMethod(Method m) {
throw new NotImplementedException();
}

public ConcreteSyntaxTree CreateFunction(string name, List<TypeArgumentInstantiation> typeArgs,
List<Formal> formals, Type resultType, IToken tok, bool isStatic, bool createBody, MemberDecl member,
bool forBodyInheritance, bool lookasideBody) {
Expand Down
33 changes: 27 additions & 6 deletions Source/Dafny/Compilers/SinglePassCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ public override void OnPostCompile() {
protected interface IClassWriter {
ConcreteSyntaxTree/*?*/ CreateMethod(Method m, List<TypeArgumentInstantiation> typeArgs, bool createBody, bool forBodyInheritance, bool lookasideBody);
ConcreteSyntaxTree/*?*/ SynthesizeMethod(Method m, List<TypeArgumentInstantiation> typeArgs, bool createBody, bool forBodyInheritance, bool lookasideBody);
ConcreteSyntaxTree/*?*/ CreateFreshMethod(Method m);
ConcreteSyntaxTree/*?*/ CreateFunction(string name, List<TypeArgumentInstantiation> typeArgs, List<Formal> formals, Type resultType, Bpl.IToken tok, bool isStatic, bool createBody,
MemberDecl member, bool forBodyInheritance, bool lookasideBody);
ConcreteSyntaxTree/*?*/ CreateGetter(string name, TopLevelDecl enclosingDecl, Type resultType, Bpl.IToken tok, bool isStatic, bool isConst, bool createBody, MemberDecl/*?*/ member, bool forBodyInheritance); // returns null iff !createBody
Expand Down Expand Up @@ -1406,6 +1407,10 @@ public ConcreteSyntaxTree SynthesizeMethod(Method m, List<TypeArgumentInstantiat
throw new UnsupportedFeatureException(m.tok, Feature.MethodSynthesis);
}

public ConcreteSyntaxTree CreateFreshMethod(Method m) {
throw new NotImplementedException();
}

public ConcreteSyntaxTree/*?*/ CreateFunction(string name, List<TypeArgumentInstantiation> typeArgs, List<Formal> formals, Type resultType, Bpl.IToken tok, bool isStatic, bool createBody, MemberDecl member, bool forBodyInheritance, bool lookasideBody) {
return createBody ? block : null;
}
Expand Down Expand Up @@ -1918,18 +1923,34 @@ void CompileClassMembers(Program program, TopLevelDeclWithMembers c, IClassWrite
v.Visit(f);
} else if (member is Method m) {
if (Attributes.Contains(m.Attributes, "synthesize")) {
if (m.IsStatic && m.Outs.Count > 0 && m.Body == null) {
classWriter.SynthesizeMethod(m, CombineAllTypeArguments(m), true, true, false);
} else {
Error(m.tok, "Method {0} is annotated with :synthesize but " +
var args = Attributes.FindExpressions(m.Attributes, "synthesize");
if (args != null && (string)(args[0] as StringLiteralExpr)?.Value == "mock") {
if (m.IsStatic && m.Outs.Count > 0 && m.Body == null) {
classWriter.SynthesizeMethod(m, CombineAllTypeArguments(m), true, true, false);
} else {
Error(m.tok, "Method {0} is annotated with :synthesize but " +
"is not static, has a body, or does not return " +
"anything",
errorWr, m.FullName);
}
} else if (args != null && (string)(args[0] as StringLiteralExpr)?.Value == "fresh") {
if (m.IsStatic && m.Outs.Count > 0 && m.Body == null) {
classWriter.CreateFreshMethod(m);
} else {
Error(m.tok, "Method {0} is annotated with :synthesize but " +
"is not static, has a body, or does not return " +
"anything",
errorWr, m.FullName);
}
} else {
Error(m.tok, "Method {0} is annotated with :synthesize but " +
"does not have the required parameters",
errorWr, m.FullName);
}
} else if (m.Body == null && !(c is TraitDecl && !m.IsStatic) &&
!(!DafnyOptions.O.DisallowExterns && (Attributes.Contains(m.Attributes, "dllimport") || (IncludeExternMembers && Attributes.Contains(m.Attributes, "extern"))))) {
// A (ghost or non-ghost) method must always have a body, except if it's an instance method in a trait.
if (Attributes.Contains(m.Attributes, "axiom") || (!DafnyOptions.O.DisallowExterns && Attributes.Contains(m.Attributes, "extern"))) {
if (Attributes.Contains(m.Attributes, "axiom")) {
// suppress error message
} else {
Error(m.tok, "Method {0} has no body", errorWr, m.FullName);
Expand Down Expand Up @@ -2823,7 +2844,7 @@ void TrStmtNonempty(Statement stmt, ConcreteSyntaxTree wr) {
protected internal void TrStmt(Statement stmt, ConcreteSyntaxTree wr) {
Contract.Requires(stmt != null);
Contract.Requires(wr != null);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep that line.

if (stmt.IsGhost) {
return;
}
Expand Down
12 changes: 12 additions & 0 deletions Source/Dafny/Compilers/Synthesizer-Csharp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ public CsharpSynthesizer(CsharpCompiler compiler, ConcreteSyntaxTree errorWriter
ErrorWriter = errorWriter;
}

/// <summary>
/// Create a body for a method returning a fresh instance of an object
/// </summary>
public ConcreteSyntaxTree CreateFreshMethod(Method m,
ConcreteSyntaxTree wr) {
var keywords = "public static ";
var returnType = compiler.GetTargetReturnTypeReplacement(m, wr);
wr = wr.NewBlock($"{keywords}{returnType} {m.CompileName}()");
wr.FormatLine($"return new {returnType}();");
return wr;
}

/// <summary>
/// Create a body of a method that synthesizes one or more objects.
/// For instance, the following Dafny method:
Expand Down
Loading