From 3894e23144ab17efd285337cb6cabb30f9a1a3c0 Mon Sep 17 00:00:00 2001 From: loki der quaeler <quaeler@gmail.com> Date: Tue, 18 Feb 2020 11:00:04 -0800 Subject: [PATCH] No-monolith option in TLC - #393 . Now providing an option to not include the module TLA+ code of all dependent modules in the generated SpecTE.tla file (-nomonolith) [Enhancement][Tools] --- tlatools/src/tlc2/TLC.java | 30 +++++-- .../src/tlc2/output/TLAMonolithCreator.java | 82 +++++++++++-------- tlatools/src/util/UsageGenerator.java | 24 ++++++ 3 files changed, 99 insertions(+), 37 deletions(-) diff --git a/tlatools/src/tlc2/TLC.java b/tlatools/src/tlc2/TLC.java index 9a283bbfb..85257a293 100644 --- a/tlatools/src/tlc2/TLC.java +++ b/tlatools/src/tlc2/TLC.java @@ -136,6 +136,7 @@ public class TLC { private File specTETLAFile; private MCParserResults mcParserResults; private MCOutputPipeConsumer mcOutputConsumer; + private boolean avoidMonolithSpecTECreation; private final AtomicBoolean waitingOnGenerationCompletion; /** @@ -162,6 +163,7 @@ public class TLC { fpSetConfiguration = new FPSetConfiguration(); + avoidMonolithSpecTECreation = false; waitingOnGenerationCompletion = new AtomicBoolean(false); } @@ -225,6 +227,8 @@ public class TLC { * encountered during model checking; this will change * to tool mode regardless of whether '-tool' was * explicitly specified. + * o -nomonolith: if generating a SpecTE, do not generate the monolith + * version * o -checkpoint num: interval for check pointing (in minutes) * Defaults to 30 * o -fpmem num: a value between 0 and 1, exclusive, representing the ratio @@ -410,6 +414,9 @@ public class TLC { { index++; TLCGlobals.tool = true; + } else if (args[index].equals("-nomonolith")) { + index++; + avoidMonolithSpecTECreation = true; } else if (args[index].equals("-generateSpecTE")) { index++; @@ -456,13 +463,22 @@ public class TLC { mcOutFIS.close(); tempTLAFIS.close(); - final List<File> extendedModules = mcOutputConsumer.getExtendedModuleLocations(); - final TLAMonolithCreator monolithCreator + final TLAMonolithCreator monolithCreator; + if (avoidMonolithSpecTECreation) { + monolithCreator + = new TLAMonolithCreator(TLAConstants.TraceExplore.ERROR_STATES_MODULE_NAME, + mcOutputConsumer.getSourceDirectory(), + mcParserResults.getAllExtendedModules()); + } else { + final List<File> extendedModules = mcOutputConsumer.getExtendedModuleLocations(); + monolithCreator = new TLAMonolithCreator(TLAConstants.TraceExplore.ERROR_STATES_MODULE_NAME, mcOutputConsumer.getSourceDirectory(), extendedModules, mcParserResults.getAllExtendedModules(), mcParserResults.getAllInstantiatedModules()); + } + monolithCreator.copy(); } @@ -1394,6 +1410,12 @@ public class TLC { sharedArguments.add(new UsageGenerator.Argument("-metadir", "path", "specify the directory in which to store metadata; defaults to\n" + "SPEC-directory/states if not specified", true)); + sharedArguments.add(new UsageGenerator.Argument("-nomonolith", + "if -generateSpecTE was specified and a SpecTE is created due\n" + + "to errors encountered, this flag specifies not to create a\n" + + "monolithic SpecTE that embeds all non-Standard-Module\n" + + "dependent TLA modules - rather, include them via a\n" + + "complete EXTENDS list", true)); sharedArguments.add(new UsageGenerator.Argument("-nowarning", "disable all warnings; defaults to reporting warnings", true)); sharedArguments.add(new UsageGenerator.Argument("-recover", "id", @@ -1443,9 +1465,7 @@ public class TLC { + "model values to start with a non-numeral and rerun the model check to generate a new SpecTE."); tips.add("If, while checking a SpecTE created via '-generateSpecTE', you get a warning concerning\n" + "duplicate operator definitions, this is likely due to the 'monolith' specification\n" - + "creation. Until a 'disable monolith creation' flag is added to TLC, provide the tool\n" - + "output of your model checking to tlc2.TraceExplorer to have it generate a non-monolithic\n" - + "specification."); + + "creation. Try re-running TLC adding the -nomonolith flag."); UsageGenerator.displayUsage(ToolIO.out, "TLC", TLCGlobals.versionOfTLC, "provides model checking and simulation of TLA+ specifications", diff --git a/tlatools/src/tlc2/output/TLAMonolithCreator.java b/tlatools/src/tlc2/output/TLAMonolithCreator.java index b46f5407a..3ce15e66a 100644 --- a/tlatools/src/tlc2/output/TLAMonolithCreator.java +++ b/tlatools/src/tlc2/output/TLAMonolithCreator.java @@ -37,6 +37,17 @@ public class TLAMonolithCreator extends AbstractTLACopier { // TODO this is insufficient for nestings beyond one level private final List<File> modulesToNest; + /** + * This is the constructor for the version which embeds no dependent modules. + * + * @param entireExtendsList the modules which the root ModuleNode or one of its sub-ModuleNodes (or one or their + * sub-ModuleNodes and so on, turtles all the way down) has defined as EXTENDS-ing + * in their spec. + */ + public TLAMonolithCreator(final String rootSpecName, final File sourceLocation, final Set<String> entireExtendsList) { + this(rootSpecName, sourceLocation, null, entireExtendsList, null); + } + /** * @param rootSpecName * @param sourceLocation @@ -46,52 +57,59 @@ public class TLAMonolithCreator extends AbstractTLACopier { * wrong order * @param entireExtendsList the modules which the root ModuleNode or one of its sub-ModuleNodes (or one or their * sub-ModuleNodes and so on, turtles all the way down) has defined as EXTENDS-ing - * in their spec; this will get the Standard Modules filtered out of it prior to - * usage in this class + * in their spec; this will get the non Standard Modules filtered out of it prior to + * usage in this class since those will get embedded as a dependent module. * @param allInstantiatedModules */ public TLAMonolithCreator(final String rootSpecName, final File sourceLocation, final List<File> extendeds, final Set<String> entireExtendsList, final Set<String> allInstantiatedModules) { super(rootSpecName, ("tmp_" + System.currentTimeMillis() + "_monolith"), sourceLocation); - final HashSet<String> instantiatedModules = new HashSet<>(allInstantiatedModules); - final Stack<File> embedStack = new Stack<>(); + final boolean willEmbedDependents = (extendeds != null); + moduleNamesBeingEmbedded = new HashSet<>(); - for (final File f : extendeds) { - final String name = f.getName(); - final int index = name.toLowerCase().indexOf(TLAConstants.Files.TLA_EXTENSION); - final boolean keep; - final String moduleName; - if (index == -1) { - // this should never be the case - keep = true; - moduleName = name; - } else { - moduleName = name.substring(0, index); - - keep = !StandardModules.isDefinedInStandardModule(moduleName); + modulesToNest = new ArrayList<>(); + modulesToEmbed = new ArrayList<>(); + if (willEmbedDependents) { + final HashSet<String> instantiatedModules = new HashSet<>(allInstantiatedModules); + final Stack<File> embedStack = new Stack<>(); + for (final File f : extendeds) { + final String name = f.getName(); + final int index = name.toLowerCase().indexOf(TLAConstants.Files.TLA_EXTENSION); + final boolean keep; + final String moduleName; + if (index == -1) { + // this should never be the case + keep = true; + moduleName = name; + } else { + moduleName = name.substring(0, index); + + keep = !StandardModules.isDefinedInStandardModule(moduleName); + } + + if (keep) { + embedStack.push(f); + instantiatedModules.remove(moduleName); + moduleNamesBeingEmbedded.add(moduleName); + } } - if (keep) { - embedStack.push(f); - instantiatedModules.remove(moduleName); - moduleNamesBeingEmbedded.add(moduleName); + while (!embedStack.isEmpty()) { + modulesToEmbed.add(embedStack.pop()); } - } - modulesToEmbed = new ArrayList<>(); - while (!embedStack.isEmpty()) { - modulesToEmbed.add(embedStack.pop()); - } - - modulesToNest = new ArrayList<>(); - for (final String module : instantiatedModules) { - if (!StandardModules.isDefinedInStandardModule(module)) { - modulesToNest.add(new File(sourceLocation, (module + TLAConstants.Files.TLA_EXTENSION))); + + for (final String module : instantiatedModules) { + if (!StandardModules.isDefinedInStandardModule(module)) { + modulesToNest.add(new File(sourceLocation, (module + TLAConstants.Files.TLA_EXTENSION))); + } } } modulesToSpecifyInExtends = new HashSet<>(entireExtendsList); - StandardModules.filterNonStandardModulesFromSet(modulesToSpecifyInExtends); + if (willEmbedDependents) { + StandardModules.filterNonStandardModulesFromSet(modulesToSpecifyInExtends); + } // for TLC things modulesToSpecifyInExtends.add(TLAConstants.BuiltInModules.TLC); // for _TE things diff --git a/tlatools/src/util/UsageGenerator.java b/tlatools/src/util/UsageGenerator.java index cdc01d1af..aa4114dc0 100644 --- a/tlatools/src/util/UsageGenerator.java +++ b/tlatools/src/util/UsageGenerator.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -316,5 +317,28 @@ public class UsageGenerator { public String getDescription() { return description; } + + @Override + public int hashCode() { + return Objects.hash(argumentName); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null) { + return false; + } + + if (getClass() != obj.getClass()) { + return false; + } + + final Argument other = (Argument) obj; + return Objects.equals(argumentName, other.argumentName); + } } } -- GitLab