diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..e597ae06e90f0eb78e2320b8893222784e2a47d6 --- /dev/null +++ b/build.gradle @@ -0,0 +1,75 @@ +apply plugin: 'java' +apply plugin: 'eclipse' +apply plugin: 'maven' +apply plugin: 'jacoco' +apply plugin: 'findbugs' + +project.version = '1.0.0-SNAPSHOT' +project.group = 'de.prob' + +sourceCompatibility = 1.5 + +repositories { + mavenCentral() + maven { + url "http://cobra.cs.uni-duesseldorf.de/artifactory/repo" + } +} + +configurations { // configuration that holds jars to copy into lib + releaseJars +} + +def parser_version = '2.4.22-SNAPSHOT' + +dependencies { + //compile (group: 'com.microsoft', name: 'tla2tools', version: '1.4.6') + compile (group: 'de.tla', name: 'tlatools', version: '1.0.0-SNAPSHOT') + + compile (group: 'de.prob', name: 'prologlib', version: parser_version) + compile (group: 'de.prob', name: 'parserbase', version: parser_version) + compile (group: 'de.prob', name: 'bparser', version: parser_version) + compile (group: 'de.prob', name: 'ltlparser', version: parser_version) + + //compile(group: 'de.prob', name: 'de.prob.core.kernel', version: '2.0.0-milestone-13-SNAPSHOT') + + + + testCompile (group: 'junit', name: 'junit', version: '4.7') + + releaseJars (group: 'de.tla', name: 'tlatools', version: '1.0.0-SNAPSHOT') + 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) +} + +jacoco { + toolVersion = "0.6.2.201302030002" + reportsDir = file("$buildDir/customJacocoReportDir") +} + +jacocoTestReport { + reports { + xml.enabled false + csv.enabled false + html.destination "${buildDir}/jacocoHtml" + } +} + +tasks.withType(FindBugs) { + reports { + xml.enabled = false + html.enabled = true + } +} + +findbugs { + ignoreFailures = true +} + + +jar { from sourceSets.main.allJava } +jar { + from configurations.releaseJars.collect { it.isDirectory() ? it : zipTree(it) } +} \ No newline at end of file diff --git a/src/main/java/de/tla2b/analysis/BOperation.java b/src/main/java/de/tla2b/analysis/BOperation.java new file mode 100644 index 0000000000000000000000000000000000000000..7e99a87e6c885df66a873d8d8f73a0e811a6126b --- /dev/null +++ b/src/main/java/de/tla2b/analysis/BOperation.java @@ -0,0 +1,145 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.analysis; + + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import de.tla2b.global.BBuiltInOPs; +import de.tla2b.global.TranslationGlobals; + +import tla2sany.semantic.ASTConstants; +import tla2sany.semantic.ExprNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.LetInNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.SemanticNode; +import tla2sany.semantic.SubstInNode; +import tlc2.tool.BuiltInOPs; +import tlc2.tool.ToolGlobals; + +public class BOperation implements ASTConstants, ToolGlobals, TranslationGlobals { + private String name; + private ExprNode node; + private ArrayList<OpApplNode> existQuans; + private ArrayList<String> opParams; + private ArrayList<String> unchangedVariables; + + public BOperation(String name, ExprNode n, + ArrayList<OpApplNode> existQuans) { + this.name = name; + this.node = n; + this.existQuans = existQuans; + evalParams(); + findUnchangedVariables(); + } + + private void evalParams() { + opParams = new ArrayList<String>(); + for (int i = 0; i < existQuans.size(); i++) { + OpApplNode n = existQuans.get(i); + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + for (int k = 0; k < params.length; k++) { + for (int j = 0; j < params[k].length; j++) { + opParams.add(params[k][j].getName().toString()); + } + } + } + } + + public String getName() { + return name; + } + + public ExprNode getNode() { + return node; + } + + public ArrayList<OpApplNode> getExistQuans() { + return new ArrayList<OpApplNode>(existQuans); + } + + public ArrayList<String> getOpParams() { + return opParams; + } + + public ArrayList<String> getUnchangedVariables(){ + return unchangedVariables; + } + + private void findUnchangedVariables() { + unchangedVariables = new ArrayList<String>(); + findUnchangedVaribalesInSemanticNode(node); + } + + + /** + * @param node2 + */ + private void findUnchangedVaribalesInSemanticNode(SemanticNode node) { + switch (node.getKind()) { + case OpApplKind: { + findUnchangedVariablesInOpApplNode((OpApplNode) node); + return; + } + case LetInKind: { + LetInNode letNode = (LetInNode) node; + findUnchangedVaribalesInSemanticNode(letNode.getBody()); + return; + } + + case SubstInKind: { + SubstInNode substInNode = (SubstInNode) node; + findUnchangedVaribalesInSemanticNode(substInNode.getBody()); + return; + } + } + } + + /** + * @param node2 + */ + private void findUnchangedVariablesInOpApplNode(OpApplNode n) { + + int kind = n.getOperator().getKind(); + if (kind == UserDefinedOpKind + && !BBuiltInOPs.contains(n.getOperator().getName())) { + OpDefNode def = (OpDefNode) n.getOperator(); + findUnchangedVaribalesInSemanticNode(def.getBody()); + return; + } else if (kind == BuiltInKind) { + int opcode = BuiltInOPs.getOpCode(n.getOperator().getName()); + switch (opcode) { + case OPCODE_land: // \land + case OPCODE_cl: { // $ConjList + for (int i = 0; i < n.getArgs().length; i++) { + findUnchangedVaribalesInSemanticNode(n.getArgs()[i]); + } + return; + } + case OPCODE_unchanged:{ + n.setToolObject(USED, false); + OpApplNode k = (OpApplNode) n.getArgs()[0]; + if (k.getOperator().getKind() == VariableDeclKind) { + String name = k.getOperator().getName().toString(); + unchangedVariables.add(name); + } else { + // Tuple + for (int i = 0; i < k.getArgs().length; i++) { + OpApplNode var = (OpApplNode) k.getArgs()[i]; + String name = var.getOperator().getName().toString(); + unchangedVariables.add(name); + } + } + } + + } + } + } + + +} diff --git a/src/main/java/de/tla2b/analysis/InstanceTransformation.java b/src/main/java/de/tla2b/analysis/InstanceTransformation.java new file mode 100644 index 0000000000000000000000000000000000000000..9fe8a1bf2aebc321d5ad7867711ffea54391bb76 --- /dev/null +++ b/src/main/java/de/tla2b/analysis/InstanceTransformation.java @@ -0,0 +1,358 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.analysis; + + +import java.util.Hashtable; + +import de.tla2b.global.BBuiltInOPs; + +import tla2sany.semantic.ASTConstants; +import tla2sany.semantic.AbortException; +import tla2sany.semantic.AtNode; +import tla2sany.semantic.Context; +import tla2sany.semantic.ExprNode; +import tla2sany.semantic.ExprOrOpArgNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.LetInNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.NumeralNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpArgNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.StringNode; +import tla2sany.semantic.Subst; +import tla2sany.semantic.SubstInNode; +import tlc2.tool.BuiltInOPs; +import util.UniqueString; + +public class InstanceTransformation extends BuiltInOPs implements ASTConstants { + + OpDefNode[] defs; + Hashtable<String, OpDefNode> defsHash; + private int substitutionId = 11; + + /** + * @param con + */ + public InstanceTransformation(ModuleNode n) { + defs = n.getOpDefs(); + + defsHash = new Hashtable<String, OpDefNode>(); + for (int i = 0; i < defs.length; i++) { + defsHash.put(defs[i].getName().toString(), defs[i]); + } + } + + /** + * @throws AbortException + * + */ + public void start() { + for (int i = 0; i < defs.length; i++) { + OpDefNode def = defs[i]; + if (def.getSource() != def + && !BBuiltInOPs.contains(def.getSource().getName())) { + // instance + String defName = def.getName().toString(); + String prefix = defName.substring(0, + defName.lastIndexOf('!') + 1); + def.setParams(generateNewParams(def.getParams())); + ExprNode body; + try { + body = generateNewExprNode(def.getBody(), prefix); + } catch (AbortException e) { + throw new RuntimeException(); + } + def.setBody(body); + } + } + } + + /** + * @param exprOrOpArgNode + * @param prefix + * @return + * @throws AbortException + */ + private ExprOrOpArgNode generateNewExprOrOpArgNode(ExprOrOpArgNode n, + String prefix) throws AbortException { + if (n instanceof ExprNode) { + return generateNewExprNode((ExprNode) n, prefix); + } else { + throw new RuntimeException("OpArgNode not implemented jet"); + } + } + + /** + * @param body + * @param prefix + * @return + * @throws AbortException + */ + private ExprNode generateNewExprNode(ExprNode n, String prefix) + throws AbortException { + switch (n.getKind()) { + case OpApplKind: { + return generateNewOpApplNode((OpApplNode) n, prefix); + } + + case NumeralKind: { + NumeralNode num = (NumeralNode) n; + return new NumeralNode(num.toString(), n.getTreeNode()); + } + + case StringKind: { + StringNode str = (StringNode) n; + return new StringNode(str.getTreeNode(), true); + } + + case SubstInKind: { + SubstInNode substInNode = (SubstInNode) n; + + Subst[] subs = substInNode.getSubsts(); + for (int i = 0; i < subs.length; i++) { + OpDeclNode op = subs[i].getOp(); + op.setToolObject(substitutionId, subs[i].getExpr()); + } + return generateNewExprNode(substInNode.getBody(), prefix); + } + case AtNodeKind: { // @ + AtNode old = (AtNode) n; + OpApplNode oldExcept = old.getExceptRef(); + OpApplNode newExcept = (OpApplNode) oldExcept + .getToolObject(substitutionId); + OpApplNode oldComponent = old.getExceptComponentRef(); + OpApplNode newComponent = (OpApplNode) oldComponent + .getToolObject(substitutionId); + return new AtNode(newExcept, newComponent); + } + + case LetInKind: { + LetInNode oldLetNode = (LetInNode) n; + OpDefNode[] newLets = new OpDefNode[oldLetNode.getLets().length]; + Context cc = oldLetNode.context; + for (int i = 0; i < oldLetNode.getLets().length; i++) { + OpDefNode let = oldLetNode.getLets()[i]; + UniqueString newName = UniqueString.uniqueStringOf(prefix + + let.getName().toString()); + OpDefNode newLet = new OpDefNode(newName, let.getKind(), + generateNewParams(let.getParams()), let.isLocal(), + generateNewExprNode(let.getBody(), prefix), + let.getOriginallyDefinedInModuleNode(), null, + let.getTreeNode(), true, let.getSource()); + let.setToolObject(substitutionId, newLet); + newLets[i] = newLet; + cc.addSymbolToContext(newName, newLet); + } + + LetInNode newLetNode = new LetInNode(oldLetNode.getTreeNode(), + newLets, null, generateNewExprNode(oldLetNode.getBody(), + prefix), cc); + return newLetNode; + } + + } + throw new RuntimeException(); + } + + /** + * @param n + * @param prefix + * @return + * @throws AbortException + */ + private ExprNode generateNewOpApplNode(OpApplNode n, String prefix) + throws AbortException { + switch (n.getOperator().getKind()) { + case VariableDeclKind: + case ConstantDeclKind: { + ExprOrOpArgNode e = (ExprOrOpArgNode) n.getOperator() + .getToolObject(substitutionId); + if (e != null) { + if (e instanceof ExprNode) { + // TODO newprefix, witout last prefix + return generateNewExprNode((ExprNode) e, ""); + } else { + OpArgNode opArg = (OpArgNode) e; + while (opArg.getOp().getToolObject(substitutionId) != null) { + opArg = (OpArgNode) opArg.getOp().getToolObject( + substitutionId); + } + return new OpApplNode(opArg.getOp(), generateNewArgs( + n.getArgs(), prefix), n.getTreeNode(), null); + } + } else { + return new OpApplNode(n.getOperator(), generateNewArgs( + n.getArgs(), prefix), n.getTreeNode(), null); + } + } + + case FormalParamKind: { + FormalParamNode f = (FormalParamNode) n.getOperator() + .getToolObject(substitutionId); + if (f == null) { + System.out.println(n.toString(4)); + System.out.println(n); + } + return new OpApplNode(f, generateNewArgs(n.getArgs(), prefix), + n.getTreeNode(), null); + } + + case BuiltInKind: { + return generateNewBuiltInNode(n, prefix); + } + + case UserDefinedOpKind: { + // in case of a call of a LetInNode + OpDefNode letOp = (OpDefNode) n.getOperator().getToolObject( + substitutionId); + if (letOp != null) { + return new OpApplNode(letOp, generateNewArgs(n.getArgs(), + prefix), n.getTreeNode(), null); + } + + // in case of a call of BBuiltInOp e.g. +, - + if (BBuiltInOPs.contains(n.getOperator().getName())) { + return new OpApplNode(n.getOperator(), generateNewArgs( + n.getArgs(), prefix), n.stn, null); + } + + // normal userdefined Operator + String opName = prefix + n.getOperator().getName().toString(); + OpDefNode op = defsHash.get(opName); + return new OpApplNode(op, generateNewArgs(n.getArgs(), prefix), + n.getTreeNode(), null); + } + } + throw new RuntimeException("OpApplkind not implemented jet"); + } + + /** + * @param n + * @param prefix + * @return + * @throws AbortException + */ + private ExprNode generateNewBuiltInNode(OpApplNode n, String prefix) + throws AbortException { + switch (getOpCode(n.getOperator().getName())) { + + case OPCODE_exc: { // Except + OpApplNode newNode = new OpApplNode(n.getOperator().getName(), + null, n.getTreeNode(), null); + n.setToolObject(substitutionId, newNode); // needed for @ node + ExprOrOpArgNode[] newArgs = new ExprOrOpArgNode[n.getArgs().length]; + newArgs[0] = generateNewExprOrOpArgNode(n.getArgs()[0], prefix); + + for (int i = 1; i < n.getArgs().length; i++) { + OpApplNode pair = (OpApplNode) n.getArgs()[i]; + OpApplNode newPair = new OpApplNode(pair.getOperator() + .getName(), null, pair.getTreeNode(), null); + // needed for @ node: we have to set a reference from the old + // pair to the new pair + // before evaluation the arguments which may be contains a @ + // node + pair.setToolObject(substitutionId, newPair); + newPair.setArgs(generateNewArgs(pair.getArgs(), prefix)); + newArgs[i] = newPair; + } + newNode.setArgs(newArgs); + return newNode; + + } + case OPCODE_uc: { // CHOOSE x : P + FormalParamNode[] oldSymbols = n.getUnbdedQuantSymbols(); + FormalParamNode[] newSymbols = new FormalParamNode[oldSymbols.length]; + for (int i = 0; i < n.getUnbdedQuantSymbols().length; i++) { + FormalParamNode f = oldSymbols[i]; + newSymbols[i] = new FormalParamNode(f.getName(), f.getArity(), + f.getTreeNode(), null, null); + f.setToolObject(substitutionId, newSymbols[i]); + } + OpApplNode newNode = new OpApplNode(n.getOperator().getName(), + newSymbols, generateNewArgs(n.getArgs(), prefix), null, + null, null, n.getTreeNode(), null); + return newNode; + } + + case OPCODE_rfs: + case OPCODE_nrfs: + case OPCODE_fc: // Represents [x \in S |-> e] + case OPCODE_be: // \E x \in S : P + case OPCODE_bf: // \A x \in S : P + case OPCODE_bc: // CHOOSE x \in S: P + case OPCODE_sso: // $SubsetOf Represents {x \in S : P} + case OPCODE_soa: // $SetOfAll Represents {e : p1 \in S, p2,p3 \in S2} + { + // new formalparamnodes + FormalParamNode[][] oldParams = n.getBdedQuantSymbolLists(); + FormalParamNode[][] newParams = new FormalParamNode[oldParams.length][0]; + for (int i = 0; i < oldParams.length; i++) { + FormalParamNode[] temp = new FormalParamNode[oldParams[i].length]; + for (int j = 0; j < oldParams[i].length; j++) { + FormalParamNode f = oldParams[i][j]; + temp[j] = new FormalParamNode(f.getName(), f.getArity(), + f.getTreeNode(), null, null); + // set reference the old param to the new + f.setToolObject(substitutionId, temp[j]); + } + newParams[i] = temp; + } + + // new ranges + ExprNode[] ranges = new ExprNode[n.getBdedQuantBounds().length]; + for (int i = 0; i < n.getBdedQuantBounds().length; i++) { + ranges[i] = generateNewExprNode(n.getBdedQuantBounds()[i], + prefix); + } + OpApplNode newNode = new OpApplNode(n.getOperator().getName(), + null, generateNewArgs(n.getArgs(), prefix), newParams, + n.isBdedQuantATuple(), ranges, n.getTreeNode(), null); + return newNode; + } + + default: { // = + OpApplNode newNode = new OpApplNode(n.getOperator(), + generateNewArgs(n.getArgs(), prefix), n.getTreeNode(), null); + return newNode; + } + } + } + + /** + * @param args + * @param prefix + * @return + * @throws AbortException + */ + private ExprOrOpArgNode[] generateNewArgs(ExprOrOpArgNode[] args, + String prefix) throws AbortException { + ExprOrOpArgNode[] res = new ExprOrOpArgNode[args.length]; + for (int i = 0; i < args.length; i++) { + res[i] = generateNewExprOrOpArgNode(args[i], prefix); + } + return res; + } + + /** + * @param oldParams + * @return + */ + private FormalParamNode[] generateNewParams(FormalParamNode[] oldParams) { + FormalParamNode[] newParams = new FormalParamNode[oldParams.length]; + for (int i = 0; i < oldParams.length; i++) { + FormalParamNode oldParam = oldParams[i]; + FormalParamNode newParam = new FormalParamNode(oldParam.getName(), + oldParam.getArity(), oldParam.getTreeNode(), null, null); + // set reference to the old param to the new + oldParam.setToolObject(substitutionId, newParam); + newParams[i] = newParam; + } + return newParams; + } + +} diff --git a/src/main/java/de/tla2b/analysis/RecursiveFunktion.java b/src/main/java/de/tla2b/analysis/RecursiveFunktion.java new file mode 100644 index 0000000000000000000000000000000000000000..cfae0ae2d934da527e6a165463f70628fcc6cc6f --- /dev/null +++ b/src/main/java/de/tla2b/analysis/RecursiveFunktion.java @@ -0,0 +1,60 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.analysis; + +import de.tla2b.exceptions.NotImplementedException; +import tla2sany.semantic.ExprOrOpArgNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDefNode; +import tlc2.tool.BuiltInOPs; + +public class RecursiveFunktion extends BuiltInOPs{ + + private OpDefNode def; + private OpApplNode rfs; + private OpApplNode ifThenElse; + + public RecursiveFunktion(OpDefNode n, OpApplNode rfs) throws NotImplementedException { + def = n; + this.rfs = rfs; + evalDef(); + } + + /** + * @throws NotImplementedException + * + */ + private void evalDef() throws NotImplementedException { + ExprOrOpArgNode e = rfs.getArgs()[0]; + + if (e instanceof OpApplNode) { + OpApplNode o = (OpApplNode) e; + switch (getOpCode(o.getOperator().getName())) + { + case OPCODE_ite:{ // IF THEN ELSE + ifThenElse = o; + return; + } + } + throw new NotImplementedException( + "Only IF/THEN/ELSE or CASE constructs are supported at the body of a recursive function."); + } else { + throw new NotImplementedException( + "Only IF/THEN/ELSE or CASE constructs are supported at the body of a recursive function."); + } + } + + public OpDefNode getOpDefNode(){ + return def; + } + + public OpApplNode getRF(){ + return rfs; + } + + public OpApplNode getIfThenElse(){ + return ifThenElse; + } +} diff --git a/src/main/java/de/tla2b/analysis/SpecAnalyser.java b/src/main/java/de/tla2b/analysis/SpecAnalyser.java new file mode 100644 index 0000000000000000000000000000000000000000..023c3c8764b0b9c2d65d778d9900f94d365a9c0f --- /dev/null +++ b/src/main/java/de/tla2b/analysis/SpecAnalyser.java @@ -0,0 +1,601 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.analysis; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Set; + +import de.tla2b.config.ConfigfileEvaluator; +import de.tla2b.exceptions.ConfigFileErrorException; +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.NotImplementedException; +import de.tla2b.exceptions.SemanticErrorException; +import de.tla2b.global.BBuiltInOPs; +import de.tla2b.global.TranslationGlobals; +import de.tla2b.types.IType; +import de.tla2b.types.TLAType; + + + + +import tla2sany.semantic.ASTConstants; +import tla2sany.semantic.AssumeNode; +import tla2sany.semantic.ExprNode; +import tla2sany.semantic.ExprOrOpArgNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.LetInNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.NumeralNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpArgNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.SemanticNode; +import tla2sany.semantic.StringNode; +import tla2sany.semantic.SymbolNode; +import tlc2.tool.BuiltInOPs; +import tlc2.tool.ToolGlobals; + +public class SpecAnalyser extends BuiltInOPs implements ASTConstants, + ToolGlobals, IType, TranslationGlobals { + private OpDefNode spec; + private OpDefNode init; + private OpDefNode next; + private ArrayList<OpDefNode> invariants; + + private ModuleNode moduleNode; + private ExprNode nextExpr; + private String nextName; + private ArrayList<OpDeclNode> bConstants; + // used to check if a b constant has arguments and is not overriden in the + // configfile + + private ArrayList<BOperation> bOperations; + private ArrayList<ExprNode> inits; + private ArrayList<LetInNode> globalLets = new ArrayList<LetInNode>(); + // these local definitions occur in assume nodes or in BOperations and will + // be added in the front part of the definitions clause of the resulting B + // Machine + + private ArrayList<OpApplNode> ifThenElseNodes = new ArrayList<OpApplNode>(); + + private Set<OpDefNode> bDefinitionsSet = new HashSet<OpDefNode>(); + // set of OpDefNodes which will appear in the resulting B Machine + private Set<OpDefNode> usedDefinitions = new HashSet<OpDefNode>(); + // definitions which are used for the type inference algorithm + private Hashtable<OpDefNode, FormalParamNode[]> letParams = new Hashtable<OpDefNode, FormalParamNode[]>(); + // additional parameters of an let Operator, these parameters are from the + // surrounding operator + private ArrayList<String> definitionMacros = new ArrayList<String>(); + + private ArrayList<RecursiveFunktion> recursiveFunctions = new ArrayList<RecursiveFunktion>(); + + /** + * @param m + * @param conEval + */ + public SpecAnalyser(ModuleNode m, ConfigfileEvaluator conEval) { + this.moduleNode = m; + this.spec = conEval.getSpecNode(); + this.init = conEval.getInitNode(); + this.next = conEval.getNextNode(); + this.invariants = conEval.getInvariants(); + this.bConstants = conEval.getbConstantList(); + } + + public SpecAnalyser(ModuleNode m) { + this.moduleNode = m; + Hashtable<String, OpDefNode> definitions = new Hashtable<String, OpDefNode>(); + for (int i = 0; i < m.getOpDefs().length; i++) { + definitions.put(m.getOpDefs()[i].getName().toString(), + m.getOpDefs()[i]); + } + this.spec = definitions.get("Spec"); + this.init = definitions.get("Init"); + this.next = definitions.get("Next"); + + // TODO are constant in the right order + this.bConstants = new ArrayList<OpDeclNode>(); + this.bConstants.addAll(Arrays.asList(m.getConstantDecls())); + } + + public void start() throws SemanticErrorException, FrontEndException, + ConfigFileErrorException, NotImplementedException { + if (spec != null) { + evalSpec(); + } else { + evalInit(); + evalNext(); + } + findOperations(); + + findDefinitions(); + usedDefinitions.addAll(bDefinitionsSet); + + // test whether there is a init predicate if there is a variable + if (moduleNode.getVariableDecls().length > 0 && inits == null) { + throw new SemanticErrorException("No initial predicate is defined."); + } + + // check if there is B constant with arguments. + for (int i = 0; i < bConstants.size(); i++) { + OpDeclNode con = bConstants.get(i); + if (con.getArity() > 0) { + throw new ConfigFileErrorException( + String.format( + "Constant '%s' must be overriden in the configuration file.", + con.getName())); + } + } + + evalRecursiveFunctions(); + } + + private void evalInit() { + if (init != null) { + inits = new ArrayList<ExprNode>(); + inits = new ArrayList<ExprNode>(); + inits.add(init.getBody()); + } + } + + private void evalNext() throws FrontEndException { + if (next != null) { + this.nextExpr = next.getBody(); + this.nextName = next.getName().toString(); + } + } + + public void evalSpec() throws SemanticErrorException, FrontEndException { + if (spec != null) { + inits = new ArrayList<ExprNode>(); + processConfigSpec(spec.getBody()); + } + + } + + private void processConfigSpec(ExprNode exprNode) + throws SemanticErrorException, FrontEndException { + + if (exprNode instanceof OpApplNode) { + OpApplNode opApp = (OpApplNode) exprNode; + ExprOrOpArgNode[] args = opApp.getArgs(); + if (args.length == 0) { + SymbolNode opNode = opApp.getOperator(); + if (opNode instanceof OpDefNode) { + OpDefNode def = (OpDefNode) opNode; + ExprNode body = def.getBody(); + body.levelCheck(1); + if (body.getLevel() == 1) { + inits.add(exprNode); + } else { + processConfigSpec(body); + } + return; + } + throw new SemanticErrorException( + "Can not handle specification conjunction."); + } + + int opcode = BuiltInOPs.getOpCode(opApp.getOperator().getName()); + if (opcode == OPCODE_cl || opcode == OPCODE_land) { + for (int i = 0; i < args.length; i++) { + this.processConfigSpec((ExprNode) args[i]); + } + return; + } + + if (opcode == OPCODE_box) { + SemanticNode boxArg = args[0]; + if ((boxArg instanceof OpApplNode) + && BuiltInOPs.getOpCode(((OpApplNode) boxArg) + .getOperator().getName()) == OPCODE_sa) { + ExprNode next = (ExprNode) ((OpApplNode) boxArg).getArgs()[0]; + this.nextExpr = next; + this.nextName = "Next"; + return; + } + } + } + if (exprNode.getLevel() <= 1) { + // init + inits.add(exprNode); + } else if (exprNode.getLevel() == 3) { + // temporal + + } else { + throw new SemanticErrorException( + "Can not handle specification conjunction."); + } + + } + + /** + * Searches for BOperations in a ExprNode. BOperations are seperated with + * the aid of the disjunction (\/) operator. + * + * @param exprNode + * @param opName + * the name of the definition where exprNode occur + * @throws FrontEndException + * @throws ConfigFileErrorException + */ + private void findOperations() throws FrontEndException, + ConfigFileErrorException { + if (nextExpr == null) + return; + bOperations = new ArrayList<BOperation>(); + ArrayList<OpApplNode> existQuans = new ArrayList<OpApplNode>(); + findOperationsInSemanticNode(nextExpr, nextName, existQuans); + } + + /** + * + * @param node + * @param opName + * @param existQuans + * a list containing all existential quantifier which will be + * parameters in the resulting B Maschine + * @throws FrontEndException + * @throws ConfigFileErrorException + */ + private void findOperationsInSemanticNode(SemanticNode node, String opName, + ArrayList<OpApplNode> existQuans) throws FrontEndException, + ConfigFileErrorException { + switch (node.getKind()) { + case OpApplKind: { + findOperationsInOpApplNode((OpApplNode) node, opName, existQuans); + return; + } + case LetInKind: { + LetInNode letInNode = (LetInNode) node; + globalLets.add(letInNode); + + findOperationsInSemanticNode(letInNode.getBody(), opName, + existQuans); + return; + } + case NumeralKind: { + int val = ((NumeralNode) node).val(); + throw new FrontEndException(String.format( + "Expected an action at '%s'.\n%s", val, node.getLocation() + .toString())); + } + + case StringKind: { + StringNode s = (StringNode) node; + throw new FrontEndException(String.format( + "Expected an action at '\"%s\"'.\n%s", s.getRep(), node + .getLocation().toString())); + } + + default: + throw new FrontEndException(String.format( + "Expected an action.\n%s", node.getLocation().toString())); + } + + } + + private void findOperationsInOpApplNode(OpApplNode n, String name, + ArrayList<OpApplNode> existQuans) throws FrontEndException, + ConfigFileErrorException { + int kind = n.getOperator().getKind(); + if (kind == UserDefinedOpKind + && !BBuiltInOPs.contains(n.getOperator().getName())) { + OpDefNode def = (OpDefNode) n.getOperator(); + usedDefinitions.add(def); + if (def.getParams().length > 0) { + BOperation op = new BOperation(def.getName().toString(), n, + existQuans); + bOperations.add(op); + return; + } else { + findOperationsInSemanticNode(def.getBody(), def.getName() + .toString(), existQuans); + return; + } + + } else if (kind == BuiltInKind) { + int opcode = BuiltInOPs.getOpCode(n.getOperator().getName()); + switch (opcode) { + case OPCODE_dl: // DisjList + { + if (n.getArgs().length == 1) { + findOperationsInSemanticNode(n.getArgs()[0], name, + existQuans); + return; + } + for (int i = 0; i < n.getArgs().length; i++) { + findOperationsInSemanticNode(n.getArgs()[i], + name + (i + 1), existQuans); + } + return; + } + case OPCODE_lor: { + for (int i = 0; i < n.getArgs().length; i++) { + findOperationsInSemanticNode(n.getArgs()[i], + name + (i + 1), existQuans); + } + return; + } + case OPCODE_be: { // BoundedExists + ArrayList<OpApplNode> clone = new ArrayList<OpApplNode>( + existQuans); + clone.add(n); + findOperationsInSemanticNode(n.getArgs()[0], name, clone); + return; + } + + case OPCODE_unchanged: + case OPCODE_eq: // = + case OPCODE_noteq: // /=, # + case OPCODE_neg: // Negation + case OPCODE_lnot: // Negation + case OPCODE_cl: // $ConjList + case OPCODE_land: // \land + case OPCODE_equiv: // \equiv + case OPCODE_implies: // => + case OPCODE_bf: // \A x \in S : P + case OPCODE_in: // \in + case OPCODE_notin: // \notin + case OPCODE_subseteq: // \subseteq - subset or equal + case OPCODE_fa: // $FcnApply f[1] + case OPCODE_ite: // IF THEN ELSE + case OPCODE_case: { + BOperation op = new BOperation(name, n, existQuans); + bOperations.add(op); + return; + } + } + } + throw new FrontEndException(String.format( + "Expected an action at '%s' :\n%s", n.getOperator().getName() + .toString(), n.getLocation().toString())); + + } + + /** + * + * @throws ConfigFileErrorException + */ + + private void findDefinitions() throws ConfigFileErrorException { + AssumeNode[] assumes = moduleNode.getAssumptions(); + for (int i = 0; i < assumes.length; i++) { + visitExprNode(assumes[i].getAssume(), null); + } + + if (inits != null) { + for (int i = 0; i < inits.size(); i++) { + visitExprNode(inits.get(i), null); + } + } + if (bOperations != null) { + for (int i = 0; i < bOperations.size(); i++) { + visitExprNode(bOperations.get(i).getNode(), null); + } + } + + if (invariants != null) { + for (int i = 0; i < invariants.size(); i++) { + OpDefNode def = invariants.get(i); + bDefinitionsSet.add(def); + visitExprNode(def.getBody(), null); + } + } + + for (int i = 0; i < globalLets.size(); i++) { + LetInNode letInNode = globalLets.get(i); + for (int j = 0; j < letInNode.getLets().length; j++) { + visitExprNode(letInNode.getLets()[j].getBody(), null); + } + } + + } + + /** + * @param exprOrOpArgNode + */ + private void visitExprOrOpArgNode(ExprOrOpArgNode n, + FormalParamNode[] parameters) { + if (n instanceof ExprNode) { + visitExprNode((ExprNode) n, parameters); + } else if (n instanceof OpArgNode) { + + } + } + + private void visitExprNode(ExprNode node, FormalParamNode[] parameters) { + switch (node.getKind()) { + case OpApplKind: { + visitOpApplNode((OpApplNode) node, parameters); + return; + } + case LetInKind: { + LetInNode l = (LetInNode) node; + for (int i = 0; i < l.getLets().length; i++) { + OpDefNode letDef = l.getLets()[i]; + + if (parameters != null) + letParams.put(letDef, parameters); + + visitExprNode(letDef.getBody(), letDef.getParams()); + } + visitExprNode(l.getBody(), parameters); + return; + } + + } + } + + /** + * @param node + * @throws ConfigFileErrorException + */ + private void visitOpApplNode(OpApplNode node, FormalParamNode[] parameters) { + switch (node.getOperator().getKind()) { + case ConstantDeclKind: { + for (int i = 0; i < node.getArgs().length; i++) { + visitExprOrOpArgNode(node.getArgs()[i], parameters); + } + return; + } + + case VariableDeclKind: { + for (int i = 0; i < node.getArgs().length; i++) { + visitExprOrOpArgNode(node.getArgs()[i], parameters); + } + return; + } + + case BuiltInKind: { + visitBuiltInKind(node, parameters); + return; + } + + case UserDefinedOpKind: { + OpDefNode def = (OpDefNode) node.getOperator(); + //TODO + ModuleNode moduleNode = def.getSource().getOriginallyDefinedInModuleNode(); + if(moduleNode.getName().toString().equals("TLA2B")){ + return; + } + if (BBuiltInOPs.contains(def.getName()) + && STANDARD_MODULES.contains(def.getSource() + .getOriginallyDefinedInModuleNode().getName() + .toString())) { + + for (int i = 0; i < node.getArgs().length; i++) { + visitExprOrOpArgNode(node.getArgs()[i], parameters); + } + return; + } + bDefinitionsSet.add(def); + visitExprNode(def.getBody(), def.getParams()); + + for (int i = 0; i < node.getArgs().length; i++) { + visitExprOrOpArgNode(node.getArgs()[i], parameters); + } + return; + } + + } + + } + + /** + * @param node + */ + private void visitBuiltInKind(OpApplNode node, FormalParamNode[] parameters) { + switch (BuiltInOPs.getOpCode(node.getOperator().getName())) { + + case OPCODE_be: + case OPCODE_bf: + case OPCODE_soa: + case OPCODE_sso: + case OPCODE_nrfs: + case OPCODE_fc: { + ExprNode[] in = node.getBdedQuantBounds(); + for (int i = 0; i < in.length; i++) { + visitExprNode(in[i], parameters); + } + break; + } + case OPCODE_ite: { + ifThenElseNodes.add(node); + // if(!definitionMacro.contains(IF_THEN_ELSE)){ + // definitionMacro.add(IF_THEN_ELSE); + // } + break; + } + + case OPCODE_bc: { + if (!definitionMacros.contains(CHOOSE)) { + definitionMacros.add(CHOOSE); + } + break; + } + case OPCODE_unchanged: { + return; + } + } + for (int i = 0; i < node.getArgs().length; i++) { + visitExprOrOpArgNode(node.getArgs()[i], parameters); + } + } + + /** + * @throws NotImplementedException + * + */ + private void evalRecursiveFunctions() throws NotImplementedException { + + for (OpDefNode def : bDefinitionsSet) { + if (def.getBody() instanceof OpApplNode) { + OpApplNode o = (OpApplNode) def.getBody(); + switch (getOpCode(o.getOperator().getName())) { + case OPCODE_rfs: { // recursive Function + bDefinitionsSet.remove(def); + ifThenElseNodes.remove(o.getArgs()[0]); + RecursiveFunktion rf = new RecursiveFunktion(def, o); + recursiveFunctions.add(rf); + return; + } + } + } + } + } + + public void evalIfThenElse() { + boolean b = false; + for (int i = 0; i < ifThenElseNodes.size() && !b; i++) { + OpApplNode node = ifThenElseNodes.get(i); + TLAType t = (TLAType) node.getToolObject(TYPE_ID); + if (t.getKind() != BOOL) + b = true; + } + if (b) + definitionMacros.add(IF_THEN_ELSE); + } + + public ArrayList<LetInNode> getGlobalLets() { + return this.globalLets; + } + + public ArrayList<BOperation> getBOperations() { + return this.bOperations; + } + + public ArrayList<ExprNode> getInits() { + return this.inits; + } + + public ExprNode getNext() { + return this.nextExpr; + } + + public Set<OpDefNode> getBDefinitions() { + return bDefinitionsSet; + } + + public Hashtable<OpDefNode, FormalParamNode[]> getLetParams() { + return letParams; + } + + public ArrayList<String> getDefinitionMacros() { + return definitionMacros; + } + + public Set<OpDefNode> getUsedDefinitions() { + return usedDefinitions; + } + + public ArrayList<RecursiveFunktion> getRecursiveFunctions() { + return recursiveFunctions; + } +} diff --git a/src/main/java/de/tla2b/analysis/SymbolRenamer.java b/src/main/java/de/tla2b/analysis/SymbolRenamer.java new file mode 100644 index 0000000000000000000000000000000000000000..fed156c6418ec9a4e50fdfe34bbc8ac97c12b228 --- /dev/null +++ b/src/main/java/de/tla2b/analysis/SymbolRenamer.java @@ -0,0 +1,359 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.analysis; + + +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Set; + +import de.tla2b.global.BBuiltInOPs; +import de.tla2b.global.TranslationGlobals; + +import tla2sany.semantic.ASTConstants; +import tla2sany.semantic.AssumeNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.LetInNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.SemanticNode; +import tlc2.tool.BuiltInOPs; + +public class SymbolRenamer extends BuiltInOPs implements TranslationGlobals, + ASTConstants { + + private final static Set<String> KEYWORDS = new HashSet<String>(); + static { + KEYWORDS.add("seq"); + KEYWORDS.add("left"); + KEYWORDS.add("right"); + KEYWORDS.add("max"); + KEYWORDS.add("min"); + KEYWORDS.add("succ"); + KEYWORDS.add("pred"); + KEYWORDS.add("dom"); + KEYWORDS.add("ran"); + KEYWORDS.add("fnc"); + KEYWORDS.add("rel"); + KEYWORDS.add("id"); + KEYWORDS.add("card"); + KEYWORDS.add("POW"); + KEYWORDS.add("POW1"); + KEYWORDS.add("FIN"); + KEYWORDS.add("FIN1"); + KEYWORDS.add("size"); + KEYWORDS.add("rev"); + KEYWORDS.add("first"); + KEYWORDS.add("last"); + KEYWORDS.add("front"); + KEYWORDS.add("tail"); + KEYWORDS.add("conc"); + KEYWORDS.add("struct"); + KEYWORDS.add("rec"); + KEYWORDS.add("tree"); + KEYWORDS.add("btree"); + KEYWORDS.add("skip"); + KEYWORDS.add("ANY"); + KEYWORDS.add("WHERE"); + KEYWORDS.add("END"); + KEYWORDS.add("BE"); + KEYWORDS.add("VAR"); + KEYWORDS.add("ASSERT"); + KEYWORDS.add("CHOICE"); + KEYWORDS.add("OR"); + KEYWORDS.add("SELECT"); + KEYWORDS.add("EITHER"); + KEYWORDS.add("WHEN"); + KEYWORDS.add("BEGIN"); + KEYWORDS.add("MACHINE"); + KEYWORDS.add("REFINEMENT"); + KEYWORDS.add("IMPLEMENTATION"); + KEYWORDS.add("SETS"); + KEYWORDS.add("CONSTRAINTS"); + KEYWORDS.add("MODEL"); + KEYWORDS.add("SYSTEM"); + KEYWORDS.add("MACHINE"); + KEYWORDS.add("EVENTS"); + KEYWORDS.add("OPERATIONS"); + } + + private final static Hashtable<String, String> INFIX_OPERATOR = new Hashtable<String, String>(); + static { + INFIX_OPERATOR.put("!!", "exclamationmark2"); + INFIX_OPERATOR.put("??", "questionmark2"); + INFIX_OPERATOR.put("&", "ampersand1"); + INFIX_OPERATOR.put("&&", "ampersand2"); + INFIX_OPERATOR.put("@@", "at2"); + INFIX_OPERATOR.put("++", "plus2"); + INFIX_OPERATOR.put("--", "minus2"); + INFIX_OPERATOR.put("^", "circumflex1"); + INFIX_OPERATOR.put("^^", "circumflex2"); + INFIX_OPERATOR.put("##", "hash2"); + INFIX_OPERATOR.put("%%", "percent2"); + INFIX_OPERATOR.put("$", "dollar1"); + INFIX_OPERATOR.put("$$", "dollar2"); + INFIX_OPERATOR.put("|", "pipe1"); + INFIX_OPERATOR.put("||", "pipe2"); + INFIX_OPERATOR.put("//", "slash2"); + INFIX_OPERATOR.put("**", "mult2"); + INFIX_OPERATOR.put("...", "dot3"); + } + + private final static Hashtable<String, String> BBUILTIN_OPERATOR = new Hashtable<String, String>(); + static { + BBUILTIN_OPERATOR.put("+", "plus"); + BBUILTIN_OPERATOR.put("-", "minus"); + BBUILTIN_OPERATOR.put("*", "mult"); + BBUILTIN_OPERATOR.put("^", "power"); + BBUILTIN_OPERATOR.put("<", "lt"); + BBUILTIN_OPERATOR.put(">", "gt"); + BBUILTIN_OPERATOR.put("\\leq", "leq"); + BBUILTIN_OPERATOR.put("\\geq", "geq"); + BBUILTIN_OPERATOR.put("%", "modulo"); + BBUILTIN_OPERATOR.put("\\div", "div"); + BBUILTIN_OPERATOR.put("..", "dot2"); + } + + private ModuleNode moduleNode; + private Set<OpDefNode> usedDefinitions; + + private Set<String> globalNames = new HashSet<String>(); + private Hashtable<OpDefNode, Set<String>> usedNamesTable = new Hashtable<OpDefNode, Set<String>>(); + + /** + * @param moduleNode2 + * @param specAnalyser + */ + public SymbolRenamer(ModuleNode moduleNode, SpecAnalyser specAnalyser) { + this.moduleNode = moduleNode; + this.usedDefinitions = specAnalyser.getUsedDefinitions(); + } + + public SymbolRenamer(ModuleNode moduleNode) { + this.moduleNode = moduleNode; + usedDefinitions = new HashSet<OpDefNode>(); + OpDefNode[] defs = moduleNode.getOpDefs(); + usedDefinitions.add(defs[defs.length - 1]); + } + + public void start() { + // Variables + for (int i = 0; i < moduleNode.getVariableDecls().length; i++) { + OpDeclNode v = moduleNode.getVariableDecls()[i]; + String newName = incName(v.getName().toString()); + globalNames.add(newName); + v.setToolObject(NEW_NAME, newName); + } + + // constants + for (int i = 0; i < moduleNode.getConstantDecls().length; i++) { + OpDeclNode c = moduleNode.getConstantDecls()[i]; + String newName = incName(c.getName().toString()); + globalNames.add(newName); + c.setToolObject(NEW_NAME, newName); + } + + for (int i = 0; i < moduleNode.getOpDefs().length; i++) { + OpDefNode def = moduleNode.getOpDefs()[i]; + String newName = getOperatorName(def); + globalNames.add(newName); + def.setToolObject(NEW_NAME, newName); + usedNamesTable.put(def, new HashSet<String>()); + } + + for (int i = 0; i < moduleNode.getAssumptions().length; i++) { + AssumeNode assumeNode = moduleNode.getAssumptions()[i]; + visitNode(assumeNode.getAssume(), new HashSet<String>()); + } + + for (int i = moduleNode.getOpDefs().length - 1; i >= 0; i--) { + OpDefNode def = moduleNode.getOpDefs()[i]; + Set<String> usedNames = usedNamesTable.get(def); + for (int j = 0; j < def.getParams().length; j++) { + FormalParamNode p = def.getParams()[j]; + String paramName = p.getName().toString(); + String newParamName = incName(paramName); + p.setToolObject(NEW_NAME, newParamName); + //Parameter of different definitions calling each other can have the same name + //usedNames.add(newParamName); + } + visitNode(def.getBody(), usedNames); + } + + } + + private void visitNode(SemanticNode n, Set<String> usedNames) { + // System.out.println(n.toString(1)+ " "+ n.getKind()); + + switch (n.getKind()) { + + case LetInKind: { + LetInNode letInNode = (LetInNode) n; + OpDefNode[] defs = letInNode.getLets(); + + // Initialize all local definitions (get a new name, get an empty + // list) + for (int i = 0; i < defs.length; i++) { + OpDefNode def = defs[i]; + String newName = getOperatorName(def); + globalNames.add(newName); + def.setToolObject(NEW_NAME, newName); + usedNamesTable.put(def, new HashSet<String>(usedNames)); + } + + // first visit the IN expression + visitNode(letInNode.getBody(), usedNames); + + // visit the definition itself + for (int i = defs.length - 1; i >= 0; i--) { + OpDefNode def = defs[i]; + Set<String> usedNamesOfDef = usedNamesTable.get(def); + for (int j = 0; j < def.getParams().length; j++) { + FormalParamNode p = def.getParams()[j]; + String paramName = p.getName().toString(); + String newParamName = incName(paramName); + p.setToolObject(NEW_NAME, newParamName); + //usedNamesOfDef.add(newParamName); + } + visitNode(def.getBody(), usedNamesOfDef); + } + return; + } + + case OpApplKind: { + OpApplNode opApplNode = (OpApplNode) n; + switch (opApplNode.getOperator().getKind()) { + + case BuiltInKind: { + visitBuiltinNode(opApplNode, usedNames); + return; + } + + case UserDefinedOpKind: { + OpDefNode def = (OpDefNode) opApplNode.getOperator(); + if (BBuiltInOPs.contains(def.getName())) { + break; + } + + usedNamesTable.get(def).addAll(usedNames); + for (int i = 0; i < n.getChildren().length; i++) { + visitNode(opApplNode.getArgs()[i], usedNames); + } + return; + } + } + + for (int i = 0; i < opApplNode.getArgs().length; i++) { + visitNode(opApplNode.getArgs()[i], usedNames); + } + return; + } + } + + if (n.getChildren() != null) { + for (int i = 0; i < n.getChildren().length; i++) { + visitNode(n.getChildren()[i], usedNames); + } + } + } + + private void visitBuiltinNode(OpApplNode opApplNode, Set<String> usedNames) { + + switch (getOpCode(opApplNode.getOperator().getName())) { + + case OPCODE_nrfs: + case OPCODE_fc: // Represents [x \in S |-> e] + case OPCODE_bc: // CHOOSE x \in S: P + case OPCODE_soa: // $SetOfAll Represents {e : p1 \in S, p2,p3 \in S2} + case OPCODE_sso: // $SubsetOf Represents {x \in S : P} + case OPCODE_bf: // \A x \in S : P + case OPCODE_be: // \E x \in S : P + { + FormalParamNode[][] params = opApplNode.getBdedQuantSymbolLists(); + Set<String> newUsedNames = new HashSet<String>(usedNames); + for (int i = 0; i < params.length; i++) { + for (int j = 0; j < params[i].length; j++) { + FormalParamNode param = params[i][j]; + String paramName = param.getName().toString(); + String newName = incName(paramName, usedNames); + param.setToolObject(NEW_NAME, newName); + newUsedNames.add(newName); + } + } + for (int i = 0; i < opApplNode.getBdedQuantBounds().length; i++) { + visitNode(opApplNode.getBdedQuantBounds()[i], usedNames); + } + + visitNode(opApplNode.getArgs()[0], newUsedNames); + + return; + } + + default: + for (int i = 0; i < opApplNode.getArgs().length; i++) { + if (opApplNode.getArgs()[i] != null) { + visitNode(opApplNode.getArgs()[i], usedNames); + } + } + + } + } + + private String getOperatorName(OpDefNode def) { + String newName = def.getName().toString(); + + if (BBUILTIN_OPERATOR.containsKey(newName)) { + // a B built-in operator is defined outside of a standard module + if (!STANDARD_MODULES.contains(def.getSource() + .getOriginallyDefinedInModuleNode().getName().toString())) { + return incName(BBUILTIN_OPERATOR.get(newName)); + } + } + + // replace invalid infix operator names + for (String e : INFIX_OPERATOR.keySet()) { + if (newName.contains(e)) { + newName = newName.replace(e, INFIX_OPERATOR.get(e)); + } + } + + // replace exclamation marks + if (newName.contains("!")) { + newName = newName.replace('!', '_'); + } + + // replace slashes + if (newName.contains("\\")) { + newName = newName.replace("\\", ""); + } + + return incName(newName); + } + + private Boolean existingName(String name) { + if (globalNames.contains(name) || KEYWORDS.contains(name)) { + return true; + } else + return false; + } + + private String incName(String name) { + String res = name; + for (int i = 1; existingName(res); i++) { + res = name + "_" + i; + } + return res; + } + + private String incName(String name, Set<String> tempSet) { + String res = name; + for (int i = 1; existingName(res) || tempSet.contains(res); i++) { + res = name + "_" + i; + } + return res; + } +} diff --git a/src/main/java/de/tla2b/analysis/SymbolSorter.java b/src/main/java/de/tla2b/analysis/SymbolSorter.java new file mode 100644 index 0000000000000000000000000000000000000000..514837f1c390fee44d28a134fe04d0746b926da9 --- /dev/null +++ b/src/main/java/de/tla2b/analysis/SymbolSorter.java @@ -0,0 +1,83 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.analysis; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Hashtable; + +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; + +public class SymbolSorter { + private ModuleNode moduleNode; + + public SymbolSorter(ModuleNode moduleNode) { + this.moduleNode = moduleNode; + } + + public void sort() { + // sort constants + Arrays.sort(moduleNode.getConstantDecls(), new OpDeclNodeComparator()); + // sort variables + Arrays.sort(moduleNode.getVariableDecls(), new OpDeclNodeComparator()); + // sort definitions + Arrays.sort(moduleNode.getOpDefs(), new OpDefNodeComparator()); + } + + public static void sortDeclNodes(OpDeclNode[] opDeclNodes){ + Arrays.sort(opDeclNodes, new OpDeclNodeComparator()); + } + + public static void sortOpDefNodes(OpDefNode[] opDefNodes){ + Arrays.sort(opDefNodes, new OpDefNodeComparator()); + } + + public static Hashtable<String, OpDefNode> getDefsHashTable(OpDefNode[] opDefNodes){ + Hashtable<String, OpDefNode> definitions = new Hashtable<String, OpDefNode>(); + for (int i = 0; i < opDefNodes.length; i++) { + OpDefNode def = opDefNodes[i]; + // Definition in this module +// if (StandardModules.contains(def.getOriginallyDefinedInModuleNode() +// .getName().toString()) +// || StandardModules.contains(def.getSource() +// .getOriginallyDefinedInModuleNode().getName() +// .toString())) { +// continue; +// } + definitions.put(def.getName().toString(), def); + } + return definitions; + } + +} + +class OpDeclNodeComparator implements Comparator<OpDeclNode> { + public int compare(OpDeclNode a, OpDeclNode b) { + if (a.getUid() < b.getUid()) + return -1; + if (a.getUid() > b.getUid()) + return 1; + return 0; + } +} + +class OpDefNodeComparator implements Comparator<OpDefNode> { + public int compare(OpDefNode a, OpDefNode b) { + if (a.getLocation().equals(b.getLocation())) { + if (a.getSource().getUid() < b.getSource().getUid()) + return -1; + if (a.getSource().getUid() > b.getSource().getUid()) + return 1; + return 0; + } + if (a.getUid() < b.getUid()) + return -1; + if (a.getUid() > b.getUid()) + return 1; + return 0; + } +} \ No newline at end of file diff --git a/src/main/java/de/tla2b/analysis/TypeChecker.java b/src/main/java/de/tla2b/analysis/TypeChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..604118c9573427cd31ff5dc9c9931f2a2cbfa499 --- /dev/null +++ b/src/main/java/de/tla2b/analysis/TypeChecker.java @@ -0,0 +1,1572 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.analysis; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.Set; + +import de.tla2b.config.ConfigfileEvaluator; +import de.tla2b.config.TLCValueNode; +import de.tla2b.config.ValueObj; +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.NotImplementedException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.exceptions.UnificationException; +import de.tla2b.global.BBuildIns; +import de.tla2b.global.BBuiltInOPs; +import de.tla2b.global.TranslationGlobals; +import de.tla2b.types.*; + +import tla2sany.semantic.ASTConstants; +import tla2sany.semantic.AssumeNode; +import tla2sany.semantic.AtNode; +import tla2sany.semantic.ExprNode; +import tla2sany.semantic.ExprOrOpArgNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.LetInNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.NumeralNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.StringNode; +import tla2sany.semantic.SymbolNode; +import tlc2.tool.BuiltInOPs; + +public class TypeChecker extends BuiltInOPs implements IType, ASTConstants, + BBuildIns, TranslationGlobals { + + private final int TEMP_TYPE_ID = 6; + private int paramId; + + private ArrayList<ExprNode> inits; + private ExprNode nextExpr; + private Set<OpDefNode> usedDefinitions; + + private ArrayList<OpApplNode> recList = new ArrayList<OpApplNode>(); + // every record node [a |-> 1 .. ] will be added to this List + private ModuleNode moduleNode; + private ArrayList<OpDeclNode> bConstList; + + private Hashtable<OpDeclNode, ValueObj> constantAssignments; + + /** + * @param moduleNode2 + * @param conEval + * @param specAnalyser + */ + public TypeChecker(ModuleNode moduleNode, ConfigfileEvaluator conEval, + SpecAnalyser specAnalyser) { + this.moduleNode = moduleNode; + if (conEval != null) { + this.bConstList = conEval.getbConstantList(); + this.constantAssignments = conEval.getConstantAssignments(); + } + this.inits = specAnalyser.getInits(); + this.nextExpr = specAnalyser.getNext(); + usedDefinitions = specAnalyser.getUsedDefinitions(); + + paramId = TYPE_ID; + } + + public TypeChecker(ModuleNode moduleNode) { + this.moduleNode = moduleNode; + + Set<OpDefNode> usedDefinitions = new HashSet<OpDefNode>(); + OpDefNode[] defs = moduleNode.getOpDefs(); + // used the last definition of the module + usedDefinitions.add(defs[defs.length - 1]); + this.usedDefinitions = usedDefinitions; + + paramId = TYPE_ID; + } + + public void start() throws TLA2BException { + OpDeclNode[] cons = moduleNode.getConstantDecls(); + for (int i = 0; i < cons.length; i++) { + OpDeclNode con = cons[i]; + if (constantAssignments != null + && constantAssignments.containsKey(con)) { + TLAType t = constantAssignments.get(con).getType(); + con.setToolObject(TYPE_ID, t); + } else { + Untyped u = new Untyped(); + con.setToolObject(TYPE_ID, u); + u.addFollower(con); + } + } + + OpDeclNode[] vars = moduleNode.getVariableDecls(); + for (int i = 0; i < vars.length; i++) { + OpDeclNode var = vars[i]; + Untyped u = new Untyped(); + var.setToolObject(TYPE_ID, u); + u.addFollower(var); + } + + evalDefinitions(moduleNode.getOpDefs()); + evalAssumptions(moduleNode.getAssumptions()); + + if (inits != null) { + for (int i = 0; i < inits.size(); i++) { + visitExprNode(inits.get(i), BoolType.getInstance()); + } + } + + if (nextExpr != null) { + visitExprNode(nextExpr, BoolType.getInstance()); + } + + // check if a variable has no type + for (int i = 0; i < vars.length; i++) { + OpDeclNode var = vars[i]; + TLAType varType = (TLAType) var.getToolObject(TYPE_ID); + if (varType.isUntyped()) { + throw new TypeErrorException("Variable '" + var.getName() + + "' has no cype!"); + } + } + + // check if a constant has no type, only constants which will appear in + // the resulting B Machine are considered + for (int i = 0; i < cons.length; i++) { + OpDeclNode con = cons[i]; + if (bConstList == null || bConstList.contains(con)) { + TLAType conType = (TLAType) con.getToolObject(TYPE_ID); + if (conType.isUntyped()) { + throw new TypeErrorException("The type of constant " + + con.getName() + " is still untyped: " + conType); + } + } + } + + evalRecList(); + } + + /** + * + */ + private void evalRecList() { + for (int i = 0; i < recList.size(); i++) { + OpApplNode n = recList.get(i); + StructType struct = (StructType) n.getToolObject(TYPE_ID); + ArrayList<String> fieldNames = new ArrayList<String>(); + ExprOrOpArgNode[] args = n.getArgs(); + for (int j = 0; j < args.length; j++) { + OpApplNode pair = (OpApplNode) args[j]; + StringNode stringNode = (StringNode) pair.getArgs()[0]; + fieldNames.add(stringNode.getRep().toString()); + } + for (int j = 0; j < struct.getFields().size(); j++) { + String fieldName = struct.getFields().get(j); + if (!fieldNames.contains(fieldName) + && struct.getType(fieldName).getKind() == MODELVALUE) { + EnumType e = (EnumType) struct.getType(fieldName); + e.setNoVal(); + } + } + } + + } + + private void evalDefinitions(OpDefNode[] opDefs) throws TLA2BException { + for (int i = 0; i < opDefs.length; i++) { + OpDefNode def = opDefs[i]; + // Definition in this module + String moduleName1 = def.getOriginallyDefinedInModuleNode() + .getName().toString(); + String moduleName2 = def.getSource() + .getOriginallyDefinedInModuleNode().getName().toString(); + + if (STANDARD_MODULES.contains(moduleName1) + || STANDARD_MODULES.contains(moduleName2)) { + continue; + } + if (usedDefinitions.contains(def)) + visitOpDefNode(def); + + } + + } + + /** + * @param def + * @throws TLA2BException + */ + private void visitOpDefNode(OpDefNode def) throws TLA2BException { + FormalParamNode[] params = def.getParams(); + for (int i = 0; i < params.length; i++) { + FormalParamNode p = params[i]; + if (p.getArity() > 0) { + throw new FrontEndException(String.format( + "TLA2B do not support 2nd-order operators: '%s'\n %s ", + def.getName(), def.getLocation())); + } + Untyped u = new Untyped(); + p.setToolObject(paramId, u); + u.addFollower(p); + } + TLAType defType = visitExprNode(def.getBody(), new Untyped()); + def.setToolObject(TYPE_ID, defType); + if (defType instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) defType).addFollower(def); + } + + } + + private void evalAssumptions(AssumeNode[] assumptions) + throws TLA2BException { + for (AssumeNode assumeNode : assumptions) { + visitExprNode(assumeNode.getAssume(), BoolType.getInstance()); + } + } + + /** + * @param exprOrOpArgNode + * @param instance + * @throws TypeErrorException + * @throws NotImplementedException + */ + private TLAType visitExprOrOpArgNode(ExprOrOpArgNode n, TLAType expected) + throws TLA2BException { + if (n instanceof ExprNode) { + return visitExprNode((ExprNode) n, expected); + } else { + throw new NotImplementedException("OpArgNode not implemented jet"); + } + + } + + private TLAType visitExprNode(ExprNode exprNode, TLAType expected) + throws TLA2BException { + + switch (exprNode.getKind()) { + case TLCValueKind: { + TLCValueNode valueNode = (TLCValueNode) exprNode; + try { + return valueNode.getType().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException( + String.format( + "Expected %s, found %s at '%s'(assigned in the configuration file),\n%s ", + expected, valueNode.getType(), + valueNode.getValue(), exprNode.getLocation())); + } + + } + + case OpApplKind: + return visitOpApplNode((OpApplNode) exprNode, expected); + + case NumeralKind: + try { + return IntType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found INTEGER at '%s',\n%s ", expected, + ((NumeralNode) exprNode).val(), exprNode.getLocation())); + } + case StringKind: { + try { + return StringType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found STRING at '%s',\n%s ", expected, + ((StringNode) exprNode).getRep(), + exprNode.getLocation())); + } + } + case AtNodeKind: { // @ + AtNode a = (AtNode) exprNode; + OpApplNode pair2 = a.getExceptComponentRef(); + ExprOrOpArgNode rightside = pair2.getArgs()[1]; + TLAType type = (TLAType) rightside.getToolObject(TYPE_ID); + try { + TLAType res = type.unify(expected); + return res; + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at '@',\n%s ", expected, type, + exprNode.getLocation())); + } + + } + + case LetInKind: { + LetInNode l = (LetInNode) exprNode; + for (int i = 0; i < l.getLets().length; i++) { + visitOpDefNode(l.getLets()[i]); + } + return visitExprNode(l.getBody(), expected); + } + + case SubstInKind: { + throw new RuntimeException( + "SubstInKind should never occur after InstanceTransformation"); + } + + case DecimalKind:{ + // currently not supported + } + + + } + + throw new NotImplementedException(exprNode.toString(2)); + + } + + /** + * @param n + * @param expected + * @return {@link TLAType} + * @throws TLA2BException + */ + private TLAType visitOpApplNode(OpApplNode n, TLAType expected) + throws TLA2BException { + + switch (n.getOperator().getKind()) { + case ConstantDeclKind: { + OpDeclNode con = (OpDeclNode) n.getOperator(); + + TLAType c = (TLAType) con.getToolObject(TYPE_ID); + if (c == null) { + throw new RuntimeException(con.getName() + " has no type yet!"); + } + try { + TLAType result = expected.unify(c); + con.setToolObject(TYPE_ID, result); + return result; + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at constant '%s',\n%s", + expected, c, con.getName(), n.getLocation()) + + ); + } + } + + case VariableDeclKind: { + SymbolNode symbolNode = n.getOperator(); + String vName = symbolNode.getName().toString(); + TLAType v = (TLAType) symbolNode.getToolObject(TYPE_ID); + if (v == null) { + throw new RuntimeException(vName + " has no type yet!"); + } + try { + TLAType result = expected.unify(v); + symbolNode.setToolObject(TYPE_ID, result); + return result; + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at variable '%s',\n%s", + expected, v, vName, n.getLocation())); + } + } + + case BuiltInKind: { + return evalBuiltInKind(n, expected); + } + + case FormalParamKind: { + SymbolNode symbolNode = n.getOperator(); + String pName = symbolNode.getName().toString(); + TLAType t = (TLAType) symbolNode.getToolObject(paramId); + if (t == null) { + t = (TLAType) symbolNode.getToolObject(TYPE_ID); + } + try { + TLAType result = expected.unify(t); + symbolNode.setToolObject(paramId, result); + return result; + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at parameter '%s',\n%s", + expected, t, pName, n.getLocation())); + } + } + + case UserDefinedOpKind: { + OpDefNode def = (OpDefNode) n.getOperator(); + + // Definition is a BBuilt-in definition + String sourceModule = def.getSource() + .getOriginallyDefinedInModuleNode().getName().toString(); + if (BBuiltInOPs.contains(def.getName()) + && STANDARD_MODULES.contains(sourceModule)) { + return evalBBuiltIns(n, expected); + } + + TLAType found = ((TLAType) def.getToolObject(TYPE_ID)); + if (found == null) + found = new Untyped(); + // throw new RuntimeException(def.getName() + " has no type yet!"); + found = found.cloneTLAType(); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at definition '%s',\n%s", + expected, found, def.getName(), n.getLocation())); + } + boolean untyped = false; + FormalParamNode[] params = def.getParams(); + for (int i = 0; i < n.getArgs().length; i++) { + // clone the parameter type, because the parameter type is not + // set/changed at a definition call + FormalParamNode p = params[i]; + TLAType pType = ((TLAType) p.getToolObject(TYPE_ID)); + if (pType == null) { + pType = new Untyped(); + // throw new RuntimeException("Parameter " + p.getName() + // + " has no type yet!\n" + p.getLocation()); + } + pType = pType.cloneTLAType(); + if (pType.isUntyped()) + untyped = true; + + pType = visitExprOrOpArgNode(n.getArgs()[i], pType); // unify + // both + // types + // set types of the arguments of the definition call to the + // parameters for reevaluation the def body + p.setToolObject(TEMP_TYPE_ID, pType); + } + + if (found.isUntyped() || untyped) { + // evaluate the body of the definition again + paramId = TEMP_TYPE_ID; + found = visitExprNode(def.getBody(), found); + paramId = TYPE_ID; + } + + n.setToolObject(TYPE_ID, found); + + return found; + + } + + default: { + throw new NotImplementedException(n.getOperator().getName() + .toString()); + } + } + + } + + /** + * @param exprNode + * @param expected + * @return {@link TLAType} + * @throws TLA2BException + */ + private TLAType evalBuiltInKind(OpApplNode n, TLAType expected) + throws TLA2BException { + + switch (getOpCode(n.getOperator().getName())) { + + /********************************************************************** + * equality and disequality: =, #, /= + **********************************************************************/ + case OPCODE_eq: // = + case OPCODE_noteq: // /=, # + { + try { + BoolType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found BOOL at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + TLAType left = visitExprOrOpArgNode(n.getArgs()[0], + new de.tla2b.types.Untyped()); + visitExprOrOpArgNode(n.getArgs()[1], left); + return BoolType.getInstance(); + } + + /********************************************************************** + * Logic Operators: \neg, \lnot, \land, \cl, \lor, \dl, \equiv, => + **********************************************************************/ + case OPCODE_neg: // Negation + case OPCODE_lnot: // Negation + case OPCODE_cl: // $ConjList + case OPCODE_dl: // $DisjList + case OPCODE_land: // \land + case OPCODE_lor: // \lor + case OPCODE_equiv: // \equiv + case OPCODE_implies: // => + { + try { + BoolType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found BOOL at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + for (int i = 0; i < n.getArgs().length; i++) { + visitExprOrOpArgNode(n.getArgs()[i], BoolType.getInstance()); + } + return BoolType.getInstance(); + } + + /********************************************************************** + * Quantification: \A x \in S : P or \E x \in S : P + **********************************************************************/ + case OPCODE_be: // \E x \in S : P + case OPCODE_bf: // \A x \in S : P + { + try { + BoolType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found BOOL at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + evalBoundedVariables(n); + visitExprOrOpArgNode(n.getArgs()[0], BoolType.getInstance()); + return BoolType.getInstance(); + } + + /********************************************************************** + * Set Operators + **********************************************************************/ + case OPCODE_se: // SetEnumeration {..} + { + SetType found = new SetType(new Untyped()); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(_A) at set enumeration,\n%s", + expected, n.getLocation())); + } + TLAType current = found.getSubType(); + for (int i = 0; i < n.getArgs().length; i++) { + current = visitExprOrOpArgNode(n.getArgs()[i], current); + } + return found; + } + + case OPCODE_in: // \in + case OPCODE_notin: // \notin + { + if (!BoolType.getInstance().compare(expected)) { + throw new TypeErrorException(String.format( + "Expected %s, found BOOL at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + TLAType element = visitExprOrOpArgNode(n.getArgs()[0], + new Untyped()); + visitExprOrOpArgNode(n.getArgs()[1], new SetType(element)); + + return BoolType.getInstance(); + } + + case OPCODE_setdiff: // set difference + case OPCODE_cup: // set union + case OPCODE_cap: // set intersection + { + SetType found = new SetType(new Untyped()); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(_A) at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + TLAType left = visitExprOrOpArgNode(n.getArgs()[0], found); + TLAType right = visitExprOrOpArgNode(n.getArgs()[1], left); + return right; + } + + case OPCODE_subseteq: // \subseteq - subset or equal + { + try { + BoolType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found BOOL at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + TLAType left = visitExprOrOpArgNode(n.getArgs()[0], new SetType( + new Untyped())); + visitExprOrOpArgNode(n.getArgs()[1], left); + return BoolType.getInstance(); + } + + /********************************************************************** + * Set Constructor + **********************************************************************/ + case OPCODE_sso: // $SubsetOf Represents {x \in S : P} + { + + TLAType domainType = evalBoundedVariables(n); + SetType found = new SetType(domainType); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at '%s',\n%s", expected, found, + n.getOperator().getName(), n.getLocation())); + } + visitExprOrOpArgNode(n.getArgs()[0], BoolType.getInstance()); + return found; + } + + case OPCODE_soa: // $SetOfAll Represents {e : p1 \in S, p2,p3 \in S2} + { + SetType found = new SetType(new Untyped()); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(_A) at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + evalBoundedVariables(n); + visitExprOrOpArgNode(n.getArgs()[0], found.getSubType()); + return found; + } + + case OPCODE_subset: // SUBSET (conforms POW in B) + { + SetType found = new SetType(new Untyped()); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(_A) at 'SUBSET',\n%s", + expected, n.getLocation())); + } + visitExprOrOpArgNode(n.getArgs()[0], found.getSubType()); + return found; + } + + case OPCODE_union: // Union - Union{{1},{2}} + { + SetType found = new SetType(new Untyped()); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(_A) at 'SUBSET',\n%s", + expected, n.getLocation())); + } + SetType setOfSet = (SetType) visitExprOrOpArgNode(n.getArgs()[0], + new SetType(found)); + return setOfSet.getSubType(); + } + + /********************************************************************** + * Prime + **********************************************************************/ + case OPCODE_prime: // prime + { + try { + OpApplNode node = (OpApplNode) n.getArgs()[0]; + if (node.getOperator().getKind() != VariableDeclKind) { + throw new TypeErrorException("Expected variable at \"" + + node.getOperator().getName() + "\":\n" + + node.getLocation()); + } + return visitExprOrOpArgNode(n.getArgs()[0], expected); + } catch (ClassCastException e) { + throw new TypeErrorException( + "Expected variable as argument of prime operator:\n" + + n.getArgs()[0].getLocation()); + } + } + + /*********************************************************************** + * Tuple: Tuple as Function 1..n to Set (Sequence) + ***********************************************************************/ + case OPCODE_tup: { // $Tuple + ArrayList<TLAType> list = new ArrayList<TLAType>(); + for (int i = 0; i < n.getArgs().length; i++) { + list.add(visitExprOrOpArgNode(n.getArgs()[i], new Untyped())); + } + TLAType found = null; + if (list.size() == 0) { + found = new FunctionType(IntType.getInstance(), new Untyped()); + } else if (list.size() == 1) { + found = new FunctionType(IntType.getInstance(), list.get(0)); + } else { + found = new TupleType(list); + } + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at Tuple,\n%s", expected, found, + n.getLocation())); + } + n.setToolObject(TYPE_ID, found); + if (found instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) found).addFollower(n); + } + return found; + } + + /*********************************************************************** + * Function constructors + ***********************************************************************/ + case OPCODE_rfs: // recursive function ( f[x\in Nat] == IF x = 0 THEN 1 + // ELSE f[n-1] + { + + FormalParamNode recFunc = n.getUnbdedQuantSymbols()[0]; + FunctionType recType = new FunctionType(); + recFunc.setToolObject(TYPE_ID, recType); + recType.addFollower(recFunc); + + TLAType domainType = evalBoundedVariables(n); + FunctionType found = new FunctionType(domainType, new Untyped()); + visitExprOrOpArgNode(n.getArgs()[0], found.getRange()); + + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException("Expected '" + expected + + "', found '" + found + "'.\n" + n.getLocation()); + } + + TLAType t = null; + try { + t = (TLAType) recFunc.getToolObject(TYPE_ID); + found = found.unify(t); + } catch (UnificationException e) { + throw new TypeErrorException("Expected '" + expected + + "', found '" + t + "'.\n" + n.getLocation()); + } + + return found; + } + + case OPCODE_nrfs: // succ[n \in Nat] == n + 1 + case OPCODE_fc: // [n \in Nat |-> n+1] + { + TLAType domainType = evalBoundedVariables(n); + FunctionType found = new FunctionType(domainType, new Untyped()); + visitExprOrOpArgNode(n.getArgs()[0], found.getRange()); + + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException("Expected '" + expected + + "', found '" + found + "'.\n" + n.getLocation()); + } + return found; + } + + /*********************************************************************** + * Function call + ***********************************************************************/ + case OPCODE_fa: // $FcnApply f[1] + { + TLAType domType; + ExprOrOpArgNode dom = n.getArgs()[1]; + if (dom instanceof OpApplNode + && ((OpApplNode) dom).getOperator().getName().toString() + .equals("$Tuple")) { + ArrayList<TLAType> domList = new ArrayList<TLAType>(); + OpApplNode domOpAppl = (OpApplNode) dom; + for (int i = 0; i < domOpAppl.getArgs().length; i++) { + TLAType d = visitExprOrOpArgNode(domOpAppl.getArgs()[i], + new Untyped()); + domList.add(d); + } + domType = new TupleType(domList); + } else { + domType = visitExprOrOpArgNode(n.getArgs()[1], new Untyped()); + } + FunctionType func = new FunctionType(domType, expected); + FunctionType res = (FunctionType) visitExprOrOpArgNode( + n.getArgs()[0], func); + return res.getRange(); + } + + /*********************************************************************** + * Domain of Function + ***********************************************************************/ + case OPCODE_domain: { + + FunctionType func = new FunctionType(new Untyped(), new Untyped()); + func = (FunctionType) visitExprOrOpArgNode(n.getArgs()[0], func); + TLAType res = null; + try { + res = new SetType(func.getDomain()).unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected '%s', found '%s' at 'DOMAIN(..)',\n%s", + expected, n.getLocation())); + } + return res; + } + /*********************************************************************** + * Set of Function + ***********************************************************************/ + case OPCODE_sof: // [ A -> B] + { + SetType A = (SetType) visitExprOrOpArgNode(n.getArgs()[0], + new SetType(new Untyped())); + SetType B = (SetType) visitExprOrOpArgNode(n.getArgs()[1], + new SetType(new Untyped())); + + SetType found = new SetType(new FunctionType(A.getSubType(), + B.getSubType())); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected '%s', found '%s' at Set of Function,\n%s", + expected, found, n.getLocation())); + } + return found; + } + + /********************************************************************** + * Except + **********************************************************************/ + case OPCODE_exc: // Except + { + return evalExcept(n, expected); + } + + /*********************************************************************** + * Cartesian Product: A \X B + ***********************************************************************/ + case OPCODE_cp: // $CartesianProd A \X B \X C as $CartesianProd(A, B, C) + { + ArrayList<TLAType> list = new ArrayList<TLAType>(); + for (int i = 0; i < n.getArgs().length; i++) { + SetType t = (SetType) visitExprOrOpArgNode(n.getArgs()[i], + new SetType(new Untyped())); + list.add(t.getSubType()); + } + + SetType found = new SetType(new TupleType(list)); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at Cartesian Product,\n%s", + expected, found, n.getLocation())); + } + return found; + } + + /*********************************************************************** + * Records + ***********************************************************************/ + case OPCODE_sor: // $SetOfRcds [L1 : e1, L2 : e2] + { + StructType struct = new StructType(); + for (int i = 0; i < n.getArgs().length; i++) { + OpApplNode pair = (OpApplNode) n.getArgs()[i]; + StringNode field = (StringNode) pair.getArgs()[0]; + SetType fieldType = (SetType) visitExprOrOpArgNode( + pair.getArgs()[1], new SetType(new Untyped())); + struct.add(field.getRep().toString(), fieldType.getSubType()); + } + + SetType found = new SetType(struct); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at Set of Records,\n%s", + expected, found, n.getLocation())); + } + n.setToolObject(TYPE_ID, found); + if (found instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) found).addFollower(n); + } + return found; + } + + case OPCODE_rc: // [h_1 |-> 1, h_2 |-> 2] + { + StructType found = new StructType(); + for (int i = 0; i < n.getArgs().length; i++) { + OpApplNode pair = (OpApplNode) n.getArgs()[i]; + StringNode field = (StringNode) pair.getArgs()[0]; + TLAType fieldType = visitExprOrOpArgNode(pair.getArgs()[1], + new Untyped()); + found.add(field.getRep().toString(), fieldType); + } + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at Record,\n%s", expected, + found, n.getLocation())); + } + n.setToolObject(TYPE_ID, found); + if (found instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) found).addFollower(n); + } + recList.add(n); + return found; + + } + + case OPCODE_rs: // $RcdSelect r.c + { + String fieldName = ((StringNode) n.getArgs()[1]).getRep() + .toString(); + StructType r = (StructType) visitExprOrOpArgNode(n.getArgs()[0], + new StructType()); + + StructType expectedStruct = new StructType(); + expectedStruct.add(fieldName, expected); + + try { + r = r.unify(expectedStruct); + return r.getType(fieldName); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Struct has no field %s with type %s: %s\n%s", + fieldName, r.getType(fieldName), r, n.getLocation())); + } + } + + /*********************************************************************** + * miscellaneous constructs + ***********************************************************************/ + case OPCODE_ite: // IF THEN ELSE + { + visitExprOrOpArgNode(n.getArgs()[0], BoolType.getInstance()); + TLAType then = visitExprOrOpArgNode(n.getArgs()[1], expected); + TLAType eelse = visitExprOrOpArgNode(n.getArgs()[2], then); + n.setToolObject(TYPE_ID, eelse); + if (eelse instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) eelse).addFollower(n); + } + return eelse; + } + + case OPCODE_case: { + /** + * CASE p1 -> e1 [] p2 -> e2 represented as $Case( $Pair(p1, + * e1),$Pair(p2, e2) ) and CASE p1 -> e1 [] p2 -> e2 [] OTHER -> e3 + * represented as $Case( $Pair(p1, e1), $Pair(p2, e2), $Pair(null, + * e3)) + **/ + TLAType found = expected; + for (int i = 0; i < n.getArgs().length; i++) { + OpApplNode pair = (OpApplNode) n.getArgs()[i]; + if (pair.getArgs()[0] != null) { + visitExprOrOpArgNode(pair.getArgs()[0], + BoolType.getInstance()); + } + found = visitExprOrOpArgNode(pair.getArgs()[1], found); + } + return found; + + } + + case OPCODE_bc: { // CHOOSE x \in S: P + if (n.isBdedQuantATuple()[0]) { + throw new TypeErrorException( + "A tuple as parameter within the set constructor is not permitted.\n" + + n.getLocation()); + } + ExprNode[] bounds = n.getBdedQuantBounds(); + SetType S = (SetType) visitExprNode(bounds[0], new SetType( + new Untyped())); + TLAType found = S.getSubType(); + + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'CHOOSE',\n%s", expected, + found, n.getLocation())); + } + FormalParamNode x = n.getBdedQuantSymbolLists()[0][0]; + x.setToolObject(TYPE_ID, found); + if (found instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) found).addFollower(x); + } + visitExprOrOpArgNode(n.getArgs()[0], BoolType.getInstance()); + return found; + } + + case OPCODE_unchanged: { + return BoolType.getInstance().unify(expected); + } + + /*********************************************************************** + * no TLA+ Built-ins + ***********************************************************************/ + case 0: { + return evalBBuiltIns(n, expected); + } + } + + throw new NotImplementedException("Not supported Operator: " + + n.getOperator().getName().toString() + "\n" + n.getLocation()); + } + + private TLAType evalBoundedVariables(OpApplNode n) throws TLA2BException { + ArrayList<TLAType> domList = new ArrayList<TLAType>(); + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ExprNode[] bounds = n.getBdedQuantBounds(); + for (int i = 0; i < bounds.length; i++) { + SetType boundType = (SetType) visitExprNode(bounds[i], new SetType( + new Untyped())); + TLAType subType = boundType.getSubType(); + + if (n.isBdedQuantATuple()[i]) { + if (subType instanceof TupleType) { + domList.add(subType); + TupleType t = (TupleType) subType; + if (params[i].length != t.getTypes().size()) { + throw new TypeErrorException("Expected tuple with " + + params[i].length + + " components, found tuple with " + + t.getTypes().size() + " components.\n" + + bounds[i].getLocation()); + } + for (int j = 0; j < params[i].length; j++) { + FormalParamNode p = params[i][j]; + TLAType paramType = t.getTypes().get(j); + p.setToolObject(TYPE_ID, paramType); + if (paramType instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) paramType).addFollower(p); + } + } + } else if (subType instanceof Untyped) { + TupleType tuple = new TupleType(params[i].length); + try { + tuple = (TupleType) tuple.unify(subType); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s ,\n%s", tuple, subType, + n.getLocation())); + } + + domList.add(tuple); + for (int j = 0; j < params[i].length; j++) { + FormalParamNode p = params[i][j]; + TLAType paramType = tuple.getTypes().get(j); + p.setToolObject(TYPE_ID, paramType); + if (paramType instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) paramType).addFollower(p); + } + } + + } else { + throw new TypeErrorException("Expected tuple, found '" + + subType + "'.\n" + bounds[i].getLocation()); + } + } else { + // is not a tuple: all parameter have the same type + for (int j = 0; j < params[i].length; j++) { + domList.add(subType); + FormalParamNode p = params[i][j]; + p.setToolObject(TYPE_ID, subType); + if (subType instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) subType).addFollower(p); + } + } + } + } + + TLAType domType = null; + if (domList.size() == 1) { + domType = domList.get(0); + } else { + domType = new TupleType(domList); + } + return domType; + } + + /** + * @param n + * @param expected + * @return + * @throws TLA2BException + */ + private TLAType evalExcept(OpApplNode n, TLAType expected) + throws TLA2BException { + TLAType t = visitExprOrOpArgNode(n.getArgs()[0], expected); + n.setToolObject(TYPE_ID, t); + if (t instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) t).addFollower(n); + } + + for (int i = 1; i < n.getArgs().length; i++) { + OpApplNode pair = (OpApplNode) n.getArgs()[i]; + ExprOrOpArgNode leftside = pair.getArgs()[0]; + ExprOrOpArgNode rightside = pair.getArgs()[1]; + // stored for @ node + Untyped untyped = new Untyped(); + rightside.setToolObject(TYPE_ID, untyped); + untyped.addFollower(rightside); + TLAType valueType = visitExprOrOpArgNode(rightside, untyped); + + OpApplNode seq = (OpApplNode) leftside; + LinkedList<ExprOrOpArgNode> list = new LinkedList<ExprOrOpArgNode>(); + for (int j = 0; j < seq.getArgs().length; j++) { + list.add(seq.getArgs()[j]); + } + ExprOrOpArgNode first = list.poll(); + + if (first instanceof StringNode) { + String field = ((StringNode) first).getRep().toString(); + TLAType res = evalType(list, valueType); + StructOrFunction s = new StructOrFunction(field, res); + try { + t = t.unify(s); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'EXCEPT',\n%s", t, s, + pair.getLocation())); + } + + } else { + // Function + ExprOrOpArgNode domExpr = first; + TLAType domType; + TLAType rangeType; + if (domExpr instanceof OpApplNode + && ((OpApplNode) domExpr).getOperator().getName() + .toString().equals("$Tuple")) { + ArrayList<TLAType> domList = new ArrayList<TLAType>(); + OpApplNode domOpAppl = (OpApplNode) domExpr; + for (int j = 0; j < domOpAppl.getArgs().length; j++) { + TLAType d = visitExprOrOpArgNode( + domOpAppl.getArgs()[j], new Untyped()); + domList.add(d); + } + domType = new TupleType(domList); + } else { + domType = visitExprOrOpArgNode(domExpr, new Untyped()); + } + rangeType = evalType(list, valueType); + FunctionType func = new FunctionType(domType, rangeType); + try { + t = t.unify(func); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'EXCEPT',\n%s", t, func, + pair.getLocation())); + } + } + } + return t; + + } + + /** + * @param list + * @param valueType + * @return + * @throws TLA2BException + */ + private TLAType evalType(LinkedList<ExprOrOpArgNode> list, TLAType valueType) + throws TLA2BException { + if (list.size() == 0) { + return valueType; + } + ExprOrOpArgNode head = list.poll(); + if (head instanceof StringNode) { + // record or function of strings + String name = ((StringNode) head).getRep().toString(); + StructOrFunction res = new StructOrFunction(name, evalType(list, + valueType)); + return res; + } + TLAType t = visitExprOrOpArgNode(head, new Untyped()); + FunctionType res = new FunctionType(t, evalType(list, valueType)); + return res; + } + + private TLAType evalBBuiltIns(OpApplNode n, TLAType expected) + throws TLA2BException { + switch (BBuiltInOPs.getOpcode(n.getOperator().getName())) { + // B Builtins + + /********************************************************************** + * Standard Module Naturals + **********************************************************************/ + case B_OPCODE_gt: // > + case B_OPCODE_lt: // < + case B_OPCODE_leq: // <= + case B_OPCODE_geq: // >= + { + try { + BoolType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found BOOL at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + for (int i = 0; i < n.getArgs().length; i++) { + visitExprOrOpArgNode(n.getArgs()[i], IntType.getInstance()); + } + return BoolType.getInstance(); + } + + case B_OPCODE_plus: // + + case B_OPCODE_minus: // - + case B_OPCODE_times: // * + case B_OPCODE_div: // / + case B_OPCODE_mod: // % modulo + case B_OPCODE_exp: { // x hoch y, x^y + try { + IntType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found INTEGER at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + for (int i = 0; i < n.getArgs().length; i++) { + visitExprOrOpArgNode(n.getArgs()[i], IntType.getInstance()); + } + return IntType.getInstance(); + } + + case B_OPCODE_dotdot: // .. + { + try { + expected.unify(new SetType(IntType.getInstance())); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(INTEGER) at '..',\n%s", + expected, n.getLocation())); + } + + for (int i = 0; i < n.getArgs().length; i++) { + visitExprOrOpArgNode(n.getArgs()[i], IntType.getInstance()); + } + return new SetType(IntType.getInstance()); + } + + case B_OPCODE_nat: // Nat + { + try { + SetType found = new SetType(IntType.getInstance()); + found = found.unify(expected); + return found; + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(INTEGER) at 'Nat',\n%s", + expected, n.getLocation())); + } + } + + /********************************************************************** + * Standard Module Integers + **********************************************************************/ + case B_OPCODE_int: // Int + { + try { + SetType found = new SetType(IntType.getInstance()); + found = found.unify(expected); + return found; + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(INTEGER) at 'Int',\n%s", + expected, n.getLocation())); + } + } + + case B_OPCODE_uminus: // -x + { + try { + IntType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found INTEGER at '-',\n%s", expected, + n.getLocation())); + } + visitExprOrOpArgNode(n.getArgs()[0], IntType.getInstance()); + return IntType.getInstance(); + } + + /********************************************************************** + * Standard Module FiniteSets + **********************************************************************/ + case B_OPCODE_finite: // IsFiniteSet + { + try { + BoolType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found BOOL at 'IsFiniteSet',\n%s", + expected, n.getLocation())); + } + visitExprOrOpArgNode(n.getArgs()[0], new SetType(new Untyped())); + return BoolType.getInstance(); + } + + case B_OPCODE_card: // Cardinality + { + try { + IntType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found INTEGER at 'Cardinality',\n%s", + expected, n.getLocation())); + } + visitExprOrOpArgNode(n.getArgs()[0], new SetType(new Untyped())); + return IntType.getInstance(); + } + + /********************************************************************** + * Standard Module Sequences + **********************************************************************/ + case B_OPCODE_seq: { // Seq(S) - set of sequences, S must be a set + + SetType S = (SetType) visitExprOrOpArgNode(n.getArgs()[0], + new SetType(new Untyped())); + + SetType set_of_seq = new SetType(new FunctionType( + IntType.getInstance(), S.getSubType())); + try { + set_of_seq = set_of_seq.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'Seq',\n%s", expected, + set_of_seq, n.getLocation())); + } + return set_of_seq; + } + + case B_OPCODE_len: { // lengh of the sequence + try { + IntType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found INTEGER at 'Len',\n%s", expected, + n.getLocation())); + } + visitExprOrOpArgNode(n.getArgs()[0], + new FunctionType(IntType.getInstance(), new Untyped())); + return IntType.getInstance(); + } + + case B_OPCODE_conc: { // s \o s2 - concatenation of s and s2 + FunctionType found = new FunctionType(IntType.getInstance(), + new Untyped()); + found = (FunctionType) visitExprOrOpArgNode(n.getArgs()[0], found); + found = (FunctionType) visitExprOrOpArgNode(n.getArgs()[1], found); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(INTEGER*_A) at '\\o',\n%s", + expected, n.getLocation())); + } + return found; + } + + case B_OPCODE_append: // Append(s, e) + { + FunctionType found = new FunctionType(IntType.getInstance(), + new Untyped()); + found = (FunctionType) visitExprOrOpArgNode(n.getArgs()[0], found); + visitExprOrOpArgNode(n.getArgs()[1], found.getRange()); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'Append',\n%s", expected, + found, n.getLocation())); + } + return found; + } + + case B_OPCODE_head: { // HEAD(s) - the first element of the sequence + FunctionType func = new FunctionType(IntType.getInstance(), + new Untyped()); + func = (FunctionType) visitExprOrOpArgNode(n.getArgs()[0], func); + + TLAType found = func.getRange(); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'Head',\n%s", expected, + found, n.getLocation())); + } + return found; + } + + case B_OPCODE_tail: { // Tail(s) + FunctionType found = new FunctionType(IntType.getInstance(), + new Untyped()); + found = (FunctionType) visitExprOrOpArgNode(n.getArgs()[0], found); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'Tail',\n%s", expected, + found, n.getLocation())); + } + return found; + } + + case B_OPCODE_subseq: { // SubSeq(s,m,n) + FunctionType found = new FunctionType(IntType.getInstance(), + new Untyped()); + found = (FunctionType) visitExprOrOpArgNode(n.getArgs()[0], found); + visitExprOrOpArgNode(n.getArgs()[1], IntType.getInstance()); + visitExprOrOpArgNode(n.getArgs()[2], IntType.getInstance()); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'SubSeq',\n%s", expected, + found, n.getLocation())); + } + return found; + } + + // TODO add BSeq to tla standard modules + + /********************************************************************** + * Standard Module TLA2B + **********************************************************************/ + + case B_OPCODE_min: // MinOfSet(S) + case B_OPCODE_max: // MaxOfSet(S) + case B_OPCODE_setprod: // SetProduct(S) + case B_OPCODE_setsum: // SetSummation(S) + { + try { + IntType.getInstance().unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found INTEGER at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + visitExprOrOpArgNode(n.getArgs()[0], + new SetType(IntType.getInstance())); + return IntType.getInstance(); + } + + case B_OPCODE_permseq: { // PermutedSequences(S) + SetType argType = (SetType) visitExprOrOpArgNode(n.getArgs()[0], + new SetType(new Untyped())); + SetType found = new SetType(new FunctionType(IntType.getInstance(), + argType.getSubType())); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at 'PermutedSequences',\n%s", + expected, found, n.getLocation())); + } + return found; + } + + /********************************************************************** + * Standard Module TLA2B + **********************************************************************/ + case B_OPCODE_pow1: // POW1 + { + + SetType set = new SetType(new Untyped()); + set = (SetType) visitExprOrOpArgNode(n.getArgs()[0], set); + SetType found = new SetType(set); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + return found; + } + + /********************************************************************** + * Standard Module Relations + **********************************************************************/ + case B_OPCODE_rel_inverse: // POW1 + { + SetType set = new SetType(new TupleType(2)); + set = (SetType) visitExprOrOpArgNode(n.getArgs()[0], set); + TupleType t = (TupleType) set.getSubType(); + ArrayList<TLAType> list = new ArrayList<TLAType>(); + list.add(t.getTypes().get(1)); + list.add(t.getTypes().get(0)); + SetType found = new SetType(new TupleType(list)); + try { + found = found.unify(expected); + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found %s at '%s',\n%s", expected, found, + n.getOperator().getName(), n.getLocation())); + } + return found; + } + + /*********************************************************************** + * TLA+ Built-Ins, but not in tlc.tool.BuiltInOPs + ***********************************************************************/ + case B_OPCODE_bool: // BOOLEAN + try { + SetType found = new SetType(BoolType.getInstance()); + found = found.unify(expected); + return found; + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(BOOL) at 'BOOLEAN',\n%s", + expected, n.getLocation())); + } + + case B_OPCODE_string: // STRING + try { + SetType found = new SetType(StringType.getInstance()); + found = found.unify(expected); + return found; + } catch (UnificationException e) { + throw new TypeErrorException(String.format( + "Expected %s, found POW(STRING) at 'STRING',\n%s", + expected, n.getLocation())); + } + + case B_OPCODE_true: + case B_OPCODE_false: + try { + BoolType.getInstance().unify(expected); + return BoolType.getInstance(); + } catch (Exception e) { + throw new TypeErrorException(String.format( + "Expected %s, found BOOL at '%s',\n%s", expected, n + .getOperator().getName(), n.getLocation())); + } + + default: { + throw new NotImplementedException(n.getOperator().getName() + .toString()); + } + } + } + + public static TLAType makePair(ArrayList<TLAType> list) { + if (list.size() == 0) + throw new RuntimeException("emptylist"); + if (list.size() == 1) + return list.get(0); + PairType p = new PairType(); + p.setFirst(list.get(0)); + for (int i = 1; i < list.size(); i++) { + p.setSecond(list.get(i)); + if (i < list.size() - 1) { + p = new PairType(p, null); + } + } + return p; + } + +} diff --git a/src/main/java/de/tla2b/config/ConfigfileEvaluator.java b/src/main/java/de/tla2b/config/ConfigfileEvaluator.java new file mode 100644 index 0000000000000000000000000000000000000000..99793b4b8d880fbffb2441219fbff3da1f04560a --- /dev/null +++ b/src/main/java/de/tla2b/config/ConfigfileEvaluator.java @@ -0,0 +1,624 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.config; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; + +import de.tla2b.exceptions.ConfigFileErrorException; +import de.tla2b.exceptions.UnificationException; +import de.tla2b.types.BoolType; +import de.tla2b.types.EnumType; +import de.tla2b.types.IntType; +import de.tla2b.types.ModelValueType; +import de.tla2b.types.SetType; +import de.tla2b.types.StringType; +import de.tla2b.types.TLAType; +import de.tla2b.types.Untyped; + + + +import tla2sany.semantic.InstanceNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.OpDefOrDeclNode; +import tlc2.tool.ModelConfig; +import tlc2.util.Vect; +import tlc2.value.IntValue; +import tlc2.value.ModelValue; +import tlc2.value.SetEnumValue; +import tlc2.value.Value; + +/** + * This class evaluates the configfile and collects all necessary information of + * the configfile. All used identifier in the configfile are checked to be valid + * in the context of the module + */ +public class ConfigfileEvaluator { + + private ModelConfig configAst; + private ModuleNode moduleNode; + private Hashtable<String, OpDefNode> definitions; + // Hashtable of all definitons in module + private Hashtable<String, OpDeclNode> constants; + // Hashtable of all constants in the module + + private OpDefNode specNode; // SPECIFICATION node, may be null + private OpDefNode nextNode; // NEXT node, may be null + private OpDefNode initNode; // INIT node, may be null + private ArrayList<OpDefNode> invariantNodeList; + // INVARIANT nodes, may be null + private ArrayList<String> enumeratedSet; + private LinkedHashMap<String, EnumType> enumeratedTypes; + private Hashtable<OpDeclNode, ValueObj> constantAssignments; + // k = 1, the ValueObj describes the right side of the assignment and + // contains it type + private Hashtable<OpDefNode, ValueObj> operatorAssignments; + // def = 1 + + private ArrayList<OpDefNode> operatorModelvalues; + + private ArrayList<OpDeclNode> bConstantList; + // List of constants in the resulting B machine. This list does not contain + // a TLA+ constant if the constant is substituted by a modelvalue with the + // same name (the constant name is moved to an enumerated set) or if the + // constants has arguments and is overriden by an operator + private Hashtable<OpDefNode, OpDefNode> operatorOverrideTable; + // This table contains mappings for operators which are overridden in the + // configuration file + private Hashtable<OpDeclNode, OpDefNode> constantOverrideTable; + + // This table contains mappings for constants which are overridden in the + // configuration file. All constants with arguments have to be overridden in + // the configuration file. + + /** + * @param configAst + * @param moduleNode + */ + public ConfigfileEvaluator(ModelConfig configAst, ModuleNode moduleNode) { + this.configAst = configAst; + this.moduleNode = moduleNode; + + definitions = new Hashtable<String, OpDefNode>(); + OpDefNode[] defs = moduleNode.getOpDefs(); + for (int i = 0; i < defs.length; i++) { + definitions.put(defs[i].getName().toString(), defs[i]); + } + + constants = new Hashtable<String, OpDeclNode>(); + bConstantList = new ArrayList<OpDeclNode>(); + OpDeclNode[] cons = moduleNode.getConstantDecls(); + for (int i = 0; i < cons.length; i++) { + constants.put(cons[i].getName().toString(), cons[i]); + bConstantList.add(cons[i]); + } + + this.constantOverrideTable = new Hashtable<OpDeclNode, OpDefNode>(); + this.operatorOverrideTable = new Hashtable<OpDefNode, OpDefNode>(); + + this.constantAssignments = new Hashtable<OpDeclNode, ValueObj>(); + this.operatorAssignments = new Hashtable<OpDefNode, ValueObj>(); + this.operatorModelvalues = new ArrayList<OpDefNode>(); + + this.enumeratedSet = new ArrayList<String>(); + this.enumeratedTypes = new LinkedHashMap<String, EnumType>(); + } + + /** + * @throws ConfigFileErrorException + * + */ + public void start() throws ConfigFileErrorException { + evalNext(); // check if NEXT declaration is a valid definition + evalInit(); // check if INIT declaration is a valid definition + evalSpec(); // check if SPECIFICATION declaration is a valid definition + + if (moduleNode.getVariableDecls().length > 0 && this.initNode == null + && this.specNode == null) { + throw new ConfigFileErrorException( + "The module contains variables." + + " Hence there must be eather a SPECIFICATION or INIT declaration."); + } + + evalInvariants(); + // check if INVARIANT declarations are valid definitions + + evalConstantOrDefOverrides(); + + evalConstantOrOperatorAssignments(); + + evalModConOrDefAssignments(); + + evalModConOrDefOverrides(); + } + + private void evalNext() throws ConfigFileErrorException { + String next = configAst.getNext(); + if (!next.equals("")) { + if (definitions.containsKey(next)) { + this.nextNode = definitions.get(next); + } else { + throw new ConfigFileErrorException( + "Invalid declaration of the next state predicate." + + " Module does not contain the defintion '" + + next + "'"); + } + } else + next = null; + + } + + private void evalInit() throws ConfigFileErrorException { + String init = configAst.getInit(); + if (!init.equals("")) { + if (definitions.containsKey(init)) { + this.initNode = definitions.get(init); + } else { + throw new ConfigFileErrorException( + "Invalid declaration of the initialisation predicate." + + " Module does not contain the defintion '" + + init + "'"); + } + } else { + init = null; + } + + } + + private void evalSpec() throws ConfigFileErrorException { + String spec = configAst.getSpec(); + if (!spec.equals("")) { + if (definitions.containsKey(spec)) { + this.specNode = definitions.get(spec); + } else { + throw new ConfigFileErrorException( + "Invalid declaration of the specification predicate." + + "Module does not contain the defintion '" + + spec + "'"); + } + } else + spec = null; + } + + private void evalInvariants() throws ConfigFileErrorException { + + Vect v = configAst.getInvariants(); + if (v.capacity() != 0) { + invariantNodeList = new ArrayList<OpDefNode>(); + for (int i = 0; i < v.capacity(); i++) { + if (v.elementAt(i) != null) { + String inv = (String) v.elementAt(i); + if (!definitions.containsKey(inv)) { + throw new ConfigFileErrorException( + "Invalid invariant declaration. Module does not contain definition '" + + inv + "'"); + } + invariantNodeList.add(definitions.get(inv)); + } + } + } + + } + + /** + * Represents a override statement in the configuration file: k <- def + * + * @throws ConfigFileErrorException + */ + @SuppressWarnings("unchecked") + private void evalConstantOrDefOverrides() throws ConfigFileErrorException { + Iterator<Map.Entry<String, String>> it = configAst.getOverrides() + .entrySet().iterator(); + while (it.hasNext()) { + Map.Entry<String, String> entry = it.next(); + String left = entry.getKey(); + String right = entry.getValue(); + + OpDefNode rightDefNode = definitions.get(right); + if (rightDefNode == null) { + throw new ConfigFileErrorException("Invalid substitution for " + + left + ".\n Module does not contain definition " + + right + "."); + } + + if (constants.containsKey(left)) { + // a constant is overridden by an operator + OpDeclNode conNode = constants.get(left); + if (conNode.getArity() != rightDefNode.getArity()) { + throw new ConfigFileErrorException( + String.format( + "Invalid substitution for %s.\n Constant %s has %s arguments while %s has %s arguments.", + left, left, conNode.getArity(), right, + rightDefNode.getArity())); + } + bConstantList.remove(conNode); + constantOverrideTable.put(conNode, rightDefNode); + } else if (definitions.containsKey(left)) { + // an operator is overridden by another operator + OpDefNode defNode = definitions.get(left); + if (defNode.getArity() != rightDefNode.getArity()) { + throw new ConfigFileErrorException( + String.format( + "Invalid substitution for %s.\n Operator %s has %s arguments while %s has %s arguments.", + left, left, defNode.getArity(), right, + rightDefNode.getArity())); + } + + operatorOverrideTable.put(defNode, rightDefNode); + } else { + // every constants in the configuration file must appear in the + // TLA+ + // module + throw new ConfigFileErrorException( + "Module does not contain the symbol: " + left); + } + } + } + + private void evalConstantOrOperatorAssignments() + throws ConfigFileErrorException { + Vect configCons = configAst.getConstants(); + // iterate over all constant or operator assignments in the config file + // k = 1 or def = 1 + for (int i = 0; i < configCons.size(); i++) { + Vect symbol = (Vect) configCons.elementAt(i); + String symbolName = symbol.elementAt(0).toString(); + Value symbolValue = (Value) symbol.elementAt(symbol.size() - 1); + TLAType symbolType = conGetType(symbol.elementAt(symbol.size() - 1)); + if (constants.containsKey(symbolName)) { + OpDeclNode c = constants.get(symbolName); + + ValueObj valueObj = new ValueObj(symbolValue, symbolType); + constantAssignments.put(c, valueObj); + /** + * if conValue is a model value and the name of the value is the + * same as the name of constants, then the constant declaration + * in the resulting B machine disappears + **/ + if (symbolType instanceof EnumType && symbolName.equals(symbolValue.toString())) { + bConstantList.remove(c); + } + } else if (definitions.containsKey(symbolName)) { + OpDefNode def = definitions.get(symbolName); + ValueObj valueObj = new ValueObj(symbolValue, symbolType); + operatorAssignments.put(def, valueObj); + + if (symbolType instanceof SetType) { + if (((SetType) symbolType).getSubType() instanceof EnumType) { + operatorModelvalues.add(def); + } + } else if ((symbolType instanceof EnumType)) { + operatorModelvalues.add(def); + } + + } else { + // every constants or operator in the configuration file must + // appear in the TLA+ + // module + throw new ConfigFileErrorException( + "Module does not contain the symbol: " + symbolName); + } + } + + } + + private void evalModConOrDefAssignments() throws ConfigFileErrorException { + // val = [Counter] 7 + @SuppressWarnings("unchecked") + Hashtable<String, Vect> configCons = configAst.getModConstants(); + Enumeration<String> moduleNames = configCons.keys(); + while (moduleNames.hasMoreElements()) { + String moduleName = (String) moduleNames.nextElement(); + ModuleNode mNode = searchModule(moduleName); + Vect assignments = configCons.get(moduleName); + for (int i = 0; i < assignments.size(); i++) { + Vect assigment = (Vect) assignments.elementAt(i); + OpDefOrDeclNode opDefOrDeclNode = searchDefinitionOrConstant( + mNode, (String) assigment.elementAt(0)); + String symbolName = opDefOrDeclNode.getName().toString(); + Value symbolValue = (Value) assigment.elementAt(1); + TLAType symbolType = conGetType(assigment.elementAt(1)); + // System.out.println(symbolName + " " + symbolValue+ " " + + // symbolType); + if (opDefOrDeclNode instanceof OpDeclNode) { + // TODO test whether c is a extended constant + // Instanced constants have to overridden in the instance + // statement + OpDeclNode c = (OpDeclNode) opDefOrDeclNode; + ValueObj valueObj = new ValueObj(symbolValue, symbolType); + constantAssignments.put(c, valueObj); + /** + * if conValue is a model value and the name of value is the + * same as the name of constants, then the constant + * declaration in the resulting B machine disappears + **/ + if (symbolName.equals(symbolValue.toString())) { + bConstantList.remove(c); + } + } else { + OpDefNode def = (OpDefNode) opDefOrDeclNode; + ValueObj valueObj = new ValueObj(symbolValue, symbolType); + operatorAssignments.put(def, valueObj); + + if (symbolType instanceof SetType) { + if (((SetType) symbolType).getSubType() instanceof EnumType) { + operatorModelvalues.add(def); + } + } else if ((symbolType instanceof EnumType)) { + operatorModelvalues.add(def); + } + + } + } + } + } + + private void evalModConOrDefOverrides() throws ConfigFileErrorException { + // foo <- [Counter] bar or k <- [Counter] bar + @SuppressWarnings("unchecked") + Hashtable<String, Hashtable<String, String>> configCons = configAst + .getModOverrides(); + Enumeration<String> moduleNames = configCons.keys(); + while (moduleNames.hasMoreElements()) { + String moduleName = moduleNames.nextElement(); + ModuleNode mNode = searchModule(moduleName); + Hashtable<String, String> o = configCons.get(moduleName); + + Iterator<Map.Entry<String, String>> it = o.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry<String, String> entry = it.next(); + String left = entry.getKey(); + String right = entry.getValue(); + + OpDefNode rightDefNode = definitions.get(right); + if (rightDefNode == null) { + throw new ConfigFileErrorException( + "Invalid substitution for " + left + + ".\n Module does not contain definition " + + right + "."); + } + OpDefOrDeclNode opDefOrDeclNode = searchDefinitionOrConstant( + mNode, left); + + if (opDefOrDeclNode instanceof OpDefNode) { + // an operator is overridden by another operator + OpDefNode defNode = (OpDefNode) opDefOrDeclNode; + if (defNode.getArity() != rightDefNode.getArity()) { + throw new ConfigFileErrorException( + String.format( + "Invalid substitution for %s.\n Operator %s has %s arguments while %s has %s arguments.", + left, left, defNode.getArity(), right, + rightDefNode.getArity())); + } + operatorOverrideTable.put(defNode, rightDefNode); + } + + else { + InstanceNode[] instanceNodes = moduleNode.getInstances(); + for (int i = 0; i < instanceNodes.length; i++) { +// if (instanceNodes[i].getModule().getName().toString() +// .equals(moduleName)) { +// /* +// * A constant overridden in a instanced module make +// * no sence. Such a constant will be overridden by +// * the instance statement +// */ +// throw new ConfigFileErrorException( +// String.format( +// "Invalid substitution for constant '%s' of module '%s'.\n A Constant of an instanced module can not be overriden.", +// left, mNode.getName().toString())); +// } + } + // a constant is overridden by an operator + OpDeclNode conNode = (OpDeclNode) opDefOrDeclNode; + if (conNode.getArity() != rightDefNode.getArity()) { + throw new ConfigFileErrorException( + String.format( + "Invalid substitution for %s.\n Constant %s has %s arguments while %s has %s arguments.", + left, left, conNode.getArity(), right, + rightDefNode.getArity())); + } + bConstantList.remove(conNode); + constantOverrideTable.put(conNode, rightDefNode); + + } + } + + } + } + + public ModuleNode searchModule(String moduleName) + throws ConfigFileErrorException { + /* + * Search module in extended modules + */ + @SuppressWarnings("unchecked") + HashSet<ModuleNode> extendedModules = moduleNode.getExtendedModuleSet(); + for (Iterator<ModuleNode> iterator = extendedModules.iterator(); iterator + .hasNext();) { + ModuleNode m = (ModuleNode) iterator.next(); + if (m.getName().toString().equals(moduleName)) { + return m; + } + } + + /* + * search module in instanced modules + */ + + + OpDefNode [] defs = moduleNode.getOpDefs(); + for (int j = defs.length-1; j > 0; j--) { + OpDefNode def = null; + OpDefNode source = defs[j]; + while(def!=source){ + def = source; + source = def.getSource(); + ModuleNode m = def.getOriginallyDefinedInModuleNode(); + if(m.getName().toString().equals(moduleName)){ + return m; + } + } + } + throw new ConfigFileErrorException( + String.format( + "Module '%s' is not included in the specification.", + moduleName)); + } + + public OpDefOrDeclNode searchDefinitionOrConstant(ModuleNode n, + String defOrConName) throws ConfigFileErrorException { + for (int i = 0; i < n.getOpDefs().length; i++) { + if (n.getOpDefs()[i].getName().toString().equals(defOrConName)) { + return n.getOpDefs()[i]; + } + } + for (int i = 0; i < n.getConstantDecls().length; i++) { + if (n.getConstantDecls()[i].getName().toString() + .equals(defOrConName)) { + return n.getConstantDecls()[i]; + } + } + throw new ConfigFileErrorException( + "Module does not contain the symbol: " + defOrConName); + } + + private TLAType conGetType(Object o) throws ConfigFileErrorException { + if (o instanceof IntValue) { + + // IntValue iv = (IntValue) o; + return IntType.getInstance(); + } else if (o.getClass().getName().equals("tlc2.value.SetEnumValue")) { + SetEnumValue set = (SetEnumValue) o; + SetType t = new SetType(new Untyped()); + if (set.size() == 0) { + throw new ConfigFileErrorException( + "empty set is not permitted!"); + } + TLAType elemType; + + if (set.elems.elementAt(0).getClass().getName() + .equals("tlc2.value.ModelValue")) { + EnumType e = new EnumType(new ArrayList<String>()); + for (int i = 0; i < set.size(); i++) { + if (set.elems.elementAt(i).getClass().getName() + .equals("tlc2.value.ModelValue")) { + String mv = ((ModelValue) set.elems.elementAt(i)) + .toString(); + if (!enumeratedSet.contains(mv)) { + enumeratedSet.add(mv); + e.modelvalues.add(mv); + } else { + e.modelvalues.add(mv); + EnumType e2 = enumeratedTypes.get(mv); + try { + e = e2.unify(e2); + } catch (UnificationException exception) { + } + } + + } else { + throw new ConfigFileErrorException( + "Elements of the set must have the same type: " + + o); + } + } + Iterator<String> it = e.modelvalues.iterator(); + while (it.hasNext()) { + enumeratedTypes.put(it.next(), e); + } + elemType = e; + } else { + elemType = conGetType(set.elems.elementAt(0)); + for (int i = 1; i < set.size(); i++) { + elemType = conGetType(set.elems.elementAt(i)); + // all Elements have the same Type? + if (!t.getSubType().compare(elemType)) { + throw new ConfigFileErrorException( + "Elements of the set must have the same type: " + + o); + } + } + } + t.setSubType(elemType); + return t; + + } else if (o.getClass().getName().equals("tlc2.value.ModelValue")) { + ModelValue mv = (ModelValue) o; + if (!enumeratedSet.contains(mv.toString())) { + enumeratedSet.add(mv.toString()); + ArrayList<String> temp = new ArrayList<String>(); + temp.add(mv.toString()); + EnumType e = new EnumType(temp); + enumeratedTypes.put(mv.toString(), e); + return e; + } else { + return enumeratedTypes.get(mv.toString()); + } + + } else if (o.getClass().getName().equals("tlc2.value.StringValue")) { + return StringType.getInstance(); + } else if (o.getClass().getName().equals("tlc2.value.BoolValue")) { + return BoolType.getInstance(); + } else { + throw new ConfigFileErrorException("Unkown ConstantType: " + o + + " " + o.getClass()); + } + } + + public OpDefNode getSpecNode() { + return specNode; + } + + public OpDefNode getNextNode() { + return nextNode; + } + + public OpDefNode getInitNode() { + return initNode; + } + + public Hashtable<OpDeclNode, OpDefNode> getConstantOverrideTable() { + return constantOverrideTable; + } + + public ArrayList<OpDefNode> getInvariants() { + return this.invariantNodeList; + } + + public Hashtable<OpDeclNode, ValueObj> getConstantAssignments() { + return this.constantAssignments; + } + + public Hashtable<OpDefNode, ValueObj> getOperatorAssignments() { + return this.operatorAssignments; + } + + public ArrayList<OpDeclNode> getbConstantList() { + return bConstantList; + } + + public Hashtable<OpDefNode, OpDefNode> getOperatorOverrideTable() { + return operatorOverrideTable; + } + + public ArrayList<String> getEnumerationSet() { + return this.enumeratedSet; + } + + public ArrayList<OpDefNode> getOperatorModelvalues(){ + return this.operatorModelvalues; + } +} diff --git a/src/main/java/de/tla2b/config/ModuleOverrider.java b/src/main/java/de/tla2b/config/ModuleOverrider.java new file mode 100644 index 0000000000000000000000000000000000000000..e344f8d70fd12964749248ec2ddd35d9667b0608 --- /dev/null +++ b/src/main/java/de/tla2b/config/ModuleOverrider.java @@ -0,0 +1,229 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.config; + +import java.util.Hashtable; + +import tla2sany.semantic.ASTConstants; +import tla2sany.semantic.AbortException; +import tla2sany.semantic.AssumeNode; +import tla2sany.semantic.ExprNode; +import tla2sany.semantic.ExprOrOpArgNode; +import tla2sany.semantic.LetInNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.SymbolNode; +import tlc2.tool.BuiltInOPs; + +public class ModuleOverrider extends BuiltInOPs implements ASTConstants { + + private ModuleNode moduleNode; + private Hashtable<OpDeclNode, OpDefNode> constantOverrideTable; + private Hashtable<OpDefNode, OpDefNode> operatorOverrideTable; + private Hashtable<OpDefNode, ValueObj> operatorAssignments; + + /** + * @param constantOverrideTable + * @param operatorOverrideTable + */ + public ModuleOverrider(ModuleNode moduleNode, + Hashtable<OpDeclNode, OpDefNode> constantOverrideTable, + Hashtable<OpDefNode, OpDefNode> operatorOverrideTable, + Hashtable<OpDefNode, ValueObj> operatorAssignments) { + this.moduleNode = moduleNode; + this.constantOverrideTable = constantOverrideTable; + this.operatorOverrideTable = operatorOverrideTable; + this.operatorAssignments = operatorAssignments; + } + + /** + * @param moduleNode2 + * @param conEval + */ + public ModuleOverrider(ModuleNode moduleNode, ConfigfileEvaluator conEval) { + this.moduleNode = moduleNode; + this.constantOverrideTable = conEval.getConstantOverrideTable(); + this.operatorOverrideTable = conEval.getOperatorOverrideTable(); + this.operatorAssignments = conEval.getOperatorAssignments(); + } + + public void start() { + OpDefNode[] defs = moduleNode.getOpDefs(); + for (int i = 0; i < defs.length; i++) { + OpDefNode def = defs[i]; + if (operatorAssignments.containsKey(def)) { + ExprNode oldExpr = def.getBody(); + TLCValueNode valueNode; + try { + valueNode = new TLCValueNode(operatorAssignments.get(def), + oldExpr.getTreeNode()); + } catch (AbortException e) { + throw new RuntimeException(); + } + def.setBody(valueNode); + } else if (operatorAssignments.containsKey(def.getSource())) { + ExprNode oldExpr = def.getBody(); + TLCValueNode valueNode; + try { + valueNode = new TLCValueNode(operatorAssignments.get(def + .getSource()), oldExpr.getTreeNode()); + } catch (AbortException e) { + throw new RuntimeException(); + } + def.setBody(valueNode); + } + + } + + for (int i = 0; i < defs.length; i++) { + OpApplNode res = visitExprNode(defs[i].getBody()); + if (res != null) { + defs[i].setBody(res); + } + } + + AssumeNode[] assumes = moduleNode.getAssumptions(); + for (int i = 0; i < assumes.length; i++) { + AssumeNode assume = assumes[i]; + OpApplNode res = visitExprNode(assume.getAssume()); + if (res != null) { + + AssumeNode newAssume = new AssumeNode(assume.stn, res, null, + null); + assumes[i] = newAssume; + } + } + } + + private OpApplNode visitExprOrOpArgNode(ExprOrOpArgNode n) { + if (n instanceof ExprNode) { + + return visitExprNode((ExprNode) n); + } else { + throw new RuntimeException("OpArgNode not implemented jet"); + } + } + + /** + * @param body + */ + private OpApplNode visitExprNode(ExprNode n) { + + switch (n.getKind()) { + case OpApplKind: + return (OpApplNode) visitOpApplNode((OpApplNode) n); + + case StringKind: + case AtNodeKind: // @ + case NumeralKind: { + return null; + } + + case LetInKind: { + LetInNode l = (LetInNode) n; + for (int i = 0; i < l.getLets().length; i++) { + visitExprNode(l.getLets()[i].getBody()); + } + + OpApplNode res = visitExprNode(l.getBody()); + if (res != null) { + throw new RuntimeException(); + } + return null; + } + } + return null; + } + + /** + * @param n + */ + private OpApplNode visitOpApplNode(OpApplNode n) { + SymbolNode s = n.getOperator(); + switch (s.getKind()) { + case ConstantDeclKind: { + if (constantOverrideTable.containsKey(s)) { + SymbolNode newOperator = constantOverrideTable.get(s); + OpApplNode newNode = null; + try { + newNode = new OpApplNode(newOperator, n.getArgs(), + n.getTreeNode(), null); + } catch (AbortException e) { + throw new RuntimeException(); + } + for (int i = 0; i < n.getArgs().length; i++) { + if (n.getArgs()[i] != null) { + OpApplNode res = visitExprOrOpArgNode(n.getArgs()[i]); + if (res != null) { + n.getArgs()[i] = res; + } + } + + } + // n.setOperator(constantOverrideTable.get(s)); + return newNode; + } + break; + + } + case FormalParamKind: // Params are not global in the modul + case VariableDeclKind: // TODO try to override variable + break; + + case BuiltInKind:// Buildin operator can not be overridden by in the + // configuration file + ExprNode[] ins = n.getBdedQuantBounds(); + for (int i = 0; i < ins.length; i++) { + + OpApplNode res = visitExprOrOpArgNode(ins[i]); + if (res != null) { + ins[i] = res; + } + } + break; + + case UserDefinedOpKind: { + if (operatorOverrideTable.containsKey(s)) { + SymbolNode newOperator = operatorOverrideTable.get(s); + OpApplNode newNode = null; + OpDefNode def = (OpDefNode) n.getOperator(); + try { + newNode = new OpApplNode(newOperator, n.getArgs(), + n.getTreeNode(), def.getOriginallyDefinedInModuleNode()); + } catch (AbortException e) { + e.printStackTrace(); + } + + for (int i = 0; i < n.getArgs().length; i++) { + if (n.getArgs()[i] != null) { + OpApplNode res = visitExprOrOpArgNode(n.getArgs()[i]); + if (res != null) { + n.getArgs()[i] = res; + } + } + + } + // n.setOperator(constantOverrideTable.get(s)); + return newNode; + } + break; + } + } + + for (int i = 0; i < n.getArgs().length; i++) { + if (n.getArgs()[i] != null) { + OpApplNode res = visitExprOrOpArgNode(n.getArgs()[i]); + if (res != null) { + n.getArgs()[i] = res; + } + } + + } + return null; + } + +} diff --git a/src/main/java/de/tla2b/config/TLCValueNode.java b/src/main/java/de/tla2b/config/TLCValueNode.java new file mode 100644 index 0000000000000000000000000000000000000000..7f47a062423b0f1e7a30e21812e2f0f6fa836db1 --- /dev/null +++ b/src/main/java/de/tla2b/config/TLCValueNode.java @@ -0,0 +1,43 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.config; + +import de.tla2b.global.TranslationGlobals; +import de.tla2b.types.TLAType; +import tla2sany.semantic.AbortException; +import tla2sany.semantic.NumeralNode; +import tla2sany.st.TreeNode; +import tlc2.value.Value; + +public class TLCValueNode extends NumeralNode implements TranslationGlobals { + + private Value value; + private TLAType type; + + /** + * @param kind + * @param stn + * @throws AbortException + */ + public TLCValueNode(ValueObj valObj, TreeNode stn) throws AbortException { + super("1337", stn); + this.value = valObj.getValue(); + this.type = valObj.getType(); + } + + public String toString2() { + return "\n*TLCValueNode: Value: '" + + value.toString() + "'"; + + } + + public TLAType getType() { + return type; + } + + public Value getValue() { + return value; + } +} diff --git a/src/main/java/de/tla2b/config/ValueObj.java b/src/main/java/de/tla2b/config/ValueObj.java new file mode 100644 index 0000000000000000000000000000000000000000..668add56ef239c479dbda0aa241520f8daa04e27 --- /dev/null +++ b/src/main/java/de/tla2b/config/ValueObj.java @@ -0,0 +1,35 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.config; + +import de.tla2b.types.TLAType; +import tlc2.value.Value; + +public class ValueObj { + private Value value; + private TLAType type; + + public ValueObj(Value value, TLAType t) { + this.value = value; + this.type = t; + } + + public Value getValue() { + return value; + } + + public void setValue(Value value) { + this.value = value; + } + + public void setType(TLAType type) { + this.type = type; + } + + public TLAType getType(){ + return type; + } + +} diff --git a/src/main/java/de/tla2b/exceptions/ConfigFileErrorException.java b/src/main/java/de/tla2b/exceptions/ConfigFileErrorException.java new file mode 100644 index 0000000000000000000000000000000000000000..e3f61bf965f63be772d2b10652b9644c24af90d8 --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/ConfigFileErrorException.java @@ -0,0 +1,10 @@ +package de.tla2b.exceptions; + + +@SuppressWarnings("serial") +public class ConfigFileErrorException extends TLA2BException{ + + public ConfigFileErrorException(String s) { + super(s); + } +} diff --git a/src/main/java/de/tla2b/exceptions/FrontEndException.java b/src/main/java/de/tla2b/exceptions/FrontEndException.java new file mode 100644 index 0000000000000000000000000000000000000000..ffca417cadc710e48e22fe18c115a7c6db95ef04 --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/FrontEndException.java @@ -0,0 +1,17 @@ +package de.tla2b.exceptions; + +import tla2sany.modanalyzer.SpecObj; + +@SuppressWarnings("serial") +public class FrontEndException extends TLA2BException{ + + public SpecObj spec; + public FrontEndException(String e){ + super(e); + } + + public FrontEndException(String string, SpecObj spec) { + super(string); + this.spec = spec; + } +} diff --git a/src/main/java/de/tla2b/exceptions/ModuleErrorException.java b/src/main/java/de/tla2b/exceptions/ModuleErrorException.java new file mode 100644 index 0000000000000000000000000000000000000000..ac91a246218bd77be479def32846c1479d292c67 --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/ModuleErrorException.java @@ -0,0 +1,10 @@ +package de.tla2b.exceptions; + + +@SuppressWarnings("serial") +public class ModuleErrorException extends TLA2BException{ + public ModuleErrorException(String e){ + super(e); + } + +} diff --git a/src/main/java/de/tla2b/exceptions/NotImplementedException.java b/src/main/java/de/tla2b/exceptions/NotImplementedException.java new file mode 100644 index 0000000000000000000000000000000000000000..d386450ccf274b3f2957468d126e0efbba697fef --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/NotImplementedException.java @@ -0,0 +1,10 @@ +package de.tla2b.exceptions; + + +@SuppressWarnings("serial") +public class NotImplementedException extends TLA2BException { + public NotImplementedException(String e){ + super(e); + } + +} diff --git a/src/main/java/de/tla2b/exceptions/SemanticErrorException.java b/src/main/java/de/tla2b/exceptions/SemanticErrorException.java new file mode 100644 index 0000000000000000000000000000000000000000..6af42f002872b1d925d7710e362819ba0bc9be7c --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/SemanticErrorException.java @@ -0,0 +1,14 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.exceptions; + +@SuppressWarnings("serial") +public class SemanticErrorException extends TLA2BException { + + public SemanticErrorException(String e){ + super(e); + } + +} diff --git a/src/main/java/de/tla2b/exceptions/TLA2BException.java b/src/main/java/de/tla2b/exceptions/TLA2BException.java new file mode 100644 index 0000000000000000000000000000000000000000..edb67f65d4bd0439e6334e19b0c0c04491777225 --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/TLA2BException.java @@ -0,0 +1,9 @@ +package de.tla2b.exceptions; + +@SuppressWarnings("serial") +public abstract class TLA2BException extends Exception{ + + public TLA2BException(String e){ + super(e); + } +} diff --git a/src/main/java/de/tla2b/exceptions/TLA2BIOException.java b/src/main/java/de/tla2b/exceptions/TLA2BIOException.java new file mode 100644 index 0000000000000000000000000000000000000000..f8541148e9d3ca58c627d4e292dca11562ea5a7a --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/TLA2BIOException.java @@ -0,0 +1,10 @@ +package de.tla2b.exceptions; + +@SuppressWarnings("serial") +public class TLA2BIOException extends TLA2BException { + + + public TLA2BIOException(String e){ + super(e); + } +} diff --git a/src/main/java/de/tla2b/exceptions/TypeErrorException.java b/src/main/java/de/tla2b/exceptions/TypeErrorException.java new file mode 100644 index 0000000000000000000000000000000000000000..cea021a7de097285f2208fd5edbe1e1cccd56514 --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/TypeErrorException.java @@ -0,0 +1,11 @@ +package de.tla2b.exceptions; + + +@SuppressWarnings("serial") +public class TypeErrorException extends TLA2BException { + + + public TypeErrorException(String s) { + super(s); + } +} diff --git a/src/main/java/de/tla2b/exceptions/UnificationException.java b/src/main/java/de/tla2b/exceptions/UnificationException.java new file mode 100644 index 0000000000000000000000000000000000000000..710fbc9a332bc6bda869c639cf395e7bbccacf7e --- /dev/null +++ b/src/main/java/de/tla2b/exceptions/UnificationException.java @@ -0,0 +1,12 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.exceptions; +@SuppressWarnings("serial") +public class UnificationException extends TLA2BException{ + + public UnificationException() { + super(null); + } +} diff --git a/src/main/java/de/tla2b/global/BBuildIns.java b/src/main/java/de/tla2b/global/BBuildIns.java new file mode 100644 index 0000000000000000000000000000000000000000..7a6e238542e7611103b0710c1237cf2f61c05a4e --- /dev/null +++ b/src/main/java/de/tla2b/global/BBuildIns.java @@ -0,0 +1,126 @@ +package de.tla2b.global; + +import util.UniqueString; + +public interface BBuildIns { + public static final UniqueString OP_dotdot = UniqueString + .uniqueStringOf(".."); + public static final UniqueString OP_plus = UniqueString.uniqueStringOf("+"); + public static final UniqueString OP_minus = UniqueString + .uniqueStringOf("-"); + public static final UniqueString OP_times = UniqueString + .uniqueStringOf("*"); + public static final UniqueString OP_div = UniqueString + .uniqueStringOf("\\div"); + public static final UniqueString OP_mod = UniqueString.uniqueStringOf("%"); + public static final UniqueString OP_exp = UniqueString.uniqueStringOf("^"); + + public static final UniqueString OP_uminus = UniqueString + .uniqueStringOf("-."); + + public static final UniqueString OP_lt = UniqueString.uniqueStringOf("<"); + public static final UniqueString OP_leq = UniqueString + .uniqueStringOf("\\leq"); + public static final UniqueString OP_gt = UniqueString.uniqueStringOf(">"); + public static final UniqueString OP_geq = UniqueString + .uniqueStringOf("\\geq"); + + public static final UniqueString OP_nat = UniqueString + .uniqueStringOf("Nat"); + public static final UniqueString OP_int = UniqueString + .uniqueStringOf("Int"); + public static final UniqueString OP_bool = UniqueString + .uniqueStringOf("BOOLEAN"); + public static final UniqueString OP_true = UniqueString + .uniqueStringOf("TRUE"); + public static final UniqueString OP_false = UniqueString + .uniqueStringOf("FALSE"); + public static final UniqueString OP_string = UniqueString + .uniqueStringOf("STRING"); + + // Sets + public static final UniqueString OP_card = UniqueString + .uniqueStringOf("Cardinality"); + public static final UniqueString OP_finite = UniqueString + .uniqueStringOf("IsFiniteSet"); + + // Sequences + public static final UniqueString OP_len = UniqueString + .uniqueStringOf("Len"); + public static final UniqueString OP_append = UniqueString + .uniqueStringOf("Append"); + public static final UniqueString OP_seq = UniqueString + .uniqueStringOf("Seq"); + public static final UniqueString OP_head = UniqueString + .uniqueStringOf("Head"); + public static final UniqueString OP_tail = UniqueString + .uniqueStringOf("Tail"); + public static final UniqueString OP_subseq = UniqueString + .uniqueStringOf("SubSeq"); + public static final UniqueString OP_conc = UniqueString + .uniqueStringOf("\\o"); + + //TLA2B + public static final UniqueString OP_min = UniqueString + .uniqueStringOf("MinOfSet"); + public static final UniqueString OP_max = UniqueString + .uniqueStringOf("MaxOfSet"); + public static final UniqueString OP_setprod = UniqueString + .uniqueStringOf("SetProduct"); + public static final UniqueString OP_setsum = UniqueString + .uniqueStringOf("SetSummation"); + public static final UniqueString OP_permseq = UniqueString + .uniqueStringOf("PermutedSequences"); + + //BBuildIns + public static final UniqueString OP_pow1 = UniqueString + .uniqueStringOf("POW1"); + + + //Relations + public static final UniqueString OP_rel_inverse = UniqueString + .uniqueStringOf("rel_inverse"); + + public static final int B_OPCODE_dotdot = 1; + public static final int B_OPCODE_plus = 2; + public static final int B_OPCODE_minus = 3; + public static final int B_OPCODE_times = 4; + public static final int B_OPCODE_div = 5; + public static final int B_OPCODE_exp = 6; + public static final int B_OPCODE_uminus = 7; + public static final int B_OPCODE_mod = 8; + + public static final int B_OPCODE_lt = B_OPCODE_mod + 1; + public static final int B_OPCODE_leq = B_OPCODE_mod + 2; + public static final int B_OPCODE_gt = B_OPCODE_mod + 3; + public static final int B_OPCODE_geq = B_OPCODE_mod + 4; + + public static final int B_OPCODE_nat = B_OPCODE_geq + 1; + public static final int B_OPCODE_bool = B_OPCODE_geq + 2; + public static final int B_OPCODE_true = B_OPCODE_geq + 3; + public static final int B_OPCODE_false = B_OPCODE_geq + 4; + public static final int B_OPCODE_int = B_OPCODE_geq + 5; + public static final int B_OPCODE_string = B_OPCODE_geq + 6; + + public static final int B_OPCODE_finite = B_OPCODE_string + 1; + public static final int B_OPCODE_card = B_OPCODE_string + 2; + + public static final int B_OPCODE_len = B_OPCODE_card + 1; + public static final int B_OPCODE_append = B_OPCODE_card + 2; + public static final int B_OPCODE_seq = B_OPCODE_card + 3; + public static final int B_OPCODE_head = B_OPCODE_card + 4; + public static final int B_OPCODE_tail = B_OPCODE_card + 5; + public static final int B_OPCODE_subseq = B_OPCODE_card + 6; + public static final int B_OPCODE_conc = B_OPCODE_card + 7; + + public static final int B_OPCODE_min = B_OPCODE_conc + 1; + public static final int B_OPCODE_max = B_OPCODE_conc + 2; + public static final int B_OPCODE_setprod = B_OPCODE_conc + 3; + public static final int B_OPCODE_setsum = B_OPCODE_conc + 4; + public static final int B_OPCODE_permseq = B_OPCODE_conc + 5; + + public static final int B_OPCODE_pow1 = B_OPCODE_permseq + 1; + + + public static final int B_OPCODE_rel_inverse = B_OPCODE_pow1 + 1; +} diff --git a/src/main/java/de/tla2b/global/BBuiltInOPs.java b/src/main/java/de/tla2b/global/BBuiltInOPs.java new file mode 100644 index 0000000000000000000000000000000000000000..b3d770ae27bdcd51efd1f8d15d359d7e445d3736 --- /dev/null +++ b/src/main/java/de/tla2b/global/BBuiltInOPs.java @@ -0,0 +1,64 @@ +package de.tla2b.global; + + +import java.util.Hashtable; + +import util.UniqueString; + +public class BBuiltInOPs implements BBuildIns{ + private static Hashtable<UniqueString, Integer> B_Opcode_Table; + static { + B_Opcode_Table = new Hashtable<UniqueString, Integer>(); + B_Opcode_Table.put(OP_dotdot, B_OPCODE_dotdot); + B_Opcode_Table.put(OP_plus, B_OPCODE_plus); + B_Opcode_Table.put(OP_minus, B_OPCODE_minus); + B_Opcode_Table.put(OP_times, B_OPCODE_times); + B_Opcode_Table.put(OP_div, B_OPCODE_div); + B_Opcode_Table.put(OP_mod, B_OPCODE_mod); + B_Opcode_Table.put(OP_exp, B_OPCODE_exp); + B_Opcode_Table.put(OP_uminus, B_OPCODE_uminus); + + B_Opcode_Table.put(OP_lt, B_OPCODE_lt); + B_Opcode_Table.put(OP_leq, B_OPCODE_leq); + B_Opcode_Table.put(OP_gt, B_OPCODE_gt); + B_Opcode_Table.put(OP_geq, B_OPCODE_geq); + B_Opcode_Table.put(OP_bool, B_OPCODE_bool); + B_Opcode_Table.put(OP_true, B_OPCODE_true); + B_Opcode_Table.put(OP_false, B_OPCODE_false); + B_Opcode_Table.put(OP_nat, B_OPCODE_nat); + B_Opcode_Table.put(OP_int, B_OPCODE_int); + B_Opcode_Table.put(OP_string, B_OPCODE_string); + + B_Opcode_Table.put(OP_finite, B_OPCODE_finite); + B_Opcode_Table.put(OP_card, B_OPCODE_card); + + B_Opcode_Table.put(OP_len, B_OPCODE_len); + B_Opcode_Table.put(OP_append, B_OPCODE_append); + B_Opcode_Table.put(OP_seq, B_OPCODE_seq); + B_Opcode_Table.put(OP_head, B_OPCODE_head); + B_Opcode_Table.put(OP_tail, B_OPCODE_tail); + B_Opcode_Table.put(OP_subseq, B_OPCODE_subseq); + B_Opcode_Table.put(OP_conc, B_OPCODE_conc); + + B_Opcode_Table.put(OP_min, B_OPCODE_min); + B_Opcode_Table.put(OP_max, B_OPCODE_max); + B_Opcode_Table.put(OP_setprod, B_OPCODE_setprod); + B_Opcode_Table.put(OP_setsum, B_OPCODE_setsum); + B_Opcode_Table.put(OP_permseq, B_OPCODE_permseq); + + B_Opcode_Table.put(OP_pow1, B_OPCODE_pow1); + + //relations + B_Opcode_Table.put(OP_rel_inverse, B_OPCODE_rel_inverse); + + + } + + public static boolean contains(UniqueString s){ + return B_Opcode_Table.containsKey(s); + } + + public static int getOpcode(UniqueString s){ + return B_Opcode_Table.get(s); + } +} diff --git a/src/main/java/de/tla2b/global/Priorities.java b/src/main/java/de/tla2b/global/Priorities.java new file mode 100644 index 0000000000000000000000000000000000000000..bf3f23168d0ff0c7f543aaf23c300dd7e2991be3 --- /dev/null +++ b/src/main/java/de/tla2b/global/Priorities.java @@ -0,0 +1,76 @@ +package de.tla2b.global; + +public interface Priorities { + public static final int P_max = 300; + + public static final int P_record_acc = 250; + public static final int P_uminus = 210; + public static final int P_exp = 200; + + public static final int P_times = 190; + public static final int P_div = 190; + public static final int P_mod = 190; + + + + public static final int P_plus = 180; + public static final int P_minus = 180; + public static final int P_setdiff = 180; + + public static final int P_dotdot = 170; + + public static final int P_maplet = 160; + + public static final int P_take_first = 160; + public static final int P_drop_last = 160; + public static final int P_conc = 160; + + public static final int P_intersect = 140; + public static final int P_union = 140; + + + public static final int P_append = 130; + + public static final int P_total_f = 125; + + public static final int P_comma = 115; + + + + public static final int P_rel_overriding = 90; + + public static final int P_in = 60; + public static final int P_notin = 60; + public static final int P_subseteq = 60; + + public static final int P_equals = 50; + public static final int P_noteq = 50; + public static final int P_gt = 50; + public static final int P_lt = 50; + public static final int P_leq = 50; + public static final int P_geq = 50; + + public static final int P_equiv = 60; + + public static final int P_and = 40; + public static final int P_or = 40; + + + public static final int P_implies = 30; + + public static final int P_min = 0; + + + + + + + + + + + + + + +} diff --git a/src/main/java/de/tla2b/global/TranslationGlobals.java b/src/main/java/de/tla2b/global/TranslationGlobals.java new file mode 100644 index 0000000000000000000000000000000000000000..3fcfb30e1e04f868efde550a4713b0acc5ed94c1 --- /dev/null +++ b/src/main/java/de/tla2b/global/TranslationGlobals.java @@ -0,0 +1,32 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.global; + +import java.util.ArrayList; +import java.util.Arrays; + +import tla2sany.semantic.FrontEnd; + +public interface TranslationGlobals { + final String VERSION = "1.0.7"; + + final int TLCValueKind = 100; + + final int USED = FrontEnd.getToolId(); + final int OVERRIDE_SUBSTITUTION_ID = 17; + final int CONSTANT_OBJECT = 18; + final int DEF_OBJECT = 19; + final int PRINT_DEFINITION = 11; + final int TYPE_ID = 5; + final int LET_PARAMS_ID = 13; + final int NEW_NAME = 20; + + final String CHOOSE = " CHOOSE(X) == \"a member of X\"; EXTERNAL_FUNCTION_CHOOSE(T) == (POW(T)-->T)"; + final String IF_THEN_ELSE = " IF_THEN_ELSE(P, a, b) == (%t_.(t_ = TRUE & P = TRUE | a )\\/%t_.(t_= TRUE & not(P= TRUE) | b ))(TRUE)"; + + final ArrayList<String> STANDARD_MODULES = new ArrayList<String>( + Arrays.asList(new String[] { "Naturals", "FiniteSets", "Integers", + "Sequences", "TLC", "Relations", "TLA2B", "BBuildIns" })); +} diff --git a/src/main/java/de/tla2b/pprint/AbstractExpressionPrinter.java b/src/main/java/de/tla2b/pprint/AbstractExpressionPrinter.java new file mode 100644 index 0000000000000000000000000000000000000000..78231d91570b2b7319b73ca9f2e91db907c0b46e --- /dev/null +++ b/src/main/java/de/tla2b/pprint/AbstractExpressionPrinter.java @@ -0,0 +1,1379 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.pprint; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.LinkedList; + +import de.tla2b.config.TLCValueNode; +import de.tla2b.global.BBuildIns; +import de.tla2b.global.BBuiltInOPs; +import de.tla2b.global.Priorities; +import de.tla2b.global.TranslationGlobals; +import de.tla2b.types.EnumType; +import de.tla2b.types.FunctionType; +import de.tla2b.types.IType; +import de.tla2b.types.SetType; +import de.tla2b.types.StructType; +import de.tla2b.types.TLAType; +import de.tla2b.types.TupleType; + +import tla2sany.semantic.ASTConstants; +import tla2sany.semantic.AtNode; +import tla2sany.semantic.ExprNode; +import tla2sany.semantic.ExprOrOpArgNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.LetInNode; +import tla2sany.semantic.NumeralNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.StringNode; +import tla2sany.semantic.SymbolNode; +import tlc2.tool.BuiltInOPs; + +public abstract class AbstractExpressionPrinter extends BuiltInOPs implements + ASTConstants, IType, BBuildIns, Priorities, TranslationGlobals { + // private int substitutionId = 10; + + final int NOBOOL = 0; + final int VALUE = 1; + final int PREDICATE = 2; + final int VALUEORPREDICATE = 3; + + protected ExprReturn visitExprOrOpArgNode(ExprOrOpArgNode n, DContext d, + int expected) { + if (n instanceof ExprNode) { + return visitExprNode((ExprNode) n, d, expected); + } else { + throw new RuntimeException("OpArgNode not implemented jet"); + } + } + + protected ExprReturn visitExprNode(ExprNode n, DContext d, int expected) { + StringBuilder out = new StringBuilder(); + switch (n.getKind()) { + case OpApplKind: + return visitOpApplNode((OpApplNode) n, d, expected); + + case NumeralKind: { + // this is hack to represent a TLCValue in abstract syntax tree of + // the module + if (n instanceof TLCValueNode) { + out.append(((TLCValueNode) n).getValue()); + return new ExprReturn(out); + } + out.append(((NumeralNode) n).val()); + return new ExprReturn(out); + } + + case StringKind: { + StringNode s = (StringNode) n; + out.append("\"" + s.getRep() + "\""); + return new ExprReturn(out); + } + + case LetInKind: { + LetInNode letInNode = (LetInNode) n; + return visitLetInNode(letInNode, d, expected); + + } + case AtNodeKind: { // @ + AtNode at = (AtNode) n; + String base = visitExprNode(at.getAtBase(), d, NOBOOL).out + .toString(); + TLAType t = (TLAType) at.getExceptRef().getToolObject(TYPE_ID); + + OpApplNode seq = at.getAtModifier(); + + LinkedList<ExprOrOpArgNode> list = new LinkedList<ExprOrOpArgNode>(); + for (int j = 0; j < seq.getArgs().length; j++) { + list.add(seq.getArgs()[j]); + } + out.append(base); + out.append(evalAtValue(list, t)); + return new ExprReturn(out); + } + case TLCValueKind: { + TLCValueNode val = (TLCValueNode) n; + return new ExprReturn(val.getValue().toString()); + } + + } + throw new RuntimeException(n.toString(2)); + } + + /** + * @param list + * @param t + */ + private StringBuilder evalAtValue(LinkedList<ExprOrOpArgNode> list, + TLAType t) { + StringBuilder sb = new StringBuilder(); + if (list.size() == 0) + return sb; + ExprOrOpArgNode first = list.poll(); + if (t instanceof StructType) { + StructType s = (StructType) t; + sb.append("'"); + String fieldName = ((StringNode) first).getRep().toString(); + sb.append(fieldName); + return sb.append(evalAtValue(list, s.getType(fieldName))); + } else { + FunctionType func = (FunctionType) t; + + TLAType range = func.getRange(); + sb.append("("); + + if (first instanceof OpApplNode + && ((OpApplNode) first).getOperator().getName().toString() + .equals("$Tuple")) { + OpApplNode domOpAppl = (OpApplNode) first; + for (int j = 0; j < domOpAppl.getArgs().length; j++) { + if (j != 0) { + sb.append(", "); + } + sb.append(visitExprOrOpArgNode(domOpAppl.getArgs()[j], + new DContext(), VALUE).out); + } + } else { + sb.append(visitExprOrOpArgNode(first, new DContext(), VALUE).out); + } + sb.append(")"); + return sb.append(evalAtValue(list, range)); + } + } + + protected ExprReturn visitLetInNode(LetInNode l, DContext d, int expected) { + for (int i = 0; i < l.getLets().length; i++) { + // do something + } + return visitExprNode(l.getBody(), d, VALUEORPREDICATE); + } + + private ExprReturn visitOpApplNode(OpApplNode n, DContext d, int expected) { + StringBuilder out = new StringBuilder(); + switch (n.getOperator().getKind()) { + case ConstantDeclKind: { + out.append(getPrintName(n.getOperator())); + if (expected == PREDICATE) { + out.append(" = TRUE"); + return new ExprReturn(out, P_equals); + } + return new ExprReturn(out); + } + case VariableDeclKind: { + out.append(getPrintName(n.getOperator())); + if (expected == PREDICATE) { + out.append(" = TRUE"); + return new ExprReturn(out, P_equals); + } + return new ExprReturn(out); + } + case BuiltInKind: + return evalBuiltInKind(n, d, expected); + + case FormalParamKind: { + return visitFormalParamNode(n, d, expected); + } + + case UserDefinedOpKind: { + return visitUserdefinedOp(n, d, expected); + } + + } + throw new RuntimeException(n.toString(2)); + } + + /** + * @param n + * @param d + * @param expected + * @return + */ + protected ExprReturn visitFormalParamNode(OpApplNode n, DContext d, + int expected) { + StringBuilder out = new StringBuilder(); + out.append(getPrintName(n.getOperator())); + if (expected == PREDICATE) { + out.append(" = TRUE"); + return new ExprReturn(out, P_equals); + } + return new ExprReturn(out); + } + + /** + * @param n + * @param d + * @param expected + * @return + */ + protected ExprReturn visitUserdefinedOp(OpApplNode n, DContext d, + int expected) { + StringBuilder out = new StringBuilder(); + OpDefNode def = (OpDefNode) n.getOperator(); + // Operator is a B built-in operator + if (BBuiltInOPs.contains(def.getName()) + && STANDARD_MODULES.contains(def.getSource() + .getOriginallyDefinedInModuleNode().getName() + .toString())) { + return evalBBuiltIns(n, d, expected); + } + + out.append(getPrintName(def)); + + if (n.getArgs().length > 0) { + out.append("("); + for (int i = 0; i < n.getArgs().length; i++) { + out.append(visitExprOrOpArgNode(n.getArgs()[i], d, VALUE).out); + if (i < n.getArgs().length - 1) { + out.append(", "); + } + } + out.append(")"); + + } + TLAType defType = (TLAType) n.getToolObject(TYPE_ID); + if (defType != null && defType.getKind() == BOOL) { + return makeBoolValue(out, expected, P_max); + } + return new ExprReturn(out); + } + + /** + * @param n + * @param d + * @param expected + * @return + */ + private ExprReturn evalBuiltInKind(OpApplNode n, DContext d, int expected) { + StringBuilder out = new StringBuilder(); + switch (getOpCode(n.getOperator().getName())) { + + /********************************************************************** + * equality and disequality: =, #, /= + **********************************************************************/ + case OPCODE_eq: { // = + out = evalOpMoreArgs(n, " = ", d, VALUE, P_equals); + return makeBoolValue(out, expected, P_equals); + } + + case OPCODE_noteq: // /= + { + out = evalOpMoreArgs(n, " /= ", d, VALUE, P_noteq); + return makeBoolValue(out, expected, P_noteq); + } + + /********************************************************************** + * Logic Operators + **********************************************************************/ + case OPCODE_cl: // $ConjList + { + for (int i = 0; i < n.getArgs().length; i++) { + if (i == 0) { + out.append(brackets( + visitExprOrOpArgNode(n.getArgs()[i], d, PREDICATE), + P_and, true)); + } else { + out.append("\n" + d.indent + " & "); + out.append(brackets( + visitExprOrOpArgNode(n.getArgs()[i], d, PREDICATE), + P_and, false)); + } + } + return makeBoolValue(out, expected, P_and); + } + case OPCODE_land: // \land + { + out = evalOpMoreArgs(n, " & ", d, PREDICATE, P_and); + return makeBoolValue(out, expected, P_and); + } + case OPCODE_dl: // $DisjList + { + for (int i = 0; i < n.getArgs().length; i++) { + if (i == 0) { + out.append(brackets( + visitExprOrOpArgNode(n.getArgs()[i], d, PREDICATE), + P_or, true)); + } else { + out.append("\n" + d.indent + " or "); + out.append(brackets( + visitExprOrOpArgNode(n.getArgs()[i], d, PREDICATE), + P_or, false)); + } + } + return makeBoolValue(out, expected, P_or); + } + + case OPCODE_lor: // \/ + { + out = evalOpMoreArgs(n, " or ", d, PREDICATE, P_or); + return makeBoolValue(out, expected, P_or); + } + case OPCODE_equiv: // \equiv + { + out = evalOpMoreArgs(n, " <=> ", d, PREDICATE, P_equiv); + return makeBoolValue(out, expected, P_equiv); + } + case OPCODE_implies: // => + { + out = evalOpMoreArgs(n, " => ", d, PREDICATE, P_implies); + return makeBoolValue(out, expected, P_implies); + } + + case OPCODE_lnot: { // \lnot + out.append("not("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, PREDICATE).out); + out.append(")"); + return makeBoolValue(out, expected, P_max); + } + + case OPCODE_be: { // \E x \in S : P + return evalBoundedQuantor(n, d, expected, "#"); + } + + case OPCODE_bf: { // \A x \in S : P + return evalBoundedQuantor(n, d, expected, "!"); + } + + /********************************************************************** + * Set Operators + **********************************************************************/ + case OPCODE_se: // SetEnumeration {..} + { + out.append("{"); + out.append(evalOpMoreArgs(n, ", ", d, VALUE, P_comma)); + out.append("}"); + return new ExprReturn(out, P_max); + } + + case OPCODE_in: // \in + { + ExprReturn r = visitExprOrOpArgNode(n.getArgs()[0], d, VALUE); + out.append(brackets(r, P_in, true)); + out.append(" : "); + r = visitExprOrOpArgNode(n.getArgs()[1], d, NOBOOL); + out.append(brackets(r, P_in, false)); + return makeBoolValue(out, expected, P_in); + } + case OPCODE_notin: // \notin + { + ExprReturn r = visitExprOrOpArgNode(n.getArgs()[0], d, VALUE); + out.append(brackets(r, P_notin, true)); + out.append(" /: "); + r = visitExprOrOpArgNode(n.getArgs()[1], d, NOBOOL); + out.append(brackets(r, P_notin, false)); + return makeBoolValue(out, expected, P_notin); + } + + case OPCODE_setdiff: // set difference + { + out = evalOpMoreArgs(n, " - ", d, NOBOOL, P_setdiff); + return new ExprReturn(out, P_setdiff); + } + + case OPCODE_cup: // set union + { + out = evalOpMoreArgs(n, " \\/ ", d, NOBOOL, P_union); + return new ExprReturn(out, P_union); + } + + case OPCODE_cap: // set intersection + { + out = evalOpMoreArgs(n, " /\\ ", d, NOBOOL, P_intersect); + return new ExprReturn(out, P_intersect); + } + + case OPCODE_subseteq: // \subseteq {1,2} <: {1,2,3} + { + out = evalOpMoreArgs(n, " <: ", d, NOBOOL, P_subseteq); + return makeBoolValue(out, expected, P_subseteq); + } + + case OPCODE_subset: // SUBSET + { + out.append("POW("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + case OPCODE_union: // Union - Union{{1},{2}} + { + out.append("union("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + /********************************************************************** + * Set Constructor + **********************************************************************/ + case OPCODE_sso: { // $SubsetOf Represents {x \in S : P} + // TODO tuple with more than 2 arguments + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ExprNode[] bounds = n.getBdedQuantBounds(); + + StringBuilder temp = new StringBuilder(); + if (params[0].length > 0) { + temp.append("("); + for (int j = 0; j < params[0].length; j++) { + FormalParamNode p = params[0][j]; + temp.append(getPrintName(p)); + if (j < params[0].length - 1) + temp.append(", "); + } + temp.append(")"); + } else { + FormalParamNode p = n.getBdedQuantSymbolLists()[0][0]; + temp.append(getPrintName(p)); + } + + out.append("{"); + out.append(temp); + out.append("|"); + out.append(temp); + out.append(" : "); + ExprNode in = n.getBdedQuantBounds()[0]; + out.append(visitExprNode(in, d, NOBOOL).out); + out.append(" & "); + out.append(brackets( + visitExprOrOpArgNode(n.getArgs()[0], d, PREDICATE), P_and, + false)); + out.append("}"); + return new ExprReturn(out); + } + + case OPCODE_soa: { // $SetOfAll Represents {e : p1 \in S, p2,p3 \in S2} + out.append("{t_|#"); + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ExprNode[] bounds = n.getBdedQuantBounds(); + for (int i = 0; i < bounds.length; i++) { + for (int j = 0; j < params[i].length; j++) { + FormalParamNode p = params[i][j]; + out.append(getPrintName(p)); + if (i < bounds.length - 1 || j < params[i].length - 1) + out.append(", "); + } + } + out.append(".("); + out.append(visitBounded(n, d)); + out.append(" & t_ = "); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, VALUE).out); + out.append(")}"); + return new ExprReturn(out); + } + /*********************************************************************** + * Tuple: Tuple as Function 1..n to Set (Sequence) + ***********************************************************************/ + case OPCODE_tup: { // $Tuple + TLAType t = (TLAType) n.getToolObject(TYPE_ID); + if (t instanceof TupleType) { + out.append("("); + out.append(evalOpMoreArgs(n, ", ", d, VALUE, P_comma)); + out.append(")"); + } else { + out.append("["); + out.append(evalOpMoreArgs(n, ", ", d, VALUE, P_comma)); + out.append("]"); + } + return new ExprReturn(out); + } + + /*********************************************************************** + * Cartesian Product: A \X B + ***********************************************************************/ + case OPCODE_cp: { // $CartesianProd A \X B \X C + out.append(evalOpMoreArgs(n, "*", d, VALUE, P_times)); + return new ExprReturn(out, P_times); + } + + /*********************************************************************** + * Functions + ***********************************************************************/ + case OPCODE_nrfs: + case OPCODE_fc: // Represents [x \in S |-> e]. + case OPCODE_rfs: { + out.append("%"); + FormalParamNode[][] vars = n.getBdedQuantSymbolLists(); + for (int i = 0; i < vars.length; i++) { + for (int j = 0; j < vars[i].length; j++) { + out.append(getPrintName(vars[i][j])); + if (j < vars[i].length - 1) { + out.append(","); + } + } + if (i < vars.length - 1) { + out.append(","); + } + } + out.append(".("); + out.append(visitBounded(n, d)); + out.append("| "); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, VALUE).out); + out.append(")"); + return new ExprReturn(out); + } + + case OPCODE_fa: { // f[1] + out.append(brackets( + visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL), P_max, + true)); + out.append("("); + ExprOrOpArgNode dom = n.getArgs()[1]; + if (dom instanceof OpApplNode + && ((OpApplNode) dom).getOperator().getName().toString() + .equals("$Tuple")) { + OpApplNode domOpAppl = (OpApplNode) dom; + for (int i = 0; i < domOpAppl.getArgs().length; i++) { + if (i != 0) + out.append(", "); + out.append(visitExprOrOpArgNode(domOpAppl.getArgs()[i], d, + VALUE).out); + } + } else { + out.append(visitExprOrOpArgNode(dom, d, VALUE).out); + } + out.append(")"); + if (expected == PREDICATE) { + out.append(" = TRUE"); + return new ExprReturn(out, P_equals); + } + return new ExprReturn(out); + } + + case OPCODE_domain: + out.append("dom("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + + case OPCODE_sof: // [ A -> B] + { + out.append(evalOpMoreArgs(n, " --> ", d, NOBOOL, P_total_f)); + return new ExprReturn(out, P_total_f); + } + + /********************************************************************** + * Except + **********************************************************************/ + case OPCODE_exc: // Except + { + TLAType t = (TLAType) n.getToolObject(TYPE_ID); + String oldRecOrFunc = visitExprOrOpArgNode(n.getArgs()[0], d, + NOBOOL).out.toString(); + + if (t.getKind() == STRUCT) { + StructType structType = (StructType) t; + + Hashtable<String, String> temp = new Hashtable<String, String>(); + for (int i = 1; i < n.getArgs().length; i++) { + OpApplNode pair = (OpApplNode) n.getArgs()[i]; + ExprOrOpArgNode first = pair.getArgs()[0]; + ExprOrOpArgNode second = pair.getArgs()[1]; + OpApplNode seq = (OpApplNode) first; + + String val = visitExprOrOpArgNode((ExprOrOpArgNode) second, + d, VALUE).out.toString(); + + LinkedList<ExprOrOpArgNode> list = new LinkedList<ExprOrOpArgNode>(); + for (int j = 0; j < seq.getArgs().length; j++) { + list.add(seq.getArgs()[j]); + } + + StringNode s = (StringNode) list.poll(); + String fieldName = s.getRep().toString(); + + String res = evalExceptValue(list, + structType.getType(fieldName), val, oldRecOrFunc + + "'" + fieldName); + temp.put(fieldName, res); + } + + out.append("rec("); + StructType st = (StructType) t; + for (int i = 0; i < st.getFields().size(); i++) { + String fieldName = st.getFields().get(i); + out.append(fieldName); + out.append(" : "); + String value = temp.get(fieldName); + if (value == null) { + value = oldRecOrFunc + "'" + fieldName; + } + out.append(value); + + if (i < st.getFields().size() - 1) { + out.append(", "); + } + } + out.append(")"); + return new ExprReturn(out); + + } else { + // function + FunctionType func = (FunctionType) t; + + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(" <+ {"); + for (int i = 1; i < n.getArgs().length; i++) { + OpApplNode pair = (OpApplNode) n.getArgs()[i]; + OpApplNode domSeq = (OpApplNode) pair.getArgs()[0]; + ExprOrOpArgNode domExpr = domSeq.getArgs()[0]; + StringBuilder dom = new StringBuilder(); + if (domExpr instanceof OpApplNode + && ((OpApplNode) domExpr).getOperator().getName() + .toString().equals("$Tuple")) { + OpApplNode domOpAppl = (OpApplNode) domExpr; + dom.append("("); + for (int j = 0; j < domOpAppl.getArgs().length; j++) { + if (j != 0) { + dom.append(", "); + } + dom.append(visitExprOrOpArgNode( + domOpAppl.getArgs()[j], d, VALUE).out); + } + dom.append(")"); + } else { + dom.append(visitExprOrOpArgNode(pair.getArgs()[0], d, + VALUE).out); + } + out.append(dom); + + out.append(" |-> "); + + ExprOrOpArgNode first = pair.getArgs()[0]; + ExprOrOpArgNode second = pair.getArgs()[1]; + OpApplNode seq = (OpApplNode) first; + + + String val = brackets(visitExprOrOpArgNode((ExprOrOpArgNode) second, + d, VALUE), P_maplet, false).toString(); + //String val = visitExprOrOpArgNode((ExprOrOpArgNode) second, + // d, VALUE).out.toString(); + + LinkedList<ExprOrOpArgNode> list = new LinkedList<ExprOrOpArgNode>(); + for (int j = 0; j < seq.getArgs().length; j++) { + list.add(seq.getArgs()[j]); + } + list.poll(); + String res = evalExceptValue(list, func.getRange(), val, + oldRecOrFunc + "(" + dom + ")"); + out.append(res); + // out.append(brackets( + // visitExprOrOpArgNode(pair.getArgs()[1], d, VALUE), + // P_maplet, false)); + if (i < n.getArgs().length - 1) { + out.append(", "); + } + } + out.append("}"); + return new ExprReturn(out, P_rel_overriding); + + } + } + + /*********************************************************************** + * Records + ***********************************************************************/ + case OPCODE_sor: { // $SetOfRcds [L1 : e1, L2 : e2] + SetType pow = (SetType) n.getToolObject(TYPE_ID); + StructType struct = (StructType) pow.getSubType(); + Hashtable<String, StringBuilder> pairs = new Hashtable<String, StringBuilder>(); + ExprOrOpArgNode[] args = n.getArgs(); + for (int i = 0; i < args.length; i++) { + OpApplNode pair = (OpApplNode) args[i]; + StringNode stringNode = (StringNode) pair.getArgs()[0]; + pairs.put(stringNode.getRep().toString(), + visitExprOrOpArgNode(pair.getArgs()[1], d, VALUE).out); + } + out.append("struct("); + for (int i = 0; i < struct.getFields().size(); i++) { + String fieldName = struct.getFields().get(i); + out.append(fieldName); + out.append(" : "); + if (pairs.containsKey(fieldName)) { + out.append(pairs.get(fieldName)); + } else { + out.append(struct.getType(fieldName)); + } + if (i < struct.getFields().size() - 1) + out.append(","); + } + out.append(")"); + return new ExprReturn(out, P_max); + } + + case OPCODE_rc: { // [h_1 |-> 1, h_2 |-> 2] + StructType struct = (StructType) n.getToolObject(TYPE_ID); + Hashtable<String, StringBuilder> pairs = new Hashtable<String, StringBuilder>(); + ExprOrOpArgNode[] args = n.getArgs(); + for (int i = 0; i < args.length; i++) { + OpApplNode pair = (OpApplNode) args[i]; + StringNode stringNode = (StringNode) pair.getArgs()[0]; + pairs.put(stringNode.getRep().toString(), + visitExprOrOpArgNode(pair.getArgs()[1], d, VALUE).out); + } + out.append("rec("); + for (int i = 0; i < struct.getFields().size(); i++) { + String fieldName = struct.getFields().get(i); + out.append(fieldName); + out.append(" : "); + if (pairs.containsKey(fieldName)) { + out.append(pairs.get(fieldName)); + } else { + out.append(getDummy(struct.getType(fieldName))); + } + if (i < struct.getFields().size() - 1) + out.append(","); + } + out.append(")"); + return new ExprReturn(out, P_max); + } + + case OPCODE_rs: { // $RcdSelect r.c + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append("'"); + StringNode stringNode = (StringNode) n.getArgs()[1]; + out.append(stringNode.getRep().toString()); + if (expected == PREDICATE) { + out.append(" = TRUE"); + return new ExprReturn(out, P_equals); + } + return new ExprReturn(out, P_record_acc); + } + + /*********************************************************************** + * miscellaneous constructs + ***********************************************************************/ + case OPCODE_ite: // IF THEN ELSE + { + return evalIfThenElse(n, d, expected); + + } + + case OPCODE_case: { // CASE p1 -> e1 [] p2 -> e2 + out.append("("); + StringBuilder all = new StringBuilder(); + for (int i = 0; i < n.getArgs().length; i++) { + OpApplNode pair = (OpApplNode) n.getArgs()[i]; + out.append("%t_.(t_ = 0 & "); + if (pair.getArgs()[0] == null) { + out.append("not(" + all + ")"); + } else { + ExprReturn p = visitExprOrOpArgNode(pair.getArgs()[0], d, + PREDICATE); + if (i != 0) { + all.append(" or "); + } + all.append(brackets(p, P_or, i == 0)); + out.append(brackets(p, P_and, false)); + } + out.append(" | "); + out.append(visitExprOrOpArgNode(pair.getArgs()[1], d, VALUE).out); + out.append(")"); + if (i < n.getArgs().length - 1) { + out.append(" \\/ "); + } + } + out.append(")(0)"); + return new ExprReturn(out); + } + + case OPCODE_bc: { // CHOOSE x \in S: P + out.append("CHOOSE({"); + FormalParamNode x = n.getBdedQuantSymbolLists()[0][0]; + out.append(getPrintName(x)); + out.append("|"); + out.append(getPrintName(x)); + out.append(" : "); + ExprNode in = n.getBdedQuantBounds()[0]; + out.append(visitExprNode(in, d, NOBOOL).out); + out.append(" & "); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, PREDICATE).out); + out.append("})"); + return new ExprReturn(out); + + } + + /*********************************************************************** + * UNCHANGED + ************************************************************************/ + case OPCODE_unchanged: + Boolean b = (Boolean) n.getToolObject(USED); + if (b != null) { + return new ExprReturn("TRUE = TRUE", P_equals); + } + OpApplNode k = (OpApplNode) n.getArgs()[0]; + if (k.getOperator().getKind() == VariableDeclKind) { + String name = k.getOperator().getName().toString(); + out.append(name + "_n = " + name); + } else { + // Tuple + for (int i = 0; i < k.getArgs().length; i++) { + String name = visitExprOrOpArgNode(k.getArgs()[i], d, VALUE).out + .toString(); + out.append(name + "_n = " + name); + if (i < k.getArgs().length - 1) { + out.append(" & "); + } + } + } + return new ExprReturn(out); + + /*********************************************************************** + * Prime + ***********************************************************************/ + case OPCODE_prime: // prime + { + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, VALUE).out); + out.append("_n"); + return new ExprReturn(out); + } + + /*********************************************************************** + * Sany internal + ***********************************************************************/ + case OPCODE_seq: // ! + { + return visitExprOrOpArgNode(n.getArgs()[0], d, expected); + } + + /*********************************************************************** + * no TLA+ Built-ins + ***********************************************************************/ + case 0: { + return evalBBuiltIns(n, d, expected); + } + + case OPCODE_sa: // []_ + case OPCODE_box: // [] + case OPCODE_diamond: // <> + case OPCODE_wf: // weak fairness + { + throw new RuntimeException("Not supported operator: " + + n.toString(2)); + } + + } + throw new RuntimeException(n.toString(2)); + } + + /** + * @param list + * @param type + * @param string + * @return + */ + private String evalExceptValue(LinkedList<ExprOrOpArgNode> list, + TLAType type, String val, String prefix) { + StringBuilder sb = new StringBuilder(); + ExprOrOpArgNode head = list.poll(); + if (head == null) { + return val; + } + if (type.getKind() == STRUCT) { + StructType structType = (StructType) type; + String field = ((StringNode) head).getRep().toString(); + + ArrayList<String> fields = structType.getFields(); + sb.append("rec("); + + for (int i = 0; i < fields.size(); i++) { + String currentField = fields.get(i); + sb.append(currentField); + sb.append(" : "); + if (currentField.equals(field)) { + String value; + if (list.size() > 0) { + value = evalExceptValue(list, + structType.getType(currentField), val, prefix + + "'" + currentField); + } else { + value = val; + } + + sb.append(value); + } else { + sb.append(prefix + "'" + currentField); + } + if (i < fields.size() - 1) { + sb.append(", "); + } + } + sb.append(")"); + + } else { + FunctionType func = (FunctionType) type; + sb.append("("); + sb.append(prefix); + sb.append(" <+ {"); + String dom = visitExprOrOpArgNode(head, new DContext(), VALUE).out + .toString(); + sb.append(dom); + sb.append(" |-> "); + + if (list.size() > 0) { + String res = evalExceptValue(list, func.getRange(), val, prefix + + "(" + dom + ")"); + sb.append(res); + } else { + sb.append(val); + } + sb.append("}"); + sb.append(")"); + } + return sb.toString(); + } + + /** + * @param n + * @return + */ + protected ExprReturn evalIfThenElse(OpApplNode n, DContext d, int expected) { + TLAType t = (TLAType) n.getToolObject(TYPE_ID); + + if (t.getKind() == BOOL) { + d.indent.append(" "); + ExprReturn iif = visitExprOrOpArgNode(n.getArgs()[0], d, PREDICATE); + ExprReturn then = visitExprOrOpArgNode(n.getArgs()[1], d, PREDICATE); + ExprReturn eelse = visitExprOrOpArgNode(n.getArgs()[2], d, + PREDICATE); + String res = String.format( + "(%s \n%s => %s) \n\t & (not(%s) \n%s => %s)", + brackets(iif, P_implies, true), d.indent, + brackets(then, P_implies, false), iif.out, d.indent, + brackets(eelse, P_implies, false)); + return makeBoolValue(new StringBuilder(res), expected, P_and); + } else { + // ExprReturn iif = visitExprOrOpArgNode(n.getArgs()[0], d, + // PREDICATE); + // ExprReturn then = visitExprOrOpArgNode(n.getArgs()[1], d, + // VALUE); + // ExprReturn eelse = visitExprOrOpArgNode(n.getArgs()[2], d, + // VALUE); + // String res = String + // .format("(%%t_.( t_ = 0 & %s | %s )\\/%%t_.( t_ = 0 & not(%s) | %s ))(0)", + // iif.out, then.out, iif.out, eelse.out); + // return new ExprReturn(res); + ExprReturn iif = visitExprOrOpArgNode(n.getArgs()[0], d, VALUE); + ExprReturn then = visitExprOrOpArgNode(n.getArgs()[1], d, VALUE); + ExprReturn eelse = visitExprOrOpArgNode(n.getArgs()[2], d, VALUE); + String res = String.format("IF_THEN_ELSE(%s, %s, %s)", iif.out, + then.out, eelse.out); + return new ExprReturn(res); + } + } + + private ExprReturn evalBoundedQuantor(OpApplNode n, DContext d, + int expected, String symbol) { + StringBuilder out = new StringBuilder(); + out.append(symbol); + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + for (int i = 0; i < params.length; i++) { + for (int j = 0; j < params[i].length; j++) { + out.append(getPrintName(params[i][j])); + if (j < params[i].length - 1) { + out.append(","); + } + } + if (i < params.length - 1) { + out.append(","); + } + } + out.append(".("); + out.append(visitBounded(n, d)); + out.append(symbol.equals("#") ? " & " : " => "); + out.append(brackets(visitExprOrOpArgNode(n.getArgs()[0], d, PREDICATE), + symbol.equals("#") ? P_and : P_implies, false)); + out.append(")"); + return makeBoolValue(out, expected, P_max); + } + + @SuppressWarnings("unused") + private ExprReturn evalStructOrRec(String string, OpApplNode n, DContext d) { + StringBuilder out = new StringBuilder(); + out.append(string); + out.append("("); + ExprOrOpArgNode[] args = n.getArgs(); + for (int i = 0; i < args.length; i++) { + OpApplNode pair = (OpApplNode) args[i]; + StringNode stringNode = (StringNode) pair.getArgs()[0]; + out.append(stringNode.getRep().toString()); + out.append(" : "); + out.append(visitExprOrOpArgNode(pair.getArgs()[1], d, VALUE).out); + if (i != args.length - 1) + out.append(", "); + } + out.append(")"); + return new ExprReturn(out, P_max); + } + + protected ExprReturn evalBBuiltIns(OpApplNode n, DContext d, int expected) { + StringBuilder out = new StringBuilder(); + + switch (BBuiltInOPs.getOpcode(n.getOperator().getName())) { + + /********************************************************************** + * Standard Module Naturals + **********************************************************************/ + case B_OPCODE_nat: // Nat + { + out.append("NATURAL"); + return new ExprReturn(out); + } + + case B_OPCODE_plus: // + + out.append(evalOpMoreArgs(n, " + ", d, NOBOOL, P_plus)); + return new ExprReturn(out, P_plus); + + case B_OPCODE_minus: // - + { + out.append(evalOpMoreArgs(n, " - ", d, NOBOOL, P_minus)); + return new ExprReturn(out, P_minus); + } + + case B_OPCODE_times: // * + { + out.append(evalOpMoreArgs(n, " * ", d, NOBOOL, P_times)); + return new ExprReturn(out, P_times); + } + + case B_OPCODE_exp: // x^y + { + out.append(evalOpMoreArgs(n, " ** ", d, NOBOOL, P_exp)); + return new ExprReturn(out, P_exp); + } + + case B_OPCODE_lt: // < + { + out.append(evalOpMoreArgs(n, " < ", d, NOBOOL, P_lt)); + return makeBoolValue(out, expected, P_lt); + } + + case B_OPCODE_gt: // > + { + out.append(evalOpMoreArgs(n, " > ", d, NOBOOL, P_gt)); + return makeBoolValue(out, expected, P_gt); + } + + case B_OPCODE_leq: // <= + { + out.append(evalOpMoreArgs(n, " <= ", d, NOBOOL, P_leq)); + return makeBoolValue(out, expected, P_leq); + } + + case B_OPCODE_geq: // >= + { + out.append(evalOpMoreArgs(n, " >= ", d, NOBOOL, P_geq)); + return makeBoolValue(out, expected, P_geq); + } + + case B_OPCODE_mod: // modulo + { + ExprReturn first = visitExprOrOpArgNode(n.getArgs()[0], d, VALUE); + ExprReturn second = visitExprOrOpArgNode(n.getArgs()[1], d, VALUE); + String res = String.format("(%s - %s * (%s / %s))", + brackets(first, P_minus, true), + brackets(second, P_times, true), + brackets(first, P_div, true), + brackets(second, P_div, false)); + return new ExprReturn(res); + } + + case B_OPCODE_div: // / + { + out.append(evalOpMoreArgs(n, " / ", d, NOBOOL, P_div)); + return new ExprReturn(out, P_div); + } + + case B_OPCODE_dotdot: // .. + { + out.append(evalOpMoreArgs(n, " .. ", d, NOBOOL, P_dotdot)); + return new ExprReturn(out, P_dotdot); + } + + /********************************************************************** + * Standard Module Integers + **********************************************************************/ + case B_OPCODE_int: // Int + { + out.append("INTEGER"); + return new ExprReturn(out); + } + + case B_OPCODE_uminus: // -x + { + out.append("-"); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + return new ExprReturn(out, P_uminus); + } + + /********************************************************************** + * Standard Module FiniteSets + **********************************************************************/ + case B_OPCODE_card: // Cardinality + { + out.append("card("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + case B_OPCODE_finite: { // IsFiniteSet + ExprReturn exprr = visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL); + // String res = String + // .format("#seq_.(seq_ : seq(%s) & !s.(s : %s => #n.(n : 1 .. size(seq_) & seq_(n) = s)))", + // exprr.out, exprr.out); + String res = String.format("%s : FIN(%s)", exprr.out, exprr.out); + out.append(res); + return makeBoolValue(out, expected, P_max); + } + + /********************************************************************** + * Standard Module Sequences + **********************************************************************/ + case B_OPCODE_seq: { // Seq(S) - set of sequences + out.append("seq("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + case B_OPCODE_len: { // length of the sequence + out.append("size("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + case B_OPCODE_conc: { // s \o s2 - concatenation of s and s2 + out.append(evalOpMoreArgs(n, " ^ ", d, NOBOOL, P_conc)); + return new ExprReturn(out, P_conc); + } + + case B_OPCODE_append: { // Append(s,x) + out.append(evalOpMoreArgs(n, " <- ", d, NOBOOL, P_append)); + return new ExprReturn(out, P_append); + } + + case B_OPCODE_head: { // Head(s) + out.append("first("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + case B_OPCODE_tail: { // Tail(s) + out.append("tail("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + case B_OPCODE_subseq: { // SubSeq(s,m,n) + StringBuilder s = visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out; + out.append("("); + out.append(s); + out.append("/|\\"); // taking first n elements + out.append(visitExprOrOpArgNode(n.getArgs()[2], d, NOBOOL).out); + out.append(")\\|/"); // dropping first m-1 elements + out.append(visitExprOrOpArgNode(n.getArgs()[1], d, NOBOOL).out); + out.append("-1"); + return new ExprReturn(out, P_drop_last); + } + + /********************************************************************** + * Standard Module TLA2B + **********************************************************************/ + case B_OPCODE_min: { // MinOfSet(s) + out.append("min("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + case B_OPCODE_max: { // MaxOfSet(s) + out.append("max("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + case B_OPCODE_setprod: { // SetProduct(s) + out.append("PI(z_).(z_:"); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append("|z_)"); + return new ExprReturn(out); + } + + case B_OPCODE_setsum: { // SetSummation(s) + out.append("SIGMA(z_).(z_:"); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append("|z_)"); + return new ExprReturn(out); + } + + case B_OPCODE_permseq: { // PermutedSequences(s) + out.append("perm("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + /********************************************************************** + * Standard Module TLA2B + **********************************************************************/ + case B_OPCODE_pow1: { // POW1 + out.append("POW1("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append(")"); + return new ExprReturn(out); + } + + /********************************************************************** + * Standard Module Relations + **********************************************************************/ + + case B_OPCODE_rel_inverse: { // POW1 + out.append("("); + out.append(visitExprOrOpArgNode(n.getArgs()[0], d, NOBOOL).out); + out.append("~)"); + return new ExprReturn(out); + } + + /*********************************************************************** + * TLA+ Built-Ins, but not in tlc.tool.BuiltInOPs + ***********************************************************************/ + case B_OPCODE_bool: // BOOLEAN + out.append("BOOL"); + return new ExprReturn(out); + + case B_OPCODE_true: // TRUE + out.append("TRUE"); + if (expected == PREDICATE) { + out.append(" = TRUE"); + return new ExprReturn(out, P_equals); + } + return new ExprReturn(out); + + case B_OPCODE_false: // FALSE + out.append("FALSE"); + if (expected == PREDICATE) { + out.append(" = TRUE"); + return new ExprReturn(out, P_equals); + } + return new ExprReturn(out); + + case B_OPCODE_string: // STRING + out.append("STRING"); + return new ExprReturn(out); + + } + + throw new RuntimeException(n.toString(2)); + } + + protected StringBuilder visitBounded(OpApplNode n, DContext d) { + StringBuilder out = new StringBuilder(); + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ExprNode[] in = n.getBdedQuantBounds(); + boolean[] isTuple = n.isBdedQuantATuple(); + for (int i = 0; i < params.length; i++) { + if (isTuple[i]) { + out.append("("); + for (int j = 0; j < params[i].length; j++) { + out.append(getPrintName(params[i][j])); + if (j == 0) + out.append(", "); + } + out.append(")"); + out.append(" : "); + out.append(visitExprNode(in[i], d, NOBOOL).out); + if (i < params.length - 1) { + out.append(" & "); + } + } else { + for (int j = 0; j < params[i].length; j++) { + out.append(getPrintName(params[i][j])); + out.append(" : "); + out.append(visitExprNode(in[i], d, NOBOOL).out); + if (j < params[i].length - 1 || i < params.length - 1) { + out.append(" & "); + } + } + } + } + return out; + } + + protected StringBuilder evalOpMoreArgs(OpApplNode n, String operator, + DContext d, int expected, int priority) { + StringBuilder out = new StringBuilder(); + ExprOrOpArgNode[] args = n.getArgs(); + for (int i = 0; i < args.length; i++) { + ExprReturn r = visitExprOrOpArgNode(args[i], d, expected); + if (i == 0) { + out.append(brackets(r, priority, true)); + } else { + out.append(operator); + out.append(brackets(r, priority, false)); + } + + } + return out; + } + + protected ExprReturn makeBoolValue(StringBuilder out, int expected, + int priority) { + StringBuilder res = new StringBuilder(); + if (expected == VALUE) { + res.append("bool(" + out + ")"); + return new ExprReturn(res); + } else { + return new ExprReturn(out, priority); + } + } + + protected StringBuilder brackets(ExprReturn r, int p, boolean left) { + StringBuilder res = new StringBuilder(); + if ((left && r.getPriority() < p) || (!left && r.getPriority() <= p)) { + res.append("("); + res.append(r.getOut()); + res.append(")"); + } else + res.append(r.getOut()); + return res; + } + + protected String getPrintName(SymbolNode node) { + if (node.getToolObject(NEW_NAME) != null) { + return (String) node.getToolObject(NEW_NAME); + } else { + return node.getName().toString(); + } + } + + private String getDummy(TLAType type) { + switch (type.getKind()) { + case INTEGER: + return "0"; + + case STRING: + return "\"\""; + + case POW: + return "{}"; + + case BOOL: + return "FALSE"; + case MODELVALUE: + EnumType e = (EnumType) type; + return "noVal" + e.id; + default: + break; + } + return null; + + } +} diff --git a/src/main/java/de/tla2b/pprint/BAstCreator.java b/src/main/java/de/tla2b/pprint/BAstCreator.java new file mode 100644 index 0000000000000000000000000000000000000000..6d6b6fff89029db5a2101775907a20a9392ef8ef --- /dev/null +++ b/src/main/java/de/tla2b/pprint/BAstCreator.java @@ -0,0 +1,1222 @@ +package de.tla2b.pprint; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.List; + +import tla2sany.semantic.ASTConstants; +import tla2sany.semantic.AssumeNode; +import tla2sany.semantic.ExprNode; +import tla2sany.semantic.ExprOrOpArgNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.NumeralNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; +import tla2sany.semantic.StringNode; +import tlc2.tool.BuiltInOPs; +import de.be4.classicalb.core.parser.node.AAbstractConstantsMachineClause; +import de.be4.classicalb.core.parser.node.AAbstractMachineParseUnit; +import de.be4.classicalb.core.parser.node.AAddExpression; +import de.be4.classicalb.core.parser.node.AAnySubstitution; +import de.be4.classicalb.core.parser.node.AAssignSubstitution; +import de.be4.classicalb.core.parser.node.ABecomesSuchSubstitution; +import de.be4.classicalb.core.parser.node.ABoolSetExpression; +import de.be4.classicalb.core.parser.node.ABooleanFalseExpression; +import de.be4.classicalb.core.parser.node.ABooleanTrueExpression; +import de.be4.classicalb.core.parser.node.ACardExpression; +import de.be4.classicalb.core.parser.node.AComprehensionSetExpression; +import de.be4.classicalb.core.parser.node.AConcatExpression; +import de.be4.classicalb.core.parser.node.AConjunctPredicate; +import de.be4.classicalb.core.parser.node.AConvertBoolExpression; +import de.be4.classicalb.core.parser.node.ACoupleExpression; +import de.be4.classicalb.core.parser.node.ADisjunctPredicate; +import de.be4.classicalb.core.parser.node.ADivExpression; +import de.be4.classicalb.core.parser.node.ADomainExpression; +import de.be4.classicalb.core.parser.node.AEmptySetExpression; +import de.be4.classicalb.core.parser.node.AEqualPredicate; +import de.be4.classicalb.core.parser.node.AEquivalencePredicate; +import de.be4.classicalb.core.parser.node.AExistsPredicate; +import de.be4.classicalb.core.parser.node.AFinSubsetExpression; +import de.be4.classicalb.core.parser.node.AFirstExpression; +import de.be4.classicalb.core.parser.node.AForallPredicate; +import de.be4.classicalb.core.parser.node.AFunctionExpression; +import de.be4.classicalb.core.parser.node.AGeneralUnionExpression; +import de.be4.classicalb.core.parser.node.AGreaterEqualPredicate; +import de.be4.classicalb.core.parser.node.AGreaterPredicate; +import de.be4.classicalb.core.parser.node.AIdentifierExpression; +import de.be4.classicalb.core.parser.node.AImplicationPredicate; +import de.be4.classicalb.core.parser.node.AInitialisationMachineClause; +import de.be4.classicalb.core.parser.node.AInsertTailExpression; +import de.be4.classicalb.core.parser.node.AIntegerExpression; +import de.be4.classicalb.core.parser.node.AIntegerSetExpression; +import de.be4.classicalb.core.parser.node.AIntersectionExpression; +import de.be4.classicalb.core.parser.node.AIntervalExpression; +import de.be4.classicalb.core.parser.node.AInvariantMachineClause; +import de.be4.classicalb.core.parser.node.ALambdaExpression; +import de.be4.classicalb.core.parser.node.ALessEqualPredicate; +import de.be4.classicalb.core.parser.node.ALessPredicate; +import de.be4.classicalb.core.parser.node.AMachineHeader; +import de.be4.classicalb.core.parser.node.AMemberPredicate; +import de.be4.classicalb.core.parser.node.AMinusOrSetSubtractExpression; +import de.be4.classicalb.core.parser.node.AMultOrCartExpression; +import de.be4.classicalb.core.parser.node.ANaturalSetExpression; +import de.be4.classicalb.core.parser.node.ANegationPredicate; +import de.be4.classicalb.core.parser.node.ANotEqualPredicate; +import de.be4.classicalb.core.parser.node.ANotMemberPredicate; +import de.be4.classicalb.core.parser.node.AOperation; +import de.be4.classicalb.core.parser.node.AOperationsMachineClause; +import de.be4.classicalb.core.parser.node.APowSubsetExpression; +import de.be4.classicalb.core.parser.node.APowerOfExpression; +import de.be4.classicalb.core.parser.node.APropertiesMachineClause; +import de.be4.classicalb.core.parser.node.ARecEntry; +import de.be4.classicalb.core.parser.node.ARecExpression; +import de.be4.classicalb.core.parser.node.ARecordFieldExpression; +import de.be4.classicalb.core.parser.node.ASeqExpression; +import de.be4.classicalb.core.parser.node.ASequenceExtensionExpression; +import de.be4.classicalb.core.parser.node.ASetExtensionExpression; +import de.be4.classicalb.core.parser.node.ASizeExpression; +import de.be4.classicalb.core.parser.node.AStringExpression; +import de.be4.classicalb.core.parser.node.AStringSetExpression; +import de.be4.classicalb.core.parser.node.AStructExpression; +import de.be4.classicalb.core.parser.node.ASubsetPredicate; +import de.be4.classicalb.core.parser.node.ATailExpression; +import de.be4.classicalb.core.parser.node.ATotalFunctionExpression; +import de.be4.classicalb.core.parser.node.AUnaryMinusExpression; +import de.be4.classicalb.core.parser.node.AUnionExpression; +import de.be4.classicalb.core.parser.node.AVariablesMachineClause; +import de.be4.classicalb.core.parser.node.EOF; +import de.be4.classicalb.core.parser.node.PExpression; +import de.be4.classicalb.core.parser.node.PMachineClause; +import de.be4.classicalb.core.parser.node.POperation; +import de.be4.classicalb.core.parser.node.PPredicate; +import de.be4.classicalb.core.parser.node.PRecEntry; +import de.be4.classicalb.core.parser.node.Start; +import de.be4.classicalb.core.parser.node.TIdentifierLiteral; +import de.be4.classicalb.core.parser.node.TIntegerLiteral; +import de.be4.classicalb.core.parser.node.TStringLiteral; +import de.tla2b.analysis.BOperation; +import de.tla2b.analysis.SpecAnalyser; +import de.tla2b.config.ConfigfileEvaluator; +import de.tla2b.global.BBuildIns; +import de.tla2b.global.BBuiltInOPs; +import de.tla2b.global.Priorities; +import de.tla2b.global.TranslationGlobals; +import de.tla2b.types.IType; +import de.tla2b.types.SetType; +import de.tla2b.types.StructType; +import de.tla2b.types.TLAType; +import de.tla2b.types.TupleType; + +public class BAstCreator extends BuiltInOPs implements TranslationGlobals, + ASTConstants, IType, BBuildIns, Priorities { + Start start; + List<PMachineClause> machineClauseList; + ConfigfileEvaluator conEval; + SpecAnalyser specAnalyser; + + private ModuleNode moduleNode; + + public Start getStartNode() { + return start; + } + + public BAstCreator(ModuleNode moduleNode, ConfigfileEvaluator conEval, + SpecAnalyser specAnalyser) { + this.conEval = conEval; + this.moduleNode = moduleNode; + this.specAnalyser = specAnalyser; + + machineClauseList = new ArrayList<PMachineClause>(); + + AAbstractMachineParseUnit aAbstractMachineParseUnit = new AAbstractMachineParseUnit(); + AMachineHeader machineHeader = new AMachineHeader(); + List<TIdentifierLiteral> headerName = createTIdentifierLiteral(moduleNode + .getName().toString()); + machineHeader.setName(headerName); + aAbstractMachineParseUnit.setHeader(machineHeader); + + createConstantsClause(); + createPropertyClause(); + createVariableClause(); + createInvariantClause(); + createInitClause(); + createOperationsClause(); + + aAbstractMachineParseUnit.setMachineClauses(machineClauseList); + + start = new Start(aAbstractMachineParseUnit, new EOF()); + + } + + private void createOperationsClause() { + ArrayList<BOperation> bOperations = specAnalyser.getBOperations(); + if (bOperations == null || bOperations.size() == 0) { + return; + } + + List<POperation> opList = new ArrayList<POperation>(); + for (int i = 0; i < bOperations.size(); i++) { + BOperation op = bOperations.get(i); + String defName = op.getName(); + List<PExpression> paramList = new ArrayList<PExpression>(); + for (int j = 0; j < op.getOpParams().size(); j++) { + paramList.add(createIdentifierNode(op.getOpParams().get(j))); + } + AOperation operation = new AOperation(); + operation.setOpName(createTIdentifierLiteral(defName)); + operation.setParameters(paramList); + operation.setReturnValues(new ArrayList<PExpression>()); + + AAnySubstitution any = new AAnySubstitution(); + OpDeclNode[] vars = moduleNode.getVariableDecls(); + List<PExpression> anyParams = new ArrayList<PExpression>(); + for (int j = 0; j < vars.length; j++) { + String varName = vars[j].getName().toString(); + if (op.getUnchangedVariables().contains(varName)) + continue; + anyParams.add(createIdentifierNode(varName + "_n")); + } + any.setIdentifiers(anyParams); + any.setWhere(visitExprOrOpArgNodePredicate(op.getNode())); + + List<PExpression> varList = new ArrayList<PExpression>(); + List<PExpression> valueList = new ArrayList<PExpression>(); + for (int j = 0; j < vars.length; j++) { + String varName = vars[j].getName().toString(); + if (op.getUnchangedVariables().contains(varName)) + continue; + varList.add(createIdentifierNode(varName)); + valueList.add(createIdentifierNode(varName + "_n")); + } + AAssignSubstitution assign = new AAssignSubstitution(varList, + valueList); + any.setThen(assign); + operation.setOperationBody(any); + opList.add(operation); + } + + AOperationsMachineClause opClause = new AOperationsMachineClause(opList); + machineClauseList.add(opClause); + } + + private void createInitClause() { + OpDeclNode[] vars = moduleNode.getVariableDecls(); + if (vars.length == 0) + return; + List<PExpression> varList = new ArrayList<PExpression>(); + for (int i = 0; i < vars.length; i++) { + varList.add(createIdentifierNode(vars[i].getName().toString())); + } + ABecomesSuchSubstitution becomes = new ABecomesSuchSubstitution(); + becomes.setIdentifiers(varList); + + List<PPredicate> predList = new ArrayList<PPredicate>(); + for (ExprNode node : specAnalyser.getInits()) { + predList.add(visitExprNodePredicate(node)); + } + becomes.setPredicate(createConjunction(predList)); + AInitialisationMachineClause initClause = new AInitialisationMachineClause( + becomes); + machineClauseList.add(initClause); + } + + private void createVariableClause() { + List<OpDeclNode> bVariables = Arrays.asList(moduleNode + .getVariableDecls()); + if (bVariables.size() > 0) { + List<PExpression> list = new ArrayList<PExpression>(); + for (OpDeclNode opDeclNode : bVariables) { + AIdentifierExpression id = new AIdentifierExpression( + createTIdentifierLiteral(opDeclNode.getName() + .toString())); + list.add(id); + } + AVariablesMachineClause varClause = new AVariablesMachineClause( + list); + machineClauseList.add(varClause); + } + } + + private void createConstantsClause() { + List<OpDeclNode> bConstants = Arrays.asList(moduleNode + .getConstantDecls()); + if (bConstants.size() > 0) { + List<PExpression> list = new ArrayList<PExpression>(); + for (OpDeclNode opDeclNode : bConstants) { + AIdentifierExpression id = new AIdentifierExpression( + createTIdentifierLiteral(opDeclNode.getName() + .toString())); + list.add(id); + } + AAbstractConstantsMachineClause abstractConstantsClause = new AAbstractConstantsMachineClause( + list); + machineClauseList.add(abstractConstantsClause); + } + } + + private void createPropertyClause() { + List<PPredicate> list = new ArrayList<PPredicate>(); + AssumeNode[] assumes = moduleNode.getAssumptions(); + if (assumes.length == 0) { + return; + } + for (AssumeNode assumeNode : assumes) { + list.add(visitAssumeNode(assumeNode)); + } + + APropertiesMachineClause propertiesClause = new APropertiesMachineClause(); + propertiesClause.setPredicates(createConjunction(list)); + + machineClauseList.add(propertiesClause); + } + + private void createInvariantClause() { + OpDeclNode[] vars = moduleNode.getVariableDecls(); + if (vars.length == 0) + return; + + List<PPredicate> predList = new ArrayList<PPredicate>(); + for (int i = 0; i < vars.length; i++) { + TLAType varType = (TLAType) vars[i].getToolObject(TYPE_ID); + + AMemberPredicate member = new AMemberPredicate(); + member.setLeft(createIdentifierNode(vars[i].getName().toString())); + member.setRight(new AIntegerSetExpression()); + + predList.add(member); + } + AInvariantMachineClause invClause = new AInvariantMachineClause( + createConjunction(predList)); + machineClauseList.add(invClause); + } + + private PPredicate visitAssumeNode(AssumeNode assumeNode) { + return visitExprNodePredicate(assumeNode.getAssume()); + } + + private PPredicate visitExprNodePredicate(ExprNode n) { + switch (n.getKind()) { + case OpApplKind: + return visitOpApplNodePredicate((OpApplNode) n); + + case NumeralKind: { + } + + } + + throw new RuntimeException(); + } + + private PExpression visitExprNodeExpression(ExprNode n) { + + switch (n.getKind()) { + + case OpApplKind: + return visitOpApplNodeExpression((OpApplNode) n); + + case NumeralKind: { + String number = String.valueOf(((NumeralNode) n).val()); + return new AIntegerExpression(new TIntegerLiteral(number)); + } + + case StringKind: { + StringNode s = (StringNode) n; + return new AStringExpression(new TStringLiteral(s.getRep() + .toString())); + } + + } + + throw new RuntimeException(); + } + + private PPredicate visitOpApplNodePredicate(OpApplNode n) { + switch (n.getOperator().getKind()) { + case ConstantDeclKind: { + return new AEqualPredicate(createIdentifierNode(n.getOperator() + .getName().toString()), new ABooleanTrueExpression()); + } + case VariableDeclKind: { + return new AEqualPredicate(createIdentifierNode(n.getOperator() + .getName().toString()), new ABooleanTrueExpression()); + + } + case BuiltInKind: + return visitBuiltInKindPredicate(n); + + case UserDefinedOpKind: { + return visitUserdefinedOpPredicate(n); + } + + } + System.out.println(n.getOperator().getName()); + throw new RuntimeException(); + } + + private PExpression visitOpApplNodeExpression(OpApplNode n) { + switch (n.getOperator().getKind()) { + case ConstantDeclKind: { + return createIdentifierNode(n.getOperator().getName().toString()); + } + case VariableDeclKind: { + return createIdentifierNode(n.getOperator().getName().toString()); + } + + case FormalParamKind: { + return createIdentifierNode(n.getOperator().getName().toString()); + } + + case BuiltInKind: + return visitBuiltInKindExpression(n); + + case UserDefinedOpKind: { + return visitUserdefinedOpExpression(n); + } + } + + System.out.println(n.getOperator().getName()); + throw new RuntimeException(); + } + + private PPredicate visitUserdefinedOpPredicate(OpApplNode n) { + OpDefNode def = (OpDefNode) n.getOperator(); + // Operator is a B built-in operator + if (BBuiltInOPs.contains(def.getName()) + && STANDARD_MODULES.contains(def.getSource() + .getOriginallyDefinedInModuleNode().getName() + .toString())) { + return visitBBuitInsPredicate(n); + } + + // new Definition or what else + + throw new RuntimeException(); + } + + private PExpression visitUserdefinedOpExpression(OpApplNode n) { + OpDefNode def = (OpDefNode) n.getOperator(); + // Operator is a B built-in operator + if (BBuiltInOPs.contains(def.getName()) + && STANDARD_MODULES.contains(def.getSource() + .getOriginallyDefinedInModuleNode().getName() + .toString())) { + return visitBBuitInsExpression(n); + } + + // new Definition or what else + + throw new RuntimeException(); + } + + private PPredicate visitBBuitInsPredicate(OpApplNode n) { + switch (BBuiltInOPs.getOpcode(n.getOperator().getName())) { + + case B_OPCODE_lt: // < + return new ALessPredicate( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_gt: // > + return new AGreaterPredicate( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_leq: // <= + return new ALessEqualPredicate( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_geq: // >= + return new AGreaterEqualPredicate( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_finite: // IsFiniteSet({1,2,3}) + { + AMemberPredicate member = new AMemberPredicate(); + member.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + member.setRight(new AFinSubsetExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]))); + return member; + } + case B_OPCODE_true: // TRUE + return new AEqualPredicate(new ABooleanTrueExpression(), + new ABooleanTrueExpression()); + + case B_OPCODE_false: // FALSE + return new AEqualPredicate(new ABooleanFalseExpression(), + new ABooleanTrueExpression()); + + } + System.out.println(n.getOperator().getName()); + throw new RuntimeException(); + } + + private PExpression visitBBuitInsExpression(OpApplNode n) { + switch (BBuiltInOPs.getOpcode(n.getOperator().getName())) { + + case B_OPCODE_bool: // BOOLEAN + return new ABoolSetExpression(); + + case B_OPCODE_true: // TRUE + return new ABooleanTrueExpression(); + case B_OPCODE_false: // FALSE + return new ABooleanFalseExpression(); + + /********************************************************************** + * Standard Module Naturals + **********************************************************************/ + case B_OPCODE_nat: // Nat + return new ANaturalSetExpression(); + + case B_OPCODE_plus: // + + return new AAddExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_minus: // - + return new AMinusOrSetSubtractExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_times: // * + return new AMultOrCartExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_exp: // x^y + return new APowerOfExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_lt: // < + return new AConvertBoolExpression(new ALessPredicate( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1]))); + + case B_OPCODE_gt: // > + return new AConvertBoolExpression(new AGreaterPredicate( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1]))); + + case B_OPCODE_leq: // <= + return new AConvertBoolExpression(new ALessEqualPredicate( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1]))); + + case B_OPCODE_geq: // >= + return new AConvertBoolExpression(new AGreaterEqualPredicate( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1]))); + + case B_OPCODE_mod: // modulo + { + PExpression f = visitExprOrOpArgNodeExpression(n.getArgs()[0]); + PExpression s = visitExprOrOpArgNodeExpression(n.getArgs()[1]); + PExpression f2 = visitExprOrOpArgNodeExpression(n.getArgs()[0]); + PExpression s2 = visitExprOrOpArgNodeExpression(n.getArgs()[1]); + + ADivExpression div = new ADivExpression(f, s); + AMultOrCartExpression mult = new AMultOrCartExpression(s2, div); + AMinusOrSetSubtractExpression minus = new AMinusOrSetSubtractExpression( + f2, mult); + return minus; + } + + case B_OPCODE_div: // / + return new ADivExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_dotdot: // .. + return new AIntervalExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_int: // Int + return new AIntegerSetExpression(); + + case B_OPCODE_uminus: // -x + return new AUnaryMinusExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0])); + + case B_OPCODE_card: // Cardinality + return new ACardExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0])); + + case B_OPCODE_finite: // IsFiniteSet({1,2,3}) + { + AMemberPredicate member = new AMemberPredicate(); + member.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + member.setRight(new AFinSubsetExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]))); + return new AConvertBoolExpression(member); + } + + case B_OPCODE_string: // STRING + return new AStringSetExpression(); + + /********************************************************************** + * Standard Module Sequences + **********************************************************************/ + + case B_OPCODE_seq: // Seq(S) - set of sequences + return new ASeqExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0])); + + case B_OPCODE_len: // length of the sequence + return new ASizeExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0])); + + case B_OPCODE_conc: // s \o s2 - concatenation of s and s2 + return new AConcatExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_append: // Append(s,x) + return new AInsertTailExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case B_OPCODE_head: // Head(s) + return new AFirstExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0])); + + case B_OPCODE_tail: // Tail(s) + return new ATailExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0])); + + case B_OPCODE_subseq: { // SubSeq(s,m,n) + // StringBuilder s = visitExprOrOpArgNode(n.getArgs()[0], d, + // NOBOOL).out; + // out.append("("); + // out.append(s); + // out.append("/|\\"); // taking first n elements + // out.append(visitExprOrOpArgNode(n.getArgs()[2], d, NOBOOL).out); + // out.append(")\\|/"); // dropping first m-1 elements + // out.append(visitExprOrOpArgNode(n.getArgs()[1], d, NOBOOL).out); + // out.append("-1"); + // return new ExprReturn(out, P_drop_last); + } + + } + System.out.println(n.getOperator().getName()); + throw new RuntimeException(); + } + + private PExpression visitBuiltInKindExpression(OpApplNode n) { + switch (getOpCode(n.getOperator().getName())) { + + case OPCODE_land: // \land + { + AConjunctPredicate conjunction = new AConjunctPredicate(); + conjunction.setLeft(visitExprOrOpArgNodePredicate(n.getArgs()[0])); + conjunction.setRight(visitExprOrOpArgNodePredicate(n.getArgs()[1])); + return new AConvertBoolExpression(conjunction); + } + + case OPCODE_cl: // $ConjList + { + List<PPredicate> list = new ArrayList<PPredicate>(); + for (int i = 0; i < n.getArgs().length; i++) { + list.add(visitExprOrOpArgNodePredicate(n.getArgs()[i])); + } + return new AConvertBoolExpression(createConjunction(list)); + } + + case OPCODE_dl: // $DisjList + { + List<PPredicate> list = new ArrayList<PPredicate>(); + for (int i = 0; i < n.getArgs().length; i++) { + list.add(visitExprOrOpArgNodePredicate(n.getArgs()[i])); + } + return new AConvertBoolExpression(createDisjunction(list)); + } + + case OPCODE_lor: // \/ + { + ADisjunctPredicate disjunction = new ADisjunctPredicate(); + disjunction.setLeft(visitExprOrOpArgNodePredicate(n.getArgs()[0])); + disjunction.setRight(visitExprOrOpArgNodePredicate(n.getArgs()[1])); + return new AConvertBoolExpression(disjunction); + } + + case OPCODE_lnot: // \lnot + return new AConvertBoolExpression(new ANegationPredicate( + visitExprOrOpArgNodePredicate(n.getArgs()[0]))); + + case OPCODE_in: // \in + { + AMemberPredicate memberPredicate = new AMemberPredicate(); + memberPredicate + .setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + memberPredicate + .setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return new AConvertBoolExpression(memberPredicate); + } + + case OPCODE_notin: // \notin + { + ANotMemberPredicate notMemberPredicate = new ANotMemberPredicate(); + notMemberPredicate.setLeft(visitExprOrOpArgNodeExpression(n + .getArgs()[0])); + notMemberPredicate.setRight(visitExprOrOpArgNodeExpression(n + .getArgs()[1])); + return new AConvertBoolExpression(notMemberPredicate); + } + + case OPCODE_eq: { // = + AEqualPredicate equal = new AEqualPredicate(); + equal.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + equal.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return new AConvertBoolExpression(equal); + } + + case OPCODE_noteq: // /= + { + ANotEqualPredicate notEqual = new ANotEqualPredicate(); + notEqual.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + notEqual.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return new AConvertBoolExpression(notEqual); + } + + /********************************************************************** + * Set Operators + **********************************************************************/ + + case OPCODE_se: // SetEnumeration {..} + { + if (n.getArgs().length == 0) { + return new AEmptySetExpression(); + } else { + List<PExpression> list = new ArrayList<PExpression>(); + + for (int i = 0; i < n.getArgs().length; i++) { + list.add(visitExprOrOpArgNodeExpression(n.getArgs()[i])); + } + return new ASetExtensionExpression(list); + } + } + + case 0: { + return visitBBuitInsExpression(n); + } + + case OPCODE_setdiff: // set difference + { + AMinusOrSetSubtractExpression minus = new AMinusOrSetSubtractExpression(); + minus.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + minus.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return minus; + } + + case OPCODE_cup: // set union + { + AUnionExpression union = new AUnionExpression(); + union.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + union.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return union; + } + + case OPCODE_cap: // set intersection + { + AIntersectionExpression inter = new AIntersectionExpression(); + inter.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + inter.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return inter; + } + + case OPCODE_subset: // SUBSET + { + APowSubsetExpression pow = new APowSubsetExpression(); + pow.setExpression(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + return pow; + } + + case OPCODE_union: // Union - Union{{1},{2}} + { + AGeneralUnionExpression union = new AGeneralUnionExpression(); + union.setExpression(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + return union; + } + + case OPCODE_subseteq: // \subseteq {1,2} <: {1,2,3} + { + ASubsetPredicate subset = new ASubsetPredicate(); + subset.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + subset.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return new AConvertBoolExpression(subset); + } + + case OPCODE_sso: { // $SubsetOf Represents {x \in S : P} + // TODO tuple with more than 2 arguments + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ExprNode[] bounds = n.getBdedQuantBounds(); + + List<PExpression> list = new ArrayList<PExpression>(); + FormalParamNode p = n.getBdedQuantSymbolLists()[0][0]; + list.add(createIdentifierNode(p.getName().toString())); + + AComprehensionSetExpression compre = new AComprehensionSetExpression(); + compre.setIdentifiers(list); + + AMemberPredicate member = new AMemberPredicate(); + member.setLeft(createIdentifierNode(p.getName().toString())); + ExprNode in = n.getBdedQuantBounds()[0]; + member.setRight(visitExprNodeExpression(in)); + + AConjunctPredicate conj = new AConjunctPredicate(member, + visitExprOrOpArgNodePredicate(n.getArgs()[0])); + compre.setPredicates(conj); + return compre; + } + + case OPCODE_soa: { // $SetOfAll Represents {e : p1 \in S, p2,p3 \in S2} + + AExistsPredicate exist = new AExistsPredicate(); + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ExprNode[] bounds = n.getBdedQuantBounds(); + + List<PExpression> idList = new ArrayList<PExpression>(); + List<PPredicate> predList = new ArrayList<PPredicate>(); + for (int i = 0; i < bounds.length; i++) { + FormalParamNode p = params[i][0]; + AMemberPredicate member = new AMemberPredicate(); + member.setLeft(createIdentifierNode(p.getName().toString())); + ExprNode in = n.getBdedQuantBounds()[i]; + member.setRight(visitExprNodeExpression(in)); + predList.add(member); + idList.add(createIdentifierNode(p.getName().toString())); + } + final String nameOfTempVariable = "t_"; + AEqualPredicate equals = new AEqualPredicate(); + equals.setLeft(createIdentifierNode(nameOfTempVariable)); + equals.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + predList.add(equals); + exist.setIdentifiers(idList); + exist.setPredicate(createConjunction(predList)); + + AComprehensionSetExpression compre = new AComprehensionSetExpression(); + List<PExpression> tList = new ArrayList<PExpression>(); + tList.add(createIdentifierNode(nameOfTempVariable)); + compre.setIdentifiers(tList); + compre.setPredicates(exist); + return compre; + } + + case OPCODE_nrfs: + case OPCODE_fc: // Represents [x \in S |-> e]. + case OPCODE_rfs: { + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ExprNode[] bounds = n.getBdedQuantBounds(); + List<PExpression> idList = new ArrayList<PExpression>(); + List<PPredicate> predList = new ArrayList<PPredicate>(); + for (int i = 0; i < params.length; i++) { + for (int j = 0; j < params[i].length; j++) { + FormalParamNode p = params[i][j]; + AMemberPredicate member = new AMemberPredicate(); + member.setLeft(createIdentifierNode(p.getName().toString())); + ExprNode in = n.getBdedQuantBounds()[i]; + member.setRight(visitExprNodeExpression(in)); + predList.add(member); + idList.add(createIdentifierNode(p.getName().toString())); + } + } + ALambdaExpression lambda = new ALambdaExpression(); + lambda.setIdentifiers(idList); + lambda.setPredicate(createConjunction(predList)); + lambda.setExpression(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + return lambda; + } + + case OPCODE_fa: { // f[1] + AFunctionExpression func = new AFunctionExpression(); + func.setIdentifier(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + List<PExpression> paramList = new ArrayList<PExpression>(); + + ExprOrOpArgNode dom = n.getArgs()[1]; + if (dom instanceof OpApplNode + && ((OpApplNode) dom).getOperator().getName().toString() + .equals("$Tuple")) { + OpApplNode domOpAppl = (OpApplNode) dom; + for (int i = 0; i < domOpAppl.getArgs().length; i++) { + paramList.add(visitExprOrOpArgNodeExpression(domOpAppl + .getArgs()[i])); + } + } else { + paramList.add(visitExprOrOpArgNodeExpression(dom)); + } + func.setParameters(paramList); + return func; + } + + case OPCODE_domain: + return new ADomainExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0])); + + case OPCODE_sof: // [ A -> B] + return new ATotalFunctionExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case OPCODE_tup: { // $Tuple + List<PExpression> list = new ArrayList<PExpression>(); + for (int i = 0; i < n.getArgs().length; i++) { + list.add(visitExprOrOpArgNodeExpression(n.getArgs()[i])); + } + TLAType t = (TLAType) n.getToolObject(TYPE_ID); + if (t instanceof TupleType) { + return new ACoupleExpression(list); + } else { + return new ASequenceExtensionExpression(list); + } + } + + case OPCODE_cp: // $CartesianProd A \X B \X C + return new AMultOrCartExpression( + visitExprOrOpArgNodeExpression(n.getArgs()[0]), + visitExprOrOpArgNodeExpression(n.getArgs()[1])); + + case OPCODE_sor: { // $SetOfRcds [L1 : e1, L2 : e2] + SetType pow = (SetType) n.getToolObject(TYPE_ID); + StructType struct = (StructType) pow.getSubType(); + ExprOrOpArgNode[] args = n.getArgs(); + Hashtable<String, PExpression> pairTable = new Hashtable<String, PExpression>(); + for (int i = 0; i < args.length; i++) { + OpApplNode pair = (OpApplNode) args[i]; + StringNode stringNode = (StringNode) pair.getArgs()[0]; + pairTable.put(stringNode.getRep().toString(), + visitExprOrOpArgNodeExpression(pair.getArgs()[1])); + + } + List<PRecEntry> recList = new ArrayList<PRecEntry>(); + for (int i = 0; i < struct.getFields().size(); i++) { + String fieldName = struct.getFields().get(i); + AIdentifierExpression field = createIdentifierNode(fieldName); + ARecEntry rec = new ARecEntry(); + rec.setIdentifier(field); + if (pairTable.containsKey(fieldName)) { + rec.setValue(pairTable.get(fieldName)); + } else { + rec.setValue(struct.getType(fieldName).getBNode()); + } + recList.add(rec); + } + + return new AStructExpression(recList); + } + + case OPCODE_rc: { // [h_1 |-> 1, h_2 |-> 2] + StructType struct = (StructType) n.getToolObject(TYPE_ID); + Hashtable<String, PExpression> pairTable = new Hashtable<String, PExpression>(); + ExprOrOpArgNode[] args = n.getArgs(); + for (int i = 0; i < args.length; i++) { + OpApplNode pair = (OpApplNode) args[i]; + StringNode stringNode = (StringNode) pair.getArgs()[0]; + pairTable.put(stringNode.getRep().toString(), + visitExprOrOpArgNodeExpression(pair.getArgs()[1])); + } + List<PRecEntry> recList = new ArrayList<PRecEntry>(); + for (int i = 0; i < struct.getFields().size(); i++) { + String fieldName = struct.getFields().get(i); + AIdentifierExpression field = createIdentifierNode(fieldName); + ARecEntry rec = new ARecEntry(); + rec.setIdentifier(field); + if (pairTable.containsKey(fieldName)) { + rec.setValue(pairTable.get(fieldName)); + } else { + // insert null element + } + recList.add(rec); + } + + return new ARecExpression(recList); + } + + case OPCODE_rs: { // $RcdSelect r.c + ARecordFieldExpression rcdSelect = new ARecordFieldExpression(); + rcdSelect.setRecord(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + StringNode stringNode = (StringNode) n.getArgs()[1]; + rcdSelect.setIdentifier(createIdentifierNode(stringNode.getRep() + .toString())); + return rcdSelect; + } + + case OPCODE_prime: // prime + { + OpApplNode node = (OpApplNode) n.getArgs()[0]; + return createIdentifierNode(node.getOperator().getName().toString() + + "_n"); + } + + } + + System.out.println(n.getOperator().getName()); + throw new RuntimeException(); + } + + private PPredicate visitBuiltInKindPredicate(OpApplNode n) { + switch (getOpCode(n.getOperator().getName())) { + case OPCODE_land: // \land + { + AConjunctPredicate conjunction = new AConjunctPredicate(); + conjunction.setLeft(visitExprOrOpArgNodePredicate(n.getArgs()[0])); + conjunction.setRight(visitExprOrOpArgNodePredicate(n.getArgs()[1])); + return conjunction; + } + + case OPCODE_cl: // $ConjList + { + List<PPredicate> list = new ArrayList<PPredicate>(); + for (int i = 0; i < n.getArgs().length; i++) { + list.add(visitExprOrOpArgNodePredicate(n.getArgs()[i])); + } + return createConjunction(list); + } + + case OPCODE_lor: // \/ + { + ADisjunctPredicate disjunction = new ADisjunctPredicate(); + disjunction.setLeft(visitExprOrOpArgNodePredicate(n.getArgs()[0])); + disjunction.setRight(visitExprOrOpArgNodePredicate(n.getArgs()[1])); + return disjunction; + } + + case OPCODE_dl: // $DisjList + { + List<PPredicate> list = new ArrayList<PPredicate>(); + for (int i = 0; i < n.getArgs().length; i++) { + list.add(visitExprOrOpArgNodePredicate(n.getArgs()[i])); + } + return createDisjunction(list); + } + + case OPCODE_lnot: // \lnot + return new ANegationPredicate( + visitExprOrOpArgNodePredicate(n.getArgs()[0])); + + case OPCODE_equiv: // \equiv + return new AEquivalencePredicate( + visitExprOrOpArgNodePredicate(n.getArgs()[0]), + visitExprOrOpArgNodePredicate(n.getArgs()[1])); + + case OPCODE_implies: // => + return new AImplicationPredicate( + visitExprOrOpArgNodePredicate(n.getArgs()[0]), + visitExprOrOpArgNodePredicate(n.getArgs()[1])); + + case OPCODE_be: { // \E x \in S : P + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ArrayList<PExpression> list = new ArrayList<PExpression>(); + for (int i = 0; i < params.length; i++) { + for (int j = 0; j < params[i].length; j++) { + list.add(createIdentifierNode(params[i][j].getName() + .toString())); + } + } + AConjunctPredicate conjunction = new AConjunctPredicate(); + conjunction.setLeft(visitBounded(n)); + conjunction.setRight(visitExprOrOpArgNodePredicate(n.getArgs()[0])); + return new AExistsPredicate(list, conjunction); + } + + case OPCODE_bf: { // \A x \in S : P + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ArrayList<PExpression> list = new ArrayList<PExpression>(); + for (int i = 0; i < params.length; i++) { + for (int j = 0; j < params[i].length; j++) { + list.add(createIdentifierNode(params[i][j].getName() + .toString())); + } + } + AImplicationPredicate implication = new AImplicationPredicate(); + implication.setLeft(visitBounded(n)); + implication.setRight(visitExprOrOpArgNodePredicate(n.getArgs()[0])); + return new AForallPredicate(list, implication); + } + + case OPCODE_eq: { // = + AEqualPredicate equal = new AEqualPredicate(); + equal.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + equal.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return equal; + } + + case OPCODE_noteq: // /= + { + ANotEqualPredicate notEqual = new ANotEqualPredicate(); + notEqual.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + notEqual.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return notEqual; + } + + case OPCODE_in: // \in + { + AMemberPredicate memberPredicate = new AMemberPredicate(); + memberPredicate + .setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + memberPredicate + .setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return memberPredicate; + } + + case OPCODE_notin: // \notin + { + ANotMemberPredicate notMemberPredicate = new ANotMemberPredicate(); + notMemberPredicate.setLeft(visitExprOrOpArgNodeExpression(n + .getArgs()[0])); + notMemberPredicate.setRight(visitExprOrOpArgNodeExpression(n + .getArgs()[1])); + return notMemberPredicate; + } + + case OPCODE_subseteq: // \subseteq {1,2} <: {1,2,3} + { + ASubsetPredicate subset = new ASubsetPredicate(); + subset.setLeft(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + subset.setRight(visitExprOrOpArgNodeExpression(n.getArgs()[1])); + return subset; + } + + case OPCODE_fa: { // f[1] + AFunctionExpression func = new AFunctionExpression(); + func.setIdentifier(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + List<PExpression> paramList = new ArrayList<PExpression>(); + + ExprOrOpArgNode dom = n.getArgs()[1]; + if (dom instanceof OpApplNode + && ((OpApplNode) dom).getOperator().getName().toString() + .equals("$Tuple")) { + OpApplNode domOpAppl = (OpApplNode) dom; + for (int i = 0; i < domOpAppl.getArgs().length; i++) { + paramList.add(visitExprOrOpArgNodeExpression(domOpAppl + .getArgs()[i])); + } + } else { + paramList.add(visitExprOrOpArgNodeExpression(dom)); + } + func.setParameters(paramList); + return new AEqualPredicate(func, new ABooleanTrueExpression()); + } + + case OPCODE_rs: { // $RcdSelect r.c + ARecordFieldExpression rcdSelect = new ARecordFieldExpression(); + rcdSelect.setRecord(visitExprOrOpArgNodeExpression(n.getArgs()[0])); + StringNode stringNode = (StringNode) n.getArgs()[1]; + rcdSelect.setIdentifier(createIdentifierNode(stringNode.getRep() + .toString())); + return new AEqualPredicate(rcdSelect, new ABooleanTrueExpression()); + } + + case OPCODE_prime: // prime + { + OpApplNode node = (OpApplNode) n.getArgs()[0]; + return new AEqualPredicate(createIdentifierNode(node.getOperator() + .getName().toString() + + "_n"), new ABooleanTrueExpression()); + } + + case 0: + return visitBBuitInsPredicate(n); + + } + + System.out.println(n.getOperator().getName()); + throw new RuntimeException(); + } + + private PPredicate visitBounded(OpApplNode n) { + FormalParamNode[][] params = n.getBdedQuantSymbolLists(); + ExprNode[] in = n.getBdedQuantBounds(); + boolean[] isTuple = n.isBdedQuantATuple(); + + List<PPredicate> predList = new ArrayList<PPredicate>(); + for (int i = 0; i < params.length; i++) { + if (isTuple[i]) { + + ArrayList<PExpression> list = new ArrayList<PExpression>(); + for (int j = 0; j < params[i].length; j++) { + list.add(createIdentifierNode(params[i][j].getName() + .toString())); + } + AMemberPredicate member = new AMemberPredicate(); + member.setLeft(new ACoupleExpression(list)); + member.setRight(visitExprNodeExpression(in[i])); + predList.add(member); + } else { + for (int j = 0; j < params[i].length; j++) { + AMemberPredicate member = new AMemberPredicate(); + member.setLeft(createIdentifierNode(params[i][j].getName() + .toString())); + member.setRight(visitExprNodeExpression(in[i])); + predList.add(member); + } + } + } + return createConjunction(predList); + } + + private PPredicate visitExprOrOpArgNodePredicate(ExprOrOpArgNode n) { + if (n instanceof ExprNode) { + return visitExprNodePredicate((ExprNode) n); + } else { + throw new RuntimeException("OpArgNode not implemented jet"); + } + } + + private PExpression visitExprOrOpArgNodeExpression(ExprOrOpArgNode n) { + + if (n instanceof ExprNode) { + return visitExprNodeExpression((ExprNode) n); + } else { + throw new RuntimeException("OpArgNode not implemented jet"); + } + } + + public static AIdentifierExpression createIdentifierNode(String name) { + return new AIdentifierExpression(createTIdentifierLiteral(name)); + } + + private PPredicate createConjunction(List<PPredicate> list) { + if (list.size() == 1) + return list.get(0); + AConjunctPredicate conj = new AConjunctPredicate(); + conj.setLeft(list.get(0)); + for (int i = 1; i < list.size(); i++) { + if (i < list.size() - 1) { + conj.setRight(list.get(i)); + conj = new AConjunctPredicate(conj, null); + } else { + conj.setRight(list.get(i)); + } + } + return conj; + } + + private PPredicate createDisjunction(List<PPredicate> list) { + if (list.size() == 1) + return list.get(0); + ADisjunctPredicate disjunction = new ADisjunctPredicate(); + disjunction.setLeft(list.get(0)); + for (int i = 1; i < list.size(); i++) { + if (i < list.size() - 1) { + disjunction.setRight(list.get(i)); + disjunction = new ADisjunctPredicate(disjunction, null); + } else { + disjunction.setRight(list.get(i)); + } + } + return disjunction; + } + + public static List<TIdentifierLiteral> createTIdentifierLiteral(String name) { + List<TIdentifierLiteral> list = new ArrayList<TIdentifierLiteral>(); + TIdentifierLiteral tid = new TIdentifierLiteral(name); + list.add(tid); + return list; + } + +} diff --git a/src/main/java/de/tla2b/pprint/BMachinePrinter.java b/src/main/java/de/tla2b/pprint/BMachinePrinter.java new file mode 100644 index 0000000000000000000000000000000000000000..555df520e439cb5ad8f0164c39e00e8651402024 --- /dev/null +++ b/src/main/java/de/tla2b/pprint/BMachinePrinter.java @@ -0,0 +1,697 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.pprint; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Set; + +import de.tla2b.analysis.BOperation; +import de.tla2b.analysis.RecursiveFunktion; +import de.tla2b.analysis.SpecAnalyser; +import de.tla2b.config.ConfigfileEvaluator; +import de.tla2b.config.ValueObj; +import de.tla2b.global.BBuiltInOPs; +import de.tla2b.global.TranslationGlobals; +import de.tla2b.types.EnumType; +import de.tla2b.types.SetType; +import de.tla2b.types.TLAType; + +import tla2sany.semantic.AssumeNode; +import tla2sany.semantic.ExprNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.LetInNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; +import tlc2.value.SetEnumValue; + +public class BMachinePrinter extends AbstractExpressionPrinter implements + TranslationGlobals { + private ModuleNode module; + private ArrayList<OpDeclNode> bConstants; + private ArrayList<ExprNode> inits; + private ArrayList<BOperation> bOperations; + private ArrayList<OpDefNode> invariants; + private ArrayList<LetInNode> globalLets; + private ArrayList<String> setEnumeration; + private ArrayList<String> definitionMacro; + private Hashtable<OpDeclNode, ValueObj> constantAssignments; + private ArrayList<OpDefNode> operatorModelvalues; + private Set<OpDefNode> bDefinitions; + // set of OpDefNodes which are called in the specification + private Hashtable<OpDefNode, FormalParamNode[]> letParams; + + private ArrayList<RecursiveFunktion> recursiveFunktions; + private ArrayList<LetInNode> tempLetInNodes = new ArrayList<LetInNode>(); + + /** + * @param moduleNode + * @param conEval + * @param specAnalyser + */ + public BMachinePrinter(ModuleNode moduleNode, ConfigfileEvaluator conEval, + SpecAnalyser specAnalyser) { + this.module = moduleNode; + + if (conEval == null) { + bConstants = new ArrayList<OpDeclNode>(); + for (int i = 0; i < moduleNode.getConstantDecls().length; i++) { + bConstants.add(moduleNode.getConstantDecls()[i]); + } + } else { + this.bConstants = conEval.getbConstantList(); + this.invariants = conEval.getInvariants(); + this.setEnumeration = conEval.getEnumerationSet(); + this.constantAssignments = conEval.getConstantAssignments(); + this.operatorModelvalues = conEval.getOperatorModelvalues(); + } + + this.inits = specAnalyser.getInits(); + this.bOperations = specAnalyser.getBOperations(); + this.globalLets = specAnalyser.getGlobalLets(); + this.definitionMacro = specAnalyser.getDefinitionMacros(); + this.bDefinitions = specAnalyser.getBDefinitions(); + this.letParams = specAnalyser.getLetParams(); + this.recursiveFunktions = specAnalyser.getRecursiveFunctions(); + } + + public StringBuilder start() { + StringBuilder out = new StringBuilder(); + out.append("MACHINE " + module.getName().toString() + "\n"); + + out.append(evalEnumeratedSets()); + + // Constants and Properties + out.append(evalConsDecl()); + out.append(evalPropertyStatements()); + tempLetInNodes.clear(); + StringBuilder operations = evalOperations(); + globalLets.addAll(tempLetInNodes); + tempLetInNodes.clear(); + + out.append(evalDefinitions()); + + out.append(evalVariables()); + + out.append(evalInvariants()); + + out.append(evalInit()); + + out.append(operations); + out.append("END"); + return out; + } + + /** + * @return + */ + private StringBuilder evalEnumeratedSets() { + StringBuilder out = new StringBuilder(); + + if (setEnumeration == null || setEnumeration.size() == 0) + return out; + + out.append("SETS\n "); + + ArrayList<EnumType> printed = new ArrayList<EnumType>(); + int counter = 1; + + OpDeclNode[] cons = module.getConstantDecls(); + boolean first = true; + for (int i = 0; i < cons.length; i++) { + TLAType type = (TLAType) cons[i].getToolObject(TYPE_ID); + EnumType e = null; + if (type instanceof SetType) { + if (((SetType) type).getSubType() instanceof EnumType) { + e = (EnumType) ((SetType) type).getSubType(); + } else + continue; + + } else if ((type instanceof EnumType)) { + e = (EnumType) type; + } else + continue; + + if (!printed.contains(e)) { + e.id = counter; + if (!first) { + out.append("; "); + } + out.append("ENUM" + counter + " = {"); + Iterator<String> it2 = e.modelvalues.iterator(); + while (it2.hasNext()) { + out.append(it2.next()); + if (it2.hasNext()) { + out.append(", "); + } + } + if (e.hasNoVal()) { + out.append(", noVal" + counter); + } + out.append("}"); + printed.add(e); + counter++; + first = false; + } + } + + if (operatorModelvalues != null && operatorModelvalues.size() > 0) { + for (int i = 0; i < operatorModelvalues.size(); i++) { + OpDefNode def = operatorModelvalues.get(i); + TLAType type = (TLAType) def.getToolObject(TYPE_ID); + EnumType e = null; + if (type instanceof SetType) { + if (((SetType) type).getSubType() instanceof EnumType) { + e = (EnumType) ((SetType) type).getSubType(); + } else + continue; + + } else if ((type instanceof EnumType)) { + e = (EnumType) type; + } else + continue; + + if (!printed.contains(e)) { + e.id = counter; + if (!first) { + out.append("; "); + } + out.append("ENUM" + counter + " = {"); + Iterator<String> it2 = e.modelvalues.iterator(); + while (it2.hasNext()) { + out.append(it2.next()); + if (it2.hasNext()) { + out.append(", "); + } + } + if (e.hasNoVal()) { + out.append(", noVal" + counter); + } + out.append("}"); + printed.add(e); + counter++; + first = false; + } + + } + + } + + out.append("\n"); + return out; + } + + private StringBuilder evalInvariants() { + StringBuilder out = new StringBuilder(); + OpDeclNode[] vars = module.getVariableDecls(); + if (vars.length > 0) { + out.append("INVARIANT\n "); + for (int i = 0; i < vars.length; i++) { + TLAType varType = (TLAType) vars[i].getToolObject(TYPE_ID); + out.append(getPrintName(vars[i]) + " : " + varType + "\n"); + if (i != vars.length - 1) + out.append(" & "); + } + if (invariants != null) { + for (int i = 0; i < invariants.size(); i++) { + out.append(" & " + invariants.get(i).getName().toString() + + "\n"); + } + } + } + return out; + } + + private StringBuilder evalInit() { + StringBuilder out = new StringBuilder(); + OpDeclNode[] vars = module.getVariableDecls(); + if (vars.length == 0) + return out; + out.append("INITIALISATION\n "); + for (int i = 0; i < vars.length; i++) { + out.append(getPrintName(vars[i])); + if (i < vars.length - 1) + out.append(", "); + } + out.append(":("); + for (int i = 0; i < inits.size(); i++) { + if (i != 0) { + out.append(" & "); + } + out.append(visitExprNode(inits.get(i), new DContext(), PREDICATE).out); + } + out.append(")\n"); + return out; + } + + private StringBuilder evalOperations() { + StringBuilder out = new StringBuilder(); + if (bOperations == null) + return out; + + out.append("OPERATIONS\n"); + for (int i = 0; i < bOperations.size(); i++) { + BOperation op = bOperations.get(i); + String defName = op.getName(); + + DContext d = new DContext("\t"); + out.append(" " + defName.replace('!', '_') + "_Op"); + if (op.getOpParams().size() > 0) { + out.append("("); + for (int j = 0; j < op.getOpParams().size(); j++) { + if (j != 0) + out.append(", "); + out.append(op.getOpParams().get(j)); + } + out.append(")"); + } + out.append(" = "); + out.append("ANY "); + OpDeclNode[] vars = module.getVariableDecls(); + boolean first = true; + for (int j = 0; j < vars.length; j++) { + String varName = vars[j].getName().toString(); + if (op.getUnchangedVariables().contains(varName)) + continue; + if (!first) { + out.append(", "); + } + out.append(varName + "_n"); + first = false; + } + out.append("\n\tWHERE "); + if (op.getOpParams().size() > 0) { + for (int j = 0; j < op.getExistQuans().size(); j++) { + OpApplNode o = op.getExistQuans().get(j); + out.append(visitBounded(o, d)); + out.append(" & "); + } + out.append("\n\t "); + } + for (int j = 0; j < vars.length; j++) { + String varName = vars[j].getName().toString(); + if (op.getUnchangedVariables().contains(varName)) + continue; + out.append(varName + "_n : " + vars[j].getToolObject(TYPE_ID)); + out.append(" & "); + } + out.append(visitExprOrOpArgNode(op.getNode(), d, PREDICATE).out); + + out.append("\n\tTHEN "); + + boolean first2 = true; + for (int j = 0; j < vars.length; j++) { + String varName = vars[j].getName().toString(); + if (op.getUnchangedVariables().contains(varName)) + continue; + if (!first2) { + out.append(", "); + } + out.append(varName); + first2 = false; + } + + out.append(" := "); + + boolean first3 = true; + for (int j = 0; j < vars.length; j++) { + String varName = vars[j].getName().toString(); + if (op.getUnchangedVariables().contains(varName)) + continue; + if (!first3) { + out.append(", "); + } + out.append(varName + "_n"); + first3 = false; + } + out.append(" END"); + if (i != bOperations.size() - 1) { + out.append(";\n\n"); + } + } + out.append("\n"); + return out; + } + + private StringBuilder evalVariables() { + StringBuilder out = new StringBuilder(); + OpDeclNode[] vars = module.getVariableDecls(); + if (vars.length > 0) { + out.append("VARIABLES\n "); + for (int i = 0; i < vars.length; i++) { + String[] comments = vars[i].getPreComments(); + if (comments.length > 0) { + String pragma = comments[comments.length - 1]; + if (pragma.startsWith("(*@")) { + pragma = pragma.replace('(', '/').replace(')', '/'); + out.append(pragma).append(" "); + } + + } + out.append(getPrintName(vars[i])); + if (i != vars.length - 1) + out.append(",\n "); + } + out.append("\n"); + } + return out; + } + + private StringBuilder evalDefinitions() { + StringBuilder out = new StringBuilder(); + ArrayList<OpDefNode> bDefs = new ArrayList<OpDefNode>(); + for (int i = 0; i < module.getOpDefs().length; i++) { + OpDefNode def = module.getOpDefs()[i]; + if (bDefinitions.contains(def)) + bDefs.add(def); + } + + if (bDefs.size() + globalLets.size() + definitionMacro.size() == 0) + return out; + out.append("DEFINITIONS\n"); + for (int i = 0; i < definitionMacro.size(); i++) { + out.append(definitionMacro.get(i)); + if (i != definitionMacro.size() - 1 + || bDefs.size() + globalLets.size() > 0) { + out.append(";\n"); + } + } + + for (int i = 0; i < bDefs.size(); i++) { + out.append(visitOpDefNode(bDefs.get(i))); + if (!(i == bDefs.size() - 1 && globalLets.size() == 0)) + out.append(";\n\n"); + } + + for (int i = 0; i < globalLets.size(); i++) { + LetInNode letInNode = globalLets.get(i); + for (int j = 0; j < letInNode.getLets().length; j++) { + out.append(evalLet(letInNode.getLets()[j])); + if (i != letInNode.getLets().length - 1) + out.append(";\n"); + } + if (i != globalLets.size() - 1) + out.append(";\n"); + } + out.append("\n"); + return out; + } + + /** + * @param letDef + * @return + */ + private StringBuilder evalLet(OpDefNode letDef) { + StringBuilder out = new StringBuilder(); + String defName = getPrintName(letDef); + out.append(" " + defName); + FormalParamNode[] shiftParams = letParams.get(letDef); + if (shiftParams == null) + shiftParams = new FormalParamNode[0]; + if (letDef.getParams().length + shiftParams.length > 0) { + out.append("("); + for (int i = 0; i < letDef.getParams().length; i++) { + if (i != 0) + out.append(","); + out.append(letDef.getParams()[i].getName().toString()); + } + for (int i = 0; i < shiftParams.length; i++) { + if (letDef.getParams().length > 0 || i != 0) + out.append(", "); + out.append(shiftParams[i].getName().toString()); + + } + out.append(")"); + } + out.append(" == "); + DContext d = new DContext("\t"); + out.append(visitExprNode(letDef.getBody(), d, VALUEORPREDICATE).out); + return out; + + } + + /** + * @param def + */ + private StringBuilder visitOpDefNode(OpDefNode def) { + StringBuilder out = new StringBuilder(); + // ConstantObj conObj = (ConstantObj) def.getSource().getToolObject( + // CONSTANT_OBJECT); + // if (conObj != null) { + // System.out.println("hier"); + // // config substitution + // // out.append(" " + defName.replace('!', '_')); + // String defName = getPrintName(def); + // String defValue = conObj.getValue().toString(); + // if(defName.equals(defName.equals(defValue))) + // return out; + // out.append(" " + defName); + // out.append(" == " + defValue); + // return out; + // } + + DContext d = new DContext("\t"); + tempLetInNodes.clear(); + StringBuilder body = visitExprNode(def.getBody(), d, VALUEORPREDICATE).out; + + for (int i = 0; i < tempLetInNodes.size(); i++) { + LetInNode letInNode = tempLetInNodes.get(i); + for (int j = 0; j < letInNode.getLets().length; j++) { + out.append(evalLet(letInNode.getLets()[j])); + out.append(";\n"); + } + + } + tempLetInNodes.clear(); + + out.append(" " + getPrintName(def)); + FormalParamNode[] params = def.getParams(); + if (params.length > 0) { + out.append("("); + for (int i = 0; i < params.length; i++) { + if (i != 0) + out.append(", "); + out.append(getPrintName(params[i])); + } + out.append(")"); + } + out.append(" == "); + out.append(body); + return out; + } + + private StringBuilder evalConsDecl() { + StringBuilder out = new StringBuilder(); + if (bConstants.size() + recursiveFunktions.size() == 0) + return out; + out.append("ABSTRACT_CONSTANTS\n"); + // out.append("CONSTANTS "); + for (int i = 0; i < bConstants.size(); i++) { + String[] comments = bConstants.get(i).getPreComments(); + if (comments.length > 0) { + String pragma = comments[comments.length - 1]; + if (pragma.startsWith("(*@")) { + pragma = pragma.replace('(', '/').replace(')', '/'); + out.append(pragma).append(" "); + } + + } + out.append(getPrintName(bConstants.get(i))); + if (i < bConstants.size() - 1 || recursiveFunktions.size() > 0) + out.append(",\n "); + } + for (int i = 0; i < recursiveFunktions.size(); i++) { + out.append(getPrintName(recursiveFunktions.get(i).getOpDefNode())); + if (i < recursiveFunktions.size() - 1) + out.append(", "); + } + out.append("\n"); + return out; + } + + private StringBuilder evalPropertyStatements() { + StringBuilder out = new StringBuilder(); + if (bConstants.size() == 0 && module.getAssumptions().length == 0) { + return out; + } + out.append("PROPERTIES\n "); + boolean notFirst = false; + for (int i = 0; i < bConstants.size(); i++) { + OpDeclNode con = bConstants.get(i); + if (notFirst) { + out.append(" & "); + } + if (constantAssignments != null + && constantAssignments.containsKey(con)) { + ValueObj v = constantAssignments.get(con); + TLAType t = v.getType(); + boolean isEnum = false; + if (t instanceof SetType) { + TLAType sub = ((SetType) t).getSubType(); + if (sub instanceof EnumType) { + EnumType en = (EnumType) sub; + SetEnumValue set = (SetEnumValue) v.getValue(); + if (set.elems.size() == en.modelvalues.size()) { + isEnum = true; + } + } + } + if (isEnum) { + out.append(String.format("%s = %s\n", getPrintName(con), + ((SetType) t).getSubType())); + } else { + out.append(String.format("%s = %s\n", getPrintName(con), v + .getValue().toString())); + } + + } else { + out.append(String.format("%s : %s\n", getPrintName(con), + con.getToolObject(TYPE_ID))); + } + + notFirst = true; + } + out.append(evalAssumptions()); + return out; + } + + private StringBuilder evalAssumptions() { + AssumeNode[] assumes = module.getAssumptions(); + StringBuilder out = new StringBuilder(); + if (assumes.length == 0) + return out; + if (bConstants.size() > 0) { + out.append(" & "); + } + tempLetInNodes.clear(); + for (int i = 0; i < assumes.length; i++) { + if (i != 0) { + out.append(" & "); + } + out.append(visitAssumeNode(assumes[i])); + out.append("\n"); + } + globalLets.addAll(tempLetInNodes); + tempLetInNodes.clear(); + + if (recursiveFunktions.size() == 0) + return out; + if (bConstants.size() + assumes.length > 0) { + out.append(" & "); + } + for (int i = 0; i < recursiveFunktions.size(); i++) { + if (i != 0) { + out.append(" & "); + } + out.append(visitRecursiveFunction(recursiveFunktions.get(i))); + out.append("\n"); + } + + return out; + } + + /** + * @param recursiveFunktion + * @return + */ + private StringBuilder visitRecursiveFunction(RecursiveFunktion rf) { + StringBuilder out = new StringBuilder(); + OpApplNode o = rf.getRF(); + OpApplNode ifThenElse = rf.getIfThenElse(); + out.append(getPrintName(rf.getOpDefNode())); + out.append(" = "); + + DContext d = new DContext(); + + FormalParamNode[][] vars = o.getBdedQuantSymbolLists(); + StringBuilder pre = new StringBuilder(); + for (int i = 0; i < vars.length; i++) { + for (int j = 0; j < vars[i].length; j++) { + pre.append(vars[i][j].getName()); + if (j < vars[i].length - 1) { + pre.append(","); + } + } + if (i < vars.length - 1) { + pre.append(","); + } + } + StringBuilder bound = visitBounded(o, d); + + ExprReturn iif = visitExprOrOpArgNode(ifThenElse.getArgs()[0], d, + PREDICATE); + ExprReturn then = visitExprOrOpArgNode(ifThenElse.getArgs()[1], d, + VALUE); + ExprReturn eelse = visitExprOrOpArgNode(ifThenElse.getArgs()[2], d, + VALUE); + String res = String.format( + "%%%s.(%s & %s | %s) \\/ %%%s.(%s & not(%s) | %s)", pre, bound, + iif.out, then.out, pre, bound, iif.out, eelse.out); + out.append(res); + return out; + } + + private StringBuilder visitAssumeNode(AssumeNode n) { + // there are named or unnamend assumptions + StringBuilder out = new StringBuilder(); + DContext d = new DContext(); + out.append(visitExprNode(n.getAssume(), d, PREDICATE).out); + + return out; + } + + @Override + protected ExprReturn visitLetInNode(LetInNode l, DContext d, int expected) { + tempLetInNodes.add(l); + return visitExprNode(l.getBody(), d, VALUEORPREDICATE); + } + + @Override + protected ExprReturn visitUserdefinedOp(OpApplNode n, DContext d, + int expected) { + StringBuilder out = new StringBuilder(); + OpDefNode def = (OpDefNode) n.getOperator(); + // Operator is a B built-in operator + if (BBuiltInOPs.contains(def.getName()) + && STANDARD_MODULES.contains(def.getSource() + .getOriginallyDefinedInModuleNode().getName() + .toString())) { + return evalBBuiltIns(n, d, expected); + } + + out.append(getPrintName(def)); + + FormalParamNode[] shiftedParams = letParams.get(def); + if (n.getArgs().length > 0 + || (shiftedParams != null && shiftedParams.length > 0)) { + out.append("("); + for (int i = 0; i < n.getArgs().length; i++) { + out.append(visitExprOrOpArgNode(n.getArgs()[i], d, VALUE).out); + if (i < n.getArgs().length - 1) { + out.append(", "); + } + } + if (shiftedParams != null) { + for (int i = 0; i < shiftedParams.length; i++) { + if (n.getArgs().length > 0 || i != 0) + out.append(", "); + out.append(shiftedParams[i].getName().toString()); + + } + } + out.append(")"); + + } + TLAType defType = (TLAType) n.getToolObject(TYPE_ID); + if (defType != null && defType.getKind() == BOOL) { + return makeBoolValue(out, expected, P_max); + } + return new ExprReturn(out); + } + +} diff --git a/src/main/java/de/tla2b/pprint/DContext.java b/src/main/java/de/tla2b/pprint/DContext.java new file mode 100644 index 0000000000000000000000000000000000000000..988026efabe0eb6bc5b993f389e58f7a586ecc6e --- /dev/null +++ b/src/main/java/de/tla2b/pprint/DContext.java @@ -0,0 +1,18 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.pprint; + +public class DContext { + public StringBuilder indent; + + + public DContext(){ + indent = new StringBuilder(); + } + + public DContext(String indent){ + this.indent = new StringBuilder(indent); + } +} diff --git a/src/main/java/de/tla2b/pprint/ExprReturn.java b/src/main/java/de/tla2b/pprint/ExprReturn.java new file mode 100644 index 0000000000000000000000000000000000000000..dfe31fd78ba7f7f799d896a141b2fadf79ab75bb --- /dev/null +++ b/src/main/java/de/tla2b/pprint/ExprReturn.java @@ -0,0 +1,53 @@ +package de.tla2b.pprint; + +public class ExprReturn { + public StringBuilder out= new StringBuilder(); + private int priority; + + + public ExprReturn(){ + priority = 300; + } + + public ExprReturn(String s){ + out.append(s); + priority = 300; + } + + public ExprReturn(StringBuilder out2) { + out.append(out2); + priority = 300; + } + + public ExprReturn(StringBuilder out2, int priority2) { + out.append(out2); + priority = priority2; + } + + public ExprReturn(String out2, int priority2) { + out.append(out2); + priority = priority2; + } + + + + public StringBuilder getOut() { + return out; + } + public void setOut(StringBuilder out) { + this.out = out; + } + public int getPriority() { + return priority; + } + public void setPriority(int priority) { + this.priority = priority; + } + + @Override + public String toString(){ + String s = "P: "+ priority + " Out: " +out.toString(); + return s; + } + +} diff --git a/src/main/java/de/tla2b/pprint/ExpressionPrinter.java b/src/main/java/de/tla2b/pprint/ExpressionPrinter.java new file mode 100644 index 0000000000000000000000000000000000000000..bb2e432b6faef92836da7cdbce289df144a04a57 --- /dev/null +++ b/src/main/java/de/tla2b/pprint/ExpressionPrinter.java @@ -0,0 +1,103 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.pprint; + + +import java.util.Hashtable; + +import de.tla2b.global.BBuiltInOPs; +import de.tla2b.types.TLAType; + +import tla2sany.semantic.ExprOrOpArgNode; +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.OpApplNode; +import tla2sany.semantic.OpDefNode; + +public class ExpressionPrinter extends AbstractExpressionPrinter { + + private Hashtable<FormalParamNode, ExprOrOpArgNode> paramterSubstitution; + private ModuleNode moduleNode; + private StringBuilder BExpression; + + public ExpressionPrinter(ModuleNode n) { + this.moduleNode = n; + paramterSubstitution = new Hashtable<FormalParamNode, ExprOrOpArgNode>(); + } + + public void start() { + OpDefNode[] defs = moduleNode.getOpDefs(); + ExprReturn e = visitExprNode(defs[defs.length - 1].getBody(), + new DContext(), VALUEORPREDICATE); + BExpression = e.out; + } + + public StringBuilder getBExpression() { + return BExpression; + } + + @Override + protected ExprReturn visitUserdefinedOp(OpApplNode n, DContext d, + int expected) { + OpDefNode def = (OpDefNode) n.getOperator(); + if (BBuiltInOPs.contains(def.getName())) { + return evalBBuiltIns(n, d, expected); + } + + // substitute the parameters and inline the boby of the operator + FormalParamNode[] params = def.getParams(); + if (params.length > 0) { + for (int i = 0; i < n.getArgs().length; i++) { + this.paramterSubstitution.put(params[i], n.getArgs()[i]); + } + } + return visitExprNode(def.getBody(), new DContext(), expected); + } + + @Override + protected ExprReturn evalIfThenElse(OpApplNode n, DContext d, int expected) { + TLAType t = (TLAType) n.getToolObject(TYPE_ID); + + if (t.getKind() == BOOL) { + d.indent.append(" "); + ExprReturn iif = visitExprOrOpArgNode(n.getArgs()[0], d, PREDICATE); + ExprReturn then = visitExprOrOpArgNode(n.getArgs()[1], d, PREDICATE); + ExprReturn eelse = visitExprOrOpArgNode(n.getArgs()[2], d, + PREDICATE); + String res = String.format( + "(%s \n%s => %s) \n\t & (not(%s) \n%s => %s)", + brackets(iif, P_implies, true), d.indent, + brackets(then, P_implies, false), iif.out, d.indent, + brackets(eelse, P_implies, false)); + return makeBoolValue(new StringBuilder(res), expected, P_and); + } else { + ExprReturn iif = visitExprOrOpArgNode(n.getArgs()[0], d, PREDICATE); + ExprReturn then = visitExprOrOpArgNode(n.getArgs()[1], d, VALUE); + ExprReturn eelse = visitExprOrOpArgNode(n.getArgs()[2], d, VALUE); + String res = String + .format("(%%t_.( t_ = 0 & %s | %s )\\/%%t_.( t_ = 0 & not(%s) | %s ))(0)", + iif.out, then.out, iif.out, eelse.out); + return new ExprReturn(res); + } + } + + @Override + protected ExprReturn visitFormalParamNode(OpApplNode n, DContext d, + int expected) { + StringBuilder out = new StringBuilder(); + ExprOrOpArgNode e = paramterSubstitution.get((FormalParamNode) n + .getOperator()); + if (e != null) { + return visitExprOrOpArgNode(e, d, expected); + } + out.append(getPrintName(n.getOperator())); + if (expected == PREDICATE) { + out.append(" = TRUE"); + return new ExprReturn(out, P_equals); + } + return new ExprReturn(out); + } + +} diff --git a/src/main/java/de/tla2b/translation/ExpressionTranslator.java b/src/main/java/de/tla2b/translation/ExpressionTranslator.java new file mode 100644 index 0000000000000000000000000000000000000000..61096f5f8ad306a47ca2db88c106769d4da8c8fd --- /dev/null +++ b/src/main/java/de/tla2b/translation/ExpressionTranslator.java @@ -0,0 +1,351 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.translation; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import de.tla2b.analysis.SymbolRenamer; +import de.tla2b.analysis.TypeChecker; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TLA2BIOException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.pprint.ExpressionPrinter; + +import tla2sany.drivers.FrontEndException; +import tla2sany.drivers.InitException; +import tla2sany.drivers.SANY; +import tla2sany.modanalyzer.ParseUnit; +import tla2sany.modanalyzer.SpecObj; +import tla2sany.parser.ParseException; +import tla2sany.semantic.ModuleNode; +import tla2sany.st.SyntaxTreeConstants; +import tla2sany.st.TreeNode; +import util.ToolIO; + +public class ExpressionTranslator implements SyntaxTreeConstants { + private String TLAExpression; + private ArrayList<String> variables; + private ArrayList<String> noVariables; + private StringBuilder BExpression; + + public static String translateExpression(String tlaExpression) + throws TLA2BException { + ToolIO.reset(); + ToolIO.setMode(ToolIO.TOOL); + ExpressionTranslator et = new ExpressionTranslator(tlaExpression); + try { + et.start(); + } catch (RuntimeException e) { + throw new TLA2BIOException(e.getMessage()); + } + + return et.BExpression.toString(); + } + + public ExpressionTranslator(String TLAExpression) { + this.TLAExpression = TLAExpression; + this.variables = new ArrayList<String>(); + this.noVariables = new ArrayList<String>(); + } + + public void start() throws TLA2BException { + + String dir = System.getProperty("java.io.tmpdir"); + ToolIO.setUserDir(dir); + + createStandardModule(dir); + + File tempFile = null; + String moduleName = null; + String module = null; + try { + tempFile = File.createTempFile("Testing", ".tla"); + + moduleName = tempFile.getName().substring(0, + tempFile.getName().indexOf(".")); + + module = "----MODULE " + moduleName + " ----\n" + + "Expression == " + TLAExpression + "\n===="; + + FileWriter fw = new FileWriter(tempFile); + fw.write(module); + fw.close(); + } catch (IOException e) { + throw new TLA2BIOException("Can not create file " + + tempFile.getName() + " in directory '" + dir + "'"); + } + + SpecObj spec = parseModuleWithoutSemanticAnalyse(moduleName, module); + evalVariables(spec, moduleName); + + StringBuilder sb = new StringBuilder(); + sb.append("----MODULE " + moduleName + " ----\n"); + sb.append("EXTENDS Naturals, Integers, Sequences, FiniteSets, TLA2B \n"); + if (variables.size() > 0) { + sb.append("VARIABLES "); + for (int i = 0; i < variables.size(); i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(variables.get(i)); + } + sb.append("\n"); + } + sb.append("Expression"); + sb.append(" == "); + sb.append(TLAExpression); + sb.append("\n===================="); + // System.out.println(sb); + + try { + FileWriter fw = new FileWriter(tempFile); + fw.write(sb.toString()); + fw.close(); + tempFile.deleteOnExit(); + } catch (IOException e) { + e.printStackTrace(); + throw new TLA2BIOException(e.getMessage()); + } + ToolIO.reset(); + BExpression = translate(moduleName, sb.toString()); + } + + private static StringBuilder translate(String moduleName, String expr) + throws TLA2BException { + + ModuleNode moduleNode = parseModule(moduleName, expr); + + TypeChecker tc = new TypeChecker(moduleNode); + try { + tc.start(); + } catch (TLA2BException e) { + String[] m = ToolIO.getAllMessages(); + String message = m[0] + "\n" + expr + "\n\n****TypeError****\n" + + e.getLocalizedMessage(); + // System.out.println(message); + throw new TypeErrorException(message); + } + + SymbolRenamer symRenamer = new SymbolRenamer(moduleNode); + symRenamer.start(); + + ExpressionPrinter p = new ExpressionPrinter(moduleNode); + p.start(); + return p.getBExpression(); + + } + + /** + * @param moduleFileName + * @throws de.tla2b.exceptions.FrontEndException + */ + private SpecObj parseModuleWithoutSemanticAnalyse(String moduleFileName, String module) + throws de.tla2b.exceptions.FrontEndException { + SpecObj spec = new SpecObj(moduleFileName, null); + + try { + SANY.frontEndInitialize(spec, ToolIO.out); + SANY.frontEndParse(spec, ToolIO.out); + + } catch (InitException e1) { + System.out.println(e1); + } catch (ParseException e1) { + System.out.println(e1); + } + + if (spec.parseErrors.isFailure()) { + String message = module + "\n\n"; + message += Tla2BTranslator.allMessagesToString(ToolIO + .getAllMessages()); + throw new de.tla2b.exceptions.FrontEndException(message, spec); + } + return spec; + } + + public static ModuleNode parseModule(String moduleName, String module) + throws de.tla2b.exceptions.FrontEndException { + SpecObj spec = new SpecObj(moduleName, null); + try { + SANY.frontEndMain(spec, moduleName, ToolIO.out); + } catch (FrontEndException e) { + // Error in Frontend, should never happens + return null; + } + + if (spec.parseErrors.isFailure()) { + String[] m = ToolIO.getAllMessages(); + String message = module + "\n\n" + + spec.parseErrors; + // System.out.println(spec.parseErrors); + message += Tla2BTranslator.allMessagesToString(ToolIO + .getAllMessages()); + throw new de.tla2b.exceptions.FrontEndException(message, spec); + } + + if (spec.semanticErrors.isFailure()) { + String[] m = ToolIO.getAllMessages(); + String message = module + "\n\n" + spec.semanticErrors; + message += Tla2BTranslator.allMessagesToString(ToolIO + .getAllMessages()); + throw new de.tla2b.exceptions.FrontEndException(message, spec); + } + + // RootModule + ModuleNode n = spec.getExternalModuleTable().rootModule; + if (spec.getInitErrors().isFailure()) { + System.err.println(spec.getInitErrors()); + throw new de.tla2b.exceptions.FrontEndException( + Tla2BTranslator + .allMessagesToString(ToolIO.getAllMessages()), + spec); + } + + if (n == null) { // Parse Error + // System.out.println("Rootmodule null"); + throw new de.tla2b.exceptions.FrontEndException( + Tla2BTranslator + .allMessagesToString(ToolIO.getAllMessages()), + spec); + } + return n; + } + + /** + * @param spec + * @return + */ + private void evalVariables(SpecObj spec, String moduleName) { + ParseUnit p = (ParseUnit) spec.parseUnitContext.get(moduleName); + TreeNode n_module = p.getParseTree(); + TreeNode n_body = n_module.heirs()[2]; + TreeNode n_operatorDefintion = n_body.heirs()[0]; + TreeNode expr = n_operatorDefintion.heirs()[2]; + searchVarInSyntaxTree(expr); + + for (int i = 0; i < noVariables.size(); i++) { + variables.remove(noVariables.get(i)); + } + + } + + private final static Set<String> KEYWORDS = new HashSet<String>(); + static { + KEYWORDS.add("BOOLEAN"); + KEYWORDS.add("TRUE"); + KEYWORDS.add("FALSE"); + KEYWORDS.add("Nat"); + KEYWORDS.add("Int"); + KEYWORDS.add("Cardinality"); + KEYWORDS.add("IsFiniteSet"); + KEYWORDS.add("Append"); + KEYWORDS.add("Head"); + KEYWORDS.add("Tail"); + KEYWORDS.add("Len"); + KEYWORDS.add("Seq"); + KEYWORDS.add("SubSeq"); + KEYWORDS.add("SelectSeq"); + KEYWORDS.add("MinOfSet"); + KEYWORDS.add("MaxOfSet"); + KEYWORDS.add("SetProduct"); + KEYWORDS.add("SetSummation"); + KEYWORDS.add("PermutedSequences"); + KEYWORDS.add("@"); + + } + + /** + * + */ + private void searchVarInSyntaxTree(TreeNode treeNode) { + // System.out.println(treeNode.getKind() + " " + treeNode.getImage()); + switch (treeNode.getKind()) { + case N_GeneralId: { + String con = treeNode.heirs()[1].getImage(); + if (!variables.contains(con) && !KEYWORDS.contains(con)) { + variables.add(con); + } + break; + } + case N_IdentLHS: { // left side of a definition + TreeNode[] children = treeNode.heirs(); + noVariables.add(children[0].getImage()); + break; + } + case N_IdentDecl: { // parameter of a LET definition + // e.g. x in LET foo(x) == e + noVariables.add(treeNode.heirs()[0].getImage()); + break; + } + case N_FunctionDefinition: { + // the first child is the function name + noVariables.add(treeNode.heirs()[0].getImage()); + break; + } + case N_UnboundQuant: { + TreeNode[] children = treeNode.heirs(); + for (int i = 1; i < children.length - 2; i = i + 2) { + // System.out.println(children[i].getImage()); + } + searchVarInSyntaxTree(treeNode.heirs()[children.length - 1]); + break; + } + case N_QuantBound: { + TreeNode[] children = treeNode.heirs(); + for (int i = 0; i < children.length - 2; i = i + 2) { + String boundedVar = children[i].getImage(); + if (!noVariables.contains(boundedVar)) { + noVariables.add(boundedVar); + } + } + searchVarInSyntaxTree(treeNode.heirs()[children.length - 1]); + break; + } + case N_SubsetOf: { // { x \in S : e } + TreeNode[] children = treeNode.heirs(); + String boundedVar = children[1].getImage(); // x + if (!noVariables.contains(boundedVar)) { + noVariables.add(boundedVar); + } + searchVarInSyntaxTree(treeNode.heirs()[3]); // S + searchVarInSyntaxTree(treeNode.heirs()[5]); // e + break; + } + + } + + for (int i = 0; i < treeNode.heirs().length; i++) { + searchVarInSyntaxTree(treeNode.heirs()[i]); + } + } + + private static File tla2b; + private void createStandardModule(String dir) throws TLA2BIOException { + tla2b = new File(dir, "TLA2B.tla"); + try { + tla2b.createNewFile(); + FileWriter fw = new FileWriter(tla2b); + fw.write(TLA2B); + fw.close(); + tla2b.deleteOnExit(); + } catch (IOException e) { + throw new TLA2BIOException( + "Can not create standard module TLA2B.tla in directory '" + + dir + "'"); + } + + } + + private static final String TLA2B = "--------- MODULE TLA2B ---------\n" + + "LOCAL INSTANCE Naturals \n" + "LOCAL INSTANCE Sequences \n" + + "MinOfSet(S) == CHOOSE p \\in S: \\A n \\in S: p \\leq n \n" + + "MaxOfSet(S) == CHOOSE p \\in S: \\A n \\in S: p \\geq n \n" + + "SetProduct(S) == S \n" + "SetSummation(S) == S \n" + + "PermutedSequences(S) == S\n" + "=============================="; +} diff --git a/src/main/java/de/tla2b/translation/TLA2B.java b/src/main/java/de/tla2b/translation/TLA2B.java new file mode 100644 index 0000000000000000000000000000000000000000..0875681a782c9a442f3a961cfd5aae1a2802eab3 --- /dev/null +++ b/src/main/java/de/tla2b/translation/TLA2B.java @@ -0,0 +1,276 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.translation; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Date; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.NotImplementedException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.global.TranslationGlobals; +import util.FileUtil; +import util.ToolIO; + +public class TLA2B implements TranslationGlobals { + private String mainFile; + private String path; + private String configFileName; + private String mainModuleName; + + private static boolean error = false; + + public static boolean hasError() { + return error; + } + + public TLA2B() { + mainFile = null; + path = null; + configFileName = null; + mainModuleName = null; + } + + public void handleParameter(String[] args) { + int i; + for (i = 0; (i < args.length) && (args[i].charAt(0) == '-'); i++) { + if (args[i].equals("-version")) { + System.out.println("TLA2B version " + VERSION); + System.exit(-1); + } else if (args[i].equals("-expr")) { + if (i + 1 == args.length) { + System.err.println("Error: expected a module file."); + System.exit(-1); + } + evalExpression(args[i + 1]); + return; + } + + else if (args[i].equals("-config")) { + i++; + if (i < args.length) { + configFileName = args[i]; + } else { + System.err + .println("Error: expect a file name for -config option."); + } + + } else { + System.err.println("Illegal switch: " + args[i]); + System.exit(-1); + } + } + + if (i == args.length) { + System.err.println("Error: expected a module file."); + System.exit(-1); + } + mainFile = args[i]; + } + + private void evalModuleFileName() throws IOException { + File file = new File(mainFile); + String canonicalPath; + if(file.exists()){ + canonicalPath = file.getCanonicalPath(); + }else { + throw new IOException("File '"+ mainFile + "' does not exit."); + } + + + String moduleName = canonicalPath; + if (moduleName.toLowerCase().endsWith(".tla")) { + moduleName = moduleName.substring(0, moduleName.length() - 4); + } + + moduleName = moduleName.replace("\\", File.separator); + moduleName = moduleName.replace("/", File.separator); + + mainModuleName = moduleName + .substring(moduleName.lastIndexOf(FileUtil.separator) + 1); + + path = moduleName.substring(0, moduleName.lastIndexOf(FileUtil.separator) + 1); + + if (path.equals("")) { + ToolIO.setUserDir("." + File.separator); + } else { + ToolIO.setUserDir(path); + } + + } + + private void evalConfigFile() { + // Config file + File file; + if (configFileName == null) { + + file = new File(path + mainModuleName + ".cfg"); + // use config if it exists + if (file.exists()) { + configFileName = mainModuleName + ".cfg"; + } + } else { + // user input + if (!configFileName.toLowerCase().endsWith(".cfg")) { + configFileName = configFileName + ".cfg"; + } + } + } + + public static void main(String[] args) { + // To indicate an error we use the exit code -1 + TLA2B tla2b = new TLA2B(); + tla2b.handleParameter(args); + + + try { + tla2b.evalModuleFileName(); + } catch (IOException e) { + System.err.println(e.getMessage()); + System.exit(-1); + } + + tla2b.evalConfigFile(); + + ToolIO.setMode(ToolIO.TOOL); + Tla2BTranslator t = new Tla2BTranslator(); + try { + t.start(tla2b.mainModuleName, tla2b.configFileName); + } catch (FrontEndException e) { + error = true; + System.err.println(e.getMessage()); + System.exit(-1); + } catch (TLA2BException e) { + error = true; + System.err.println(e.getMessage()); + System.exit(-1); + } catch (RuntimeException e) { + error = true; + System.err.println(e.getMessage()); + System.exit(-1); + } + StringBuilder s = new StringBuilder(); + try { + s = t.translate(); + } catch (NotImplementedException e) { + error = true; + System.err.print("**** Translation Error ****\n"); + System.err.print("Not implemented:\n"); + System.err.println(e.getMessage()); + System.exit(-1); + } catch (TLA2BException e) { + error = true; + System.err.print("**** Translation Error ****\n"); + System.err.println(e.getMessage()); + System.exit(-1); + } + s.insert(0, "/*@ generated by TLA2B " + VERSION + " " + new Date() + + " */\n"); + tla2b.createMachineFile(s); + } + + private void createMachineFile(StringBuilder s) { + String machineFileName = path + mainModuleName + "_tla.mch"; + File machineFile; + machineFile = new File(machineFileName); + if (machineFile.exists()) { + try { + BufferedReader in; + + in = new BufferedReader(new FileReader(machineFile)); + + String firstLine = null; + firstLine = in.readLine(); + in.close(); + if (!firstLine.startsWith("/*@ generated by TLA2B ")) { + System.err.println("Error: File " + machineFileName + + " already exists" + + " and was not generated by TLA2B.\n" + + "Delete or move this file."); + System.exit(-1); + } + } catch (IOException e) { + System.err.println(e.getMessage()); + System.exit(-1); + } + } + + try { + machineFile.createNewFile(); + } catch (IOException e) { + System.err.println(String.format("Could not create File %s.", + machineFileName)); + System.exit(-1); + } + + Writer fw = null; + try { + String res = s.toString(); + fw = new FileWriter(machineFile); + fw.write(res); + fw.close(); + System.out.println("B-Machine " + mainModuleName + + "_tla.mch created."); + } catch (IOException e) { + System.err.println("Error while creating file " + mainModuleName + + "mch."); + System.exit(-1); + } + + } + + public static String translateFile(String mainFile) throws TLA2BException, IOException { + TLA2B tla2b = new TLA2B(); + tla2b.mainFile = mainFile; + tla2b.evalModuleFileName(); + Tla2BTranslator t = new Tla2BTranslator(); + t.start(tla2b.mainModuleName, tla2b.configFileName); + StringBuilder s = t.translate(); + return s.toString(); + } + + /** + * @throws IOException + * + */ + private static void evalExpression(String file) { + + ToolIO.setMode(ToolIO.TOOL); + String expr = null; + try { + expr = fileToString(file); + } catch (IOException e) { + e.printStackTrace(); + } + ExpressionTranslator et = new ExpressionTranslator(expr); + try { + et.start(); + } catch (TLA2BException e) { + System.err.println("------ExpressionError----------------"); + System.err.println(e.getMessage()); + } + + } + + public static String fileToString(String fileName) throws IOException { + StringBuilder res = new StringBuilder(); + BufferedReader in = new BufferedReader(new FileReader(fileName)); + String str; + boolean first = true; + while ((str = in.readLine()) != null) { + if (!first) + res.append("\n"); + res.append(str); + } + in.close(); + return res.toString(); + } + +} diff --git a/src/main/java/de/tla2b/translation/Tla2BTranslator.java b/src/main/java/de/tla2b/translation/Tla2BTranslator.java new file mode 100644 index 0000000000000000000000000000000000000000..bba0f4436b6c8717a234e1030129d26c29bff548 --- /dev/null +++ b/src/main/java/de/tla2b/translation/Tla2BTranslator.java @@ -0,0 +1,215 @@ +package de.tla2b.translation; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import de.tla2b.analysis.InstanceTransformation; +import de.tla2b.analysis.SpecAnalyser; +import de.tla2b.analysis.SymbolRenamer; +import de.tla2b.analysis.SymbolSorter; +import de.tla2b.analysis.TypeChecker; +import de.tla2b.config.ConfigfileEvaluator; +import de.tla2b.config.ModuleOverrider; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.global.TranslationGlobals; +import de.tla2b.pprint.BAstCreator; +import de.tla2b.pprint.BMachinePrinter; +import tla2sany.drivers.FrontEndException; +import tla2sany.drivers.SANY; +import tla2sany.modanalyzer.SpecObj; +import tla2sany.semantic.ModuleNode; +import tlc2.tool.ModelConfig; +import util.FileUtil; +import util.ToolIO; + +public class Tla2BTranslator implements TranslationGlobals { + private ModuleNode moduleNode; + private ModelConfig modelConfig; + private TypeChecker typechecker; + private String moduleName; + + public Tla2BTranslator() { + this.moduleName = "Testing"; + } + + public Tla2BTranslator(String moduleName) { + this.moduleName = moduleName; + } + + public void start(String moduleFileName, String configFileName) + throws TLA2BException { + String moduleName = Tla2BTranslator.evalFileName(moduleFileName); + moduleNode = parseModule(moduleName); + + modelConfig = null; + if (configFileName != null) { + modelConfig = new ModelConfig(configFileName, null); + modelConfig.parse(); + } + } + + public static StringBuilder translateString(String moduleName, + String moduleString, String configString) throws FrontEndException, + TLA2BException { + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + Tla2BTranslator translator = new Tla2BTranslator(moduleName); + translator.startTest(moduleString, configString); + return translator.translate(); + } + + public void startTest(String moduleString, String configString) + throws de.tla2b.exceptions.FrontEndException, TLA2BException { + File dir = new File("temp/"); + dir.mkdirs(); + + try { + File f = new File("temp/"+ moduleName+ ".tla"); + f.createNewFile(); + FileWriter fw = new FileWriter(f); + fw.write(moduleString); + fw.close(); + f.deleteOnExit(); + } catch (IOException e) { + e.printStackTrace(); + } + + ToolIO.setUserDir("temp/"); + moduleNode = parseModule(moduleName + ".tla"); + + + modelConfig = null; + if (configString != null) { + File f = new File("temp/" + moduleName +".cfg"); + try { + f.createNewFile(); + FileWriter fw = new FileWriter(f); + fw.write(configString); + fw.close(); + } catch (IOException e) { + e.printStackTrace(); + } + modelConfig = new ModelConfig(moduleName +".cfg", null); + modelConfig.parse(); + f.deleteOnExit(); + } + dir.deleteOnExit(); + } + + + public StringBuilder translate() throws TLA2BException { + InstanceTransformation trans = new InstanceTransformation(moduleNode); + trans.start(); + + SymbolSorter symbolSorter = new SymbolSorter(moduleNode); + symbolSorter.sort(); + + SpecAnalyser specAnalyser; + + ConfigfileEvaluator conEval = null; + if (modelConfig != null) { + + conEval = new ConfigfileEvaluator(modelConfig, moduleNode); + conEval.start(); + + ModuleOverrider modOver = new ModuleOverrider(moduleNode, conEval); + modOver.start(); + specAnalyser = new SpecAnalyser(moduleNode, conEval); + } else { + specAnalyser = new SpecAnalyser(moduleNode); + } + + specAnalyser.start(); + + typechecker = new TypeChecker(moduleNode, conEval, specAnalyser); + typechecker.start(); + + specAnalyser.evalIfThenElse(); + + SymbolRenamer symRenamer = new SymbolRenamer(moduleNode, specAnalyser); + symRenamer.start(); + BMachinePrinter p = new BMachinePrinter(moduleNode, conEval, + specAnalyser); + //BAstCreator bAstCreator = new BAstCreator(moduleNode, conEval, specAnalyser); + + return p.start(); + } + + public static ModuleNode parseModule(String moduleName) + throws de.tla2b.exceptions.FrontEndException { + SpecObj spec = new SpecObj(moduleName, null); + try { + SANY.frontEndMain(spec, moduleName, ToolIO.out); + } catch (FrontEndException e) { + // Error in Frontend, should never happens + return null; + } + + if (spec.parseErrors.isFailure()) { + throw new de.tla2b.exceptions.FrontEndException( + allMessagesToString(ToolIO.getAllMessages()) + + spec.parseErrors, spec); + } + + if (spec.semanticErrors.isFailure()) { + throw new de.tla2b.exceptions.FrontEndException( + // allMessagesToString(ToolIO.getAllMessages()) + "" + spec.semanticErrors, spec); + } + + // RootModule + ModuleNode n = spec.getExternalModuleTable().rootModule; + if (spec.getInitErrors().isFailure()) { + System.err.println(spec.getInitErrors()); + return null; + } + + if (n == null) { // Parse Error + // System.out.println("Rootmodule null"); + throw new de.tla2b.exceptions.FrontEndException( + allMessagesToString(ToolIO.getAllMessages()), spec); + } + return n; + } + + public static String allMessagesToString(String[] allMessages) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < allMessages.length - 1; i++) { + sb.append(allMessages[i] + "\n"); + } + return sb.toString(); + } + + public static String evalFileName(String name) { + if (name.toLowerCase().endsWith(".tla")) { + name = name.substring(0, name.length() - 4); + } + + if (name.toLowerCase().endsWith(".cfg")) { + name = name.substring(0, name.length() - 4); + } + + String sourceModuleName = name.substring(name + .lastIndexOf(FileUtil.separator) + 1); + + String path = name.substring(0, + name.lastIndexOf(FileUtil.separator) + 1); + if (!path.equals("")) + ToolIO.setUserDir(path); + return sourceModuleName; + } + + public ModuleNode getModuleNode() { + return moduleNode; + } + + public ModelConfig getModelConfig() { + return modelConfig; + } + + public TypeChecker getTypecheChecker() { + return typechecker; + } + +} diff --git a/src/main/java/de/tla2b/types/AbstractHasFollowers.java b/src/main/java/de/tla2b/types/AbstractHasFollowers.java new file mode 100644 index 0000000000000000000000000000000000000000..fc6bc447a4d78ad3d7817ec55b747ee1569e541f --- /dev/null +++ b/src/main/java/de/tla2b/types/AbstractHasFollowers.java @@ -0,0 +1,92 @@ +package de.tla2b.types; + +import java.util.ArrayList; +import tla2sany.semantic.SemanticNode; + +public abstract class AbstractHasFollowers extends TLAType { + + public ArrayList<Object> followers; + + public AbstractHasFollowers(int t) { + super(t); + followers = new ArrayList<Object>(); + } + + public ArrayList<Object> getFollowers() { + return followers; + } + + public void addFollower(Object o) { + // only (partial) untyped types need follower + if (this.followers != null) { + for (int i = 0; i < followers.size(); i++) { + if (followers.get(i) == o) + return; + } + followers.add(o); + } + + } + + public void deleteFollower(Object o) { + followers.remove(o); + } + + public void deleteFollowers() { + followers = null; + } + + public void removeFollower(Object o) { + followers.remove(o); + } + + public String followersToString() { + return followers.toString(); + } + + protected void setFollowersTo(TLAType newType) { + if (this.followers == null) + return; + for (int i = 0; i < this.followers.size(); i++) { + + Object follower = this.followers.get(i); + if (follower instanceof SemanticNode) { + ((SemanticNode) follower).setToolObject(5, newType); + if (newType instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) newType).addFollower(follower); + } + } else if (follower instanceof AbstractSymbol) { + ((AbstractSymbol) follower).setType(newType); + } else if (follower instanceof SetType) { + ((SetType) follower).setSubType(newType); + } else if (follower instanceof TupleType) { + ((TupleType) follower).update(this, newType); + } else if (follower instanceof PairType) { + PairType pair = ((PairType) follower); + if (pair.getFirst() == this) { + pair.setFirst(newType); + } + if (pair.getSecond() == this) { + pair.setSecond(newType); + } + + } else if (follower instanceof FunctionType) { + ((FunctionType) follower).update(this, newType); + } else if (follower instanceof StructType) { + ((StructType) follower).setNewType(this, newType); + } else if (follower instanceof StructOrFunction) { + ((StructOrFunction) follower).setNewType(this, newType); + } else { + throw new RuntimeException("Unknown follower type: " + + follower.getClass()); + } + } + } + + public boolean hasFollower() { + if (followers.size() == 0) { + return false; + } else + return true; + } +} diff --git a/src/main/java/de/tla2b/types/AbstractSymbol.java b/src/main/java/de/tla2b/types/AbstractSymbol.java new file mode 100644 index 0000000000000000000000000000000000000000..498abc0e7570d9db4d3cf87f4de744ddcfd8c8c9 --- /dev/null +++ b/src/main/java/de/tla2b/types/AbstractSymbol.java @@ -0,0 +1,23 @@ +package de.tla2b.types; + +public abstract class AbstractSymbol { + + private TLAType type; + + public AbstractSymbol(TLAType t){ + setType(t); + } + + public TLAType getType() { + return type; + } + + + protected void setType(TLAType t) { + this.type = t; + if (type instanceof AbstractHasFollowers) { + AbstractHasFollowers p = (AbstractHasFollowers) t; + p.addFollower(this); + } + } +} diff --git a/src/main/java/de/tla2b/types/BoolType.java b/src/main/java/de/tla2b/types/BoolType.java new file mode 100644 index 0000000000000000000000000000000000000000..013822a26580803600506494f3751cba2bf7b824 --- /dev/null +++ b/src/main/java/de/tla2b/types/BoolType.java @@ -0,0 +1,62 @@ +package de.tla2b.types; + +import de.be4.classicalb.core.parser.node.ABoolSetExpression; +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class BoolType extends TLAType { + + private static BoolType instance = new BoolType(); + + private BoolType() { + super(BOOL); + } + + public static BoolType getInstance() { + return instance; + } + + @Override + public String toString() { + return "BOOL"; + } + + @Override + public boolean isUntyped() { + return false; + } + + @Override + public boolean compare(TLAType o) { + if (o.getKind() == UNTYPED || o.getKind() == BOOL) + return true; + else + return false; + } + + @Override + public BoolType unify(TLAType o) throws UnificationException { + if (o.getKind() == BOOL) { + return this; + } else if (o instanceof Untyped) { + ((Untyped) o).setFollowersTo(this); + return this; + } else + throw new UnificationException(); + } + + @Override + public BoolType cloneTLAType() { + return this; + } + + @Override + public boolean contains(TLAType o) { + return false; + } + + @Override + public PExpression getBNode() { + return new ABoolSetExpression(); + } +} \ No newline at end of file diff --git a/src/main/java/de/tla2b/types/EnumType.java b/src/main/java/de/tla2b/types/EnumType.java new file mode 100644 index 0000000000000000000000000000000000000000..c36ed7c712899662edd51c0982be9b7b6a448d0d --- /dev/null +++ b/src/main/java/de/tla2b/types/EnumType.java @@ -0,0 +1,86 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.types; + +import java.util.ArrayList; +import java.util.LinkedHashSet; + +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + + + +public class EnumType extends AbstractHasFollowers { + public LinkedHashSet<String> modelvalues; + public int id; + private boolean noVal = false; + + public EnumType(ArrayList<String> enums) { + super(MODELVALUE); + modelvalues = new LinkedHashSet<String>(enums); + } + + public void setNoVal() { + noVal = true; + } + + public boolean hasNoVal() { + return noVal; + } + + public LinkedHashSet<String> getValues() { + return modelvalues; + } + + @Override + public boolean isUntyped() { + return false; + } + + @Override + public boolean compare(TLAType o) { + if (o.getKind() == UNTYPED || o.getKind() == MODELVALUE) + return true; + else + return false; + } + + @Override + public EnumType unify(TLAType o) throws UnificationException { + if (o instanceof Untyped) { + ((Untyped) o).setFollowersTo(this); + return this; + } + if (o instanceof EnumType) { + EnumType e = (EnumType) o; + e.setFollowersTo(this); + this.modelvalues.addAll(((EnumType) o).modelvalues); + return this; + } + throw new UnificationException(); + } + + @Override + public EnumType cloneTLAType() { + return this; + } + + @Override + public boolean contains(TLAType o) { + //TODO is this really false + return false; + } + + @Override + public String toString() { + return "ENUM" + id; + } + + @Override + public PExpression getBNode() { + // TODO Auto-generated method stub + return null; + } +} \ No newline at end of file diff --git a/src/main/java/de/tla2b/types/FunctionType.java b/src/main/java/de/tla2b/types/FunctionType.java new file mode 100644 index 0000000000000000000000000000000000000000..06a6d93eb3e821ae7ba705cf5c55cb455e962d7a --- /dev/null +++ b/src/main/java/de/tla2b/types/FunctionType.java @@ -0,0 +1,122 @@ +package de.tla2b.types; + +import de.be4.classicalb.core.parser.node.APartialFunctionExpression; +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class FunctionType extends AbstractHasFollowers { + private TLAType domain; + private TLAType range; + + public FunctionType(TLAType domain, TLAType range) { + super(FUNCTION); + this.setDomain(domain); + this.setRange(range); + } + + public FunctionType() { + super(FUNCTION); + this.setDomain(new Untyped()); + this.setRange(new Untyped()); + } + + + public void update(TLAType oldType, TLAType newType) { + if (domain == oldType) + setDomain(newType); + if (range == oldType) + setRange(newType); + } + + @Override + public boolean compare(TLAType o) { + if (this.contains(o)) + return false; + if (o.getKind() == UNTYPED) + return true; + if (o instanceof FunctionType) { + FunctionType f = (FunctionType) o; + return domain.compare(f.domain) && range.compare(f.range); + } + if(o instanceof TupleType){ + return o.compare(this); + } + + return false; + } + + @Override + public boolean contains(TLAType o) { + return domain.equals(o) || domain.contains(o) || range.equals(o) + || range.contains(o); + } + + @Override + public boolean isUntyped() { + return domain.isUntyped() || range.isUntyped(); + } + + @Override + public TLAType cloneTLAType() { + return new FunctionType(domain.cloneTLAType(), range.cloneTLAType()); + } + + @Override + public FunctionType unify(TLAType o) throws UnificationException { + if (!this.compare(o)) + throw new UnificationException(); + if (o instanceof Untyped) { + ((Untyped) o).setFollowersTo(this); + return this; + } + if (o instanceof FunctionType) { + domain = domain.unify(((FunctionType) o).domain); + range = range.unify(((FunctionType) o).range); + return this; + } + if (o instanceof TupleType){ + return (FunctionType) o.unify(this); + } + throw new RuntimeException(); + } + + public TLAType getDomain() { + return domain; + } + + public TLAType getRange() { + return range; + } + + public void setDomain(TLAType domain) { + this.domain = domain; + if (domain instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) domain).addFollower(this); + } + } + + public void setRange(TLAType range) { + this.range = range; + if (range instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) range).addFollower(this); + } + } + + @Override + public String toString() { + String res = "POW(" + domain + "*"; + if (range instanceof TupleType) { + res += "(" + range + ")"; + } else{ + res += range; + } + res += ")"; + return res; + } + + @Override + public PExpression getBNode() { + return new APartialFunctionExpression(domain.getBNode(), range.getBNode()); + } + +} diff --git a/src/main/java/de/tla2b/types/IType.java b/src/main/java/de/tla2b/types/IType.java new file mode 100644 index 0000000000000000000000000000000000000000..26c84cae66ddac18cd81f1505192d33eb7fd5c7f --- /dev/null +++ b/src/main/java/de/tla2b/types/IType.java @@ -0,0 +1,17 @@ +package de.tla2b.types; + +public interface IType { + public final int UNTYPED = 0; + public final int INTEGER = 1; + public final int BOOL = 2; + public final int STRING = 3; + public final int MODELVALUE = 4; + public final int POW = 5; + public final int PAIR = 6; + public final int STRUCT = 7; + public final int TUPLEORSEQ =8; + public final int STRUCT_OR_FUNCTION = 9; + public final int FUNCTION = 10; + public final int TUPLE = 11; + +} diff --git a/src/main/java/de/tla2b/types/IntType.java b/src/main/java/de/tla2b/types/IntType.java new file mode 100644 index 0000000000000000000000000000000000000000..b5fae0f68e30f0b1c6ea22b1e8cee102a5464f74 --- /dev/null +++ b/src/main/java/de/tla2b/types/IntType.java @@ -0,0 +1,62 @@ +package de.tla2b.types; + +import de.be4.classicalb.core.parser.node.AIntegerSetExpression; +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class IntType extends TLAType { + + private static IntType instance = new IntType(); + + private IntType() { + super(INTEGER); + } + + public static IntType getInstance() { + return instance; + } + + @Override + public String toString() { + return "INTEGER"; + } + + @Override + public boolean isUntyped() { + return false; + } + + @Override + public boolean compare(TLAType o) { + if (o.getKind() == UNTYPED || o.getKind() == INTEGER) + return true; + else + return false; + } + + @Override + public IntType unify(TLAType o) throws UnificationException { + if (o.getKind() == INTEGER) { + return this; + } else if (o instanceof Untyped) { + ((Untyped) o).setFollowersTo(this); + return this; + } else + throw new UnificationException(); + } + + @Override + public IntType cloneTLAType() { + return this; + } + + @Override + public boolean contains(TLAType o) { + return false; + } + + @Override + public PExpression getBNode() { + return new AIntegerSetExpression(); + } +} \ No newline at end of file diff --git a/src/main/java/de/tla2b/types/ModelValueType.java b/src/main/java/de/tla2b/types/ModelValueType.java new file mode 100644 index 0000000000000000000000000000000000000000..e196cea10b2ae6ed2799b8ff49a88c466f19090f --- /dev/null +++ b/src/main/java/de/tla2b/types/ModelValueType.java @@ -0,0 +1,63 @@ +package de.tla2b.types; + +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class ModelValueType extends TLAType { + + private static ModelValueType instance = new ModelValueType(); + + private ModelValueType() { + super(MODELVALUE); + } + + public static ModelValueType getInstance() { + return instance; + } + + + @Override + public String toString() { + return "ENUM"; + } + + @Override + public boolean isUntyped() { + return false; + } + + @Override + public boolean compare(TLAType o) { + if (o.getKind() == UNTYPED || o.getKind() == MODELVALUE) + return true; + else + return false; + } + + @Override + public ModelValueType unify(TLAType o) throws UnificationException { + if (o.getKind() == MODELVALUE) { + return this; + } else if (o instanceof Untyped) { + ((Untyped) o).setFollowersTo(this); + return this; + } else + throw new UnificationException(); + } + + @Override + public ModelValueType cloneTLAType() { + return this; + } + + @Override + public boolean contains(TLAType o) { + return false; + } + + @Override + public PExpression getBNode() { + // TODO Auto-generated method stub + return null; + } +} \ No newline at end of file diff --git a/src/main/java/de/tla2b/types/PairType.java b/src/main/java/de/tla2b/types/PairType.java new file mode 100644 index 0000000000000000000000000000000000000000..29d382d62439aa78fc3dc5fbcfe590113b115f24 --- /dev/null +++ b/src/main/java/de/tla2b/types/PairType.java @@ -0,0 +1,140 @@ +package de.tla2b.types; + +import java.util.ArrayList; +import java.util.List; + +import de.be4.classicalb.core.parser.node.ACoupleExpression; +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class PairType extends AbstractHasFollowers { + + private TLAType first; + private TLAType second; + + public PairType() { + super(PAIR); + setFirst(new Untyped()); + setSecond(new Untyped()); + } + + public PairType(TLAType f, TLAType s) { + super(PAIR); + this.first = f; + if (first instanceof AbstractHasFollowers) { + AbstractHasFollowers firstHasFollowers = (AbstractHasFollowers) first; + firstHasFollowers.addFollower(this); + } + this.second = s; + if (second instanceof AbstractHasFollowers) { + AbstractHasFollowers secondHasFollowers = (AbstractHasFollowers) second; + secondHasFollowers.addFollower(this); + } + } + + public TLAType getFirst() { + return first; + } + + public void setFirst(TLAType f) { + this.first = f; + + if (first instanceof AbstractHasFollowers) { + AbstractHasFollowers firstHasFollowers = (AbstractHasFollowers) first; + firstHasFollowers.addFollower(this); + } + + // setting first can leads to a completely typed type + if (!this.isUntyped()) { + // this type is completely typed + this.deleteFollowers(); + } + } + + public TLAType getSecond() { + return second; + } + + public void setSecond(TLAType s) { + this.second = s; + + if (second instanceof AbstractHasFollowers) { + AbstractHasFollowers secondHasFollowers = (AbstractHasFollowers) second; + secondHasFollowers.addFollower(this); + } + + // setting second can leads to a completely typed type + if (!this.isUntyped()) { + // this type is completely typed + this.deleteFollowers(); + } + } + + @Override + public boolean isUntyped() { + return first.isUntyped() || second.isUntyped(); + } + + @Override + public PairType unify(TLAType o) throws UnificationException { + if (!this.compare(o)) + throw new UnificationException(); + if (o instanceof AbstractHasFollowers) + ((AbstractHasFollowers) o).setFollowersTo(this); + + if (o instanceof PairType) { + PairType p = (PairType) o; + this.first = this.first.unify(p.first); + this.second = this.second.unify(p.second); + return this; + } + throw new RuntimeException(); + } + + @Override + public boolean compare(TLAType o) { + if (this.contains(o)) + return false; + if (o.getKind() == UNTYPED) + return true; + + if (o instanceof PairType) { + PairType p = (PairType) o; + // test first and second component compatibility + return this.first.compare(p.first) && this.second.compare(p.second); + } else + return false; + } + + @Override + public PairType cloneTLAType() { + return new PairType(this.first.cloneTLAType(), + this.second.cloneTLAType()); + } + + @Override + public boolean contains(TLAType o) { + return first.equals(o) || first.contains(o) || second.equals(o) + || second.contains(o); + } + + @Override + public String toString() { + String res = first + "*"; + if (second instanceof PairType) { + res += "(" + second + ")"; + } else + res += second; + return res; + + } + + @Override + public PExpression getBNode() { + List<PExpression> list = new ArrayList<PExpression>(); + list.add(first.getBNode()); + list.add(second.getBNode()); + return new ACoupleExpression(list); + } + +} diff --git a/src/main/java/de/tla2b/types/SetType.java b/src/main/java/de/tla2b/types/SetType.java new file mode 100644 index 0000000000000000000000000000000000000000..636aee87ea809ea6379957ceaa1bf7d08cef15c3 --- /dev/null +++ b/src/main/java/de/tla2b/types/SetType.java @@ -0,0 +1,110 @@ +package de.tla2b.types; + +import de.be4.classicalb.core.parser.node.APowSubsetExpression; +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class SetType extends AbstractHasFollowers { + private TLAType subType; + + public SetType(TLAType t) { + super(POW); + setSubType(t); + } + + public TLAType getSubType() { + return subType; + } + + public void setSubType(TLAType t) { + // if (subType instanceof AbstractHasFollowers) { + // // delete old reference + // ((AbstractHasFollowers) subType).deleteFollower(this); + // } + + if (t instanceof AbstractHasFollowers) { + // set new reference + ((AbstractHasFollowers) t).addFollower(this); + } + this.subType = t; + + // setting subType can lead to a completely typed type + if (!this.isUntyped()) { + // this type is completely typed + this.deleteFollowers(); + } + } + + public SetType unify(TLAType o) throws UnificationException { + + if (!this.compare(o)|| this.contains(o)) { + throw new UnificationException(); + } + // if o has followers than switch pointer to this + if (o instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) o).setFollowersTo(this); + } + + if (o instanceof StructOrFunction){ + return (SetType)o.unify(this); + } + if (o instanceof SetType) { + SetType p = (SetType) o; + this.subType = this.subType.unify(p.subType); + +// if (this.subType instanceof AbstractHasFollowers) { +// ((AbstractHasFollowers) this.subType).removeFollower(p); +// } + } + return this; + } + + @Override + public boolean compare(TLAType o) { + if(this.contains(o)) + return false; + + if (o.getKind() == UNTYPED) + return true; + + if (o instanceof StructOrFunction){ + return o.compare(this); + } + + if (o instanceof SetType) { + SetType p = (SetType) o; + // test sub types compatibility + return this.subType.compare(p.subType); + } else + return false; + } + + @Override + public String toString() { + String res = "POW(" + this.getSubType() + ")"; + + return res; + } + + @Override + public boolean isUntyped() { + return subType.isUntyped(); + } + + @Override + public SetType cloneTLAType() { + return new SetType(this.subType.cloneTLAType()); + } + + + @Override + public boolean contains(TLAType o) { + return this.getSubType().equals(o) || this.getSubType().contains(o); + } + + @Override + public PExpression getBNode() { + return new APowSubsetExpression(this.getSubType().getBNode()); + } + +} diff --git a/src/main/java/de/tla2b/types/StringType.java b/src/main/java/de/tla2b/types/StringType.java new file mode 100644 index 0000000000000000000000000000000000000000..e66f900a83c7412baa70b3d6f4ac17ccdfb28d49 --- /dev/null +++ b/src/main/java/de/tla2b/types/StringType.java @@ -0,0 +1,68 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.types; + +import de.be4.classicalb.core.parser.node.AStringSetExpression; +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class StringType extends TLAType { + + private static StringType instance = new StringType(); + + private StringType() { + super(STRING); + } + + public static StringType getInstance(){ + return instance; + } + + @Override + public String toString() { + return "STRING"; + } + + @Override + public boolean compare(TLAType o) { + if (o.getKind() == UNTYPED || o.getKind() == STRING) + return true; + else + return false; + } + + @Override + public boolean isUntyped() { + return false; + } + + @Override + public StringType unify(TLAType o) throws UnificationException { + if (o.getKind() == STRING) { + return this; + } else if (o instanceof Untyped) { + ((Untyped) o).setFollowersTo(this); + ((Untyped) o).deleteFollowers(); + return this; + } else + throw new UnificationException(); + } + + @Override + public StringType cloneTLAType() { + return this; + } + + @Override + public boolean contains(TLAType o) { + return false; + } + + @Override + public PExpression getBNode() { + return new AStringSetExpression(); + } + +} diff --git a/src/main/java/de/tla2b/types/StructOrFunction.java b/src/main/java/de/tla2b/types/StructOrFunction.java new file mode 100644 index 0000000000000000000000000000000000000000..f62233497737e0307cdf1f8943ddc0b6720ac329 --- /dev/null +++ b/src/main/java/de/tla2b/types/StructOrFunction.java @@ -0,0 +1,232 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.types; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Set; +import java.util.Map.Entry; + +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + + + +public class StructOrFunction extends AbstractHasFollowers { + private LinkedHashMap<String, TLAType> types; + + public StructOrFunction(String name, TLAType type) { + super(STRUCT_OR_FUNCTION); + types = new LinkedHashMap<String, TLAType>(); + types.put(name, type); + } + + public StructOrFunction() { + super(STRUCT_OR_FUNCTION); + types = new LinkedHashMap<String, TLAType>(); + } + + public void setNewType(TLAType old, TLAType New) { + Set<Entry<String, TLAType>> set = types.entrySet(); + Iterator<Entry<String, TLAType>> iterator = set.iterator(); + + while (iterator.hasNext()) { + Entry<String, TLAType> entry = iterator.next(); + if (entry.getValue() == old) { + String key = entry.getKey(); + if (New instanceof AbstractHasFollowers) { + // set new reference + ((AbstractHasFollowers) New).addFollower(this); + } + types.put(key, New); + } + } + testRecord(); + } + + @Override + public String toString() { + String res = "StructOrFunction("; + for (Iterator<String> keys = types.keySet().iterator(); keys.hasNext();) { + String key = keys.next(); + res += "\""+key + "\" : " + types.get(key); + if (keys.hasNext()) + res += ", "; + } + res += ")"; + return res; + } + + @Override + public boolean compare(TLAType o) { + if (this.contains(o) || o.contains(this)) + return false; + if (o.getKind() == UNTYPED) + return true; + if (o instanceof StructType) { + StructType s = (StructType) o; + Iterator<String> thisKeys = types.keySet().iterator(); + while (thisKeys.hasNext()) { + String fieldName = (String) thisKeys.next(); + if (s.getFields().contains(fieldName)) { + if (!this.types.get(fieldName) + .compare(s.getType(fieldName))) { + return false; + } + } + } + return true; + } + if (o instanceof SetType) { + SetType p = (SetType) o; + TLAType sub = p.getSubType(); + if (sub.getKind() == UNTYPED) + return true; + + if (sub instanceof PairType) { + PairType pair = (PairType) sub; + if (pair.getFirst().compare(StringType.getInstance())) { + for (String key : types.keySet()) { + if (!pair.getSecond().compare(types.get(key))) + return false; + } + return true; + } else + return false; + } else + return false; + } + + if (o instanceof StructOrFunction) { + StructOrFunction s = (StructOrFunction) o; + + Iterator<String> thisKeys = types.keySet().iterator(); + while (thisKeys.hasNext()) { + String fieldName = (String) thisKeys.next(); + if (s.types.containsKey(fieldName)) { + if (!this.types.get(fieldName).compare( + s.types.get(fieldName))) { + return false; + } + } + } + return true; + + } + + return false; + } + + @Override + public boolean contains(TLAType o) { + Iterator<String> thisKeys = types.keySet().iterator(); + while (thisKeys.hasNext()) { + String fieldName = (String) thisKeys.next(); + TLAType type = this.types.get(fieldName); + if (type.equals(o) || type.contains(o)) + return true; + } + return false; + } + + @Override + public boolean isUntyped() { + return true; + // Iterator<BType> itr = types.values().iterator(); + // while (itr.hasNext()) { + // if (itr.next().isUntyped()) + // return true; + // } + // return false; + } + + @Override + public TLAType cloneTLAType() { + StructOrFunction res = new StructOrFunction(); + for (String field : types.keySet()) { + res.types.put(field, this.types.get(field)); + } + return res; + } + + @Override + public TLAType unify(TLAType o) throws UnificationException { + if (!this.compare(o)) + throw new UnificationException(); + + if (o instanceof Untyped) { + ((Untyped) o).setFollowersTo(this); + return this; + } + + if (o instanceof SetType) { + Iterator<TLAType> itr = types.values().iterator(); + TLAType temp = itr.next(); + while (itr.hasNext()) { + temp = temp.unify(itr.next()); + } + SetType found = new SetType(new PairType( + StringType.getInstance(), temp)); + return found.unify(o); + } + if (o instanceof StructType) { + StructType res = new StructType(); + + for (String field : types.keySet()) { + res.add(field, this.types.get(field)); + } + return o.unify(res); + } + if (o instanceof StructOrFunction) { + StructOrFunction other = (StructOrFunction) o; + for (String field : other.types.keySet()) { + TLAType type = other.types.get(field); + if (this.types.containsKey(field)) { + TLAType res = this.types.get(field).unify(type); + this.types.put(field, res); + } else { + if (type instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) type).addFollower(this); + } + this.types.put(field, type); + } + } + TLAType res = testRecord(); + return res; + } + return this; + } + + private TLAType testRecord() { + Iterator<TLAType> itr = types.values().iterator(); + TLAType temp = itr.next().cloneTLAType(); + while (itr.hasNext()) { + TLAType next = itr.next().cloneTLAType(); + try { + temp.unify(next); + } catch (UnificationException e) { + StructType res = new StructType(); + for (String field : this.types.keySet()) { + res.add(field, this.types.get(field)); + } + this.setFollowersTo(res); + return res; + } + } + return this; + } + + public SetType getFunction() { + Iterator<TLAType> itr = types.values().iterator(); + return new SetType(new PairType(StringType.getInstance(), + itr.next())); + } + + @Override + public PExpression getBNode() { + return null; + } + +} diff --git a/src/main/java/de/tla2b/types/StructType.java b/src/main/java/de/tla2b/types/StructType.java new file mode 100644 index 0000000000000000000000000000000000000000..34e52e01bfe27a9e01a97b8ad23aaf16d5f1841d --- /dev/null +++ b/src/main/java/de/tla2b/types/StructType.java @@ -0,0 +1,192 @@ +package de.tla2b.types; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import de.be4.classicalb.core.parser.node.ARecEntry; +import de.be4.classicalb.core.parser.node.AStructExpression; +import de.be4.classicalb.core.parser.node.PExpression; +import de.be4.classicalb.core.parser.node.PRecEntry; +import de.tla2b.exceptions.UnificationException; +import de.tla2b.pprint.BAstCreator; + + + +public class StructType extends AbstractHasFollowers { + private LinkedHashMap<String, TLAType> types; + + public StructType() { + super(STRUCT); + types = new LinkedHashMap<String, TLAType>(); + } + + public TLAType getType(String fieldName) { + return types.get(fieldName); + } + + public void add(String name, TLAType type) { + if (type instanceof AbstractHasFollowers) { + // set new reference + ((AbstractHasFollowers) type).addFollower(this); + } + types.put(name, type); + } + + public void setNewType(TLAType old, TLAType New) { + Set<Entry<String, TLAType>> set = types.entrySet(); + Iterator<Entry<String, TLAType>> iterator = set.iterator(); + + while (iterator.hasNext()) { + Entry<String, TLAType> entry = iterator.next(); + if (entry.getValue() == old) { + String key = entry.getKey(); + if (New instanceof AbstractHasFollowers) { + // set new reference + ((AbstractHasFollowers) New).addFollower(this); + } + types.put(key, New); + } + } + } + + @Override + public boolean isUntyped() { + Iterator<TLAType> ts = types.values().iterator(); + while (ts.hasNext()) { + TLAType bType = (TLAType) ts.next(); + if (bType.isUntyped()) + return true; + } + return false; + } + + public boolean compare(TLAType o) { + if(this.contains(o)|| o.contains(this)) + return false; + if (o.getKind() == UNTYPED) + return true; + + if (o instanceof StructOrFunction){ + return o.compare(this); + } + if (o instanceof StructType) { + StructType s = (StructType) o; + + Iterator<String> thisKeys = types.keySet().iterator(); + while (thisKeys.hasNext()) { + String fieldName = (String) thisKeys.next(); + if (s.types.containsKey(fieldName)) { + if (!this.types.get(fieldName).compare( + s.types.get(fieldName))) { + return false; + } + } + } + return true; + } + return false; + } + + public StructType unify(TLAType o) throws UnificationException { + if (!this.compare(o)) { + throw new UnificationException(); + } + if (o instanceof AbstractHasFollowers) + ((AbstractHasFollowers) o).setFollowersTo(this); + + if (o instanceof StructOrFunction){ + return (StructType) o.unify(this); + } + + if (o instanceof StructType) { + StructType s = (StructType) o; + Iterator<String> keys = s.types.keySet().iterator(); + while (keys.hasNext()) { + String fieldName = (String) keys.next(); + TLAType sType = s.types.get(fieldName); + if (this.types.containsKey(fieldName)) { + TLAType res = this.types.get(fieldName).unify(sType); + this.types.put(fieldName, res); + } else { + if (sType instanceof AbstractHasFollowers) { + // set new reference + ((AbstractHasFollowers) sType).addFollower(this); + } + this.types.put(fieldName, sType); + } + } + return this; + } + return this; + } + + @Override + public StructType cloneTLAType() { + StructType clone = new StructType(); + + Set<Entry<String, TLAType>> set = this.types.entrySet(); + Iterator<Entry<String, TLAType>> iterator = set.iterator(); + + while (iterator.hasNext()) { + Entry<String, TLAType> entry = iterator.next(); + String field = entry.getKey(); + TLAType type = entry.getValue().cloneTLAType(); + clone.add(field, type); + } + + return clone; + } + + public ArrayList<String> getFields() { + ArrayList<String> fields = new ArrayList<String>(); + Iterator<String> keys = this.types.keySet().iterator(); + while (keys.hasNext()) { + String fieldName = (String) keys.next(); + fields.add(fieldName); + } + return fields; + } + + @Override + public boolean contains(TLAType o) { + Iterator<TLAType> ts = types.values().iterator(); + while (ts.hasNext()) { + TLAType bType = (TLAType) ts.next(); + if (bType.equals(o) || bType.contains(o)) + return true; + } + return false; + } + + @Override + public String toString() { + String res = "struct("; + Iterator<String> keys = types.keySet().iterator(); + if(!keys.hasNext()) + res += "..."; + while (keys.hasNext()) { + String fieldName = (String) keys.next(); + res += fieldName + ":" + types.get(fieldName); + if (keys.hasNext()) + res += ","; + } + res += ")"; + return res; + } + + @Override + public PExpression getBNode() { + List<PRecEntry> recList = new ArrayList<PRecEntry>(); + for (Entry<String, TLAType> entry : types.entrySet()) { + ARecEntry rec = new ARecEntry(); + rec.setIdentifier(BAstCreator.createIdentifierNode(entry.getKey())); + rec.setValue(entry.getValue().getBNode()); + recList.add(rec); + } + return new AStructExpression(recList); + } +} diff --git a/src/main/java/de/tla2b/types/TLAType.java b/src/main/java/de/tla2b/types/TLAType.java new file mode 100644 index 0000000000000000000000000000000000000000..f6da56a6623e127a23d08c0946dc5caebca2ac06 --- /dev/null +++ b/src/main/java/de/tla2b/types/TLAType.java @@ -0,0 +1,44 @@ +package de.tla2b.types; + +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + + +public abstract class TLAType implements IType { + private int kind; + + public TLAType(int t) { + this.kind = t; + } + + public final int getKind() { + return kind; + } + + public abstract String toString(); + + public abstract PExpression getBNode(); + + public abstract boolean compare(TLAType o); + + public abstract boolean contains(TLAType o); + + public abstract boolean isUntyped(); + + public abstract TLAType cloneTLAType(); + + public abstract TLAType unify(TLAType o) throws UnificationException; + + public TLAType unityAll(TLAType[] types) throws UnificationException{ + TLAType current = this; + for (int i = 0; i < types.length; i++) { + current = current.unify(types[i]); + } + return current; + } + + public final String printObjectToString() { + return super.toString(); + } + +} diff --git a/src/main/java/de/tla2b/types/TupleType.java b/src/main/java/de/tla2b/types/TupleType.java new file mode 100644 index 0000000000000000000000000000000000000000..4adcfefc87992f9a345967e97d13fa3bbe3a4980 --- /dev/null +++ b/src/main/java/de/tla2b/types/TupleType.java @@ -0,0 +1,210 @@ +package de.tla2b.types; + +import java.util.ArrayList; +import java.util.List; + +import de.be4.classicalb.core.parser.node.ACoupleExpression; +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class TupleType extends AbstractHasFollowers { + private ArrayList<TLAType> types; + + public TupleType(ArrayList<TLAType> typeList) { + super(TUPLE); + setTypes(typeList); + } + + public TupleType(int size) { + super(TUPLE); + ArrayList<TLAType> list = new ArrayList<TLAType>(); + for (int i = 0; i < size; i++) { + list.add(new Untyped()); + } + setTypes(list); + } + + public ArrayList<TLAType> getTypes() { + return new ArrayList<TLAType>(types); + } + + public void setTypes(ArrayList<TLAType> types) { + this.types = types; + types = new ArrayList<TLAType>(types); + for (TLAType tlaType : types) { + if (tlaType instanceof AbstractHasFollowers) { + ((AbstractHasFollowers) tlaType).addFollower(this); + } + } + } + + + public void update(TLAType oldType, TLAType newType) { + for (int i = 0; i < types.size(); i++) { + TLAType t = types.get(i); + if (oldType == t) { + types.set(i, newType); + } + } + if (oldType instanceof AbstractHasFollowers) + ((AbstractHasFollowers) oldType).addFollower(this); + } + + @Override + public boolean compare(TLAType o) { + if (this.contains(o)) + return false; + if (o.getKind() == UNTYPED) + return true; + if (o instanceof TupleType) { + TupleType t = (TupleType) o; + if (this.types.size() != t.types.size()) { + for (int i = 0; i < t.types.size(); i++) { + if (!compareToAll(t.types.get(i))) { + return false; + } + } + // both are sequences with different lengths + return true; + } + for (int i = 0; i < types.size(); i++) { + if (!types.get(i).compare(t.types.get(i))) + return false; + } + return true; + } + if (o instanceof FunctionType) { + //TODO + FunctionType func = (FunctionType) o; + if (!(func.getDomain() instanceof IntType)) { + return false; + } + TLAType range = func.getRange(); + for (int i = 0; i < types.size(); i++) { + if (types.get(i).compare(range)) { + continue; + } else { + return false; + } + } + return true; + } + return false; + } + + private boolean compareToAll(TLAType other) { + for (int i = 0; i < types.size(); i++) { + for (int j = i + 1; j < types.size(); j++) { + if (!types.get(i).compare(types.get(j))) + return false; + } + if (!types.get(i).compare(other)) + return false; + } + return true; + } + + @Override + public boolean contains(TLAType o) { + for (TLAType tlaType : types) { + if (tlaType.equals(o) || tlaType.contains(o)) + return true; + } + return false; + } + + @Override + public boolean isUntyped() { + for (TLAType tlaType : types) { + if (tlaType.isUntyped()) + return true; + } + return false; + } + + @Override + public TLAType cloneTLAType() { + ArrayList<TLAType> list = new ArrayList<TLAType>(); + for (TLAType tlaType : types) { + list.add(tlaType.cloneTLAType()); + } + return new TupleType(list); + } + + @Override + public TLAType unify(TLAType o) throws UnificationException { + if (!this.compare(o)) { + throw new UnificationException(); + } + if (o instanceof Untyped) { + ((Untyped) o).setFollowersTo(this); + return this; + } + if (o instanceof TupleType) { + TupleType tuple = (TupleType) o; + if (this.types.size() != tuple.types.size()) { + TLAType t = types.get(0); + for (int i = 1; i < types.size(); i++) { + t = t.unify(types.get(i)); + } + for (int i = 0; i < tuple.types.size(); i++) { + t = t.unify(tuple.types.get(i)); + } + return new FunctionType(IntType.getInstance(), t); + } else { + for (int i = 0; i < types.size(); i++) { + TLAType res = types.get(i).unify(tuple.types.get(i)); + types.set(i, res); + if (res instanceof AbstractHasFollowers) + ((AbstractHasFollowers) res).addFollower(this); + } + return this; + } + } + if (o instanceof FunctionType) { + //TODO + if(compareToAll(new Untyped())){ + //Function + TLAType t = types.get(0); + for (int i = 1; i < types.size(); i++) { + t = t.unify(types.get(i)); + } + FunctionType func = new FunctionType(IntType.getInstance(), t); + this.setFollowersTo(func); + return func.unify(o); + }else{ + TLAType res = types.get(1).unify(((FunctionType) o).getRange()); + types.set(1, res); + return this; + } + + } + throw new RuntimeException(); + } + + @Override + public String toString() { + String res = ""; + for (int i = 0; i < types.size(); i++) { + if (types.get(i) instanceof TupleType && i != 0) { + res += "(" + types.get(i) + ")"; + } else + res += types.get(i); + + if (i < types.size() - 1) { + res += "*"; + } + } + return res; + } + + @Override + public PExpression getBNode() { + List<PExpression> list = new ArrayList<PExpression>(); + for (TLAType t : types) { + list.add(t.getBNode()); + } + return new ACoupleExpression(list); + } + +} diff --git a/src/main/java/de/tla2b/types/Untyped.java b/src/main/java/de/tla2b/types/Untyped.java new file mode 100644 index 0000000000000000000000000000000000000000..7b7b36de7952f08c4f026394f725060dedb0b1b6 --- /dev/null +++ b/src/main/java/de/tla2b/types/Untyped.java @@ -0,0 +1,54 @@ +package de.tla2b.types; + +import de.be4.classicalb.core.parser.node.PExpression; +import de.tla2b.exceptions.UnificationException; + +public class Untyped extends AbstractHasFollowers { + + public Untyped() { + super(UNTYPED); + } + + public TLAType unify(TLAType o) throws UnificationException { + if (!this.compare(o)) { + throw new UnificationException(); + } + // u2 contains more or equal type information than untyped (this) + this.setFollowersTo(o); + //this.deleteFollowers(); + return o; + } + + @Override + public boolean compare(TLAType o){ + if(o.contains(this)){ + return false; + } + return true; + } + + @Override + public boolean contains(TLAType o){ + return false; + } + + @Override + public String toString() { + return "UNTYPED_"+hashCode(); + } + + @Override + public boolean isUntyped() { + return true; + } + + @Override + public Untyped cloneTLAType() { + return new Untyped(); + } + + @Override + public PExpression getBNode() { + return null; + } +} diff --git a/src/main/java/de/tla2bAst/TLAParser.java b/src/main/java/de/tla2bAst/TLAParser.java new file mode 100644 index 0000000000000000000000000000000000000000..32b92ca2db8ee3b76900f44c480223ddd647d818 --- /dev/null +++ b/src/main/java/de/tla2bAst/TLAParser.java @@ -0,0 +1,44 @@ +package de.tla2bAst; + +import tla2sany.drivers.FrontEndException; +import tla2sany.drivers.SANY; +import tla2sany.modanalyzer.SpecObj; +import tla2sany.semantic.ModuleNode; +import util.FilenameToStream; +import util.ToolIO; + +public class TLAParser { + + private FilenameToStream filenameToStream; + + public TLAParser(FilenameToStream filenameToStream) { + this.filenameToStream = filenameToStream; + } + + public ModuleNode parseModule(String moduleName) { + SpecObj spec = new SpecObj(moduleName, filenameToStream); + try { + SANY.frontEndMain(spec, moduleName, ToolIO.out); + } catch (FrontEndException e) { + // Error in Frontend, should never happens + return null; + } + + if (spec.parseErrors.isFailure()) { + } + + if (spec.semanticErrors.isFailure()) { + } + + // RootModule + ModuleNode n = spec.getExternalModuleTable().rootModule; + if (spec.getInitErrors().isFailure()) { + System.err.println(spec.getInitErrors()); + return null; + } + + if (n == null) { // Parse Error + } + return n; + } +} diff --git a/src/main/java/de/tla2bAst/Translator.java b/src/main/java/de/tla2bAst/Translator.java new file mode 100644 index 0000000000000000000000000000000000000000..b5744d7cd451f9c89a064f5f154341725fe8db5f --- /dev/null +++ b/src/main/java/de/tla2bAst/Translator.java @@ -0,0 +1,153 @@ +package de.tla2bAst; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import de.be4.classicalb.core.parser.node.Node; +import de.tla2b.analysis.InstanceTransformation; +import de.tla2b.analysis.SpecAnalyser; +import de.tla2b.analysis.SymbolRenamer; +import de.tla2b.analysis.SymbolSorter; +import de.tla2b.analysis.TypeChecker; +import de.tla2b.config.ConfigfileEvaluator; +import de.tla2b.config.ModuleOverrider; +import de.tla2b.exceptions.ConfigFileErrorException; +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.NotImplementedException; +import de.tla2b.exceptions.SemanticErrorException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.pprint.BAstCreator; +import de.tla2b.pprint.BMachinePrinter; +import tla2sany.semantic.ModuleNode; +import tlc2.tool.ModelConfig; +import util.FileUtil; +import util.ToolIO; + +public class Translator { + private String moduleFileName; + private String configFileName; + + + + private String moduleName; + private ModuleNode moduleNode; + private ModelConfig modelConfig; + + public Translator(String moduleFileName, String configFileName) { + this.moduleFileName = moduleFileName; + this.configFileName = configFileName; + + parse(); + } + + private void parse(){ + moduleName = evalFileName(moduleFileName); + + TLAParser tlaParser = new TLAParser(null); + moduleNode = tlaParser.parseModule(moduleName); + + modelConfig = null; + if (configFileName != null) { + modelConfig = new ModelConfig(configFileName, null); + modelConfig.parse(); + } + } + + public Translator(String moduleString, String configString, int i) { + moduleName = "Testing"; + File dir = new File("temp/"); + dir.mkdirs(); + + try { + File f = new File("temp/" + moduleName + ".tla"); + f.createNewFile(); + FileWriter fw = new FileWriter(f); + fw.write(moduleString); + fw.close(); + f.deleteOnExit(); + moduleFileName = f.getAbsolutePath(); + } catch (IOException e) { + e.printStackTrace(); + } + + modelConfig = null; + if (configString != null) { + File f = new File("temp/" + moduleName + ".cfg"); + + try { + f.createNewFile(); + FileWriter fw = new FileWriter(f); + fw.write(configString); + fw.close(); + } catch (IOException e) { + e.printStackTrace(); + } + f.deleteOnExit(); + configFileName = f.getAbsolutePath(); + } + dir.deleteOnExit(); + + parse(); + } + + public Node translate() throws TLA2BException { + InstanceTransformation trans = new InstanceTransformation(moduleNode); + trans.start(); + + SymbolSorter symbolSorter = new SymbolSorter(moduleNode); + symbolSorter.sort(); + + SpecAnalyser specAnalyser; + + ConfigfileEvaluator conEval = null; + if (modelConfig != null) { + + conEval = new ConfigfileEvaluator(modelConfig, moduleNode); + conEval.start(); + + ModuleOverrider modOver = new ModuleOverrider(moduleNode, conEval); + modOver.start(); + specAnalyser = new SpecAnalyser(moduleNode, conEval); + } else { + specAnalyser = new SpecAnalyser(moduleNode); + } + + specAnalyser.start(); + + TypeChecker typechecker = new TypeChecker(moduleNode, conEval, + specAnalyser); + typechecker.start(); + + specAnalyser.evalIfThenElse(); + + SymbolRenamer symRenamer = new SymbolRenamer(moduleNode, specAnalyser); + symRenamer.start(); + BMachinePrinter p = new BMachinePrinter(moduleNode, conEval, + specAnalyser); + //System.out.println(p.start()); + BAstCreator bAstCreator = new BAstCreator(moduleNode, conEval, + specAnalyser); + return bAstCreator.getStartNode(); + } + + public static String evalFileName(String name) { + if (name.toLowerCase().endsWith(".tla")) { + name = name.substring(0, name.length() - 4); + } + + if (name.toLowerCase().endsWith(".cfg")) { + name = name.substring(0, name.length() - 4); + } + + String sourceModuleName = name.substring(name + .lastIndexOf(FileUtil.separator) + 1); + + String path = name.substring(0, + name.lastIndexOf(FileUtil.separator) + 1); + if (!path.equals("")) + ToolIO.setUserDir(path); + return sourceModuleName; + } + +} diff --git a/src/test/java/de/tla2b/prettyprintb/BBuiltInsTest.java b/src/test/java/de/tla2b/prettyprintb/BBuiltInsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..93f059306fe65ebe5b6a504711c299a3b9009aa6 --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/BBuiltInsTest.java @@ -0,0 +1,61 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb; + +import static de.tla2b.util.TestUtil.compare; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.util.TestUtil; +import util.ToolIO; + +public class BBuiltInsTest { + + @Test + public void testBoolean() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE \\in BOOLEAN\n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE : BOOL \n" + "END"; + compare(expected, module); + } + + @Test + public void testString() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME \"abc\" \\in STRING\n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES \"abc\" : STRING \n" + "END"; + compare(expected, module); + } + + @Test + public void testBoolValue() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE \n" + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE = TRUE \n" + "END"; + compare(expected, module); + } + + @Test + public void testBoolValue2() throws Exception { + ToolIO.reset(); + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE = FALSE \n" + + "================================="; + + StringBuilder sb = TestUtil.translateString(module); + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE = FALSE \n" + "END"; + assertEquals(TestUtil.getBTreeofMachineString(expected), TestUtil.getBTreeofMachineString(sb.toString())); + } +} diff --git a/src/test/java/de/tla2b/prettyprintb/FunctionTest.java b/src/test/java/de/tla2b/prettyprintb/FunctionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b8846c5719e0ddeddcc363d4ab3e203991fad3ec --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/FunctionTest.java @@ -0,0 +1,197 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb; + +import static de.tla2b.util.TestUtil.compare; +import static org.junit.Assert.assertEquals; + +import org.junit.Ignore; +import org.junit.Test; + +import de.tla2b.util.TestUtil; +import util.ToolIO; + +public class FunctionTest { + + @Test + public void testFunctionConstructor() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = [x \\in {1} |-> TRUE = TRUE] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = %x.(x : {1}| bool(TRUE = TRUE)) \n" + + "END"; + compare(expected, module); + } + + @Test + public void testFunctionConstructor2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = [x,y \\in {1} |-> 1] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = %x,y.(x : {1} & y : {1}| 1) \n" + + "END"; + compare(expected, module); + } + + @Test + public void testFunctionConstructor3() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = [x \\in {1}, y \\in BOOLEAN |-> 1] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = %x,y.(x : {1} & y : BOOL| 1) \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * recursive Function + **********************************************************************/ + + @Ignore + @Test + public void testRecursiveFunction() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2, k3 \n" + + "fact[n \\in {1,2}] == IF n = 0 THEN 1 ELSE n+ fact[n-1] \n" + + "ASSUME k = fact /\\ fact[k2] = k3 \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k,k2,k3\n" + + "PROPERTIES k : POW(INTEGER*INTEGER) & k2 : INTEGER & k3 : INTEGER \n" + + " & k = fact & fact(k2) = k3 \n" + + "DEFINITIONS IF_THEN_ELSE(P, a, b) == (%t_.(t_=TRUE & P = TRUE | a )\\/%t_.(t_=TRUE & not(P= TRUE) | b ))(TRUE); \n" + + "fact == %n.(n : {1, 2}| IF_THEN_ELSE(bool(n = 0), 1, n + fact(n - 1))) \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Function call + **********************************************************************/ + @Test + public void testFunctionCall() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k\n" + + "ASSUME k = [x,y \\in {1} |-> x+y] /\\ k[1,2] = 1 \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = %x,y.(x : {1} & y : {1}| x + y) & k(1, 2) = 1" + + "END"; + compare(expected, module); + } + + @Test + public void testFunctionCall2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k\n" + + "ASSUME k = [x \\in {1} |-> TRUE] /\\ k[1] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = %x.(x : {1}| TRUE) & k(1) = TRUE\n" + "END"; + compare(expected, module); + } + + @Test + public void testDomain() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k\n" + + "ASSUME k = [x \\in {1} |-> x] /\\ DOMAIN k = {1} \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = %x.(x : {1}| x) & dom(k) = {1}" + "END"; + compare(expected, module); + } + + @Test + public void testSetOfFunction() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [BOOLEAN -> {1}] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = BOOL --> {1}" + + "END"; + compare(expected, module); + } + + @Ignore + @Test + public void testFunctionExcept() throws Exception { + ToolIO.reset(); + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [k EXCEPT ![TRUE] = 0, ![FALSE] = 0] \n" + + "================================="; + + StringBuilder sb = TestUtil.translateString(module); + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES " + " k : POW(BOOL*INTEGER)" + + "& k = k <+ {TRUE |-> 0, FALSE |-> 0}" + "END"; + assertEquals(TestUtil.getBTreeofMachineString(expected), TestUtil.getBTreeofMachineString(sb.toString())); + } + + /********************************************************************** + * Record Except @ + **********************************************************************/ + @Ignore + @Test + public void testFunctionExceptAt() throws Exception { + ToolIO.reset(); + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [x \\in {1,2} |-> x] /\\ k2 = [k EXCEPT ![1] = @ + 1] \n" + + "================================="; + + StringBuilder sb = TestUtil.translateString(module); + System.out.println(sb); + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k, k2\n" + + "PROPERTIES k : POW(INTEGER*INTEGER) & k2 : POW(INTEGER*INTEGER) & k = %x.(x : {1, 2}| x) & k2 = k <+ {1 |-> k(1) + 1} \n" + + "END"; + assertEquals(TestUtil.getBTreeofMachineString(expected), TestUtil.getBTreeofMachineString(sb.toString())); + } + @Ignore + @Test + public void testFunctionExceptAt2() throws Exception { + ToolIO.reset(); + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [x,y \\in {1,2} |-> x+y] /\\ k2 = [k EXCEPT ![1,1] = @ + 4] \n" + + "================================="; + + StringBuilder sb = TestUtil.translateString(module); + System.out.println(sb); + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k, k2\n" + + "PROPERTIES k : POW(INTEGER*INTEGER*INTEGER) " + + "& k2 : POW(INTEGER*INTEGER*INTEGER) " + + "& k = %x,y.(x : {1, 2} & y : {1, 2}| x + y) " + + "& k2 = k <+ {(1, 1) |-> k(1, 1) + 4} \n" + "END"; + assertEquals(TestUtil.getBTreeofMachineString(expected), TestUtil.getBTreeofMachineString(sb.toString())); + } +} diff --git a/src/test/java/de/tla2b/prettyprintb/LogicOperatorsTest.java b/src/test/java/de/tla2b/prettyprintb/LogicOperatorsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ae3d6e136fd61c5877aeb079d55303d8d23cce4f --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/LogicOperatorsTest.java @@ -0,0 +1,171 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb; + +import org.junit.Test; + +import de.tla2b.util.TestUtil; +import static de.tla2b.util.TestUtil.compare; +import static org.junit.Assert.*; + +public class LogicOperatorsTest { + + @Test + public void testEquality() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k = (k2 # 1)\n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k, k2\n" + + "PROPERTIES k = bool(k2 /= 1)\n" + + "END"; + compare(expected, module); + } + + @Test + public void testEquality2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = TRUE\n" + + "================================="; + + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = TRUE \n" + "END"; + compare(expected, module); + } + + @Test + public void testEquality3() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE\n" + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE = TRUE \n" + "END"; + compare(expected, module); + } + + /********************************************************************** + * Logic Operators: \neg, \lnot, \land, \cl, \lor, \dl, \equiv, => + **********************************************************************/ + @Test + public void testAnd() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k = (FALSE \\land k2) \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k, k2\n" + + "PROPERTIES k = bool(FALSE = TRUE & k2 = TRUE) \n" + + "END"; + compare(expected, module); + } + + @Test + public void testAnd2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE /\\ (TRUE \\/ FALSE) \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE = TRUE & (TRUE = TRUE or FALSE = TRUE) \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Negation: ~, \neg, \lnot + **********************************************************************/ + @Test + public void testNegation() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME \\lnot TRUE \n" + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES not(TRUE = TRUE) \n" + "END"; + compare(expected, module); + } + + /********************************************************************** + * Implication and Equivalence: =>, \equiv + **********************************************************************/ + + @Test + public void testImplication() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE /\\ (TRUE => FALSE) \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE = TRUE & (TRUE = TRUE => FALSE = TRUE) \n" + + "END"; + compare(expected, module); + } + + @Test + public void testEquivalence() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE /\\ (TRUE <=> FALSE) \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE = TRUE & (TRUE = TRUE <=> FALSE = TRUE) \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Quantification: \A x \in S : P or \E x \in S : P + **********************************************************************/ + @Test + public void testUniversalQuantifier() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME \\A x,y \\in {1,2} : x = 0 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES !x,y.(x : {1, 2} & y : {1, 2} => x = 0) \n" + + "END"; + compare(expected, module); + } + + @Test + public void testExistentialQuantifier() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME \\E x,y \\in {1,2} : x = 0 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES #x,y.(x : {1, 2} & y : {1, 2} & x = 0) \n" + + "END"; + compare(expected, module); + } + + @Test + public void testAppend() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "ASSUME Append(<<1>>, 2) = <<1,2>> \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES [1] <- 2 = [1,2] \n" + + "END"; + compare(expected, module); + } + + @Test + public void testQuantifier() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals, Sequences \n" + + "CONSTANTS S \n" + + "ASSUME S = {1,2,3} /\\ \\E u \\in Seq(S) : \\A s \\in S : \\E n \\in 1..Len(u) : u[n] = s \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS S\n" + + "PROPERTIES S = {1, 2, 3} & #u.(u : seq(S) & !s.(s : S => #n.(n : 1 .. size(u) & u(n) = s))) \n" + + "END"; + compare(expected, module); + } + +} diff --git a/src/test/java/de/tla2b/prettyprintb/PrecedenceTest.java b/src/test/java/de/tla2b/prettyprintb/PrecedenceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..479f8a55a5d70a7af9846b3cf5613947a2e0b51e --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/PrecedenceTest.java @@ -0,0 +1,77 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb; + +import static de.tla2b.util.TestUtil.compare; +import static org.junit.Assert.assertEquals; + +import org.junit.Ignore; +import org.junit.Test; + +import de.tla2b.util.TestUtil; +import util.ToolIO; + +public class PrecedenceTest { + + @Test + public void testSetConstructor() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME {x \\in {1,2,3} : x \\in {1} \\/ x \\in {2}} = {1,2} \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES {x|x : {1, 2, 3} & (x : {1} or x : {2})} = {1, 2} \n" + "END"; + compare(expected, module); + } + + @Test + public void testPrecedence() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME 1 + (2 * 3) = 7 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES 1 + 2 * 3 = 7 \n" + "END"; + compare(expected, module); + } + + + + @Test + public void testPrecedence2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME (1 + 2) * 3 = 9 \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES (1 + 2) * 3 = 9 \n" + "END"; + compare(expected, module); + } + + @Test + public void testPrecedence3() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME (1 + 2) + 3 = 6 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES 1 + 2 + 3 = 6 \n" + "END"; + compare(expected, module); + } + + @Test + public void testPrecedence4() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME 1 + (2 + 3) = 6 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES 1 + (2 + 3) = 6 \n" + "END"; + compare(expected, module); + } + +} diff --git a/src/test/java/de/tla2b/prettyprintb/SetsTest.java b/src/test/java/de/tla2b/prettyprintb/SetsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b3090c42b87c5aee5beee0e2f3737b34eb08e2ef --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/SetsTest.java @@ -0,0 +1,175 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb; + +import static de.tla2b.util.TestUtil.compare; + +import org.junit.Test; + +public class SetsTest { + + @Test + public void testSetEnumeration() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = {1,2,3}\n" + + "================================="; + + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = {1,2,3} \n" + "END"; + compare(expected, module); + } + + @Test + public void testSetEnumeration2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = {TRUE, 1 = 1}\n" + + "================================="; + + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = {TRUE, bool(1=1)} \n" + "END"; + compare(expected, module); + } + + /********************************************************************** + * Element of: \in, \notin + **********************************************************************/ + @Test + public void testIn() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE \\in BOOLEAN \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE : BOOL \n" + "END"; + compare(expected, module); + } + + @Test + public void testIn2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 \\in {1,2,3} \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES 1 : {1,2,3} \n" + "END"; + compare(expected, module); + } + + @Test + public void testNotIn() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 \\notin {} \n" + + "================================="; + final String expected = "MACHINE Testing\n" + "PROPERTIES 1 /: {} \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * set operators like difference, union, intersection: \setdiff, \cup, \cap + **********************************************************************/ + @Test + public void testSetDifference() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME {1} = {1,2} \\ {1} \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES {1} = {1,2} - {1} \n" + "END"; + compare(expected, module); + } + + @Test + public void testCup() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME {1,2} = {1} \\cup {2} \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES {1,2} = {1} \\/ {2} \n" + "END"; + compare(expected, module); + } + + @Test + public void testCap() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME {1} = {1,2} \\cap {2} \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES {1} = {1,2} /\\ {2} \n" + "END"; + compare(expected, module); + } + + /********************************************************************** + * Subseteq: subset or equal + **********************************************************************/ + @Test + public void testSubsteq() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME TRUE = ({1} \\subseteq {1,2}) \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES TRUE = bool({1} <: {1,2}) \n" + "END"; + compare(expected, module); + } + + /********************************************************************** + * SUBSET: conforms POW in B + **********************************************************************/ + @Test + public void testSubset() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME {{},{1}} = SUBSET {1,2} \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES {{},{1}} = POW({1,2}) \n" + "END"; + compare(expected, module); + } + + /********************************************************************** + * UNION + **********************************************************************/ + @Test + public void testUnion() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME UNION {{1},{2}} = {1,2} \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES union({{1},{2}}) = {1,2} \n" + "END"; + compare(expected, module); + } + + /********************************************************************** + * Set Constructor + **********************************************************************/ + @Test + public void testConstructor1() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME {x \\in {1,2} : x = 1} = {1} \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES {x | x : {1,2} & x = 1} = {1} \n" + "END"; + compare(expected, module); + } + + @Test + public void testConstructor2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME {1} = {x + y+ 2: x \\in {1,2}, y \\in {1} } \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES {1} = {t_|#x, y.(x : {1, 2} & y : {1} & t_ = x + y + 2)} \n" + + "END"; + compare(expected, module); + } + +} diff --git a/src/test/java/de/tla2b/prettyprintb/StructTest.java b/src/test/java/de/tla2b/prettyprintb/StructTest.java new file mode 100644 index 0000000000000000000000000000000000000000..78d0d0f6de7c95c6ba70961aa33400dd821d0aeb --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/StructTest.java @@ -0,0 +1,149 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb; + +import static de.tla2b.util.TestUtil.compare; +import static org.junit.Assert.assertEquals; + +import org.junit.Ignore; +import org.junit.Test; + +import de.tla2b.util.TestUtil; +import util.ToolIO; + +public class StructTest { + static { + ToolIO.setMode(ToolIO.TOOL); + } + + /********************************************************************** + * Set of Records: [L1 : e1, L2 : e2] + **********************************************************************/ + @Test + public void testStruct() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [a : {1}, b : BOOLEAN] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = struct(a : {1}, b : BOOL) \n" + + "END"; + compare(expected, module); + } + + + @Test + public void testStructExpansion() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME [a: {2}] = [a : {1}, b : BOOLEAN] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES struct(a : {2},b : BOOL) = struct(a : {1},b : BOOL) \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Record: [L1 |-> e1, L2 |-> e2] + **********************************************************************/ + @Test + public void testRecord() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [a |-> 1, b |-> TRUE] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = rec(a : 1, b : TRUE) \n" + + "END"; + compare(expected, module); + } + + + @Ignore + @Test + public void testRecordExpansion() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME [a|-> 2] = [a |-> 1, b |-> \"abc\"] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES rec(a : 2,b : \"\") = rec(a : 1,b : \"abc\") \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Record Select: r.c + **********************************************************************/ + @Test + public void testRecordSelect() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [a |-> 1, b |-> TRUE] /\\ k2 = k.a \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k, k2\n" + + "PROPERTIES k = rec(a : 1, b : TRUE) & k2 = k'a \n" + + "END"; + compare(expected, module); + } + + @Test + public void testRecordSelect2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [a |-> 1, b |-> TRUE] /\\ k.b \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = rec(a : 1, b : TRUE) & k'b = TRUE \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Record Except + **********************************************************************/ + @Ignore + @Test + public void testRecordExcept() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [a |-> 1, b |-> TRUE] /\\ k2 = [k EXCEPT !.a = 2] \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k, k2\n" + + "PROPERTIES k = rec(a : 1, b : TRUE) & k2 = rec(a : 2, b : k'b) \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Record Except @ + **********************************************************************/ + @Ignore + @Test + public void testRecordExceptAt() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [a |-> 1, b |-> TRUE] /\\ k2 = [k EXCEPT !.a = @ + 1] \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "ABSTRACT_CONSTANTS k, k2\n" + + "PROPERTIES k : struct(a:INTEGER,b:BOOL) & k2 : struct(a:INTEGER,b:BOOL) & k = rec(a : 1, b : TRUE) & k2 = rec(a : k'a + 1, b : k'b) \n" + + "END"; + compare(expected, module); + } + +} diff --git a/src/test/java/de/tla2b/prettyprintb/TupleTest.java b/src/test/java/de/tla2b/prettyprintb/TupleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..507ab4cb2f128d53757a0cada2e117dbc3904f6d --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/TupleTest.java @@ -0,0 +1,54 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb; + +import static de.tla2b.util.TestUtil.compare; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.util.TestUtil; + + +public class TupleTest { + + @Test + public void testTuple() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = <<TRUE,FALSE,TRUE>>\n" + + "================================="; + + final String expected = "MACHINE Testing\n" + "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = (TRUE,FALSE,TRUE) \n" + "END"; + compare(expected, module); + } + + @Test + public void testCartesianProduct() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = BOOLEAN \\X {1} \n" + + "================================="; + + final String expected = "MACHINE Testing\n"+ "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = BOOL*{1} \n" + "END"; + compare(expected, module); + } + + @Test + public void testCartesianProduct2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = BOOLEAN \\X ({1} \\X BOOLEAN) \n" + + "================================="; + + final String expected = "MACHINE Testing\n"+ "ABSTRACT_CONSTANTS k\n" + + "PROPERTIES k = BOOL*({1}*BOOL) \n" + "END"; + compare(expected, module); + } + + +} diff --git a/src/test/java/de/tla2b/prettyprintb/VariablesTest.java b/src/test/java/de/tla2b/prettyprintb/VariablesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..386aa9198e480ff1e38ad7a41ada7ebaa47dc7c2 --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/VariablesTest.java @@ -0,0 +1,29 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb; + +import static de.tla2b.util.TestUtil.compare; + +import org.junit.Test; + +public class VariablesTest { + + @Test + public void testVariables() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "VARIABLES x, y \n" + + "Init == x = 1 /\\ y = 1 \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "VARIABLES x, y\n" + + "INVARIANT x : INTEGER & y : INTEGER \n" + + "INITIALISATION x, y:(x = 1 & y = 1) \n" + + "END"; + compare(expected, module); + } + +} diff --git a/src/test/java/de/tla2b/prettyprintb/standardmodules/TestModuleFiniteSets.java b/src/test/java/de/tla2b/prettyprintb/standardmodules/TestModuleFiniteSets.java new file mode 100644 index 0000000000000000000000000000000000000000..507bfb84d6be5738ac7c201fb9d45e1b0506b27e --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/standardmodules/TestModuleFiniteSets.java @@ -0,0 +1,50 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb.standardmodules; + +import static de.tla2b.util.TestUtil.compare; +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.util.TestUtil; + + +public class TestModuleFiniteSets { + + @Test + public void testIsFiniteSet() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "ASSUME IsFiniteSet({1,2,3}) \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES {1,2,3} : FIN({1,2,3}) \n" + "END"; + compare(expected, module); + } + + @Test + public void testIsFiniteSet2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets, Naturals \n" + + "ASSUME IsFiniteSet(Nat) \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES NATURAL : FIN(NATURAL) \n" + "END"; + compare(expected, module); + } + + @Test + public void testCardinality() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets, Naturals \n" + + "ASSUME Cardinality({1,2,3}) = 3 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES card({1,2,3}) = 3 \n" + "END"; + compare(expected, module); + } + +} diff --git a/src/test/java/de/tla2b/prettyprintb/standardmodules/TestModuleNaturals.java b/src/test/java/de/tla2b/prettyprintb/standardmodules/TestModuleNaturals.java new file mode 100644 index 0000000000000000000000000000000000000000..fbd087135098a74165c5a6b969fc7e89a2d6464e --- /dev/null +++ b/src/test/java/de/tla2b/prettyprintb/standardmodules/TestModuleNaturals.java @@ -0,0 +1,99 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.prettyprintb.standardmodules; + +import static de.tla2b.util.TestUtil.compare; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.util.TestUtil; + + +public class TestModuleNaturals { + + /********************************************************************** + * >, <, <=, >= + **********************************************************************/ + + @Test + public void testCompareOperators() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME 1 < 2 /\\ 2 > 1 /\\ 1 <= 1 /\\ 1 >= 1 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES 1 < 2 & 2 > 1 & 1 <= 1 & 1 >= 1 \n" + "END"; + compare(expected, module); + } + + @Test + public void testCompareOperators2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME (1 < 2) = (2 > 1) /\\ (1 <= 1) = (1 >= 1) \n" + + "================================="; + + final String expected = "MACHINE Testing\n" + + "PROPERTIES bool(1 < 2) = bool(2 > 1) & bool(1 <= 1) = bool(1 >= 1) \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Arithmetic operator: +, -, *, \div, %, ^ + **********************************************************************/ + @Test + public void testArithmeticOperators() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME 1 + 2 = 4-1 /\\ 1 * 2 = 4 \\div 2 /\\ 1 ^ 1 = 1 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES 1 + 2 = 4 - 1 & 1 * 2 = 4 / 2 & 1 ** 1 = 1 \n" + + "END"; + compare(expected, module); + } + + /********************************************************************** + * Interval operator: x .. y + **********************************************************************/ + @Test + public void testDotDot() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME 1 \\in 1 .. 2 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES 1 : 1..2 \n" + + "END"; + compare(expected, module); + } + + @Test + public void testNat() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME 1 \\in Nat \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES 1 : NATURAL \n" + + "END"; + compare(expected, module); + } + + @Test + public void testMod() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals, Integers \n" + + "ASSUME -3 % 2 = 1 \n" + + "================================="; + final String expected = "MACHINE Testing\n" + + "PROPERTIES -3 - 2 * (-3 / 2) = 1 \n" + + "END"; + compare(expected, module); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/BBuiltInsTest.java b/src/test/java/de/tla2b/typechecking/BBuiltInsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a79f3b65f25528091feb3163d01273fa01d20757 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/BBuiltInsTest.java @@ -0,0 +1,90 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class BBuiltInsTest { + + + /********************************************************************** + * BOOLEAN + **********************************************************************/ + @Test + public void testBoolean() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = BOOLEAN \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k")); + } + + @Test (expected = TypeErrorException.class) + public void testBooleanException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME 1 \\in BOOLEAN \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k")); + } + + + /********************************************************************** + * String + **********************************************************************/ + @Test + public void testString() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = STRING \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(STRING)", t.getConstantType("k")); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorString() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME 1 = STRING \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Bool value: TRUE, FALSE + **********************************************************************/ + @Test + public void testBoolValue() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = TRUE \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k")); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorBoolValue() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 = TRUE \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + + +} diff --git a/src/test/java/de/tla2b/typechecking/ConfigTest.java b/src/test/java/de/tla2b/typechecking/ConfigTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ff938d0deb2b08a1810e709968b3a45a6edb8ca8 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/ConfigTest.java @@ -0,0 +1,42 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class ConfigTest { + + @Test + public void TestConAssignment() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + "================================="; + final String config = "CONSTANTS k = 1"; + TestTypeChecker t = TestUtil.typeCheckString(module, config); + assertEquals("INTEGER", t.getConstantType("k").toString()); + } + + @Test + public void TestConOverride() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "foo == 1\n" + + "ASSUME k2 = k\n" + + "================================="; + final String config = "CONSTANTS k <- foo"; + TestTypeChecker t = TestUtil.typeCheckString(module, config); + assertEquals("INTEGER", t.getConstantType("k2").toString()); + } + + // TODO DefOverriding + +} diff --git a/src/test/java/de/tla2b/typechecking/ConstantTypesTest.java b/src/test/java/de/tla2b/typechecking/ConstantTypesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f3c7471b068f64a3b257c02bbd740deb9ef89309 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/ConstantTypesTest.java @@ -0,0 +1,107 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class ConstantTypesTest { + + @Test + public void test1() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = 1 /\\ k2 = k\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void test2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = k2 /\\ k = 1\n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void test3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = k2 /\\ k = k3 /\\ k3 = 1\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k3")); + } + + @Test + public void worstCaseUnification() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS a, b, c, d, e, f, g, h \n" + + "ASSUME a = b \n" + + "ASSUME c = d \n" + + "ASSUME a = c \n" + + "ASSUME e = f \n" + + "ASSUME g = h \n" + + "ASSUME e = g \n" + + "ASSUME a = e \n" + + "ASSUME h = 1 \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("a")); + assertEquals("INTEGER", t.getConstantType("b")); + assertEquals("INTEGER", t.getConstantType("c")); + assertEquals("INTEGER", t.getConstantType("d")); + assertEquals("INTEGER", t.getConstantType("e")); + assertEquals("INTEGER", t.getConstantType("f")); + assertEquals("INTEGER", t.getConstantType("g")); + assertEquals("INTEGER", t.getConstantType("h")); + } + + @Test(expected = TypeErrorException.class) + public void prime() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "Next == 1' = 1 \n" + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void prime2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "foo == k' = 1 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test + public void ifThenElse() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k = IF 1 = 1 THEN k2 ELSE 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/DefinitionsTest.java b/src/test/java/de/tla2b/typechecking/DefinitionsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..954fe821e0418b9b5e1436e88bad89b0e5f525ad --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/DefinitionsTest.java @@ -0,0 +1,231 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class DefinitionsTest { + + /********************************************************************** + * Definition: foo(a,b) == e + **********************************************************************/ + @Test + public void testDefinition() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "foo(a,b) == a = 1 /\\ b = TRUE \n" + + "Next == foo(1,TRUE) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertEquals("INTEGER", t.getDefinitionParamType("foo", "a")); + assertEquals("BOOL", t.getDefinitionParamType("foo", "b")); + } + + @Test + public void testDefinition2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "foo(a,b) == a = k /\\ b = k2 \n" + + "bar == k = 1 /\\ k2 = TRUE \n" + + "ASSUME foo(1,FALSE) /\\ bar \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertEquals("INTEGER", t.getDefinitionParamType("foo", "a")); + assertEquals("BOOL", t.getDefinitionParamType("foo", "b")); + assertEquals("BOOL", t.getDefinitionType("bar")); + + } + + @Test + public void testDefinition3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "foo == k \n" + + "bar == foo = 1 \n" + + "ASSUME bar \n" + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getDefinitionType("foo")); + assertEquals("BOOL", t.getDefinitionType("bar")); + } + + @Test + public void testDefinition4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "foo(var, value) == var = value \n" + + "ASSUME foo(k,1) /\\ foo(k2,TRUE) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("BOOL", t.getConstantType("k2")); + } + + /********************************************************************** + * Definition Call + **********************************************************************/ + + @Test + public void testDefinitionCall() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "foo(a) == TRUE \n" + + "bar == foo(1) \n" + + "ASSUME bar \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertEquals("BOOL", t.getDefinitionType("bar")); + } + + @Test + public void testDefinitionCall2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "foo(a) == a \n" + + "bar == foo(1) \n" + + "baz == foo(TRUE) \n" + + "ASSUME baz /\\ bar = bar" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertTrue(t.getDefinitionType("foo").startsWith("UNTYPED")); + assertEquals("INTEGER", t.getDefinitionType("bar")); + assertEquals("BOOL", t.getDefinitionType("baz")); + } + + @Test + public void testDefinitionCall3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "foo(a) == a \n" + + "bar == foo(1) \n" + + "baz == k = foo(k2) /\\ k2 = bar \n" + + "ASSUME baz \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertTrue(t.getDefinitionType("foo").startsWith("UNTYPED")); + assertEquals("INTEGER", t.getDefinitionType("bar")); + assertEquals("BOOL", t.getDefinitionType("baz")); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testDefinitionCall4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "foo(a,b) == a \\cup b \n" + + "bar == foo({1}, k) \n" + + "baz == foo({TRUE}, k2)\n" + + "ASSUME baz = baz /\\ bar = bar" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertTrue(t.getDefinitionType("foo").startsWith("POW(UNTYPED")); + assertEquals("POW(INTEGER)", t.getDefinitionType("bar")); + assertEquals("POW(BOOL)", t.getDefinitionType("baz")); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("POW(BOOL)", t.getConstantType("k2")); + } + + @Test + public void testDefinitionCall5() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "foo(a,b) == a = b \n" + + "bar == foo(1,k) \n" + + "ASSUME bar \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertEquals("INTEGER", t.getConstantType("k")); + } + + @Test + public void testDefinitionCall6() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "foo(a,b) == a = b \n" + + "bar == foo(k, k2) /\\ k2 = 1 \n" + + "ASSUME bar \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertTrue(t.getDefinitionParamType("foo", "a").startsWith("UNTYPED")); + assertTrue(t.getDefinitionParamType("foo", "b").startsWith("UNTYPED")); + assertEquals("BOOL", t.getDefinitionType("bar")); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testDefinitionCall7() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "foo(a,b) == a \\cup b \n" + + "bar(x,y) == x = foo(y, k) /\\ y ={1} \n" + + "ASSUME bar(k2,k3) \n" + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertTrue(t.getDefinitionType("foo").startsWith("POW(UNTYPED")); + assertTrue(t.getDefinitionParamType("foo", "a").startsWith( + "POW(UNTYPED")); + assertTrue(t.getDefinitionParamType("foo", "b").startsWith( + "POW(UNTYPED")); + assertEquals("BOOL", t.getDefinitionType("bar")); + assertEquals("POW(INTEGER)", t.getDefinitionParamType("bar", "x")); + assertEquals("POW(INTEGER)", t.getDefinitionParamType("bar", "y")); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + } + + @Test + public void testDefinitionCall8() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "foo(a) == k = a \n" + + "bar == foo(k2)\n" + + "baz == k2 = 1 \n" + + "ASSUME bar /\\ baz \n" + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertEquals("BOOL", t.getDefinitionType("bar")); + assertEquals("BOOL", t.getDefinitionType("baz")); + assertEquals("INTEGER", t.getDefinitionParamType("foo", "a")); + } + + @Test + public void testDefinitionCall9() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "foo(a,b) == a = b \n" + + "ASSUME foo(k, 1) /\\ foo(k2, TRUE) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("BOOL", t.getConstantType("k2")); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertTrue(t.getDefinitionParamType("foo", "a").startsWith("UNTYPED")); + assertTrue(t.getDefinitionParamType("foo", "b").startsWith("UNTYPED")); + } + + @Test + public void testDefinitionCall10() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "foo(a,b) == a= 1 /\\ b = TRUE \n" + + "ASSUME foo(1, TRUE) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getDefinitionType("foo")); + assertEquals("INTEGER", t.getDefinitionParamType("foo", "a")); + assertEquals("BOOL", t.getDefinitionParamType("foo", "b")); + } +} diff --git a/src/test/java/de/tla2b/typechecking/ExceptTest.java b/src/test/java/de/tla2b/typechecking/ExceptTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ce5086df31130834b1a65c9c874c8efae3245c0b --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/ExceptTest.java @@ -0,0 +1,124 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class ExceptTest { + + @Test + public void testFunction() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [k2 EXCEPT ![TRUE] = 0] \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL*INTEGER)", t.getConstantType("k")); + assertEquals("POW(BOOL*INTEGER)", t.getConstantType("k2")); + } + + @Test + public void testFunctionRecord() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [k EXCEPT ![1] = [a|-> 1, b |-> TRUE], ![1].b = k2 ] " + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*struct(a:INTEGER,b:BOOL))", + t.getConstantType("k")); + assertEquals("BOOL", t.getConstantType("k2")); + } + + @Test + public void testFunctionRecord2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [k EXCEPT ![1].a = 2, ![1].b = k2 ] /\\ k2 = TRUE \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*struct(a:INTEGER,b:BOOL))", + t.getConstantType("k")); + } + + @Test + public void testRecord() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k = [k EXCEPT !.a = 2, !.b = TRUE] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k") + .toString()); + } + + @Test (expected = TypeErrorException.class) + public void testRecordOrFunction() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS a, b \n" + + "ASSUME a = [a EXCEPT !.a = 1, !.b = 1] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testRecordAtTypeError() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS r, r2\n" + + "ASSUME r = [a |-> TRUE] \n" + + "/\\ r2 = [r EXCEPT !.a = 1 = @] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testRecordAtTypeError2() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS r, r2\n" + + "ASSUME r = [x \\in {1,2}|->TRUE] \n" + + "/\\ r2 = [r EXCEPT ![1] = 1 = @] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testRecordAtTypeError3() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS r, r2\n" + + "ASSUME r = [x \\in {1,2}|->TRUE] \n" + + "/\\ r2 = [r EXCEPT ![1] = @ + 1] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test + public void testRecordAt() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k\n" + + "ASSUME k = [k EXCEPT ![1] = @ = @] \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/ExtendsTest.java b/src/test/java/de/tla2b/typechecking/ExtendsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..95e7cedf057e1b2d67bb885121f57dd26f1e13c3 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/ExtendsTest.java @@ -0,0 +1,24 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class ExtendsTest { + + @Test + public void TestExtendsCounter() throws Exception { + String path = "src/test/resources/typechecking/modules/"; + TestTypeChecker t = TestUtil.typeCheck(path + "ExtendsCounter.tla"); + assertEquals("INTEGER", t.getVariableType("x")); + assertEquals("INTEGER", t.getConstantType("start")); + } +} diff --git a/src/test/java/de/tla2b/typechecking/FunctionTest.java b/src/test/java/de/tla2b/typechecking/FunctionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..419fd9773193e4b2010961ce9099aecbcad29076 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/FunctionTest.java @@ -0,0 +1,440 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class FunctionTest { + + /********************************************************************** + * Function constructor + **********************************************************************/ + + @Test + public void testSimpleFunctionConstructor() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k = [x \\in {1} |-> 1] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*INTEGER)", t.getConstantType("k")); + } + + @Test + public void testFunctionConstructor() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, S \n" + + "ASSUME k = [x \\in S |-> x = k2] /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("POW(INTEGER)", t.getConstantType("S")); + } + + @Test + public void testFunctionConstructorTwoVariables() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [x,y \\in {1} |-> TRUE] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*INTEGER*BOOL)", t.getConstantType("k") + .toString()); + } + + @Test + public void testFunctionConstructor2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [<<x,y>> \\in {<<1,TRUE>>} |-> TRUE] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL*BOOL)", t.getConstantType("k") + .toString()); + } + + @Test + public void testFunctionConstructor6() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [x \\in {1}, <<y,z>> \\in {<<1,TRUE>>} |-> TRUE] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + //System.out.println(t.getConstantType("k").toString()); + assertEquals("POW(INTEGER*(INTEGER*BOOL)*BOOL)", t.getConstantType("k") + .toString()); + } + + @Test + public void testFunctionConstructorTwoVariables2() + throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [x \\in {1}, y \\in BOOLEAN |-> TRUE] \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL*BOOL)", t.getConstantType("k") + .toString()); + } + + @Test(expected = TypeErrorException.class) + public void testFunctionConstructorFail() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [<<x,y>> \\in {1} |-> TRUE] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test (expected = TypeErrorException.class) + public void testFunctionConstructorFail2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [<<x,y,z>> \\in ({1} \\times {1}) |-> TRUE] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + System.out.println(t.getConstantType("k")); + } + + @Test + public void testFunctionConstructor3() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S, S2 \n" + + "ASSUME k = [x,y \\in S, z \\in S2 |-> z] /\\ S = BOOLEAN /\\ S2 = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL*BOOL*INTEGER*INTEGER)", t.getConstantType("k")); + assertEquals("POW(BOOL)", t.getConstantType("S")); + assertEquals("POW(INTEGER)", t.getConstantType("S2")); + } + + @Test + public void testFunctionConstructor4() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, S, S2 \n" + + "ASSUME [x \\in S |-> k] = [x \\in S2 |-> x=k2] /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("POW(INTEGER)", t.getConstantType("S")); + assertEquals("POW(INTEGER)", t.getConstantType("S2")); + } + + @Test + public void testFunctionConstructor5() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS S, S2 \n" + + "ASSUME [x \\in S, y \\in S2 |-> 1] = [x,y \\in {1} |-> 1] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("S")); + assertEquals("POW(INTEGER)", t.getConstantType("S2")); + } + + @Test(expected = TypeErrorException.class) + public void testFunctionConstructorException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, S, S2 \n" + + "ASSUME [x \\in S, y \\in S2 |-> 1] = [x \\in {1} |-> 1] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * recursive Function + **********************************************************************/ + @Test + public void testRecursiveFunction() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2, k3 \n" + + "fact[n \\in {1,2}] == IF n = 0 THEN 1 ELSE n+ fact[n-1] \n" + + "ASSUME k = fact /\\ fact[k2] = k3 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*INTEGER)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k3")); + } + + /********************************************************************** + * Function call + **********************************************************************/ + + @Test + public void testFunctionCall() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k[1] = TRUE \n" + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + } + + @Test + public void testFunctionCall2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k[1,TRUE,2] = TRUE \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL*INTEGER*BOOL)", t.getConstantType("k")); + } + + @Test + public void testFunctionCall3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, S \n" + + "ASSUME k[k2,TRUE] = k3 \n" + + "ASSUME k = [x \\in {1}, y \\in S |-> 1]\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL*INTEGER)", t.getConstantType("k") + .toString()); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k3")); + assertEquals("POW(BOOL)", t.getConstantType("S")); + } + + @Test + public void testFunctionCall4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k[(TRUE /\\ TRUE)] = 2 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL*INTEGER)", t.getConstantType("k")); + } + + @Test(expected = TypeErrorException.class) + public void testFunctionCallException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, S \n" + + "ASSUME k = [x \\in {1} |-> 1]\n" + + "ASSUME k[k2,TRUE] = k3 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Domain + **********************************************************************/ + @Test + public void testDomain() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [x \\in {1}, y \\in BOOLEAN |-> 1]\n" + + "ASSUME k2 = DOMAIN k \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL*INTEGER)", t.getConstantType("k") + .toString()); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + } + + @Test + public void testDomain2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [x \\in {1}, y \\in BOOLEAN |-> 1]\n" + + "ASSUME k2 = DOMAIN k \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL*INTEGER)", t.getConstantType("k") + .toString()); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + } + + /********************************************************************** + * Set of Function + **********************************************************************/ + @Test + public void testSetOfFunction() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [BOOLEAN -> {1}] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(POW(BOOL*INTEGER))", t.getConstantType("k")); + } + + @Test + public void testSetOfFunction2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS S, S2 \n" + + "ASSUME [x \\in BOOLEAN |-> 1] \\in [S -> S2] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("S")); + assertEquals("POW(INTEGER)", t.getConstantType("S2")); + } + + @Test(expected = TypeErrorException.class) + public void testSetOfFunctionException() throws FrontEndException, + TLA2BException { + /* + * A set of tuple is not a function in TLA+ + */ + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS S, S2 \n" + + "ASSUME {1} \\X BOOLEAN \\in [S -> S2] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Except + **********************************************************************/ + @Test + public void testFunctionExcept() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [k2 EXCEPT ![TRUE] = 0] \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + + assertEquals("POW(BOOL*INTEGER)", t.getConstantType("k")); + assertEquals("POW(BOOL*INTEGER)", t.getConstantType("k2")); + } + + @Test + public void testFunctionExcept2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = [k2 EXCEPT ![TRUE,1] = k3] /\\ k3 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL*INTEGER*INTEGER)", t.getConstantType("k") + .toString()); + assertEquals("POW(BOOL*INTEGER*INTEGER)", t.getConstantType("k2") + .toString()); + assertEquals("INTEGER", t.getConstantType("k3")); + + } + + @Test + public void testFunctionExcept3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, k4, k5 \n" + + "ASSUME k = [k2 EXCEPT ![k3,k4] = k5]\n" + + "ASSUME k2 = [x \\in {1}, y \\in BOOLEAN |-> 1]" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL*INTEGER)", t.getConstantType("k") + .toString()); + assertEquals("POW(INTEGER*BOOL*INTEGER)", t.getConstantType("k2") + .toString()); + assertEquals("INTEGER", t.getConstantType("k3")); + assertEquals("BOOL", t.getConstantType("k4")); + assertEquals("INTEGER", t.getConstantType("k5")); + + } + + @Test + public void testFunctionExcept4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, k4, k5 \n" + + "ASSUME k = [k2 EXCEPT ![k3,k4] = k5]\n" + + "ASSUME k = [x \\in {1}, y \\in BOOLEAN |-> 1]" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL*INTEGER)", t.getConstantType("k") + .toString()); + assertEquals("POW(INTEGER*BOOL*INTEGER)", t.getConstantType("k2") + .toString()); + assertEquals("INTEGER", t.getConstantType("k3")); + assertEquals("BOOL", t.getConstantType("k4")); + assertEquals("INTEGER", t.getConstantType("k5")); + } + + @Test + public void testFunctionExcept6() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, k4\n" + + "ASSUME k = [k2 EXCEPT ![k3] = k4, ![1] = TRUE ]\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k").toString()); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2").toString()); + assertEquals("INTEGER", t.getConstantType("k3")); + assertEquals("BOOL", t.getConstantType("k4")); + } + + @Test + public void testFunctionExcept5() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [k2 EXCEPT ![1][1] = 2]\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*POW(INTEGER*INTEGER))", + t.getConstantType("k")); + assertEquals("POW(INTEGER*POW(INTEGER*INTEGER))", + t.getConstantType("k2")); + } + + @Test + public void testFunctionExcept7() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [k2 EXCEPT ![<<1,2>>] = 2]\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*INTEGER*INTEGER)", t.getConstantType("k")); + } + + /********************************************************************** + * Except @ + **********************************************************************/ + + @Test + public void testAt2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2,k3 \n" + + "ASSUME k = [k2 EXCEPT ![1] = TRUE, ![2] = @=k3] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("BOOL", t.getConstantType("k3")); + } + + @Test(expected = TypeErrorException.class) + public void testAtException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [k2 EXCEPT ![1] = TRUE, ![2] = @=1] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/InstanceTest.java b/src/test/java/de/tla2b/typechecking/InstanceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..60fd53e881e6a737e7450caada11d302259d35e8 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/InstanceTest.java @@ -0,0 +1,67 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + +import util.ToolIO; + +public class InstanceTest { + + private static String path = "src/test/resources/typechecking/modules/"; + + @Test + public void TestNamedInstanceCounter() throws Exception { + TestTypeChecker t = TestUtil.typeCheck(path + "NamedInstanceCounter.tla"); + assertEquals("INTEGER", t.getVariableType("c")); + assertEquals("INTEGER", t.getConstantType("start")); + } + + @Test + public void TestNamedInstancePoly() throws Exception { + TestTypeChecker t = TestUtil.typeCheck(path + "NamedInstancePoly.tla"); + assertEquals("INTEGER", t.getVariableType("c")); + } + + @Test + public void TestNamedInstancePoly2() throws Exception { + TestTypeChecker t = TestUtil.typeCheck(path + "NamedInstancePoly2.tla"); + assertEquals("INTEGER", t.getVariableType("c")); + } + + @Test + public void TestNamedInstancePoly3() throws Exception { + TestTypeChecker t = TestUtil.typeCheck(path + "NamedInstancePoly3.tla"); + assertEquals("BOOL", t.getVariableType("c")); + assertEquals("INTEGER", t.getVariableType("c2")); + } + + @Test + public void TestNamedInstancePoly4() throws Exception { + TestTypeChecker t = TestUtil.typeCheck(path + "NamedInstancePoly4.tla"); + assertEquals("BOOL", t.getVariableType("c")); + assertEquals("INTEGER", t.getConstantType("k")); + } + + @Test + public void TestInstanceValue() throws Exception { + TestTypeChecker t = TestUtil.typeCheck(path + "InstanceValue.tla", + "InstanceValue.cfg"); + assertEquals("INTEGER", t.getConstantType("c2")); + assertEquals("INTEGER", t.getConstantType("val2")); + } + + @Test + public void TestInstanceValue2Times() throws Exception { + TestTypeChecker t = TestUtil.typeCheck(path + "InstanceValue2Times.tla"); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("BOOL", t.getConstantType("k2")); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/LogicOperatorsTest.java b/src/test/java/de/tla2b/typechecking/LogicOperatorsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f4585bf4dc0ae16d6592ca53c4820478a8c8c153 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/LogicOperatorsTest.java @@ -0,0 +1,100 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class LogicOperatorsTest { + + /********************************************************************** + * equality and disequality: =, #, + **********************************************************************/ + @Test + public void testEquality() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k = (k2 = 1)\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k").toString()); + assertEquals("INTEGER", t.getConstantType("k2").toString()); + } + + @Test (expected = TypeErrorException.class) + public void testEqualityError() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 = TRUE\n" + + "================================="; + TestUtil.typeCheckString(module); + } + @Test (expected = TypeErrorException.class) + public void testEqualityError2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 = (1=1)\n" + + "================================="; + TestUtil.typeCheckString(module); + } + + + + /********************************************************************** + * Logic Operators: \neg, \lnot, \land, \cl, \lor, \dl, \equiv, => + **********************************************************************/ + @Test + public void testLogicOperators() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3\n" + + "ASSUME k = (k2 \\land k3) \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k").toString()); + assertEquals("BOOL", t.getConstantType("k2").toString()); + assertEquals("BOOL", t.getConstantType("k3").toString()); + } + + @Test (expected = TypeErrorException.class) + public void testLogicOperatorsError() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3\n" + + "ASSUME 1 = (k2 \\land k3) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Quantification: \A x \in S : P or \E x \in S : P. + **********************************************************************/ + + + @Test + public void testQuantification() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, S\n" + + "ASSUME k = (\\A x \\in S : x = k2) /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k").toString()); + assertEquals("INTEGER", t.getConstantType("k2").toString()); + assertEquals("POW(INTEGER)", t.getConstantType("S").toString()); + } + + @Test(expected = TypeErrorException.class) + public void testQuantificationException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME \\A <<x,y>> \\in {1} : TRUE \n" + + "================================="; + TestUtil.typeCheckString(module); + } +} diff --git a/src/test/java/de/tla2b/typechecking/MiscellaneousConstructsTest.java b/src/test/java/de/tla2b/typechecking/MiscellaneousConstructsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..38b627a7299d29f6670e34518b1c2ea8672c52bd --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/MiscellaneousConstructsTest.java @@ -0,0 +1,109 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class MiscellaneousConstructsTest { + + /********************************************************************** + * IF THEN ELSE + **********************************************************************/ + @Test + public void testIfThenElse() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, k4 \n" + + "ASSUME k = (IF k2 THEN k3 ELSE k4) /\\ k4 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER",t.getConstantType("k")); + assertEquals("BOOL",t.getConstantType("k2")); + assertEquals("INTEGER",t.getConstantType("k3")); + assertEquals("INTEGER",t.getConstantType("k4")); + } + + + /********************************************************************** + * IF THEN ELSE + **********************************************************************/ + @Test + public void testCase() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, e1, e2 \n" + + "ASSUME k = (CASE k2 -> e1 [] k3 -> e2) /\\ e2 = 1 \n" + + "================================="; + TestTypeChecker t =TestUtil.typeCheckString(module); + assertEquals("INTEGER",t.getConstantType("k")); + assertEquals("BOOL",t.getConstantType("k2")); + assertEquals("BOOL",t.getConstantType("k3")); + assertEquals("INTEGER",t.getConstantType("e1")); + assertEquals("INTEGER",t.getConstantType("e2")); + } + + @Test + public void testCase2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, e1, e2, e3 \n" + + "ASSUME k = (CASE k2 -> e1 [] k3 -> e2 [] OTHER -> e3) /\\ e2 = 1 \n" + + "================================="; + TestTypeChecker t =TestUtil.typeCheckString(module); + assertEquals("INTEGER",t.getConstantType("k")); + assertEquals("BOOL",t.getConstantType("k2")); + assertEquals("BOOL",t.getConstantType("k3")); + assertEquals("INTEGER",t.getConstantType("e1")); + assertEquals("INTEGER",t.getConstantType("e2")); + assertEquals("INTEGER",t.getConstantType("e3")); + } + + /********************************************************************** + * LET d == exp IN e + **********************************************************************/ + @Test + public void testLetIn() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = (LET d == k2 IN d = k3) /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t =TestUtil.typeCheckString(module); + assertEquals("BOOL",t.getConstantType("k")); + assertEquals("INTEGER",t.getConstantType("k2")); + assertEquals("INTEGER",t.getConstantType("k3")); + } + + @Test + public void testLetIn2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = (LET d == k2 d2 == k3 IN d = d2) /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t =TestUtil.typeCheckString(module); + assertEquals("BOOL",t.getConstantType("k")); + assertEquals("INTEGER",t.getConstantType("k2")); + assertEquals("INTEGER",t.getConstantType("k3")); + } + + @Test + public void testLetIn3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, k4 \n" + + "ASSUME k = (LET d(a,b) == a=k2/\\b=k3 IN d(1,k4)) /\\ k4 = TRUE \n" + + "================================="; + TestTypeChecker t =TestUtil.typeCheckString(module); + assertEquals("BOOL",t.getConstantType("k")); + assertEquals("INTEGER",t.getConstantType("k2")); + assertEquals("BOOL",t.getConstantType("k3")); + assertEquals("BOOL",t.getConstantType("k4")); + } + + +} diff --git a/src/test/java/de/tla2b/typechecking/OpArgTest.java b/src/test/java/de/tla2b/typechecking/OpArgTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a1c305305020ba7698ce99a88b23921cf5fd1097 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/OpArgTest.java @@ -0,0 +1,65 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.ConfigFileErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + + +public class OpArgTest { + + @Test + public void TestConOverridenByLessOp() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k(_,_), k2 \n" + + "ASSUME k2 = k(1,2)\n" + "================================="; + final String config = "CONSTANTS k <- <"; + TestTypeChecker t = TestUtil.typeCheckString(module, config); + assertEquals("BOOL", t.getConstantType("k2")); + } + + @Test(expected = ConfigFileErrorException.class) + public void TestOverridenConstantWrongArityException() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k(_,_) \n" + + "def == TRUE /\\ FALSE \n" + + "================================="; + final String config = "CONSTANTS k <- def"; + TestUtil.typeCheckString(module, config); + } + + @Test(expected = ConfigFileErrorException.class) + public void TestOverridenDefWrongArityException() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "foo(a, b) == a /\\ b \n" + + "def == TRUE /\\ FALSE \n" + + "ASSUME foo(TRUE, FALSE) \n" + + "================================="; + final String config = "CONSTANTS foo <- def"; + TestUtil.typeCheckString(module, config); + } + + @Test + public void TestOverridenByDef() throws Exception { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k(_,_), k2 \n" + + "def(a,b) == a /\\ b \n" + + "ASSUME k2 = k(TRUE,TRUE)\n" + + "================================="; + final String config = "CONSTANTS k <- def"; + TestTypeChecker t = TestUtil.typeCheckString(module, config); + assertEquals("BOOL", t.getConstantType("k2")); + System.out.println(t.getDefinitionType("def")); + assertEquals("BOOL", t.getDefinitionType("def")); + assertEquals("BOOL", t.getDefinitionParamType("def", "a")); + } +} diff --git a/src/test/java/de/tla2b/typechecking/SetTest.java b/src/test/java/de/tla2b/typechecking/SetTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4fad92a6033832457a2ce1ce105c9abc73de906d --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/SetTest.java @@ -0,0 +1,506 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + +import tla2sany.semantic.AbortException; + +public class SetTest { + + /********************************************************************** + * Set Enumeration: {1,2,3} + * + * @throws AbortException + **********************************************************************/ + + @Test + public void testSetEnumeration() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3\n" + + "ASSUME k = {k2, k3} /\\ k3 = 1\n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k3")); + + } + + @Test + public void testSetEnumeration2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3\n" + + "ASSUME k = {k2, k3} /\\ k = {1}\n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k3")); + } + + @Test + public void testSetEnumeration3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3\n" + + "ASSUME k = {k2,{k3}} /\\ k3 = 1\n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(POW(INTEGER))", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k3")); + } + + @Test + public void testSetEnumeration4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k = {{1},{k2}}\n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(POW(INTEGER))", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test(expected = TypeErrorException.class) + public void testSetEnumerationException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k = {1, TRUE}\n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testSetEnumerationException2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME 1 = {1, 2}\n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Element of: \in, \notin + **********************************************************************/ + @Test + public void testElementOfSet() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k \\in {k2} /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testElementOfSet2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k \\in {k2} /\\ k = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testElementOfSet3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k \\in {<<TRUE>>}\n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + } + + @Test(expected = TypeErrorException.class) + public void testElementOfSetError() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 = (1 \\in {1}) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testElementOfSetError2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 \\in 1 \n" + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * set operators like difference, union, intersection + **********************************************************************/ + @Test + public void testSetOperators() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3\n" + + "ASSUME k = (k2 \\cup k3) /\\ k3 = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("k2")); + assertEquals("POW(INTEGER)", t.getConstantType("k3")); + } + + @Test + public void testSetOperators2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k = (k \\cup k2) /\\ k2 = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("k2")); + } + + @Test(expected = TypeErrorException.class) + public void testSetOperatorsException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME 1 = k \\cup k2 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testSetOperatorsException2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = {1} \\cup {TRUE} \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * set constructor: {x \in S : p}. + **********************************************************************/ + @Test + public void testSubsetOf() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S\n" + + "ASSUME k = {x \\in S : x = 1} \n" + + "================================="; + TestTypeChecker t =TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("S")); + } + + @Test + public void testSubsetOf2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2\n" + + "ASSUME k = {x \\in {TRUE} : x = k2} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k")); + assertEquals("BOOL", t.getConstantType("k2")); + } + + @Test + public void testSubsetOf3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S, k2\n" + + "ASSUME k = {x \\in S : x = k2} /\\ k2 = TRUE \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k")); + assertEquals("POW(BOOL)", t.getConstantType("S")); + assertEquals("BOOL", t.getConstantType("k2")); + } + + @Test + public void testSubsetOf4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S\n" + + "ASSUME k = {x \\in S : TRUE} /\\ k = {TRUE} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k")); + assertEquals("POW(BOOL)", t.getConstantType("S")); + } + + @Test (expected = TypeErrorException.class) + public void testSubsetOfException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = {<<x,y>> \\in {TRUE} : TRUE} \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testSubsetOfException2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = {x \\in 1 : TRUE} \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test (expected = TypeErrorException.class) + public void testSubsetOfException3() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = {x \\in {} : 1 = 1} \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test + public void testSubsetOfTuple() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k\n" + + "ASSUME k = {<<x,y>> \\in {1} \\times {TRUE} : TRUE} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + } + + @Test + public void testSubsetOfTuple2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S, S2\n" + + "ASSUME k = {<<x,y>> \\in S \\times S2 : x = 1 /\\ y = TRUE} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("S")); + assertEquals("POW(BOOL)", t.getConstantType("S2")); + } + + @Test + public void testSubsetOfTuple3() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S\n" + + "ASSUME k = {<<x,y>> \\in S : x = 1 /\\ y = TRUE} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("S")); + } + + /********************************************************************** + * set constructor: {e : x \in S} + **********************************************************************/ + @Test + public void testSetOfAll() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S, k2\n" + + "ASSUME k = {x = k2 : x \\in S} /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("S")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testSetOfAll2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S\n" + + "ASSUME k = {{x} : x \\in S} /\\ S = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(POW(INTEGER))", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("S")); + } + + @Test + public void testSetOfAll3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S, k2\n" + + "ASSUME k = { x = y /\\ y = k2 : x,y \\in S} /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("S")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testSetOfAll4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S, S2, k2, k3\n" + + "ASSUME k = { x = k2 /\\ y /\\ z = k3 : x \\in S, y,z \\in S2 } /\\ k2 = TRUE \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k")); + assertEquals("POW(BOOL)", t.getConstantType("S")); + assertEquals("BOOL", t.getConstantType("k2")); + assertEquals("BOOL", t.getConstantType("k3")); + } + + @Test(expected = TypeErrorException.class) + public void testSetOfAllException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S\n" + + "ASSUME 1 = {x : x \\in S} \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testSetOfAllException2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S\n" + + "ASSUME k = {x : x \\in 1} \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testSetOfAllException3() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, S\n" + + "ASSUME k = {x : <<x,y>> \\in S} \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * SUBSET: conforms POW in B + **********************************************************************/ + @Test + public void testSubset() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = SUBSET k2 /\\ k2 = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testSubset2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = SUBSET k2 /\\ k = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test(expected = TypeErrorException.class) + public void testSubsetException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME 1 = SUBSET k \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * UNION + **********************************************************************/ + @Test + public void testUnion() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = UNION k2 /\\ k = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("POW(POW(INTEGER))", t.getConstantType("k2")); + } + + @Test + public void testUnion2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = UNION k2 /\\ k2 = {{1},{2}} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("POW(POW(INTEGER))", t.getConstantType("k2")); + } + + @Test(expected = TypeErrorException.class) + public void testUnionException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = UNION k2 /\\ k = 1 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testUnionException2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = UNION k2 /\\ k2 = {1,2} \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Subseteq: subset or equal + **********************************************************************/ + @Test + public void testSubseteq() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = (k2 \\subseteq k3) /\\ k3 = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("k2")); + assertEquals("POW(INTEGER)", t.getConstantType("k3")); + } + + @Test(expected = TypeErrorException.class) + public void testSubseteqException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = (k2 \\subseteq 1) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testSubseteqException2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME 1 = (k \\subseteq k2) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/StringTest.java b/src/test/java/de/tla2b/typechecking/StringTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6944edec529ba2bce7e200085971b57440934ef6 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/StringTest.java @@ -0,0 +1,64 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class StringTest { + + /********************************************************************** + * a String: "abc" + **********************************************************************/ + + @Test + public void testAString() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = \"abc\" \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("STRING", t.getConstantType("k").toString()); + } + + @Test (expected = TypeErrorException.class) + public void testAStringException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 = \"abc\" \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + + /********************************************************************** + * STRING + **********************************************************************/ + @Test + public void testString() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = STRING \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(STRING)", t.getConstantType("k").toString()); + } + + @Test (expected = TypeErrorException.class) + public void testStringException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 = STRING \n" + + "================================="; + + TestUtil.typeCheckString(module); + } +} diff --git a/src/test/java/de/tla2b/typechecking/StructTest.java b/src/test/java/de/tla2b/typechecking/StructTest.java new file mode 100644 index 0000000000000000000000000000000000000000..360131c61b56ed09d872b47de8ac0243f8bbe42a --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/StructTest.java @@ -0,0 +1,277 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + +import util.ToolIO; + +public class StructTest { + static { + ToolIO.setMode(ToolIO.TOOL); + } + + /********************************************************************** + * Set of Records: [L1 : e1, L2 : e2] + **********************************************************************/ + @Test + public void testStruct() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [a : {1}, b : BOOLEAN] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(struct(a:INTEGER,b:BOOL))", t.getConstantType("k")); + } + + @Test + public void testStruct2() throws FrontEndException, TLA2BException { + + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = [a : k2, b : k3] /\\ k2 = {1} /\\ k3 = BOOLEAN \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + + assertEquals("POW(struct(a:INTEGER,b:BOOL))", t.getConstantType("k")); + } + + @Test + public void testStruct3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME [a : {1}, b : BOOLEAN] = [a : k, b : k2] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("POW(BOOL)", t.getConstantType("k2")); + } + + @Test(expected = TypeErrorException.class) + public void testStructException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME 1 = [a : 1, b : TRUE] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testStructException2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME [a : {1}, b : BOOLEAN] = [a : BOOLEAN, b : BOOLEAN] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testStructException3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME [aa : {1}, b : BOOLEAN] = [a : {1}, b : BOOLEAN] \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Record: [L1 |-> e1, L2 |-> e2] + **********************************************************************/ + + @Test + public void testRecord() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [a |-> 1, b |-> TRUE] \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + } + + @Test + public void testRecord2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = [a |-> k2, b |-> k3] /\\ k2 = 1 /\\ k3 = TRUE \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + } + + @Test(expected = TypeErrorException.class) + public void testRecordException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "ASSUME 1 = [b |-> 1, a |-> TRUE] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test + public void testRecord3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME [a |-> k, b |-> k2] \\in [a: {1}, b: BOOLEAN] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("BOOL", t.getConstantType("k2")); + } + + /********************************************************************** + * Record Select: r.c + **********************************************************************/ + + @Test + public void testRecordSelect() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = [a |-> 1, b |-> TRUE] /\\ k2 = k.a \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testRecordSelect2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k2 = k.a /\\ k = [a |-> 1, b |-> TRUE] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testRecordSelect3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = [a |-> k2, b |-> k3] /\\ k.a = 1 /\\ k.b = TRUE \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("BOOL", t.getConstantType("k3")); + } + + @Test + public void testRecordSelect4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k \\in [a : k2, b : k3] /\\ k.a = 1 /\\ k.b = TRUE \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("k2")); + assertEquals("POW(BOOL)", t.getConstantType("k3")); + } + + @Test + public void testRecordSelectException3() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [a |-> 1] /\\ TRUE = k.b \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test + public void testRecordSelect5() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME 1 = k.a /\\ TRUE = k.b /\\ k = [a |-> 1] \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + } + + @Test(expected = TypeErrorException.class) + public void testRecordSelectException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME TRUE = k.a /\\ k = [a |-> 1] \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testRecordSelectException4() throws FrontEndException, + TLA2BException { + + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [a |-> 1] /\\ TRUE = k.a \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Record Except + **********************************************************************/ + + @Test + public void testRecordExcept() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3, k4 \n" + + "ASSUME k = [a|-> k2, b|-> k3] /\\ k4 = [k EXCEPT !.a = 1, !.b = TRUE]\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k4")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("BOOL", t.getConstantType("k3")); + } + + @Test + public void testRecordExcept2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME k.a = 1/\\ k2 = [k EXCEPT !.a = 1, !.b = TRUE] /\\ k2 = [a|->2, b |-> FALSE]\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k")); + assertEquals("struct(a:INTEGER,b:BOOL)", t.getConstantType("k2")); + } + + /********************************************************************** + * Record Except @ + **********************************************************************/ + + @Test + public void testRecordExceptAt() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = [a|-> TRUE] /\\ k2 = [k EXCEPT !.a = @ = k3]\n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("struct(a:BOOL)", t.getConstantType("k")); + assertEquals("struct(a:BOOL)", t.getConstantType("k2")); + assertEquals("BOOL", t.getConstantType("k3")); + } + + @Test(expected = TypeErrorException.class) + public void testRecordExceptAtException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = [a|-> TRUE] /\\ k2 = [k EXCEPT !.a = @ = 1]\n" + + "================================="; + TestUtil.typeCheckString(module); + } +} diff --git a/src/test/java/de/tla2b/typechecking/TupleTest.java b/src/test/java/de/tla2b/typechecking/TupleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6671f089ace2e6be874f68568d0ba27d6bfdc2ea --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/TupleTest.java @@ -0,0 +1,171 @@ +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class TupleTest { + + @Test + public void testSimpleTuple() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k = <<1,TRUE>> \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER*BOOL", t.getConstantType("k").toString()); + } + + @Test + public void testTuple3Components() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k = <<1,TRUE,1>> \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER*BOOL*INTEGER", t.getConstantType("k").toString()); + } + + @Test + public void testTuple3Components2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k = <<1,1,1>> \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER*INTEGER*INTEGER", t.getConstantType("k").toString()); + } + + @Test + public void testTupleComponentsOfTheSameType() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k = <<1,1>> \n" + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER*INTEGER", t.getConstantType("k").toString()); + } + + @Test + public void testTuple1() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = <<1,k2>> /\\ k2 = TRUE \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER*BOOL", t.getConstantType("k").toString()); + assertEquals("BOOL", t.getConstantType("k2").toString()); + } + + @Test + public void testCartesianProduct() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k = {1} \\times BOOLEAN \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k").toString()); + } + + @Test + public void testTupleSingleElement() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = <<TRUE>> \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k").toString()); + } + + @Test(expected = TypeErrorException.class) + public void testTuple2Elements() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = <<k2, k3>> /\\ k3 = TRUE \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + @Test + public void testUnifyTuple3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = <<k2, <<k3>> >> /\\ k3 = TRUE /\\ k2 = 1\n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER*POW(INTEGER*BOOL)", t.getConstantType("k") + .toString()); + assertEquals("INTEGER", t.getConstantType("k2").toString()); + assertEquals("BOOL", t.getConstantType("k3").toString()); + } + + @Test(expected = TypeErrorException.class) + public void testUnifyTuple4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k \\in <<TRUE>>\n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Cartesian Product + **********************************************************************/ + @Test + public void testCartesianProduct2() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = BOOLEAN \\X {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL*INTEGER)", t.getConstantType("k").toString()); + } + + @Test + public void testCartesianProduct3() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k, k2 \n" + + "ASSUME BOOLEAN \\X {1} = k \\X k2 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(BOOL)", t.getConstantType("k").toString()); + assertEquals("POW(INTEGER)", t.getConstantType("k2").toString()); + } + + @Test(expected = TypeErrorException.class) + public void testCartesianProductException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = BOOLEAN \\X 1 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/TupleVsSequenceTest.java b/src/test/java/de/tla2b/typechecking/TupleVsSequenceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..24cf8a104acb0a11d248f9d22b619725d70986fd --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/TupleVsSequenceTest.java @@ -0,0 +1,50 @@ +package de.tla2b.typechecking; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class TupleVsSequenceTest { + + @Test + public void testTupleVsSequence() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME k = Append(<<>>, TRUE) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + } + + @Test + public void testTupleVsSequence2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = Append(<<1,2,3>>, k2) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*INTEGER)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test + public void testTupleVsSequence3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS a, b, c\n" + + "ASSUME <<1,2,3,4>> = <<a,b,c>> \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("a")); + assertEquals("INTEGER", t.getConstantType("b")); + assertEquals("INTEGER", t.getConstantType("c")); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/TypeConflictsTest.java b/src/test/java/de/tla2b/typechecking/TypeConflictsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e4a1b9b25c0987732c4293ce3316cf0e9cf205ed --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/TypeConflictsTest.java @@ -0,0 +1,79 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + +import util.ToolIO; + +public class TypeConflictsTest { + + @Test(expected = TypeErrorException.class) + public void testTypeConflict1() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = {k} \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testTypeConflict2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME {k} = k \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testTypeConflict3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME {{k}} = k \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testTypeConflict4() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS k \n" + + "ASSUME k = [a |-> k] \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testTypeConflict5() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Integers \n" + + "CONSTANTS k \n" + + "ASSUME k = [x \\in {} |-> k] \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void testTypeConflict6() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "CONSTANTS a,b \n" + + "ASSUME a = [x|->1] /\\ b = [y|->a, x|->1] /\\ a=b \n" + + "================================="; + + TestUtil.typeCheckString(module); + } +} diff --git a/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleFiniteSets.java b/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleFiniteSets.java new file mode 100644 index 0000000000000000000000000000000000000000..fa93e1d0fc72c34dfb059497b22d5a21a0e4f639 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleFiniteSets.java @@ -0,0 +1,120 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking.standardmodules; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class TestModuleFiniteSets { + + /********************************************************************** + * IsFiniteSet + **********************************************************************/ + @Test + public void unifyIsFiniteSet() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "CONSTANTS k \n" + + "ASSUME k = IsFiniteSet({1,2,3}) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k")); + } + + @Test + public void unifyIsFiniteSet2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = IsFiniteSet(k2) /\\ k2 = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("k2")); + + } + + @Test + public void unifyIsFiniteSet3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "CONSTANTS k \n" + + "ASSUME k = IsFiniteSet({}) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k")); + } + + @Test(expected = TypeErrorException.class) + public void unifyErrorIsFiniteSet() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "ASSUME IsFiniteSet(1)\n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void unifyErrorIsFiniteSet2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "ASSUME 1 = IsFiniteSet({1})\n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Cardinality + **********************************************************************/ + @Test + public void unifyCardinality() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "CONSTANTS k \n" + + "ASSUME k = Cardinality({1,2,3}) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + } + + @Test + public void unifyCardinality2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = Cardinality(k2) /\\ k2 = {1} \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("POW(INTEGER)", t.getConstantType("k2")); + } + + @Test(expected = TypeErrorException.class) + public void unifyErrorCardinality() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "ASSUME Cardinality(1)\n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test(expected = TypeErrorException.class) + public void unifyErrorCardinality2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS FiniteSets \n" + + "ASSUME TRUE = Cardinality({1})\n" + + "================================="; + TestUtil.typeCheckString(module); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleIntegers.java b/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleIntegers.java new file mode 100644 index 0000000000000000000000000000000000000000..b658435a201b03a406568fd6e7dcbcb6265650b8 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleIntegers.java @@ -0,0 +1,67 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking.standardmodules; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class TestModuleIntegers { + + /********************************************************************** + * Int + **********************************************************************/ + @Test + public void unifyInt() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Integers \n" + + "CONSTANTS k \n" + + "ASSUME k = Int \n" + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + } + + @Test(expected = TypeErrorException.class) + public void unifyErrorInt() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Integers \n" + + "ASSUME TRUE \\in Int \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * unary minus: -x + **********************************************************************/ + @Test + public void unifyUnaryMinus() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Integers \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = -k2 \n" + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test(expected = TypeErrorException.class) + public void unifyErrorUnaryMinus() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Integers \n" + + "ASSUME TRUE = -1 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleNaturals.java b/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleNaturals.java new file mode 100644 index 0000000000000000000000000000000000000000..3fa055da24b9cc519bc546bd8f7bcc7b36833c24 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleNaturals.java @@ -0,0 +1,124 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking.standardmodules; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class TestModuleNaturals { + + /********************************************************************** + * Relational operators: >, <, <=, >= + **********************************************************************/ + @Test + public void testRelationalOperators() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = (k2 > k3) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k2")); + } + + @Test(expected = TypeErrorException.class) + public void testRelationalOperatorsException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2 \n" + + "ASSUME 1 = (2 > 1) \n" + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Arithmetic operator: +, -, *, /, mod, exp + **********************************************************************/ + @Test + public void testArithmeticOperators() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = k2 + k3 \n" + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k3")); + } + + @Test(expected = TypeErrorException.class) + public void testArithmeticOperatorsException() throws FrontEndException, + TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2 \n" + + "ASSUME TRUE = 1 + 1 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Interval operator: x .. y + **********************************************************************/ + + @Test + public void testDotDot() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = k2 .. k3 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + assertEquals("INTEGER", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("k3")); + } + + @Test(expected = TypeErrorException.class) + public void testDotDotException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k2, k3 \n" + + "ASSUME TRUE \\in k2 .. k3 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Nat + **********************************************************************/ + @Test + public void testNat() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "CONSTANTS k \n" + + "ASSUME k = Nat \n" + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER)", t.getConstantType("k")); + } + + @Test(expected = TypeErrorException.class) + public void unifyErrorNat() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Naturals \n" + + "ASSUME TRUE \\in Nat \n" + + "================================="; + TestUtil.typeCheckString(module); + } + +} diff --git a/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleSequences.java b/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleSequences.java new file mode 100644 index 0000000000000000000000000000000000000000..0ae160faef029bcd572d77ab1cada3a7c3685481 --- /dev/null +++ b/src/test/java/de/tla2b/typechecking/standardmodules/TestModuleSequences.java @@ -0,0 +1,356 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.typechecking.standardmodules; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.exceptions.TypeErrorException; +import de.tla2b.util.TestTypeChecker; +import de.tla2b.util.TestUtil; + + +public class TestModuleSequences { + + /********************************************************************** + * Seq(S): The set of all sequences of elements in S. + **********************************************************************/ + @Test + public void testSeq() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME k = Seq({TRUE}) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(POW(INTEGER*BOOL))", t.getConstantType("k")); + } + + @Test + public void testSeq2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME <<k>> \\in Seq({TRUE}) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("BOOL", t.getConstantType("k")); + } + + + + @Test (expected = TypeErrorException.class) + public void testSeqException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "ASSUME 1 = Seq({1}) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test (expected = TypeErrorException.class) + public void testSeqException2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME k = Seq(1) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + + /********************************************************************** + * Len(S) + **********************************************************************/ + @Test + public void testLen() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME k = Len(<<1,2,3>>) \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + } + + @Test (expected = TypeErrorException.class) + public void testLenException() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME TRUE = Len(<<1,2,3>>) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test (expected = TypeErrorException.class) + public void testLenException2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME 3 = Len({1,2,3}) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorLen2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME 1 = Len(1) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + + /********************************************************************** + * s \o s2 - concatenation of s and s2 + **********************************************************************/ + @Test + public void testUnifyConcatenation() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = k2 \\o <<TRUE>> \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + } + + @Test + public void testUnifyConcatenation2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME <<TRUE>> = k \\o k2 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + } + + @Test + public void testUnifyConcatenation3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k= k2 \\o k3 /\\ k3 = <<TRUE>> \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k3")); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorConcatenation() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = 1 \\o k2 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorConcatenation2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME 1 = k \\o k2 \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorConcatenation3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME <<TRUE>> = <<1>> \\o <<2>> \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + + /********************************************************************** + * Append(s, e) + **********************************************************************/ + @Test + public void testUnifyAppend() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = Append(k2, k3) /\\ k3 = TRUE \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + assertEquals("BOOL", t.getConstantType("k3")); + } + + @Test + public void testUnifyAppend2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = Append(k2, k3) /\\ k = <<TRUE>> \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + assertEquals("BOOL", t.getConstantType("k3")); + } + + @Test + public void testUnifyAppend3() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = Append(k2, 1) \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*INTEGER)", t.getConstantType("k")); + assertEquals("POW(INTEGER*INTEGER)", t.getConstantType("k2")); + } + + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorAppend() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2, k3 \n" + + "ASSUME k = Append(1, k3) \n" + + "================================="; + + TestUtil.typeCheckString(module); + } + + + /********************************************************************** + * Head(s): the first element of the seq + **********************************************************************/ + @Test + public void testUnifyHead() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = Head(k2) /\\ k2 = <<1>> \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("POW(INTEGER*INTEGER)", t.getConstantType("k2")); + } + + @Test + public void testUnifyHead2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = Head(k2) /\\ k = 1 \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("INTEGER", t.getConstantType("k")); + assertEquals("POW(INTEGER*INTEGER)", t.getConstantType("k2")); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorHead() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME k = Head(1) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * Tail(s): the sequence without the first element + **********************************************************************/ + @Test + public void testUnifyTail() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = Tail(k2) /\\ k = <<TRUE>> \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + } + + @Test + public void testUnifyTail2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2 \n" + + "ASSUME k = Tail(k2) /\\ k2 = <<TRUE>> \n" + + "================================="; + + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorTail() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k \n" + + "ASSUME k = Tail(1) \n" + + "================================="; + TestUtil.typeCheckString(module); + } + + /********************************************************************** + * SubSeq(s,m,n): The sequence <<s[m], s[m+1], ... , s[n]>> + **********************************************************************/ + @Test + public void testUnifySubSeq() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2, m, n \n" + + "ASSUME k = SubSeq(k2, m, n) /\\ k = <<TRUE>> \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("m")); + assertEquals("INTEGER", t.getConstantType("n")); + } + + @Test + public void testUnifySubSeq2() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2, m, n \n" + + "ASSUME k = SubSeq(k2, m, n) /\\ k2= <<TRUE>> \n" + + "================================="; + TestTypeChecker t = TestUtil.typeCheckString(module); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k")); + assertEquals("POW(INTEGER*BOOL)", t.getConstantType("k2")); + assertEquals("INTEGER", t.getConstantType("m")); + assertEquals("INTEGER", t.getConstantType("n")); + } + + @Test (expected = TypeErrorException.class) + public void testUnifyErrorSubSeq() throws FrontEndException, TLA2BException { + final String module = "-------------- MODULE Testing ----------------\n" + + "EXTENDS Sequences \n" + + "CONSTANTS k, k2, m, n \n" + + "ASSUME k = SubSeq(1, m, n) \n" + + "================================="; + + TestUtil.typeCheckString(module); + } +} diff --git a/src/test/java/de/tla2b/util/Ast2String.java b/src/test/java/de/tla2b/util/Ast2String.java new file mode 100644 index 0000000000000000000000000000000000000000..2fb20951b48d533fd1cf178399c657b817d06dd0 --- /dev/null +++ b/src/test/java/de/tla2b/util/Ast2String.java @@ -0,0 +1,67 @@ +package de.tla2b.util; + +import de.be4.classicalb.core.parser.analysis.ExtendedDFAdapter; +import de.be4.classicalb.core.parser.node.Node; +import de.be4.classicalb.core.parser.node.Start; +import de.be4.classicalb.core.parser.node.Token; + +public class Ast2String extends ExtendedDFAdapter { + private final StringBuilder builder = new StringBuilder(); + + @Override + public String toString() { + return builder.toString(); + } + + @Override + public void defaultIn(final Node node) { + super.defaultIn(node); + builder.append(node.getClass().getSimpleName()); + builder.append("("); + } + + @Override + public void defaultCase(final Node node) { + super.defaultCase(node); + if (node instanceof Token) { + builder.append(((Token) node).getText()); + } else { + builder.append(node.toString()); + } + + } + + @Override + public void defaultOut(final Node node) { + super.defaultOut(node); + builder.append(")"); + } + + @Override + public void beginList(final Node parent) { + builder.append('['); + } + + @Override + public void betweenListElements(final Node parent) { + builder.append(','); + } + + @Override + public void endList(final Node parent) { + builder.append(']'); + } + + @Override + public void betweenChildren(final Node parent) { + builder.append(','); + } + + @Override + public void caseStart(final Start node) { + inStart(node); + node.getPParseUnit().apply(this); + node.getEOF().apply(this); + outStart(node); + } +} diff --git a/src/test/java/de/tla2b/util/TestTypeChecker.java b/src/test/java/de/tla2b/util/TestTypeChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..f858a8646930b01aa8f8f65de3f0809b6efd370c --- /dev/null +++ b/src/test/java/de/tla2b/util/TestTypeChecker.java @@ -0,0 +1,127 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.util; + +import java.util.Hashtable; + +import de.tla2b.analysis.TypeChecker; +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.global.TranslationGlobals; +import de.tla2b.translation.Tla2BTranslator; +import de.tla2b.types.TLAType; + +import tla2sany.semantic.FormalParamNode; +import tla2sany.semantic.ModuleNode; +import tla2sany.semantic.OpDeclNode; +import tla2sany.semantic.OpDefNode; + +public class TestTypeChecker implements TranslationGlobals { + + public ModuleNode moduleNode; + public final int toolId = 5; + private Hashtable<String, TLAType> constants; + private Hashtable<String, TLAType> variables; + private Hashtable<String, DefCon> definitions; + + public TestTypeChecker() { + constants = new Hashtable<String, TLAType>(); + variables = new Hashtable<String, TLAType>(); + definitions = new Hashtable<String, DefCon>(); + } + + public void startTest(String moduleString, String configString) + throws FrontEndException, TLA2BException { + Tla2BTranslator translator = new Tla2BTranslator(); + translator.startTest(moduleString, configString); + translator.translate(); + moduleNode = translator.getModuleNode(); + init(); + } + + public void start(String moduleFileName, String configFileName) + throws FrontEndException, TLA2BException { + Tla2BTranslator translator = new Tla2BTranslator(); + translator.start(moduleFileName, configFileName); + translator.translate(); + moduleNode = translator.getModuleNode(); + init(); + } + + private void init() { + for (int i = 0; i < moduleNode.getConstantDecls().length; i++) { + OpDeclNode con = moduleNode.getConstantDecls()[i]; + constants.put(con.getName().toString(), + (TLAType) con.getToolObject(toolId)); + } + + for (int i = 0; i < moduleNode.getVariableDecls().length; i++) { + OpDeclNode var = moduleNode.getVariableDecls()[i]; + variables.put(var.getName().toString(), + (TLAType) var.getToolObject(toolId)); + } + + for (int i = 0; i < moduleNode.getOpDefs().length; i++) { + OpDefNode def = moduleNode.getOpDefs()[i]; + DefCon defCon = new DefCon((TLAType) def.getToolObject(5)); + if (defCon.getType() == null) + continue; + + if (STANDARD_MODULES.contains(def + .getOriginallyDefinedInModuleNode().getName().toString()) + || STANDARD_MODULES.contains(def.getSource() + .getOriginallyDefinedInModuleNode().getName() + .toString())) { + continue; + } + + for (int j = 0; j < def.getParams().length; j++) { + FormalParamNode p = def.getParams()[j]; + defCon.parameters.put(p.getName().toString(), + (TLAType) p.getToolObject(toolId)); + } + definitions.put(def.getName().toString(), defCon); + } + } + + + public String getConstantType(String conName) { + return constants.get(conName).toString(); + } + + public String getVariableType(String varName){ + return variables.get(varName).toString(); + } + + public String getDefinitionType(String defName){ + return definitions.get(defName).getType().toString(); + } + + public String getDefinitionParamType(String defName, String paramName){ + return definitions.get(defName).getParams().get(paramName).toString(); + } + + public class DefCon { + private Hashtable<String, TLAType> parameters; + private TLAType type; + + private DefCon(TLAType t) { + parameters = new Hashtable<String, TLAType>(); + type = t; + } + + public Hashtable<String, TLAType> getParams() { + return parameters; + } + + public TLAType getType() { + return type; + } + + public void setType(TLAType type) { + this.type = type; + } + } +} diff --git a/src/test/java/de/tla2b/util/TestUtil.java b/src/test/java/de/tla2b/util/TestUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..d8f7b1d17b5d5a653e5359d9467b9411f072d41a --- /dev/null +++ b/src/test/java/de/tla2b/util/TestUtil.java @@ -0,0 +1,149 @@ +/** + * @author Dominik Hansen <Dominik.Hansen at hhu.de> + **/ + +package de.tla2b.util; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; + +import de.be4.classicalb.core.parser.BParser; +import de.be4.classicalb.core.parser.exceptions.BException; +import de.be4.classicalb.core.parser.node.Node; +import de.be4.classicalb.core.parser.node.Start; +import de.tla2b.exceptions.FrontEndException; +import de.tla2b.exceptions.TLA2BException; +import de.tla2b.translation.Tla2BTranslator; +import de.tla2bAst.Translator; +import tla2sany.semantic.AbortException; +import util.FileUtil; +import util.ToolIO; + +public class TestUtil { + + public static StringBuilder translateString(String moduleString) + throws FrontEndException, TLA2BException, AbortException { + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + Tla2BTranslator translator = new Tla2BTranslator(); + translator.startTest(moduleString, null); + return translator.translate(); + } + + public static void compare(String bMachine, String tlaModule) throws BException, TLA2BException{ + ToolIO.setMode(ToolIO.TOOL); + String expected = getBTreeofMachineString(bMachine); + System.out.println(expected); + + Translator trans = new Translator(tlaModule, null, 1); + Node resultNode = trans.translate(); + String result = getTreeAsString(resultNode); + System.out.println(result); + assertEquals(expected, result); + } + + public static String getTreeAsString(Node node){ + final Ast2String ast2String = new Ast2String(); + node.apply(ast2String); + return ast2String.toString(); + } + + + public static StringBuilder translateString(String moduleString, String configString) + throws FrontEndException, TLA2BException, AbortException { + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + Tla2BTranslator translator = new Tla2BTranslator(); + translator.startTest(moduleString, configString); + return translator.translate(); + } + + + public static StringBuilder translate(String moduleFileName) + throws FrontEndException, TLA2BException, AbortException { + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + moduleFileName = moduleFileName.replace('/', FileUtil.separatorChar); + Tla2BTranslator translator = new Tla2BTranslator(); + translator.start(moduleFileName, null); + StringBuilder res = translator.translate(); + return res; + } + + public static StringBuilder translate(String moduleFileName, String configFileName) + throws FrontEndException, TLA2BException { + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + moduleFileName = moduleFileName.replace('/', FileUtil.separatorChar); + configFileName = configFileName.replace('/', FileUtil.separatorChar); + Tla2BTranslator translator = new Tla2BTranslator(); + translator.start(moduleFileName, configFileName); + return translator.translate(); + } + + + public static TestTypeChecker typeCheckString(String moduleString) throws FrontEndException, TLA2BException{ + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + TestTypeChecker testTypeChecker = new TestTypeChecker(); + testTypeChecker.startTest(moduleString, null); + return testTypeChecker; + + } + + public static TestTypeChecker typeCheckString(String moduleString, String configString) throws FrontEndException, TLA2BException{ + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + TestTypeChecker testTypeChecker = new TestTypeChecker(); + testTypeChecker.startTest(moduleString, configString); + return testTypeChecker; + } + + public static TestTypeChecker typeCheck(String moduleFileName) throws FrontEndException, TLA2BException{ + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + moduleFileName = moduleFileName.replace('/', FileUtil.separatorChar); + TestTypeChecker testTypeChecker = new TestTypeChecker(); + testTypeChecker.start(moduleFileName, null); + return testTypeChecker; + } + + public static TestTypeChecker typeCheck(String moduleFileName, String configFileName) throws FrontEndException, TLA2BException{ + ToolIO.setMode(ToolIO.TOOL); + ToolIO.reset(); + moduleFileName = moduleFileName.replace('/', FileUtil.separatorChar); + configFileName = configFileName.replace('/', FileUtil.separatorChar); + TestTypeChecker testTypeChecker = new TestTypeChecker(); + testTypeChecker.start(moduleFileName, configFileName); + return testTypeChecker; + } + + + public static String fileToString(String fileName) throws IOException { + StringBuilder res = new StringBuilder(); + BufferedReader in = new BufferedReader(new FileReader(fileName)); + String str; + while ((str = in.readLine()) != null) { + res.append(str + "\n"); + } + in.close(); + return res.toString(); + } + + + public static String getBTreeofMachineString(final String testMachine) + throws BException { + final BParser parser = new BParser("testcase"); + final Start startNode = parser.parse(testMachine, false); + + final Ast2String ast2String = new Ast2String(); + startNode.apply(ast2String); + final String string = ast2String.toString(); + return string; + } + + +} diff --git a/src/test/resources/examples/AsynchInterface/AsynchInterface.cfg b/src/test/resources/examples/AsynchInterface/AsynchInterface.cfg new file mode 100644 index 0000000000000000000000000000000000000000..4a45c4c6914fb06480b45c400ebd4c445ce8ae93 --- /dev/null +++ b/src/test/resources/examples/AsynchInterface/AsynchInterface.cfg @@ -0,0 +1,3 @@ +INIT Init +NEXT Next +INVARIANTS TypeInvariant \ No newline at end of file diff --git a/src/test/resources/examples/AsynchInterface/AsynchInterface.mch b/src/test/resources/examples/AsynchInterface/AsynchInterface.mch new file mode 100644 index 0000000000000000000000000000000000000000..b15fa61cbb52d4a8ff4113e35f1fe357d841d675 --- /dev/null +++ b/src/test/resources/examples/AsynchInterface/AsynchInterface.mch @@ -0,0 +1,33 @@ +MACHINE AsynchInterface +ABSTRACT_CONSTANTS Data +PROPERTIES + Data : POW(INTEGER) + & Data = 0 .. 7 +DEFINITIONS + TypeInvariant == val : Data + & rdy : {0, 1} + & ack : {0, 1} +VARIABLES val, rdy, ack +INVARIANT + val : INTEGER + & rdy : INTEGER + & ack : INTEGER + & TypeInvariant +INITIALISATION + val, rdy, ack:(val : Data + & rdy : {0, 1} + & ack = rdy) +OPERATIONS + Snd_Op = ANY val_n, rdy_n + WHERE val_n : INTEGER & rdy_n : INTEGER & rdy = ack + & val_n : Data + & rdy_n = 1 - rdy + & TRUE = TRUE + THEN val, rdy := val_n, rdy_n END; + + Rcv_Op = ANY ack_n + WHERE ack_n : INTEGER & rdy /= ack + & ack_n = 1 - ack + & TRUE = TRUE + THEN ack := ack_n END +END diff --git a/src/test/resources/examples/AsynchInterface/AsynchInterface.tla b/src/test/resources/examples/AsynchInterface/AsynchInterface.tla new file mode 100644 index 0000000000000000000000000000000000000000..3eddf863b771b07b5adfa998826363cc45a7f9ed --- /dev/null +++ b/src/test/resources/examples/AsynchInterface/AsynchInterface.tla @@ -0,0 +1,25 @@ +----- MODULE AsynchInterface ----- +EXTENDS Naturals +CONSTANTS Data +ASSUME Data = 0..7 (* added to avoid having to give Data a value in .cfg file *) +VARIABLES val, rdy, ack +TypeInvariant == /\ val \in Data + /\ rdy \in {0,1} + /\ ack \in {0,1} +---------------------- +Init == /\ val \in Data + /\ rdy \in {0,1} + /\ ack = rdy +Snd == /\ rdy=ack + /\ val' \in Data + /\ rdy' = 1-rdy + /\ UNCHANGED ack +Rcv == /\ rdy # ack + /\ ack' = 1-ack + /\ UNCHANGED <<val,rdy>> +Next == Snd \/ Rcv +Spec == Init /\ [] [Next]_<<val,rdy,ack>> +---------------------- +THEOREM Spec => [] TypeInvariant (* this defines the invariant; not yet automatically detected by TLA2B *) +======================= + diff --git a/src/test/resources/examples/Channel/Channel.cfg b/src/test/resources/examples/Channel/Channel.cfg new file mode 100644 index 0000000000000000000000000000000000000000..dbaae4075b4171db16d9b608eba70fe121c7e4fb --- /dev/null +++ b/src/test/resources/examples/Channel/Channel.cfg @@ -0,0 +1,5 @@ +CONSTANTS +Data = {d1,d2} +INIT Init +NEXT Next +INVARIANTS TypeInvariant \ No newline at end of file diff --git a/src/test/resources/examples/Channel/Channel.mch b/src/test/resources/examples/Channel/Channel.mch new file mode 100644 index 0000000000000000000000000000000000000000..99d83b20501aba325a5dbe7a72343ac5b96bc50f --- /dev/null +++ b/src/test/resources/examples/Channel/Channel.mch @@ -0,0 +1,30 @@ +MACHINE Channel +SETS + ENUM1 = {d1, d2} +ABSTRACT_CONSTANTS Data +PROPERTIES + Data = ENUM1 +DEFINITIONS + TypeInvariant == chan : struct(val : Data,rdy : {0, 1},ack : {0, 1}); + + Send(d) == chan'rdy = chan'ack + & chan_n = rec(val : d, rdy : 1 - chan'rdy, ack : chan'ack) +VARIABLES chan +INVARIANT + chan : struct(val:ENUM1,rdy:INTEGER,ack:INTEGER) + & TypeInvariant +INITIALISATION + chan:(TypeInvariant + & chan'ack = chan'rdy) +OPERATIONS + Send_Op(d) = ANY chan_n + WHERE d : Data & + chan_n : struct(val:ENUM1,rdy:INTEGER,ack:INTEGER) & Send(d) + THEN chan := chan_n END; + + Rcv_Op = ANY chan_n + WHERE chan_n : struct(val:ENUM1,rdy:INTEGER,ack:INTEGER) & chan'rdy /= chan'ack + & chan_n = rec(val : chan'val, rdy : chan'rdy, ack : 1 - chan'ack) + THEN chan := chan_n END +END + diff --git a/src/test/resources/examples/Channel/Channel.tla b/src/test/resources/examples/Channel/Channel.tla new file mode 100644 index 0000000000000000000000000000000000000000..3ac12470f4efb0ff91f590f61dee2f0db5b74673 --- /dev/null +++ b/src/test/resources/examples/Channel/Channel.tla @@ -0,0 +1,20 @@ +-------------------------- MODULE Channel ----------------------------- +EXTENDS Naturals +CONSTANT Data +VARIABLE chan + +TypeInvariant == chan \in [val : Data, rdy : {0, 1}, ack : {0, 1}] +----------------------------------------------------------------------- +Init == /\ TypeInvariant + /\ chan.ack = chan.rdy +Send(d) == /\ chan.rdy = chan.ack + /\ chan' = [chan EXCEPT !.val = d, !.rdy = 1 - @] + +Rcv == /\ chan.rdy # chan.ack + /\ chan' = [chan EXCEPT !.ack = 1 - @] + +Next == (\E d \in Data : Send(d)) \/ Rcv +Spec == Init /\ [] [Next]_<<chan>> +---------------------- +THEOREM Spec => [] TypeInvariant (* this defines the invariant; not yet automatically detected by TLA2B *) +======================================================================= diff --git a/src/test/resources/examples/Club/Club.cfg b/src/test/resources/examples/Club/Club.cfg new file mode 100644 index 0000000000000000000000000000000000000000..2f57580b8191246f34e4691675619b0af85f3b86 --- /dev/null +++ b/src/test/resources/examples/Club/Club.cfg @@ -0,0 +1,4 @@ +INIT Init +NEXT Next +CONSTANTS +NAME = {n1,n2,n3} diff --git a/src/test/resources/examples/Club/Club.mch b/src/test/resources/examples/Club/Club.mch new file mode 100644 index 0000000000000000000000000000000000000000..d81f1bfa5706cc598fbc32b0e9377960d673800b --- /dev/null +++ b/src/test/resources/examples/Club/Club.mch @@ -0,0 +1,39 @@ +MACHINE Club +SETS + ENUM1 = {n1, n2, n3} +ABSTRACT_CONSTANTS capacity, NAME, total +PROPERTIES + capacity : INTEGER + & NAME = ENUM1 + & total : INTEGER + & capacity : NATURAL & capacity = 2 + & card(NAME) > capacity + & total : NATURAL & total > 2 +DEFINITIONS + join_queue(nn) == nn /: member & nn /: waiting & card(waiting) < total & waiting_n = waiting \/ {nn} & TRUE = TRUE; + + join(nn) == nn : waiting & card(member) < capacity & member_n = member \/ {nn} & waiting_n = waiting - {nn}; + + remove(nn) == nn : member & member_n = member - {nn} & TRUE = TRUE +VARIABLES member, waiting +INVARIANT + member : POW(ENUM1) + & waiting : POW(ENUM1) +INITIALISATION + member, waiting:(member = {} & waiting = {}) +OPERATIONS + join_queue_Op(nn) = ANY waiting_n + WHERE nn : NAME & + waiting_n : POW(ENUM1) & join_queue(nn) + THEN waiting := waiting_n END; + + join_Op(nn) = ANY member_n, waiting_n + WHERE nn : NAME & + member_n : POW(ENUM1) & waiting_n : POW(ENUM1) & join(nn) + THEN member, waiting := member_n, waiting_n END; + + remove_Op(nn) = ANY member_n + WHERE nn : NAME & + member_n : POW(ENUM1) & remove(nn) + THEN member := member_n END +END diff --git a/src/test/resources/examples/Club/Club.tla b/src/test/resources/examples/Club/Club.tla new file mode 100644 index 0000000000000000000000000000000000000000..905b0ac493bf0e07438e80ce03c0f457ed0046a0 --- /dev/null +++ b/src/test/resources/examples/Club/Club.tla @@ -0,0 +1,31 @@ +------------------------------ MODULE Club ------------------------------- +EXTENDS Naturals, FiniteSets +CONSTANTS capacity, NAME, total +ASSUME capacity \in Nat /\ capacity = 2 +ASSUME Cardinality(NAME) > capacity +ASSUME total \in Nat /\ total > 2 + +VARIABLES member, waiting +---------------------------------------------------------------------------- +Inv == member \subseteq NAME /\ waiting \subseteq NAME + /\ member \cup waiting = {} + /\ Cardinality(member) \leq 4096 + /\ Cardinality(waiting) \leq total + +Init == member = {} /\ waiting = {} +---------------------------------------------------------------------------- + +join_queue(nn) == nn \notin member /\ nn \notin waiting + /\ Cardinality(waiting) < total /\ waiting' = waiting \cup {nn} + /\ UNCHANGED member + +join(nn) == nn \in waiting /\ Cardinality(member) < capacity + /\ member' = member \cup {nn} /\ waiting' = waiting\{nn} + +remove(nn) == nn \in member /\ member' = member\{nn} /\ UNCHANGED waiting + + +Next == \/ (\E nn \in NAME: join_queue(nn)) + \/ (\E nn \in NAME: join(nn)) + \/ (\E nn \in NAME: remove(nn)) +============================================================================= diff --git a/src/test/resources/examples/Counter/Counter.cfg b/src/test/resources/examples/Counter/Counter.cfg new file mode 100644 index 0000000000000000000000000000000000000000..c2c935a8c9abab6cadd624ad796e68ced5cf767a --- /dev/null +++ b/src/test/resources/examples/Counter/Counter.cfg @@ -0,0 +1,4 @@ +INIT Init +NEXT Next +CONSTANTS +k = 10 \ No newline at end of file diff --git a/src/test/resources/examples/Counter/Counter.mch b/src/test/resources/examples/Counter/Counter.mch new file mode 100644 index 0000000000000000000000000000000000000000..4e14b6b3049b1b69b6ae420875357230ed082f72 --- /dev/null +++ b/src/test/resources/examples/Counter/Counter.mch @@ -0,0 +1,18 @@ +MACHINE Counter +ABSTRACT_CONSTANTS k +PROPERTIES + k = 10 +VARIABLES a +INVARIANT + a : INTEGER +INITIALISATION + a:(a = 0) +OPERATIONS + Inc_Op = ANY a_n + WHERE a_n : INTEGER & a < k & a_n = a + 1 + THEN a := a_n END; + + Dec_Op = ANY a_n + WHERE a_n : INTEGER & a > 0 & a_n = a - 1 + THEN a := a_n END +END diff --git a/src/test/resources/examples/Counter/Counter.tla b/src/test/resources/examples/Counter/Counter.tla new file mode 100644 index 0000000000000000000000000000000000000000..42bd73e75f3091951825706e13424488b4433a81 --- /dev/null +++ b/src/test/resources/examples/Counter/Counter.tla @@ -0,0 +1,13 @@ +------------------------------ MODULE Counter ------------------------------- +EXTENDS Naturals +CONSTANTS k + +VARIABLES a + +Init == a = 0 + +Inc == a < k /\ a' = a+1 +Dec == a > 0 /\ a' = a-1 +Next == Inc \/ Dec + +============================================================================= \ No newline at end of file diff --git a/src/test/resources/examples/DefCapture/DefCapture.mch b/src/test/resources/examples/DefCapture/DefCapture.mch new file mode 100644 index 0000000000000000000000000000000000000000..643c7fff3b40fe6be59a0be8c867eb6c7666f23d --- /dev/null +++ b/src/test/resources/examples/DefCapture/DefCapture.mch @@ -0,0 +1,10 @@ +MACHINE DefCapture +PROPERTIES + Double(2) + & NotDouble(3) + & {x|x : {2, 3} & NotDouble(x)} = {3} +DEFINITIONS + Double(y) == #x_1.(x_1 : 1 .. 10 & x_1 + x_1 = y); + + NotDouble(y) == not(Double(y)) +END diff --git a/src/test/resources/examples/DefCapture/DefCapture.tla b/src/test/resources/examples/DefCapture/DefCapture.tla new file mode 100644 index 0000000000000000000000000000000000000000..7aa53cc4b90354d9c2be1b201caa5df3b9ae503d --- /dev/null +++ b/src/test/resources/examples/DefCapture/DefCapture.tla @@ -0,0 +1,15 @@ +-------------------------------- MODULE DefCapture -------------------------------- +EXTENDS Naturals + +Double(y) == \E x \in 1..10 :(x+x=y) + +NotDouble(y) == \neg Double(y) + +ASSUME Double(2) + +ASSUME NotDouble(3) + +ASSUME {x \in {2,3} : NotDouble(x)} = {3} + +======================= + diff --git a/src/test/resources/examples/DieHard/DieHard.cfg b/src/test/resources/examples/DieHard/DieHard.cfg new file mode 100644 index 0000000000000000000000000000000000000000..08aa2418b9aa2ed935c9a2eff7293c55a2b15681 --- /dev/null +++ b/src/test/resources/examples/DieHard/DieHard.cfg @@ -0,0 +1,3 @@ +INIT Init +NEXT Next +INVARIANTS TypeOK NotSolved diff --git a/src/test/resources/examples/DieHard/DieHard.mch b/src/test/resources/examples/DieHard/DieHard.mch new file mode 100644 index 0000000000000000000000000000000000000000..b65ad6e09ef0c59c6f6c8a7b1dffadfd49115de6 --- /dev/null +++ b/src/test/resources/examples/DieHard/DieHard.mch @@ -0,0 +1,49 @@ +MACHINE DieHard +DEFINITIONS + IF_THEN_ELSE(P, a, b) == (%t_.(t_ = TRUE & P = TRUE | a )\/%t_.(t_= TRUE & not(P= TRUE) | b ))(TRUE); + TypeOK == small : 0 .. 3 + & big : 0 .. 5; + + Min(m,n) == IF_THEN_ELSE(bool(m < n), m, n); + + NotSolved == big /= 4 +VARIABLES big, small +INVARIANT + big : INTEGER + & small : INTEGER + & TypeOK + & NotSolved +INITIALISATION + big, small:(big = 0 + & small = 0) +OPERATIONS + FillSmallJug_Op = ANY big_n, small_n + WHERE big_n : INTEGER & small_n : INTEGER & small_n = 3 + & big_n = big + THEN big, small := big_n, small_n END; + + FillBigJug_Op = ANY big_n, small_n + WHERE big_n : INTEGER & small_n : INTEGER & big_n = 5 + & small_n = small + THEN big, small := big_n, small_n END; + + EmptySmallJug_Op = ANY big_n, small_n + WHERE big_n : INTEGER & small_n : INTEGER & small_n = 0 + & big_n = big + THEN big, small := big_n, small_n END; + + EmptyBigJug_Op = ANY big_n, small_n + WHERE big_n : INTEGER & small_n : INTEGER & big_n = 0 + & small_n = small + THEN big, small := big_n, small_n END; + + SmallToBig_Op = ANY big_n, small_n + WHERE big_n : INTEGER & small_n : INTEGER & big_n = Min(big + small, 5) + & small_n = small - (big_n - big) + THEN big, small := big_n, small_n END; + + BigToSmall_Op = ANY big_n, small_n + WHERE big_n : INTEGER & small_n : INTEGER & small_n = Min(big + small, 3) + & big_n = big - (small_n - small) + THEN big, small := big_n, small_n END +END diff --git a/src/test/resources/examples/DieHard/DieHard.tla b/src/test/resources/examples/DieHard/DieHard.tla new file mode 100644 index 0000000000000000000000000000000000000000..0447532ccd6c21e6d42c16ce99b31b63cdea0b20 --- /dev/null +++ b/src/test/resources/examples/DieHard/DieHard.tla @@ -0,0 +1,129 @@ +------------------------------ MODULE DieHard ------------------------------- +(***************************************************************************) +(* In the movie Die Hard 3, the heros must obtain exactly 4 gallons of *) +(* water using a 5 gallon jug, a 3 gallon jug, and a water faucet. Our *) +(* goal: to get TLC to solve the problem for us. *) +(* *) +(* First, we write a spec that describes all allowable behaviors of our *) +(* heros. *) +(***************************************************************************) +EXTENDS Naturals + (*************************************************************************) + (* This statement imports the definitions of the ordinary operators on *) + (* natural numbers, such as +. *) + (*************************************************************************) + +(***************************************************************************) +(* We next declare the specification's variables. *) +(***************************************************************************) +VARIABLES big, \* The number of gallons of water in the 5 gallon jug. + small \* The number of gallons of water in the 3 gallon jug. + + +(***************************************************************************) +(* We now define TypeOK to be the type invariant, asserting that the value *) +(* of each variable is an element of the appropriate set. A type *) +(* invariant like this is not part of the specification, but it's *) +(* generally a good idea to include it because it helps the reader *) +(* understand the spec. Moreover, having TLC check that it is an *) +(* invariant of the spec catches errors that, in a typed language, are *) +(* caught by type checking. *) +(* *) +(* Note: TLA+ uses the convention that a list of formulas bulleted by /\ *) +(* or \/ denotes the conjunction or disjunction of those formulas. *) +(* Indentation of subitems is significant, allowing one to eliminate lots *) +(* of parentheses. This makes a large formula much easier to read. *) +(* However, it does mean that you have to be careful with your indentation.*) +(***************************************************************************) +TypeOK == /\ small \in 0..3 + /\ big \in 0..5 + + +(***************************************************************************) +(* Now we define of the initial predicate, that specifies the initial *) +(* values of the variables. I like to name this predicate Init, but the *) +(* name doesn't matter. *) +(***************************************************************************) +Init == /\ big = 0 + /\ small = 0 + +(***************************************************************************) +(* Now we define the actions that our hero can perform. There are three *) +(* things they can do: *) +(* *) +(* - Pour water from the faucet into a jug. *) +(* *) +(* - Pour water from a jug onto the ground. *) +(* *) +(* - Pour water from one jug into another *) +(* *) +(* We now consider the first two. Since the jugs are not calibrated, *) +(* partially filling or partially emptying a jug accomplishes nothing. *) +(* So, the first two possibilities yield the following four possible *) +(* actions. *) +(***************************************************************************) +FillSmallJug == /\ small' = 3 + /\ big' = big + +FillBigJug == /\ big' = 5 + /\ small' = small + +EmptySmallJug == /\ small' = 0 + /\ big' = big + +EmptyBigJug == /\ big' = 0 + /\ small' = small + +(***************************************************************************) +(* We now consider pouring water from one jug into another. Again, since *) +(* the jugs are not callibrated, when pouring from jug A to jug B, it *) +(* makes sense only to either fill B or empty A. And there's no point in *) +(* emptying A if this will cause B to overflow, since that could be *) +(* accomplished by the two actions of first filling B and then emptying A. *) +(* So, pouring water from A to B leaves B with the lesser of (i) the water *) +(* contained in both jugs and (ii) the volume of B. To express this *) +(* mathematically, we first define Min(m,n) to equal the minimum of the *) +(* numbers m and n. *) +(***************************************************************************) +Min(m,n) == IF m < n THEN m ELSE n + +(***************************************************************************) +(* Now we define the last two pouring actions. From the observation *) +(* above, these definitions should be clear. *) +(***************************************************************************) +SmallToBig == /\ big' = Min(big + small, 5) + /\ small' = small - (big' - big) + +BigToSmall == /\ small' = Min(big + small, 3) + /\ big' = big - (small' - small) + +(***************************************************************************) +(* We define the next-state relation, which I like to call Next. A Next *) +(* step is a step of one of the six actions defined above. Hence, Next is *) +(* the disjunction of those actions. *) +(***************************************************************************) +Next == \/ FillSmallJug + \/ FillBigJug + \/ EmptySmallJug + \/ EmptyBigJug + \/ SmallToBig + \/ BigToSmall + +----------------------------------------------------------------------------- + +(***************************************************************************) +(* Remember that our heros must measure out 4 gallons of water. *) +(* Obviously, those 4 gallons must be in the 5 gallon jug. So, they have *) +(* solved their problem when they reach a state with big = 4. So, we *) +(* define NotSolved to be the predicate asserting that big # 4. *) +(***************************************************************************) +NotSolved == big # 4 + +(***************************************************************************) +(* We find a solution by having TLC check if NotSolved is an invariant, *) +(* which will cause it to print out an "error trace" consisting of a *) +(* behavior ending in a states where NotSolved is false. Such a *) +(* behavior is the desired solution. (Because TLC uses a breadth-first *) +(* search, it will find the shortest solution.) *) +(***************************************************************************) +============================================================================= diff --git a/src/test/resources/examples/DieHard/DieHarder.cfg b/src/test/resources/examples/DieHard/DieHarder.cfg new file mode 100644 index 0000000000000000000000000000000000000000..7d9d78bce48c7e2a77fb26d922f50cb56aae20c5 --- /dev/null +++ b/src/test/resources/examples/DieHard/DieHarder.cfg @@ -0,0 +1,7 @@ +INIT Init +NEXT Next +INVARIANT NotSolved +CONSTANTS +Goal = 4 +Jug <- MCJug +Capacity <- MCCapacity \ No newline at end of file diff --git a/src/test/resources/examples/DieHard/DieHarder.mch b/src/test/resources/examples/DieHard/DieHarder.mch new file mode 100644 index 0000000000000000000000000000000000000000..fbb17293bacc05ea51b0941f0cad06aacebce1c8 --- /dev/null +++ b/src/test/resources/examples/DieHard/DieHarder.mch @@ -0,0 +1,44 @@ +MACHINE DieHarder +ABSTRACT_CONSTANTS Goal +PROPERTIES + Goal = 4 + & MCCapacity : MCJug --> {n|n : NATURAL & n > 0} + & Goal : NATURAL +DEFINITIONS + IF_THEN_ELSE(P, a, b) == (%t_.(t_ = TRUE & P = TRUE | a )\/%t_.(t_= TRUE & not(P= TRUE) | b ))(TRUE); + MCJug == {"j1", "j2"}; + + MCCapacity == %j_1.(j_1 : MCJug| (%t_.(t_ = 0 & j_1 = "j1" | 3) \/ %t_.(t_ = 0 & j_1 = "j2" | 5))(0)); + + Min(m,n) == IF_THEN_ELSE(bool(m < n), m, n); + + FillJug(j) == contents_n = contents <+ {j |-> MCCapacity(j)}; + + EmptyJug(j) == contents_n = contents <+ {j |-> 0}; + + amountPoured(j, k) == Min(contents(j), MCCapacity(k) - contents(k)); + JugToJug(j,k) == contents_n = contents <+ {j |-> contents(j) - amountPoured(j, k), k |-> contents(k) + amountPoured(j, k)}; + + NotSolved == !j.(j : MCJug => contents(j) /= Goal) +VARIABLES contents +INVARIANT + contents : POW(STRING*INTEGER) + & NotSolved +INITIALISATION + contents:(contents = %j.(j : MCJug| 0)) +OPERATIONS + FillJug_Op(j) = ANY contents_n + WHERE j : MCJug & + contents_n : POW(STRING*INTEGER) & FillJug(j) + THEN contents := contents_n END; + + EmptyJug_Op(j) = ANY contents_n + WHERE j : MCJug & + contents_n : POW(STRING*INTEGER) & EmptyJug(j) + THEN contents := contents_n END; + + JugToJug_Op(j, k) = ANY contents_n + WHERE j : MCJug & k : MCJug - {j} & + contents_n : POW(STRING*INTEGER) & JugToJug(j, k) + THEN contents := contents_n END +END \ No newline at end of file diff --git a/src/test/resources/examples/DieHard/DieHarder.tla b/src/test/resources/examples/DieHard/DieHarder.tla new file mode 100644 index 0000000000000000000000000000000000000000..27f329aff260fb7bf990765ef97afc4b7bd6cb78 --- /dev/null +++ b/src/test/resources/examples/DieHard/DieHarder.tla @@ -0,0 +1,104 @@ +----------------------------- MODULE DieHarder ------------------------------ +(***************************************************************************) +(* We now generalize the problem from Die Hard into one with an arbitrary *) +(* number of jugs, each holding some specified amount of water. *) +(***************************************************************************) +EXTENDS Naturals + +(***************************************************************************) +(* We now declare two constant parameters. *) +(***************************************************************************) + +CONSTANT Jug, \* The set of all jugs. + Capacity, \* A function, where Capacity[j] is the capacity of jug j. + Goal \* The quantity of water our heros must measure. +(***************************************************************************) +(* We make an assumption about these constants--namely, that Capacity is a *) +(* function from jugs to positive integers, and Goal is a natural number. *) +(***************************************************************************) +ASSUME /\ Capacity \in [Jug -> {n \in Nat : n > 0}] + /\ Goal \in Nat + + +(***************************************************************************) +(* Configfile replacements *) +(* Jug <- MCJug *) +(* Capacity <- MCCapacity *) +MCJug == {"j1", "j2"} + +MCCapacity == + [j \in MCJug |-> CASE j = "j1" -> 3 + [] j = "j2" -> 5 ] +(***************************************************************************) +(* We are going to need the Min operator again, so let's define it here. *) +(* (I prefer defining constant operators like this in the part of the *) +(* spec where constants are declared. *) +(***************************************************************************) +Min(m,n) == IF m < n THEN m ELSE n +----------------------------------------------------------------------------- +(***************************************************************************) +(* We declare the specification's single variable and define its type *) +(* invariant and initial predicate. *) +(***************************************************************************) +VARIABLE contents \* contents[j] is the amount of water in jug j + +TypeOK == contents \in [Jug -> Nat] + +Init == contents = [j \in Jug |-> 0] +----------------------------------------------------------------------------- +(***************************************************************************) +(* Now we define the actions that can be performed. They are the obvious *) +(* generalizations of the ones from the simple DieHard spec. First come *) +(* the actions of filling and emptying jug j, then the action of *) +(* pouring water from jug j to jug k. *) +(* *) +(* Note: The definitions use the TLA+ notation *) +(* *) +(* [f EXCEPT ![c]=e] *) +(* *) +(* which is the function g that is the same as f except g[c]=e. In the *) +(* expression e, the symbol @ stands for f[c]. This has the more general *) +(* form *) +(* *) +(* [f EXCEPT ![c1] = e1, ... , ![ck] = ek] *) +(* *) +(* that has the expected meaning. *) +(***************************************************************************) +FillJug(j) == contents' = [contents EXCEPT ![j] = Capacity[j]] + +EmptyJug(j) == contents' = [contents EXCEPT ![j] = 0] + +JugToJug(j, k) == + LET amountPoured == Min(contents[j], Capacity[k]-contents[k]) + IN contents' = [contents EXCEPT ![j] = @ - amountPoured, + ![k] = @ + amountPoured] + +(***************************************************************************) +(* As usual, the next-state relation Next is the disjunction of all *) +(* possible actions, where existential quantification is a general form of *) +(* disjunction. *) +(***************************************************************************) +Next == \E j \in Jug : \/ FillJug(j) + \/ EmptyJug(j) + \/ \E k \in Jug \ {j} : JugToJug(j, k) + +(***************************************************************************) +(* We define the formula Spec to be the complete specification, asserting *) +(* of a behavior that it begins in a state satisfying Init, and that every *) +(* step either satisfies Next or else leaves contents unchanged. *) +(***************************************************************************) +Spec == Init /\ [][Next]_contents +----------------------------------------------------------------------------- +(***************************************************************************) +(* We define NotSolved to be true of a state iff no jug contains Goal *) +(* gallons of water. *) +(***************************************************************************) +NotSolved == \A j \in Jug : contents[j] # Goal + +(***************************************************************************) +(* We find a solution by having TLC check if NotSolved is an invariant, *) +(* which will cause it to print out an "error trace" consisting of a *) +(* behavior ending in a states where NotSolved is false. Such a *) +(* behavior is the desired solution. *) +(***************************************************************************) +============================================================================= diff --git a/src/test/resources/examples/Doors/Doors.cfg b/src/test/resources/examples/Doors/Doors.cfg new file mode 100644 index 0000000000000000000000000000000000000000..3cae8360b34554c2ab9e1645c5118898db10cb37 --- /dev/null +++ b/src/test/resources/examples/Doors/Doors.cfg @@ -0,0 +1,8 @@ +INIT Init +NEXT Next +CONSTANTS +DOOR = {D1,D2,D3} +open = open +closed = closed +INVARIANT +Inv \ No newline at end of file diff --git a/src/test/resources/examples/Doors/Doors.mch b/src/test/resources/examples/Doors/Doors.mch new file mode 100644 index 0000000000000000000000000000000000000000..c515edcb75be9b66375a7cbb06441b817c6d77c4 --- /dev/null +++ b/src/test/resources/examples/Doors/Doors.mch @@ -0,0 +1,31 @@ +MACHINE Doors +SETS + ENUM1 = {D1, D2, D3}; ENUM2 = {open, closed} +ABSTRACT_CONSTANTS DOOR, POSITION +PROPERTIES + DOOR = ENUM1 + & POSITION : POW(ENUM2) + & POSITION = {open, closed} +DEFINITIONS + Inv == position : DOOR --> POSITION; + + opening(dd) == dd : DOOR & position_n = position <+ {dd |-> open}; + + closedoor(dd) == dd : DOOR & position_n = position <+ {dd |-> closed} +VARIABLES position +INVARIANT + position : POW(ENUM1*ENUM2) + & Inv +INITIALISATION + position:(position = %x.(x : DOOR| closed)) +OPERATIONS + opening_Op(dd) = ANY position_n + WHERE dd : DOOR & + position_n : POW(ENUM1*ENUM2) & opening(dd) + THEN position := position_n END; + + closedoor_Op(dd) = ANY position_n + WHERE dd : DOOR & + position_n : POW(ENUM1*ENUM2) & closedoor(dd) + THEN position := position_n END +END diff --git a/src/test/resources/examples/Doors/Doors.tla b/src/test/resources/examples/Doors/Doors.tla new file mode 100644 index 0000000000000000000000000000000000000000..4c42a68c8654ec445d3ee7ab747ff299e002eac3 --- /dev/null +++ b/src/test/resources/examples/Doors/Doors.tla @@ -0,0 +1,15 @@ +------------------------------ MODULE Doors ------------------------------- +EXTENDS Naturals +CONSTANTS DOOR, POSITION, open, closed +ASSUME POSITION = {open,closed} +VARIABLES position + +Inv == position \in [DOOR -> POSITION] +Init == position = [x \in DOOR |-> closed] + +opening(dd)== dd \in DOOR /\ position' = [position EXCEPT ![dd] = open ] + +closedoor(dd)== dd \in DOOR /\ position' = [position EXCEPT ![dd] = closed ] + +Next == \E dd \in DOOR : opening(dd) \/ closedoor(dd) +============================================================================= \ No newline at end of file diff --git a/src/test/resources/examples/FastPaxos/FastPaxos.tla b/src/test/resources/examples/FastPaxos/FastPaxos.tla new file mode 100644 index 0000000000000000000000000000000000000000..f2494dffbae85a751c3936fa54f393442ff9c00b --- /dev/null +++ b/src/test/resources/examples/FastPaxos/FastPaxos.tla @@ -0,0 +1,210 @@ +------------------------------ MODULE FastPaxos ----------------------------- +CONSTANTS PVal, Acceptor, FastNum, ClassicNum, Quorum(_), _\prec_, NextNum(_) + +i \preceq j == (i \prec j) \/ (i = j) + +Max(S) == CHOOSE i \in S : \A j \in S : j \preceq i + +RNum == FastNum \cup ClassicNum + +ASSUME + /\ FastNum \cap ClassicNum = {} + /\ \A i, j, k \in RNum : (i \prec j) /\ (j \prec k) => (i \prec k) + /\ \A i \in RNum : ~(i \prec i) + /\ \A i, j \in RNum : (i \preceq j) \/ (j \preceq i) + /\ (0 \notin RNum) /\ \A i \in RNum : 0 \prec i + /\ \A i \in FastNum : NextNum(i) \in RNum => + ~\E j \in RNum : (i \prec j) /\ (j \prec NextNum(i)) + +R3 == \A i, j \in RNum : + \A Q \in Quorum(i), R \in Quorum(j) : Q \cap R # {} +R5b == \A i, j \in RNum : + (j \in FastNum) => \A Q \in Quorum(i), R1, R2 \in Quorum(j) : + Q \cap R1 \cap R2 # {} + +ASSUME + /\ \A i \in RNum : Quorum(i) \subseteq SUBSET Acceptor + /\ R3 /\ R5b + +any == CHOOSE v : v \notin PVal + +Message == + [type : {"propose"}, pval : PVal] + \cup [type : {"phase1a"}, rnd : RNum] + \cup [type : {"phase1b"}, rnd : RNum, vrnd : RNum \cup {0}, + pval : PVal \cup {any}, acc : Acceptor] + \cup [type : {"phase2a"}, rnd : RNum, pval : PVal \cup {any}] + \cup [type : {"phase2b"}, rnd : RNum, pval : PVal, acc : Acceptor] + + +VARIABLES rnd, vrnd, pval, sentMsg, learned +vars == <<rnd, vrnd, pval, sentMsg, learned>> + +TypeOK == + /\ rnd \in [Acceptor -> RNum \cup {0}] + /\ vrnd \in [Acceptor -> RNum \cup {0}] + /\ pval \in [Acceptor -> PVal \cup {any}] + /\ sentMsg \in SUBSET Message + /\ learned \in SUBSET PVal + +Init == + /\ rnd = [a \in Acceptor |-> 0] + /\ vrnd = [a \in Acceptor |-> 0] + /\ pval = [a \in Acceptor |-> any] + /\ sentMsg = {} + /\ learned = {} +----------------------------------------------------------------------------- +Send(m) == sentMsg' = sentMsg \cup {m} + +Propose(v) == + /\ Send([type |-> "propose", pval |-> v]) + /\ UNCHANGED <<rnd, vrnd, pval, learned>> + +Phase1a(i) == + /\ Send([type |-> "phase1a", rnd |-> i]) + /\ UNCHANGED <<rnd, vrnd, pval, learned>> + +Phase1b(a, i) == + /\ rnd[a] \prec i + /\ \E m \in sentMsg : (m.type = "phase1a") /\ (m.rnd = i) + /\ rnd' = [rnd EXCEPT ![a] = i] + /\ Send([type |-> "phase1b", rnd |-> i, vrnd |-> vrnd[a], pval |-> pval[a], + acc |-> a]) + /\ UNCHANGED <<vrnd, pval, learned>> + +P1bMsg(Q, i) == + {m \in sentMsg : (m.type = "phase1b") /\ (m.acc \in Q) /\ (m.rnd = i)} + +SafeSet(M, Q, i) == + LET k == Max({m.vrnd : m \in M}) + Vk == {m.pval : m \in {mm \in M : mm.vrnd = k}} + Only(v) == \/ Vk = {v} + \/ /\ k \in FastNum + /\ \E R \in Quorum(k) : + \A a \in Q \cap R : + \E m \in M : /\ m.vrnd = k + /\ m.pval = v + /\ m.acc = a + IN IF k = 0 + THEN PVal + ELSE IF \E v \in Vk : Only(v) + THEN {CHOOSE v \in Vk : Only(v)} + ELSE PVal + +Phase2a(i, va) == + /\ ~\E m \in sentMsg : (m.type = "phase2a") /\ (m.rnd = i) + /\ \E Q \in Quorum(i) : + /\ \A a \in Q : \E m \in sentMsg : /\ m.type = "phase1b" + /\ m.rnd = i + /\ m.acc = a + /\ \/ /\ va \in SafeSet(P1bMsg(Q,i), Q, i) + /\ \E m \in sentMsg : /\ m.type \in {"propose", "phase1b"} + /\ m.pval = va + \/ /\ SafeSet(P1bMsg(Q,i), Q, i) = PVal + /\ i \in FastNum + /\ va = any + /\ Send([type |-> "phase2a", rnd |-> i, pval |-> va]) + /\ UNCHANGED <<rnd, vrnd, pval, learned>> + +Phase2b(i, a, v) == + /\ rnd[a] \preceq i + /\ vrnd[a] \prec i + /\ \E m \in sentMsg : + /\ m.type = "phase2a" + /\ m.rnd = i + /\ \/ m.pval = v + \/ /\ m.pval = any + /\ \E mm \in sentMsg : (mm.type = "propose") /\ (mm.pval = v) + /\ rnd' = [rnd EXCEPT ![a] = i] + /\ vrnd' = [vrnd EXCEPT ![a] = i] + /\ pval' = [pval EXCEPT ![a] = v] + /\ Send([type |-> "phase2b", rnd |-> i, pval |-> v, acc |-> a]) + /\ UNCHANGED learned + +Learn(v) == + /\ \E i \in RNum : + \E Q \in Quorum(i) : + \A a \in Q : + \E m \in sentMsg : /\ m.type = "phase2b" + /\ m.rnd = i + /\ m.pval = v + /\ m.acc = a + /\ learned' = learned \cup {v} + /\ UNCHANGED <<rnd, vrnd, pval, sentMsg>> +----------------------------------------------------------------------------- +P2bToP1b(Q, i) == + LET iMsg == + {m \in sentMsg : (m.type = "phase2b") /\ (m.rnd = i) /\ (m.acc \in Q)} + IN {[type |-> "phase1b", rnd |-> NextNum(i), vrnd |-> i, + pval |-> m.pval, acc |-> m.acc] : m \in iMsg} + +LeaderRecovery(i, v) == + /\ ~\E m \in sentMsg : (m.type = "phase2a") /\ (m.rnd = NextNum(i)) + /\ \E Q \in Quorum(i) : + /\ \A a \in Q : \E m \in P2bToP1b(Q, i) : m.acc = a + /\ v \in SafeSet(P2bToP1b(Q, i), Q, NextNum(i)) + /\ \E m \in P2bToP1b(Q, i) : m.pval = v + /\ Send([type |-> "phase2a", rnd |-> NextNum(i), pval |-> v]) + /\ UNCHANGED <<rnd, vrnd, pval, learned>> + +LeaderlessRecovery(i, a, v) == + /\ NextNum(i) \in FastNum + /\ rnd[a] = i + /\ vrnd[a] = i + /\ \E Q \in Quorum(i) : + /\ \A b \in Q : \E m \in P2bToP1b(Q, i) : m.acc = b + /\ v \in SafeSet(P2bToP1b(Q, i), Q, NextNum(i)) + /\ \E m \in P2bToP1b(Q, i): m.pval = v + /\ rnd' = [rnd EXCEPT ![a] = NextNum(i)] + /\ vrnd' = [vrnd EXCEPT ![a] = NextNum(i)] + /\ pval' = [pval EXCEPT ![a] = v] + /\ Send([type |-> "phase2b", rnd |-> NextNum(i), pval |-> v, acc |-> a]) + /\ UNCHANGED learned + + +----------------------------------------------------------------------------- +Next == + \/ \E v \in PVal : Propose(v) \/ Learn(v) + \/ \E i \in RNum : \/ Phase1a(i) + \/ \E a \in Acceptor : \/ Phase1b(a, i) + \/ \E v \in PVal : Phase2b(i, a, v) + \/ \E va \in PVal \cup {any} : Phase2a(i, va) + (*\/ \E i \in FastNum, v \in PVal : + \/ LeaderRecovery(i, v) + \/ \E a \in Acceptor :LeaderlessRecovery(i, a, v)*) + +Spec == Init /\ [][Next]_vars + +VotedForIn(a, v, i) == + \E m \in sentMsg : /\ m.type = "phase2b" + /\ m.acc = a + /\ m.pval = v + /\ m.rnd = i + +VotedorAbstainedIn(a, i) == + \/ \E v \in PVal : VotedForIn(a, v, i) + \/ i \prec rnd[a] + +R1 == \A m \in sentMsg : + (m.type = "phase2b") => \E mm \in sentMsg : /\ mm.type = "propose" + /\ mm.pval = m.pval + +R2 == \A a \in Acceptor, v1, v2 \in PVal, i \in RNum : + VotedForIn(a, v1, i) /\ VotedForIn(a, v2, i) => (v1 = v2) + +ChooseableIn(v, i) == + \E Q \in Quorum(i) : + \A a \in Q : (~ VotedorAbstainedIn(a, i)) \/ VotedForIn(a, v, i) + +NOC(v, i) == \A w \in PVal : ChooseableIn(w, i) => (w = v) + +SafeIn(v, i) == \A j \in RNum : (j \prec i) => NOC(v, j) + +R4 == \A a \in Acceptor, v \in PVal, i \in RNum : + VotedForIn(a, v, i) => SafeIn(v, i) + +R5a == \A j \in ClassicNum : + \A a1, a2 \in Acceptor : + \A v1, v2 \in PVal : + VotedForIn(a1, v1, j) /\ VotedForIn(a2, v2, j) => (v1 = v2) +============================================================================= diff --git a/src/test/resources/examples/FastPaxos/MCFastPaxos.cfg b/src/test/resources/examples/FastPaxos/MCFastPaxos.cfg new file mode 100644 index 0000000000000000000000000000000000000000..7988268bf808945b1ee5c763df8f5d3b7def732d --- /dev/null +++ b/src/test/resources/examples/FastPaxos/MCFastPaxos.cfg @@ -0,0 +1,13 @@ +CONSTANTS + ClassicNum = {1,3} + FastNum = {2} + Acceptor = {a1,a2,a3} + PVal = {v1,v2} + Quorum <- MCQuorum + any =[FastPaxos] any + a1=a1 a2=a2 a3=a3 v1=v1 v2=v2 + +SPECIFICATION Spec +INVARIANT TypeOK Correctness \* R1 R2 R4 R5a + + diff --git a/src/test/resources/examples/FastPaxos/MCFastPaxos.tla b/src/test/resources/examples/FastPaxos/MCFastPaxos.tla new file mode 100644 index 0000000000000000000000000000000000000000..e1cd84b489711c5ebaf80f45be6b2145a426eed4 --- /dev/null +++ b/src/test/resources/examples/FastPaxos/MCFastPaxos.tla @@ -0,0 +1,25 @@ +----------------------------- MODULE MCFastPaxos ---------------------------- +EXTENDS FiniteSets, Naturals + +CONSTANTS PVal, Acceptor, FastNum, ClassicNum, Quorum(_) \* , _\prec_ +VARIABLES rnd, vrnd, pval, sentMsg, learned + +NextNum(a) == IF a+1 \in FastNum \cup ClassicNum THEN a+1 ELSE 0 + +INSTANCE FastPaxos WITH \prec <- < +CONSTANTS a1, a2, a3, v1, v2 + +MCQuorum(i) == IF i \in ClassicNum THEN {{a1,a2}, {a1,a3}, {a2, a3}} + ELSE {{a1,a2,a3}} +Correctness == + /\ Cardinality(learned) \leq 1 + /\ \A v \in learned : \E m \in sentMsg : /\ m.type = "propose" + /\ m.pval = v +TSpec == Init /\ [][Next]_vars + +(* +TInit == + +TSpec == TInit /\ [][Next]_vars +*) +============================================================================= diff --git a/src/test/resources/examples/GraphIso/GraphIso.cfg b/src/test/resources/examples/GraphIso/GraphIso.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f4de133b686366e3e6ac5098eb8d2734d459ddd3 --- /dev/null +++ b/src/test/resources/examples/GraphIso/GraphIso.cfg @@ -0,0 +1,2 @@ +INIT Init +NEXT Solve \ No newline at end of file diff --git a/src/test/resources/examples/GraphIso/GraphIso.mch b/src/test/resources/examples/GraphIso/GraphIso.mch new file mode 100644 index 0000000000000000000000000000000000000000..325180a9bfb31f3a9dd9bec034697e4bb0ef1cbb --- /dev/null +++ b/src/test/resources/examples/GraphIso/GraphIso.mch @@ -0,0 +1,24 @@ +MACHINE GraphIso +VARIABLES g1, g2, p, n, solved +INVARIANT + g1 : POW(INTEGER*INTEGER) + & g2 : POW(INTEGER*INTEGER) + & p : POW(INTEGER*INTEGER) + & n : INTEGER + & solved : INTEGER +INITIALISATION + g1, g2, p, n, solved:(n = 9 + & g1 = %i.(i : 1 .. n| i) <+ {1 |-> 3, 2 |-> 3, 3 |-> 6, 4 |-> 6, 5 |-> 6, 8 |-> 9, 9 |-> 8} + & g2 = %i.(i : 1 .. n| i) <+ {2 |-> 5, 3 |-> 5, 4 |-> 5, 6 |-> 4, 7 |-> 4, 1 |-> 9, 9 |-> 1} + & p = %i.(i : 1 .. n| 0) + & solved = 0) +OPERATIONS + Solve_Op = ANY p_n, solved_n + WHERE p_n : POW(INTEGER*INTEGER) & solved_n : INTEGER & solved = 0 + & solved_n = 1 + & p_n : 1 .. n --> 1 .. n + & !i.(i : 1 .. n => #j.(j : 1 .. n & p_n(j) = i)) + & !i.(i : 1 .. n => p_n(g1(i)) = g2(p_n(i))) + & TRUE = TRUE + THEN p, solved := p_n, solved_n END +END diff --git a/src/test/resources/examples/GraphIso/GraphIso.tla b/src/test/resources/examples/GraphIso/GraphIso.tla new file mode 100644 index 0000000000000000000000000000000000000000..f09eaeecab33af03b66974ab7b6de25db39b91fa --- /dev/null +++ b/src/test/resources/examples/GraphIso/GraphIso.tla @@ -0,0 +1,24 @@ +---- MODULE GraphIso ---- + +EXTENDS Naturals, FiniteSets +VARIABLE g1, g2, p, n, solved +---- +Init == /\ n = 9 + /\ g1 = [[i\in 1..n|->i] EXCEPT ![1]=3,![2]=3,![3]=6,![4]=6,![5]=6,![8]=9,![9]=8] + /\ g2 = [[i\in 1..n|->i] EXCEPT ![2]=5,![3]=5,![4]=5,![6]=4,![7]=4,![1]=9,![9]=1] + /\ p = [i \in 1..n |-> 0] + /\ solved = 0 +Solve == /\ solved = 0 + /\ solved' = 1 + /\ p' \in [1..n -> 1..n] + /\ \A i \in 1..n : (\E j \in 1..n : p'[j]=i) + /\ \A i \in 1..n : (p'[g1[i]] = g2[p'[i]]) + /\ UNCHANGED <<g1,g2,n>> +==== +\* Generated at Wed Jul 21 15:51:20 CEST 2010 +\* /\ \A i \in 1..n : (p'[g1[i]] = g2[p'[i]]) +\* trying to encode graph isomporphism in TLA for graphs with exactly one successor +\* ProB takes 0.06 seconds for first solution; 0.1 second for all 8 solutions +\* TLC starts at 21:28:18 +\* finds permutation <<6, 7, 4, 2, 3, 5, 8, 1, 9>> at 23:34:46 (2h 6mins 28secs) +\* same as first permutation found by ProB in 0.06 seconds \ No newline at end of file diff --git a/src/test/resources/examples/HourClock/HourClock.cfg b/src/test/resources/examples/HourClock/HourClock.cfg new file mode 100644 index 0000000000000000000000000000000000000000..7f032c783b822cd13c760106166328f13ae6e64a --- /dev/null +++ b/src/test/resources/examples/HourClock/HourClock.cfg @@ -0,0 +1,3 @@ +INIT HCini +NEXT HCnxt +INVARIANTS HCini \ No newline at end of file diff --git a/src/test/resources/examples/HourClock/HourClock.mch b/src/test/resources/examples/HourClock/HourClock.mch new file mode 100644 index 0000000000000000000000000000000000000000..b696afa4b38e572cb2bf8066b601ea0dcdf04a51 --- /dev/null +++ b/src/test/resources/examples/HourClock/HourClock.mch @@ -0,0 +1,15 @@ +MACHINE HourClock +DEFINITIONS + IF_THEN_ELSE(P, a, b) == (%t_.(t_ = TRUE & P = TRUE | a )\/%t_.(t_= TRUE & not(P= TRUE) | b ))(TRUE); + HCini == hr : 1 .. 12 +VARIABLES hr +INVARIANT + hr : INTEGER + & HCini +INITIALISATION + hr:(hr : 1 .. 12) +OPERATIONS + HCnxt_Op = ANY hr_n + WHERE hr_n : INTEGER & hr_n = IF_THEN_ELSE(bool(hr /= 12), hr + 1, 1) + THEN hr := hr_n END +END diff --git a/src/test/resources/examples/HourClock/HourClock.tla b/src/test/resources/examples/HourClock/HourClock.tla new file mode 100644 index 0000000000000000000000000000000000000000..253eea2af2ed0ab6fe81e03791c6aa5de01fb17b --- /dev/null +++ b/src/test/resources/examples/HourClock/HourClock.tla @@ -0,0 +1,9 @@ +---------------------- MODULE HourClock ---------------------- +EXTENDS Naturals +VARIABLE hr +HCini == hr \in (1 .. 12) +HCnxt == hr' = IF hr #12 THEN hr+1 ELSE 1 +HC == HCini /\ [] [HCnxt]_hr +-------------------------------------------------------------- +THEOREM HC => []HCini +============================================================== diff --git a/src/test/resources/examples/Jukebox/Jukebox.cfg b/src/test/resources/examples/Jukebox/Jukebox.cfg new file mode 100644 index 0000000000000000000000000000000000000000..edf388f92669546052fc55cd316adfaf814c64e5 --- /dev/null +++ b/src/test/resources/examples/Jukebox/Jukebox.cfg @@ -0,0 +1,5 @@ +INIT Init +NEXT Next +INVARIANT Inv +CONSTANTS +TRACK = {t1,t2,t3} \ No newline at end of file diff --git a/src/test/resources/examples/Jukebox/Jukebox.mch b/src/test/resources/examples/Jukebox/Jukebox.mch new file mode 100644 index 0000000000000000000000000000000000000000..bd120d8fc316e8bce4b0d4cfdf69861c37e6ff09 --- /dev/null +++ b/src/test/resources/examples/Jukebox/Jukebox.mch @@ -0,0 +1,48 @@ +MACHINE Jukebox +SETS + ENUM1 = {t1, t2, t3} +ABSTRACT_CONSTANTS TRACK, limit +PROPERTIES + TRACK = ENUM1 + & limit : INTEGER + & limit : NATURAL & limit > 0 +DEFINITIONS + IF_THEN_ELSE(P, a, b) == (%t_.(t_ = TRUE & P = TRUE | a )\/%t_.(t_= TRUE & not(P= TRUE) | b ))(TRUE); + Inv == credit : NATURAL & credit <= limit & playset <: TRACK; + + minimum(a,b) == IF_THEN_ELSE(bool(a < b), a, b); + + pay(cc) == cc > 0 & credit_n = minimum(credit + cc, limit); + + select(tt) == credit > 0 & (credit_n = credit - 1 or credit_n = credit) & playset_n = playset \/ {tt} +VARIABLES credit, playset +INVARIANT + credit : INTEGER + & playset : POW(ENUM1) + & Inv +INITIALISATION + credit, playset:(credit = 0 & playset = {}) +OPERATIONS + pay_Op(cc) = ANY credit_n, playset_n + WHERE cc : NATURAL & + credit_n : INTEGER & playset_n : POW(ENUM1) & pay(cc) + THEN credit, playset := credit_n, playset_n END; + + select_Op(tt) = ANY credit_n, playset_n + WHERE tt : TRACK & + credit_n : INTEGER & playset_n : POW(ENUM1) & select(tt) + THEN credit, playset := credit_n, playset_n END; + + play_Op = ANY playset_n + WHERE playset_n : POW(ENUM1) & playset /= {} & #tr.(tr : playset & playset_n = playset - {tr}) & TRUE = TRUE + THEN playset := playset_n END; + + removeCredit_Op = ANY credit_n + WHERE credit_n : INTEGER & credit > 0 & credit_n = credit - 1 & TRUE = TRUE + THEN credit := credit_n END; + + dropTrack_Op(tt) = ANY playset_n + WHERE tt : playset & + playset_n : POW(ENUM1) & playset_n = playset - {tt} & TRUE = TRUE + THEN playset := playset_n END +END diff --git a/src/test/resources/examples/Jukebox/Jukebox.tla b/src/test/resources/examples/Jukebox/Jukebox.tla new file mode 100644 index 0000000000000000000000000000000000000000..7e187bfb5e6d8b1e7c635fbcf65e07550fa0f077 --- /dev/null +++ b/src/test/resources/examples/Jukebox/Jukebox.tla @@ -0,0 +1,48 @@ +-------------------------- MODULE Jukebox ----------------------------- +EXTENDS Naturals +CONSTANT TRACK, limit +ASSUME limit \in Nat /\ limit > 0 + +VARIABLE credit, playset +Init == credit = 0 /\ playset = {} +Inv == credit \in Nat /\ credit \leq limit /\ playset \subseteq TRACK +----------------------------------------------------------------------- + +(* A user can purchase some credits to make some selections from the +jukebox. The limit cannot be exceeded. *) + +minimum(a,b) == IF a < b THEN a ELSE b +pay(cc) == cc > 0 /\ credit' = minimum(credit + cc, limit) + + +(* The select action occasionally provides free selections. The +intention is that this should occur occasionally, and randomly. Note that even a free selection can only be made if the credit total is positive. *) + +select(tt) == credit > 0 /\ (credit' = credit - 1 \/ credit' = credit) + /\ playset' = playset \cup {tt} + + +(* Any track that is currently in the set to be played can be output +by this action. *) + +play == playset # {} /\ (\E tr \in playset: playset' = playset\{tr}) /\ UNCHANGED credit + + +(* the penalty action, invoked when the jukebox is mistreated, +either removes a credit if there are any left, or drops a tack from +the playset, if there are any left. If both are possible, then it can +do either of these.*) + +removeCredit == credit > 0 /\ credit' = credit -1 /\ UNCHANGED playset +dropTrack == \E tt \in playset: playset' = playset\{tt} /\ UNCHANGED credit +penalty == removeCredit \/ dropTrack + + +(* Disjunction of all actions *) + +Next == \/ (\E cc \in Nat: pay(cc)) + \/ (\E tt \in TRACK: select(tt)) + \/ play + \/ penalty + +======================================================================= diff --git a/src/test/resources/examples/MySequence/MySequence.tla b/src/test/resources/examples/MySequence/MySequence.tla new file mode 100644 index 0000000000000000000000000000000000000000..e84c3eecf7fee1018e36fce89e1fa1889de6a194 --- /dev/null +++ b/src/test/resources/examples/MySequence/MySequence.tla @@ -0,0 +1,9 @@ +----- MODULE MySequence----- +EXTENDS Sequences +VARIABLE q +Init == q = <<1, 2, 3>> +Next == + /\ q # <<>> + /\ q' = Tail(q) +Spec == Init /\ [][Next]_q +======================= diff --git a/src/test/resources/examples/Queens/Queens.cfg b/src/test/resources/examples/Queens/Queens.cfg new file mode 100644 index 0000000000000000000000000000000000000000..f4de133b686366e3e6ac5098eb8d2734d459ddd3 --- /dev/null +++ b/src/test/resources/examples/Queens/Queens.cfg @@ -0,0 +1,2 @@ +INIT Init +NEXT Solve \ No newline at end of file diff --git a/src/test/resources/examples/Queens/Queens.mch b/src/test/resources/examples/Queens/Queens.mch new file mode 100644 index 0000000000000000000000000000000000000000..fafa8565590097078c66768b2b607e6083eb9293 --- /dev/null +++ b/src/test/resources/examples/Queens/Queens.mch @@ -0,0 +1,19 @@ +MACHINE Queens +VARIABLES q, n, solved +INVARIANT + q : POW(INTEGER*INTEGER) + & n : INTEGER + & solved : INTEGER +INITIALISATION + q, n, solved:(q = %i.(i : 1 .. 2| 0) + & n = 7 + & solved = 0) +OPERATIONS + Solve_Op = ANY q_n, n_n, solved_n + WHERE q_n : POW(INTEGER*INTEGER) & n_n : INTEGER & solved_n : INTEGER & solved = 0 + & q_n : 1 .. n --> 1 .. n + & !i.(i : 1 .. n => !j.(j : 2 .. n => (i < j => q_n(i) /= q_n(j) & q_n(i) + (i - j) /= q_n(j) & q_n(i) - i + j /= q_n(j)))) + & solved_n = 1 + & n_n = n + THEN q, n, solved := q_n, n_n, solved_n END +END diff --git a/src/test/resources/examples/Queens/Queens.tla b/src/test/resources/examples/Queens/Queens.tla new file mode 100644 index 0000000000000000000000000000000000000000..5edd6010acb4c53d4e775760c360b428f42c5900 --- /dev/null +++ b/src/test/resources/examples/Queens/Queens.tla @@ -0,0 +1,22 @@ +---- MODULE Queens ---- + +EXTENDS Naturals, FiniteSets + +VARIABLE q, n, solved +---- + +Init == /\ q=[i \in 1..2 |-> 0] + /\ n=7 + /\ solved = 0 + +Solve == /\ solved=0 + /\ q' \in [1..n -> 1..n] + /\ \A i \in 1..n : (\A j \in 2..n : i<j => q'[i] # q'[j] /\ q'[i]+i-j # q'[j] /\ q'[i]-i+j # q'[j]) + /\ solved'=1 + /\ n'=n +Spec == Init /\ [] [Solve]_<<n,q>> +======= +\* Generated at Tue Jun 22 21:06:17 CEST 2010 +\* Takes 2 seconds for n-6, 12 seconds to solve for n=7 and 4 minutes 9 seconds for n=8, 1h45min47sec for n=9 +\* ProB takes 0.01 seconds for n=8, both on MacBook Pro 3.06 GHz +\* /\ \A i \in 1..n : (\E j \in 1..n : q'[j]=i) \ No newline at end of file diff --git a/src/test/resources/examples/Queens/Queens2.cfg b/src/test/resources/examples/Queens/Queens2.cfg new file mode 100644 index 0000000000000000000000000000000000000000..ac11778eb3b8b6b8991288bc9e419219926ae0c8 --- /dev/null +++ b/src/test/resources/examples/Queens/Queens2.cfg @@ -0,0 +1,5 @@ +INIT Init +NEXT PlaceQueen +INVARIANT TypeInvariant Invariant +CONSTANTS +N =5 \ No newline at end of file diff --git a/src/test/resources/examples/Queens/Queens2.mch b/src/test/resources/examples/Queens/Queens2.mch new file mode 100644 index 0000000000000000000000000000000000000000..8809b151a45874482857aedfca558676dc2a65c9 --- /dev/null +++ b/src/test/resources/examples/Queens/Queens2.mch @@ -0,0 +1,44 @@ +MACHINE Queens2 +ABSTRACT_CONSTANTS N +PROPERTIES + N = 5 + & N : NATURAL - {0} +DEFINITIONS + Attacks(queens,i,j) == queens(i) = queens(j) + or queens(i) - queens(j) = i - j + or queens(j) - queens(i) = i - j; + + IsSolution(queens) == !i.(i : 1 .. size(queens) - 1 => !j.(j : i + 1 .. size(queens) => not(Attacks(queens, i, j)))); + + Solutions == {queens|queens : 1 .. N --> 1 .. N & IsSolution(queens)}; + + TypeInvariant == todo : POW(seq(1 .. N)) & !s.(s : todo => size(s) < N) + & (sols : POW(seq(1 .. N)) & !s.(s : sols => size(s) = N)); + + Invariant == sols <: Solutions + & (todo = {} => Solutions <: sols); + + nxtQ == size(queens) + 1; + cols == {c|c : 1 .. N & not(#i.(i : 1 .. size(queens) & Attacks(queens <- c, i, nxtQ)))}; + exts == {t_|#c.(c : cols & t_ = queens <- c)}; + +VARIABLES todo, sols +INVARIANT + todo : POW(POW(INTEGER*INTEGER)) + & sols : POW(POW(INTEGER*INTEGER)) + & TypeInvariant + & Invariant +INITIALISATION + todo, sols:(todo = {[]} + & sols = {}) +OPERATIONS + PlaceQueen_Op(queens) = ANY todo_n, sols_n + WHERE queens : todo & + todo_n : POW(POW(INTEGER*INTEGER)) & sols_n : POW(POW(INTEGER*INTEGER)) & (nxtQ = N + => todo_n = todo - {queens} + & sols_n = sols \/ exts) + & (not(nxtQ = N) + => todo_n = todo - {queens} \/ exts + & sols_n = sols) + THEN todo, sols := todo_n, sols_n END +END diff --git a/src/test/resources/examples/Queens/Queens2.tla b/src/test/resources/examples/Queens/Queens2.tla new file mode 100644 index 0000000000000000000000000000000000000000..0c466eaf9a2ff44745b1910d733404371e3cb178 --- /dev/null +++ b/src/test/resources/examples/Queens/Queens2.tla @@ -0,0 +1,85 @@ +------------------------------- MODULE Queens2 ------------------------------- +EXTENDS Naturals, Sequences +(***************************************************************************) +(* Formulation of the N-queens problem and an iterative algorithm to solve *) +(* the problem in TLA+. Since there must be exactly one queen in every row *) +(* we represent placements of queens as functions of the form *) +(* queens \in [ 1..N -> 1..N ] *) +(* where queens[i] gives the column of the queen in row i. Note that such *) +(* a function is just a sequence of length N. *) +(* We will also consider partial solutions, also represented as sequences *) +(* of length \leq N. *) +(***************************************************************************) + +CONSTANT N \** number of queens and size of the board +ASSUME N \in Nat \ {0} + +(* The following predicate determines if queens i and j attack each other + in a placement of queens (represented by a sequence as above). *) +Attacks(queens,i,j) == + \/ queens[i] = queens[j] \** same column + \/ queens[i] - queens[j] = i - j \** first diagonal + \/ queens[j] - queens[i] = i - j \** second diagonal + +(* A placement represents a (partial) solution if no two different queens + attack each other in it. *) +IsSolution(queens) == + \A i \in 1 .. Len(queens)-1 : \A j \in i+1 .. Len(queens) : + ~ Attacks(queens,i,j) + +(* Compute the set of solutions of the N-queens problem. *) +Solutions == { queens \in [1..N -> 1..N] : IsSolution(queens) } + +(***************************************************************************) +(* We now describe an algorithm that iteratively computes the set of *) +(* solutions of the N-queens problem by successively placing queens. *) +(* The current state of the algorithm is given by two variables: *) +(* - todo contains a set of partial solutions, *) +(* - sols contains the set of full solutions found so far. *) +(* At every step, the algorithm picks some partial solution and computes *) +(* all possible extensions by the next queen. If N queens have been placed *) +(* these extensions are in fact full solutions, otherwise they are added *) +(* to the set todo. *) +(***************************************************************************) + +VARIABLES todo, sols + +Init == /\ todo = { << >> } \** << >> is a partial (but not full) solution + /\ sols = {} \** no full solution found so far + +PlaceQueen == \E queens \in todo : + \** extend some partial solution by placing the next queen + LET nxtQ == Len(queens) + 1 \** number of queen to place + cols == \** set of columns on which queen can be placed without any + \** conflict with some queen already placed + { c \in 1..N : ~ \E i \in 1 .. Len(queens) : + Attacks( Append(queens, c), i, nxtQ ) } + exts == { Append(queens, c) : c \in cols } \** possible extensions + IN IF nxtQ = N \** completed solution + THEN /\ todo' = todo \ {queens} + /\ sols' = sols \union exts + ELSE /\ todo' = (todo \ {queens}) \union exts + /\ sols' = sols + +vars == <<todo,sols>> +Spec == Init /\ [][PlaceQueen]_vars /\ WF_vars(PlaceQueen) + +TypeInvariant == + /\ todo \in SUBSET Seq(1 .. N) /\ \A s \in todo : Len(s) < N + /\ sols \in SUBSET Seq(1 .. N) /\ \A s \in sols : Len(s) = N + +(* The set of sols contains only solutions, and contains all solutions + when todo is empty. *) +Invariant == + /\ sols \subseteq Solutions + /\ todo = {} => Solutions \subseteq sols + +Termination == <>(todo = {}) + +(* Assert that no solutions are ever computed so that TLC displays one *) +NoSolutions == sols = {} + +============================================================================= +\* Modification History +\* Last modified Sat Dec 11 09:58:48 CET 2010 by merz +\* Created Sat Dec 11 08:50:24 CET 2010 by merz diff --git a/src/test/resources/examples/RecursiveFunction/RecursiveFunction.mch b/src/test/resources/examples/RecursiveFunction/RecursiveFunction.mch new file mode 100644 index 0000000000000000000000000000000000000000..4f24de357d3586b3298c7c9bcbb7e291ecac7c53 --- /dev/null +++ b/src/test/resources/examples/RecursiveFunction/RecursiveFunction.mch @@ -0,0 +1,11 @@ +MACHINE RecursiveFunction +ABSTRACT_CONSTANTS k, k2, k3, fact +PROPERTIES + k : INTEGER + & k2 : INTEGER + & k3 : INTEGER + & k = fact(0) & k2 = fact(3) & k3 = fact(4) + & fact = %n.(n : NATURAL & n = 0 | 1) \/ %n.(n : NATURAL & not(n = 0) | n * fact(n - 1)) +DEFINITIONS + IF_THEN_ELSE(P, a, b) == (%t_.(t_ = TRUE & P = TRUE | a )\/%t_.(t_= TRUE & not(P= TRUE) | b ))(TRUE) +END diff --git a/src/test/resources/examples/RecursiveFunction/RecursiveFunction.tla b/src/test/resources/examples/RecursiveFunction/RecursiveFunction.tla new file mode 100644 index 0000000000000000000000000000000000000000..958c71a1be9f6f155df4d1c517a4cc99335e1145 --- /dev/null +++ b/src/test/resources/examples/RecursiveFunction/RecursiveFunction.tla @@ -0,0 +1,7 @@ +----- MODULE RecursiveFunction ----- +EXTENDS Naturals +CONSTANTS k, k2, k3 +fact[n \in Nat] == IF n = 0 THEN 1 ELSE n * fact[n-1] +ASSUME k = fact[0] /\ k2 = fact[3] /\ k3 = fact[4] +======================= + diff --git a/src/test/resources/examples/Relations.tla b/src/test/resources/examples/Relations.tla new file mode 100644 index 0000000000000000000000000000000000000000..a9a1bc1e0f5c3c8fc88150450a8c35d948f19437 --- /dev/null +++ b/src/test/resources/examples/Relations.tla @@ -0,0 +1,66 @@ +----------------------------- MODULE Relations ----------------------------- + +EXTENDS TLC, Sequences, Naturals, FiniteSets, Integers + +domain(r) == {x[1]: x \in r} +range(r) == {x[2]: x \in r} +id(S) == {<<x,x>>: x \in S} +set_of_relations(x,y) == SUBSET (x \times y) +domain_restriction(S, r) == {x \in r: x[1] \in S} +domain_substraction(S, r) == {x \in r: x[1] \notin S} +range_restriction(S, r) == {x \in r: x[2] \in S} +range_substraction(S, r) == {x \in r: x[2] \notin S} + +rel_inverse(r) == {<<x[2],x[1]>>: x\in r} +relational_image(r, S) =={y[2] :y \in {x \in r: x[1] \in S}} +relational_overriding(r, r2) == {x \in r: x[1] \notin domain(r2)} \cup r2 + + +direct_product(r1, r2) == {<<x, u>> \in (domain(r1)\cup domain(r2)) \times (range(r1) \times range(r2)): + u[1] \in relational_image(r1, {x}) /\ u[2] \in relational_image(r2,{x})} +direct_product2(r1, r2) == {u \in (domain(r1)\cup domain(r2)) \times (range(r1) \times range(r2)): + <<u[1],u[2][1]>> \in r1 /\ <<u[1],u[2][2]>> \in r2} + +relational_composition(r1, r2) == {<<u[1][1],u[2][2]>> : u \in + {x \in range_restriction(domain(r2),r1) \times domain_restriction(range(r1),r2): x[1][2] = x[2][1]} + } + +prj1(E, F) == {u \in E \times F \times E: u[1] = u[3]} +prj2(E, F) == {u \in E \times F \times F: u[2] = u[3]} + + +RECURSIVE iterate(_,_) +iterate(r, n) == CASE n = 0 -> id(domain(r)\cup range(r)) + [] n = 1 -> r + [] OTHER -> iterate(relational_composition(r,r), n-1) + +RECURSIVE closure1(_) +closure1(R) == IF relational_composition(R,R) \R # {} + THEN R \cup closure1(relational_composition(R,R)) + ELSE R + +closure(R) == closure1( R \cup {<<x[1],x[1]>>: x \in R} \cup {<<x[2],x[2]>>: x \in R}) + +relational_call(r, x) == (CHOOSE y \in r: y[1] = x)[2] + + +is_partial_func(f) == \A x \in domain(f): Cardinality(relational_image(f, {x})) <= 1 +is_partial_func2(f, S, S2) == /\ \A x \in f: x[1] \in S /\ x[2] \in S2 /\ relational_image(f, {x[1]}) = {x[2]} + +partial_func(S, S2) == {x \in (SUBSET (S \times S2)): is_partial_func(x)} + +is_func(f) == \A x \in domain(f): Cardinality(relational_image(f, {x})) < 2 +total_func(S, S2) == {x \in (SUBSET (S \times S2)): is_func(x) /\ domain(x)= S} + +is_total_func(f, S, S2) == domain(f) = S /\ \A x \in f: x[1] \in S /\ x[2] \in S2 /\ relational_image(f, {x[1]}) = {x[2]} + +is_injectiv_func(f) == \A x \in range(f): Cardinality(relational_image(rel_inverse(f), {x})) <= 1 +total_injection(S, S2) == {x \in (SUBSET (S \times S2)): is_func(x) /\ domain(x)= S /\ is_injectiv_func(x) } +partial_injection(S, S2) == {x \in (SUBSET (S \times S2)): is_func(x) /\ is_injectiv_func(x) } + +total_surjection(S, S2) == {x \in (SUBSET (S \times S2)): is_func(x)/\ domain(x)= S /\ S2 = range(x)} +partial_surjection(S, S2) == {x \in (SUBSET (S \times S2)): is_func(x)/\ S2 = range(x)} + +total_bijection(S, S2) == {x \in (SUBSET (S \times S2)): is_func(x) /\ domain(x) = S /\ is_injectiv_func(x) /\ S2 = range(x)} + +============================================================================= \ No newline at end of file diff --git a/src/test/resources/examples/Scheduler/Scheduler.cfg b/src/test/resources/examples/Scheduler/Scheduler.cfg new file mode 100644 index 0000000000000000000000000000000000000000..5d1dbd39ff05ef5075420c2f426df29f659b6dfe --- /dev/null +++ b/src/test/resources/examples/Scheduler/Scheduler.cfg @@ -0,0 +1,5 @@ +INIT Init +NEXT Next +INVARIANT Inv +CONSTANTS +PID = {p1,p2,p3,p4,p5,p6,p7} diff --git a/src/test/resources/examples/Scheduler/Scheduler.mch b/src/test/resources/examples/Scheduler/Scheduler.mch new file mode 100644 index 0000000000000000000000000000000000000000..7bb32cbd8c3997cdef1a7c61990d0442b5e5ef42 --- /dev/null +++ b/src/test/resources/examples/Scheduler/Scheduler.mch @@ -0,0 +1,48 @@ +MACHINE Scheduler +SETS + ENUM1 = {p1, p2, p3, p4, p5, p6, p7} +ABSTRACT_CONSTANTS PID +PROPERTIES + PID = ENUM1 +DEFINITIONS + Inv == active : POW(PID) & ready : POW(PID) & waiting : POW(PID) & active <: PID & ready <: PID & waiting <: PID & ready /\ waiting = {} & card(active) <= 1 & (active = {} => ready = {}); + + new(pp) == pp /: active & pp /: ready \/ waiting & waiting_n = waiting \/ {pp} & TRUE = TRUE; + + del(pp) == pp : waiting & waiting_n = waiting - {pp} & TRUE = TRUE; + + ready_(rr) == rr : waiting & waiting_n = waiting - {rr} & ((active = {} + => active_n = {rr} & ready_n = ready) + & (not(active = {}) + => ready_n = ready \/ {rr} & active_n = active)) +VARIABLES active, ready, waiting +INVARIANT + active : POW(ENUM1) + & ready : POW(ENUM1) + & waiting : POW(ENUM1) + & Inv +INITIALISATION + active, ready, waiting:(active = {} & ready = {} & waiting = {}) +OPERATIONS + new_Op(pp) = ANY waiting_n + WHERE pp : PID & + waiting_n : POW(ENUM1) & new(pp) + THEN waiting := waiting_n END; + + del_Op(pp) = ANY waiting_n + WHERE pp : PID & + waiting_n : POW(ENUM1) & del(pp) + THEN waiting := waiting_n END; + + ready__Op(rr) = ANY active_n, ready_n, waiting_n + WHERE rr : PID & + active_n : POW(ENUM1) & ready_n : POW(ENUM1) & waiting_n : POW(ENUM1) & ready_(rr) + THEN active, ready, waiting := active_n, ready_n, waiting_n END; + + swap_Op = ANY active_n, ready_n, waiting_n + WHERE active_n : POW(ENUM1) & ready_n : POW(ENUM1) & waiting_n : POW(ENUM1) & active /= {} & waiting_n = waiting \/ active & ((ready = {} + => active_n = {} & ready_n = ready) + & (not(ready = {}) + => #pp.(pp : ready & (active_n = {pp} & ready_n = ready - {pp})))) + THEN active, ready, waiting := active_n, ready_n, waiting_n END +END diff --git a/src/test/resources/examples/Scheduler/Scheduler.tla b/src/test/resources/examples/Scheduler/Scheduler.tla new file mode 100644 index 0000000000000000000000000000000000000000..f93545ac3ffba7e5f97646eb10d33032f4d6b4bb --- /dev/null +++ b/src/test/resources/examples/Scheduler/Scheduler.tla @@ -0,0 +1,29 @@ +------------------------------ MODULE Scheduler ------------------------------- +EXTENDS Naturals, FiniteSets +CONSTANTS PID +VARIABLES active, ready, waiting +Inv == active \in SUBSET(PID) /\ ready \in SUBSET(PID) /\ waiting \in SUBSET(PID) + /\ active \subseteq PID /\ ready \subseteq PID /\ waiting \subseteq PID + /\ (ready \cap waiting) = {} /\ Cardinality(active) \leq 1 + /\ (active = {} => ready = {}) +Init == active = {} /\ ready = {} /\ waiting = {} +------------------------------------------------------------------------------ +new(pp) == pp \notin active /\ pp \notin (ready \cup waiting) /\ waiting' = waiting \cup {pp} /\ UNCHANGED <<ready,active>> + +del(pp) == pp \in waiting /\ waiting' = waiting\{pp} /\ UNCHANGED <<ready,active>> + +ready_(rr) == rr \in waiting /\ waiting' = waiting\{rr} /\ + IF active = {} THEN active' = {rr} /\ UNCHANGED ready + ELSE ready' = ready \cup {rr} /\ UNCHANGED active + +swap == active # {} /\ waiting' = waiting \cup active + /\ IF ready = {} THEN active' = {} /\ UNCHANGED ready + ELSE \E pp \in ready: active' ={pp} /\ ready' = ready\{pp} + + + +Next == \/ (\E pp \in PID : new(pp)) + \/ (\E pp \in PID : del(pp)) + \/ (\E rr \in PID : ready_(rr)) + \/ swap +============================================================================= diff --git a/src/test/resources/examples/SecCtx.cfg b/src/test/resources/examples/SecCtx.cfg new file mode 100644 index 0000000000000000000000000000000000000000..d9bdb0b9b1707d86c7a668bc84dfa3d5759b8f0e --- /dev/null +++ b/src/test/resources/examples/SecCtx.cfg @@ -0,0 +1,8 @@ +INIT SecCtx_Init +NEXT SecCtx_Next +INVARIANT Inv +CONSTANTS +usr_lst_cnt = 2 +REG_USR = {0,1} +NAT = {0,1,2,3} +INT = {0,1,2,3} \ No newline at end of file diff --git a/src/test/resources/examples/SecCtx.tla b/src/test/resources/examples/SecCtx.tla new file mode 100644 index 0000000000000000000000000000000000000000..a31684ddcf69f96b1eaa4388fa8e5b4e8ae223cf --- /dev/null +++ b/src/test/resources/examples/SecCtx.tla @@ -0,0 +1,475 @@ +------------------------------- MODULE SecCtx ------------------------------- +EXTENDS Naturals, Integers, Relations +CONSTANTS usr_lst_cnt, REG_USR, INT, NAT +ASSUME usr_lst_cnt \in Nat\{0} /\ REG_USR = 0..(usr_lst_cnt-1) + +min(S) == CHOOSE x \in S : \A i \in S: x \leq i + +VARIABLES + flg_comm_active, (* communicating *) + flg_got_cli_nonce, (* Client Nonce received *) + flg_sent_serv_nonce, (* Server Nonce sent *) + flg_sent_cert, (* Server certificate sent *) + flg_got_premaster, (* premaster secret received from client *) + flg_set_cmn_key, (* session common key set *) + flg_done_hs_verify, (* Data for verifying a Handshake message checked *) + flg_sent_hs_verify, (* Data for verifying a Handshake message sent *) + flg_cipher_on, (* Applied encryption to communication data *) + + flg_allow_user_auth, (* the propriety user authenticating user *) + flg_done_user_auth, (* user authenticated flag *) + flg_allow_user_data, (* the propriety sending and receiving user data flag *) + + flg_tx_msg_encoded, (* encryption of sending data flag *) + flg_tx_add_mac, (* Given MAC of sending data flag *) + flg_allow_send_data, (* Permission of sending TCP data flag*) + + flg_rx_msg_decoded, (* encryption of receiviing data flag *) + flg_rx_chk_mac, (* Given MAC of receiviing data flag *) + flg_allow_recv_data, (* Permission of giving application software received data flag*) + + auth_fail_cnt, (* consecutive unsuccessful authentication attempts for each user *) + recent_auth_tim (* previous time of authentication attempts for each user for each user *) + +Inv == (* Definition of type *) + (* -------------------------------------------------------- *) + flg_comm_active \in BOOLEAN /\ + flg_got_cli_nonce \in BOOLEAN /\ + flg_sent_serv_nonce \in BOOLEAN /\ + flg_sent_cert \in BOOLEAN /\ + flg_got_premaster \in BOOLEAN /\ + flg_set_cmn_key \in BOOLEAN /\ + flg_done_hs_verify \in BOOLEAN /\ + flg_sent_hs_verify \in BOOLEAN /\ + flg_cipher_on \in BOOLEAN /\ + + flg_allow_user_auth \in BOOLEAN /\ + flg_done_user_auth \in BOOLEAN /\ + flg_allow_user_data \in BOOLEAN /\ + + flg_tx_msg_encoded \in BOOLEAN /\ + flg_tx_add_mac \in BOOLEAN /\ + flg_allow_send_data \in BOOLEAN /\ + + flg_rx_msg_decoded \in BOOLEAN /\ + flg_rx_chk_mac \in BOOLEAN /\ + flg_allow_recv_data \in BOOLEAN /\ + + is_total_func(auth_fail_cnt, REG_USR, NAT) /\ (* auth_fail_cnt : REG_USR +-> NAT & dom(auth_fail_cnt)=REG_USR &*) + is_total_func(recent_auth_tim, REG_USR, INT) /\ (*recent_auth_tim : REG_USR +-> INT & dom(recent_auth_tim)=REG_USR &*) + + (flg_sent_serv_nonce=TRUE => flg_got_cli_nonce=TRUE) /\ + (flg_sent_cert=TRUE => flg_sent_serv_nonce=TRUE) /\ + (flg_got_premaster=TRUE => flg_sent_cert=TRUE) /\ + (flg_sent_hs_verify=TRUE => flg_got_premaster=TRUE) /\ + (flg_allow_user_auth = TRUE + => (flg_sent_cert = TRUE) /\ (flg_got_premaster=TRUE) /\ (flg_sent_hs_verify=TRUE)) + + /\ (flg_allow_user_data = TRUE + => (flg_sent_cert = TRUE) /\ (flg_got_premaster=TRUE) /\ (flg_sent_hs_verify=TRUE)) + + /\ + (* Encryption of user data:Prevent eavesdropping *) + ( flg_cipher_on=TRUE => flg_set_cmn_key=TRUE) /\ + ( flg_allow_user_auth=TRUE => flg_cipher_on=TRUE) /\ + ( flg_done_user_auth=TRUE => flg_allow_user_auth=TRUE) /\ + ( flg_allow_send_data=TRUE => (flg_allow_user_data=TRUE)/\(flg_tx_msg_encoded=TRUE) ) /\ + ( flg_allow_recv_data=TRUE => (flg_allow_user_data=TRUE)/\(flg_rx_msg_decoded=TRUE) ) /\ + + + (* Make the unique common key for every session:Prevent replying *) + ( flg_allow_user_auth=TRUE => flg_done_hs_verify=TRUE ) /\ + ( flg_allow_user_auth=TRUE => flg_sent_hs_verify=TRUE ) /\ + ( flg_cipher_on=TRUE => flg_got_cli_nonce=TRUE ) /\ + ( flg_cipher_on=TRUE => flg_sent_serv_nonce=TRUE ) /\ + ( flg_comm_active=FALSE => flg_set_cmn_key=FALSE) /\ + + (* Make hash:Prevent Prevent falsifying(contain adding messages, + deleting messages and replacing an order of a message ) and replying *) + ( flg_allow_send_data=TRUE => (flg_allow_user_data=TRUE)/\(flg_tx_add_mac=TRUE) ) /\ + ( flg_allow_recv_data=TRUE => (flg_allow_user_data=TRUE)/\(flg_rx_chk_mac=TRUE) ) /\ + + (* Authenticate User:Prevent masquerading as an user *) + ( flg_allow_user_auth = TRUE => flg_cipher_on = TRUE ) /\ + ( flg_allow_user_data = TRUE => flg_done_user_auth = TRUE ) + + +SecCtx_Init == + flg_comm_active = FALSE /\ + flg_got_cli_nonce = FALSE /\ + flg_sent_serv_nonce = FALSE /\ + flg_sent_cert = FALSE /\ + flg_got_premaster = FALSE /\ + flg_set_cmn_key = FALSE /\ + flg_done_hs_verify = FALSE /\ + flg_sent_hs_verify = FALSE /\ + flg_cipher_on = FALSE /\ + flg_allow_user_auth = FALSE /\ + flg_done_user_auth = FALSE /\ + flg_allow_user_data = FALSE /\ + + flg_tx_msg_encoded = FALSE /\ + flg_tx_add_mac = FALSE /\ + flg_allow_send_data = FALSE /\ + + flg_rx_msg_decoded = FALSE /\ + flg_rx_chk_mac = FALSE /\ + flg_allow_recv_data = FALSE /\ + + auth_fail_cnt = REG_USR \times {0} /\ + recent_auth_tim = (REG_USR \times {-1}) + + + + (* Set flag operations *) +SetFlgCommActive == + /\ flg_comm_active = FALSE + /\ flg_comm_active' = TRUE + /\ UNCHANGED << flg_got_cli_nonce,flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key, flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth, flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded, flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim >> + +SetFlgGotCliNonce == + /\ flg_got_cli_nonce' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + +SetFlgSentServNonce == + /\ flg_got_cli_nonce = TRUE + /\ flg_sent_serv_nonce' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + +SetFlgSentCert == + /\ flg_sent_serv_nonce = TRUE + /\ flg_sent_cert' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + +SetFlgGotPremaster == + /\ flg_sent_cert = TRUE + /\ flg_got_premaster' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetFlgCmnKey == + /\ (flg_comm_active = TRUE) + /\ (flg_got_premaster = TRUE) + /\ (flg_got_cli_nonce = TRUE) + /\ (flg_sent_serv_nonce = TRUE) + /\ flg_set_cmn_key' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetFlgCipherOn == + /\ (flg_got_premaster = TRUE) + /\ (flg_got_cli_nonce = TRUE) + /\ (flg_sent_serv_nonce = TRUE) + /\ (flg_set_cmn_key = TRUE) + /\ flg_cipher_on' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetFlgDoneHsVerify == + /\ flg_done_hs_verify' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + + +SetFlgSentHsVerify == + /\ flg_got_premaster = TRUE + /\ flg_sent_hs_verify' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + + +SetFlgAllowUserAuth == + /\ (flg_cipher_on = TRUE) + /\ (flg_done_hs_verify = TRUE) + /\ (flg_sent_hs_verify = TRUE) + /\ flg_allow_user_auth' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetFlgDoneUserAuth == + /\ flg_allow_user_auth = TRUE + /\ flg_done_user_auth' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetSuccessUserAuth(usr, tim) == + /\ usr \in INT /\ usr \in REG_USR /\ tim \in INT + /\ flg_allow_user_auth = TRUE + + /\ flg_done_user_auth' = TRUE + /\ auth_fail_cnt'= relational_overriding(auth_fail_cnt, {<<usr,0>>}) + /\ recent_auth_tim' = relational_overriding(recent_auth_tim, {<<usr, tim>>}) + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data>> + +SetFailUserAuth(usr, tim) == + /\ usr \in INT /\ usr \in REG_USR /\ tim \in INT + /\ flg_done_user_auth' = FALSE + /\ flg_allow_user_data' = FALSE + /\ flg_allow_send_data' = FALSE + /\ flg_allow_recv_data' = FALSE + /\ auth_fail_cnt' = relational_overriding(auth_fail_cnt, {<<usr,min({relational_call(auth_fail_cnt,usr)+1, 3})>>}) + /\ recent_auth_tim' = relational_overriding(recent_auth_tim, {<<usr, tim>>}) + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth, flg_tx_msg_encoded,flg_tx_add_mac,flg_rx_msg_decoded,flg_rx_chk_mac>> + + SetFlgAllowUserData == + /\ (flg_sent_cert = TRUE) + /\ (flg_got_premaster=TRUE) + /\ (flg_sent_hs_verify = TRUE) + /\ (flg_cipher_on = TRUE) + /\ (flg_done_user_auth = TRUE) + /\ flg_allow_user_data' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + +SetFlgTxMsgEncoded == + /\ flg_tx_msg_encoded' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetFlgTxAddMac == + /\ flg_tx_add_mac' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetFlgAllowSendData == + /\ (flg_allow_user_data=TRUE) + /\ (flg_tx_msg_encoded = TRUE) + /\ (flg_tx_add_mac = TRUE) + /\ flg_allow_send_data' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetFlgRxMsgDecoded == + /\ flg_rx_msg_decoded' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetFlgRxChkMac == + /\ flg_rx_chk_mac' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + + +SetFlgAllowRecvData == + /\ flg_cipher_on = TRUE + /\ (flg_allow_user_data = TRUE) + /\ (flg_rx_msg_decoded = TRUE) + /\ (flg_rx_chk_mac = TRUE) + /\ flg_allow_recv_data' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,auth_fail_cnt,recent_auth_tim>> + + (* Complete Handshake *) +SetFlgsHndshkCompleteSts == + flg_comm_active' = TRUE /\ + flg_got_cli_nonce' = TRUE /\ + flg_sent_serv_nonce' = TRUE /\ + flg_sent_cert' = TRUE /\ + flg_got_premaster' = TRUE /\ + flg_set_cmn_key' = TRUE /\ + flg_done_hs_verify' = TRUE /\ + flg_sent_hs_verify' = TRUE /\ + flg_cipher_on' = TRUE /\ + flg_allow_user_auth' = TRUE + /\ UNCHANGED <<flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + (* Reset Handshake Status *) +ResetFlgsHndshkCompleteSts == + /\ flg_allow_user_data = FALSE + + /\ flg_comm_active' = FALSE /\ + flg_got_cli_nonce' = FALSE /\ + flg_sent_serv_nonce' = FALSE /\ + flg_sent_cert' = FALSE /\ + flg_got_premaster' = FALSE /\ + flg_set_cmn_key' = FALSE /\ + flg_done_hs_verify' = FALSE /\ + flg_sent_hs_verify' = FALSE /\ + flg_cipher_on' = FALSE /\ + flg_allow_user_auth' = FALSE /\ + flg_done_user_auth' =FALSE + /\ UNCHANGED <<flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + (* Complete user authentication *) +SetFlgsAuthCompleteSts == + /\ flg_allow_user_auth = TRUE + /\ + flg_done_user_auth' = TRUE /\ + flg_allow_user_data' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + (* Reset user authentication status *) +ResetFlgsAuthCompleteSts == + /\ + flg_done_user_auth' = FALSE /\ + flg_allow_user_data' = FALSE /\ + + flg_allow_send_data' = FALSE /\ + flg_allow_recv_data' = FALSE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth, flg_tx_msg_encoded,flg_tx_add_mac,flg_rx_msg_decoded,flg_rx_chk_mac,auth_fail_cnt,recent_auth_tim>> + + + (* Complete https_acp successfully *) +SetFlgsAcpCompleteSts == + /\ + flg_comm_active' = TRUE /\ + flg_got_cli_nonce' = TRUE /\ + flg_sent_serv_nonce' = TRUE /\ + flg_sent_cert' = TRUE /\ + flg_got_premaster' = TRUE /\ + flg_set_cmn_key' = TRUE /\ + flg_done_hs_verify' = TRUE /\ + flg_sent_hs_verify' = TRUE /\ + flg_cipher_on' = TRUE /\ + flg_allow_user_auth' = TRUE /\ + flg_done_user_auth' = TRUE /\ + flg_allow_user_data' = TRUE + /\ UNCHANGED <<flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + + (* Reset https_acp status *) +ResetFlgsAcpCompleteSts == + /\ + flg_comm_active' = FALSE /\ + flg_got_cli_nonce' = FALSE /\ + flg_sent_serv_nonce' = FALSE /\ + flg_sent_cert' = FALSE /\ + flg_got_premaster' = FALSE /\ + flg_set_cmn_key' = FALSE /\ + flg_done_hs_verify' = FALSE /\ + flg_sent_hs_verify' = FALSE /\ + flg_cipher_on' = FALSE /\ + flg_allow_user_auth' = FALSE /\ + flg_done_user_auth' = FALSE /\ + flg_allow_user_data' = FALSE /\ + + flg_allow_send_data' = FALSE /\ + flg_allow_recv_data' = FALSE + /\ UNCHANGED <<flg_tx_msg_encoded,flg_tx_add_mac,flg_rx_msg_decoded,flg_rx_chk_mac,auth_fail_cnt,recent_auth_tim>> + +(* Set status of user data receiving *) +SetFlgRx == + /\ flg_allow_user_data = TRUE /\ + flg_allow_recv_data '= TRUE /\ + flg_rx_msg_decoded' = TRUE /\ + flg_rx_chk_mac' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,auth_fail_cnt,recent_auth_tim>> + + + +ResetFlgRx == + /\ + flg_allow_recv_data' = FALSE /\ + flg_rx_msg_decoded' = FALSE /\ + flg_rx_chk_mac' = FALSE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,auth_fail_cnt,recent_auth_tim>> + + + (* Set status of user data transmitting *) +SetFlgTx == + /\ flg_allow_user_data = TRUE /\ + flg_allow_send_data' = TRUE /\ + flg_tx_msg_encoded' = TRUE /\ + flg_tx_add_mac' = TRUE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + +ResetFlgTx == + /\ + flg_allow_send_data' = FALSE /\ + flg_tx_msg_encoded' = FALSE /\ + flg_tx_add_mac' = FALSE + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + +SetAuthInf(usr, tim, cnt) == + /\ usr \in INT /\ usr \in REG_USR /\ tim \in INT /\ cnt \in NAT + /\ + auth_fail_cnt'= relational_overriding(auth_fail_cnt, {<<usr,cnt>>}) /\ + recent_auth_tim' = relational_overriding(recent_auth_tim, {<<usr, tim>>}) + /\ UNCHANGED <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data>> + + +(* set https_acp complete status and reset the count of unsuccessful authentication attemps *) +SetAuthSuccessSts(usr, cnt, tim) == + /\ usr \in INT /\ usr \in REG_USR /\ cnt \in NAT /\ tim \in INT + /\ + flg_comm_active' = TRUE /\ + flg_got_cli_nonce' = TRUE /\ + flg_sent_serv_nonce' = TRUE /\ + flg_sent_cert' = TRUE /\ + flg_got_premaster' = TRUE /\ + flg_set_cmn_key' = TRUE /\ + flg_done_hs_verify' = TRUE /\ + flg_sent_hs_verify' = TRUE /\ + flg_cipher_on' = TRUE /\ + flg_allow_user_auth' = TRUE /\ + flg_done_user_auth' = TRUE /\ + flg_allow_user_data' = TRUE /\ + + auth_fail_cnt'= relational_overriding(auth_fail_cnt, {<<usr,cnt>>}) /\ + recent_auth_tim' = relational_overriding(recent_auth_tim, {<<usr, tim>>}) + /\ UNCHANGED <<flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data>> + + (* Reset https_acp status and count up unsuccessful authentication attemps *) +SetAuthFailSts(usr, cnt, tim) == + /\ usr \in INT /\ usr \in REG_USR /\ cnt \in NAT /\ tim \in INT + /\ + flg_comm_active' = FALSE /\ + flg_got_cli_nonce' = FALSE /\ + flg_sent_serv_nonce' = FALSE /\ + flg_sent_cert' = FALSE /\ + flg_got_premaster' = FALSE /\ + flg_set_cmn_key' = FALSE /\ + flg_done_hs_verify' = FALSE /\ + flg_sent_hs_verify' = FALSE /\ + flg_cipher_on' = FALSE /\ + flg_allow_user_auth' = FALSE /\ + flg_done_user_auth' = FALSE /\ + flg_allow_user_data' = FALSE /\ + + flg_allow_send_data' = FALSE /\ + flg_allow_recv_data' = FALSE /\ + + auth_fail_cnt'= relational_overriding(auth_fail_cnt, {<<usr,cnt>>}) /\ + recent_auth_tim' = relational_overriding(recent_auth_tim, {<<usr, tim>>}) + /\ UNCHANGED <<flg_tx_msg_encoded,flg_tx_add_mac,flg_rx_msg_decoded,flg_rx_chk_mac>> + + + +allVars == <<flg_comm_active, flg_got_cli_nonce, flg_sent_serv_nonce, flg_sent_cert,flg_got_premaster,flg_set_cmn_key,flg_done_hs_verify,flg_sent_hs_verify,flg_cipher_on, flg_allow_user_auth,flg_done_user_auth,flg_allow_user_data, flg_tx_msg_encoded,flg_tx_add_mac,flg_allow_send_data,flg_rx_msg_decoded,flg_rx_chk_mac,flg_allow_recv_data,auth_fail_cnt,recent_auth_tim>> + + + +SecCtx_Next == + \/ SetFlgCommActive + \/ SetFlgGotCliNonce + \/ SetFlgSentServNonce + \/ SetFlgSentCert + \/ SetFlgGotPremaster + \/ SetFlgCmnKey + \/ SetFlgCipherOn + \/ SetFlgDoneHsVerify + \/ SetFlgSentHsVerify + \/ SetFlgAllowUserAuth + \/ SetFlgDoneUserAuth + \/ \E usr \in REG_USR, tim \in INT: SetSuccessUserAuth(usr, tim) + \/ \E usr \in REG_USR, tim \in INT: SetFailUserAuth(usr, tim) + \/ SetFlgAllowUserData + \/ SetFlgTxMsgEncoded + \/ SetFlgTxAddMac + \/ SetFlgAllowSendData + \/ SetFlgRxMsgDecoded + \/ SetFlgRxChkMac + \/ SetFlgAllowRecvData + \/ SetFlgsHndshkCompleteSts + \/ ResetFlgsHndshkCompleteSts + \/ SetFlgsAuthCompleteSts + \/ SetFlgsAcpCompleteSts + \/ ResetFlgsAcpCompleteSts + \/ SetFlgRx + \/ ResetFlgRx + \/ SetFlgTx + \/ ResetFlgTx + \/ \E usr \in REG_USR, tim \in INT, cnt \in NAT: SetAuthInf(usr, tim, cnt) + \/ \E usr \in REG_USR, tim \in INT, cnt \in NAT: SetAuthSuccessSts(usr, cnt, tim) + \/ \E usr \in REG_USR, tim \in INT, cnt \in NAT: SetAuthFailSts(usr, cnt, tim) + +============================================================================= diff --git a/src/test/resources/examples/SimpleSATProblem/SimpleSATProblem.mch b/src/test/resources/examples/SimpleSATProblem/SimpleSATProblem.mch new file mode 100644 index 0000000000000000000000000000000000000000..19cf45e03afd8684c953eb13553566c7f032b81c --- /dev/null +++ b/src/test/resources/examples/SimpleSATProblem/SimpleSATProblem.mch @@ -0,0 +1,27 @@ +MACHINE SimpleSATProblem +ABSTRACT_CONSTANTS x1, x2, x3, x4, x5, x6, x7 +PROPERTIES + x1 : BOOL + & x2 : BOOL + & x3 : BOOL + & x4 : BOOL + & x5 : BOOL + & x6 : BOOL + & x7 : BOOL + & x1 : BOOL & x2 : BOOL & x3 : BOOL + & (x4 : BOOL & x5 : BOOL & x6 : BOOL & x7 : BOOL) + & (x1 = TRUE or x2 = TRUE or x5 = TRUE or x4 = TRUE) + & (x1 = TRUE or x2 = TRUE or not(x5 = TRUE) or x4 = TRUE) + & (x3 = TRUE or x6 = TRUE) + & (not(x4 = TRUE) or x7 = TRUE or x1 = TRUE) + & (not(x4 = TRUE) or not(x7 = TRUE) or x2 = TRUE) +VARIABLES r +INVARIANT + r : BOOL*BOOL*BOOL*BOOL*BOOL*BOOL*BOOL +INITIALISATION + r:(r = (TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)) +OPERATIONS + Set_Op = ANY r_n + WHERE r_n : BOOL*BOOL*BOOL*BOOL*BOOL*BOOL*BOOL & r_n = (x1, x2, x3, x4, x5, x6, x7) + THEN r := r_n END +END diff --git a/src/test/resources/examples/SimpleSATProblem/SimpleSATProblem.tla b/src/test/resources/examples/SimpleSATProblem/SimpleSATProblem.tla new file mode 100644 index 0000000000000000000000000000000000000000..3e7e797170d8f973ee268e59f9e9b60edce809d7 --- /dev/null +++ b/src/test/resources/examples/SimpleSATProblem/SimpleSATProblem.tla @@ -0,0 +1,18 @@ +----- MODULE SimpleSATProblem ----- +EXTENDS Naturals +CONSTANTS x1,x2,x3,x4,x5,x6,x7 +ASSUME + /\ x1 \in BOOLEAN /\ x2 \in BOOLEAN /\ x3 \in BOOLEAN + /\ x4 \in BOOLEAN /\ x5 \in BOOLEAN /\ x6 \in BOOLEAN /\ x7 \in BOOLEAN + /\ (x1 \/ x2 \/ x5 \/ x4) + /\ (x1 \/ x2 \/ ~x5 \/ x4) + /\ (x3 \/ x6) + /\ (~x4 \/ x7 \/ x1) + /\ (~x4 \/ ~x7 \/ x2) + \* 60 different solutions exist +VARIABLES r +Init == r = <<TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE>> +Set == r'= <<x1,x2,x3,x4,x5,x6,x7>> +Next == Set +======================= + diff --git a/src/test/resources/examples/SumAndProduct/SumAndProductTransition.tla b/src/test/resources/examples/SumAndProduct/SumAndProductTransition.tla new file mode 100644 index 0000000000000000000000000000000000000000..94feee1746e078d07522b4f368ef216e61fd5c39 --- /dev/null +++ b/src/test/resources/examples/SumAndProduct/SumAndProductTransition.tla @@ -0,0 +1,96 @@ +------------------------- MODULE SumAndProductTransition --------------------- +(****************************************************************************) +(* This module formalizes the "sum and product" puzzle, due to Freudenthal *) +(* (1969), and which goes as follows: *) +(* J says to S and P: I have chosen two integers x and y such that *) +(* 1 < x <= y < 100. In a moment, I will inform S only of the sum x+y *) +(* and P only of the product x*y. These announcements remain private. *) +(* You are required to determine the pair (x,y). He acts as said. *) +(* The following conversation now takes place: *) +(* 1. P says: "I don't know it." *) +(* 2. S says: "I knew you didn't." *) +(* 3. P says: "Now I know it." *) +(* 4. S says: "I now also know it." *) +(* Determine the pair (x,y). *) +(* *) +(* The following TLA+ module represents the puzzle as a transition system *) +(* where the two values are picked arbitrarily, then the feasibility of the *) +(* above dialogue is verified, with S and P adapting their beliefs at each *) +(* step. *) +(* In fact, the first announcement is implied by the second one, so we do *) +(* not have to represent it explicitly. *) +(****************************************************************************) + +EXTENDS Naturals, FiniteSets + +VARIABLES x, y, \* the numbers chosen by J + beliefP, beliefS, \* the pairs considered possible by P and S + step \* next announcement in the conversation + +Pairs == { <<i,j>> \in (2 .. 99) \X (2 .. 99) : i <= j } + +(* Set of pairs that are equivalent from the point of view of P or S with a pair (i,j). + In particular, possibleP(x,y) denotes the set of pairs that P considers possible + given her initial knowledge. *) +possibleP(i,j) == { <<u,v>> \in Pairs : u*v = i*j } +possibleS(i,j) == { <<u,v>> \in Pairs : u+v = i+j } + +(* Given a set B of beliefs (pairs of numbers), an agent knows the pair if B + is a singleton. For example, P knows the pair if knows(beliefP) holds. *) +knows(B) == Cardinality(B) = 1 + +(* Given a set B of beliefs, one knows that P knows the pair, if for every + belief b in B, P knows the result based on what it considers compatible + with b. For example, S knows that P knows if knows_knowsP(beliefS) holds. *) +knows_knowsP(B) == \A <<i,j>> \in B : knows(possibleP(i,j)) + +(* Similarly, given B, one knows that P doesn't know if there is no pair in B + for which P knows. *) +knows_not_knowsP(B) == \A <<i,j>> \in B : ~ knows(possibleP(i,j)) + +Init == + /\ x \in 2 .. 99 /\ y \in 2 .. 99 /\ x <= y +(* uncomment the following conjunct to check uniqueness of solution *) +\* /\ ~ (x=4 /\ y=13) + /\ beliefP = possibleP(x,y) + /\ beliefS = possibleS(x,y) + /\ step = 2 + +(* The following actions correspond to the different steps in the conversation. *) +Step2 == + /\ step = 2 + /\ ~ knows(beliefP) \* logically redundant, but speeds up verification + /\ knows_not_knowsP(beliefS) + /\ beliefP' = beliefP \ { <<i,j>> \in beliefP : ~ knows_not_knowsP(possibleS(i,j)) } + /\ step' = 3 + /\ UNCHANGED <<x,y,beliefS>> + +Step3 == + /\ step = 3 + /\ knows(beliefP) + /\ beliefS' = beliefS \ { <<i,j>> \in beliefS : + LET P == possibleP(i,j) + IN ~ knows(P \ {<<u,v>> \in P : ~ knows_not_knowsP(possibleS(u,v))}) } + /\ step' = 4 + /\ UNCHANGED <<x,y,beliefP>> + +Step4 == + /\ step = 4 + /\ knows(beliefS) + /\ step' = 5 + /\ UNCHANGED <<x,y,beliefP,beliefS>> + +Next == Step2 \/ Step3 \/ Step4 + +vars == <<x,y,beliefP,beliefS>> + +SumProduct == Init /\ [][Next]_vars + +(* The following assertion says that the protocol cannot finish. Try to verify it + in order to find the solution of the puzzle (disable deadlock checking). *) +Impossible == step # 5 + +============================================================================= +\* Modification History +\* Last modified Mon Apr 22 12:17:12 CEST 2013 by merz +\* Created Fri Apr 19 18:30:06 CEST 2013 by merz diff --git a/src/test/resources/examples/uf50_02.tla b/src/test/resources/examples/uf50_02.tla new file mode 100644 index 0000000000000000000000000000000000000000..060850f9bae725c21dc3f7bb452c86243e457bd6 --- /dev/null +++ b/src/test/resources/examples/uf50_02.tla @@ -0,0 +1,245 @@ +----- MODULE uf50_02 ----- +(* CNF Translated to TLA *) +(* A SATLIB Problem with 50 variables *) +(* Can be solved very quickly by ProB *) +VARIABLES + x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, + x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, + x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, + x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, + x41, x42, x43, x44, x45, x46, x47, x48, x49, x50 +TypeInv == + x1 \in BOOLEAN /\ x2 \in BOOLEAN /\ x3 \in BOOLEAN /\ x4 \in BOOLEAN /\ x5 \in BOOLEAN /\ + x6 \in BOOLEAN /\ x7 \in BOOLEAN /\ x8 \in BOOLEAN /\ x9 \in BOOLEAN /\ x10 \in BOOLEAN /\ + x11 \in BOOLEAN /\ x12 \in BOOLEAN /\ x13 \in BOOLEAN /\ x14 \in BOOLEAN /\ x15 \in BOOLEAN /\ + x16 \in BOOLEAN /\ x17 \in BOOLEAN /\ x18 \in BOOLEAN /\ x19 \in BOOLEAN /\ x20 \in BOOLEAN /\ + x21 \in BOOLEAN /\ x22 \in BOOLEAN /\ x23 \in BOOLEAN /\ x24 \in BOOLEAN /\ x25 \in BOOLEAN /\ + x26 \in BOOLEAN /\ x27 \in BOOLEAN /\ x28 \in BOOLEAN /\ x29 \in BOOLEAN /\ x30 \in BOOLEAN /\ + x31 \in BOOLEAN /\ x32 \in BOOLEAN /\ x33 \in BOOLEAN /\ x34 \in BOOLEAN /\ x35 \in BOOLEAN /\ + x36 \in BOOLEAN /\ x37 \in BOOLEAN /\ x38 \in BOOLEAN /\ x39 \in BOOLEAN /\ x40 \in BOOLEAN /\ + x41 \in BOOLEAN /\ x42 \in BOOLEAN /\ x43 \in BOOLEAN /\ x44 \in BOOLEAN /\ x45 \in BOOLEAN /\ + x46 \in BOOLEAN /\ x47 \in BOOLEAN /\ x48 \in BOOLEAN /\ x49 \in BOOLEAN /\ x50\in BOOLEAN +Sol == + ( x42 \/ x28 \/ x33 ) /\ + ( x1 \/ ~x12 \/ x2 ) /\ + ( ~x15 \/ ~x38 \/ ~x12 ) /\ + ( ~x40 \/ x8 \/ x9 ) /\ + ( x32 \/ x14 \/ x30 ) /\ + ( x38 \/ x47 \/ ~x21 ) /\ + ( ~x7 \/ ~x14 \/ ~x28 ) /\ + ( x44 \/ x27 \/ ~x3 ) /\ + ( ~x15 \/ ~x26 \/ x42 ) /\ + ( ~x22 \/ ~x45 \/ x36 ) /\ + ( ~x14 \/ x47 \/ x1 ) /\ + ( ~x10 \/ ~x8 \/ x17 ) /\ + ( ~x27 \/ x31 \/ ~x33 ) /\ + ( x12 \/ x19 \/ x26 ) /\ + ( ~x10 \/ x31 \/ x1 ) /\ + ( ~x49 \/ x19 \/ ~x48 ) /\ + ( x2 \/ ~x12 \/ ~x8 ) /\ + ( x23 \/ ~x25 \/ x5 ) /\ + ( x14 \/ x48 \/ ~x30 ) /\ + ( ~x27 \/ ~x37 \/ x21 ) /\ + ( x11 \/ ~x36 \/ x18 ) /\ + ( x25 \/ ~x42 \/ x37 ) /\ + ( ~x47 \/ ~x10 \/ x14 ) /\ + ( ~x14 \/ ~x36 \/ ~x49 ) /\ + ( ~x8 \/ x28 \/ x21 ) /\ + ( x47 \/ ~x31 \/ ~x44 ) /\ + ( x34 \/ ~x19 \/ x20 ) /\ + ( ~x29 \/ ~x38 \/ x16 ) /\ + ( x12 \/ ~x1 \/ ~x40 ) /\ + ( x44 \/ x38 \/ ~x9 ) /\ + ( x23 \/ ~x13 \/ x9 ) /\ + ( x45 \/ ~x11 \/ x21 ) /\ + ( ~x20 \/ x9 \/ ~x50 ) /\ + ( ~x39 \/ x14 \/ x38 ) /\ + ( x9 \/ ~x16 \/ x6 ) /\ + ( x46 \/ x3 \/ x34 ) /\ + ( ~x7 \/ ~x14 \/ x21 ) /\ + ( ~x40 \/ ~x47 \/ x10 ) /\ + ( x27 \/ ~x20 \/ ~x25 ) /\ + ( ~x32 \/ x6 \/ ~x13 ) /\ + ( ~x9 \/ x19 \/ x45 ) /\ + ( x3 \/ x30 \/ x27 ) /\ + ( ~x25 \/ ~x47 \/ ~x1 ) /\ + ( x46 \/ ~x13 \/ ~x1 ) /\ + ( ~x18 \/ ~x8 \/ ~x4 ) /\ + ( x23 \/ ~x5 \/ x45 ) /\ + ( x31 \/ x50 \/ x48 ) /\ + ( x11 \/ ~x48 \/ ~x50 ) /\ + ( ~x42 \/ ~x28 \/ x48 ) /\ + ( ~x41 \/ ~x16 \/ ~x32 ) /\ + ( x21 \/ ~x19 \/ ~x31 ) /\ + ( ~x33 \/ x17 \/ x27 ) /\ + ( ~x34 \/ x48 \/ ~x45 ) /\ + ( x8 \/ ~x17 \/ x29 ) /\ + ( ~x21 \/ ~x14 \/ ~x17 ) /\ + ( x29 \/ ~x49 \/ ~x21 ) /\ + ( ~x33 \/ ~x11 \/ ~x10 ) /\ + ( x31 \/ ~x28 \/ x38 ) /\ + ( x18 \/ x13 \/ x3 ) /\ + ( x44 \/ x24 \/ x36 ) /\ + ( x45 \/ x50 \/ ~x18 ) /\ + ( x1 \/ x38 \/ x10 ) /\ + ( ~x4 \/ x1 \/ ~x32 ) /\ + ( x15 \/ x28 \/ ~x42 ) /\ + ( x39 \/ x44 \/ ~x18 ) /\ + ( x43 \/ x47 \/ ~x39 ) /\ + ( x9 \/ x12 \/ x32 ) /\ + ( x23 \/ x26 \/ x3 ) /\ + ( x34 \/ ~x30 \/ ~x41 ) /\ + ( ~x19 \/ x36 \/ ~x34 ) /\ + ( x27 \/ x3 \/ ~x34 ) /\ + ( ~x9 \/ ~x22 \/ ~x7 ) /\ + ( ~x41 \/ x13 \/ x4 ) /\ + ( x6 \/ ~x50 \/ ~x46 ) /\ + ( ~x44 \/ ~x32 \/ x20 ) /\ + ( x6 \/ x43 \/ ~x40 ) /\ + ( x29 \/ x27 \/ x41 ) /\ + ( x9 \/ ~x28 \/ ~x23 ) /\ + ( x7 \/ x44 \/ ~x42 ) /\ + ( x39 \/ ~x11 \/ x19 ) /\ + ( x14 \/ x47 \/ x2 ) /\ + ( ~x37 \/ x46 \/ ~x33 ) /\ + ( x46 \/ x22 \/ x26 ) /\ + ( x10 \/ ~x29 \/ ~x14 ) /\ + ( x38 \/ ~x19 \/ ~x42 ) /\ + ( x15 \/ ~x41 \/ ~x29 ) /\ + ( x22 \/ x31 \/ x42 ) /\ + ( ~x3 \/ x4 \/ ~x27 ) /\ + ( x49 \/ ~x31 \/ x29 ) /\ + ( ~x43 \/ x19 \/ x28 ) /\ + ( ~x17 \/ x38 \/ ~x46 ) /\ + ( ~x42 \/ ~x25 \/ ~x21 ) /\ + ( x39 \/ x32 \/ x31 ) /\ + ( ~x15 \/ x9 \/ x32 ) /\ + ( ~x2 \/ ~x13 \/ x31 ) /\ + ( ~x35 \/ x15 \/ ~x43 ) /\ + ( ~x20 \/ ~x2 \/ ~x21 ) /\ + ( ~x18 \/ ~x25 \/ ~x32 ) /\ + ( ~x50 \/ x5 \/ ~x32 ) /\ + ( ~x50 \/ ~x32 \/ ~x26 ) /\ + ( ~x14 \/ x44 \/ x22 ) /\ + ( x13 \/ ~x6 \/ ~x38 ) /\ + ( x20 \/ x16 \/ x19 ) /\ + ( ~x18 \/ x11 \/ ~x9 ) /\ + ( x45 \/ ~x8 \/ ~x10 ) /\ + ( x50 \/ ~x1 \/ ~x33 ) /\ + ( ~x39 \/ x6 \/ ~x41 ) /\ + ( ~x14 \/ ~x28 \/ x48 ) /\ + ( ~x41 \/ x13 \/ x14 ) /\ + ( ~x27 \/ ~x8 \/ x30 ) /\ + ( x26 \/ ~x27 \/ x17 ) /\ + ( ~x44 \/ x37 \/ x15 ) /\ + ( x17 \/ x26 \/ ~x50 ) /\ + ( ~x17 \/ ~x48 \/ x8 ) /\ + ( ~x1 \/ x23 \/ x28 ) /\ + ( x46 \/ ~x35 \/ ~x31 ) /\ + ( ~x21 \/ x36 \/ ~x15 ) /\ + ( x9 \/ ~x37 \/ x4 ) /\ + ( x3 \/ ~x16 \/ x8 ) /\ + ( x31 \/ ~x46 \/ ~x26 ) /\ + ( ~x13 \/ ~x21 \/ x19 ) /\ + ( ~x22 \/ ~x4 \/ x47 ) /\ + ( x14 \/ x48 \/ x3 ) /\ + ( ~x28 \/ x9 \/ x18 ) /\ + ( x38 \/ x50 \/ ~x9 ) /\ + ( x49 \/ x20 \/ ~x5 ) /\ + ( x28 \/ x35 \/ ~x40 ) /\ + ( ~x41 \/ x35 \/ ~x27 ) /\ + ( x46 \/ x29 \/ x40 ) /\ + ( ~x27 \/ x2 \/ x8 ) /\ + ( x19 \/ ~x13 \/ ~x35 ) /\ + ( ~x10 \/ ~x8 \/ x32 ) /\ + ( x29 \/ x24 \/ ~x37 ) /\ + ( ~x36 \/ x12 \/ ~x17 ) /\ + ( ~x34 \/ ~x1 \/ ~x33 ) /\ + ( ~x6 \/ ~x4 \/ ~x10 ) /\ + ( x38 \/ ~x36 \/ ~x48 ) /\ + ( x23 \/ x14 \/ x4 ) /\ + ( x47 \/ ~x5 \/ x31 ) /\ + ( ~x45 \/ x13 \/ ~x7 ) /\ + ( ~x24 \/ ~x9 \/ x46 ) /\ + ( x24 \/ x38 \/ ~x8 ) /\ + ( x1 \/ ~x30 \/ x7 ) /\ + ( x24 \/ ~x35 \/ x29 ) /\ + ( x11 \/ x43 \/ x22 ) /\ + ( x9 \/ ~x43 \/ ~x34 ) /\ + ( ~x26 \/ x49 \/ ~x20 ) /\ + ( ~x27 \/ x21 \/ ~x7 ) /\ + ( ~x8 \/ x48 \/ ~x30 ) /\ + ( x45 \/ ~x13 \/ ~x21 ) /\ + ( x41 \/ ~x38 \/ x31 ) /\ + ( ~x7 \/ ~x16 \/ x5 ) /\ + ( x4 \/ x25 \/ x44 ) /\ + ( ~x5 \/ x16 \/ x17 ) /\ + ( ~x12 \/ x47 \/ x31 ) /\ + ( x21 \/ ~x4 \/ ~x47 ) /\ + ( x8 \/ x35 \/ x3 ) /\ + ( ~x36 \/ ~x16 \/ ~x27 ) /\ + ( x48 \/ x30 \/ x50 ) /\ + ( x33 \/ x25 \/ x48 ) /\ + ( x24 \/ ~x27 \/ ~x15 ) /\ + ( x8 \/ ~x36 \/ ~x27 ) /\ + ( ~x12 \/ x34 \/ ~x3 ) /\ + ( x22 \/ x11 \/ x8 ) /\ + ( x22 \/ x8 \/ x46 ) /\ + ( ~x31 \/ x44 \/ x28 ) /\ + ( x37 \/ ~x21 \/ ~x41 ) /\ + ( x50 \/ ~x43 \/ ~x22 ) /\ + ( ~x31 \/ x3 \/ x46 ) /\ + ( x8 \/ x45 \/ ~x28 ) /\ + ( ~x4 \/ ~x45 \/ x42 ) /\ + ( ~x37 \/ x26 \/ x28 ) /\ + ( ~x39 \/ ~x49 \/ x38 ) /\ + ( x21 \/ x32 \/ ~x18 ) /\ + ( x16 \/ x49 \/ x19 ) /\ + ( ~x8 \/ x5 \/ ~x4 ) /\ + ( x23 \/ ~x35 \/ ~x17 ) /\ + ( ~x49 \/ x39 \/ ~x20 ) /\ + ( x10 \/ x49 \/ ~x9 ) /\ + ( x33 \/ x2 \/ x12 ) /\ + ( x23 \/ ~x29 \/ x26 ) /\ + ( x43 \/ x22 \/ x33 ) /\ + ( ~x2 \/ x1 \/ ~x35 ) /\ + ( x1 \/ x17 \/ ~x35 ) /\ + ( x1 \/ ~x22 \/ x42 ) /\ + ( ~x24 \/ ~x10 \/ ~x44 ) /\ + ( ~x15 \/ x22 \/ x3 ) /\ + ( ~x12 \/ x27 \/ ~x15 ) /\ + ( x22 \/ ~x18 \/ x1 ) /\ + ( ~x36 \/ ~x35 \/ ~x42 ) /\ + ( ~x43 \/ x10 \/ x38 ) /\ + ( x18 \/ x24 \/ x39 ) /\ + ( ~x35 \/ ~x32 \/ x41 ) /\ + ( ~x33 \/ x49 \/ x26 ) /\ + ( ~x3 \/ x39 \/ ~x46 ) /\ + ( x23 \/ ~x8 \/ ~x41 ) /\ + ( x28 \/ ~x12 \/ ~x22 ) /\ + ( x31 \/ x17 \/ ~x23 ) /\ + ( x29 \/ ~x49 \/ x48 ) /\ + ( x15 \/ ~x35 \/ x40 ) /\ + ( ~x41 \/ x2 \/ x14 ) /\ + ( x29 \/ x40 \/ x19 ) /\ + ( x42 \/ x37 \/ ~x17 ) /\ + ( x14 \/ ~x36 \/ x31 ) /\ + ( x13 \/ x4 \/ ~x47 ) /\ + ( x8 \/ ~x3 \/ ~x28 ) /\ + ( ~x28 \/ x12 \/ ~x30 ) /\ + ( x48 \/ x3 \/ ~x22 ) /\ + ( ~x47 \/ ~x31 \/ x14 ) /\ + ( ~x41 \/ x5 \/ x7 ) /\ + ( ~x13 \/ ~x14 \/ x22 ) /\ + ( x30 \/ x13 \/ ~x15 ) /\ + ( x44 \/ x7 \/ ~x29 ) /\ + ( x44 \/ ~x18 \/ x26 ) /\ + ( x11 \/ x36 \/ ~x22 ) /\ + ( x36 \/ x35 \/ ~x43 ) /\ + ( ~x11 \/ x4 \/ ~x39 ) /\ + ( ~x2 \/ x6 \/ x5 ) /\ + TRUE +Init == TypeInv /\ Sol +DLK == 1=2 /\ x1'=x1 (* always deadlocks *) +Next == DLK + ======================= diff --git a/src/test/resources/main/Counter.tla b/src/test/resources/main/Counter.tla new file mode 100644 index 0000000000000000000000000000000000000000..52482d3053e73d2f5b55d80b836c4e58ec1ff3d6 --- /dev/null +++ b/src/test/resources/main/Counter.tla @@ -0,0 +1,10 @@ +-------------------------- MODULE Counter ----------------------------- +EXTENDS Naturals +CONSTANTS start +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +Inc == x' = x + 1 +Dec == x' = x - 1 +Next == Inc \/ Dec +======================================================================= diff --git a/src/test/resources/main/Counter_tla.mch b/src/test/resources/main/Counter_tla.mch new file mode 100644 index 0000000000000000000000000000000000000000..4044c9e4da676bd72c8b5c5cba42628e387ce0b6 --- /dev/null +++ b/src/test/resources/main/Counter_tla.mch @@ -0,0 +1,21 @@ +/*@ generated by TLA2B 1.0.7 Fri Mar 07 11:03:11 CET 2014 */ +MACHINE Counter +ABSTRACT_CONSTANTS +start +PROPERTIES + start : INTEGER +VARIABLES + x +INVARIANT + x : INTEGER +INITIALISATION + x:(x = start) +OPERATIONS + Inc_Op = ANY x_n + WHERE x_n : INTEGER & x_n = x + 1 + THEN x := x_n END; + + Dec_Op = ANY x_n + WHERE x_n : INTEGER & x_n = x - 1 + THEN x := x_n END +END \ No newline at end of file diff --git a/src/test/resources/main/Test.cfg b/src/test/resources/main/Test.cfg new file mode 100644 index 0000000000000000000000000000000000000000..8b6cfcba421df1370704ac1a8ae8fe807d7a6a57 --- /dev/null +++ b/src/test/resources/main/Test.cfg @@ -0,0 +1,2 @@ +INIT Init +NEXT Next \ No newline at end of file diff --git a/src/test/resources/main/Test.tla b/src/test/resources/main/Test.tla new file mode 100644 index 0000000000000000000000000000000000000000..ca1faca54d9cf99f8c5e2cde3e9790f73945fb41 --- /dev/null +++ b/src/test/resources/main/Test.tla @@ -0,0 +1,10 @@ +-------------------------- MODULE Test ----------------------------- +EXTENDS Naturals +CONSTANTS start +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +Inc == x' = x + 1 +Dec == x' = x - 1 +Next == Inc \/ Dec +======================================================================= diff --git a/src/test/resources/main/TypeError.tla b/src/test/resources/main/TypeError.tla new file mode 100644 index 0000000000000000000000000000000000000000..bd182b1d0e88d7baac77415b9e8d00c236e708dc --- /dev/null +++ b/src/test/resources/main/TypeError.tla @@ -0,0 +1,3 @@ +---- MODULE TypeError ---- +ASSUME 1 = TRUE +====== \ No newline at end of file diff --git a/src/test/resources/prettyprint/BBuildIns/BBuildIns.tla b/src/test/resources/prettyprint/BBuildIns/BBuildIns.tla new file mode 100644 index 0000000000000000000000000000000000000000..2874304ba44656de7f8f18c9af1a8b626a6d56d8 --- /dev/null +++ b/src/test/resources/prettyprint/BBuildIns/BBuildIns.tla @@ -0,0 +1,3 @@ +--------- MODULE BBuildIns --------- +POW1(S) == (SUBSET S) \ {} +============================== \ No newline at end of file diff --git a/src/test/resources/prettyprint/BBuildIns/Pow1.tla b/src/test/resources/prettyprint/BBuildIns/Pow1.tla new file mode 100644 index 0000000000000000000000000000000000000000..2079e5f38e9d8b483f3fe55479d68f2c68d7b4b7 --- /dev/null +++ b/src/test/resources/prettyprint/BBuildIns/Pow1.tla @@ -0,0 +1,4 @@ +---- MODULE Pow1 ---- +EXTENDS BBuildIns +ASSUME {{1}} = POW1({1}) +====== \ No newline at end of file diff --git a/src/test/resources/prettyprint/constantWithArgs/Counter.tla b/src/test/resources/prettyprint/constantWithArgs/Counter.tla new file mode 100644 index 0000000000000000000000000000000000000000..bdc49ce5f29f253a510dd071d8cedd9f4f4e904e --- /dev/null +++ b/src/test/resources/prettyprint/constantWithArgs/Counter.tla @@ -0,0 +1,9 @@ +-------------------------- MODULE Counter ----------------------------- +EXTENDS Naturals +CONSTANTS start, _\prec_ +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +val == 1 +Next == 1 \prec 2 /\ x' = x + val +======================================================================= diff --git a/src/test/resources/prettyprint/constantWithArgs/InstanceCounter.mch b/src/test/resources/prettyprint/constantWithArgs/InstanceCounter.mch new file mode 100644 index 0000000000000000000000000000000000000000..47967bf450665d0756cf20e0b5cfba63600d1179 --- /dev/null +++ b/src/test/resources/prettyprint/constantWithArgs/InstanceCounter.mch @@ -0,0 +1,15 @@ +MACHINE InstanceCounter +DEFINITIONS + prec(a, b) == a < b; + + val == 1 +VARIABLES c +INVARIANT + c : INTEGER +INITIALISATION + c:(c = 0) +OPERATIONS + Next_Op = ANY c_n + WHERE c_n : INTEGER & prec(1, 2) & c_n = c + val + THEN c := c_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/constantWithArgs/InstanceCounter.tla b/src/test/resources/prettyprint/constantWithArgs/InstanceCounter.tla new file mode 100644 index 0000000000000000000000000000000000000000..29b05182ffe9cb685c93158a5f848f3158cee616 --- /dev/null +++ b/src/test/resources/prettyprint/constantWithArgs/InstanceCounter.tla @@ -0,0 +1,6 @@ +-------------- MODULE InstanceCounter ---------------- +EXTENDS Naturals +VARIABLES c +a \prec b == a < b +INSTANCE Counter WITH x <- c, start <- 0, \prec <- \prec +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/defOverriding/Counter.tla b/src/test/resources/prettyprint/defOverriding/Counter.tla new file mode 100644 index 0000000000000000000000000000000000000000..21b60bf30d1a78649117bfe7d0114b457cd97b7e --- /dev/null +++ b/src/test/resources/prettyprint/defOverriding/Counter.tla @@ -0,0 +1,9 @@ +-------------------------- MODULE Counter ----------------------------- +EXTENDS Naturals +CONSTANTS start, foo(_) +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +val == foo(1) +Next == x' = x + val +======================================================================= diff --git a/src/test/resources/prettyprint/defOverriding/DefOverriding.cfg b/src/test/resources/prettyprint/defOverriding/DefOverriding.cfg new file mode 100644 index 0000000000000000000000000000000000000000..03ac00882f2c3cecfe405c6b927ef18091c0f5b8 --- /dev/null +++ b/src/test/resources/prettyprint/defOverriding/DefOverriding.cfg @@ -0,0 +1,2 @@ +CONSTANTS +foo <- bar \ No newline at end of file diff --git a/src/test/resources/prettyprint/defOverriding/InstanceDefOverriding.cfg b/src/test/resources/prettyprint/defOverriding/InstanceDefOverriding.cfg new file mode 100644 index 0000000000000000000000000000000000000000..1e8b350dc77bc05843ca9b8c0b407a624fb13a30 --- /dev/null +++ b/src/test/resources/prettyprint/defOverriding/InstanceDefOverriding.cfg @@ -0,0 +1,4 @@ +INIT Init +NEXT Next +CONSTANTS +foo <- bar \ No newline at end of file diff --git a/src/test/resources/prettyprint/extends/Counter.tla b/src/test/resources/prettyprint/extends/Counter.tla new file mode 100644 index 0000000000000000000000000000000000000000..addaef7e755a413ee720c9a43733071d439679c9 --- /dev/null +++ b/src/test/resources/prettyprint/extends/Counter.tla @@ -0,0 +1,9 @@ +-------------------------- MODULE Counter ----------------------------- +EXTENDS Naturals +CONSTANTS start +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +val == 1 +Next == x' = x + val +======================================================================= diff --git a/src/test/resources/prettyprint/extends/ExtendsCounter.cfg b/src/test/resources/prettyprint/extends/ExtendsCounter.cfg new file mode 100644 index 0000000000000000000000000000000000000000..0209aca647b51caf2210cd783361933e3d6e5d7e --- /dev/null +++ b/src/test/resources/prettyprint/extends/ExtendsCounter.cfg @@ -0,0 +1,4 @@ +INIT Init +NEXT Next +CONSTANTS +start = 2 \ No newline at end of file diff --git a/src/test/resources/prettyprint/extends/ExtendsCounter.mch b/src/test/resources/prettyprint/extends/ExtendsCounter.mch new file mode 100644 index 0000000000000000000000000000000000000000..efbedb91c45df59c016e4e852d485bfd31ed789b --- /dev/null +++ b/src/test/resources/prettyprint/extends/ExtendsCounter.mch @@ -0,0 +1,16 @@ +MACHINE ExtendsCounter +ABSTRACT_CONSTANTS start +PROPERTIES + start = 2 +DEFINITIONS + val == 1 +VARIABLES x +INVARIANT + x : INTEGER +INITIALISATION + x:(x = start) +OPERATIONS + Next_Op = ANY x_n + WHERE x_n : INTEGER & x_n = x + val + THEN x := x_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/extends/ExtendsCounter.tla b/src/test/resources/prettyprint/extends/ExtendsCounter.tla new file mode 100644 index 0000000000000000000000000000000000000000..37137860beebfb718d868a26ab0366c9e99cafa1 --- /dev/null +++ b/src/test/resources/prettyprint/extends/ExtendsCounter.tla @@ -0,0 +1,3 @@ +-------------- MODULE ExtendsCounter ---------------- +EXTENDS Counter +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/extends/ExtendsCounter2.cfg b/src/test/resources/prettyprint/extends/ExtendsCounter2.cfg new file mode 100644 index 0000000000000000000000000000000000000000..6b25f9936a8770c60dcc76d86df7a452a75367b5 --- /dev/null +++ b/src/test/resources/prettyprint/extends/ExtendsCounter2.cfg @@ -0,0 +1,4 @@ +INIT Init +NEXT Next +CONSTANTS +start = [Counter] 2 \ No newline at end of file diff --git a/src/test/resources/prettyprint/extends/ExtendsCounter2.mch b/src/test/resources/prettyprint/extends/ExtendsCounter2.mch new file mode 100644 index 0000000000000000000000000000000000000000..efbedb91c45df59c016e4e852d485bfd31ed789b --- /dev/null +++ b/src/test/resources/prettyprint/extends/ExtendsCounter2.mch @@ -0,0 +1,16 @@ +MACHINE ExtendsCounter +ABSTRACT_CONSTANTS start +PROPERTIES + start = 2 +DEFINITIONS + val == 1 +VARIABLES x +INVARIANT + x : INTEGER +INITIALISATION + x:(x = start) +OPERATIONS + Next_Op = ANY x_n + WHERE x_n : INTEGER & x_n = x + val + THEN x := x_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/Counter.tla b/src/test/resources/prettyprint/instance/Counter/Counter.tla new file mode 100644 index 0000000000000000000000000000000000000000..addaef7e755a413ee720c9a43733071d439679c9 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/Counter.tla @@ -0,0 +1,9 @@ +-------------------------- MODULE Counter ----------------------------- +EXTENDS Naturals +CONSTANTS start +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +val == 1 +Next == x' = x + val +======================================================================= diff --git a/src/test/resources/prettyprint/instance/Counter/InstanceDefinition.mch b/src/test/resources/prettyprint/instance/Counter/InstanceDefinition.mch new file mode 100644 index 0000000000000000000000000000000000000000..688146d036fac93fdd9ed749cca16db291bd37a4 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/InstanceDefinition.mch @@ -0,0 +1,13 @@ +MACHINE InstanceDefinition +DEFINITIONS + val == 5 +VARIABLES c +INVARIANT + c : INTEGER +INITIALISATION + c:(c = 0) +OPERATIONS + Next_Op = ANY c_n + WHERE c_n : INTEGER & c_n = c + val + THEN c := c_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/InstanceDefinition.tla b/src/test/resources/prettyprint/instance/Counter/InstanceDefinition.tla new file mode 100644 index 0000000000000000000000000000000000000000..303d8b59e063b0550108b125949b6943ec2d4f4b --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/InstanceDefinition.tla @@ -0,0 +1,5 @@ +-------------- MODULE InstanceDefinition ---------------- +VARIABLES c +val == 5 (* the val definition of the Counter module will be automatically overriden by SANY *) +INSTANCE Counter WITH x <- c, start <- 0 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/InstanceNoName.mch b/src/test/resources/prettyprint/instance/Counter/InstanceNoName.mch new file mode 100644 index 0000000000000000000000000000000000000000..ad110dca9e20e37494cfdf54fe03a6569d974b29 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/InstanceNoName.mch @@ -0,0 +1,18 @@ +MACHINE InstanceNoName +ABSTRACT_CONSTANTS start +PROPERTIES + start : INTEGER +DEFINITIONS + Init == c = start; + + val == 1 +VARIABLES c +INVARIANT + c : INTEGER +INITIALISATION + c:(Init) +OPERATIONS + Next_Op = ANY c_n + WHERE c_n : INTEGER & c_n = c + val + THEN c := c_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/InstanceNoName.tla b/src/test/resources/prettyprint/instance/Counter/InstanceNoName.tla new file mode 100644 index 0000000000000000000000000000000000000000..b2e5e4d0d3b1562d88e5b9e5cf43f7d857126f64 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/InstanceNoName.tla @@ -0,0 +1,6 @@ +-------------- MODULE InstanceNoName ---------------- +CONSTANTS start +VARIABLES c +INSTANCE Counter WITH x <- c +Spec == Init /\ [][Next]_c +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.cfg b/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.cfg new file mode 100644 index 0000000000000000000000000000000000000000..e4eda93e3f0fcbb23080a8e7dc29081ce42ffe76 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.cfg @@ -0,0 +1,3 @@ +INIT Init +NEXT Next +CONSTANTS val = [Counter] 7 \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.mch b/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.mch new file mode 100644 index 0000000000000000000000000000000000000000..73115303fa5b849795a8bf7d78e4962e013a7776 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.mch @@ -0,0 +1,13 @@ +MACHINE ModConstantAssignment +DEFINITIONS + val == 7 +VARIABLES c +INVARIANT + c : INTEGER +INITIALISATION + c:(c = 0) +OPERATIONS + Next_Op = ANY c_n + WHERE c_n : INTEGER & c_n = c + val + THEN c := c_n END +END diff --git a/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.tla b/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.tla new file mode 100644 index 0000000000000000000000000000000000000000..59009a98f2468d1364464f2a9f8f85efe41b7f43 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/ModConstantAssignment.tla @@ -0,0 +1,4 @@ +-------------- MODULE ModConstantAssignment ---------------- +VARIABLES c +INSTANCE Counter WITH x <- c, start <- 0 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/OneInstanced.mch b/src/test/resources/prettyprint/instance/Counter/OneInstanced.mch new file mode 100644 index 0000000000000000000000000000000000000000..0a7a02dad5d328d1f245e4bdd03d6b7f3264577c --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/OneInstanced.mch @@ -0,0 +1,19 @@ +MACHINE OneInstanced +ABSTRACT_CONSTANTS start +PROPERTIES + start : INTEGER +DEFINITIONS + count_Init == c = start; + + count_val == 1; + +VARIABLES c +INVARIANT + c : INTEGER +INITIALISATION + c:(count_Init) +OPERATIONS + count_Next_Op = ANY c_n + WHERE c_n : INTEGER & c_n = c + count_val + THEN c := c_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/OneInstanced.tla b/src/test/resources/prettyprint/instance/Counter/OneInstanced.tla new file mode 100644 index 0000000000000000000000000000000000000000..69cca02f78c9a06ca1990a479ae13df5a6a11b43 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/OneInstanced.tla @@ -0,0 +1,8 @@ +-------------- MODULE OneInstanced ---------------- +CONSTANTS start +VARIABLES c +count == INSTANCE Counter WITH x <- c +Init == count!Init +Next == count!Next +================================= + \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/TwoInstance.mch b/src/test/resources/prettyprint/instance/Counter/TwoInstance.mch new file mode 100644 index 0000000000000000000000000000000000000000..d23db8b678843cd223a8bac4cceb4fe0d07c3fb8 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/TwoInstance.mch @@ -0,0 +1,32 @@ +MACHINE TwoInstanced +ABSTRACT_CONSTANTS start +PROPERTIES + start : INTEGER +DEFINITIONS + count_Init == c = start; + + count_val == 1; + + count_Next == c_n = c + count_val; + + count2_Init == c2 = 0; + + count2_val == 1; + + count2_Next == c2_n = c2 + count2_val; + +VARIABLES c, c2 +INVARIANT + c : INTEGER + & c2 : INTEGER +INITIALISATION + c, c2:(count_Init & count2_Init) +OPERATIONS + Next1_Op = ANY c_n + WHERE c_n : INTEGER & count_Next & TRUE = TRUE + THEN c := c_n END; + + Next2_Op = ANY c2_n + WHERE c2_n : INTEGER & count2_Next & TRUE = TRUE + THEN c2 := c2_n END +END diff --git a/src/test/resources/prettyprint/instance/Counter/TwoInstance.tla b/src/test/resources/prettyprint/instance/Counter/TwoInstance.tla new file mode 100644 index 0000000000000000000000000000000000000000..5939e9dcb2ab565f85bc6844159d0a6a7414ded8 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/TwoInstance.tla @@ -0,0 +1,9 @@ +-------------- MODULE TwoInstanced -------------- +CONSTANTS start +VARIABLES c, c2 +count == INSTANCE Counter WITH x <- c +count2 == INSTANCE Counter WITH x <- c2, start <- 0 +Init == count!Init /\ count2!Init +Next == \/ (count!Next /\ UNCHANGED c2) + \/ (count2!Next /\ UNCHANGED c) +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/Counter/TwoInstanced.mch b/src/test/resources/prettyprint/instance/Counter/TwoInstanced.mch new file mode 100644 index 0000000000000000000000000000000000000000..d23db8b678843cd223a8bac4cceb4fe0d07c3fb8 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/TwoInstanced.mch @@ -0,0 +1,32 @@ +MACHINE TwoInstanced +ABSTRACT_CONSTANTS start +PROPERTIES + start : INTEGER +DEFINITIONS + count_Init == c = start; + + count_val == 1; + + count_Next == c_n = c + count_val; + + count2_Init == c2 = 0; + + count2_val == 1; + + count2_Next == c2_n = c2 + count2_val; + +VARIABLES c, c2 +INVARIANT + c : INTEGER + & c2 : INTEGER +INITIALISATION + c, c2:(count_Init & count2_Init) +OPERATIONS + Next1_Op = ANY c_n + WHERE c_n : INTEGER & count_Next & TRUE = TRUE + THEN c := c_n END; + + Next2_Op = ANY c2_n + WHERE c2_n : INTEGER & count2_Next & TRUE = TRUE + THEN c2 := c2_n END +END diff --git a/src/test/resources/prettyprint/instance/Counter/TwoInstanced.tla b/src/test/resources/prettyprint/instance/Counter/TwoInstanced.tla new file mode 100644 index 0000000000000000000000000000000000000000..5939e9dcb2ab565f85bc6844159d0a6a7414ded8 --- /dev/null +++ b/src/test/resources/prettyprint/instance/Counter/TwoInstanced.tla @@ -0,0 +1,9 @@ +-------------- MODULE TwoInstanced -------------- +CONSTANTS start +VARIABLES c, c2 +count == INSTANCE Counter WITH x <- c +count2 == INSTANCE Counter WITH x <- c2, start <- 0 +Init == count!Init /\ count2!Init +Next == \/ (count!Next /\ UNCHANGED c2) + \/ (count2!Next /\ UNCHANGED c) +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/OpArg/OpArg.tla b/src/test/resources/prettyprint/instance/OpArg/OpArg.tla new file mode 100644 index 0000000000000000000000000000000000000000..60a318106bbc6e701b724430bdb0a27c879d2035 --- /dev/null +++ b/src/test/resources/prettyprint/instance/OpArg/OpArg.tla @@ -0,0 +1,7 @@ +-------------- MODULE OpArg ---------------- +EXTENDS Naturals +CONSTANTS k(_,_) +VARIABLES c +Init == c = 1 +Next == c' = c + k(1, 2) +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/OpArg/OpArgInstanced.mch b/src/test/resources/prettyprint/instance/OpArg/OpArgInstanced.mch new file mode 100644 index 0000000000000000000000000000000000000000..a9e7cf31d3ead0f7a3936d849ad61bd5310d9150 --- /dev/null +++ b/src/test/resources/prettyprint/instance/OpArg/OpArgInstanced.mch @@ -0,0 +1,14 @@ +MACHINE OpArgInstanced +DEFINITIONS + foo(a,b) == a + b; + +VARIABLES c +INVARIANT + c : INTEGER +INITIALISATION + c:(c = 1) +OPERATIONS + Next_Op = ANY c_n + WHERE c_n : INTEGER & c_n = c + foo(1,2) + THEN c := c_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/OpArg/OpArgInstanced.tla b/src/test/resources/prettyprint/instance/OpArg/OpArgInstanced.tla new file mode 100644 index 0000000000000000000000000000000000000000..07e36d098a26749032f3c488f1daabf76e3eab9e --- /dev/null +++ b/src/test/resources/prettyprint/instance/OpArg/OpArgInstanced.tla @@ -0,0 +1,6 @@ +-------------- MODULE OpArgInstanced -------------- +EXTENDS Naturals +VARIABLES c +foo(a,b) == a + b +INSTANCE OpArg WITH k <- foo +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/configOverride/Counter.tla b/src/test/resources/prettyprint/instance/configOverride/Counter.tla new file mode 100644 index 0000000000000000000000000000000000000000..addaef7e755a413ee720c9a43733071d439679c9 --- /dev/null +++ b/src/test/resources/prettyprint/instance/configOverride/Counter.tla @@ -0,0 +1,9 @@ +-------------------------- MODULE Counter ----------------------------- +EXTENDS Naturals +CONSTANTS start +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +val == 1 +Next == x' = x + val +======================================================================= diff --git a/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.cfg b/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.cfg new file mode 100644 index 0000000000000000000000000000000000000000..3471675f8ebd5b9b1474da75830d4a8fe9c3a5bc --- /dev/null +++ b/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.cfg @@ -0,0 +1,4 @@ +INIT Init +NEXT Next +CONSTANTS +val =[Counter] 4 \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.mch b/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.mch new file mode 100644 index 0000000000000000000000000000000000000000..5b0c40aab287f28cbea784919bd1b0e12479680a --- /dev/null +++ b/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.mch @@ -0,0 +1,16 @@ +MACHINE InstanceCounter +ABSTRACT_CONSTANTS start +PROPERTIES + start : INTEGER +DEFINITIONS + val == 4 +VARIABLES x +INVARIANT + x : INTEGER +INITIALISATION + x:(x = start) +OPERATIONS + Next_Op = ANY x_n + WHERE x_n : INTEGER & x_n = x + val + THEN x := x_n END +END diff --git a/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.tla b/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.tla new file mode 100644 index 0000000000000000000000000000000000000000..de92f0f504ca2bdaf151bcc0ae87dd43f01dcf7c --- /dev/null +++ b/src/test/resources/prettyprint/instance/configOverride/InstanceCounter.tla @@ -0,0 +1,5 @@ +-------------- MODULE InstanceCounter ---------------- +CONSTANTS start +VARIABLES x +INSTANCE Counter +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/configOverride/InstanceCounterException.cfg b/src/test/resources/prettyprint/instance/configOverride/InstanceCounterException.cfg new file mode 100644 index 0000000000000000000000000000000000000000..efebca9fc0b6e5d9309a96fc72fd7a0695c0c2f7 --- /dev/null +++ b/src/test/resources/prettyprint/instance/configOverride/InstanceCounterException.cfg @@ -0,0 +1,4 @@ +INIT Init +NEXT Next +CONSTANTS +start <-[Counter] foo \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/configOverride/InstanceCounterException.tla b/src/test/resources/prettyprint/instance/configOverride/InstanceCounterException.tla new file mode 100644 index 0000000000000000000000000000000000000000..268aa31239fdcc8d64990010afda015c70795a52 --- /dev/null +++ b/src/test/resources/prettyprint/instance/configOverride/InstanceCounterException.tla @@ -0,0 +1,6 @@ +-------------- MODULE InstanceCounterException ---------------- +CONSTANTS start +VARIABLES x +INSTANCE Counter +foo == 11 +========================== \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceInstanceOpArg.cfg b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceInstanceOpArg.cfg new file mode 100644 index 0000000000000000000000000000000000000000..ff2050f0405ec0c0440ed7fc8ee2ac72d4c8ff1e --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceInstanceOpArg.cfg @@ -0,0 +1 @@ +CONSTANTS foo3 <- bazz \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceInstanceOpArg.tla b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceInstanceOpArg.tla new file mode 100644 index 0000000000000000000000000000000000000000..52ffeda8a2e77e841a1ac85e538fcb3e47b980cb --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceInstanceOpArg.tla @@ -0,0 +1,7 @@ +-------------- MODULE InstanceInstanceOpArg ---------------- +EXTENDS Naturals +CONSTANTS c3, foo3(_,_) +bazz(a,b) == a + b +INSTANCE InstanceOpArg WITH c2 <- c3, foo2 <- foo3 +ASSUME def /\ c3 = 3 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg.tla b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg.tla new file mode 100644 index 0000000000000000000000000000000000000000..74d8d2c25c59d1c9b9d1c732ccbd2ae9980075b8 --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg.tla @@ -0,0 +1,5 @@ +-------------------------- MODULE InstanceOpArg ----------------------------- +CONSTANTS c2, foo2(_,_) +INSTANCE OpArg WITH c <- c2, foo <- foo2 + +======================================================================= diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg2.tla b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg2.tla new file mode 100644 index 0000000000000000000000000000000000000000..72a3bb64df1b6e79622182987c51c3f11e23209c --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg2.tla @@ -0,0 +1,7 @@ +-------------- MODULE InstanceOpArg2 ---------------- +EXTENDS Naturals +CONSTANTS c2 +bar(a,b) == a + b +INSTANCE OpArg WITH c <- c2, foo <- bar +ASSUME def /\ c2 = 3 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg3.cfg b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg3.cfg new file mode 100644 index 0000000000000000000000000000000000000000..016dd9c9c87a0fb70651f40e8af1d3e3da0bc30d --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg3.cfg @@ -0,0 +1 @@ +CONSTANTS bar <- bazz \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg3.tla b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg3.tla new file mode 100644 index 0000000000000000000000000000000000000000..7b37512bf2d05d014722c0b7dc9db29b0f51ceb1 --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArg3.tla @@ -0,0 +1,7 @@ +-------------- MODULE InstanceOpArg3 ---------------- +EXTENDS Naturals +CONSTANTS c2, bar(_,_) +bazz(a,b) == a + b +INSTANCE OpArg WITH c <- c2, foo <- bar +ASSUME def /\ c2 = 3 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArgException.tla b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArgException.tla new file mode 100644 index 0000000000000000000000000000000000000000..0d79faacfda771f54fd5385e3a7415b914b9594c --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceOpArgException.tla @@ -0,0 +1,6 @@ +-------------- MODULE InstanceOpArgException ---------------- +EXTENDS Naturals +CONSTANTS c2, bar(_,_) +INSTANCE OpArg WITH c <- c2, foo <- bar +ASSUME def /\ c2 = 3 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceValue.tla b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceValue.tla new file mode 100644 index 0000000000000000000000000000000000000000..1b29c5f56f7706acc5b3a362389689431dae235c --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceValue.tla @@ -0,0 +1,6 @@ +-------------- MODULE InstanceValue ---------------- +EXTENDS Naturals +CONSTANTS c +INSTANCE Value WITH val <- 1+1 +ASSUME def +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/InstanceValue2.tla b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceValue2.tla new file mode 100644 index 0000000000000000000000000000000000000000..a6e649e164c07842e2d71c67dc25d838f4ac823b --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/InstanceValue2.tla @@ -0,0 +1,6 @@ +-------------- MODULE InstanceValue2 ---------------- +EXTENDS Naturals +CONSTANTS c, val2 +INSTANCE Value WITH val <- val2 +ASSUME def /\ val2 = 1 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/OpArg.tla b/src/test/resources/prettyprint/instance/constantSubstitution/OpArg.tla new file mode 100644 index 0000000000000000000000000000000000000000..d129ef51a7e4112c0c1d9165f48d3416b9b6882c --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/OpArg.tla @@ -0,0 +1,5 @@ +-------------------------- MODULE OpArg ----------------------------- +CONSTANTS c, foo(_,_) +def == c = foo(1,2) + +======================================================================= diff --git a/src/test/resources/prettyprint/instance/constantSubstitution/Value.tla b/src/test/resources/prettyprint/instance/constantSubstitution/Value.tla new file mode 100644 index 0000000000000000000000000000000000000000..366f450e641cc29eb1f8b52fb6033aa8c6a007c8 --- /dev/null +++ b/src/test/resources/prettyprint/instance/constantSubstitution/Value.tla @@ -0,0 +1,6 @@ +-------------------------- MODULE Value ----------------------------- +EXTENDS Naturals +CONSTANTS c, val +def == c = val + +======================================================================= diff --git a/src/test/resources/prettyprint/instance/let/InstanceLet.mch b/src/test/resources/prettyprint/instance/let/InstanceLet.mch new file mode 100644 index 0000000000000000000000000000000000000000..39f7baa86628f762aa896dc57e8d51e5e12aee8e --- /dev/null +++ b/src/test/resources/prettyprint/instance/let/InstanceLet.mch @@ -0,0 +1,26 @@ +MACHINE InstanceLet +DEFINITIONS + inst_Init == c = 1; + + inst_val == 4; + + inst_foo(p) == 1 + e + p; + inst_Next == #e.(e : {1, 2} & c_n = c + inst_foo(3) + inst_val); + + inst2_Init == c2 = 1; + + inst2_val == 4; + + inst2_foo(p) == 1 + e + p; + inst2_Next == #e.(e : {1, 2} & c2_n = c2 + inst2_foo(3) + inst2_val) +VARIABLES c, c2 +INVARIANT + c : INTEGER + & c2 : INTEGER +INITIALISATION + c, c2:(inst_Init & inst2_Init) +OPERATIONS + Next_Op = ANY c_n, c2_n + WHERE c_n : INTEGER & c2_n : INTEGER & inst_Next & inst2_Next + THEN c, c2 := c_n, c2_n END +END diff --git a/src/test/resources/prettyprint/instance/let/InstanceLet.tla b/src/test/resources/prettyprint/instance/let/InstanceLet.tla new file mode 100644 index 0000000000000000000000000000000000000000..91f6f079b2169857c61d0a0321ecefe927eb2c59 --- /dev/null +++ b/src/test/resources/prettyprint/instance/let/InstanceLet.tla @@ -0,0 +1,7 @@ +-------------- MODULE InstanceLet ---------------- +VARIABLES c, c2 +inst == INSTANCE Let WITH x <- c +inst2 == INSTANCE Let WITH x <- c2 +Init == inst!Init /\ inst2!Init +Next == inst!Next /\ inst2!Next +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/instance/let/Let.tla b/src/test/resources/prettyprint/instance/let/Let.tla new file mode 100644 index 0000000000000000000000000000000000000000..e715e11af7b1ae46c0fbcff449d9e923ca0f812b --- /dev/null +++ b/src/test/resources/prettyprint/instance/let/Let.tla @@ -0,0 +1,14 @@ +---------------------------- MODULE Let ------------------------------- +EXTENDS Naturals +VARIABLES x +----------------------------------------------------------------------------- +Init == x = 1 +val == 4 +Next == + \E e \in {1,2}: + LET + foo(p) == 1 + e + p + IN + x' = x + foo(3) + val +============================================================================= + diff --git a/src/test/resources/prettyprint/instance/twoInstanced/first.tla b/src/test/resources/prettyprint/instance/twoInstanced/first.tla new file mode 100644 index 0000000000000000000000000000000000000000..3a03509da1cd4b153600b0dd37de4a89a9a39b72 --- /dev/null +++ b/src/test/resources/prettyprint/instance/twoInstanced/first.tla @@ -0,0 +1,5 @@ +-------------------------- MODULE first ----------------------------- +EXTENDS Naturals +CONSTANTS c2 +INSTANCE second WITH c1 <- c2 +======================================================================= diff --git a/src/test/resources/prettyprint/instance/twoInstanced/second.tla b/src/test/resources/prettyprint/instance/twoInstanced/second.tla new file mode 100644 index 0000000000000000000000000000000000000000..d41e27a04046fe739ec5bbee89ee0be663fbafca --- /dev/null +++ b/src/test/resources/prettyprint/instance/twoInstanced/second.tla @@ -0,0 +1,6 @@ +-------------------------- MODULE first ----------------------------- +EXTENDS Naturals +CONSTANTS c1 + +val == c1 + 1 +======================================================================= diff --git a/src/test/resources/prettyprint/realworld/FastPaxos.cfg b/src/test/resources/prettyprint/realworld/FastPaxos.cfg new file mode 100644 index 0000000000000000000000000000000000000000..abc34f264e9817eac70466647bbf4e109f3fa4d5 --- /dev/null +++ b/src/test/resources/prettyprint/realworld/FastPaxos.cfg @@ -0,0 +1,11 @@ +INIT Init +NEXT Next +CONSTANTS + ClassicNum = {1,3} + FastNum = {2} + Acceptor = {a1,a2,a3} + PVal = {v1,v2} + any = any + a1=a1 a2=a2 a3=a3 v1=v1 v2=v2 + Max <- MaxOfSet +INVARIANT TypeOK \ No newline at end of file diff --git a/src/test/resources/prettyprint/realworld/FastPaxos.tla b/src/test/resources/prettyprint/realworld/FastPaxos.tla new file mode 100644 index 0000000000000000000000000000000000000000..1b7faa5424bb1afbdc7071dc347360787b15d677 --- /dev/null +++ b/src/test/resources/prettyprint/realworld/FastPaxos.tla @@ -0,0 +1,178 @@ +------------------------------ MODULE FastPaxos ----------------------------- +EXTENDS Naturals +CONSTANTS PVal, Acceptor, FastNum, ClassicNum, a1, a2, a3, v1, v2 + +NextNum(a) == IF a+1 \in FastNum \cup ClassicNum THEN a+1 ELSE 0 + +RNum == FastNum \cup ClassicNum + +any == CHOOSE v : v \notin PVal + +i \prec j == i < j +i \preceq j == (i \prec j) \/ (i = j) + +MaxOfSet(S) == CHOOSE p \in S: \A n \in S: p \geq n +Max(S) == CHOOSE i \in S : \A j \in S : j \preceq i +Message == + [type : {"propose"}, pval : PVal] + \cup [type : {"phase1a"}, rnd : RNum] + \cup [type : {"phase1b"}, rnd : RNum, vrnd : RNum \cup {0}, + pval : PVal \cup {any}, acc : Acceptor] + \cup [type : {"phase2a"}, rnd : RNum, pval : PVal \cup {any}] + \cup [type : {"phase2b"}, rnd : RNum, pval : PVal, acc : Acceptor] + +Quorum(i) == IF i \in ClassicNum THEN {{a1,a2}, {a1,a3}, {a2, a3}} + ELSE {{a1,a2,a3}} + + + +ASSUME + /\ FastNum \cap ClassicNum = {} + /\ \A i, j, k \in RNum : (i \prec j) /\ (j \prec k) => (i \prec k) + /\ \A i \in RNum : ~(i \prec i) + /\ \A i, j \in RNum : (i \preceq j) \/ (j \preceq i) + /\ (0 \notin RNum) /\ \A i \in RNum : 0 \prec i + /\ \A i \in FastNum : NextNum(i) \in RNum => + ~\E j \in RNum : (i \prec j) /\ (j \prec NextNum(i)) + + + +VARIABLES rnd, vrnd, pval, sentMsg, learned +vars == <<rnd, vrnd, pval, sentMsg, learned>> + +TypeOK == + /\ rnd \in [Acceptor -> RNum \cup {0}] + /\ vrnd \in [Acceptor -> RNum \cup {0}] + /\ pval \in [Acceptor -> PVal \cup {any}] + /\ sentMsg \in SUBSET Message + /\ learned \in SUBSET PVal + +Init == + /\ rnd = [a \in Acceptor |-> 0] + /\ vrnd = [a \in Acceptor |-> 0] + /\ pval = [a \in Acceptor |-> any] + /\ sentMsg = {} + /\ learned = {} +----------------------------------------------------------------------------- +Send(m) == sentMsg' = sentMsg \cup {m} + +Propose(v) == + /\ Send([type |-> "propose", pval |-> v]) + /\ UNCHANGED <<rnd, vrnd, pval, learned>> + +Phase1a(i) == + /\ Send([type |-> "phase1a", rnd |-> i]) + /\ UNCHANGED <<rnd, vrnd, pval, learned>> + +Phase1b(a, i) == + /\ rnd[a] \prec i + /\ \E m \in sentMsg : (m.type = "phase1a") /\ (m.rnd = i) + /\ rnd' = [rnd EXCEPT ![a] = i] + /\ Send([type |-> "phase1b", rnd |-> i, vrnd |-> vrnd[a], pval |-> pval[a], + acc |-> a]) + /\ UNCHANGED <<vrnd, pval, learned>> + +P1bMsg(Q, i) == + {m \in sentMsg : (m.type = "phase1b") /\ (m.acc \in Q) /\ (m.rnd = i)} + +SafeSet(M, Q, i) == + LET k == Max({m.vrnd : m \in M}) + Vk == {m.pval : m \in {mm \in M : mm.vrnd = k}} + Only(v) == \/ Vk = {v} + \/ /\ k \in FastNum + /\ \E R \in Quorum(k) : + \A a \in Q \cap R : + \E m \in M : /\ m.vrnd = k + /\ m.pval = v + /\ m.acc = a + IN IF k = 0 + THEN PVal + ELSE IF \E v \in Vk : Only(v) + THEN {CHOOSE v \in {v1}(*Vk*) : Only(v)} + ELSE PVal + +Phase2a(i, va) == + /\ ~\E m \in sentMsg : (m.type = "phase2a") /\ (m.rnd = i) + /\ \E Q \in Quorum(i) : + /\ \A a \in Q : \E m \in sentMsg : /\ m.type = "phase1b" + /\ m.rnd = i + /\ m.acc = a + /\ \/ /\ va \in SafeSet(P1bMsg(Q,i), Q, i) + /\ \E m \in sentMsg : /\ m.type \in {"propose", "phase1b"} + /\ m.pval = va + \/ /\ SafeSet(P1bMsg(Q,i), Q, i) = PVal + /\ i \in FastNum + /\ va = any + /\ Send([type |-> "phase2a", rnd |-> i, pval |-> va]) + /\ UNCHANGED <<rnd, vrnd, pval, learned>> + +Phase2b(i, a, v) == + /\ rnd[a] \preceq i + /\ vrnd[a] \prec i + /\ \E m \in sentMsg : + /\ m.type = "phase2a" + /\ m.rnd = i + /\ \/ m.pval = v + \/ /\ m.pval = any + /\ \E mm \in sentMsg : (mm.type = "propose") /\ (mm.pval = v) + /\ rnd' = [rnd EXCEPT ![a] = i] + /\ vrnd' = [vrnd EXCEPT ![a] = i] + /\ pval' = [pval EXCEPT ![a] = v] + /\ Send([type |-> "phase2b", rnd |-> i, pval |-> v, acc |-> a]) + /\ UNCHANGED learned + +Learn(v) == + /\ \E i \in RNum : + \E Q \in Quorum(i) : + \A a \in Q : + \E m \in sentMsg : /\ m.type = "phase2b" + /\ m.rnd = i + /\ m.pval = v + /\ m.acc = a + /\ learned' = learned \cup {v} + /\ UNCHANGED <<rnd, vrnd, pval, sentMsg>> +----------------------------------------------------------------------------- +P2bToP1b(Q, i) == + LET iMsg == + {m \in sentMsg : (m.type = "phase2b") /\ (m.rnd = i) /\ (m.acc \in Q)} + IN {[type |-> "phase1b", rnd |-> NextNum(i), vrnd |-> i, + pval |-> m.pval, acc |-> m.acc] : m \in iMsg} + +LeaderRecovery(i, v) == + /\ ~\E m \in sentMsg : (m.type = "phase2a") /\ (m.rnd = NextNum(i)) + /\ \E Q \in Quorum(i) : + /\ \A a \in Q : \E m \in P2bToP1b(Q, i) : m.acc = a + /\ v \in SafeSet(P2bToP1b(Q, i), Q, NextNum(i)) + /\ \E m \in P2bToP1b(Q, i) : m.pval = v + /\ Send([type |-> "phase2a", rnd |-> NextNum(i), pval |-> v]) + /\ UNCHANGED <<rnd, vrnd, pval, learned>> + +LeaderlessRecovery(i, a, v) == + /\ NextNum(i) \in FastNum + /\ rnd[a] = i + /\ vrnd[a] = i + /\ \E Q \in Quorum(i) : + /\ \A b \in Q : \E m \in P2bToP1b(Q, i) : m.acc = b + /\ v \in SafeSet(P2bToP1b(Q, i), Q, NextNum(i)) + /\ \E m \in P2bToP1b(Q, i): m.pval = v + /\ rnd' = [rnd EXCEPT ![a] = NextNum(i)] + /\ vrnd' = [vrnd EXCEPT ![a] = NextNum(i)] + /\ pval' = [pval EXCEPT ![a] = v] + /\ Send([type |-> "phase2b", rnd |-> NextNum(i), pval |-> v, acc |-> a]) + /\ UNCHANGED learned + + +----------------------------------------------------------------------------- +Next == + \/ \E v \in PVal : Propose(v) \/ Learn(v) + \/ \E i \in RNum : \/ Phase1a(i) + \/ \E a \in Acceptor : \/ Phase1b(a, i) + \/ \E v \in PVal : Phase2b(i, a, v) + \/ \E va \in PVal \cup {any} : Phase2a(i, va) + \/ \E i \in FastNum, v \in PVal : + \/ LeaderRecovery(i, v) + \/ \E a \in Acceptor :LeaderlessRecovery(i, a, v) + + + +============================================================================= diff --git a/src/test/resources/prettyprint/realworld/ManyAssumes.tla b/src/test/resources/prettyprint/realworld/ManyAssumes.tla new file mode 100644 index 0000000000000000000000000000000000000000..64d96f930c9bd6268f40a9cb4821098b58b65536 --- /dev/null +++ b/src/test/resources/prettyprint/realworld/ManyAssumes.tla @@ -0,0 +1,518 @@ +----- MODULE ManyAssumes ----- +CONSTANTS a, b, c, d +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 +ASSUME a = 1 /\ b = 1 /\ c = 1 /\ d = 1 + + + + +========== \ No newline at end of file diff --git a/src/test/resources/prettyprint/realworld/fowler.mch b/src/test/resources/prettyprint/realworld/fowler.mch new file mode 100644 index 0000000000000000000000000000000000000000..7b52dd004d45604ce2eebca929c6dc8abd8b97a1 --- /dev/null +++ b/src/test/resources/prettyprint/realworld/fowler.mch @@ -0,0 +1,55 @@ +MACHINE fowler +DEFINITIONS + Init == state = "idle" + & light = "off" + & draw = "closed" + & door = "unlocked" + & panel = "locked" +VARIABLES state, light, draw, panel, door +INVARIANT + state : STRING + & light : STRING + & draw : STRING + & panel : STRING + & door : STRING +INITIALISATION + state, light, draw, panel, door:(Init) +OPERATIONS + CloseDoor_Op = ANY state_n, door_n + WHERE state_n : STRING & door_n : STRING & door = "unlocked" + & door_n = "locked" + & state_n = "active" + & TRUE = TRUE + THEN state, door := state_n, door_n END; + + LightOn_Op = ANY state_n, light_n, panel_n, door_n + WHERE state_n : STRING & light_n : STRING & panel_n : STRING & door_n : STRING & light = "off" + & light_n = "on" + & ((draw = "opened" + => state_n = "unlockedPanel" & panel_n = "unlocked" & door_n = "locked") + & (not(draw = "opened") + => state_n = "waitingForDraw" + & panel_n = panel & door_n = door)) + & TRUE = TRUE + THEN state, light, panel, door := state_n, light_n, panel_n, door_n END; + + OpenDraw_Op = ANY state_n, draw_n, panel_n, door_n + WHERE state_n : STRING & draw_n : STRING & panel_n : STRING & door_n : STRING & draw = "closed" + & draw_n = "opened" + & ((light = "on" + => state_n = "unlockedPanel" & panel_n = "unlocked" & door_n = "locked") + & (not(light = "on") + => state_n = "waitingForLight" + & panel_n = panel & door_n = door)) + & TRUE = TRUE + THEN state, draw, panel, door := state_n, draw_n, panel_n, door_n END; + + ClosePanel_Op = ANY state_n, light_n, draw_n, panel_n, door_n + WHERE state_n : STRING & light_n : STRING & draw_n : STRING & panel_n : STRING & door_n : STRING & panel = "unlocked" + & panel_n = "locked" + & light_n = "off" + & draw_n = "closed" + & door_n = "unlocked" + & state_n = "idle" + THEN state, light, draw, panel, door := state_n, light_n, draw_n, panel_n, door_n END +END diff --git a/src/test/resources/prettyprint/realworld/fowler.tla b/src/test/resources/prettyprint/realworld/fowler.tla new file mode 100644 index 0000000000000000000000000000000000000000..09288eb98665a0bfbf2880c807f3cf255d73c8a5 --- /dev/null +++ b/src/test/resources/prettyprint/realworld/fowler.tla @@ -0,0 +1,120 @@ +---------------------------- MODULE fowler ------------------------------------ +(*****************************************************************************) +(* Controller of the secret compartment of Mrs. H, who loves secrets! *) +(* Following the example of M. Fowler, *) +(* which can be found at: `^http://martinfowler.com/^' *) +(*****************************************************************************) + +(*****************************************************************************) +(* Variables *) +(*****************************************************************************) +VARIABLE + state, \* the state for display, only to be compliant with Fowler + light, \* state of the light + draw, \* state of the draw + panel, \* state of the secret panel + door \* state of the entry door + +(*****************************************************************************) +(* Type invariance *) +(*****************************************************************************) +TypeInv == + /\ state \in { "idle", "active", "waitingForDraw", + "waitingForLight", "unlockedPanel" } + /\ light \in { "on", "off" } + /\ draw \in { "opened", "closed" } + /\ door \in { "locked", "unlocked"} + /\ panel \in { "locked", "unlocked" } +(*****************************************************************************) +(* Initial state *) +(*****************************************************************************) +Init == + /\ state = "idle" + /\ light = "off" + /\ draw = "closed" + /\ door = "unlocked" + /\ panel = "locked" +------------------------------------------------------------------------------- +(*****************************************************************************) +(* Action definition. *) +(* Note that the state variable is not *) +(* used for the determination of the *) +(* actual state, but only for display. *) +(* This shows that this variable *) +(* is not required in TLA+ *) +(*****************************************************************************) + +(*****************************************************************************) +(* Closes the door, to activate *) +(*****************************************************************************) +CloseDoor == + /\ door = "unlocked" + /\ door' = "locked" + /\ state' = "active" + /\ UNCHANGED << panel, light, draw >> +(*****************************************************************************) +(* Switch on the light, if the draw is *) +(* opened, this opens the secret panel *) +(*****************************************************************************) +LightOn == + /\ light = "off" + /\ light' = "on" + /\ IF draw = "opened" THEN + /\ state' = "unlockedPanel" + /\ panel' = "unlocked" + /\ door' = "locked" + ELSE + /\ state' = "waitingForDraw" + /\ UNCHANGED << panel, door >> + /\ UNCHANGED << draw >> +(*****************************************************************************) +(* Open the draw, if the light is on, *) +(* this opens the secret panel *) +(*****************************************************************************) +OpenDraw == + /\ draw = "closed" + /\ draw' = "opened" + /\ IF light = "on" THEN + /\ state' = "unlockedPanel" + /\ panel' = "unlocked" + /\ door' = "locked" + ELSE + /\ state' = "waitingForLight" + /\ UNCHANGED << panel, door >> + /\ UNCHANGED << light >> +(*****************************************************************************) +(* Closes the secret panel and move the *) +(* system to initial state *) +(*****************************************************************************) +ClosePanel == + /\ panel = "unlocked" + /\ panel' = "locked" + /\ light' = "off" + /\ draw' = "closed" + /\ door' = "unlocked" + /\ state' = "idle" +------------------------------------------------------------------------------- +(*****************************************************************************) +(* All possible actions *) +(*****************************************************************************) +Next == + \/ CloseDoor + \/ LightOn + \/ OpenDraw + \/ ClosePanel +(*****************************************************************************) +(* Specification of the entire system *) +(*****************************************************************************) +Spec == Init /\ [][Next]_<< panel, light, draw, door, state >> + +(*****************************************************************************) +(* Specification never violates the type invariance *) +(*****************************************************************************) +THEOREM Spec => []TypeInv +(*****************************************************************************) +(* The panel and door are never both unlocked in the same time *) +(*****************************************************************************) +Inv == + \/ panel = "unlocked" => door = "locked" + \/ door = "unlocked" => panel = "locked" +=============================================================================== \ No newline at end of file diff --git a/src/test/resources/prettyprint/realworld/microwave.cfg b/src/test/resources/prettyprint/realworld/microwave.cfg new file mode 100644 index 0000000000000000000000000000000000000000..97359debc947e0aa4856f7b06f9e06cce96b35fa --- /dev/null +++ b/src/test/resources/prettyprint/realworld/microwave.cfg @@ -0,0 +1,2 @@ +SPECIFICATION Spec +INVARIANT Door_Locked_When_Heating \ No newline at end of file diff --git a/src/test/resources/prettyprint/realworld/microwave.mch b/src/test/resources/prettyprint/realworld/microwave.mch new file mode 100644 index 0000000000000000000000000000000000000000..9a31d390f00429985df08f9d5946dfa82c35a097 --- /dev/null +++ b/src/test/resources/prettyprint/realworld/microwave.mch @@ -0,0 +1,94 @@ +MACHINE microwave +DEFINITIONS + Init == magnetron_running = FALSE + & door_open = FALSE + & button_locked = FALSE + & error = FALSE + & time = 0; + + Action_Start == error = FALSE + & magnetron_running = FALSE + & door_open = FALSE + & time /= 0 + & magnetron_running_n = TRUE + & button_locked_n = TRUE + & door_open_n = door_open & time_n = time & error_n = error; + + Action_Stop == magnetron_running = TRUE + & magnetron_running_n = FALSE + & button_locked_n = FALSE + & time_n = 0 + & door_open_n = door_open & error_n = error; + + Door_Locked_When_Heating == (magnetron_running = TRUE => door_open = FALSE) + & (magnetron_running = TRUE => button_locked = TRUE); + +VARIABLES magnetron_running, door_open, button_locked, time, error +INVARIANT + magnetron_running : BOOL + & door_open : BOOL + & button_locked : BOOL + & time : INTEGER + & error : BOOL + & Door_Locked_When_Heating +INITIALISATION + magnetron_running, door_open, button_locked, time, error:(Init) +OPERATIONS + Action_Open_Door_Op = ANY door_open_n + WHERE door_open_n : BOOL & button_locked = FALSE + & magnetron_running = FALSE + & door_open = FALSE + & door_open_n = TRUE + & TRUE = TRUE + THEN door_open := door_open_n END; + + Action_Close_Door_Op = ANY door_open_n + WHERE door_open_n : BOOL & door_open = TRUE + & door_open_n = FALSE + & TRUE = TRUE + THEN door_open := door_open_n END; + + Action_Change_Time_Op = ANY time_n + WHERE time_n : INTEGER & magnetron_running = FALSE + & (time = 180 + & time_n = 120 + or (time = 120 + & time_n = 90) + or (time = 90 + & time_n = 60) + or (time = 60 + & time_n = 30) + or (time = 30 + & time_n = 15) + or (time = 15 + & time_n = 180) + or (time = 0 + & time_n = 180)) + & TRUE = TRUE + THEN time := time_n END; + + Action_Button_S_Op = ANY magnetron_running_n, door_open_n, button_locked_n, time_n, error_n + WHERE magnetron_running_n : BOOL & door_open_n : BOOL & button_locked_n : BOOL & time_n : INTEGER & error_n : BOOL & (magnetron_running = FALSE + => Action_Start) + & (not(magnetron_running = FALSE) + => Action_Stop) + THEN magnetron_running, door_open, button_locked, time, error := magnetron_running_n, door_open_n, button_locked_n, time_n, error_n END; + + Action_Error_Op = ANY magnetron_running_n, error_n + WHERE magnetron_running_n : BOOL & error_n : BOOL & error_n = TRUE + & magnetron_running_n = FALSE + & TRUE = TRUE + THEN magnetron_running, error := magnetron_running_n, error_n END; + + Action_Tick_Op = ANY magnetron_running_n, door_open_n, button_locked_n, time_n, error_n + WHERE magnetron_running_n : BOOL & door_open_n : BOOL & button_locked_n : BOOL & time_n : INTEGER & error_n : BOOL & magnetron_running = TRUE + & ((time /= 1 + => time_n = time - 1 + & door_open_n = door_open & magnetron_running_n = magnetron_running & button_locked_n = button_locked & error_n = error) + & (not(time /= 1) + => time_n = 0 + & magnetron_running_n = FALSE + & button_locked_n = FALSE + & door_open_n = door_open & error_n = error)) + THEN magnetron_running, door_open, button_locked, time, error := magnetron_running_n, door_open_n, button_locked_n, time_n, error_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/realworld/microwave.tla b/src/test/resources/prettyprint/realworld/microwave.tla new file mode 100644 index 0000000000000000000000000000000000000000..e6962e4928806644cb098f1a35c0559ea5046752 --- /dev/null +++ b/src/test/resources/prettyprint/realworld/microwave.tla @@ -0,0 +1,175 @@ +---- MODULE microwave ---- +EXTENDS Naturals + +VARIABLES +magnetron_running, +door_open, +button_locked, +time, +error + +allvars == <<magnetron_running, door_open, button_locked, time, error>> + +\* Initialisierung - die Mikrowelle ist aus, die Tuer geschlossen +Init == + /\ magnetron_running = FALSE + /\ door_open = FALSE + /\ button_locked = FALSE + /\ error = FALSE + /\ time = 0 + +\* Repraesentiert den Benutzer, der die Tuer oeffnet +Action_Open_Door == + /\ button_locked = FALSE + /\ magnetron_running = FALSE + /\ door_open = FALSE + /\ door_open' = TRUE + /\ UNCHANGED <<magnetron_running, button_locked, time, error>> + +\* Repraesentiert den Benutzer, der die Tuer schliesst +Action_Close_Door == + /\ door_open = TRUE + /\ door_open' = FALSE + /\ UNCHANGED <<magnetron_running, button_locked, time, error>> + +\* Setzt die Zeit auf die (festen) Werte +\* Wenn die Mikrowelle gestoppt wird, ist die Zeit wieder Null +Action_Change_Time == + /\ magnetron_running = FALSE + /\ \/ /\ time = 180 + /\ time' = 120 + \/ /\ time = 120 + /\ time' = 90 + \/ /\ time = 90 + /\ time' = 60 + \/ /\ time = 60 + /\ time' = 30 + \/ /\ time = 30 + /\ time' = 15 + \/ /\ time = 15 + /\ time' = 180 + \/ /\ time = 0 + /\ time' = 180 + /\ UNCHANGED <<magnetron_running, door_open, button_locked, error>> + +\* Starten der Mikrowelle: Magnetron an, Knopf gesperrt +Action_Start == + /\ error = FALSE \* Kein Fehlerzustand + /\ magnetron_running = FALSE + /\ door_open = FALSE \* Die Tuer muss geschlossen sein + /\ time /= 0 + /\ magnetron_running' = TRUE + /\ button_locked' = TRUE + /\ UNCHANGED <<door_open, time, error>> + +\* Stoppen der Mikrowelle: Magnetron aus, Sperre loesen +Action_Stop == + /\ magnetron_running = TRUE \* Nur wenn eingeschaltet + /\ magnetron_running' = FALSE + /\ button_locked' = FALSE + /\ time' = 0 + /\ UNCHANGED <<door_open, error>> + +\* Wenn die Mikrowelle laeuft, stoppt Knopf S sie, +\* wenn sie nicht laeuft, startet S +Action_Button_S == + IF magnetron_running = FALSE + THEN Action_Start + ELSE Action_Stop + +\* Ein Fehler tritt auf. Einschalten soll nicht mehr moeglich sein. +\* Fehlerzustand kann nur durch Neustart des Modells verlassen werden +Action_Error == + /\ error' = TRUE + /\ magnetron_running' = FALSE + /\ UNCHANGED <<door_open, button_locked, time>> + +\* Tick: Eine Sekunde vergeht +Action_Tick == + /\ magnetron_running = TRUE + /\ IF time /= 1 + THEN /\ time' = time - 1 + /\ UNCHANGED <<door_open, magnetron_running, button_locked, error>> + ELSE /\ time' = 0 \* Wenn der Timer 0 erreicht, + /\ magnetron_running' = FALSE \* Mikrowelle abschalten + /\ button_locked' = FALSE \* Und Sperre loesen + /\ UNCHANGED <<door_open, error>> + +Next == + \/ Action_Open_Door + \/ Action_Close_Door + \/ Action_Change_Time + \/ Action_Button_S + \/ Action_Error + \/ Action_Tick + +\* Typinvariante +TypeInvariant == + /\ magnetron_running \in BOOLEAN + /\ door_open \in BOOLEAN + /\ button_locked \in BOOLEAN + /\ error \in BOOLEAN + /\ time \in 0..180 + +\* Die Spezifikation +\* Start mit Init, dann unendlich viele Next-Schritte +\* - Die ersten drei Fairness Angaben repraesentieren den Benutzer, +\* der die Mikrowelle verwendet (noetig fuer Liveness Beweise) +\* - Das letzte Fairness Statement bedeutet, dass das Tick-Ereignis +\* ausgefuehrt werden muss (die Zeit darf nicht stehen bleiben) +Spec == + /\ Init + /\ [][Next]_allvars + /\ SF_allvars (Action_Change_Time) + /\ SF_allvars (Action_Button_S) + /\ SF_allvars (Action_Close_Door) + /\ SF_allvars (Action_Tick) + +---- +THEOREM Spec => []TypeInvariant +---- +\* Die folgenden Statements werden per Modelcheck geprueft + +\* Wenn das Magnetron laeuft, ist die Tuer geschlossen +\* und der Knopf gesperrt +Door_Locked_When_Heating == + /\ magnetron_running = TRUE => door_open = FALSE + /\ magnetron_running = TRUE => button_locked = TRUE + +\* Die Zeit kann nur geaendert werden, wenn die Mikrowelle nicht laeuft +Only_Change_Time_When_Off == + magnetron_running = TRUE => \neg ENABLED Action_Change_Time + +\* Die Mirkowelle laeuft nicht dauerhaft +Not_Constantly_Heating == + [] <> (magnetron_running = FALSE) + +\* Wenn ein Fehler auftritt, heizt die Mikrowelle nicht (mehr) +No_Heating_Error_State == + error = TRUE => magnetron_running = FALSE + +\* Die Mikrowelle kann immer gestoppt werden, wenn sie laeuft +Stopable_At_All_Times == + magnetron_running = TRUE => ENABLED Action_Stop + +\* Wenn die Mikrowelle heizt, ist die Zeit nicht Null +Heating_Time_Not_Zero == + magnetron_running = TRUE => time /= 0 + +\* Wenn der Knopf gedrueckt wird beginnt das heizen +\* Wenn der Knopf aktiviert ist wird er irgendwann gedrueckt (Fairness) +button1 == + /\ magnetron_running = FALSE + /\ ENABLED Action_Button_S + /\ error = FALSE + => [] <> (magnetron_running = TRUE) +\* Der Knopf ist die einzige Moeglichkeit, das Magnetron zu aktivieren +button2 == + [] (\neg ENABLED Action_Start) => [] (magnetron_running = FALSE) + +\* Liveness: Es gibt immer einen Punkt in der Zukunft, +\* an dem die Mikrowelle heizt. +\* (es sei denn, ein Fehler tritt auf) +Alive == + [] <> (magnetron_running = TRUE \/ error = TRUE) +==== \ No newline at end of file diff --git a/src/test/resources/prettyprint/standardModules/MinOfSet.tla b/src/test/resources/prettyprint/standardModules/MinOfSet.tla new file mode 100644 index 0000000000000000000000000000000000000000..808f1cdd3a89fbacc36f42e96b5a9bae75a2b635 --- /dev/null +++ b/src/test/resources/prettyprint/standardModules/MinOfSet.tla @@ -0,0 +1,4 @@ +-------------- MODULE MinOfSet ---------------- +EXTENDS TLA2B +ASSUME MinOfSet({1,2,3}) = 1 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/standardModules/PermutedSequences.tla b/src/test/resources/prettyprint/standardModules/PermutedSequences.tla new file mode 100644 index 0000000000000000000000000000000000000000..3b4df8bd58b070db68b8903203aeb6fa93aae36d --- /dev/null +++ b/src/test/resources/prettyprint/standardModules/PermutedSequences.tla @@ -0,0 +1,4 @@ +-------------- MODULE PermutedSequences ---------------- +EXTENDS TLA2B +ASSUME PermutedSequences({1,2}) = {<<1,2>>,<<2,1>>} +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/standardModules/SetProduct.tla b/src/test/resources/prettyprint/standardModules/SetProduct.tla new file mode 100644 index 0000000000000000000000000000000000000000..e3efb9532de40ad829a75c6581ee3558aa11760a --- /dev/null +++ b/src/test/resources/prettyprint/standardModules/SetProduct.tla @@ -0,0 +1,4 @@ +-------------- MODULE SetProduct ---------------- +EXTENDS TLA2B +ASSUME SetProduct({1,2,3}) = 6 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/standardModules/SetSummation.tla b/src/test/resources/prettyprint/standardModules/SetSummation.tla new file mode 100644 index 0000000000000000000000000000000000000000..e8bae967f7281ac7603f071ae1cb7c93f9bb792b --- /dev/null +++ b/src/test/resources/prettyprint/standardModules/SetSummation.tla @@ -0,0 +1,4 @@ +------------- MODULE SetSummation ---------------- +EXTENDS TLA2B +ASSUME SetSummation({1,2,3}) = 6 +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/standardModules/TLA2B.tla b/src/test/resources/prettyprint/standardModules/TLA2B.tla new file mode 100644 index 0000000000000000000000000000000000000000..c4d1b5d2f962ca06b608c4ab482115a2cf895aeb --- /dev/null +++ b/src/test/resources/prettyprint/standardModules/TLA2B.tla @@ -0,0 +1,9 @@ +--------- MODULE TLA2B --------- +LOCAL INSTANCE Naturals +LOCAL INSTANCE Sequences +MinOfSet(S) == CHOOSE p \in S: \A n \in S: p \leq n +MaxOfSet(S) == CHOOSE p \in S: \A n \in S: p \geq n +SetProduct(S) == S +SetSummation(S) == S +PermutedSequences(S) == S +============================== \ No newline at end of file diff --git a/src/test/resources/prettyprint/unchanged/OneUnchangedVariable.mch b/src/test/resources/prettyprint/unchanged/OneUnchangedVariable.mch new file mode 100644 index 0000000000000000000000000000000000000000..01eac55e9633c9630b66afc119ab898e4bfc282b --- /dev/null +++ b/src/test/resources/prettyprint/unchanged/OneUnchangedVariable.mch @@ -0,0 +1,12 @@ +MACHINE OneUnchangedVariable +VARIABLES a, b +INVARIANT + a : INTEGER + & b : INTEGER +INITIALISATION + a, b:(a = 0 & b = 0) +OPERATIONS + Next_Op = ANY a_n + WHERE a_n : INTEGER & a = 1 & TRUE = TRUE + THEN a := a_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/unchanged/OneUnchangedVariable.tla b/src/test/resources/prettyprint/unchanged/OneUnchangedVariable.tla new file mode 100644 index 0000000000000000000000000000000000000000..e96976aca605b20721773ed685d8d06198c4beae --- /dev/null +++ b/src/test/resources/prettyprint/unchanged/OneUnchangedVariable.tla @@ -0,0 +1,5 @@ +-----MODULE OneUnchangedVariable ----- +VARIABLES a, b +Init == a= 0 /\ b = 0 +Next == a = 1 /\ UNCHANGED b +================================= \ No newline at end of file diff --git a/src/test/resources/prettyprint/unchanged/SeveralUnchangedVariables.mch b/src/test/resources/prettyprint/unchanged/SeveralUnchangedVariables.mch new file mode 100644 index 0000000000000000000000000000000000000000..9d5d58e93578d2ff7c4384b4f24ba6a90c040029 --- /dev/null +++ b/src/test/resources/prettyprint/unchanged/SeveralUnchangedVariables.mch @@ -0,0 +1,15 @@ +MACHINE SeveralUnchangedVariables +VARIABLES a, b, c, d, e +INVARIANT + a : INTEGER + & b : INTEGER + & c : INTEGER + & d : INTEGER + & e : INTEGER +INITIALISATION + a, b, c, d, e:(a = 0 & b = 0 & c = 0 & d = 0 & e = 0) +OPERATIONS + Next_Op = ANY a_n + WHERE a_n : INTEGER & a = 1 & TRUE = TRUE + THEN a := a_n END +END \ No newline at end of file diff --git a/src/test/resources/prettyprint/unchanged/SeveralUnchangedVariables.tla b/src/test/resources/prettyprint/unchanged/SeveralUnchangedVariables.tla new file mode 100644 index 0000000000000000000000000000000000000000..4bc2e367fbcf4f092a894391a027466db81b1c59 --- /dev/null +++ b/src/test/resources/prettyprint/unchanged/SeveralUnchangedVariables.tla @@ -0,0 +1,5 @@ + ----- MODULE SeveralUnchangedVariables ----- +VARIABLES a,b,c,d,e +Init == a= 0 /\ b = 0 /\ c = 0 /\ d = 0 /\ e = 0 +Next == a = 1 /\ UNCHANGED <<b,c,d,e>> +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/Counter.tla b/src/test/resources/typechecking/modules/Counter.tla new file mode 100644 index 0000000000000000000000000000000000000000..52482d3053e73d2f5b55d80b836c4e58ec1ff3d6 --- /dev/null +++ b/src/test/resources/typechecking/modules/Counter.tla @@ -0,0 +1,10 @@ +-------------------------- MODULE Counter ----------------------------- +EXTENDS Naturals +CONSTANTS start +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +Inc == x' = x + 1 +Dec == x' = x - 1 +Next == Inc \/ Dec +======================================================================= diff --git a/src/test/resources/typechecking/modules/Counter2.tla b/src/test/resources/typechecking/modules/Counter2.tla new file mode 100644 index 0000000000000000000000000000000000000000..2dd5137a1f1f4d3037c43842a6982cf26b90edfa --- /dev/null +++ b/src/test/resources/typechecking/modules/Counter2.tla @@ -0,0 +1,10 @@ +-------------------------- MODULE Counter2 ----------------------------- +EXTENDS Naturals +CONSTANTS start +VARIABLE x +----------------------------------------------------------------------- +Init == x = start +plus(a,b) == a + b +Inc == x' = plus(x, 2) +Next == Inc +======================================================================= diff --git a/src/test/resources/typechecking/modules/ExtendsCounter.tla b/src/test/resources/typechecking/modules/ExtendsCounter.tla new file mode 100644 index 0000000000000000000000000000000000000000..224a5f096b79157393b654f41a8051c909514e02 --- /dev/null +++ b/src/test/resources/typechecking/modules/ExtendsCounter.tla @@ -0,0 +1,3 @@ +-------------- MODULE ExtendsCounter ---------------- +EXTENDS Counter +================================= diff --git a/src/test/resources/typechecking/modules/InstCounter.tla b/src/test/resources/typechecking/modules/InstCounter.tla new file mode 100644 index 0000000000000000000000000000000000000000..a79c0aeca4fc2564b0ba525da66e42fd6e612ce4 --- /dev/null +++ b/src/test/resources/typechecking/modules/InstCounter.tla @@ -0,0 +1,11 @@ +-------------------------- MODULE InstCounter ----------------------------- +EXTENDS Naturals +CONSTANTS k +VARIABLE u +bar == 1 +inst == INSTANCE Counter WITH x <- u, start <- bar + k +inst2 == INSTANCE Counter WITH x <- u, start <- bar + inst!val +Init == inst!Init + +----------------------------------------------------------------------- +======================================================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/InstanceValue.cfg b/src/test/resources/typechecking/modules/InstanceValue.cfg new file mode 100644 index 0000000000000000000000000000000000000000..266984b5d884ea42cf0766103c69fb7a19d3aa90 --- /dev/null +++ b/src/test/resources/typechecking/modules/InstanceValue.cfg @@ -0,0 +1 @@ +CONSTANTS c2 = 1 \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/InstanceValue.tla b/src/test/resources/typechecking/modules/InstanceValue.tla new file mode 100644 index 0000000000000000000000000000000000000000..2e9335379f0e026861ae317e4dc180b88307f882 --- /dev/null +++ b/src/test/resources/typechecking/modules/InstanceValue.tla @@ -0,0 +1,5 @@ +-------------- MODULE InstanceValue ---------------- +CONSTANTS c2, val2 +INSTANCE Value WITH val <- val2, c <- c2 +ASSUME def +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/InstanceValue2Times.tla b/src/test/resources/typechecking/modules/InstanceValue2Times.tla new file mode 100644 index 0000000000000000000000000000000000000000..949f9ad1668c2532dc184b9257f9cb6aeeac5067 --- /dev/null +++ b/src/test/resources/typechecking/modules/InstanceValue2Times.tla @@ -0,0 +1,6 @@ + -------------- MODULE InstanceValue2Times ---------------- +CONSTANTS k, k2 +Inst == INSTANCE Value WITH val <- 1, c <- k +Inst2 == INSTANCE Value WITH val <- TRUE, c <- k2 +ASSUME Inst!def /\ Inst2!def +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/InstanceValues2Times.tla b/src/test/resources/typechecking/modules/InstanceValues2Times.tla new file mode 100644 index 0000000000000000000000000000000000000000..949f9ad1668c2532dc184b9257f9cb6aeeac5067 --- /dev/null +++ b/src/test/resources/typechecking/modules/InstanceValues2Times.tla @@ -0,0 +1,6 @@ + -------------- MODULE InstanceValue2Times ---------------- +CONSTANTS k, k2 +Inst == INSTANCE Value WITH val <- 1, c <- k +Inst2 == INSTANCE Value WITH val <- TRUE, c <- k2 +ASSUME Inst!def /\ Inst2!def +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/NamedInstanceCounter.tla b/src/test/resources/typechecking/modules/NamedInstanceCounter.tla new file mode 100644 index 0000000000000000000000000000000000000000..7d242f88d24195b6e5630dae50ca0ff00909bdb6 --- /dev/null +++ b/src/test/resources/typechecking/modules/NamedInstanceCounter.tla @@ -0,0 +1,7 @@ +-------------- MODULE NamedInstanceCounter ---------------- +CONSTANTS start +VARIABLES c +count == INSTANCE Counter WITH x <- c +Init == count!Init +Next == count!Next +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/NamedInstancePoly.tla b/src/test/resources/typechecking/modules/NamedInstancePoly.tla new file mode 100644 index 0000000000000000000000000000000000000000..bb4b9b3a6c9f580f32fc34271007bd57c025b533 --- /dev/null +++ b/src/test/resources/typechecking/modules/NamedInstancePoly.tla @@ -0,0 +1,5 @@ +-------------- MODULE NamedInstancePoly ---------------- +VARIABLES c +count == INSTANCE Poly WITH x <- c +Init == count!foo = 1 +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/NamedInstancePoly2.tla b/src/test/resources/typechecking/modules/NamedInstancePoly2.tla new file mode 100644 index 0000000000000000000000000000000000000000..85944c43bb260107065ab8cd7e85d9d4804a9b32 --- /dev/null +++ b/src/test/resources/typechecking/modules/NamedInstancePoly2.tla @@ -0,0 +1,5 @@ +-------------- MODULE NamedInstancePoly2 ---------------- +VARIABLES c +count == INSTANCE Poly WITH x <- c +Init == count!bar(1) +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/NamedInstancePoly3.tla b/src/test/resources/typechecking/modules/NamedInstancePoly3.tla new file mode 100644 index 0000000000000000000000000000000000000000..77e062761ac7671415347a04be0ae4f8efa0248b --- /dev/null +++ b/src/test/resources/typechecking/modules/NamedInstancePoly3.tla @@ -0,0 +1,8 @@ +----------- MODULE NamedInstancePoly3 ---------------- +VARIABLES c, c2 +count == INSTANCE Poly WITH x <- c +count2 == INSTANCE Poly WITH x <- c2 +foo == count!foo = TRUE +foo2 == count2!foo = 1 +Init == foo /\ foo2 +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/NamedInstancePoly4.tla b/src/test/resources/typechecking/modules/NamedInstancePoly4.tla new file mode 100644 index 0000000000000000000000000000000000000000..7ac2ec82c584a3bb0a23510e792a49b17213b63f --- /dev/null +++ b/src/test/resources/typechecking/modules/NamedInstancePoly4.tla @@ -0,0 +1,7 @@ +-------------- MODULE NamedInstancePoly4 ---------------- +CONSTANTS k +VARIABLES c +poly == INSTANCE Poly WITH x <- c +Init == poly!foo = TRUE +ASSUME poly!baz(1,k) +================================= \ No newline at end of file diff --git a/src/test/resources/typechecking/modules/Poly.tla b/src/test/resources/typechecking/modules/Poly.tla new file mode 100644 index 0000000000000000000000000000000000000000..b4d1d8121ea07062557e4375e25525538bc929c3 --- /dev/null +++ b/src/test/resources/typechecking/modules/Poly.tla @@ -0,0 +1,7 @@ +-------------------------- MODULE Poly ----------------------------- +VARIABLE x +----------------------------------------------------------------------- +foo == x +bar(a) == x = a +baz(a,b) == a = b +======================================================================= diff --git a/src/test/resources/typechecking/modules/Value.tla b/src/test/resources/typechecking/modules/Value.tla new file mode 100644 index 0000000000000000000000000000000000000000..85a2df253e2e0e08fa356d589057b5422232710e --- /dev/null +++ b/src/test/resources/typechecking/modules/Value.tla @@ -0,0 +1,5 @@ +-------------------------- MODULE Value ----------------------------- +CONSTANTS c, val +def == c = val + +======================================================================= diff --git a/src/test/resources/typechecking/modules/ext.tla b/src/test/resources/typechecking/modules/ext.tla new file mode 100644 index 0000000000000000000000000000000000000000..68c7e74cd63fe6b97117aff2451ba70f9c7e04a5 --- /dev/null +++ b/src/test/resources/typechecking/modules/ext.tla @@ -0,0 +1,9 @@ +-------------------------- MODULE ext----------------------------- +EXTENDS Naturals +----------------------------------------------------------------------- + +ext1 == 1 +ext2 == 1 +ext5 == 1 +ext3 == 1 +======================================================================= diff --git a/src/test/resources/typechecking/modules/test.tla b/src/test/resources/typechecking/modules/test.tla new file mode 100644 index 0000000000000000000000000000000000000000..53debdc3b0700c5ebcf810ca420c0b7720dd80ad --- /dev/null +++ b/src/test/resources/typechecking/modules/test.tla @@ -0,0 +1,5 @@ +-------------------------- MODULE test----------------------------- +cc == INSTANCE ext +----------------------------------------------------------------------- +test == 1 +=======================================================================