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

Inconsistency in allowed LHS between var decl statement and let expression #129

Closed
wilcoxjay opened this issue Jul 25, 2017 · 1 comment · Fixed by #131
Closed

Inconsistency in allowed LHS between var decl statement and let expression #129

wilcoxjay opened this issue Jul 25, 2017 · 1 comment · Fixed by #131
Assignees
Labels
kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny

Comments

@wilcoxjay
Copy link
Collaborator

Tuples can be matched in both var decl statements and let expressions:

function method Foo(): (int, int)
{
    (1, 2)
}

method Bar()
    ensures var (x, y) := Foo(); x < y
{
    var (x, y) := Foo();
}

However, user declared datatypes with one constructor cannot be matched in var decl statements, only let expressions.

datatype Point = Point(x: int, y: int)

function method FooPoint(): Point
{
    Point(1, 2)
}

method BarPoint()
    ensures var Point(x, y) := FooPoint(); x < y
{
    var Point(x, y) := FooPoint();
}
@wilcoxjay wilcoxjay added the kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny label Jul 25, 2017
@wilcoxjay wilcoxjay self-assigned this Jul 25, 2017
@wilcoxjay
Copy link
Collaborator Author

There are some design decisions to be made here.

Currently, a statement beginning with var is either:

  • a VarDeclStmt, whose LHS consists of some number of identifiers and whose RHS is allowed to be a method call, among other things
  • a LetStmt, whose LHS consists of a tuple of patterns, and whose RHS must be an expression (in particular, not a method call)

The concrete gotcha raised by this issue is that a LetStmt requires it's LHS to be a tuple of patterns, not an arbitrary pattern. The obvious solution is to allow an arbitrary pattern on the LHS of a LetStmt while retaining the distinction between VarDeclStmt and LetStmt. There are some subtleties, though. For example,

var Foo := Bar();
  • Bar might be a function method or a method.
  • Foo might be the name of a parameterless constructor or not

If Bar is a method, then this must be VarDeclStmt, and the LHS always means "introduce a local variable named Foo, even if Foo is the name of a constructor.

If Bar is a function method and Foo is the name of a parameterless constructor, then this is a syntactically valid LetStmt, but is rejected by the resolver since its pattern doesn't introduce any bound variables.

While we're at it, it seems natural to want pattern matching on the LHS of a VarDeclStmt as well. Then we could do things like this:

method Line() returns (start: Point, end: Point)
{
    start := Point(0, 0);
    end := Point(1, 1);
}

method UseLine()
{
    var Point(x0, y0), Point(x1, y1) := Line();
}

This has its own problems though. For example, I think it would make it impossible to shadow the name of a parameterless constructor.

For now, I think I will see if I can get arbitrary patterns working in LetStmts, and see what troubles I run into.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: enhancement Enhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafny
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant