Skip to content

Commit eb45d23

Browse files
Remove IncludeToken as prep for caching parsing (#3858)
Currently a file that's included is parsed differently. Its tokens are wrapped in an `IncludeToken`, that includes a reference to the including file. To allow reusing parsed files in a cache, how the file is parsed should be independent of what triggered it to be parsed. To achieve that, this PR removes `IncludeToken`. To enable still determining whether a particular token was part of an include or not, tokens now store a `Uri` that uniquely identifies the document that token came from. The Uris of the root documents are stored in `DefaultModuleDefinition`, which is just below `Program`. Any token with a Uri that is not part of the root set is considered to be included. <small>By submitting this pull request, I confirm that my contribution is made under the terms of the [MIT license](https://github.com/dafny-lang/dafny/blob/master/LICENSE.txt).</small>
1 parent d94af38 commit eb45d23

File tree

100 files changed

+840
-823
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+840
-823
lines changed

Source/DafnyCore.Test/DooFileTest.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ public void UnknownManifestEntries() {
2929
}
3030

3131
private static Program ParseProgram(string dafnyProgramText, DafnyOptions options) {
32-
var module = new LiteralModuleDecl(new DefaultModuleDefinition(), null);
33-
const string fullFilePath = "foo";
32+
const string fullFilePath = "untitled:foo";
33+
var rootUri = new Uri(fullFilePath);
34+
var outerModule = new DefaultModuleDefinition(new List<Uri> { rootUri });
35+
var module = new LiteralModuleDecl(outerModule, null);
3436
Microsoft.Dafny.Type.ResetScopes();
3537
var builtIns = new BuiltIns(options);
36-
var errorReporter = new ConsoleErrorReporter(options);
37-
var parseResult = Parser.Parse(dafnyProgramText, fullFilePath, "foo", module, builtIns, errorReporter);
38+
var errorReporter = new ConsoleErrorReporter(options, outerModule);
39+
var parseResult = Parser.Parse(dafnyProgramText, rootUri, module, builtIns, errorReporter);
3840
Assert.Equal(0, parseResult);
3941
return new Program(fullFilePath, module, builtIns, errorReporter);
4042
}

Source/DafnyCore/AST/Cloner.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public Cloner(bool cloneResolvedFields = false) {
3131

3232
public virtual ModuleDefinition CloneModuleDefinition(ModuleDefinition m, Name name) {
3333
ModuleDefinition nw;
34-
if (m is DefaultModuleDefinition) {
35-
nw = new DefaultModuleDefinition();
34+
if (m is DefaultModuleDefinition defaultModuleDefinition) {
35+
nw = new DefaultModuleDefinition(defaultModuleDefinition.RootUris);
3636
} else {
3737
nw = new ModuleDefinition(Range(m.RangeToken), name, m.PrefixIds, m.IsAbstract, m.IsFacade,
3838
m.RefinementQId, m.EnclosingModule, CloneAttributes(m.Attributes),

Source/DafnyCore/AST/DafnyAst.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ void ObjectInvariant() {
3939
Contract.Invariant(DefaultModule != null);
4040
}
4141

42+
public List<Include> Includes => DefaultModuleDef.Includes;
43+
4244
public readonly string FullName;
4345
[FilledInDuringResolution] public Dictionary<ModuleDefinition, ModuleSignature> ModuleSigs;
4446
// Resolution essentially flattens the module hierarchy, for
@@ -48,7 +50,7 @@ void ObjectInvariant() {
4850

4951
public Method MainMethod; // Method to be used as main if compiled
5052
public readonly ModuleDecl DefaultModule;
51-
public readonly ModuleDefinition DefaultModuleDef;
53+
public readonly DefaultModuleDefinition DefaultModuleDef;
5254
public readonly BuiltIns BuiltIns;
5355
public DafnyOptions Options => Reporter.Options;
5456
public ErrorReporter Reporter { get; set; }
@@ -101,7 +103,7 @@ public IToken GetFirstTopLevelToken() {
101103

102104
var firstToken = DefaultModule.RootToken.Next;
103105
// We skip all included files
104-
while (firstToken is { Next: { } } && firstToken.Next.Filename != DefaultModule.RootToken.Filename) {
106+
while (firstToken is { Next: { } } && firstToken.Next.Filepath != DefaultModule.RootToken.Filepath) {
105107
firstToken = firstToken.Next;
106108
}
107109

@@ -122,13 +124,13 @@ public override IEnumerable<Assumption> Assumptions(Declaration decl) {
122124
}
123125

124126
public class Include : TokenNode, IComparable {
125-
public string IncluderFilename { get; }
127+
public Uri IncluderFilename { get; }
126128
public string IncludedFilename { get; }
127129
public string CanonicalPath { get; }
128130
public bool CompileIncludedCode { get; }
129131
public bool ErrorReported;
130132

131-
public Include(IToken tok, string includer, string theFilename, bool compileIncludedCode) {
133+
public Include(IToken tok, Uri includer, string theFilename, bool compileIncludedCode) {
132134
this.tok = tok;
133135
this.IncluderFilename = includer;
134136
this.IncludedFilename = theFilename;

Source/DafnyCore/AST/Expressions/LitPattern.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public LiteralExpr OptimisticallyDesugaredLit {
4343
} else {
4444
var n = (BigInteger)lit.Value;
4545
var tok = new Token(neg.tok.line, neg.tok.col) {
46-
Filename = neg.tok.Filename,
46+
Uri = neg.tok.Uri,
4747
val = "-0"
4848
};
4949
optimisticallyDesugaredLit = new LiteralExpr(tok, -n);

Source/DafnyCore/AST/Grammar/IndentationFormatter.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Concurrent;
1+
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Linq;
45
using System.Text.RegularExpressions;
@@ -23,7 +24,7 @@ public IndentationFormatter(TokenNewIndentCollector formatter) {
2324
/// by immediately processing all nodes and assigning indentations to most structural tokens
2425
/// </summary>
2526
public static IndentationFormatter ForProgram(Program program, bool reduceBlockiness = true) {
26-
var tokenNewIndentCollector = new TokenNewIndentCollector {
27+
var tokenNewIndentCollector = new TokenNewIndentCollector(program) {
2728
ReduceBlockiness = reduceBlockiness
2829
};
2930
foreach (var child in program.DefaultModuleDef.PreResolveChildren) {

Source/DafnyCore/AST/Grammar/Printer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -972,9 +972,9 @@ private bool PrintModeSkipFunctionOrMethod(bool IsGhost, Attributes attributes,
972972
return false;
973973
}
974974

975-
private bool PrintModeSkipGeneral(Bpl.IToken tok, string fileBeingPrinted) {
975+
private bool PrintModeSkipGeneral(IToken tok, string fileBeingPrinted) {
976976
return (printMode == PrintModes.NoIncludes || printMode == PrintModes.NoGhost)
977-
&& tok.filename != null && fileBeingPrinted != null && Path.GetFullPath(tok.filename) != fileBeingPrinted;
977+
&& tok.Uri != null && fileBeingPrinted != null && tok.Uri.LocalPath != fileBeingPrinted;
978978
}
979979

980980
public void PrintMethod(Method method, int indent, bool printSignatureOnly) {

Source/DafnyCore/AST/Grammar/TokenNewIndentCollector.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ namespace Microsoft.Dafny;
5050
* ```
5151
*/
5252
public class TokenNewIndentCollector : TopDownVisitor<int> {
53+
private readonly Program program;
54+
5355
/* If true, the indentation will be
5456
* var name := method(
5557
* x,
@@ -81,8 +83,8 @@ private Indentations PosToIndentations(int pos) {
8183
public int binOpIndent = -1;
8284
public int binOpArgIndent = -1;
8385

84-
85-
internal TokenNewIndentCollector() {
86+
internal TokenNewIndentCollector(Program program) {
87+
this.program = program;
8688
preResolve = true;
8789
}
8890

@@ -229,7 +231,7 @@ public static bool IsFollowedByNewline(IToken token) {
229231
// 'inline' is the hypothetical indentation of this token if it was on its own line
230232
// 'below' is the hypothetical indentation of a comment after that token, and of the next token if it does not have a set indentation
231233
public void SetIndentations(IToken token, int above = -1, int inline = -1, int below = -1) {
232-
if (token is IncludeToken || (token.line == 0 && token.col == 0)) {
234+
if (token.WasIncluded(program) || (token.line == 0 && token.col == 0)) {
233235
// Just ignore this token.
234236
return;
235237
}
@@ -399,7 +401,7 @@ public void SetStatementIndentation(Statement statement) {
399401
}
400402

401403
public void SetDeclIndentation(TopLevelDecl topLevelDecl, int indent) {
402-
if (topLevelDecl.tok is IncludeToken) {
404+
if (topLevelDecl.tok.WasIncluded(program)) {
403405
return;
404406
}
405407

@@ -420,7 +422,7 @@ public void SetDeclIndentation(TopLevelDecl topLevelDecl, int indent) {
420422

421423
var initialMemberIndent = declWithMembers.tok.line == 0 ? indent : indent2;
422424
foreach (var member in declWithMembers.PreResolveChildren) {
423-
if (member.Tok is IncludeToken) {
425+
if (member.Tok.WasIncluded(program)) {
424426
continue;
425427
}
426428

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
5+
namespace Microsoft.Dafny;
6+
7+
public static class IncludeHandler {
8+
public static bool WasIncluded(this IToken token, DefaultModuleDefinition outerModule) {
9+
if (token is RefinementToken) {
10+
return false;
11+
}
12+
13+
if (token == Token.NoToken) {
14+
return false;
15+
}
16+
17+
var files = outerModule.RootUris;
18+
if (files.Contains(token.Uri)) {
19+
return false;
20+
}
21+
22+
return true;
23+
}
24+
25+
public static bool WasIncluded(this IToken token, Program program) {
26+
return token.WasIncluded(program.DefaultModuleDef);
27+
}
28+
}

Source/DafnyCore/AST/Tokens.cs

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections.Generic;
44
using System.Diagnostics.Contracts;
5+
using System.IO;
56
using System.Text;
67

78
namespace Microsoft.Dafny;
@@ -17,12 +18,14 @@ public interface IToken : Microsoft.Boogie.IToken {
1718
string val { get; set; }
1819
bool IsValid { get; }*/
1920
string Boogie.IToken.filename {
20-
get => Filename;
21-
set => Filename = value;
21+
get => Uri == null ? null : Path.GetFileName(Uri.LocalPath);
22+
set => throw new NotSupportedException();
2223
}
2324

24-
public string ActualFilename { get; }
25-
string Filename { get; set; }
25+
public string ActualFilename => Uri.LocalPath;
26+
string Filepath => Uri.LocalPath;
27+
28+
Uri Uri { get; set; }
2629

2730
/// <summary>
2831
/// TrailingTrivia contains everything after the token,
@@ -70,8 +73,9 @@ public Token(int linenum, int colnum) {
7073

7174
public int kind { get; set; } // Used by coco, so we can't rename it to Kind
7275

73-
public string ActualFilename => Filename;
74-
public string Filename { get; set; }
76+
public string ActualFilename => Filepath;
77+
public string Filepath => Uri?.LocalPath;
78+
public Uri Uri { get; set; }
7579

7680
public int pos { get; set; } // Used by coco, so we can't rename it to Pos
7781

@@ -104,7 +108,7 @@ public IToken WithVal(string newVal) {
104108
line = line,
105109
Prev = Prev,
106110
Next = Next,
107-
Filename = Filename,
111+
Uri = Uri,
108112
kind = kind,
109113
val = newVal
110114
};
@@ -115,7 +119,7 @@ public override int GetHashCode() {
115119
}
116120

117121
public override string ToString() {
118-
return $"{Filename}@{pos} - @{line}:{col}";
122+
return $"'{val}': {Path.GetFileName(Filepath)}@{pos} - @{line}:{col}";
119123
}
120124
}
121125

@@ -136,9 +140,11 @@ public virtual int col {
136140

137141
public string ActualFilename => WrappedToken.ActualFilename;
138142

139-
public virtual string Filename {
140-
get { return WrappedToken.Filename; }
141-
set { WrappedToken.filename = value; }
143+
public virtual string Filepath => WrappedToken.Filepath;
144+
145+
public Uri Uri {
146+
get => WrappedToken.Uri;
147+
set => WrappedToken.Uri = value;
142148
}
143149

144150
public bool IsValid {
@@ -180,6 +186,32 @@ public virtual IToken Prev {
180186
}
181187

182188
public static class TokenExtensions {
189+
190+
public static string TokenToString(this Boogie.IToken tok, DafnyOptions options) {
191+
if (tok is IToken dafnyToken) {
192+
return dafnyToken.TokenToString(options);
193+
}
194+
195+
return $"{tok.filename}({tok.line},{tok.col - 1})";
196+
}
197+
198+
public static string TokenToString(this IToken tok, DafnyOptions options) {
199+
if (tok.Uri == null) {
200+
return $"({tok.line},{tok.col - 1})";
201+
}
202+
203+
var currentDirectory = Directory.GetCurrentDirectory();
204+
string filename = tok.Uri.Scheme switch {
205+
"stdin" => "<stdin>",
206+
"transcript" => Path.GetFileName(tok.Filepath),
207+
_ => options.UseBaseNameForFileName
208+
? Path.GetFileName(tok.Filepath)
209+
: (tok.Filepath.StartsWith(currentDirectory) ? Path.GetRelativePath(currentDirectory, tok.Filepath) : tok.Filepath)
210+
};
211+
212+
return $"{filename}({tok.line},{tok.col - 1})";
213+
}
214+
183215
public static RangeToken ToRange(this IToken token) {
184216
if (token is BoogieRangeToken boogieRangeToken) {
185217
return new RangeToken(boogieRangeToken.StartToken, boogieRangeToken.EndToken);
@@ -301,54 +333,6 @@ public override IToken WithVal(string newVal) {
301333
}
302334
}
303335

304-
/// <summary>
305-
/// An IncludeToken is a wrapper that indicates that the function/method was
306-
/// declared in a file that was included. Any proof obligations from such an
307-
/// included file are to be ignored.
308-
/// </summary>
309-
public class IncludeToken : TokenWrapper {
310-
public Include Include;
311-
public IncludeToken(Include include, IToken wrappedToken)
312-
: base(wrappedToken) {
313-
Contract.Requires(wrappedToken != null);
314-
this.Include = include;
315-
}
316-
317-
public override string val {
318-
get { return WrappedToken.val; }
319-
set { WrappedToken.val = value; }
320-
}
321-
322-
public override int pos {
323-
get { return WrappedToken.pos; }
324-
set { WrappedToken.pos = value; }
325-
}
326-
327-
public override int line {
328-
get { return WrappedToken.line; }
329-
set { WrappedToken.line = value; }
330-
}
331-
332-
public override int col {
333-
get { return WrappedToken.col; }
334-
set { WrappedToken.col = value; }
335-
}
336-
337-
public override IToken Prev {
338-
get { return WrappedToken.Prev; }
339-
set { WrappedToken.Prev = value; }
340-
}
341-
342-
public override IToken Next {
343-
get { return WrappedToken.Next; }
344-
set { WrappedToken.Next = value; }
345-
}
346-
347-
public override IToken WithVal(string newVal) {
348-
return new IncludeToken(Include, WrappedToken.WithVal(newVal));
349-
}
350-
}
351-
352336
/// <summary>
353337
/// A token wrapper used to produce better type checking errors
354338
/// for quantified variables. See QuantifierVar.ExtractSingleRange()

Source/DafnyCore/AST/TopLevelDeclarations.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,14 +1130,14 @@ public override IEnumerable<Assumption> Assumptions(Declaration decl) {
11301130
}
11311131

11321132
public class DefaultModuleDefinition : ModuleDefinition {
1133-
public DefaultModuleDefinition()
1133+
1134+
public IList<Uri> RootUris { get; }
1135+
public DefaultModuleDefinition(IList<Uri> rootUris)
11341136
: base(RangeToken.NoToken, new Name("_module"), new List<IToken>(), false, false, null, null, null, true, true, true) {
1137+
RootUris = rootUris;
11351138
}
1136-
public override bool IsDefaultModule {
1137-
get {
1138-
return true;
1139-
}
1140-
}
1139+
1140+
public override bool IsDefaultModule => true;
11411141
}
11421142

11431143
public abstract class TopLevelDecl : Declaration, TypeParameter.ParentType {

0 commit comments

Comments
 (0)