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

feat: Prelude extractor #5621

Merged
merged 57 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
efb92f7
Make some BoogieGenerator methods public
RustanLeino Jul 11, 2024
655583a
Add —extract option
RustanLeino Jul 11, 2024
69a233a
Add beginning of extractor
RustanLeino Jul 11, 2024
22f1043
Add support for :extract_attribute
RustanLeino Jul 11, 2024
8a09af0
Add support for :extract_used_by
RustanLeino Jul 11, 2024
740cf74
Translate expressions
RustanLeino Jul 11, 2024
eaf91d8
Look for :extract on module
RustanLeino Jul 11, 2024
c8c76ac
Sort declarations from each module
RustanLeino Jul 11, 2024
0f2b6e2
Remove debugging comment
RustanLeino Jul 11, 2024
1fc1aaa
Add scripts to generate prelude
RustanLeino Jul 11, 2024
727c9cd
Ignore files
RustanLeino Jul 11, 2024
01eeec5
chore: Mostly whitespace changes
RustanLeino Jul 11, 2024
827bba1
Rename files to have better names
RustanLeino Jul 11, 2024
8969d7a
Don’t include this generated file
RustanLeino Jul 11, 2024
083e0d9
chore: Change formatting to match generated
RustanLeino Jul 11, 2024
5bd75ce
Move non-generated seq decls into Core file
RustanLeino Jul 11, 2024
2e6bf6d
Don’t include this generated file
RustanLeino Jul 11, 2024
cbc6e87
Change order of declarations
RustanLeino Jul 11, 2024
0fdae0d
chore: Change formatting
RustanLeino Jul 11, 2024
204fa36
chore: Name parameters
RustanLeino Jul 11, 2024
88f563a
Fix forall/exists distinction
RustanLeino Jul 11, 2024
589c6ac
chore: Adjust formatting
RustanLeino Jul 11, 2024
005109e
Remove the used Seq#Singleton
RustanLeino Jul 11, 2024
3a8a234
chore: Add spaces after commas
RustanLeino Jul 11, 2024
9855a01
chore: Remove trailing spaces
RustanLeino Jul 11, 2024
f98bde4
Update formatting using pretty-printed Boogie
RustanLeino Jul 11, 2024
fd3efe5
Fix extraction of logical not
RustanLeino Jul 11, 2024
d0afb38
Adjust formatting
RustanLeino Jul 11, 2024
8a6902d
Fix order of pattern attributes in output
RustanLeino Jul 11, 2024
02c45ca
Adjust formatting
RustanLeino Jul 11, 2024
4187d2c
Change order of declarations
RustanLeino Jul 11, 2024
2436e65
Split model into separate files
RustanLeino Jul 11, 2024
a1ff5ee
Adjust line spacing
RustanLeino Jul 12, 2024
2a88513
Add missing pattern
RustanLeino Jul 12, 2024
e781392
Move declarations
RustanLeino Jul 12, 2024
575fbb6
Adjust whitespace
RustanLeino Jul 12, 2024
41b14b2
Move declarations
RustanLeino Jul 12, 2024
873ed66
Move declarations
RustanLeino Jul 12, 2024
eea48b6
Add missing dependency
RustanLeino Jul 12, 2024
9fd74ad
Adjust template file
RustanLeino Jul 12, 2024
eb49dd5
Add Boogie comments into model file
RustanLeino Jul 12, 2024
3abc19d
Merge branch 'master' into prelude-extractor
RustanLeino Jul 12, 2024
ecd4fdc
Add error handling
RustanLeino Jul 12, 2024
c16a10f
Enable some simplifications
RustanLeino Jul 12, 2024
797e4c9
Add release notes
RustanLeino Jul 12, 2024
8d8d2c8
Format Dafny code
RustanLeino Jul 12, 2024
bfaa289
Account for order change of error messages
RustanLeino Jul 12, 2024
f010720
Use :isolate_assertions with SchorrWaite.dfy
RustanLeino Jul 12, 2024
3e126cc
Update Source/DafnyDriver/Commands/VerifyCommand.cs
RustanLeino Aug 20, 2024
4efe617
Rename “Extractor” “BoogieExtractor”
RustanLeino Aug 20, 2024
c6e2015
Overhaul the attribute names
RustanLeino Aug 20, 2024
cd87e9c
Merge branch 'master' into prelude-extractor
RustanLeino Aug 20, 2024
81c44f3
Adjust resource count in expect file
RustanLeino Aug 21, 2024
374d8c4
Merge branch 'master' into prelude-extractor
RustanLeino Aug 26, 2024
ac69f69
Merge branch 'master' into prelude-extractor
RustanLeino Aug 28, 2024
26c98d1
Merge branch 'master' into prelude-extractor
RustanLeino Aug 29, 2024
6a3f5f6
Update resource counts for SchorrWaite.dfy
RustanLeino Aug 29, 2024
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ Source/IntegrationTests/TestFiles/LitTests/LitTest/**/*.deps.json
Source/IntegrationTests/TestFiles/LitTests/LitTest/**/*.csproj
/Source/IntegrationTests/TestFiles/LitTests/LitTest/pythonmodule/multimodule/PythonModule2
/Source/IntegrationTests/TestFiles/LitTests/LitTest/pythonmodule/singlemodule/dafnysource/PythonModule1
/Source/DafnyCore/Prelude/DafnyPrelude.bpl
/Source/DafnyCore/Prelude/Sequences.bpl
350 changes: 350 additions & 0 deletions Source/DafnyCore/Backends/BoogieExtractor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,350 @@
//-----------------------------------------------------------------------------
//
// Copyright by the contributors to the Dafny Project
// SPDX-License-Identifier: MIT
//
//-----------------------------------------------------------------------------

#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Diagnostics.Contracts;
using Microsoft.BaseTypes;
using Microsoft.Boogie;

namespace Microsoft.Dafny.Compilers {
public class ExtractorError : Exception {
public ExtractorError(string message)
: base(message) {
}
}

public class BoogieExtractor : ASTVisitor<IASTVisitorContext> {
/// <summary>
/// Says to look inside the module for contents to extract.
/// Can be applied to a module.
///
/// Note: This attribute isn't used yet, so the use of the attribute is just a stylistic thing at the moment.
/// Similarly, one can imagine that the extractor will look at a module's export clauses, to--in some way--check that
/// the set of Boogie declarations exported are self consistent. But that isn't done yet, either. Instead, all contents
/// of all files given to the extractor are considered for extraction.
/// </summary>
private const string ExtractAttribute = "extract_boogie";

/// <summary>
/// Gives the Boogie name to be used in the extraction.
/// Can be applied to types and functions.
/// </summary>
private const string NameAttribute = "extract_boogie_name";

/// <summary>
/// Says to place the extracted axiom declaration in the "uses" block of the given function.
/// Can be applied to lemmas.
/// </summary>
private const string UsedByAttribute = "extract_used_by";

/// <summary>
/// Gives a matching pattern to be applied in the quantifier emitted from a lemma or from a quantifier.
/// Can be applied to lemmas and quantifiers.
/// </summary>
private const string PatternAttribute = "extract_pattern";

/// <summary>
/// Specifies an additional attribute to be attached to the quantifier emitted from a lemma.
/// Can be applied to lemmas.
/// </summary>
private const string AttributeAttribute = "extract_attribute";

/// <summary>
/// Throws an "ExtractorError" if the input is unexpected or unsupported.
/// </summary>
public static Boogie.Program Extract(Program program) {
var extractor = new BoogieExtractor();
extractor.VisitModule(program.DefaultModule);
extractor.FixUpUsedByInformation();

var extractedProgram = new Boogie.Program();
extractedProgram.AddTopLevelDeclarations(extractor.allDeclarations);
return extractedProgram;
}

private List<Boogie.Declaration> declarations = new(); // for the current module
private List<Boogie.Declaration> allDeclarations = new(); // these are the declarations for all modules marked with {:extract}
private readonly Dictionary<Function, Boogie.Function> functionExtractions = new();
private readonly List<(Boogie.Axiom, Function)> axiomUsedBy = new();

private BoogieExtractor() {
}

void FixUpUsedByInformation() {
foreach (var (axiom, function) in axiomUsedBy) {
if (!functionExtractions.TryGetValue(function, out var boogieFunction)) {
throw new ExtractorError($":{UsedByAttribute} attribute mentions non-extracted function: {function.Name}");
}
boogieFunction.OtherDefinitionAxioms.Add(axiom);
}
axiomUsedBy.Clear();
}

public override IASTVisitorContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostcondition) {
return astVisitorContext;
}

void VisitModule(ModuleDecl module) {
var previousDeclarations = declarations;
declarations = new();

VisitDeclarations(module.Signature.TopLevels.Values.ToList());

if (Attributes.Contains(module.Signature.ModuleDef.Attributes, ExtractAttribute)) {
declarations.Sort((d0, d1) => d0.tok.pos - d1.tok.pos);
allDeclarations.AddRange(declarations);
}
declarations = previousDeclarations;
}

protected override void VisitOneDeclaration(TopLevelDecl decl) {
if (decl is ModuleDecl moduleDecl) {
VisitModule(moduleDecl);
return;
}

if (GetExtractName(decl.Attributes) is { } extractName) {
var ty = new Boogie.TypeCtorDecl(decl.tok, extractName, decl.TypeArgs.Count);
declarations.Add(ty);
}

base.VisitOneDeclaration(decl); // this will visit the declaration's members
}

public override void VisitMethod(Method method) {
if (method is not Lemma lemma) {
return;
}

var patterns = Attributes.FindAllExpressions(lemma.Attributes, PatternAttribute);
var usedByInfo = Attributes.Find(lemma.Attributes, UsedByAttribute);
if (patterns == null && usedByInfo == null) {
return;
}

if ((lemma.Ins.Count == 0) != (patterns == null)) {
throw new ExtractorError($"a parameterized lemma must specify at least one :{PatternAttribute}: {lemma.Name}");
}
if (lemma.TypeArgs.Count != 0) {
throw new ExtractorError($"an extracted lemma is not allowed to have type parameters: {lemma.Name}");
}
if (lemma.Outs.Count != 0) {
throw new ExtractorError($"an extracted lemma is not allowed to have out-parameters: {lemma.Name}");
}

var tok = lemma.tok;

var boundVars = lemma.Ins.ConvertAll(formal =>
(Boogie.Variable)new Boogie.BoundVariable(tok, new TypedIdent(tok, formal.Name, ExtractType(formal.Type)))
);

var triggers = GetTriggers(tok, patterns);

var ante = BoogieGenerator.BplAnd(lemma.Req.ConvertAll(req => ExtractExpr(req.E)));
var post = BoogieGenerator.BplAnd(lemma.Ens.ConvertAll(ens => ExtractExpr(ens.E)));
var body = BoogieGenerator.BplImp(ante, post);

Boogie.Expr axiomBody;
if (boundVars.Count == 0) {
axiomBody = body;
} else {
var kv = GetKeyValues(tok, lemma.Attributes);
axiomBody = new Boogie.ForallExpr(tok, new List<TypeVariable>(), boundVars, kv, triggers, body);
}
var axiom = new Boogie.Axiom(tok, axiomBody);
declarations.Add(axiom);

if (usedByInfo != null) {
if (usedByInfo.Args.Count == 1 && usedByInfo.Args[0].Resolved is MemberSelectExpr { Member: Function function }) {
axiomUsedBy.Add((axiom, function));
} else {
throw new ExtractorError($":{UsedByAttribute} argument on lemma '{lemma.Name}' is expected to be an extracted function");
}
}
}

private Trigger? GetTriggers(IToken tok, List<List<Expression>>? patterns) {
if (patterns == null) {
return null;
}

Boogie.Trigger? triggers = null;
for (var i = 0; i < patterns.Count; i++) {
var terms = patterns![i].ConvertAll(ExtractExpr);
triggers = new Boogie.Trigger(tok, true, terms, triggers);
}

return triggers;
}

private QKeyValue? GetKeyValues(IToken tok, Attributes attributes) {
Boogie.QKeyValue kv = null;

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / build-refman (ubuntu-22.04)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / build-refman (ubuntu-22.04)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / singletons

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / singletons

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / singletons

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / singletons

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / ubuntu-20.04 (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / ubuntu-20.04 (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / ubuntu-20.04 (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / ubuntu-20.04 (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / ubuntu-20.04 (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / ubuntu-20.04 (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / ubuntu-20.04 (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / ubuntu-20.04 (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / doctests

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / doctests

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / win (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / win (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / win (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / integration-tests / test (ubuntu-20.04, 3)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / osx (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / osx (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / xunit-tests / osx (1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / integration-tests / test (ubuntu-20.04, 5)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / integration-tests / test (ubuntu-20.04, 1)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / integration-tests / test (ubuntu-20.04, 2)

Converting null literal or possible null value to non-nullable type.

Check warning on line 190 in Source/DafnyCore/Backends/BoogieExtractor.cs

View workflow job for this annotation

GitHub Actions / integration-tests / test (ubuntu-20.04, 4)

Converting null literal or possible null value to non-nullable type.
var extractAttributes = Attributes.FindAllExpressions(attributes, AttributeAttribute);
if (extractAttributes != null) {
if (extractAttributes.Count == 0) {
throw new ExtractorError($"first argument to :{AttributeAttribute} is expected to be a literal string; got no arguments");
}
for (var i = extractAttributes.Count; 0 <= --i;) {
string? attrName = null;
var parameters = new List<object>();
foreach (var argument in extractAttributes[i]) {
if (attrName != null) {
parameters.Add(ExtractExpr(argument));
} else if (argument is StringLiteralExpr { Value: string name }) {
attrName = name;
} else {
throw new ExtractorError($"first argument to :{AttributeAttribute} is expected to be a literal string; got: {argument}");
}
}

kv = new Boogie.QKeyValue(tok, attrName, parameters, kv);
}
}

return kv;
}

public override void VisitFunction(Function function) {
if (GetExtractName(function.Attributes) is { } extractName) {
var tok = function.tok;
if (function.TypeArgs.Count != 0) {
throw new ExtractorError($"an extracted function is not allowed to have type parameters: {function.Name}");
}
var inParams = function.Ins.ConvertAll(formal =>
(Boogie.Variable)new Boogie.Formal(tok, new TypedIdent(tok, formal.Name, ExtractType(formal.Type)), true)
);
var result = new Boogie.Formal(tok, new TypedIdent(tok, TypedIdent.NoName, ExtractType(function.ResultType)), false);
var fn = new Boogie.Function(tok, extractName, inParams, result);
declarations.Add(fn);
functionExtractions.Add(function, fn);
}
}

private Boogie.Type ExtractType(Type type) {
switch (type) {
case IntType:
return Boogie.Type.Int;
case BoolType:
return Boogie.Type.Bool;
case UserDefinedType udt: {
var cl = udt.ResolvedClass;
var name = GetExtractName(cl.Attributes) ?? cl.Name;
return new Boogie.UnresolvedTypeIdentifier(Boogie.Token.NoToken, name, udt.TypeArgs.ConvertAll(ExtractType));
}
default:
throw new ExtractorError($"type not supported by extractor: {type}");
}
}

private string? GetExtractName(Attributes attributes) {
if (Attributes.Find(attributes, NameAttribute) is { } extractNameAttribute) {
if (extractNameAttribute.Args.Count == 1 && extractNameAttribute.Args[0] is StringLiteralExpr { Value: string extractName }) {
return extractName;
}
}
return null;
}

private Boogie.Expr ExtractExpr(Expression expr) {
expr = expr.Resolved;
var tok = expr.tok;
switch (expr) {
case LiteralExpr literalExpr: {
if (literalExpr.Value is bool boolValue) {
// use the specific literals, rather than Boogie.LiteralExpr(bool), in order for the
// peephole optimizations to kick in
return boolValue ? Boogie.Expr.True : Boogie.Expr.False;
} else if (literalExpr.Value is BigInteger intValue) {
var n = BigNum.FromBigInt(intValue);
return Boogie.Expr.Literal(n);
}
break;
}

case IdentifierExpr identifierExpr:
return new Boogie.IdentifierExpr(tok, identifierExpr.Name);

case FunctionCallExpr functionCallExpr: {
var function = functionCallExpr.Function;
var functionName = GetExtractName(function.Attributes) ?? function.Name;
Contract.Assert(function.IsStatic);
var arguments = functionCallExpr.Args.ConvertAll(ExtractExpr);
return new Boogie.NAryExpr(tok, new Boogie.FunctionCall(new Boogie.IdentifierExpr(tok, functionName)), arguments);
}

case BinaryExpr binaryExpr: {
var e0 = ExtractExpr(binaryExpr.E0);
var e1 = ExtractExpr(binaryExpr.E1);
switch (binaryExpr.ResolvedOp) {
case BinaryExpr.ResolvedOpcode.EqCommon:
return Boogie.Expr.Eq(e0, e1);
case BinaryExpr.ResolvedOpcode.NeqCommon:
return Boogie.Expr.Neq(e0, e1);
case BinaryExpr.ResolvedOpcode.Iff:
return BoogieGenerator.BplIff(e0, e1);
case BinaryExpr.ResolvedOpcode.Imp:
return BoogieGenerator.BplImp(e0, e1);
case BinaryExpr.ResolvedOpcode.And:
return BoogieGenerator.BplAnd(e0, e1);
case BinaryExpr.ResolvedOpcode.Or:
return BoogieGenerator.BplOr(e0, e1);
case BinaryExpr.ResolvedOpcode.Le:
return Boogie.Expr.Le(e0, e1);
case BinaryExpr.ResolvedOpcode.Lt:
return Boogie.Expr.Lt(e0, e1);
case BinaryExpr.ResolvedOpcode.Add:
return Boogie.Expr.Add(e0, e1);
case BinaryExpr.ResolvedOpcode.Sub:
return Boogie.Expr.Sub(e0, e1);
default:
break;
}
break;
}

case UnaryOpExpr unaryOpExpr:
if (unaryOpExpr.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot) {
var e = ExtractExpr(unaryOpExpr.E);
return Boogie.Expr.Not(e);
} else {
throw new ExtractorError($"extractor does not support unary operator {unaryOpExpr.ResolvedOp}");
}

case QuantifierExpr quantifierExpr: {
var boundVars = quantifierExpr.BoundVars.ConvertAll(boundVar =>
(Boogie.Variable)new Boogie.BoundVariable(tok, new TypedIdent(tok, boundVar.Name, ExtractType(boundVar.Type)))
);

var patterns = Attributes.FindAllExpressions(quantifierExpr.Attributes, PatternAttribute);
if (patterns.Count == 0) {
throw new ExtractorError($"extraction expects every quantifier to specify at least one :{PatternAttribute}");
}
var triggers = GetTriggers(tok, patterns);

var kv = GetKeyValues(tok, quantifierExpr.Attributes);
var body = ExtractExpr(quantifierExpr.LogicalBody());
if (quantifierExpr is ExistsExpr) {
return new Boogie.ExistsExpr(tok, new List<TypeVariable>(), boundVars, kv, triggers, body);
} else {
Contract.Assert(quantifierExpr is ForallExpr);
return new Boogie.ForallExpr(tok, new List<TypeVariable>(), boundVars, kv, triggers, body);
}
}

default:
break;
}

throw new ExtractorError($"extraction does not support expression of type {expr.GetType()}: {expr}");
}
}
}
1 change: 1 addition & 0 deletions Source/DafnyCore/DafnyOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ public enum ContractTestingMode {
public PrintModes PrintMode = PrintModes.Everything; // Default to printing everything
public bool DafnyVerify = true;
public string DafnyPrintResolvedFile = null;
public string BoogieExtractionTargetFile = null;
public List<string> DafnyPrintExportedViews = new List<string>();
public bool Compile = true;
public List<string> MainArgs = new List<string>();
Expand Down
Loading
Loading