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: Added ranges to expression #1985

Merged
merged 7 commits into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- fix: Allow datatype update expressions for constructors with nameonly parameters (https://github.com/dafny-lang/dafny/pull/1949)
- fix: Fix malformed Java code generated for comprehensions that use maps (https://github.com/dafny-lang/dafny/pull/1939)
- feat: Recognize `!in` operator when looking for compilable comprehensions (https://github.com/dafny-lang/dafny/pull/1939)
- feat: The dafny language server now returns expressions ranges instead of token ranges to better report errors (https://github.com/dafny-lang/dafny/pull/1985)

# 3.5.0

Expand Down
61 changes: 61 additions & 0 deletions Source/Dafny/AST/DafnyAst.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6927,6 +6927,16 @@ public virtual IEnumerable<Expression> NonSpecificationSubExpressions {
}
}
}

[FilledInDuringResolution] private IToken rangeToken;
public virtual IToken RangeToken {
get {
if (rangeToken == null) {
rangeToken = new RangeToken(Tok, EndTok);
}
return rangeToken;
}
}
}

public class LList<T> {
Expand Down Expand Up @@ -8884,6 +8894,25 @@ public virtual string val {
}
}

public class RangeToken : TokenWrapper {
// The wrapped token is the startTok
private IToken endTok;

public IToken StartToken => WrappedToken;
public IToken EndToken => endTok;

// Used for range reporting
override public string val {
get {
return new string(' ', endTok.pos + endTok.val.Length - pos);
}
}

public RangeToken(IToken startTok, IToken endTok) : base(startTok) {
this.endTok = endTok;
}
}

public class NestedToken : TokenWrapper {
public NestedToken(IToken outer, IToken inner, string message = null)
: base(outer) {
Expand Down Expand Up @@ -8997,6 +9026,38 @@ public virtual IEnumerable<Expression> SubExpressions {
get { yield break; }
}

private RangeToken rangeToken;

/// Creates a token on the entire range of the expression.
/// Used only for error reporting.
public RangeToken RangeToken {
get {
if (rangeToken == null) {
var startTok = tok;
var endTok = tok;
foreach (var e in SubExpressions) {
if (e.tok.filename != tok.filename || e.IsImplicit) {
// Ignore auto-generated expressions, if any.
continue;
}

if (e.StartToken.pos < startTok.pos) {
startTok = e.StartToken;
} else if (e.EndToken.pos > endTok.pos) {
endTok = e.EndToken;
}
}

rangeToken = new RangeToken(startTok, endTok);
}

return rangeToken;
}
}

public IToken StartToken => RangeToken.StartToken;
public IToken EndToken => RangeToken.EndToken;

/// <summary>
/// Returns the list of types that appear in this expression proper (that is, not including types that
/// may appear in subexpressions). Types occurring in sub-statements of the expression are not included.
Expand Down
469 changes: 237 additions & 232 deletions Source/Dafny/Verifier/Translator.ExpressionTranslator.cs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Source/Dafny/Verifier/Translator.TrStatement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ private void TrPredicateStmt(PredicateStmt stmt, BoogieStmtListBuilder builder,
bool splitHappened;
var ss = TrSplitExpr(stmt.Expr, etran, true, out splitHappened);
if (!splitHappened) {
var tok = enclosingToken == null ? stmt.Expr.tok : new NestedToken(enclosingToken, stmt.Expr.tok);
var tok = enclosingToken == null ? GetToken(stmt.Expr) : new NestedToken(enclosingToken, GetToken(stmt.Expr));
var desc = new PODesc.AssertStatement(errorMessage);
(proofBuilder ?? b).Add(Assert(tok, etran.TrExpr(stmt.Expr), desc, stmt.Tok,
etran.TrAttributes(stmt.Attributes, null)));
Expand Down Expand Up @@ -1640,7 +1640,7 @@ void TrCallStmt(CallStmt s, BoogieStmtListBuilder builder, List<Variable> locals
builder.Add(Bpl.Cmd.SimpleAssign(s.Tok, initHeap, etran.HeapExpr));
}
builder.Add(new CommentCmd("TrCallStmt: Before ProcessCallStmt"));
ProcessCallStmt(s.Tok, tySubst, GetTypeParams(s.Method), s.Receiver, actualReceiver, s.Method, s.MethodSelect.AtLabel, s.Args, bLhss, lhsTypes, builder, locals, etran);
ProcessCallStmt(GetToken(s), tySubst, GetTypeParams(s.Method), s.Receiver, actualReceiver, s.Method, s.MethodSelect.AtLabel, s.Args, bLhss, lhsTypes, builder, locals, etran);
builder.Add(new CommentCmd("TrCallStmt: After ProcessCallStmt"));
for (int i = 0; i < lhsBuilders.Count; i++) {
var lhs = s.Lhs[i];
Expand Down
Loading