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

Implement entities database and auditor #11

Merged
merged 106 commits into from
Sep 14, 2022
Merged

Conversation

atomb
Copy link
Member

@atomb atomb commented Sep 7, 2022

Creates a database of program entities (modules, types, definitions, etc.) and updates the translator to handle an entire program instead of a single method.

On top of this, implements an auditor for Dafny, focused initially on producing a report summarizing all assumptions in a program (addressing dafny-lang/dafny#2236).


//// AST traversals ////

function {:opaque} Any<T>(P: T ~> bool, ts: seq<T>) : (b: bool)
Copy link
Member Author

Choose a reason for hiding this comment

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

This should go in the standard library

Copy link
Member

Choose a reason for hiding this comment

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

Can we move it to our own library for now?

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed it as it's no longer used.

@@ -0,0 +1,450 @@
include "Library.dfy"
Copy link
Member Author

Choose a reason for hiding this comment

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

We should eventually move as much as possible of this file and Library.dfy into https://github.com/dafny-lang/libraries.

import Utils.Lib.SetSort
import OS = Utils.Lib.Outcome.OfSeq

// DISCUSS: Should this module be parameterized by `TExpr`?
Copy link
Member Author

Choose a reason for hiding this comment

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

I could see value in doing so, but I'd be inclined to only change it if we have a concrete use case, along with the change to implement that use case.


datatype TranslationError =
| Invalid(msg: string)
| GhostExpr(expr: C.Expression)
Copy link
Member Author

Choose a reason for hiding this comment

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

We could remove this and use Unsupported instead.

| GhostExpr(expr: C.Expression)
| UnsupportedType(ty: C.Type)
| UnsupportedExpr(expr: C.Expression)
| UnsupportedStmt(stmt: C.Statement)
Copy link
Member Author

Choose a reason for hiding this comment

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

We could get rid of this now that it's no longer used. And we could almost get rid of UnsupportedExpr, too.

else if md is C.Method then
TranslateMethod(md)
else
Failure(Invalid("Unsupported member declaration type: " + TypeConv.AsString(md.FullName)))
Copy link
Member Author

Choose a reason for hiding this comment

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

We should add an unsupported entity constructor and return Success with it here.

// TODO: handle nonnull types
var x := TypeConv.AsString(st.Var.Name);
var ty :- Expr.TranslateType(st.Rhs);
var constraint :-Expr.TranslateExpression(st.Constraint);
Copy link
Member Author

Choose a reason for hiding this comment

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

Suggested change
var constraint :-Expr.TranslateExpression(st.Constraint);
var constraint :- Expr.TranslateExpression(st.Constraint);

var x := TypeConv.AsString(st.Var.Name);
var ty :- Expr.TranslateType(st.Rhs);
var constraint :-Expr.TranslateExpression(st.Constraint);
var wit :-Expr.TranslateOptionalExpression(st.Witness);
Copy link
Member Author

Choose a reason for hiding this comment

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

Suggested change
var wit :-Expr.TranslateOptionalExpression(st.Witness);
var wit :- Expr.TranslateOptionalExpression(st.Witness);

var x := TypeConv.AsString(nt.Var.Name);
var ty :- Expr.TranslateType(nt.BaseType);
var constraint :- Expr.TranslateOptionalExpression(nt.Constraint);
var wit :-Expr.TranslateOptionalExpression(nt.Witness);
Copy link
Member Author

Choose a reason for hiding this comment

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

Suggested change
var wit :-Expr.TranslateOptionalExpression(nt.Witness);
var wit :- Expr.TranslateOptionalExpression(nt.Witness);

else if tl is C.ClassDecl then
TranslateClassDecl(tl)
else
Failure(Invalid("Unsupported top level declaration type for " + TypeConv.AsString(tl.FullName)));
Copy link
Member Author

Choose a reason for hiding this comment

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

Also return Success(Unsupported(...)) here.

assume ASTHeight(md.Signature) < ASTHeight(tl);
TranslateModule(md.Signature)
else
Failure(Invalid("Unsupported top level declaration type for " + TypeConv.AsString(tl.FullName)))
Copy link
Member Author

Choose a reason for hiding this comment

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

Also return Success(Unsupported(...)) here.

var topDecls' := Seq.Flatten(topDecls);
var topNames := Seq.Map((d: E.Entity) => d.ei.name, topDecls');
//:- Need(forall nm <- topNames :: nm.ChildOf(name), Invalid("Malformed name in " + name.ToString()));
assume forall nm <- topNames :: nm.ChildOf(name);
Copy link
Member Author

Choose a reason for hiding this comment

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

Remove this and use Need again.

var prog := E.Program(reg, defaultModule := defaultModuleName, mainMethod := mainMethodName);
if prog.Valid?() then Success(prog) else Failure(Invalid("Generated invalid program"))
case Fail(errs) =>
var err := Seq.Flatten(Seq.Map((e: E.ValidationError) => e.ToString(), errs));
Copy link
Member Author

Choose a reason for hiding this comment

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

Make this message prettier.

reads *
decreases ASTHeight(ue), 0
{
var children := []; // TODO: ListUtils.ToSeq(ue.SubExpressions);
Copy link
Member Author

Choose a reason for hiding this comment

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

Implement ListUtils.ToSeq but for IEnumerable.

var stmts :- Seq.MapResult(ListUtils.ToSeq(m.Body.Body), TranslateStatement);
Success(D.Method("Main", DE.Block(stmts)))
var subexprs := []; // TODO: ListUtils.ToSeq(ue.SubExpressions);
var substmts := []; // TODO: ListUtils.ToSeq(ue.SubStatements);
Copy link
Member Author

Choose a reason for hiding this comment

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

Implement ListUtils.ToSeq but for IEnumerable.

}
var names := p.registry.SortedNames();
var entities := Seq.Map(p.registry.Get, names);
// TODO: prove
Copy link
Member Author

Choose a reason for hiding this comment

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

Either prove this entirely or just for the Main method.

@@ -300,11 +315,14 @@ module Compiler {
// but it seems cleaner to state that we need ``NotANegatedBinopExpr`` in the
// preconditions, as it is more precise and ``Tr_Expr_Post`` might be expanded
// in the future.
// TODO: need to redo this for all the entities in the program
Copy link
Member Author

Choose a reason for hiding this comment

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

Or just for the Main method.

Map_Expr_PreservesRel(m.methodBody, tr, rel);
}

/*
Copy link
Member Author

Choose a reason for hiding this comment

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

Uncomment this and prove it so we can use it to prove transformations correct.

e requires Shallow.All_Entity(e, tr.f.requires) => Map_Entity(e, tr)
}

// TODO: prove!
Copy link
Member Author

Choose a reason for hiding this comment

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

Prove this!

Copy link
Member

Choose a reason for hiding this comment

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

Let's create an issue for this

@@ -20,5 +22,6 @@ module Bootstrap.Passes.Pass {
// the input and the output.
requires Tr_Pre(p)
ensures Tr_Post(p)
ensures EqInterp(p.mainMethod.methodBody, p'.mainMethod.methodBody)
// TODO!
Copy link
Member Author

Choose a reason for hiding this comment

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

Prove this!

// Apply the transformation to a program.
{
Deep.All_Expr_True_Forall(Tr_Expr.f.requires);
assert Deep.All_Program(p, Tr_Expr.f.requires);
EqInterp_Lift(Tr_Expr.f);
Map_Program_PreservesRel(p, Tr_Expr, Tr_Expr_Rel);
//Map_Program_PreservesRel(p, Tr_Expr, Tr_Expr_Rel);
Copy link
Member Author

Choose a reason for hiding this comment

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

Hopefully this will go through as-is one Map_Program_PreservesRel goes through.

// Apply the transformation to a program.
{
Deep.All_Expr_True_Forall(Tr_Expr.f.requires);
assert Deep.All_Program(p, Tr_Expr.f.requires);
TrPreservesRel();
Map_Program_PreservesRel(p, Tr_Expr, Tr_Expr_Rel);
//Map_Program_PreservesRel(p, Tr_Expr, Tr_Expr_Rel);
Copy link
Member Author

Choose a reason for hiding this comment

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

Hopefully this will go through as-is (with the ensures clause back in place) once Map_Program_PreservesRel exists again.

@keyboardDrummer
Copy link
Member

Is there an issue that this PR relates to? Maybe we could add one in https://github.com/dafny-lang/dafny ?

@atomb
Copy link
Member Author

atomb commented Sep 8, 2022

Is there an issue that this PR relates to? Maybe we could add one in https://github.com/dafny-lang/dafny ?

I just edited the description to be non-empty and include a reference to the relevant issue.

Copy link
Member

@cpitclaudel cpitclaudel left a comment

Choose a reason for hiding this comment

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

Neat, just read through the whole thing, and it's looking pretty good!

GNUmakefile Outdated Show resolved Hide resolved
GNUmakefile Outdated Show resolved Hide resolved
src/AST/Entities.dfy Outdated Show resolved Hide resolved
src/AST/Entities.dfy Outdated Show resolved Hide resolved
src/AST/Entities.dfy Outdated Show resolved Hide resolved
src/Utils/Library.dfy Show resolved Hide resolved
src/Utils/Library.dfy Show resolved Hide resolved
src/Utils/Library.dfy Show resolved Hide resolved
src/Utils/Library.dfy Outdated Show resolved Hide resolved
src/AST/Translator.Entity.dfy Show resolved Hide resolved
atomb and others added 26 commits September 14, 2022 02:21
The Failure case now should only occur for malformed ASTs, and
unsupported constructs should use Success(Unuspported(...)).
* Mark `List` and `Dictionary` parameters nullable when they are that.
* Sort dictionary keys to ensure that `DictUtils.FoldL` is a function.
* Include `reads` clauses on Dafny `{:extern}` functions for above.
* Change assumption collection process.
* Improve text of error message on failure to translate program.
The compiler keeps it in, even if it’s marked ghost, leading to later
compilation failures. Let’s reduce it to a smaller example and file a
compiler issue about it.
Avoid using `Need` to check types.
These all have issues, but these comments help make plans more
immediately clear when browsing the code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants