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

Allow specifying an outer namespace when translating #4591

Merged
merged 23 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6801e50
Enable outer modules for C# and Java
keyboardDrummer Oct 13, 2023
7530350
Fix parser
keyboardDrummer Oct 13, 2023
c0ec305
Add deleted tests
keyboardDrummer Oct 13, 2023
869f434
Delete tests that don't exercise the feature
keyboardDrummer Oct 13, 2023
4b713dc
Merge remote-tracking branch 'origin/master' into translatePrefix
keyboardDrummer Oct 13, 2023
e462de7
Fix NRE issue
keyboardDrummer Oct 13, 2023
f1c2f4e
Merge branch 'master' into translatePrefix
keyboardDrummer Oct 13, 2023
1af41f8
Fix NSE
keyboardDrummer Oct 16, 2023
30cf7d1
Switch to --outer-module option
keyboardDrummer Oct 16, 2023
dba4c44
Merge branch 'translatePrefix' of github.com:keyboardDrummer/dafny in…
keyboardDrummer Oct 16, 2023
b70aace
Merge branch 'master' into translatePrefix
keyboardDrummer Oct 16, 2023
2dd7299
Run formatter and add missing tests
keyboardDrummer Oct 16, 2023
b724f66
Fix NRE
keyboardDrummer Oct 16, 2023
660198a
Merge branch 'translatePrefix' of github.com:keyboardDrummer/dafny in…
keyboardDrummer Oct 16, 2023
55306f6
Differentiate between module, static class and instance class separat…
keyboardDrummer Oct 17, 2023
9796715
Merge branch 'master' into translatePrefix
keyboardDrummer Oct 17, 2023
a6150e2
Customize module separators for Python and Go
keyboardDrummer Oct 17, 2023
deba271
Fix
keyboardDrummer Oct 17, 2023
6f97cfc
Generate package files for Python
keyboardDrummer Oct 17, 2023
58a9275
Python, every module is a package
keyboardDrummer Oct 17, 2023
84a4e74
Python fixes
keyboardDrummer Oct 17, 2023
2607ebf
Fix test so they do not abuse regex
keyboardDrummer Oct 17, 2023
ec6f01b
Merge branch 'master' into translatePrefix
robin-aws Oct 17, 2023
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
43 changes: 26 additions & 17 deletions Source/DafnyCore/AST/Grammar/ProgramParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -157,24 +158,10 @@ private static void AddParseResultToProgram(DfyParseResult parseResult, Program

parseResult.ErrorReporter.CopyDiagnostics(program.Reporter);

foreach (var declToMove in fileModule.DefaultClasses.Concat(fileModule.SourceDecls)) {
declToMove.EnclosingModuleDefinition = defaultModule;
if (declToMove is LiteralModuleDecl literalModuleDecl) {
literalModuleDecl.ModuleDef.EnclosingModule = defaultModule;
}
ModuleDefinition sourceModule = fileModule;
ModuleDefinition targetModule = defaultModule;

if (declToMove is ClassLikeDecl { NonNullTypeDecl: { } nonNullTypeDecl }) {
nonNullTypeDecl.EnclosingModuleDefinition = defaultModule;
}
if (declToMove is DefaultClassDecl defaultClassDecl) {
foreach (var member in defaultClassDecl.Members) {
defaultModule.DefaultClass.Members.Add(member);
member.EnclosingClass = defaultModule.DefaultClass;
}
} else {
defaultModule.SourceDecls.Add(declToMove);
}
}
MoveModuleContents(sourceModule, targetModule);

foreach (var include in fileModule.Includes) {
defaultModule.Includes.Add(include);
Expand All @@ -187,6 +174,28 @@ private static void AddParseResultToProgram(DfyParseResult parseResult, Program
defaultModule.DefaultClass.SetMembersBeforeResolution();
}

public static void MoveModuleContents(ModuleDefinition sourceModule, ModuleDefinition targetModule) {
foreach (var declToMove in sourceModule.DefaultClasses.Concat(sourceModule.SourceDecls)) {
declToMove.EnclosingModuleDefinition = targetModule;
if (declToMove is LiteralModuleDecl literalModuleDecl) {
literalModuleDecl.ModuleDef.EnclosingModule = targetModule;
}

if (declToMove is ClassLikeDecl { NonNullTypeDecl: { } nonNullTypeDecl }) {
nonNullTypeDecl.EnclosingModuleDefinition = targetModule;
}

if (declToMove is DefaultClassDecl defaultClassDecl) {
foreach (var member in defaultClassDecl.Members) {
targetModule.DefaultClass.Members.Add(member);
member.EnclosingClass = targetModule.DefaultClass;
}
} else {
targetModule.SourceDecls.Add(declToMove);
}
}
}

public IList<DfyParseResult> TryParseIncludes(
IReadOnlyList<DafnyFile> files,
IEnumerable<Include> roots,
Expand Down
4 changes: 3 additions & 1 deletion Source/DafnyCore/AST/Modules/DefaultModuleDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ public DefaultModuleDefinition(Cloner cloner, DefaultModuleDefinition original)

public DefaultModuleDefinition(IList<Uri> rootSourceUris)
: base(RangeToken.NoToken, new Name("_module"), new List<IToken>(), false, false,
null, null, null, true) {
null, null, null) {
RootSourceUris = rootSourceUris;
}

public override bool IsDefaultModule => true;

public override bool TryToAvoidName => Name == "_module";

public override IEnumerable<INode> Children => Includes.Concat(base.Children);
public override IEnumerable<INode> PreResolveChildren => Includes.Concat(base.PreResolveChildren);
public new DefaultModuleDefinition Clone(Cloner cloner) {
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/AST/Modules/FileModuleDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class FileModuleDefinition : ModuleDefinition {

public FileModuleDefinition(IToken token) :
base(token.ToRange(), new Name("_module"), new List<IToken>(),
false, false, null, null, null, true) {
false, false, null, null, null) {
{
}
}
Expand Down
36 changes: 26 additions & 10 deletions Source/DafnyCore/AST/Modules/ModuleDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class ModuleDefinition : RangeNode, IAttributeBearingDeclaration, IClonea
public IToken BodyStartTok = Token.NoToken;
public IToken TokenWithTrailingDocString = Token.NoToken;
public string DafnyName => NameNode.StartToken.val; // The (not-qualified) name as seen in Dafny source code
public readonly Name NameNode; // (Last segment of the) module name
public Name NameNode; // (Last segment of the) module name

public override IToken Tok => NameNode.StartToken;

Expand All @@ -31,7 +31,7 @@ public string FullDafnyName {
}
public string FullName {
get {
if (EnclosingModule == null || EnclosingModule.IsDefaultModule) {
if (EnclosingModule == null || EnclosingModule.TryToAvoidName) {
return Name;
} else {
return EnclosingModule.FullName + "." + Name;
Expand All @@ -47,7 +47,7 @@ public string FullName {
public bool SuccessfullyResolved; // set to true upon successful resolution; modules that import an unsuccessfully resolved module are not themselves resolved
public readonly bool IsAbstract;
public readonly bool IsFacade; // True iff this module represents a module facade (that is, an abstract interface)
private readonly bool IsBuiltinName; // true if this is something like _System that shouldn't have it's name mangled.
private bool IsBuiltinName => Name is "_System" or "_module"; // true if this is something like _System that shouldn't have it's name mangled.

public DefaultClassDecl DefaultClass { get; set; }

Expand Down Expand Up @@ -119,11 +119,9 @@ void ObjectInvariant() {

public ModuleDefinition(Cloner cloner, ModuleDefinition original, Name name) : this(cloner, original) {
NameNode = name;
IsBuiltinName = true;
}

public ModuleDefinition(Cloner cloner, ModuleDefinition original) : base(cloner, original) {
IsBuiltinName = original.IsBuiltinName;
NameNode = original.NameNode;
PrefixIds = original.PrefixIds.Select(cloner.Tok).ToList();

Expand Down Expand Up @@ -156,8 +154,7 @@ public ModuleDefinition(Cloner cloner, ModuleDefinition original) : base(cloner,
}

public ModuleDefinition(RangeToken tok, Name name, List<IToken> prefixIds, bool isAbstract, bool isFacade,
ModuleQualifiedId refinementQId, ModuleDefinition parent, Attributes attributes,
bool isBuiltinName) : base(tok) {
ModuleQualifiedId refinementQId, ModuleDefinition parent, Attributes attributes) : base(tok) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
this.NameNode = name;
Expand All @@ -167,7 +164,6 @@ public ModuleDefinition(RangeToken tok, Name name, List<IToken> prefixIds, bool
this.RefinementQId = refinementQId;
this.IsAbstract = isAbstract;
this.IsFacade = isFacade;
this.IsBuiltinName = isBuiltinName;

if (Name != "_System") {
DefaultClass = new DefaultClassDecl(this, new List<MemberDecl>());
Expand All @@ -180,8 +176,15 @@ public ModuleDefinition(RangeToken tok, Name name, List<IToken> prefixIds, bool

public virtual bool IsDefaultModule => false;

public virtual bool TryToAvoidName => false;

private string sanitizedName = null;

public void ClearNameCache() {
sanitizedName = null;
compileName = null;
}

public string SanitizedName {
get {
if (sanitizedName == null) {
Expand Down Expand Up @@ -212,7 +215,20 @@ public string GetCompileName(DafnyOptions options) {
} else if (externArgs != null) {
compileName = Name + nonExternSuffix;
} else {
compileName = SanitizedName + nonExternSuffix;

if (IsBuiltinName) {
compileName = Name;
} else if (EnclosingModule is { TryToAvoidName: false }) {
// Include all names in the module tree path, to disambiguate when compiling
// a flat list of modules.
// Use an "underscore-escaped" character as a module name separator, since
// underscores are already used as escape characters in SanitizeName()
compileName = EnclosingModule.GetCompileName(options) + options.Backend.ModuleSeparator + NonglobalVariable.SanitizeName(Name);
} else {
compileName = NonglobalVariable.SanitizeName(Name);
}

compileName += nonExternSuffix;
}
}

Expand Down Expand Up @@ -602,7 +618,7 @@ public void ProcessPrefixNamedModules() {
var prefixNameModule = prefixNamedModules.First();
var firstPartToken = prefixNameModule.Parts[0];
var modDef = new ModuleDefinition(RangeToken.NoToken, new Name(firstPartToken.ToRange(), name), new List<IToken>(), false,
false, null, this, null, false);
false, null, this, null);
// Add the new module to the top-level declarations of its parent and then bind its names as usual

// Use an empty cloneId because these are empty module declarations.
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/AST/SystemModuleManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Microsoft.Dafny;
public class SystemModuleManager {
public DafnyOptions Options { get; }
public readonly ModuleDefinition SystemModule = new(RangeToken.NoToken, new Name("_System"), new List<IToken>(),
false, false, null, null, null, true);
false, false, null, null, null);
internal readonly Dictionary<int, ClassDecl> arrayTypeDecls = new();
public readonly Dictionary<int, ArrowTypeDecl> ArrowTypeDecls = new();
public readonly Dictionary<int, SubsetTypeDecl> PartialArrowTypeDecls = new(); // same keys as arrowTypeDecl
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/AST/TypeDeclarations/TopLevelDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public string GetFullCompileName(DafnyOptions options) {
}
}

return options.Backend.GetCompileName(EnclosingModuleDefinition.IsDefaultModule,
return options.Backend.GetCompileName(EnclosingModuleDefinition.TryToAvoidName,
EnclosingModuleDefinition.GetCompileName(options), GetCompileName(options));
}

Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/AST/Types/UserDefinedType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void ObjectInvariant() {

public string FullName {
get {
if (ResolvedClass?.EnclosingModuleDefinition?.IsDefaultModule == false) {
if (ResolvedClass?.EnclosingModuleDefinition?.TryToAvoidName == false) {
return ResolvedClass.EnclosingModuleDefinition.Name + "." + Name;
} else {
return Name;
Expand All @@ -36,7 +36,7 @@ public string FullName {
public string GetFullCompanionCompileName(DafnyOptions options) {
Contract.Requires(ResolvedClass is TraitDecl || (ResolvedClass is NonNullTypeDecl nntd && nntd.Class is TraitDecl));
var m = ResolvedClass.EnclosingModuleDefinition;
var s = m.IsDefaultModule ? "" : m.GetCompileName(options) + ".";
var s = m.TryToAvoidName ? "" : m.GetCompileName(options) + ".";
return s + "_Companion_" + ResolvedClass.GetCompileName(options);
}

Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/Auditor/AuditReport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public string RenderMarkdownIETF() {
StringBuilder text = new StringBuilder();

foreach (var module in modulesWithEntries) {
if (module.IsDefaultModule) {
if (module.TryToAvoidName) {
text.AppendLine($"# Default module");
} else {
text.AppendLine($"# Module `{module.Name}`");
Expand Down
10 changes: 5 additions & 5 deletions Source/DafnyCore/Compilers/CSharp/Compiler-Csharp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,7 @@ void DatatypeFieldsAndConstructor(DatatypeCtor ctor, int constructorIndex, Concr
if (dt is TupleTypeDecl) {
nm = "";
} else {
nm = (dt.EnclosingModuleDefinition.IsDefaultModule ? "" : dt.EnclosingModuleDefinition.Name + ".") + dt.Name + "." + ctor.Name;
nm = (dt.EnclosingModuleDefinition.TryToAvoidName ? "" : dt.EnclosingModuleDefinition.Name + ".") + dt.Name + "." + ctor.Name;
}

switch (dt) {
Expand Down Expand Up @@ -1166,7 +1166,7 @@ string DtCtorName(DatatypeCtor ctor) {
Contract.Ensures(Contract.Result<string>() != null);

var dt = ctor.EnclosingDatatype;
var dtName = dt.EnclosingModuleDefinition.IsDefaultModule ? IdName(dt) : dt.GetFullCompileName(Options);
var dtName = dt.EnclosingModuleDefinition.TryToAvoidName ? IdName(dt) : dt.GetFullCompileName(Options);
return dt.IsRecordType ? dtName : dtName + "_" + ctor.GetCompileName(Options);
}

Expand Down Expand Up @@ -2426,10 +2426,10 @@ private string FullTypeName(UserDefinedType udt, MemberDecl/*?*/ member = null,
if ((cl is DatatypeDecl)
&& !ignoreInterface
&& (member is null || !NeedsCustomReceiver(member))) {
return (cl.EnclosingModuleDefinition.IsDefaultModule ? "" : IdProtect(cl.EnclosingModuleDefinition.GetCompileName(Options)) + ".") + DtTypeName(cl, false);
return (cl.EnclosingModuleDefinition.TryToAvoidName ? "" : IdProtect(cl.EnclosingModuleDefinition.GetCompileName(Options)) + ".") + DtTypeName(cl, false);
}

if (cl.EnclosingModuleDefinition.IsDefaultModule) {
if (cl.EnclosingModuleDefinition.TryToAvoidName) {
return IdProtect(cl.GetCompileName(Options));
}

Expand Down Expand Up @@ -3381,7 +3381,7 @@ public override void EmitCallToMain(Method mainMethod, string baseName, Concrete
var companion = TypeName_Companion(UserDefinedType.FromTopLevelDeclWithAllBooleanTypeParameters(mainMethod.EnclosingClass), wr, mainMethod.tok, mainMethod);
var wClass = wr.NewNamedBlock("class __CallToMain");
var wBody = wClass.NewNamedBlock("public static void Main(string[] args)");
var modName = mainMethod.EnclosingClass.EnclosingModuleDefinition.GetCompileName(Options) == "_module" ? "_module." : "";
var modName = mainMethod.EnclosingClass.EnclosingModuleDefinition.TryToAvoidName ? "_module." : "";
companion = modName + companion;

var idName = IssueCreateStaticMain(mainMethod) ? "_StaticMain" : IdName(mainMethod);
Expand Down
3 changes: 1 addition & 2 deletions Source/DafnyCore/Compilers/CSharp/CsharpBackend.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
using System.Text.Json;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace Microsoft.Dafny.Compilers;

public class CsharpBackend : ExecutableBackend {

protected override SinglePassCompiler CreateCompiler() {
return new CsharpCompiler(Options, Reporter);
}
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/Compilers/Cplusplus/Compiler-cpp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public CppCompiler(DafnyOptions options, ErrorReporter reporter, ReadOnlyCollect
const string DafnySeqClass = "DafnySequence";
const string DafnyMapClass = "DafnyMap";

protected override string ModuleSeparator => "::";
public override string ModuleSeparator => "::";
protected override string ClassAccessor => "->";

protected override void EmitHeader(Program program, ConcreteSyntaxTree wr) {
Expand Down
48 changes: 35 additions & 13 deletions Source/DafnyCore/Compilers/ExecutableBackend.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
Expand All @@ -17,39 +18,60 @@ public abstract class ExecutableBackend : IExecutableBackend {
// May be null for backends that don't use the single-pass compiler logic
protected SinglePassCompiler compiler;

protected ExecutableBackend(DafnyOptions options) {
Options = options;
protected ExecutableBackend(DafnyOptions options) : base(options) {
}

public DafnyOptions Options { get; }

public override IReadOnlySet<Feature> UnsupportedFeatures => CreateCompiler().UnsupportedFeatures;

public override bool SupportsDatatypeWrapperErasure =>
CreateCompiler()?.SupportsDatatypeWrapperErasure ?? base.SupportsDatatypeWrapperErasure;

public override string ModuleSeparator => Compiler.ModuleSeparator;

public override void Compile(Program dafnyProgram, ConcreteSyntaxTree output) {
compiler.Compile(dafnyProgram, output);
var outerModules = GetOuterModules();
ModuleDefinition rootUserModule = null;
foreach (var outerModule in outerModules) {
var newRoot = new ModuleDefinition(RangeToken.NoToken, new Name(outerModule), new List<IToken>(), false, false,
null, null, null);
newRoot.EnclosingModule = rootUserModule;
rootUserModule = newRoot;
}

if (rootUserModule != null) {
dafnyProgram.DefaultModuleDef.NameNode = rootUserModule.NameNode;
dafnyProgram.DefaultModuleDef.EnclosingModule = rootUserModule.EnclosingModule;
}

foreach (var module in dafnyProgram.CompileModules) {
module.ClearNameCache();
}
Compiler.Compile(dafnyProgram, output);
}

public override void OnPreCompile(ErrorReporter reporter, ReadOnlyCollection<string> otherFileNames) {
base.OnPreCompile(reporter, otherFileNames);
compiler = CreateCompiler();
SinglePassCompiler Compiler {
get {
if (compiler == null) {
compiler = CreateCompiler();
}

return compiler;
}
}

public override void OnPostCompile() {
base.OnPostCompile();
compiler.Coverage.WriteLegendFile();
Compiler.Coverage.WriteLegendFile();
}

protected abstract SinglePassCompiler CreateCompiler();

public override string PublicIdProtect(string name) {
return compiler.PublicIdProtect(name);
return Compiler.PublicIdProtect(name);
}

public override void EmitCallToMain(Method mainMethod, string baseName, ConcreteSyntaxTree callToMainTree) {
compiler.EmitCallToMain(mainMethod, baseName, callToMainTree);
Compiler.EmitCallToMain(mainMethod, baseName, callToMainTree);
}

public ProcessStartInfo PrepareProcessStartInfo(string programName, IEnumerable<string> args = null) {
Expand Down Expand Up @@ -140,11 +162,11 @@ public override bool RunTargetProgram(string dafnyProgramName, string targetProg
}

public override void InstrumentCompiler(CompilerInstrumenter instrumenter, Program dafnyProgram) {
if (compiler == null) {
if (Compiler == null) {
return;
}

instrumenter.Instrument(this, compiler, dafnyProgram);
instrumenter.Instrument(this, Compiler, dafnyProgram);
}

protected static void WriteFromFile(string inputFilename, TextWriter outputWriter) {
Expand Down
Loading
Loading