diff --git a/build.gradle b/build.gradle index 1a3534069db76a39ad0ed6e42056d5e7edf68bcf..e923aec4563860df131604b47fde5c3c9bb55303 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ dependencies { releaseJars (group: 'de.prob', name: 'prologlib', version: parser_version) releaseJars (group: 'de.prob', name: 'parserbase', version: parser_version) releaseJars (group: 'de.prob', name: 'bparser', version: parser_version) + releaseJars (group: 'de.prob', name: 'ltlparser', version: parser_version) } diff --git a/src/main/java/de/b2tla/B2TLA.java b/src/main/java/de/b2tla/B2TLA.java index e467d870e5d3b723303023842a512b0b269423c4..db8ff976dd82b97df67035c77f3f24abe371a086 100644 --- a/src/main/java/de/b2tla/B2TLA.java +++ b/src/main/java/de/b2tla/B2TLA.java @@ -33,7 +33,8 @@ public class B2TLA { private String config; private B2TlaTranslator translator; private TLCOutputInfo tlcOutputInfo; - + private String ltlFormula; + public static void main(String[] args) throws IOException { StopWatch.start("Translation"); B2TLA b2tla = new B2TLA(); @@ -85,7 +86,7 @@ public class B2TLA { tlcOutput.parseTLCOutput(); System.out.println("Model checking time: " + tlcOutput.getRunningTime() + " sec"); - + System.out.println("Result: " + tlcOutput.getError()); if (tlcOutput.hasTrace() && createTraceFile) { StringBuilder trace = tlcOutput.getErrorTrace(); @@ -110,6 +111,15 @@ public class B2TLA { Globals.invariant = false; } else if (args[index].toLowerCase().equals("-tool")) { Globals.tool = true; + } else if (args[index].toLowerCase().equals("-noltl")) { + Globals.checkltl = false; + } else if (args[index].toLowerCase().equals("-ltlformula")) { + index = index + 1; + if (index == args.length) { + throw new B2TLAIOException( + "Error: LTL formula requiered after option '-ltlformula'."); + } + ltlFormula = args[index]; } else if (args[index].charAt(0) == '-') { throw new B2TLAIOException("Error: unrecognized option: " + args[index]); @@ -134,7 +144,7 @@ public class B2TLA { handleMainFileName(); if (Globals.translate) { - translator = new B2TlaTranslator(machineName, getFile()); + translator = new B2TlaTranslator(machineName, getFile(), this.ltlFormula); translator.translate(); this.tlaModule = translator.getModuleString(); @@ -189,7 +199,7 @@ public class B2TLA { STANDARD_MODULES.BBuiltIns)) { createStandardModule(path, STANDARD_MODULES.BBuiltIns.toString()); } - + if (translator.getUsedStandardModule().contains( STANDARD_MODULES.FunctionsAsRelations)) { createStandardModule(path, diff --git a/src/main/java/de/b2tla/B2TlaTranslator.java b/src/main/java/de/b2tla/B2TlaTranslator.java index 4006acbecc6a9f8416688e7ff56547b9fcde43ed..9327ff5e896c76a86983de8130b21f62e0deff71 100644 --- a/src/main/java/de/b2tla/B2TlaTranslator.java +++ b/src/main/java/de/b2tla/B2TlaTranslator.java @@ -9,14 +9,15 @@ import de.b2tla.analysis.ConstantsEliminator; import de.b2tla.analysis.ConstantsEvaluator; import de.b2tla.analysis.DefinitionsAnalyser; import de.b2tla.analysis.MachineContext; +import de.b2tla.analysis.UnchangedVariablesFinder; import de.b2tla.analysis.PrecedenceCollector; import de.b2tla.analysis.PrimedNodesMarker; import de.b2tla.analysis.Renamer; import de.b2tla.analysis.TypeRestrictor; import de.b2tla.analysis.Typechecker; -import de.b2tla.analysis.UnchangedVariablesFinder; import de.b2tla.analysis.UsedStandardModules; import de.b2tla.analysis.UsedStandardModules.STANDARD_MODULES; +import de.b2tla.ltl.LTLFormulaVisitor; import de.b2tla.prettyprint.TLAPrinter; import de.b2tla.tla.Generator; import de.b2tla.tlc.TLCOutputInfo; @@ -31,6 +32,7 @@ public class B2TlaTranslator { private String moduleString; private String configString; private String machineName; + private String ltlFormula; private ArrayList<STANDARD_MODULES> usedStandardModules; private TLCOutputInfo tlcOutputInfo; @@ -42,9 +44,20 @@ public class B2TlaTranslator { start.apply(ast2String2); System.out.println(ast2String2.toString()); } + + public B2TlaTranslator(String machineString, String ltlFormula) throws BException { + this.machineString = machineString; + this.ltlFormula = ltlFormula; + BParser parser = new BParser("Testing"); + start = parser.parse(machineString, false); + final Ast2String ast2String2 = new Ast2String(); + start.apply(ast2String2); + System.out.println(ast2String2.toString()); + } - public B2TlaTranslator(String machineName, File machineFile) + public B2TlaTranslator(String machineName, File machineFile, String ltlFormula) throws IOException, BException { + this.ltlFormula = ltlFormula; BParser parser = new BParser(machineName); start = parser.parseFile(machineFile, false); final Ast2String ast2String2 = new Ast2String(); @@ -53,13 +66,15 @@ public class B2TlaTranslator { } public void translate() { - - MachineContext machineContext = new MachineContext(start); + + MachineContext machineContext = new MachineContext(start, ltlFormula); this.machineName = machineContext.getMachineName(); + Typechecker typechecker = new Typechecker(machineContext); - UnchangedVariablesFinder unchangedVariablesFinder = new UnchangedVariablesFinder( - machineContext); + + UnchangedVariablesFinder unchangedVariablesFinder = new UnchangedVariablesFinder(machineContext); + PrecedenceCollector precedenceCollector = new PrecedenceCollector( start, typechecker.getTypes()); diff --git a/src/main/java/de/b2tla/Globals.java b/src/main/java/de/b2tla/Globals.java index 71c4420a8bd6fac61430889c76f5fe0e71b97754..137921c1c0358d434dde441a77a55de1326237fd 100644 --- a/src/main/java/de/b2tla/Globals.java +++ b/src/main/java/de/b2tla/Globals.java @@ -10,6 +10,7 @@ public class Globals { public static boolean runTLC = true; public static boolean translate = true; public static boolean invariant = true; + public static boolean checkltl = true; public static boolean tool = false; public static boolean deleteOnExit = false; diff --git a/src/main/java/de/b2tla/Main.java b/src/main/java/de/b2tla/Main.java deleted file mode 100644 index dca1eb77582078063017242fc1c798b719c00b1b..0000000000000000000000000000000000000000 --- a/src/main/java/de/b2tla/Main.java +++ /dev/null @@ -1,53 +0,0 @@ -package de.b2tla; -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import de.be4.classicalb.core.parser.BParser; -import de.be4.classicalb.core.parser.analysis.pragma.Pragma; -import de.be4.classicalb.core.parser.analysis.prolog.RecursiveMachineLoader; -import de.be4.classicalb.core.parser.exceptions.BException; -import de.be4.classicalb.core.parser.node.Start; - - -public class Main { - - - public static void main(String[] args) throws IOException, BException { - - - String filename = "M1.mch"; - final File machineFile = new File(filename); - //final String probfilename = filename.substring(0, dot) + ".prob"; - - - - BParser parser = new BParser(filename); - Start tree = parser.parseFile(machineFile, false); - - //System.out.println(parser.getDefinitions().getDefinitionNames()); - - - RecursiveMachineLoader r = new RecursiveMachineLoader(machineFile.getParent(), parser.getContentProvider()); - - - List<Pragma> pragmas = new ArrayList<Pragma>(); - pragmas.addAll(parser.getPragmas()); - r.loadAllMachines(machineFile, tree, parser.getSourcePositions(), parser.getDefinitions(), pragmas); - - r.printAsProlog(new PrintWriter(System.out), false); - - -// //System.out.println(r.getParsedMachines()); -// System.out.println(r.getParsedMachines().size()); -// for (String name : r.getParsedMachines().keySet()) { -// System.out.print(name+ " "); -// System.out.println(r.getParsedMachines().get(name)); -// } - - - } - -} diff --git a/src/main/java/de/b2tla/analysis/AssignedVariablesFinder.java b/src/main/java/de/b2tla/analysis/AssignedVariablesFinder.java index db67446d4db38d4a3a53af641967c83fd165d394..f2a8d0b144e1a1e64ce4fb2d9c28ff8a83cae152 100644 --- a/src/main/java/de/b2tla/analysis/AssignedVariablesFinder.java +++ b/src/main/java/de/b2tla/analysis/AssignedVariablesFinder.java @@ -88,8 +88,7 @@ public class AssignedVariablesFinder extends DepthFirstAdapter { getVariableList(node.getSubstitutions())); /* - * In the INITIALISATION clause all variables must be assigned. TODO - * ouput parameter must be assigned too? + * In the INITIALISATION clause all variables must be assigned. */ HashSet<Node> allVariables = new HashSet<Node>(machineContext .getVariables().values()); diff --git a/src/main/java/de/b2tla/analysis/DefinitionsAnalyser.java b/src/main/java/de/b2tla/analysis/DefinitionsAnalyser.java index acc969cd8afe965af8c865eab591abc4d9a17169..4b2d2a35b8f872be7ff239e7647989f110a68b1e 100644 --- a/src/main/java/de/b2tla/analysis/DefinitionsAnalyser.java +++ b/src/main/java/de/b2tla/analysis/DefinitionsAnalyser.java @@ -13,6 +13,14 @@ import de.be4.classicalb.core.parser.node.AIntegerExpression; import de.be4.classicalb.core.parser.node.AIntervalExpression; import de.be4.classicalb.core.parser.node.Node; +/** + * + * + * + * @author hansen + * + */ + public class DefinitionsAnalyser extends DepthFirstAdapter{ private MachineContext machineContext; private HashMap<Node, Integer> deferredSetSizeTable; @@ -60,6 +68,7 @@ public class DefinitionsAnalyser extends DepthFirstAdapter{ @Override public void caseAIdentifierExpression(AIdentifierExpression node) { + //TODO never reached Node ref_node = machineContext.getReferences().get(node); if(deferredSetSizeTable.containsKey(ref_node)){ try { diff --git a/src/main/java/de/b2tla/analysis/DefinitionsOrder.java b/src/main/java/de/b2tla/analysis/DefinitionsOrder.java index 579e13cec18a58df4004cfcbef3480e8ea0ba907..16a50a3fbbd35a33cfb49e1754d0be91156f1bc6 100644 --- a/src/main/java/de/b2tla/analysis/DefinitionsOrder.java +++ b/src/main/java/de/b2tla/analysis/DefinitionsOrder.java @@ -14,6 +14,13 @@ import de.be4.classicalb.core.parser.node.ASubstitutionDefinitionDefinition; import de.be4.classicalb.core.parser.node.Node; import de.be4.classicalb.core.parser.node.PDefinition; +/** + * A BDefinitions can depend on another BDefinitions. For the translation to + * TLA+ the definitions must be sorted. + * + * @author hansen + */ + public class DefinitionsOrder extends DepthFirstAdapter { private MachineContext machineContext; private Hashtable<Node, HashSet<Node>> dependenciesTable; @@ -25,7 +32,6 @@ public class DefinitionsOrder extends DepthFirstAdapter { return allDefinitions; } - public DefinitionsOrder(MachineContext machineContext, ArrayList<PDefinition> allDefinitions) { this.machineContext = machineContext; @@ -35,9 +41,8 @@ public class DefinitionsOrder extends DepthFirstAdapter { def.apply(this); } - this.allDefinitions = sort(new ArrayList<PDefinition>(allDefinitions)); - + } private ArrayList<PDefinition> sort(ArrayList<PDefinition> list) { @@ -70,7 +75,7 @@ public class DefinitionsOrder extends DepthFirstAdapter { } } } - + if (result.size() != list.size()) { throw new RuntimeException("Found cyclic Definitions."); } @@ -118,32 +123,32 @@ public class DefinitionsOrder extends DepthFirstAdapter { } public void inADefinitionExpression(ADefinitionExpression node) { - + Node refNode = machineContext.getReferences().get(node); /* - * If refNode is null, then the whole branch was cloned when a constant assignment was generated + * If refNode is null, then the whole branch was cloned when a constant + * assignment was generated */ - - if(null != refNode){ + + if (null != refNode) { current.add(refNode); } - + } public void inAIdentifierExpression(AIdentifierExpression node) { Node identifierRef = machineContext.getReferences().get(node); - if(identifierRef == null) + if (identifierRef == null) return; - - if(machineContext.getConstants().containsValue(identifierRef)){ + + if (machineContext.getConstants().containsValue(identifierRef)) { current.add(identifierRef); return; } - - if (machineContext.getReferences().get(identifierRef) instanceof PDefinition){ + + if (machineContext.getReferences().get(identifierRef) instanceof PDefinition) { current.add(identifierRef); } - - + } } diff --git a/src/main/java/de/b2tla/analysis/MachineContext.java b/src/main/java/de/b2tla/analysis/MachineContext.java index a11c76027012ecafc7087da56d5cb0ddb57e9875..ef17d962b0d57c52f0b3cf23b13424de2f73315e 100644 --- a/src/main/java/de/b2tla/analysis/MachineContext.java +++ b/src/main/java/de/b2tla/analysis/MachineContext.java @@ -1,14 +1,18 @@ package de.b2tla.analysis; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import de.b2tla.exceptions.ScopeException; +import de.b2tla.ltl.LTLBPredicate; +import de.b2tla.ltl.LTLFormulaVisitor; import de.be4.classicalb.core.parser.Utils; import de.be4.classicalb.core.parser.analysis.DepthFirstAdapter; import de.be4.classicalb.core.parser.node.AAbstractMachineParseUnit; @@ -41,6 +45,7 @@ import de.be4.classicalb.core.parser.node.AOpSubstitution; import de.be4.classicalb.core.parser.node.AOperation; import de.be4.classicalb.core.parser.node.AOperationsMachineClause; import de.be4.classicalb.core.parser.node.APredicateDefinitionDefinition; +import de.be4.classicalb.core.parser.node.APredicateParseUnit; import de.be4.classicalb.core.parser.node.APrimedIdentifierExpression; import de.be4.classicalb.core.parser.node.APropertiesMachineClause; import de.be4.classicalb.core.parser.node.AQuantifiedIntersectionExpression; @@ -50,6 +55,7 @@ import de.be4.classicalb.core.parser.node.ARecordFieldExpression; import de.be4.classicalb.core.parser.node.ASeesMachineClause; import de.be4.classicalb.core.parser.node.ASetsContextClause; import de.be4.classicalb.core.parser.node.ASetsMachineClause; +import de.be4.classicalb.core.parser.node.AStringExpression; import de.be4.classicalb.core.parser.node.ASubstitutionDefinitionDefinition; import de.be4.classicalb.core.parser.node.AVariablesMachineClause; import de.be4.classicalb.core.parser.node.Node; @@ -69,6 +75,7 @@ public class MachineContext extends DepthFirstAdapter { private PMachineHeader header; private final Start start; private final Hashtable<String, MachineContext> machineContextsTable; + private ArrayList<LTLFormulaVisitor> ltlVisitors; // machine identifier private final LinkedHashMap<String, Node> setParameter; @@ -87,7 +94,7 @@ public class MachineContext extends DepthFirstAdapter { private AAbstractMachineParseUnit abstractMachineParseUnit; private AConstraintsMachineClause constraintMachineClause; private ASeesMachineClause seesMachineClause; - private ASetsContextClause setsMachineClause; // TODO + private ASetsContextClause setsMachineClause; private AConstantsMachineClause constantsMachineClause; private ADefinitionsMachineClause definitionMachineClause; private APropertiesMachineClause propertiesMachineClause; @@ -101,31 +108,39 @@ public class MachineContext extends DepthFirstAdapter { private final Hashtable<Node, Node> referencesTable; - public MachineContext(Start start, - Hashtable<String, MachineContext> machineContextsTable) { + // public MachineContext(Start start, + // Hashtable<String, MachineContext> machineContextsTable) { + // this.start = start; + // this.ltlVisitors = new ArrayList<LTLFormulaVisitor>(); + // this.referencesTable = new Hashtable<Node, Node>(); + // + // this.setParameter = new LinkedHashMap<String, Node>(); + // this.scalarParameter = new LinkedHashMap<String, Node>(); + // + // this.deferredSets = new LinkedHashMap<String, Node>(); + // this.enumeratedSets = new LinkedHashMap<String, Node>(); + // this.enumValues = new LinkedHashMap<String, Node>(); + // this.constants = new LinkedHashMap<String, Node>(); + // this.definitions = new LinkedHashMap<String, Node>(); + // this.variables = new LinkedHashMap<String, Node>(); + // this.operations = new LinkedHashMap<String, Node>(); + // this.seenMachines = new LinkedHashMap<String, AIdentifierExpression>(); + // + // this.machineContextsTable = machineContextsTable; + // + // start.apply(this); + // } + + public MachineContext(Start start, String ltlFormula) { this.start = start; this.referencesTable = new Hashtable<Node, Node>(); + this.ltlVisitors = new ArrayList<LTLFormulaVisitor>(); - this.setParameter = new LinkedHashMap<String, Node>(); - this.scalarParameter = new LinkedHashMap<String, Node>(); - - this.deferredSets = new LinkedHashMap<String, Node>(); - this.enumeratedSets = new LinkedHashMap<String, Node>(); - this.enumValues = new LinkedHashMap<String, Node>(); - this.constants = new LinkedHashMap<String, Node>(); - this.definitions = new LinkedHashMap<String, Node>(); - this.variables = new LinkedHashMap<String, Node>(); - this.operations = new LinkedHashMap<String, Node>(); - this.seenMachines = new LinkedHashMap<String, AIdentifierExpression>(); - - this.machineContextsTable = machineContextsTable; - - start.apply(this); - } - - public MachineContext(Start start) { - this.start = start; - this.referencesTable = new Hashtable<Node, Node>(); + LTLFormulaVisitor ltlVisitor = null; + if (null != ltlFormula) { + ltlVisitor = new LTLFormulaVisitor("ltl", ltlFormula, this); + this.ltlVisitors.add(ltlVisitor); + } this.setParameter = new LinkedHashMap<String, Node>(); this.scalarParameter = new LinkedHashMap<String, Node>(); @@ -141,6 +156,34 @@ public class MachineContext extends DepthFirstAdapter { this.machineContextsTable = new Hashtable<String, MachineContext>(); start.apply(this); + + checkLTLFormulas(); + } + + private void checkLTLFormulas() { + for (int i = 0; i < ltlVisitors.size(); i++) { + LTLFormulaVisitor visitor = ltlVisitors.get(i); + visitor.start(); + } + } + + public void checkLTLBPredicate(LTLBPredicate ltlbPredicate) { + contextTable = new ArrayList<LinkedHashMap<String, Node>>(); + contextTable.add(getDeferredSets()); + contextTable.add(getEnumeratedSets()); + contextTable.add(getEnumValues()); + contextTable.add(getConstants()); + contextTable.add(getVariables()); + contextTable.add(getDefinitions()); + + LinkedHashMap<String, Node> identifierHashTable = ltlbPredicate + .getIdentifierList(); + if (identifierHashTable.size() > 0) { + LinkedHashMap<String, Node> currentContext = new LinkedHashMap<String, Node>(); + currentContext.putAll(identifierHashTable); + contextTable.add(currentContext); + } + ltlbPredicate.getBFormula().apply(this); } private void exist(LinkedList<TIdentifierLiteral> list) { @@ -204,6 +247,12 @@ public class MachineContext extends DepthFirstAdapter { } } + @Override + public void caseAPredicateParseUnit(APredicateParseUnit node) { + + node.getPredicate().apply(this); + } + /** * Definitions */ @@ -211,16 +260,32 @@ public class MachineContext extends DepthFirstAdapter { @Override public void caseADefinitionsMachineClause(ADefinitionsMachineClause node) { definitionMachineClause = node; - List<PDefinition> copy = new ArrayList<PDefinition>( - node.getDefinitions()); + List<PDefinition> copy = node.getDefinitions(); /* * The definitions are not in a predefined order. In particular * definitions can depend on each other. First all definitions are added * to the definitions context table. Then all definitions are visited. */ + Collection<PDefinition> definitionsToRemove = new HashSet<PDefinition>(); + for (PDefinition e : copy) { if (e instanceof AExpressionDefinitionDefinition) { + AExpressionDefinitionDefinition def = (AExpressionDefinitionDefinition) e; + String name = def.getName().getText(); + if (name.startsWith("ASSERT_LTL")) { + try { + AStringExpression stringNode = (AStringExpression) def + .getRhs(); + LTLFormulaVisitor visitor = new LTLFormulaVisitor(name, + stringNode.getContent().getText(), this); + this.ltlVisitors.add(visitor); + } catch (ClassCastException castException) { + throw new ScopeException( + "Error: LTL formula is not in a string representation."); + } + definitionsToRemove.add(def); + } evalDefinitionName(((AExpressionDefinitionDefinition) e) .getName().getText().toString(), e); } else if (e instanceof APredicateDefinitionDefinition) { @@ -231,7 +296,12 @@ public class MachineContext extends DepthFirstAdapter { .getName().getText().toString(), e); } } - + /* + * At this point all ASSERT_LTL formulas of the definitions are removed. + * LTL formulas are stored in the Arraylist {@value #ltlVisitors}. + */ + copy.removeAll(definitionsToRemove); + this.contextTable = new ArrayList<LinkedHashMap<String, Node>>(); ArrayList<MachineContext> list = lookupExtendedMachines(); for (int i = 0; i < list.size(); i++) { @@ -250,7 +320,7 @@ public class MachineContext extends DepthFirstAdapter { } private void evalDefinitionName(String name, Node node) { - if (name.equals("ASSERT_LTL")) { + if (name.startsWith("ASSERT_LTL")) { return; } existString(name); @@ -646,8 +716,11 @@ public class MachineContext extends DepthFirstAdapter { if (e instanceof AFunctionExpression) { contextTable = varTable; ((AFunctionExpression) e).getIdentifier().apply(this); + + // full context table + contextTable = temp; for (Node n : ((AFunctionExpression) e).getParameters()) { - contextTable = temp; + n.apply(this); } } else { @@ -918,6 +991,10 @@ public class MachineContext extends DepthFirstAdapter { return referencesTable; } + public ArrayList<LTLFormulaVisitor> getLTLFormulas() { + return ltlVisitors; + } + /* * machine clauses getter */ diff --git a/src/main/java/de/b2tla/analysis/MachineDeclarationsCollector.java b/src/main/java/de/b2tla/analysis/MachineDeclarationsCollector.java index ee7f92d39c98b4e489d7f6297361d570184871a0..812568b139a05f82552e855b6a57a09ad8ea183b 100644 --- a/src/main/java/de/b2tla/analysis/MachineDeclarationsCollector.java +++ b/src/main/java/de/b2tla/analysis/MachineDeclarationsCollector.java @@ -1,3 +1,7 @@ + +/* + * currently not used + */ package de.b2tla.analysis; import java.util.ArrayList; diff --git a/src/main/java/de/b2tla/analysis/MissingVariablesFinder.java b/src/main/java/de/b2tla/analysis/MissingVariablesFinder.java deleted file mode 100644 index d9bb6cd1088fbb90071d579e1fb0d72bd1cbbc84..0000000000000000000000000000000000000000 --- a/src/main/java/de/b2tla/analysis/MissingVariablesFinder.java +++ /dev/null @@ -1,315 +0,0 @@ -package de.b2tla.analysis; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.List; - -import de.b2tla.exceptions.SubstitutionException; -import de.be4.classicalb.core.parser.analysis.DepthFirstAdapter; -import de.be4.classicalb.core.parser.node.AAnySubstitution; -import de.be4.classicalb.core.parser.node.AAssertionSubstitution; -import de.be4.classicalb.core.parser.node.AAssignSubstitution; -import de.be4.classicalb.core.parser.node.ABecomesSuchSubstitution; -import de.be4.classicalb.core.parser.node.ABlockSubstitution; -import de.be4.classicalb.core.parser.node.AChoiceOrSubstitution; -import de.be4.classicalb.core.parser.node.AChoiceSubstitution; -import de.be4.classicalb.core.parser.node.ADefinitionsMachineClause; -import de.be4.classicalb.core.parser.node.AIfSubstitution; -import de.be4.classicalb.core.parser.node.AInitialisationMachineClause; -import de.be4.classicalb.core.parser.node.ALetSubstitution; -import de.be4.classicalb.core.parser.node.AOperation; -import de.be4.classicalb.core.parser.node.AParallelSubstitution; -import de.be4.classicalb.core.parser.node.APreconditionSubstitution; -import de.be4.classicalb.core.parser.node.ASelectSubstitution; -import de.be4.classicalb.core.parser.node.ASelectWhenSubstitution; -import de.be4.classicalb.core.parser.node.ASkipSubstitution; -import de.be4.classicalb.core.parser.node.Node; -import de.be4.classicalb.core.parser.node.PExpression; -import de.be4.classicalb.core.parser.node.PSubstitution; - -/** - * This class is a tree walker which calculates all missing variables - * assignments for each node inside a operation body. Missing variables - * assignments correspond to unchanged variables in TLA+. B definitions or the - * initialisation are not visited by this class. - * - * @author Dominik Hansen <Dominik.Hansen at hhu.de> - * - */ - -class MissingVariablesFinder extends DepthFirstAdapter { - private final MachineContext machineContext; - private final Hashtable<Node, HashSet<Node>> assignedIdentifiersTable; - - // this table contains a set of all variables which must be assigned in the - // node or in the sub nodes of the node - private final Hashtable<Node, HashSet<Node>> expectedVariablesTable; - private final Hashtable<Node, HashSet<Node>> expectedOutputParametersTable; - - private final Hashtable<Node, HashSet<Node>> missingVariablesTable; - - private final Hashtable<Node, HashSet<Node>> missingVariablesNull; - - public Hashtable<Node, HashSet<Node>> getMissingVariablesTable() { - return missingVariablesTable; - } - - public Hashtable<Node, HashSet<Node>> getMissingVariablesNull() { - return missingVariablesNull; - } - - public MissingVariablesFinder(MachineContext c, - Hashtable<Node, HashSet<Node>> assignedVariablesTable) { - this.machineContext = c; - this.assignedIdentifiersTable = assignedVariablesTable; - - this.expectedVariablesTable = new Hashtable<Node, HashSet<Node>>(); - this.expectedOutputParametersTable = new Hashtable<Node, HashSet<Node>>(); - - this.missingVariablesTable = new Hashtable<Node, HashSet<Node>>(); - this.missingVariablesNull = new Hashtable<Node, HashSet<Node>>(); - - c.getTree().apply(this); - } - - @Override - public void caseAInitialisationMachineClause( - AInitialisationMachineClause node) { - } - - @Override - public void caseADefinitionsMachineClause(ADefinitionsMachineClause node) { - } - - @Override - public void caseAOperation(AOperation node) { - HashSet<Node> expectedOutputParameter = new HashSet<Node>(); - List<PExpression> returnValues = new ArrayList<PExpression>( - node.getReturnValues()); - for (PExpression e : returnValues) { - expectedOutputParameter.add(e); - } - - Node body = node.getOperationBody(); - expectedOutputParametersTable.put(body, expectedOutputParameter); - expectedVariablesTable.put(body, new HashSet<Node>(machineContext - .getVariables().values())); - - body.apply(this); - - // missingVariablesTable.put(node, missingVariablesTable.get(body)); - } - - private void check(Node node) { - HashSet<Node> found = assignedIdentifiersTable.get(node); - HashSet<Node> missingVariables = new HashSet<Node>( - expectedVariablesTable.get(node)); - missingVariables.removeAll(found); - missingVariablesTable.put(node, missingVariables); - - HashSet<Node> missingOutputParameter = new HashSet<Node>( - expectedOutputParametersTable.get(node)); - missingOutputParameter.removeAll(found); - if (missingOutputParameter.size() > 0) { - throw new SubstitutionException( - "To the following output parameters no values are assigned: " - + missingOutputParameter); - } - } - - @Override - public void caseAAssignSubstitution(AAssignSubstitution node) { - check(node); - } - - @Override - public void caseABecomesSuchSubstitution(ABecomesSuchSubstitution node) { - check(node); - } - - @Override - public void caseAParallelSubstitution(AParallelSubstitution node) { - check(node); - - List<PSubstitution> copy = new ArrayList<PSubstitution>( - node.getSubstitutions()); - for (PSubstitution e : copy) { - - expectedOutputParametersTable.put(e, new HashSet<Node>()); - expectedVariablesTable.put(e, new HashSet<Node>()); - e.apply(this); - } - } - - @Override - public void caseAAnySubstitution(AAnySubstitution node) { - check(node); - - expectedOutputParametersTable.put(node.getThen(), new HashSet<Node>()); - expectedVariablesTable.put(node.getThen(), new HashSet<Node>()); - node.getThen().apply(this); - } - - @Override - public void caseALetSubstitution(ALetSubstitution node) { - check(node); - - expectedOutputParametersTable.put(node.getSubstitution(), - new HashSet<Node>()); - expectedVariablesTable.put(node.getSubstitution(), new HashSet<Node>()); - node.getSubstitution().apply(this); - } - - @Override - public void caseAChoiceSubstitution(AChoiceSubstitution node) { - check(node); - - // Separating variables and output parameters - HashSet<Node> foundIdentifiers = assignedIdentifiersTable.get(node); - HashSet<Node> variables = new HashSet<Node>(foundIdentifiers); - variables.removeAll(expectedOutputParametersTable.get(node)); - - // System.out.println(parameters); - - List<PSubstitution> copy = new ArrayList<PSubstitution>( - node.getSubstitutions()); - for (PSubstitution e : copy) { - // each child of CHOICE must assign all variables and all output - // parameter - expectedOutputParametersTable.put(e, - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(e, variables); - e.apply(this); - } - } - - @Override - public void caseAChoiceOrSubstitution(AChoiceOrSubstitution node) { - Node sub = node.getSubstitution(); - expectedOutputParametersTable.put(sub, - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(sub, expectedVariablesTable.get(node)); - - sub.apply(this); - - missingVariablesTable.put(node, missingVariablesTable.get(sub)); - - } - - @Override - public void caseAIfSubstitution(AIfSubstitution node) { - check(node); - - // Separating variables and output parameters - HashSet<Node> foundIdentifiers = assignedIdentifiersTable.get(node); - HashSet<Node> foundVariables = new HashSet<Node>(foundIdentifiers); - foundVariables.removeAll(expectedOutputParametersTable.get(node)); - - expectedOutputParametersTable.put(node.getThen(), - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(node.getThen(), foundVariables); - node.getThen().apply(this); - - List<PSubstitution> copy = new ArrayList<PSubstitution>( - node.getElsifSubstitutions()); - for (PSubstitution e : copy) { - expectedOutputParametersTable.put(e, - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(e, foundVariables); - e.apply(this); - } - - if (node.getElse() != null) { - expectedOutputParametersTable.put(node.getElse(), - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(node.getElse(), foundVariables); - node.getElse().apply(this); - } else { - missingVariablesNull.put(node, - assignedIdentifiersTable.get(node.getThen())); - } - - } - - @Override - public void caseAPreconditionSubstitution(APreconditionSubstitution node) { - // check(node); - // - // // Separating variables and output parameters - // HashSet<Node> foundIdentifiers = assignedIdentifiersTable.get(node); - // System.out.println(foundIdentifiers); - // HashSet<Node> foundVariables = new HashSet<Node>(foundIdentifiers); - // foundVariables.removeAll(expectedOutputParametersTable.get(node)); - - expectedOutputParametersTable.put(node.getSubstitution(), - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(node.getSubstitution(), - expectedVariablesTable.get(node)); - node.getSubstitution().apply(this); - } - - @Override - public void caseAAssertionSubstitution(AAssertionSubstitution node) { - expectedOutputParametersTable.put(node.getSubstitution(), - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(node.getSubstitution(), - expectedVariablesTable.get(node)); - node.getSubstitution().apply(this); - } - - @Override - public void caseABlockSubstitution(ABlockSubstitution node) { - expectedOutputParametersTable.put(node.getSubstitution(), - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(node.getSubstitution(), - expectedVariablesTable.get(node)); - node.getSubstitution().apply(this); - } - - @Override - public void caseASelectSubstitution(ASelectSubstitution node) { - check(node); - // Separating variables and output parameters - HashSet<Node> foundIdentifiers = assignedIdentifiersTable.get(node); - HashSet<Node> variables = new HashSet<Node>(foundIdentifiers); - variables.removeAll(expectedOutputParametersTable.get(node)); - - expectedOutputParametersTable.put(node.getThen(), - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(node.getThen(), variables); - node.getThen().apply(this); - { - List<PSubstitution> copy = new ArrayList<PSubstitution>( - node.getWhenSubstitutions()); - for (PSubstitution e : copy) { - expectedOutputParametersTable.put(e, - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(e, variables); - e.apply(this); - } - } - - if (node.getElse() != null) { - expectedOutputParametersTable.put(node.getElse(), - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(node.getElse(), variables); - node.getElse().apply(this); - } - } - - @Override - public void caseASelectWhenSubstitution(ASelectWhenSubstitution node) { - check(node); - expectedOutputParametersTable.put(node.getSubstitution(), - expectedOutputParametersTable.get(node)); - expectedVariablesTable.put(node.getSubstitution(), - expectedVariablesTable.get(node)); - node.getSubstitution().apply(this); - } - - @Override - public void caseASkipSubstitution(ASkipSubstitution node) { - check(node); - } -} diff --git a/src/main/java/de/b2tla/analysis/TypeRestrictor.java b/src/main/java/de/b2tla/analysis/TypeRestrictor.java index 1e15f7d514ee07d8b801779cb7a77768e933d695..be2ec09bf54533107cfdef570ad12d2d8e6d1760 100644 --- a/src/main/java/de/b2tla/analysis/TypeRestrictor.java +++ b/src/main/java/de/b2tla/analysis/TypeRestrictor.java @@ -9,6 +9,8 @@ import de.b2tla.analysis.nodes.ElementOfNode; import de.b2tla.analysis.nodes.EqualsNode; import de.b2tla.analysis.nodes.NodeType; import de.b2tla.analysis.nodes.SubsetNode; +import de.b2tla.ltl.LTLBPredicate; +import de.b2tla.ltl.LTLFormulaVisitor; import de.be4.classicalb.core.parser.analysis.DepthFirstAdapter; import de.be4.classicalb.core.parser.node.AAnySubstitution; import de.be4.classicalb.core.parser.node.AComprehensionSetExpression; @@ -26,6 +28,7 @@ import de.be4.classicalb.core.parser.node.ALetSubstitution; import de.be4.classicalb.core.parser.node.AMemberPredicate; import de.be4.classicalb.core.parser.node.AOperation; import de.be4.classicalb.core.parser.node.APreconditionSubstitution; +import de.be4.classicalb.core.parser.node.APredicateParseUnit; import de.be4.classicalb.core.parser.node.APropertiesMachineClause; import de.be4.classicalb.core.parser.node.AQuantifiedIntersectionExpression; import de.be4.classicalb.core.parser.node.AQuantifiedUnionExpression; @@ -35,6 +38,8 @@ import de.be4.classicalb.core.parser.node.Node; import de.be4.classicalb.core.parser.node.PExpression; import de.be4.classicalb.core.parser.node.PSubstitution; import de.be4.classicalb.core.parser.node.Start; +import de.be4.ltl.core.parser.node.AExistsLtl; +import de.be4.ltl.core.parser.node.AForallLtl; public class TypeRestrictor extends DepthFirstAdapter { @@ -54,6 +59,31 @@ public class TypeRestrictor extends DepthFirstAdapter { start.apply(this); + checkLTLFormulas(); + } + + private void checkLTLFormulas() { + for (LTLFormulaVisitor visitor : machineContext.getLTLFormulas()) { + + for (de.be4.ltl.core.parser.node.Node ltlNode : visitor + .getUnparsedHashTable().keySet()) { + Node bNode = visitor.getBAst(ltlNode); + + if(ltlNode instanceof AExistsLtl){ + Node id = visitor.getLTLIdentifier(((AExistsLtl) ltlNode).getExistsIdentifier().getText()); + HashSet<Node> list = new HashSet<Node>(); + list.add(id); + analysePredicate(bNode, list); + }else if (ltlNode instanceof AForallLtl){ + Node id = visitor.getLTLIdentifier(((AForallLtl) ltlNode).getForallIdentifier().getText()); + HashSet<Node> list = new HashSet<Node>(); + list.add(id); + analysePredicate(bNode, list); + } + bNode.apply(this); + } + + } } public ArrayList<NodeType> getRestrictedTypesSet(Node node) { @@ -153,7 +183,15 @@ public class TypeRestrictor extends DepthFirstAdapter { analysePredicate(((AConjunctPredicate) n).getRight(), list); return; } - + + if(n instanceof Start){ + analysePredicate(((Start) n).getPParseUnit(), list); + } + + if(n instanceof APredicateParseUnit){ + analysePredicate(((APredicateParseUnit) n).getPredicate(), list); + return; + } } @Override @@ -236,9 +274,8 @@ public class TypeRestrictor extends DepthFirstAdapter { } analysePredicate(node.getPredicates(), list); } - - public void inAGeneralProductExpression(AGeneralProductExpression node) - { + + public void inAGeneralProductExpression(AGeneralProductExpression node) { HashSet<Node> list = new HashSet<Node>(); List<PExpression> copy = new ArrayList<PExpression>( node.getIdentifiers()); @@ -246,8 +283,7 @@ public class TypeRestrictor extends DepthFirstAdapter { list.add(e); } analysePredicate(node.getPredicates(), list); - } - + } private Hashtable<Node, HashSet<Node>> expectedIdentifieListTable = new Hashtable<Node, HashSet<Node>>(); diff --git a/src/main/java/de/b2tla/analysis/Typechecker.java b/src/main/java/de/b2tla/analysis/Typechecker.java index ff335453d6038630fffbb6cb1a6334e21e4eca8e..fc6eb771a3a17408d3ee49153656792e4f7237a1 100644 --- a/src/main/java/de/b2tla/analysis/Typechecker.java +++ b/src/main/java/de/b2tla/analysis/Typechecker.java @@ -1,6 +1,7 @@ package de.b2tla.analysis; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Hashtable; import java.util.LinkedHashMap; @@ -23,6 +24,8 @@ import de.b2tla.btypes.StructType; import de.b2tla.btypes.UntypedType; import de.b2tla.exceptions.TypeErrorException; import de.b2tla.exceptions.UnificationException; +import de.b2tla.ltl.LTLBPredicate; +import de.b2tla.ltl.LTLFormulaVisitor; import de.be4.classicalb.core.parser.Utils; import de.be4.classicalb.core.parser.analysis.DepthFirstAdapter; import de.be4.classicalb.core.parser.node.*; @@ -36,12 +39,12 @@ public class Typechecker extends DepthFirstAdapter implements ITypechecker { private final Hashtable<Node, BType> types; private final Hashtable<Node, Node> referenceTable; - private final MachineContext context; + private final MachineContext machineContext; public Typechecker(MachineContext machineContext, Hashtable<String, MachineContext> contextTable, Hashtable<String, Typechecker> typecheckerTable) { - this.context = machineContext; + this.machineContext = machineContext; this.types = new Hashtable<Node, BType>(); this.referenceTable = machineContext.getReferences(); } @@ -49,8 +52,32 @@ public class Typechecker extends DepthFirstAdapter implements ITypechecker { public Typechecker(MachineContext c) { this.types = new Hashtable<Node, BType>(); this.referenceTable = c.getReferences(); - this.context = c; + this.machineContext = c; c.getTree().apply(this); + + checkLTLFormulas(); + } + + private void checkLTLFormulas() { + ArrayList<LTLFormulaVisitor> visitors = machineContext.getLTLFormulas(); + for (int i = 0; i < visitors.size(); i++) { + LTLFormulaVisitor visitor = visitors.get(i); + Collection<AIdentifierExpression> parameter = visitor.getParameter(); + for (AIdentifierExpression param : parameter) { + setType(param, new UntypedType()); + } + for (int j = 0; j < visitor.getBPredicates().size(); j++) { + LTLBPredicate ltlBPredicate = visitor.getBPredicates().get(j); + ltlBPredicate.getBFormula().apply(this); + } + } + + } + + @Override + public void caseAPredicateParseUnit(APredicateParseUnit node) { + setType(node.getPredicate(), BoolType.getInstance()); + node.getPredicate().apply(this); } public Hashtable<Node, BType> getTypes() { @@ -58,7 +85,7 @@ public class Typechecker extends DepthFirstAdapter implements ITypechecker { } public MachineContext getContext() { - return context; + return machineContext; } public void setType(Node node, BType t) { @@ -266,7 +293,8 @@ public class Typechecker extends DepthFirstAdapter implements ITypechecker { setType(node.getPredicates(), BoolType.getInstance()); node.getPredicates().apply(this); } - LinkedHashMap<String, Node> parameter = context.getScalarParameter(); + LinkedHashMap<String, Node> parameter = machineContext + .getScalarParameter(); for (String c : parameter.keySet()) { Node n = parameter.get(c); if (getType(n).isUntyped()) { @@ -282,7 +310,7 @@ public class Typechecker extends DepthFirstAdapter implements ITypechecker { setType(node.getPredicates(), BoolType.getInstance()); node.getPredicates().apply(this); } - LinkedHashMap<String, Node> constants = context.getConstants(); + LinkedHashMap<String, Node> constants = machineContext.getConstants(); for (String c : constants.keySet()) { Node n = constants.get(c); if (getType(n).isUntyped()) { @@ -296,7 +324,7 @@ public class Typechecker extends DepthFirstAdapter implements ITypechecker { public void caseAInvariantMachineClause(AInvariantMachineClause node) { setType(node.getPredicates(), BoolType.getInstance()); node.getPredicates().apply(this); - LinkedHashMap<String, Node> variables = context.getVariables(); + LinkedHashMap<String, Node> variables = machineContext.getVariables(); for (String c : variables.keySet()) { Node n = variables.get(c); if (getType(n).isUntyped()) { diff --git a/src/main/java/de/b2tla/analysis/UnchangedVariablesFinder.java b/src/main/java/de/b2tla/analysis/UnchangedVariablesFinder.java index c4416bbc2c0c2bc61f206efc12f88894beeedad2..863a18bcb950de5ff9c8de91e33f56e66ebd8a50 100644 --- a/src/main/java/de/b2tla/analysis/UnchangedVariablesFinder.java +++ b/src/main/java/de/b2tla/analysis/UnchangedVariablesFinder.java @@ -1,38 +1,316 @@ package de.b2tla.analysis; +import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; +import java.util.List; - +import de.b2tla.exceptions.SubstitutionException; +import de.be4.classicalb.core.parser.analysis.DepthFirstAdapter; +import de.be4.classicalb.core.parser.node.AAnySubstitution; +import de.be4.classicalb.core.parser.node.AAssertionSubstitution; +import de.be4.classicalb.core.parser.node.AAssignSubstitution; +import de.be4.classicalb.core.parser.node.ABecomesSuchSubstitution; +import de.be4.classicalb.core.parser.node.ABlockSubstitution; +import de.be4.classicalb.core.parser.node.AChoiceOrSubstitution; +import de.be4.classicalb.core.parser.node.AChoiceSubstitution; +import de.be4.classicalb.core.parser.node.ADefinitionsMachineClause; +import de.be4.classicalb.core.parser.node.AIfSubstitution; +import de.be4.classicalb.core.parser.node.AInitialisationMachineClause; +import de.be4.classicalb.core.parser.node.ALetSubstitution; +import de.be4.classicalb.core.parser.node.AOperation; +import de.be4.classicalb.core.parser.node.AParallelSubstitution; +import de.be4.classicalb.core.parser.node.APreconditionSubstitution; +import de.be4.classicalb.core.parser.node.ASelectSubstitution; +import de.be4.classicalb.core.parser.node.ASelectWhenSubstitution; +import de.be4.classicalb.core.parser.node.ASkipSubstitution; import de.be4.classicalb.core.parser.node.Node; +import de.be4.classicalb.core.parser.node.PExpression; +import de.be4.classicalb.core.parser.node.PSubstitution; /** + * This class is a tree walker which calculates all missing variables + * assignments for each node inside a operation body. Missing variables + * assignments correspond to unchanged variables in TLA+. B definitions or the + * initialisation are not visited by this class. * * @author Dominik Hansen <Dominik.Hansen at hhu.de> * */ -public class UnchangedVariablesFinder { + +public class UnchangedVariablesFinder extends DepthFirstAdapter { + private final MachineContext machineContext; + private final Hashtable<Node, HashSet<Node>> assignedIdentifiersTable; + + // this table contains a set of all variables which must be assigned in the + // node or in the sub nodes of the node + private final Hashtable<Node, HashSet<Node>> expectedVariablesTable; + private final Hashtable<Node, HashSet<Node>> expectedOutputParametersTable; + private final Hashtable<Node, HashSet<Node>> unchangedVariablesTable; + private final Hashtable<Node, HashSet<Node>> unchangedVariablesNull; - - public Hashtable<Node, HashSet<Node>> getUnchangedVariablesTable() { - return unchangedVariablesTable; + + public HashSet<Node> getUnchangedVariables(Node node){ + return unchangedVariablesTable.get(node); } - public Hashtable<Node, HashSet<Node>> getUnchangedVariablesNull() { - return unchangedVariablesNull; + public HashSet<Node> getUnchangedVariablesNull(Node node) { + return unchangedVariablesNull.get(node); } public UnchangedVariablesFinder(MachineContext c) { -// Start start = c.getTree(); + this.machineContext = c; AssignedVariablesFinder aVF = new AssignedVariablesFinder(c); - //start.apply(aVF); - // assignedVariablesTable = aVF.getAssignedVariablesTable(); - MissingVariablesFinder mVF = new MissingVariablesFinder(c, - aVF.getAssignedVariablesTable()); - //start.apply(mVF); - this.unchangedVariablesTable = mVF.getMissingVariablesTable(); - this.unchangedVariablesNull = mVF.getMissingVariablesNull(); - } -} \ No newline at end of file + this.assignedIdentifiersTable = aVF.getAssignedVariablesTable(); + + this.expectedVariablesTable = new Hashtable<Node, HashSet<Node>>(); + this.expectedOutputParametersTable = new Hashtable<Node, HashSet<Node>>(); + + this.unchangedVariablesTable = new Hashtable<Node, HashSet<Node>>(); + this.unchangedVariablesNull = new Hashtable<Node, HashSet<Node>>(); + + c.getTree().apply(this); + } + + @Override + public void caseAInitialisationMachineClause( + AInitialisationMachineClause node) { + } + + @Override + public void caseADefinitionsMachineClause(ADefinitionsMachineClause node) { + } + + @Override + public void caseAOperation(AOperation node) { + HashSet<Node> expectedOutputParameter = new HashSet<Node>(); + List<PExpression> returnValues = new ArrayList<PExpression>( + node.getReturnValues()); + for (PExpression e : returnValues) { + expectedOutputParameter.add(e); + } + + Node body = node.getOperationBody(); + expectedOutputParametersTable.put(body, expectedOutputParameter); + expectedVariablesTable.put(body, new HashSet<Node>(machineContext + .getVariables().values())); + + body.apply(this); + + // missingVariablesTable.put(node, missingVariablesTable.get(body)); + } + + private void check(Node node) { + HashSet<Node> found = assignedIdentifiersTable.get(node); + HashSet<Node> missingVariables = new HashSet<Node>( + expectedVariablesTable.get(node)); + missingVariables.removeAll(found); + unchangedVariablesTable.put(node, missingVariables); + + HashSet<Node> missingOutputParameter = new HashSet<Node>( + expectedOutputParametersTable.get(node)); + missingOutputParameter.removeAll(found); + if (missingOutputParameter.size() > 0) { + throw new SubstitutionException( + "To the following output parameters no values are assigned: " + + missingOutputParameter); + } + } + + @Override + public void caseAAssignSubstitution(AAssignSubstitution node) { + check(node); + } + + @Override + public void caseABecomesSuchSubstitution(ABecomesSuchSubstitution node) { + check(node); + } + + @Override + public void caseAParallelSubstitution(AParallelSubstitution node) { + check(node); + + List<PSubstitution> copy = new ArrayList<PSubstitution>( + node.getSubstitutions()); + for (PSubstitution e : copy) { + + expectedOutputParametersTable.put(e, new HashSet<Node>()); + expectedVariablesTable.put(e, new HashSet<Node>()); + e.apply(this); + } + } + + @Override + public void caseAAnySubstitution(AAnySubstitution node) { + check(node); + + expectedOutputParametersTable.put(node.getThen(), new HashSet<Node>()); + expectedVariablesTable.put(node.getThen(), new HashSet<Node>()); + node.getThen().apply(this); + } + + @Override + public void caseALetSubstitution(ALetSubstitution node) { + check(node); + + expectedOutputParametersTable.put(node.getSubstitution(), + new HashSet<Node>()); + expectedVariablesTable.put(node.getSubstitution(), new HashSet<Node>()); + node.getSubstitution().apply(this); + } + + @Override + public void caseAChoiceSubstitution(AChoiceSubstitution node) { + check(node); + + // Separating variables and output parameters + HashSet<Node> foundIdentifiers = assignedIdentifiersTable.get(node); + HashSet<Node> variables = new HashSet<Node>(foundIdentifiers); + variables.removeAll(expectedOutputParametersTable.get(node)); + + // System.out.println(parameters); + + List<PSubstitution> copy = new ArrayList<PSubstitution>( + node.getSubstitutions()); + for (PSubstitution e : copy) { + // each child of CHOICE must assign all variables and all output + // parameter + expectedOutputParametersTable.put(e, + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(e, variables); + e.apply(this); + } + } + + @Override + public void caseAChoiceOrSubstitution(AChoiceOrSubstitution node) { + Node sub = node.getSubstitution(); + expectedOutputParametersTable.put(sub, + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(sub, expectedVariablesTable.get(node)); + + sub.apply(this); + + unchangedVariablesTable.put(node, unchangedVariablesTable.get(sub)); + + } + + @Override + public void caseAIfSubstitution(AIfSubstitution node) { + check(node); + + // Separating variables and output parameters + HashSet<Node> foundIdentifiers = assignedIdentifiersTable.get(node); + HashSet<Node> foundVariables = new HashSet<Node>(foundIdentifiers); + foundVariables.removeAll(expectedOutputParametersTable.get(node)); + + expectedOutputParametersTable.put(node.getThen(), + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(node.getThen(), foundVariables); + node.getThen().apply(this); + + List<PSubstitution> copy = new ArrayList<PSubstitution>( + node.getElsifSubstitutions()); + for (PSubstitution e : copy) { + expectedOutputParametersTable.put(e, + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(e, foundVariables); + e.apply(this); + } + + if (node.getElse() != null) { + expectedOutputParametersTable.put(node.getElse(), + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(node.getElse(), foundVariables); + node.getElse().apply(this); + } else { + unchangedVariablesNull.put(node, + assignedIdentifiersTable.get(node.getThen())); + } + + } + + @Override + public void caseAPreconditionSubstitution(APreconditionSubstitution node) { + // check(node); + // + // // Separating variables and output parameters + // HashSet<Node> foundIdentifiers = assignedIdentifiersTable.get(node); + // System.out.println(foundIdentifiers); + // HashSet<Node> foundVariables = new HashSet<Node>(foundIdentifiers); + // foundVariables.removeAll(expectedOutputParametersTable.get(node)); + + expectedOutputParametersTable.put(node.getSubstitution(), + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(node.getSubstitution(), + expectedVariablesTable.get(node)); + node.getSubstitution().apply(this); + } + + @Override + public void caseAAssertionSubstitution(AAssertionSubstitution node) { + expectedOutputParametersTable.put(node.getSubstitution(), + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(node.getSubstitution(), + expectedVariablesTable.get(node)); + node.getSubstitution().apply(this); + } + + @Override + public void caseABlockSubstitution(ABlockSubstitution node) { + expectedOutputParametersTable.put(node.getSubstitution(), + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(node.getSubstitution(), + expectedVariablesTable.get(node)); + node.getSubstitution().apply(this); + } + + @Override + public void caseASelectSubstitution(ASelectSubstitution node) { + check(node); + // Separating variables and output parameters + HashSet<Node> foundIdentifiers = assignedIdentifiersTable.get(node); + HashSet<Node> variables = new HashSet<Node>(foundIdentifiers); + variables.removeAll(expectedOutputParametersTable.get(node)); + + expectedOutputParametersTable.put(node.getThen(), + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(node.getThen(), variables); + node.getThen().apply(this); + { + List<PSubstitution> copy = new ArrayList<PSubstitution>( + node.getWhenSubstitutions()); + for (PSubstitution e : copy) { + expectedOutputParametersTable.put(e, + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(e, variables); + e.apply(this); + } + } + + if (node.getElse() != null) { + expectedOutputParametersTable.put(node.getElse(), + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(node.getElse(), variables); + node.getElse().apply(this); + } + } + + @Override + public void caseASelectWhenSubstitution(ASelectWhenSubstitution node) { + check(node); + expectedOutputParametersTable.put(node.getSubstitution(), + expectedOutputParametersTable.get(node)); + expectedVariablesTable.put(node.getSubstitution(), + expectedVariablesTable.get(node)); + node.getSubstitution().apply(this); + } + + @Override + public void caseASkipSubstitution(ASkipSubstitution node) { + check(node); + } +} diff --git a/src/main/java/de/b2tla/exceptions/LTLParseException.java b/src/main/java/de/b2tla/exceptions/LTLParseException.java new file mode 100644 index 0000000000000000000000000000000000000000..74c017d00ae0a23895bf22ef8502af75c30e560e --- /dev/null +++ b/src/main/java/de/b2tla/exceptions/LTLParseException.java @@ -0,0 +1,15 @@ +package de.b2tla.exceptions; + +@SuppressWarnings("serial") +public class LTLParseException extends B2tlaException{ + + public LTLParseException(String e) { + super(e); + } + + @Override + public String getError() { + return "LTLParseError"; + } + +} diff --git a/src/main/java/de/b2tla/ltl/LTLBPredicate.java b/src/main/java/de/b2tla/ltl/LTLBPredicate.java new file mode 100644 index 0000000000000000000000000000000000000000..15e36dbea88c0c544f5ca290664f491dbc4a81b0 --- /dev/null +++ b/src/main/java/de/b2tla/ltl/LTLBPredicate.java @@ -0,0 +1,30 @@ +package de.b2tla.ltl; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +public class LTLBPredicate { + LinkedHashMap<String, de.be4.classicalb.core.parser.node.Node> identifierHashTable; + + de.be4.classicalb.core.parser.node.Node predicate; + + public LTLBPredicate(LinkedHashMap<String, de.be4.classicalb.core.parser.node.Node> identifierHashTable, de.be4.classicalb.core.parser.node.Node predicate){ + this.identifierHashTable = identifierHashTable; + this.predicate = predicate; + } + + public LTLBPredicate( + ArrayList<de.be4.classicalb.core.parser.node.Node> arrayList, + de.be4.classicalb.core.parser.node.Start start) { + // TODO Auto-generated constructor stub + } + + public de.be4.classicalb.core.parser.node.Node getBFormula(){ + return predicate; + } + + public LinkedHashMap<String, de.be4.classicalb.core.parser.node.Node> getIdentifierList(){ + return identifierHashTable; + } + +} diff --git a/src/main/java/de/b2tla/ltl/LTLFormulaPrinter.java b/src/main/java/de/b2tla/ltl/LTLFormulaPrinter.java new file mode 100644 index 0000000000000000000000000000000000000000..b26de46fde09bbe9cd3cbd2b27258c26cadf6a43 --- /dev/null +++ b/src/main/java/de/b2tla/ltl/LTLFormulaPrinter.java @@ -0,0 +1,137 @@ +package de.b2tla.ltl; + +import de.b2tla.prettyprint.TLAPrinter; +import de.be4.classicalb.core.parser.node.AIdentifierExpression; +import de.be4.classicalb.core.parser.node.Node; +import de.be4.ltl.core.parser.analysis.DepthFirstAdapter; +import de.be4.ltl.core.parser.node.AAndLtl; +import de.be4.ltl.core.parser.node.AEnabledLtl; +import de.be4.ltl.core.parser.node.AExistsLtl; +import de.be4.ltl.core.parser.node.AFalseLtl; +import de.be4.ltl.core.parser.node.AFinallyLtl; +import de.be4.ltl.core.parser.node.AForallLtl; +import de.be4.ltl.core.parser.node.AGloballyLtl; +import de.be4.ltl.core.parser.node.AImpliesLtl; +import de.be4.ltl.core.parser.node.ANotLtl; +import de.be4.ltl.core.parser.node.AOrLtl; +import de.be4.ltl.core.parser.node.AStrongFairLtl; +import de.be4.ltl.core.parser.node.ATrueLtl; +import de.be4.ltl.core.parser.node.AUnparsedLtl; +import de.be4.ltl.core.parser.node.AWeakFairLtl; + +public class LTLFormulaPrinter extends DepthFirstAdapter { + + private final LTLFormulaVisitor ltlFormulaVisitor; + private final TLAPrinter tlaPrinter; + + public LTLFormulaPrinter(TLAPrinter tlaPrinter, + LTLFormulaVisitor ltlFormulaVisitor) { + this.ltlFormulaVisitor = ltlFormulaVisitor; + this.tlaPrinter = tlaPrinter; + + ltlFormulaVisitor.getLTLFormulaStart().apply(this); + } + + @Override + public void caseAGloballyLtl(AGloballyLtl node) { + tlaPrinter.moduleStringAppend("[]("); + node.getLtl().apply(this); + tlaPrinter.moduleStringAppend(")"); + } + + @Override + public void caseAFinallyLtl(AFinallyLtl node) { + tlaPrinter.moduleStringAppend("<>("); + node.getLtl().apply(this); + tlaPrinter.moduleStringAppend(")"); + } + + @Override + public void caseATrueLtl(ATrueLtl node) { + tlaPrinter.moduleStringAppend("TRUE"); + } + + @Override + public void caseAFalseLtl(AFalseLtl node) { + tlaPrinter.moduleStringAppend("FALSE"); + } + + @Override + public void caseAUnparsedLtl(AUnparsedLtl node) { + ltlFormulaVisitor.getBAst(node).apply(tlaPrinter); + } + + @Override + public void caseAAndLtl(AAndLtl node) { + node.getLeft().apply(this); + tlaPrinter.moduleStringAppend(" /\\ "); + node.getRight().apply(this); + } + + @Override + public void caseAOrLtl(AOrLtl node) { + node.getLeft().apply(this); + tlaPrinter.moduleStringAppend(" \\/ "); + node.getRight().apply(this); + } + + @Override + public void caseANotLtl(ANotLtl node) { + tlaPrinter.moduleStringAppend("\\neg("); + node.getLtl().apply(this); + tlaPrinter.moduleStringAppend(")"); + } + + @Override + public void caseAImpliesLtl(AImpliesLtl node) { + node.getLeft().apply(this); + tlaPrinter.moduleStringAppend(" => "); + node.getRight().apply(this); + } + + @Override + public void caseAEnabledLtl(AEnabledLtl node) { + tlaPrinter.moduleStringAppend("ENABLED("); + tlaPrinter.moduleStringAppend(node.getOperation().getText()); + tlaPrinter.moduleStringAppend(")"); + } + + @Override + public void caseAWeakFairLtl(AWeakFairLtl node) { + tlaPrinter.printWeakFairness(node.getOperation().getText()); + } + + @Override + public void caseAStrongFairLtl(AStrongFairLtl node) { + tlaPrinter.printStrongFairness(node.getOperation().getText()); + } + + @Override + public void caseAExistsLtl(AExistsLtl node) { + tlaPrinter.moduleStringAppend("\\E "); + tlaPrinter.moduleStringAppend(node.getExistsIdentifier().getText()); + tlaPrinter.moduleStringAppend(" \\in "); + Node id = this.ltlFormulaVisitor.getLTLIdentifier(node + .getExistsIdentifier().getText()); + tlaPrinter.printTypeOfIdentifier((AIdentifierExpression) id); + tlaPrinter.moduleStringAppend(": "); + ltlFormulaVisitor.getBAst(node).apply(tlaPrinter); + tlaPrinter.moduleStringAppend(" /\\ "); + node.getLtl().apply(this); + } + + @Override + public void caseAForallLtl(AForallLtl node) { + tlaPrinter.moduleStringAppend("\\A "); + tlaPrinter.moduleStringAppend(node.getForallIdentifier().getText()); + tlaPrinter.moduleStringAppend(" \\in "); + Node id = this.ltlFormulaVisitor.getLTLIdentifier(node + .getForallIdentifier().getText()); + tlaPrinter.printTypeOfIdentifier((AIdentifierExpression) id); + tlaPrinter.moduleStringAppend(": "); + ltlFormulaVisitor.getBAst(node).apply(tlaPrinter); + tlaPrinter.moduleStringAppend(" /\\ "); + node.getLtl().apply(this); + } + +} diff --git a/src/main/java/de/b2tla/ltl/LTLFormulaVisitor.java b/src/main/java/de/b2tla/ltl/LTLFormulaVisitor.java new file mode 100644 index 0000000000000000000000000000000000000000..2b7fc3d809115664e1dac13aa106794a1368e395 --- /dev/null +++ b/src/main/java/de/b2tla/ltl/LTLFormulaVisitor.java @@ -0,0 +1,270 @@ +package de.b2tla.ltl; + +import java.io.IOException; +import java.io.PushbackReader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.List; + +import de.b2tla.analysis.MachineContext; +import de.b2tla.exceptions.LTLParseException; +import de.b2tla.exceptions.ScopeException; +import de.b2tla.prettyprint.TLAPrinter; +import de.be4.classicalb.core.parser.BParser; +import de.be4.classicalb.core.parser.exceptions.BException; +import de.be4.classicalb.core.parser.node.AIdentifierExpression; +import de.be4.classicalb.core.parser.node.Node; +import de.be4.classicalb.core.parser.node.TIdentifierLiteral; +import de.be4.ltl.core.parser.analysis.DepthFirstAdapter; +import de.be4.ltl.core.parser.internal.LtlLexer; +import de.be4.ltl.core.parser.lexer.Lexer; +import de.be4.ltl.core.parser.lexer.LexerException; +import de.be4.ltl.core.parser.node.AEnabledLtl; +import de.be4.ltl.core.parser.node.AExistsLtl; +import de.be4.ltl.core.parser.node.AForallLtl; +import de.be4.ltl.core.parser.node.AHistoricallyLtl; +import de.be4.ltl.core.parser.node.AOnceLtl; +import de.be4.ltl.core.parser.node.AReleaseLtl; +import de.be4.ltl.core.parser.node.ASinceLtl; +import de.be4.ltl.core.parser.node.AStrongFairLtl; +import de.be4.ltl.core.parser.node.ATriggerLtl; +import de.be4.ltl.core.parser.node.AUnparsedLtl; +import de.be4.ltl.core.parser.node.AUntilLtl; +import de.be4.ltl.core.parser.node.AWeakFairLtl; +import de.be4.ltl.core.parser.node.AWeakuntilLtl; +import de.be4.ltl.core.parser.node.AYesterdayLtl; +import de.be4.ltl.core.parser.node.PLtl; +import de.be4.ltl.core.parser.node.Start; +import de.be4.ltl.core.parser.parser.Parser; +import de.be4.ltl.core.parser.parser.ParserException; + +public class LTLFormulaVisitor extends DepthFirstAdapter { + + private final String name; + private final Start ltlFormulaStart; + private final MachineContext machineContext; + + private final LinkedHashMap<de.be4.ltl.core.parser.node.Node, de.be4.classicalb.core.parser.node.Node> ltlNodeToBNodeTable; + private final ArrayList<LTLBPredicate> bPredicates; + private final Hashtable<String, AIdentifierExpression> ltlIdentifierTable; + + private ArrayList<Hashtable<String, AIdentifierExpression>> contextTable; + + public ArrayList<LTLBPredicate> getBPredicates() { + return bPredicates; + } + + public Collection<AIdentifierExpression> getParameter() { + return ltlIdentifierTable.values(); + } + + public AIdentifierExpression getLTLIdentifier(String identifier) { + return ltlIdentifierTable.get(identifier); + } + + public LinkedHashMap<de.be4.ltl.core.parser.node.Node, de.be4.classicalb.core.parser.node.Node> getUnparsedHashTable() { + return ltlNodeToBNodeTable; + } + + public de.be4.classicalb.core.parser.node.Node getBAst( + de.be4.ltl.core.parser.node.Node unparsedLtl) { + return ltlNodeToBNodeTable.get(unparsedLtl); + } + + public String getName() { + return this.name; + } + + public LTLFormulaVisitor(String name, String ltlFormula, + MachineContext machineContext) { + this.name = name; + this.ltlFormulaStart = parse(ltlFormula); + this.machineContext = machineContext; + + this.bPredicates = new ArrayList<LTLBPredicate>(); + this.ltlNodeToBNodeTable = new LinkedHashMap<de.be4.ltl.core.parser.node.Node, de.be4.classicalb.core.parser.node.Node>(); + this.ltlIdentifierTable = new Hashtable<String, AIdentifierExpression>(); + + this.contextTable = new ArrayList<Hashtable<String, AIdentifierExpression>>(); + } + + public void start() { + ltlFormulaStart.apply(this); + } + + public Start getLTLFormulaStart() { + return ltlFormulaStart; + } + + public void printLTLFormula(TLAPrinter tlaPrinter) { + LTLFormulaPrinter ltlFormulaPrinter = new LTLFormulaPrinter(tlaPrinter, + this); + } + + public static Start parse(String ltlFormula) { + StringReader reader = new StringReader(ltlFormula); + PushbackReader r = new PushbackReader(reader); + Lexer l = new LtlLexer(r); + Parser p = new Parser(l); + Start ast = null; + try { + ast = p.parse(); + + } catch (Exception e) { + e.printStackTrace(); + throw new LTLParseException(e.getMessage()); + } + return ast; + } + + @Override + public void caseAUnparsedLtl(AUnparsedLtl node) { + de.be4.classicalb.core.parser.node.Start start = parseBPredicate(node + .getPredicate().getText()); + + ltlNodeToBNodeTable.put(node, start); + + LTLBPredicate ltlBPredicate = new LTLBPredicate( + new LinkedHashMap<String, Node>(), start); + this.bPredicates.add(ltlBPredicate); + + machineContext.checkLTLBPredicate(ltlBPredicate); + } + + private de.be4.classicalb.core.parser.node.Start parseBPredicate(String text) { + String bPredicate = "#PREDICATE " + text; + BParser parser = new BParser("Testing"); + de.be4.classicalb.core.parser.node.Start start = null; + try { + start = parser.parse(bPredicate, false); + } catch (BException e) { + e.printStackTrace(); + } + + return start; + } + + @Override + public void caseAExistsLtl(AExistsLtl node) { + handleQuantification(node, node.getExistsIdentifier().getText(), node + .getPredicate().getText(), node.getLtl()); + + } + + @Override + public void caseAForallLtl(AForallLtl node) { + handleQuantification(node, node.getForallIdentifier().getText(), node + .getPredicate().getText(), node.getLtl()); + } + + private void handleQuantification(de.be4.ltl.core.parser.node.Node node, + String parameterName, String bPredicateString, PLtl ltl) { + // create an identifier (b ast node) for the parameter of the + // quantification + List<TIdentifierLiteral> list = new ArrayList<TIdentifierLiteral>(); + list.add(new TIdentifierLiteral(parameterName)); + AIdentifierExpression parameterNode = new AIdentifierExpression(list); + + // add the created identifier to the current context + Hashtable<String, AIdentifierExpression> currentContext = new Hashtable<String, AIdentifierExpression>(); + currentContext.put(parameterName, parameterNode); + this.contextTable.add(currentContext); + + // collection the all parameters in + ltlIdentifierTable.put(parameterName, parameterNode); + + // parse the b predicate and create a reference to the b ast node + de.be4.classicalb.core.parser.node.Start start = parseBPredicate(bPredicateString); + ltlNodeToBNodeTable.put(node, start); + + // collect all identifiers which can be used in the bPredicate and + // verify the bPredicate + LTLBPredicate ltlBPredicate = new LTLBPredicate(getUnifiedContext(), + start); + this.bPredicates.add(ltlBPredicate); + machineContext.checkLTLBPredicate(ltlBPredicate); + + // remaining LTL formula + ltl.apply(this); + + // remove currentContext from contextTable + contextTable.remove(contextTable.size() - 1); + + } + + private LinkedHashMap<String, Node> getUnifiedContext() { + LinkedHashMap<String, Node> context = new LinkedHashMap<String, Node>(); + for (int i = 0; i < contextTable.size(); i++) { + context.putAll(contextTable.get(i)); + } + return context; + } + + @Override + public void caseAEnabledLtl(AEnabledLtl node) { + String operationName = node.getOperation().getText(); + if (!machineContext.getOperations().containsKey(operationName)) { + throw new ScopeException("Unkown operation " + operationName + "."); + } + } + + @Override + public void caseAWeakFairLtl(AWeakFairLtl node) { + String operationName = node.getOperation().getText(); + if (!machineContext.getOperations().containsKey(operationName)) { + throw new ScopeException("Unkown operation " + operationName + "."); + } + } + + @Override + public void caseAStrongFairLtl(AStrongFairLtl node) { + String operationName = node.getOperation().getText(); + if (!machineContext.getOperations().containsKey(operationName)) { + throw new ScopeException("Unkown operation " + operationName + "."); + } + } + + public void inAUntilLtl(AUntilLtl node) { + throw new ScopeException( + "The 'until' operator is not supported by TLC."); + } + + public void inAWeakuntilLtl(AWeakuntilLtl node) { + throw new ScopeException( + "The 'weak until' operator is not supported by TLC."); + } + + public void inAReleaseLtl(AReleaseLtl node) { + throw new ScopeException( + "The 'release' operator is not supported by TLC."); + } + + public void inASinceLtl(ASinceLtl node) { + throw new ScopeException( + "The 'since' operator is not supported by TLC."); + } + + public void inATriggerLtl(ATriggerLtl node) { + throw new ScopeException( + "The 'trigger' operator is not supported by TLC."); + } + + public void inAHistoricallyLtl(AHistoricallyLtl node) { + throw new ScopeException( + "The 'history' operator is not supported by TLC."); + } + + public void inAOnceLtl(AOnceLtl node) { + throw new ScopeException("The 'once' operator is not supported by TLC."); + } + + public void inAYesterdayLtl(AYesterdayLtl node) { + throw new ScopeException( + "The 'yesterday' operator is not supported by TLC."); + } + +} diff --git a/src/main/java/de/b2tla/prettyprint/TLAPrinter.java b/src/main/java/de/b2tla/prettyprint/TLAPrinter.java index a8656b065521d9145fa96d174a40ebce436de508..6a9df8697271ddb886d2775611ce8e2c4a5ba7d7 100644 --- a/src/main/java/de/b2tla/prettyprint/TLAPrinter.java +++ b/src/main/java/de/b2tla/prettyprint/TLAPrinter.java @@ -8,12 +8,12 @@ import java.util.List; import de.b2tla.Globals; import de.b2tla.analysis.MachineContext; +import de.b2tla.analysis.UnchangedVariablesFinder; import de.b2tla.analysis.PrecedenceCollector; import de.b2tla.analysis.PrimedNodesMarker; import de.b2tla.analysis.Renamer; import de.b2tla.analysis.TypeRestrictor; import de.b2tla.analysis.Typechecker; -import de.b2tla.analysis.UnchangedVariablesFinder; import de.b2tla.analysis.UsedStandardModules; import de.b2tla.analysis.nodes.EqualsNode; import de.b2tla.analysis.nodes.NodeType; @@ -22,6 +22,7 @@ import de.b2tla.btypes.BType; import de.b2tla.btypes.FunctionType; import de.b2tla.btypes.IntegerType; import de.b2tla.btypes.SetType; +import de.b2tla.ltl.LTLFormulaVisitor; import de.b2tla.tla.ConfigFile; import de.b2tla.tla.TLADefinition; import de.b2tla.tla.TLAModule; @@ -46,7 +47,7 @@ public class TLAPrinter extends DepthFirstAdapter { private MachineContext machineContext; private Typechecker typechecker; - private UnchangedVariablesFinder unchangedVariablesFinder; + private UnchangedVariablesFinder missingVariableFinder; private PrecedenceCollector precedenceCollector; private UsedStandardModules usedStandardModules; private TypeRestrictor typeRestrictor; @@ -64,7 +65,7 @@ public class TLAPrinter extends DepthFirstAdapter { Renamer renamer) { this.typechecker = typechecker; this.machineContext = machineContext; - this.unchangedVariablesFinder = unchangedVariablesFinder; + this.missingVariableFinder = unchangedVariablesFinder; this.precedenceCollector = precedenceCollector; this.usedStandardModules = usedStandardModules; this.typeRestrictor = typeRestrictor; @@ -75,9 +76,6 @@ public class TLAPrinter extends DepthFirstAdapter { this.tlaModuleString = new StringBuilder(); this.configFileString = new StringBuilder(); - - // Start start = machineContext.getTree(); - // start.apply(this); } public void start() { @@ -91,18 +89,93 @@ public class TLAPrinter extends DepthFirstAdapter { printAssertions(); printInit(); printOperations(); + printSpecFormula(); + printLTLFormulas(); tlaModuleString.append("===="); printConfig(); } - private void printConfig() { - if (this.configFile.isInit()) { - this.configFileString.append("INIT Init\n"); + private void printSpecFormula() { + + if (this.configFile.isSpec()) { + tlaModuleString.append("vars == "); + printVarsAsTuple(); + tlaModuleString.append("\n"); + + tlaModuleString.append("VWF == "); + printWeakFairness("Next"); + tlaModuleString.append("\n"); + tlaModuleString.append("Spec == Init /\\ [][Next]_vars /\\ VWF\n"); } - if (this.configFile.isInit()) { - this.configFileString.append("NEXT Next\n"); + + } + + public void printStrongFairness(String s) { + tlaModuleString + .append(String + .format("([]<><<%s>>_vars \\/ <>[]~ENABLED(%s) \\/ []<> ENABLED(%s /\\ ", + s, s, s)); + printVarsStuttering(); + tlaModuleString.append("))"); + + } + + public void printWeakFairness(String s) { + tlaModuleString + .append(String + .format("([]<><<%s>>_vars \\/ []<>~ENABLED(%s) \\/ []<> ENABLED(%s /\\ ", + s, s, s)); + printVarsStuttering(); + tlaModuleString.append("))"); + + } + + private void printVarsStuttering() { + ArrayList<Node> vars = this.tlaModule.getVariables(); + for (int i = 0; i < vars.size(); i++) { + vars.get(i).apply(this); + tlaModuleString.append("' = "); + vars.get(i).apply(this); + if (i < vars.size() - 1) + tlaModuleString.append(","); + } + } + + private void printVarsAsTuple() { + ArrayList<Node> vars = this.tlaModule.getVariables(); + if (vars.size() == 0) + return; + tlaModuleString.append("<<"); + for (int i = 0; i < vars.size(); i++) { + vars.get(i).apply(this); + if (i < vars.size() - 1) + tlaModuleString.append(","); + } + tlaModuleString.append(">>"); + } + + private void printLTLFormulas() { + ArrayList<LTLFormulaVisitor> visitors = machineContext.getLTLFormulas(); + for (int i = 0; i < visitors.size(); i++) { + LTLFormulaVisitor visitor = visitors.get(i); + tlaModuleString.append(visitor.getName() + " == "); + visitor.printLTLFormula(this); + tlaModuleString.append("\n"); + } + } + + private void printConfig() { + if (this.configFile.isSpec()) { + this.configFileString.append("SPECIFICATION Spec\n"); + } else { + if (this.configFile.isInit()) { + this.configFileString.append("INIT Init\n"); + } + if (this.configFile.isInit()) { + this.configFileString.append("NEXT Next\n"); + } } if (configFile.isInvariant()) { this.configFileString.append("INVARIANT Invariant\n"); @@ -120,8 +193,14 @@ public class TLAPrinter extends DepthFirstAdapter { } - // CONSTANTS + for (int i = 0; i < machineContext.getLTLFormulas().size(); i++) { + LTLFormulaVisitor ltlVisitor = machineContext.getLTLFormulas().get( + i); + this.configFileString.append("PROPERTIES " + ltlVisitor.getName() + + "\n"); + } + // CONSTANTS ArrayList<ConfigFileAssignment> assignments = configFile .getAssignments(); if (assignments.size() != 0) { @@ -132,6 +211,10 @@ public class TLAPrinter extends DepthFirstAdapter { } } + public void moduleStringAppend(String str) { + this.tlaModuleString.append(str); + } + private void printHeader() { tlaModuleString.append("---- MODULE "); tlaModuleString.append(this.tlaModule.getModuleName()); @@ -365,28 +448,15 @@ public class TLAPrinter extends DepthFirstAdapter { @Override public void caseAEnumeratedSetSet(AEnumeratedSetSet node) { - inAEnumeratedSetSet(node); - { - List<TIdentifierLiteral> copy = new ArrayList<TIdentifierLiteral>( - node.getIdentifier()); - - String setName = Utils.getIdentifierAsString(copy); - - tlaModuleString.append(renamer.getNameOfRef(node) + " == {"); - } - { - List<PExpression> copy = new ArrayList<PExpression>( - node.getElements()); - for (int i = 0; i < copy.size(); i++) { - copy.get(i).apply(this); - if (i < copy.size() - 1) { - tlaModuleString.append(", "); - } + List<PExpression> copy = new ArrayList<PExpression>(node.getElements()); + tlaModuleString.append(renamer.getNameOfRef(node) + " == {"); + for (int i = 0; i < copy.size(); i++) { + copy.get(i).apply(this); + if (i < copy.size() - 1) { + tlaModuleString.append(", "); } } tlaModuleString.append("}\n"); - outAEnumeratedSetSet(node); - } @Override @@ -517,8 +587,8 @@ public class TLAPrinter extends DepthFirstAdapter { } public void printUnchangedVariables(Node node, boolean printAnd) { - HashSet<Node> unchangedVariablesSet = unchangedVariablesFinder - .getUnchangedVariablesTable().get(node); + HashSet<Node> unchangedVariablesSet = missingVariableFinder + .getUnchangedVariables(node); if (null != unchangedVariablesSet) { ArrayList<Node> unchangedVariables = new ArrayList<Node>( unchangedVariablesSet); @@ -589,8 +659,8 @@ public class TLAPrinter extends DepthFirstAdapter { } public void printUnchangedVariablesNull(Node node, boolean printAnd) { - HashSet<Node> unchangedVariablesSet = unchangedVariablesFinder - .getUnchangedVariablesNull().get(node); + HashSet<Node> unchangedVariablesSet = missingVariableFinder + .getUnchangedVariablesNull(node); if (null != unchangedVariablesSet) { ArrayList<Node> unchangedVariables = new ArrayList<Node>( unchangedVariablesSet); @@ -742,9 +812,10 @@ public class TLAPrinter extends DepthFirstAdapter { public void caseAOperation(AOperation node) { String name = renamer.getNameOfRef(node); tlaModuleString.append(name); - - List<PExpression> output = new ArrayList<PExpression>( - node.getReturnValues()); + + // TODO handle output parameter of a operation + // List<PExpression> output = new ArrayList<PExpression>( + // node.getReturnValues()); List<PExpression> params = new ArrayList<PExpression>( node.getParameters()); List<PExpression> newList = new ArrayList<PExpression>(); @@ -950,7 +1021,7 @@ public class TLAPrinter extends DepthFirstAdapter { */ inAExistsPredicate(node); tlaModuleString.append("\\E "); - + List<PExpression> copy = new ArrayList<PExpression>( node.getIdentifiers()); for (int i = 0; i < copy.size(); i++) { @@ -1329,7 +1400,7 @@ public class TLAPrinter extends DepthFirstAdapter { } } - private void printTypeOfIdentifier(PExpression e) { + public void printTypeOfIdentifier(PExpression e) { // NodeType n = typeRestrictor.getRestrictedTypes().get(e); ArrayList<NodeType> list = typeRestrictor.getRestrictedTypesSet(e); if (list != null) { diff --git a/src/main/java/de/b2tla/tla/ConfigFile.java b/src/main/java/de/b2tla/tla/ConfigFile.java index d17f29f923d95363d63dc934c10745c045ee300e..7766721e561429bf00776f55125bce29becbccff 100644 --- a/src/main/java/de/b2tla/tla/ConfigFile.java +++ b/src/main/java/de/b2tla/tla/ConfigFile.java @@ -9,6 +9,7 @@ public class ConfigFile { private final ArrayList<ConfigFileAssignment> assignments; private boolean invariant; + private boolean spec; private boolean init; private boolean next; private int assertionsSize; @@ -25,6 +26,10 @@ public class ConfigFile { return assignments; } + public boolean isSpec(){ + return spec; + } + public boolean isInvariant() { return invariant; @@ -68,6 +73,9 @@ public class ConfigFile { return assertionsSize; } + public void setSpec(){ + this.spec = true; + } public void setGoal(){ this.goal = true; diff --git a/src/main/java/de/b2tla/tla/Generator.java b/src/main/java/de/b2tla/tla/Generator.java index e9bc25998da21ff92493af8693363e34e44edebf..bbc6a7f22b26a5b050c9dd4f552d75f60d1df1db 100644 --- a/src/main/java/de/b2tla/tla/Generator.java +++ b/src/main/java/de/b2tla/tla/Generator.java @@ -64,6 +64,15 @@ public class Generator extends DepthFirstAdapter { evalOperations(); evalGoal(); machineContext.getTree().apply(this); + + evalSpec(); + } + + private void evalSpec() { + if (this.configFile.isInit() && this.configFile.isNext() + && machineContext.getLTLFormulas().size() > 0) { + this.configFile.setSpec(); + } } private void evalGoal() { @@ -175,7 +184,8 @@ public class Generator extends DepthFirstAdapter { } private void evalDefinitions() { - ADefinitionsMachineClause node = machineContext.getDefinitionMachineClause(); + ADefinitionsMachineClause node = machineContext + .getDefinitionMachineClause(); if (node != null) { for (PDefinition def : node.getDefinitions()) { this.tlaModule.addToAllDefinitions(def); @@ -212,7 +222,6 @@ public class Generator extends DepthFirstAdapter { (PExpression) value.clone()); machineContext.getReferences().put(exprDef, con); - this.tlaModule.addToAllDefinitions(exprDef); } diff --git a/src/main/java/de/b2tla/tlc/TLCOutput.java b/src/main/java/de/b2tla/tlc/TLCOutput.java index 56c3f39828c56217e704ef65a22275b4602bd7d5..fbd5c476017a80c316d7f70754249e8bc82b04a6 100644 --- a/src/main/java/de/b2tla/tlc/TLCOutput.java +++ b/src/main/java/de/b2tla/tlc/TLCOutput.java @@ -22,7 +22,7 @@ public class TLCOutput { String parseError; public static enum ERROR { - Deadlock, Goal, Invariant, ParseError, NoError, Assertion, PropertiesError, EnumerateError, TLCError + Deadlock, Goal, Invariant, ParseError, NoError, Assertion, PropertiesError, EnumerateError, TLCError, TemporalProperty } public long getRunningTime() { @@ -31,8 +31,10 @@ public class TLCOutput { } public String getError() { - if(error == ERROR.Invariant){ + if (error == ERROR.Invariant) { return "Invariant Violation"; + }else if(error == ERROR.TemporalProperty){ + return "Temporal Property Violation"; } return error.toString(); } @@ -41,8 +43,8 @@ public class TLCOutput { parseTrace(); return trace; } - - public String getModuleName(){ + + public String getModuleName() { return moduleName; } @@ -121,13 +123,16 @@ public class TLCOutput { for (int i = 0; i < states.size(); i++) { String m = states.get(i); // System.out.println(m); - String location = m.substring(0, m.indexOf("\n")); + // String location = m.substring(0, m.indexOf("\n")); // String operationName = moduleMatcher.getName(location); - + int pos = m.indexOf("\n"); + if (pos == -1) + break; // e.g. 'State 10: Stuttering' String predicate = m.substring(m.indexOf("\n") + 1); - //String res = TLCExpressionParser.parseLine(predicate); - //TODO OUTPUT - String res = TLCExpressionParser.parseLine(predicate, tlcOutputInfo.getTypes()); + // String res = TLCExpressionParser.parseLine(predicate); + // TODO OUTPUT + String res = TLCExpressionParser.parseLine(predicate, + tlcOutputInfo.getTypes()); trace.append(res); trace.append("\n"); } @@ -159,10 +164,14 @@ public class TLCOutput { } } else if (res[1].equals("Assumption")) { return ERROR.PropertiesError; + } else if (res[1].equals("Temporal")) { + return ERROR.TemporalProperty; } else if (m.equals("Error: TLC threw an unexpected exception.")) { return ERROR.ParseError; } else if (m.startsWith("Error: The behavior up to")) { return null; + } else if (m.startsWith("Error: The following behavior constitutes a counter-example:")) { + return null; } System.out.println(m); return ERROR.TLCError; diff --git a/src/test/java/de/b2tla/analysis/ScopeTest.java b/src/test/java/de/b2tla/analysis/ScopeTest.java index b526447b0135bbae08bf91d4a402eb96a2e72b99..5f3840976d1c9de0661d9c28b34ac391cd2b6000 100644 --- a/src/test/java/de/b2tla/analysis/ScopeTest.java +++ b/src/test/java/de/b2tla/analysis/ScopeTest.java @@ -101,7 +101,7 @@ public class ScopeTest { checkMachine(machine); } - @Ignore //TODO + @Ignore //TODO machineContext line 657 @Test(expected = ScopeException.class) public void testConstantSubstitution() throws Exception { String machine = "MACHINE test\n" + "CONSTANTS x \n" diff --git a/src/test/java/de/b2tla/ltl/LtlFormulaTest.java b/src/test/java/de/b2tla/ltl/LtlFormulaTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ab3d9cebfe5b21ba5c3b619d8217a90cbe7ccc37 --- /dev/null +++ b/src/test/java/de/b2tla/ltl/LtlFormulaTest.java @@ -0,0 +1,325 @@ +package de.b2tla.ltl; + + +import static de.b2tla.util.TestUtil.compareLTL; +import static de.b2tla.util.TestUtil.compareEqualsConfig; + +import org.junit.Ignore; +import org.junit.Test; + +import de.b2tla.exceptions.ScopeException; +import de.b2tla.exceptions.TypeErrorException; + + +public class LtlFormulaTest { + + + + @Test (expected = ScopeException.class) + public void testScopeException() throws Exception { + String machine = "MACHINE test\n" + + "VARIABLES x\n" + + "INVARIANT x = 1\n" + + "INITIALISATION x := 1\n" + + "OPERATIONS foo = x := 1" + + "END"; + compareLTL("", machine, "G{y = 1}"); + } + + @Test (expected = TypeErrorException.class) + public void testTypeError() throws Exception { + String machine = "MACHINE test\n" + + "VARIABLES x\n" + + "INVARIANT x = 1\n" + + "INITIALISATION x := 1\n" + + "OPERATIONS foo = x := 1" + + "END"; + compareLTL("", machine, "G{x = FALSE}"); + } + + @Test (expected = ScopeException.class) + public void testUnkownOperation() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "e(foo)"); + } + + @Ignore + @Test + public void testGobally() throws Exception { + String machine = "MACHINE test\n" + + "VARIABLES x\n" + + "INVARIANT x = 1\n" + + "INITIALISATION x := 1\n" + + "OPERATIONS foo = x := 1" + + "END"; + + String expected = "---- MODULE test ----\n" + + "VARIABLES x\n" + + "Invariant == x = 1\n" + + "Init == x = 1\n" + + "foo == x' = 1\n\n" + + "Next == \\/ foo\n" + + "Spec == Init /\\ [][Next]_<<x>> /\\ WF_<<x>>(Next)\n" + + "ltl == [](x = 1)\n" + + "===="; + compareLTL(expected, machine, "G{x = 1}"); + } + + @Ignore + @Test + public void testFinally() throws Exception { + String machine = "MACHINE test\n" + + "VARIABLES x\n" + + "INVARIANT x = 1\n" + + "INITIALISATION x := 1\n" + + "OPERATIONS foo = x := 1" + + "END"; + + String expected = "---- MODULE test ----\n" + + "VARIABLES x\n" + + "Invariant == x = 1\n" + + "Init == x = 1\n" + + "foo == x' = 1\n\n" + + "Next == \\/ foo\n" + + "Spec == Init /\\ [][Next]_<<x>> /\\ WF_<<x>>(Next)\n" + + "ltl == <>(x = 1)\n" + + "===="; + compareLTL(expected, machine, "F{x = 1}"); + } + + @Test + public void testTrue() throws Exception { + String machine = "MACHINE test\n" + + "END"; + + String expected = "---- MODULE test ----\n" + + "ltl == TRUE\n" + + "===="; + compareLTL(expected, machine, "true"); + } + + @Test + public void testFalse() throws Exception { + String machine = "MACHINE test\n" + + "END"; + + String expected = "---- MODULE test ----\n" + + "ltl == FALSE\n" + + "===="; + compareLTL(expected, machine, "false"); + } + + @Test + public void testImplication() throws Exception { + String machine = "MACHINE test\n" + + "END"; + + String expected = "---- MODULE test ----\n" + + "ltl == FALSE => TRUE\n" + + "===="; + compareLTL(expected, machine, "false => true"); + } + + @Test + public void testAnd() throws Exception { + String machine = "MACHINE test\n" + + "END"; + + String expected = "---- MODULE test ----\n" + + "ltl == TRUE /\\ FALSE\n" + + "===="; + compareLTL(expected, machine, "true & false"); + } + + @Test + public void testOr() throws Exception { + String machine = "MACHINE test\n" + + "END"; + + String expected = "---- MODULE test ----\n" + + "ltl == TRUE \\/ FALSE\n" + + "===="; + compareLTL(expected, machine, "true or false"); + } + + @Test + public void testNegation() throws Exception { + String machine = "MACHINE test\n" + + "END"; + + String expected = "---- MODULE test ----\n" + + "ltl == \\neg(TRUE)\n" + + "===="; + compareLTL(expected, machine, "not(true)"); + } + + @Test (expected = ScopeException.class) + public void testUntil() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "true U false"); + } + + @Test (expected = ScopeException.class) + public void testWeakUntil() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "true W false"); + } + + @Test (expected = ScopeException.class) + public void testRelease() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "true R false"); + } + + @Test (expected = ScopeException.class) + public void testHistory() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "H false"); + } + + @Test (expected = ScopeException.class) + public void testOnce() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "O false"); + } + + @Test (expected = ScopeException.class) + public void testYesterday() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "Y false"); + } + + @Test (expected = ScopeException.class) + public void testSince() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "true S false"); + } + + @Test (expected = ScopeException.class) + public void testTrigger() throws Exception { + String machine = "MACHINE test\n" + + "END"; + compareLTL("", machine, "true T false"); + } + + @Ignore + @Test + public void testEnabled() throws Exception { + String machine = "MACHINE test\n" + + "VARIABLES x\n" + + "INVARIANT x = 1\n" + + "INITIALISATION x := 1\n" + + "OPERATIONS foo = x := 1" + + "END"; + + String expected = "---- MODULE test ----\n" + + "VARIABLES x\n" + + "Invariant == x = 1\n" + + "Init == x = 1\n" + + "foo == x' = 1\n\n" + + "Next == \\/ foo\n" + + "Spec == Init /\\ [][Next]_<<x>> /\\ WF_<<x>>(Next)\n" + + "ltl == ENABLED(foo)\n" + + "===="; + compareLTL(expected, machine, "e(foo)"); + } + + @Ignore + @Test + public void testWeakFairness() throws Exception { + String machine = "MACHINE test\n" + + "VARIABLES x\n" + + "INVARIANT x = 1\n" + + "INITIALISATION x := 1\n" + + "OPERATIONS foo = x := 1" + + "END"; + + String expected = "---- MODULE test ----\n" + + "VARIABLES x\n" + + "Invariant == x = 1\n" + + "Init == x = 1\n" + + "foo == x' = 1\n\n" + + "Next == \\/ foo\n" + + "Spec == Init /\\ [][Next]_<<x>> /\\ WF_<<x>>(Next)\n" + + "ltl == ENABLED(foo)\n" + + "===="; + compareLTL(expected, machine, "WF(foo)"); + } + + @Ignore + @Test + public void testStrongFairness() throws Exception { + String machine = "MACHINE test\n" + + "VARIABLES x\n" + + "INVARIANT x = 1\n" + + "INITIALISATION x := 1\n" + + "OPERATIONS foo = x := 1" + + "END"; + + String expected = "---- MODULE test ----\n" + + "VARIABLES x\n" + + "Invariant == x = 1\n" + + "Init == x = 1\n" + + "foo == x' = 1\n\n" + + "Next == \\/ foo\n" + + "Spec == Init /\\ [][Next]_<<x>> /\\ WF_<<x>>(Next)\n" + + "ltl == ENABLED(foo)\n" + + "===="; + compareLTL(expected, machine, "SF(foo)"); + } + + + @Test + public void testExistentialQuantification() throws Exception { + String machine = "MACHINE test\n" + + "END"; + String expected = "---- MODULE test ----\n" + + "ltl == \\E p \\in {1}: p = 1 /\\ TRUE\n" + + "===="; + compareLTL(expected, machine, "#p.({p=1} & true)"); + } + + @Test + public void testForallQuantification() throws Exception { + String machine = "MACHINE test\n" + + "END"; + String expected = "---- MODULE test ----\n" + + "ltl == \\A p \\in {1}: p = 1 /\\ TRUE\n" + + "===="; + compareLTL(expected, machine, "!p.({p=1} => true)"); + } + + @Ignore + @Test + public void testLTLFormulaInDefinitions() throws Exception { + final String machine = "MACHINE test\n" + + "DEFINITIONS ASSERT_LTL == \"false\" \n" + + "VARIABLES x\n" + + "INVARIANT x = 1\n" + + "INITIALISATION x := 1\n" + + "OPERATIONS foo = x := 1" + + "END"; + + final String expected = "---- MODULE test ----\n" + + "VARIABLES x\n" + + "Invariant == x = 1\n" + + "Init == x = 1\n" + + "foo == x' = 1\n\n" + + "Next == \\/ foo\n" + + "Spec == Init /\\ [][Next]_<<x>> /\\ WF_<<x>>(Next)\n" + + "ASSERT_LTL == FALSE\n" + + "===="; + final String config = "SPECIFICATION Spec\nINVARIANT Invariant\nPROPERTIES ASSERT_LTL\n"; + + compareEqualsConfig(expected, config, machine); + } + +} diff --git a/src/test/java/de/b2tla/prettyprint/EnumeratedSetsTest.java b/src/test/java/de/b2tla/prettyprint/EnumeratedSetsTest.java index d1959f034799664a35be4397ec5e45435f733178..8e4df28d60475147c0bd12e0d45c007f44c9c89a 100644 --- a/src/test/java/de/b2tla/prettyprint/EnumeratedSetsTest.java +++ b/src/test/java/de/b2tla/prettyprint/EnumeratedSetsTest.java @@ -6,13 +6,13 @@ import org.junit.Test; public class EnumeratedSetsTest { @Test - public void testSetComprehensionEquals() throws Exception { - // TODO verify config + public void testTwoEnumeratedSets() throws Exception { String machine = "MACHINE test\n" + "SETS set = {a,b,c}; set2 = {d}\n" + "END"; String expected = "---- MODULE test ----\n" + "CONSTANTS a, b, c, d\n" + "set == {a, b, c}\n" + "set2 == {d}\n" + "===="; - compareEquals(expected, machine); + final String config = "CONSTANTS\na = a\nb = b\nc = c\nd = d\n"; + compareEqualsConfig(expected, config, machine); } } diff --git a/src/test/java/de/b2tla/tlc/integration/LTLTest.java b/src/test/java/de/b2tla/tlc/integration/LTLTest.java new file mode 100644 index 0000000000000000000000000000000000000000..94f347b82726996abe4f78c6530e64e8b924afa3 --- /dev/null +++ b/src/test/java/de/b2tla/tlc/integration/LTLTest.java @@ -0,0 +1,19 @@ +package de.b2tla.tlc.integration; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.b2tla.B2TLA; +import de.b2tla.tlc.TLCOutput; + +public class LTLTest { + + @Test + public void testRelations() throws Exception { + String[] a = new String[] { ".\\src\\test\\resources\\ltl\\CounterLTL.mch"}; + B2TLA.main(a); + //assertEquals(TLCOutput.ERROR.TemporalProperty, B2TLA.test(a)); + } + +} diff --git a/src/test/java/de/b2tla/typechecking/TestTypechecker.java b/src/test/java/de/b2tla/typechecking/TestTypechecker.java index 6dd249f360efbc68368217d3462c3595a7508f8e..663db02b45fc4abb309cf663ff54696fbc693b34 100644 --- a/src/test/java/de/b2tla/typechecking/TestTypechecker.java +++ b/src/test/java/de/b2tla/typechecking/TestTypechecker.java @@ -26,7 +26,7 @@ public class TestTypechecker { final Ast2String ast2String2 = new Ast2String(); start.apply(ast2String2); System.out.println(ast2String2.toString()); - MachineContext c = new MachineContext(start); + MachineContext c = new MachineContext(start, null); Typechecker t = new Typechecker(c); for (String name : c.getSetParamter().keySet()) { diff --git a/src/test/java/de/b2tla/util/TestUtil.java b/src/test/java/de/b2tla/util/TestUtil.java index 860d73bfbf5c927d92a980847524649da4723937..6d67b2107114040aba5c94fb68f6c7f317ed4ce0 100644 --- a/src/test/java/de/b2tla/util/TestUtil.java +++ b/src/test/java/de/b2tla/util/TestUtil.java @@ -44,6 +44,18 @@ public class TestUtil { // assertEquals(sb2.toString(), sb1.toString()); } + + public static void compareLTL(String expectedModule, String machine, String ltlFormula) + throws Exception { + B2TlaTranslator b2tlaTranslator = new B2TlaTranslator(machine, ltlFormula); + b2tlaTranslator.translate(); + System.out.println(b2tlaTranslator.getModuleString()); + String name = b2tlaTranslator.getMachineName(); + de.tla2b.translation.Tla2BTranslator + .translateString(name, b2tlaTranslator.getModuleString(), null); + assertEquals(expectedModule, b2tlaTranslator.getModuleString()); + } + public static void checkMachine(String machine) throws Exception { B2TlaTranslator b2tlaTranslator = new B2TlaTranslator(machine); @@ -61,6 +73,23 @@ public class TestUtil { System.out.println(ast2String2.toString()); } + public static void compareEqualsConfig(String expectedModule, + String expectedConfig, String machine) throws Exception { + B2TlaTranslator b2tlaTranslator = new B2TlaTranslator(machine); + b2tlaTranslator.translate(); + // print(b2tlaTranslator.getStart()); + System.out.println(b2tlaTranslator.getModuleString()); + System.out.println(b2tlaTranslator.getConfigString()); + + String name = b2tlaTranslator.getMachineName(); + de.tla2b.translation.Tla2BTranslator + .translateString(name, b2tlaTranslator.getModuleString(), + b2tlaTranslator.getConfigString()); + + assertEquals(expectedModule, b2tlaTranslator.getModuleString()); + assertEquals(expectedConfig, b2tlaTranslator.getConfigString()); + } + public static void compareConfig(String expectedModule, String expectedConfig, String machine) throws Exception { B2TlaTranslator b2tlaTranslator = new B2TlaTranslator(machine); diff --git a/src/test/java/standard/CompoundScopeTest.java b/src/test/java/standard/CompoundScopeTest.java index f1ea58bd7928fd75e30fca03190bb6d6ea6a09df..b9c3993de94eb447580c54b9963161a0422f4a51 100644 --- a/src/test/java/standard/CompoundScopeTest.java +++ b/src/test/java/standard/CompoundScopeTest.java @@ -56,8 +56,8 @@ public class CompoundScopeTest { start.apply(ast2String2); System.out.println(ast2String2.toString()); - MachineContext c = new MachineContext(start, machineContextsTable); - machineContextsTable.put(name, c); + //MachineContext c = new MachineContext(start, machineContextsTable); + //machineContextsTable.put(name, c); } diff --git a/src/test/resources/ltl/CounterLTL.mch b/src/test/resources/ltl/CounterLTL.mch new file mode 100644 index 0000000000000000000000000000000000000000..ce5fae9d50d5b15a073d10b1f7b56828c1f989ee --- /dev/null +++ b/src/test/resources/ltl/CounterLTL.mch @@ -0,0 +1,11 @@ +MACHINE CounterLTL +DEFINITIONS +ASSERT_LTL_1 == "F {x = 10}" +VARIABLES x +INVARIANT + x : 1..10 +INITIALISATION x:=1 +OPERATIONS + Inc = PRE x < 10 THEN x:= x + 1 END; + Reset = PRE x = 10 THEN x := 1 END +END \ No newline at end of file