From 418cc5e618ee32cc201f393aeb34845340d4f55c Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Fri, 24 Dec 2021 10:22:24 +0100 Subject: [PATCH 001/129] Changes in the core coming from LSP PR --- .../csail/sdg/alloy4whole/DemoFileSystem.java | 5 +- .../sdg/alloy4whole/ExampleUsingTheAPI.java | 13 +- .../mit/csail/sdg/alloy4whole/SimpleCLI.java | 6 +- .../csail/sdg/alloy4whole/SimpleReporter.java | 26 +- org.alloytools.alloy.core/parser/Alloy.cup | 87 +++--- .../java/edu/mit/csail/sdg/alloy4/Pos.java | 17 +- .../java/edu/mit/csail/sdg/ast/Assert.java | 64 ++++ .../java/edu/mit/csail/sdg/ast/Clause.java | 21 ++ .../java/edu/mit/csail/sdg/ast/Command.java | 46 ++- .../edu/mit/csail/sdg/ast/CommandScope.java | 14 +- .../main/java/edu/mit/csail/sdg/ast/Expr.java | 8 - .../java/edu/mit/csail/sdg/ast/ExprCall.java | 16 + .../main/java/edu/mit/csail/sdg/ast/Func.java | 83 ++++- .../java/edu/mit/csail/sdg/ast/Module.java | 4 +- .../main/java/edu/mit/csail/sdg/ast/Sig.java | 141 +++++++-- .../edu/mit/csail/sdg/ast/VisitQuery.java | 16 + .../edu/mit/csail/sdg/ast/VisitQueryOnce.java | 24 ++ .../edu/mit/csail/sdg/ast/VisitReturn.java | 10 + .../edu/mit/csail/sdg/parser/CompModule.java | 287 +++++++++++++----- .../edu/mit/csail/sdg/parser/CompUtil.java | 4 + .../java/edu/mit/csail/sdg/parser/Macro.java | 40 ++- .../mit/csail/sdg/parser/MarkdownHandler.java | 2 +- .../edu/mit/csail/sdg/sim/SimInstance.java | 17 ++ .../sdg/translator/A4SolutionReader.java | 15 +- .../sdg/translator/ConvToConjunction.java | 18 ++ .../translator/TranslateAlloyToKodkod.java | 21 +- .../alloy/core/AlloyModelsTest.java | 38 +++ 27 files changed, 819 insertions(+), 224 deletions(-) create mode 100644 org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Assert.java diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/DemoFileSystem.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/DemoFileSystem.java index 9d9b598e3..3e5dd6d27 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/DemoFileSystem.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/DemoFileSystem.java @@ -21,6 +21,7 @@ import java.util.Set; import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Attr; import edu.mit.csail.sdg.ast.Command; import edu.mit.csail.sdg.ast.Decl; @@ -54,14 +55,14 @@ PrimSig makeSig(String name, boolean isAbstract, boolean isOne) throws Err { } PrimSig makeSig(PrimSig parent, String name, boolean isAbstract, boolean isOne) throws Err { - PrimSig ans = new PrimSig(name, parent, (isAbstract ? Attr.ABSTRACT : null), (isOne ? Attr.ONE : null)); + PrimSig ans = new PrimSig(null, name, Pos.UNKNOWN, parent, (isAbstract ? Attr.ABSTRACT : null), (isOne ? Attr.ONE : null)); sigs.add(ans); return ans; } void runFor3(Expr expr) throws Err { A4Options opt = new A4Options(); - Command cmd = new Command(false, 3, 3, 3, expr.and(fact)); + Command cmd = new Command(false, 3, 3, 3, null, expr.and(fact)); A4Solution sol = TranslateAlloyToKodkod.execute_command(NOP, sigs, cmd, opt); System.out.println(sol.toString().trim()); if (sol.satisfiable()) { diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheAPI.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheAPI.java index 29cbf8276..1a1930629 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheAPI.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/ExampleUsingTheAPI.java @@ -22,6 +22,7 @@ import java.util.List; import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.alloy4.Util; import edu.mit.csail.sdg.ast.Attr; import edu.mit.csail.sdg.ast.Command; @@ -54,10 +55,10 @@ public static void main(String[] args) throws Err { PrimSig B = new PrimSig("B"); // one sig A1 extends A {} - PrimSig A1 = new PrimSig("A1", A, Attr.ONE); + PrimSig A1 = new PrimSig(null, "A1", Pos.UNKNOWN, A, Attr.ONE); // one sig A2 extends A {} - PrimSig A2 = new PrimSig("A2", A, Attr.ONE); + PrimSig A2 = new PrimSig(null, "A2", Pos.UNKNOWN, A, Attr.ONE); // A { f: B lone->lone B } Expr f = A.addField("f", B.lone_arrow_lone(B)); @@ -71,13 +72,13 @@ public static void main(String[] args) throws Err { // If you want "setOf", you need: A.addField(null, "g", B.setOf()) // pred someG { some g } - Func someG = new Func(null, "SomeG", null, null, g.some()); + Func someG = new Func(null, Pos.UNKNOWN, "SomeG", null, null, g.some()); // pred atMostThree[x:univ, y:univ] { #(x+y) >= 3 } Decl x = UNIV.oneOf("x"); Decl y = UNIV.oneOf("y"); Expr body = x.get().plus(y.get()).cardinality().lte(ExprConstant.makeNUMBER(3)); - Func atMost3 = new Func(null, "atMost3", Util.asList(x, y), null, body); + Func atMost3 = new Func(null, Pos.UNKNOWN, "atMost3", Util.asList(x, y), null, body); List sigs = Arrays.asList(new Sig[] { A, B, A1, A2 @@ -85,14 +86,14 @@ public static void main(String[] args) throws Err { // run { some A && atMostThree[B,B] } for 3 but 3 int, 3 seq Expr expr1 = A.some().and(atMost3.call(B, B)); - Command cmd1 = new Command(false, 3, 3, 3, expr1); + Command cmd1 = new Command(false, 3, 3, 3, null, expr1); A4Solution sol1 = TranslateAlloyToKodkod.execute_command(NOP, sigs, cmd1, opt); System.out.println("[Solution1]:"); System.out.println(sol1.toString()); // run { some f && SomeG[] } for 3 but 2 int, 1 seq, 5 A, exactly 6 B Expr expr2 = f.some().and(someG.call()); - Command cmd2 = new Command(false, 3, 2, 1, expr2); + Command cmd2 = new Command(false, 3, 2, 1, null, expr2); cmd2 = cmd2.change(A, false, 1); cmd2 = cmd2.change(B, true, 1); A4Solution sol2 = TranslateAlloyToKodkod.execute_command(NOP, sigs, cmd2, opt); diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleCLI.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleCLI.java index 5de8c4ebd..0871426b1 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleCLI.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleCLI.java @@ -235,9 +235,9 @@ public static void main(String[] args) throws Exception { x.b.toString(sb, 4); rep.flush(); } - for (Pair x : m.getAllAssertions()) { - sb.append("\nAssertion ").append(x.a).append("\n"); - x.b.toString(sb, 4); + for (edu.mit.csail.sdg.ast.Assert x : m.getAllAssertions()) { + sb.append("\nAssertion ").append(x.label).append("\n"); + x.expr.toString(sb, 4); rep.flush(); } if (m == world) diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java index 113692e8d..2a5ddf8ba 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java @@ -762,38 +762,40 @@ else if (ai.highLevelCore().a.size() > 0) rep.cb("", " #" + (i + 1) + ": Unknown.\n"); continue; } + StringBuilder sb = new StringBuilder(); if (result.get(i).endsWith(".xml")) { rep.cb("", " #" + (i + 1) + ": "); rep.cb("link", r.check ? "Counterexample found. " : "Instance found. ", "XML: " + result.get(i)); - rep.cb("", r.label + (r.check ? " is invalid" : " is consistent")); + sb.append(r.label + (r.check ? " is invalid" : " is consistent")); if (r.expects == 0) - rep.cb("", ", contrary to expectation"); + sb.append(", contrary to expectation"); else if (r.expects == 1) - rep.cb("", ", as expected"); + sb.append(", as expected"); } else if (result.get(i).endsWith(".core")) { rep.cb("", " #" + (i + 1) + ": "); rep.cb("link", r.check ? "No counterexample found. " : "No instance found. ", "CORE: " + result.get(i)); - rep.cb("", r.label + (r.check ? " may be valid" : " may be inconsistent")); + sb.append(r.label + (r.check ? " may be valid" : " may be inconsistent")); if (r.expects == 1) - rep.cb("", ", contrary to expectation"); + sb.append(", contrary to expectation"); else if (r.expects == 0) - rep.cb("", ", as expected"); + sb.append(", as expected"); } else { if (r.check) - rep.cb("", " #" + (i + 1) + ": No counterexample found. " + r.label + " may be valid"); + sb.append(" #" + (i + 1) + ": No counterexample found. " + r.label + " may be valid"); else - rep.cb("", " #" + (i + 1) + ": No instance found. " + r.label + " may be inconsistent"); + sb.append(" #" + (i + 1) + ": No instance found. " + r.label + " may be inconsistent"); if (r.expects == 1) - rep.cb("", ", contrary to expectation"); + sb.append(", contrary to expectation"); else if (r.expects == 0) - rep.cb("", ", as expected"); + sb.append(", as expected"); } - rep.cb("", ".\n"); + sb.append(".\n"); + rep.cb("", sb.toString()); } rep.cb("", "\n"); } if (rep.warn > 1) - rep.cb("bold", "Note: There were " + rep.warn + " compilation warnings. Please scroll up to see them.\n"); + rep.cb("bold", "Note: There were " + rep.warn + " compilation warnings.\n"); if (rep.warn == 1) rep.cb("bold", "Note: There was 1 compilation warning. Please scroll up to see it.\n"); diff --git a/org.alloytools.alloy.core/parser/Alloy.cup b/org.alloytools.alloy.core/parser/Alloy.cup index 7d4f26005..a59b4fd44 100644 --- a/org.alloytools.alloy.core/parser/Alloy.cup +++ b/org.alloytools.alloy.core/parser/Alloy.cup @@ -26,6 +26,7 @@ package edu.mit.csail.sdg.parser; import java.util.Stack; import java.util.List; import java.util.ArrayList; +import java.util.Locale; import java.util.TreeSet; import java.util.Map; import java.util.LinkedHashMap; @@ -298,7 +299,7 @@ parser code {: if (content==null && loaded!=null) content = loaded.get(filename); if (content==null) content = Util.readAll(filename); if (loaded!=null) loaded.put(filename,content); - content = MarkdownHandler.strip(content); + if (content.startsWith("---") || filename.toLowerCase(Locale.ROOT).endsWith(".md")) content = MarkdownHandler.strip(content); content = Util.convertLineBreak(content); isr = new StringReader(content); CompFilter s = new CompFilter(u, seenDollar, filename, lineOffset, new BufferedReader(isr)); @@ -378,9 +379,9 @@ action code {: } } if (n!=null) - parser.alloymodule.addCommand(follow, p, n, o.label.equals("c"), overall, bitwidth, maxseq, mintime, maxtime, expects, s, x); + parser.alloymodule.addCommand(follow, p, n, o, overall, bitwidth, maxseq, mintime, maxtime, expects, s, x); else - parser.alloymodule.addCommand(follow, p, e, o.label.equals("c"), overall, bitwidth, maxseq, mintime, maxtime, expects, s, x); + parser.alloymodule.addCommand(follow, p, e, o, overall, bitwidth, maxseq, mintime, maxtime, expects, s, x); } private Expr t(Pos pos, Pos oldClosing, Expr left, Expr right, Pos close) throws Err { if (right instanceof ExprVar) { @@ -648,9 +649,9 @@ Spec ::= Spec Vis:p ENUM:o Name:a LBRACE RBRACE:c { Spec ::= Spec FACT:o Super:e {: parser.alloymodule.addFact (o , "" , e); :}; Spec ::= Spec FACT:o Name:n Super:e {: nod(n); parser.alloymodule.addFact (o , n.label , e); :}; Spec ::= Spec FACT:o STR:n Super:e {: parser.alloymodule.addFact (o , n.string , e); :}; -Spec ::= Spec ASSERT:o Super:e {: parser.alloymodule.addAssertion (o , "" , e); :}; -Spec ::= Spec ASSERT:o Name:n Super:e {: nod(n); parser.alloymodule.addAssertion (o , n.label , e); :}; -Spec ::= Spec ASSERT:o STR:n Super:e {: parser.alloymodule.addAssertion (o , n.string , e); :}; +Spec ::= Spec ASSERT:o Super:e {: parser.alloymodule.addAssertion (o , null , "" , e); :}; +Spec ::= Spec ASSERT:o Name:n Super:e {: nod(n); parser.alloymodule.addAssertion (o , n.pos, n.label , e); :}; +Spec ::= Spec ASSERT:o STR:n Super:e {: parser.alloymodule.addAssertion (o , null, n.string , e); :}; Spec ::= Spec Sig ; Spec ::= Spec Function ; Spec ::= Spec Predicate ; @@ -673,8 +674,8 @@ Command ::= Command IMPLIES CommandPrefix:o Name:n Scope:s Expects:c { Expects ::= {: RESULT=null; :}; Expects ::= EXPECT NUMBER:a {: RESULT=a; :}; -Scope ::= FOR NUMBER:a {: RESULT=new ArrayList(); RESULT.add(new CommandScope(a.pos, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; -Scope ::= FOR NUMBER:a BUT Typescopes:b {: RESULT=b; b.add(new CommandScope(a.pos, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; +Scope ::= FOR NUMBER:a {: RESULT=new ArrayList(); RESULT.add(new CommandScope(a.pos, Pos.UNKNOWN, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; +Scope ::= FOR NUMBER:a BUT Typescopes:b {: RESULT=b; b.add(new CommandScope(a.pos, Pos.UNKNOWN, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; Scope ::= FOR Typescopes:b {: RESULT=b; :}; Scope ::= {: RESULT=new ArrayList(); :}; @@ -683,7 +684,7 @@ Typescopes ::= Typescopes:a COMMA Typescope:b {: RESULT=a; a.add(b); Typescope ::= TypeNumber:a Name:b {: nod(b); - RESULT = new CommandScope(a.pos.merge(b.pos), new PrimSig(b.label, AttrType.WHERE.make(a.pos.merge(b.pos))), a.isExact, a.startingScope, a.endingScope, a.increment); + RESULT = new CommandScope(a.pos.merge(b.pos), b.pos, new PrimSig(b.label, AttrType.WHERE.make(a.pos.merge(b.pos))), a.isExact, a.startingScope, a.endingScope, a.increment); :}; //[AM]: INT -> SIGINT @@ -691,31 +692,31 @@ Typescope ::= TypeNumber:a SIGINT:b {: Pos p = a.pos.merge(b); if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); - RESULT = new CommandScope(p, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); + RESULT = new CommandScope(p, b, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); :}; Typescope ::= TypeNumber:a INT:b {: Pos p = a.pos.merge(b); if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); - RESULT = new CommandScope(p, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); + RESULT = new CommandScope(p, b, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); :}; Typescope ::= TypeNumber:a SEQ:b {: Pos p = a.pos.merge(b); if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"seq\""); if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the number of sequence index has to be exact."); - RESULT = new CommandScope(p, new PrimSig("seq", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); + RESULT = new CommandScope(p, b, new PrimSig("seq", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); :}; Typescope ::= TypeNumber:e UNIV:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on univ."); :}; -Typescope ::= TypeNumber:a STRING:b {: RESULT = new CommandScope(a.pos.merge(b), new PrimSig("String", AttrType.WHERE.make(a.pos.merge(b))), a.isExact, a.startingScope, a.endingScope, a.increment); :}; +Typescope ::= TypeNumber:a STRING:b {: RESULT = new CommandScope(a.pos.merge(b), b, new PrimSig("String", AttrType.WHERE.make(a.pos.merge(b))), a.isExact, a.startingScope, a.endingScope, a.increment); :}; // [electrum] scope on Time Typescope ::= TypeNumber:a TIME:b {: Pos p = a.pos.merge(b); - RESULT = new CommandScope(p, new PrimSig("steps", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.endingScope, a.increment); + RESULT = new CommandScope(p, Pos.UNKNOWN, new PrimSig("steps", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.endingScope, a.increment); :}; //[AM] Typescope ::= TypeNumber:e SIGINT:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You can no longer set a scope on Int; the number of Int atoms is always exactly equal to 2^(integer bitwidth).\n"); :}; @@ -723,39 +724,39 @@ Typescope ::= TypeNumber:a TIME:b {: Typescope ::= TypeNumber:e NONE:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on none."); :}; // [electrum] distinguish between "n" and "n..n", the latter become exact; open ended scopes "n.." -TypeNumber ::= EXACTLY:e NUMBER:a {: RESULT = new CommandScope( e.merge(a.pos), Sig.NONE, true, a.num, a.num, 1 ); :}; -TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(b.pos), Sig.NONE, true, a.num, b.num, 1 ); :}; -TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e , Sig.NONE, true, a.num, Integer.MAX_VALUE, 1 ); :}; -TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Sig.NONE, true, a.num, b.num, i.num); :}; -TypeNumber ::= EXACTLY:e NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Sig.NONE, true, a.num, Integer.MAX_VALUE, i.num); :}; -TypeNumber ::= NUMBER:a {: RESULT = new CommandScope(a.pos , Sig.NONE, false, a.num, a.num, 1 ); :}; -TypeNumber ::= NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(b.pos), Sig.NONE, a.num == b.num, a.num, b.num, 1 ); :}; -TypeNumber ::= NUMBER:a DOT DOT {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos , Sig.NONE, false, a.num, Integer.MAX_VALUE, 1 ); :}; -TypeNumber ::= NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Sig.NONE, a.num == b.num, a.num, b.num, i.num); :}; -TypeNumber ::= NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Sig.NONE, false, a.num, Integer.MAX_VALUE, i.num); :}; - -Macro ::= Vis:p LET:o Name:n LPAREN Names:d RPAREN MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, d , v); :}; -Macro ::= Vis:p LET:o Name:n LPAREN RPAREN MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; -Macro ::= Vis:p LET:o Name:n LBRACKET Names:d RBRACKET MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, d , v); :}; -Macro ::= Vis:p LET:o Name:n LBRACKET RBRACKET MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; -Macro ::= Vis:p LET:o Name:n MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.label, null , v); :}; +TypeNumber ::= EXACTLY:e NUMBER:a {: RESULT = new CommandScope( e.merge(a.pos), Pos.UNKNOWN, Sig.NONE, true, a.num, a.num, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(b.pos), Pos.UNKNOWN, Sig.NONE, true, a.num, b.num, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e , Pos.UNKNOWN, Sig.NONE, true, a.num, Integer.MAX_VALUE, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Pos.UNKNOWN, Sig.NONE, true, a.num, b.num, i.num); :}; +TypeNumber ::= EXACTLY:e NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Pos.UNKNOWN, Sig.NONE, true, a.num, Integer.MAX_VALUE, i.num); :}; +TypeNumber ::= NUMBER:a {: RESULT = new CommandScope(a.pos , Pos.UNKNOWN, Sig.NONE, false, a.num, a.num, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(b.pos), Pos.UNKNOWN, Sig.NONE, a.num == b.num, a.num, b.num, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos , Pos.UNKNOWN, Sig.NONE, false, a.num, Integer.MAX_VALUE, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Pos.UNKNOWN, Sig.NONE, a.num == b.num, a.num, b.num, i.num); :}; +TypeNumber ::= NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Pos.UNKNOWN, Sig.NONE, false, a.num, Integer.MAX_VALUE, i.num); :}; + +Macro ::= Vis:p LET:o Name:n LPAREN Names:d RPAREN MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.pos, n.label, d , v); :}; +Macro ::= Vis:p LET:o Name:n LPAREN RPAREN MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.pos, n.label, null , v); :}; +Macro ::= Vis:p LET:o Name:n LBRACKET Names:d RBRACKET MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.pos, n.label, d , v); :}; +Macro ::= Vis:p LET:o Name:n LBRACKET RBRACKET MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.pos, n.label, null , v); :}; +Macro ::= Vis:p LET:o Name:n MacroBody:v {: nod(n); parser.alloymodule.addMacro(o.merge(v.span()), p, n.pos, n.label, null , v); :}; MacroBody ::= Super:a {: RESULT=a; :}; MacroBody ::= EQUALS Expr:a {: RESULT=a; :}; -Function ::= Vis:p FUN:o Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , mult(r), v); :}; -Function ::= Vis:p FUN:o Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , mult(r), v); :}; -Function ::= Vis:p FUN:o Name:n COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, null , mult(r), v); :}; -Function ::= Vis:p FUN:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , mult(r), v); :}; -Function ::= Vis:p FUN:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , mult(r), v); :}; -Function ::= Vis:p FUN:o SigRef:f DOT Name:n COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , null , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, null, d , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, null, d , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, null, null , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, f , d , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, f , d , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n COLON Expr:r Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, f , null , mult(r), v); :}; -Predicate ::= Vis:p PRED:o Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , null, v); :}; -Predicate ::= Vis:p PRED:o Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, d , null, v); :}; -Predicate ::= Vis:p PRED:o Name:n Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, null, null , null, v); :}; -Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , null, v); :}; -Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , d , null, v); :}; -Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n.label, f , null , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, null, d , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, null, d , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, null, null , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, f , d , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, f , d , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n Super:v {: nod(n); parser.alloymodule.addFunc(o.merge(v.span()), p, n, f , null , null, v); :}; Vis ::= {: RESULT=null; :}; Vis ::= PRIVATE:p {: RESULT=p; :}; @@ -765,7 +766,7 @@ Sig ::= SigQuals:a Names:b SigIn:c LBRACE Decls:d RBRACE:o SuperOpt:e if (e==null) e = ExprConstant.Op.TRUE.make(o, 0); ExprVar cc = (c!=null && c.size()>0) ? c.remove(c.size()-1) : null; for(ExprVar bb:b) { - parser.alloymodule.addSig(bb.label, cc, c, d, e, + parser.alloymodule.addSig(bb.pos, bb.label, cc, c, d, e, AttrType.WHERE .makenull(bb.pos.merge(e==null ? o : e.span())), AttrType.ABSTRACT.makenull(a.get(0)), AttrType.LONE .makenull(a.get(1)), diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Pos.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Pos.java index a82798858..07e6b84fa 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Pos.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Pos.java @@ -102,9 +102,9 @@ public Pos(String filename, int x, int y, int x2, int y2) { * @param that - the other position object */ public Pos merge(Pos that) { - if (that == null || that == UNKNOWN || that == this) + if (that == null || that.equals(UNKNOWN) || that == this) return this; - if (this == UNKNOWN) + if (this.equals(UNKNOWN)) return that; int x = this.x, y = this.y, x2 = that.x2, y2 = that.y2; if (that.y < y || (that.y == y && that.x < x)) { @@ -178,6 +178,11 @@ public String toString() { return "line " + y + ", column " + x + ", filename=" + filename; } + public String toRangeString() { + String filePart = filename.length() == 0 ? "" : ", filename=" + filename; + return "line " + y + ", column " + x + " to line " + y2 + ", column " + x2 + filePart; + } + int start() { return y * 500 + x; } @@ -194,6 +199,10 @@ public boolean contains(Pos pos) { int anchor = pos.start(); int ourStart = start(); int ourEnd = end(); + + if(!filename.equals(pos.filename) && !"".equals(pos.filename)) + return false; + if (ourStart > anchor) return false; @@ -308,4 +317,8 @@ public String substring(String text) { public boolean sameFile(Pos pos) { return this.filename.equals(pos.filename); } + + public Pos withFilename(String filename){ + return new Pos(filename, x, y, x2, y2); + } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Assert.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Assert.java new file mode 100644 index 000000000..a7431265e --- /dev/null +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Assert.java @@ -0,0 +1,64 @@ +package edu.mit.csail.sdg.ast; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.Pos; + +public final class Assert extends Expr implements Clause { + public final Expr expr; + public final Pos labelPos; + public final String label; + + public Assert(Pos pos, Pos labelPos, String label, Expr expr) { + super(pos, Type.FORMULA); + this.expr = expr; + this.labelPos = labelPos; + this.label = label; + } + + @Override + public String explain() { + return "assert " + label; + } + + @Override + public void toString(StringBuilder out, int indent) { + if (indent < 0) { + out.append(label); + } else { + for (int i = 0; i < indent; i++) { + out.append(' '); + } + out.append( "assert ").append(label).append('\n'); + } + } + + @Override + public T accept(VisitReturn visitor) throws Err { + return visitor.visit(this); + } + + @Override + public Expr resolve(Type t, Collection warnings) { + return this; + } + + @Override + public int getDepth() { + return 1; + } + + @Override + public String getHTML() { + return "assert " + label; + } + + @Override + public List< ? extends Browsable> getSubnodes() { + return Arrays.asList(expr); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Clause.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Clause.java index 10d951644..a512d2399 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Clause.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Clause.java @@ -22,4 +22,25 @@ public interface Clause { * @return a string formatted like a set */ String explain(); + + public final class Custom implements Clause{ + final Pos pos; + final String explanation; + + public Custom(Pos pos, String explanation) { + this.pos = pos; + this.explanation = explanation; + } + + @Override + public Pos pos() { + return pos; + } + + @Override + public String explain() { + return explanation; + } + + } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Command.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Command.java index 3e39158fc..033057377 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Command.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Command.java @@ -125,6 +125,11 @@ public final class Command extends Browsable { public final Expr nameExpr; + /** + * The 'check' or 'run' keyword + */ + public final ExprVar commandKeyword; + /** * Returns a human-readable string that summarizes this Run or Check command. */ @@ -170,6 +175,27 @@ else if (bitwidth >= 0 || maxseq >= 0 || scope.size() > 0 || minprefix >= 0 || m return sb.toString(); } + /** + * Constructs a new Command object. + * + * @param check - true if this is a "check"; false if this is a "run" + * @param overall - the overall scope (0 or higher) (-1 if no overall scope was + * specified) + * @param bitwidth - the integer bitwidth (0 or higher) (-1 if it was not + * specified) + * @param maxseq - the maximum sequence length (0 or higher) (-1 if it was not + * specified) + * @param mintime - the minimal trace length (0 or higher) (-1 if it was not + * specified) + * @param maxtime - the maximal trace length (0 or higher) (-1 if it was not + * specified) + * @param formula - the formula that must be satisfied by this command + */ + //extended with time scopes + public Command(boolean check, int overall, int bitwidth, int maxseq, int mintime, int maxtime, ExprVar commandKeyword, Expr formula) throws ErrorSyntax { + this(null, null, "", check, overall, bitwidth, maxseq, mintime, maxtime, -1, null, null, commandKeyword, formula, null); + } + /** * Constructs a new Command object. * @@ -182,8 +208,8 @@ else if (bitwidth >= 0 || maxseq >= 0 || scope.size() > 0 || minprefix >= 0 || m * specified) * @param formula - the formula that must be satisfied by this command */ - public Command(boolean check, int overall, int bitwidth, int maxseq, Expr formula) throws ErrorSyntax { - this(null, null, "", check, overall, bitwidth, maxseq, -1, -1, -1, null, null, formula, null); + public Command(boolean check, int overall, int bitwidth, int maxseq, ExprVar commandKeyword, Expr formula) throws ErrorSyntax { + this(null, null, "", check, overall, bitwidth, maxseq, -1, -1, -1, null, null, commandKeyword, formula, null); } /** @@ -210,10 +236,11 @@ public Command(boolean check, int overall, int bitwidth, int maxseq, Expr formul * exact though we may or may not know what the scope is yet * @param formula - the formula that must be satisfied by this command */ - public Command(Pos pos, Expr e, String label, boolean check, int overall, int bitwidth, int maxseq, int minprefix, int maxprefix, int expects, Iterable scope, Iterable additionalExactSig, Expr formula, Command parent) { + public Command(Pos pos, Expr e, String label, boolean check, int overall, int bitwidth, int maxseq, int minprefix, int maxprefix, int expects, Iterable scope, Iterable additionalExactSig, ExprVar commandKeyword, Expr formula, Command parent) { if (pos == null) pos = Pos.UNKNOWN; this.nameExpr = e; + this.commandKeyword = commandKeyword; this.formula = formula; this.pos = pos; this.label = (label == null ? "" : label); @@ -234,24 +261,27 @@ public Command(Pos pos, Expr e, String label, boolean check, int overall, int bi * Constructs a new Command object where it is the same as the current object, * except with a different formula. */ + //extended with time scopes public Command change(Expr newFormula) { - return new Command(pos, nameExpr, label, check, overall, bitwidth, maxseq, minprefix, maxprefix, expects, scope, additionalExactScopes, newFormula, parent); + return new Command(pos, nameExpr, label, check, overall, bitwidth, maxseq, minprefix, maxprefix, expects, scope, additionalExactScopes, commandKeyword, newFormula, parent); } /** * Constructs a new Command object where it is the same as the current object, * except with a different scope. */ + //extended with time scopes public Command change(ConstList scope) { - return new Command(pos, nameExpr, label, check, overall, bitwidth, maxseq, minprefix, maxprefix, expects, scope, additionalExactScopes, formula, parent); + return new Command(pos, nameExpr, label, check, overall, bitwidth, maxseq, minprefix, maxprefix, expects, scope, additionalExactScopes, commandKeyword, formula, parent); } /** * Constructs a new Command object where it is the same as the current object, * except with a different list of "additional exact sigs". */ + //extended with time scopes public Command change(Sig... additionalExactScopes) { - return new Command(pos, nameExpr, label, check, overall, bitwidth, maxseq, minprefix, maxprefix, expects, scope, Util.asList(additionalExactScopes), formula, parent); + return new Command(pos, nameExpr, label, check, overall, bitwidth, maxseq, minprefix, maxprefix, expects, scope, Util.asList(additionalExactScopes), commandKeyword, formula, parent); } /** @@ -269,10 +299,10 @@ public Command change(Sig sig, boolean isExact, int newScope) throws ErrorSyntax public Command change(Sig sig, boolean isExact, int startingScope, int endingScope, int increment) throws ErrorSyntax { for (int i = 0; i < scope.size(); i++) if (scope.get(i).sig == sig) { - CommandScope sc = new CommandScope(scope.get(i).pos, sig, isExact, startingScope, endingScope, increment); + CommandScope sc = new CommandScope(scope.get(i).pos, scope.get(i).sigPos, sig, isExact, startingScope, endingScope, increment); return change(new TempList(scope).set(i, sc).makeConst()); } - CommandScope sc = new CommandScope(Pos.UNKNOWN, sig, isExact, startingScope, endingScope, increment); + CommandScope sc = new CommandScope(Pos.UNKNOWN, Pos.UNKNOWN, sig, isExact, startingScope, endingScope, increment); return change(Util.append(scope, sc)); } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/CommandScope.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/CommandScope.java index 357be5bfb..408f88b82 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/CommandScope.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/CommandScope.java @@ -37,6 +37,10 @@ public class CommandScope { */ public final Pos pos; + /** + * The position of the sig reference + */ + public final Pos sigPos; /** * The sig whose scope is being given by this CommandScope object. */ @@ -69,7 +73,7 @@ public class CommandScope { * @throws ErrorSyntax if scope is less than zero */ public CommandScope(Sig sig, boolean isExact, int scope) throws ErrorSyntax { - this(null, sig, isExact, scope, scope, 1); + this(null, null, sig, isExact, scope, scope, 1); } /** @@ -87,7 +91,7 @@ public CommandScope(Sig sig, boolean isExact, int scope) throws ErrorSyntax { * @throws ErrorSyntax if endingScope is less than startingScope * @throws ErrorSyntax if increment is less than one */ - public CommandScope(Pos pos, Sig sig, boolean isExact, int startingScope, int endingScope, int increment) throws ErrorSyntax { + public CommandScope(Pos pos, Pos sigPos, Sig sig, boolean isExact, int startingScope, int endingScope, int increment) throws ErrorSyntax { if (pos == null) pos = Pos.UNKNOWN; if (sig == null) @@ -104,12 +108,18 @@ public CommandScope(Pos pos, Sig sig, boolean isExact, int startingScope, int en throw new ErrorSyntax(pos, "Sig " + sig + "'s increment value cannot be " + increment + ".\nThe increment must be 1 or greater."); this.pos = pos; this.sig = sig; + this.sigPos = sigPos; this.isExact = isExact; this.startingScope = startingScope; this.endingScope = endingScope; this.increment = increment; } + Expr sigRef = null; + public Expr sigRef(){ + if(sigRef == null) sigRef = ExprUnary.Op.NOOP.make(sigPos, sig, null, 0); + return sigRef; + } /** {@inheritDoc} */ @Override public String toString() { diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java index 336c82466..f4a27bade 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java @@ -1180,10 +1180,6 @@ public final Expr eventually() { *

* this must be a formula */ - public final Expr after() { - return ExprUnary.Op.AFTER.make(span(), this); - } - /** * Returns the formula (before this) *

@@ -1198,10 +1194,6 @@ public final Expr before() { *

* this must be a formula */ - public final Expr historically() { - return ExprUnary.Op.HISTORICALLY.make(span(), this); - } - /** * Returns the formula (once this) *

diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprCall.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprCall.java index 14c421bde..fc33446ca 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprCall.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprCall.java @@ -31,6 +31,7 @@ import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.alloy4.Util; import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.parser.Macro; /** * Immutable; represents a call. @@ -266,6 +267,21 @@ public Type visit(Sig x) { return x.type; } + @Override + public Type visit(Func x) throws Err { + return x.type; + } + + @Override + public Type visit(Assert x) throws Err { + return x.type; + } + + @Override + public Type visit(Macro x) throws Err { + return x.type(); + } + @Override public Type visit(Field x) { return x.type; diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Func.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Func.java index 6518c9d30..c8a4d3e0e 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Func.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Func.java @@ -18,13 +18,16 @@ import static edu.mit.csail.sdg.alloy4.TableView.clean; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.NoSuchElementException; +import java.util.stream.Collectors; import edu.mit.csail.sdg.alloy4.ConstList; import edu.mit.csail.sdg.alloy4.Err; import edu.mit.csail.sdg.alloy4.ErrorSyntax; import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.alloy4.Util; @@ -40,7 +43,7 @@ * predicate/function call */ -public final class Func extends Browsable implements Clause { +public final class Func extends Expr implements Clause { /** * The location in the original file where this predicate/function is declared; @@ -59,6 +62,11 @@ public final class Func extends Browsable implements Clause { */ public final String label; + /** + * The position of the label + */ + public final Pos labelPos; + /** * True if this is a predicate; false if this is a function. */ @@ -133,8 +141,8 @@ public List params() { * @throws ErrorSyntax if this function's return type declaration contains a * predicate/function call */ - public Func(Pos pos, String label, List decls, Expr returnDecl, Expr body) throws Err { - this(pos, null, label, decls, returnDecl, body); + public Func(Pos pos, Pos labelPos, String label, List decls, Expr returnDecl, Expr body) throws Err { + this(pos, null, labelPos, label, decls, returnDecl, body); } /** @@ -167,12 +175,14 @@ public Func(Pos pos, String label, List decls, Expr returnDecl, Expr body) * @throws ErrorSyntax if this function's return type declaration contains a * predicate/function call */ - public Func(Pos pos, Pos isPrivate, String label, List decls, Expr returnDecl, Expr body) throws Err { + public Func(Pos pos, Pos isPrivate, Pos labelPos, String label, List decls, Expr returnDecl, Expr body) throws Err { + super(pos, Type.FORMULA); if (pos == null) pos = Pos.UNKNOWN; this.pos = pos; this.isPrivate = isPrivate; this.label = (label == null ? "" : label); + this.labelPos = labelPos; this.isPred = (returnDecl == null); if (returnDecl == null) returnDecl = ExprConstant.FALSE; @@ -252,12 +262,6 @@ public final String toString() { return (isPred ? "pred " : "fun ") + label; } - /** {@inheritDoc} */ - @Override - public final Pos pos() { - return pos; - } - /** {@inheritDoc} */ @Override public final Pos span() { @@ -270,6 +274,12 @@ public String getHTML() { return (isPred ? "pred " : "fun ") + label; } + ExprVar labelExpr = null; + public Expr labelExpr(){ + if(labelExpr == null) + labelExpr = ExprVar.make(labelPos, label); + return labelExpr; + } /** {@inheritDoc} */ @Override public List< ? extends Browsable> getSubnodes() { @@ -284,8 +294,7 @@ public String getHTML() { return ans; } - @Override - public String explain() { + public String explainOld() { if (clean(label).contains("run$")) { return null; } @@ -324,4 +333,54 @@ public String explain() { return sb.toString(); } + @Override + public String explain() { + StringBuilder sb = new StringBuilder(); + if (isPred) + sb.append("pred "); + else + sb.append("fun "); + + sb.append(clean(label)); + + if (decls.size() > 0 ) { + sb.append(" [\n"); + sb.append(decls.stream() + .flatMap(decl -> decl.names.stream().map(e -> " " + e + " : " + decl.expr.type)) + .collect(Collectors.joining(",\n"))); + sb.append("\n]"); + } + if (!isPred) { + sb.append(" ⟶ ").append(returnDecl.type.toString()); + } + return sb.toString(); + } + + @Override + public void toString(StringBuilder out, int indent) { + if (indent < 0) { + out.append("(").append(label).append(" <: ").append(label).append(")"); + } else { + for (int i = 0; i < indent; i++) { + out.append(' '); + } + out.append( isPred? "pred " : "field ").append(label).append('\n'); + } + } + + @Override + public T accept(VisitReturn visitor) throws Err { + return visitor.visit(this); + } + + @Override + public Expr resolve(Type t, Collection warnings) { + return this; + } + + @Override + public int getDepth() { + return 1; + } + } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Module.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Module.java index 07d768156..85f5b785e 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Module.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Module.java @@ -79,7 +79,7 @@ public interface Module extends Clause { /** * Return an unmodifiable list of all assertions in this module. */ - public ConstList> getAllAssertions(); + public ConstList getAllAssertions(); /** * Return an unmodifiable list of all facts in this module. @@ -110,7 +110,7 @@ public interface Module extends Clause { public JFrame showAsTree(Listener listener); /** - * Parse one expression by starting fromt this module as the root module. + * Parse one expression by starting from this module as the root module. */ public Expr parseOneExpressionFromString(String input) throws Err, FileNotFoundException, IOException; } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Sig.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Sig.java index 211040e65..e422f8752 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Sig.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Sig.java @@ -20,6 +20,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import edu.mit.csail.sdg.alloy4.ConstList; import edu.mit.csail.sdg.alloy4.ConstList.TempList; @@ -33,6 +35,7 @@ import edu.mit.csail.sdg.alloy4.Util; import edu.mit.csail.sdg.alloy4.Version; import edu.mit.csail.sdg.ast.Attr.AttrType; +import org.alloytools.util.table.Table; /** * Mutable; represents a signature. @@ -45,26 +48,26 @@ public abstract class Sig extends Expr implements Clause { /** The built-in "univ" signature. */ - public static final PrimSig UNIV = new PrimSig("univ", null, true, false); + public static final PrimSig UNIV = new PrimSig("univ", null, null, false, false); /** The built-in "Int" signature. */ - public static final PrimSig SIGINT = new PrimSig("Int", UNIV, false, false); + public static final PrimSig SIGINT = new PrimSig("Int", Pos.UNKNOWN, UNIV, false, false); /** The built-in "seq/Int" signature. */ - public static final PrimSig SEQIDX = new PrimSig("seq/Int", SIGINT, false, true); + public static final PrimSig SEQIDX = new PrimSig("seq/Int", Pos.UNKNOWN, SIGINT, false, true); /** The built-in "String" signature. */ - public static final PrimSig STRING = new PrimSig("String", UNIV, false, true); + public static final PrimSig STRING = new PrimSig("String", Pos.UNKNOWN, UNIV, false, true); /** The built-in "none" signature. */ - public static final PrimSig NONE = new PrimSig("none", null, false, false); + public static final PrimSig NONE = new PrimSig("none", null, null, false, false); /** The built-in "none" signature. */ public static final PrimSig GHOST = mkGhostSig(); private static final PrimSig mkGhostSig() { try { - return new PrimSig("Univ", null, new Attr[0]); + return new PrimSig(null, "Univ", null, null, new Attr[0]); } catch (Err e) { return null; // never happens } @@ -226,6 +229,11 @@ public final T accept(VisitReturn visitor) throws Err { */ public final Pos isVariable; + /** + * The position of the sig label + */ + public final Pos labelPos; + /** * The label for this sig; this name does not need to be unique. */ @@ -268,11 +276,12 @@ private Sig(String label, boolean var) { this.isMeta = null; this.isEnum = null; this.isVariable = var ? Pos.UNKNOWN : null; + this.labelPos = null; this.attributes = ConstList.make(); } /** Constructs a new PrimSig or SubsetSig. */ - private Sig(Type type, String label, Attr... attributes) throws Err { + private Sig(Type type, Pos labelPos, String label, Attr... attributes) throws Err { super(AttrType.WHERE.find(attributes), type); this.attributes = Util.asList(attributes); Expr oneof = ExprUnary.Op.ONEOF.make(null, this); @@ -328,6 +337,7 @@ private Sig(Type type, String label, Attr... attributes) throws Err { this.isVariable = isVariable; this.label = label; this.builtin = false; + this.labelPos = labelPos; if (isLone != null && isOne != null) throw new ErrorSyntax(isLone.merge(isOne), "You cannot declare a sig to be both lone and one."); if (isLone != null && isSome != null) @@ -359,6 +369,13 @@ public boolean isSame(Expr obj) { /** Returns true iff "this is equal or subtype of that" */ public abstract boolean isSameOrDescendentOf(Sig that); + public boolean isEnumMember() { + if (this instanceof PrimSig) { + PrimSig _this = (PrimSig) this; + return _this.parent.isEnum != null; + } else + return false; + } /** {@inheritDoc} */ @Override public int getDepth() { @@ -469,10 +486,27 @@ public Iterable descendents() throws Err { */ public final PrimSig parent; + /** + * The position of the reference to the parent Sig. + * Can be null only if parent is null + */ + public final Pos parentRefPos; + + + private Expr parentRef; + public Expr parentRef(){ + if(parentRef == null ){ + parentRef = ExprUnary.Op.NOOP.make(parentRefPos , parent ); + } + return parentRef; + } + /** Constructs a builtin PrimSig. */ - private PrimSig(String label, PrimSig parent, boolean var, boolean add) { + private PrimSig(String label, Pos parentRefPos, PrimSig parent, boolean var, boolean add) { super(label, var); this.parent = parent; + assert parent == null ? parentRefPos == null : parentRefPos != null; + this.parentRefPos = parentRefPos ; if (add) this.parent.children.add(this); } @@ -488,8 +522,10 @@ private PrimSig(String label, PrimSig parent, boolean var, boolean add) { * @throws ErrorType if you attempt to extend the builtin sigs NONE, SIGINT, * SEQIDX, or STRING */ - public PrimSig(String label, PrimSig parent, Attr... attributes) throws Err { - super(((parent != null && parent.isEnum != null) ? parent.type : null), label, Util.append(attributes, Attr.SUBSIG)); + public PrimSig(Pos labelPos, String label, Pos parentRefPos, PrimSig parent, Attr... attributes) throws Err { + super(((parent != null && parent.isEnum != null) ? parent.type : null), labelPos, label, Util.append(attributes, Attr.SUBSIG)); + assert parent == null ? parentRefPos == null : parentRefPos != null; + if (parent == SIGINT) throw new ErrorSyntax(pos, "sig " + label + " cannot extend the builtin \"Int\" signature"); if (parent == SEQIDX) @@ -503,6 +539,8 @@ public PrimSig(String label, PrimSig parent, Attr... attributes) throws Err { else if (parent != UNIV) parent.children.add(this); this.parent = parent; + this.parentRefPos = parentRefPos; + if (isEnum != null && parent != UNIV) throw new ErrorType(pos, "sig " + label + " is not a toplevel sig, so it cannot be an enum."); for (; parent != null; parent = parent.parent) @@ -523,7 +561,7 @@ else if (parent != UNIV) * @throws ErrorSyntax if the signature has two or more multiplicities */ public PrimSig(String label, Attr... attributes) throws Err { - this(label, null, attributes); + this(null, label, null, null, attributes); } /** {@inheritDoc} */ @@ -611,6 +649,23 @@ private static Type getType(String label, Iterable parents) throws Err { return (ans != null) ? ans : (UNIV.type); } + /** + * The positions of references to parent Sigs (in parents field). + * Could be null + */ + public final ConstList parentRefPoss; + + private ConstList parentRefs; + public ConstList parentRefs(){ + if(parentRefs == null){ + TempList res = new TempList<>(); + for(int i = 0; i < parents.size(); i++){ + res.add(ExprUnary.Op.NOOP.make(parentRefPoss != null ? parentRefPoss.get(i) : Pos.UNKNOWN, parents.get(i) )); + } + parentRefs = res.makeConst(); + } + return parentRefs; + } /** * Constructs a subset sig. * @@ -622,8 +677,8 @@ private static Type getType(String label, Iterable parents) throws Err { * @throws ErrorSyntax if the signature has two or more multiplicities * @throws ErrorType if parents only contains NONE */ - public SubsetSig(String label, Collection parents, Attr... attributes) throws Err { - super(getType(label, parents), label, Util.append(attributes, Attr.SUBSET)); + public SubsetSig(Pos labelPos, String label, Collection parentRefPoss, Collection parents, Attr... attributes) throws Err { + super(getType(label, parents), labelPos, label, Util.append(attributes, Attr.SUBSET)); if (isEnum != null) throw new ErrorType(pos, "Subset signature cannot be an enum."); boolean exact = false; @@ -656,6 +711,7 @@ public SubsetSig(String label, Collection parents, Attr... attributes) thro if (temp.size() == 0) throw new ErrorType(pos, "Sig " + label + " must have at least one non-empty parent."); this.parents = temp.makeConst(); + this.parentRefPoss = parentRefPoss != null ? new TempList(parentRefPoss).makeConst() : null; } /** {@inheritDoc} */ @@ -696,13 +752,15 @@ public static final class Field extends ExprHasName implements Clause { /** The declaration that this field came from. */ private Decl decl; + public final Pos labelPos; + /** Return the declaration that this field came from. */ public Decl decl() { return decl; } /** Constructs a new Field object. */ - private Field(Pos pos, Pos isPrivate, Pos isMeta, Pos disjoint, Pos disjoint2, Pos isVar, Sig sig, String label, Expr bound) throws Err { + private Field(Pos pos, Pos isPrivate, Pos isMeta, Pos disjoint, Pos disjoint2, Pos isVar, Sig sig, Pos labelPos, String label, Expr bound) throws Err { super(pos, label, sig.type.product(bound.type)); this.defined = bound.mult() == ExprUnary.Op.EXACTLYOF; if (sig.builtin) @@ -717,6 +775,7 @@ private Field(Pos pos, Pos isPrivate, Pos isMeta, Pos disjoint, Pos disjoint2, P this.isMeta = (isMeta != null ? isMeta : sig.isMeta); this.isVariable = isVar; this.sig = sig; + this.labelPos = labelPos; } /** @@ -837,7 +896,7 @@ public final Field addField(String label, Expr bound) throws Err { // multiplicity // symbol, we assume // it's oneOf - final Field f = new Field(null, null, null, null, null, null, this, label, bound); + final Field f = new Field(null, null, null, null, null, null, this, null, label, bound); final Decl d = new Decl(null, null, null, null, Arrays.asList(f), bound); f.decl = d; fields.add(d); @@ -867,7 +926,7 @@ public final Field addField(String label, Expr bound) throws Err { * @throws ErrorType if the bound is not fully typechecked or is not a * set/relation */ - public final Field[] addTrickyField(Pos pos, Pos isPrivate, Pos isDisjoint, Pos isDisjoint2, Pos isMeta, Pos isVar, String[] labels, Expr bound) throws Err { + public final Field[] addTrickyField(Pos pos, Pos isPrivate, Pos isDisjoint, Pos isDisjoint2, Pos isMeta, Pos isVar, List labels, Expr bound) throws Err { bound = bound.typecheck_as_set(); if (bound.ambiguous) bound = bound.resolve_as_set(null); @@ -876,9 +935,9 @@ public final Field[] addTrickyField(Pos pos, Pos isPrivate, Pos isDisjoint, Pos // multiplicity // symbol, we assume // it's oneOf - final Field[] f = new Field[labels.length]; + final Field[] f = new Field[labels.size()]; for (int i = 0; i < f.length; i++) - f[i] = new Field(pos, isPrivate, isMeta, isDisjoint, isDisjoint2, isVar, this, labels[i], bound); + f[i] = new Field(pos, isPrivate, isMeta, isDisjoint, isDisjoint2, isVar, this, labels.get(i).pos, labels.get(i).label, bound); final Decl d = new Decl(isPrivate, isDisjoint, isDisjoint2, isVar, Arrays.asList(f), bound); for (int i = 0; i < f.length; i++) { f[i].decl = d; @@ -917,7 +976,7 @@ public final Field addDefinedField(Pos pos, Pos isPrivate, Pos isMeta, String la bound = bound.resolve_as_set(null); if (bound.mult() != ExprUnary.Op.EXACTLYOF) bound = ExprUnary.Op.EXACTLYOF.make(null, bound); - final Field f = new Field(pos, isPrivate, isMeta, null, null, null, this, label, bound); + final Field f = new Field(pos, isPrivate, isMeta, null, null, null, this, null, label, bound); final Decl d = new Decl(null, null, null, null, Arrays.asList(f), bound); f.decl = d; fields.add(d); @@ -925,8 +984,10 @@ public final Field addDefinedField(Pos pos, Pos isPrivate, Pos isMeta, String la return f; } - @Override - public String explain() { + // TODO remove at some point + public String explainOld() { + Table t = new Table(2, 1 + realFields.size(), 1); + StringBuilder sb = new StringBuilder(); if (builtin) sb.append("builtin "); @@ -956,6 +1017,44 @@ public String explain() { } sb.append(" }"); + //return sb.toString(); + + return t.transpose(0).toString(); + } + + @Override + public String explain() { + StringBuilder sb = new StringBuilder(); + if (builtin) + sb.append("builtin "); + if (isEnum != null) + sb.append("enum "); + if (isAbstract != null) + sb.append("abstract "); + if (isLone != null) + sb.append("lone "); + if (isOne != null) + sb.append("one "); + if (isMeta != null) + sb.append("meta "); + if (isSome != null) + sb.append("some "); + if (isSubsig != null) + sb.append("sig "); + if (isSubset != null) + sb.append("subset "); + + sb.append(clean(label)); + if(! realFields.isEmpty()){ + sb.append(" {\n"); + + sb.append(StreamSupport.stream(realFields.spliterator(), false) + .map(f -> " " + clean(f.label) + " : " + + clean(type.join(f.type).toString())) + .collect(Collectors.joining(",\n"))); + + sb.append("\n}"); + } return sb.toString(); } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitQuery.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitQuery.java index 5b91dfb86..f692968b8 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitQuery.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitQuery.java @@ -17,6 +17,7 @@ import edu.mit.csail.sdg.alloy4.Err; import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.parser.Macro; /** * This abstract class implements a Query visitor that walks over an Expr and @@ -149,6 +150,21 @@ public T visit(Sig x) throws Err { return null; } + @Override + public T visit(Func x) throws Err { + return null; + } + + @Override + public T visit(Assert x) throws Err { + return null; + } + + @Override + public T visit(Macro x) throws Err { + return null; + } + /** * Visits a Field node (this default implementation simply returns null) */ diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitQueryOnce.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitQueryOnce.java index e6a03242c..f51104442 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitQueryOnce.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitQueryOnce.java @@ -4,6 +4,7 @@ import edu.mit.csail.sdg.alloy4.Err; import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.parser.Macro; /** * Acts like VisitQuery but never traverses a node more than once. @@ -144,4 +145,27 @@ protected boolean visited(Expr x) { return visited.put(x, x) != null; } + @Override + public T visit(Func x) throws Err { + if (visited(x)) + return null; + else + return super.visit(x); + } + + @Override + public T visit(Assert x) throws Err { + if (visited(x)) + return null; + else + return super.visit(x); + } + + @Override + public T visit(Macro x) throws Err { + if (visited(x)) + return null; + else + return super.visit(x); + } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitReturn.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitReturn.java index 626e5ea87..c78f58890 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitReturn.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/VisitReturn.java @@ -17,6 +17,7 @@ import edu.mit.csail.sdg.alloy4.Err; import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.parser.Macro; /** * This abstract class defines what a Return Visitor's interface needs to be. @@ -81,4 +82,13 @@ public T visit(ExprBadJoin x) throws Err { /** Visits a Field node. */ public abstract T visit(Field x) throws Err; + + /** Visits a Func node. */ + public abstract T visit(Func x) throws Err; + + /** Visists an Assert node. */ + public abstract T visit(Assert x) throws Err; + + /** Visits a Macro node. */ + public abstract T visit(Macro macro) throws Err; } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java index 7fff7c4e0..658b35222 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java @@ -40,6 +40,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import edu.mit.csail.sdg.alloy4.A4Reporter; import edu.mit.csail.sdg.alloy4.ConstList; @@ -56,6 +57,7 @@ import edu.mit.csail.sdg.alloy4.SafeList; import edu.mit.csail.sdg.alloy4.Util; import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.ast.Assert; import edu.mit.csail.sdg.ast.Attr; import edu.mit.csail.sdg.ast.Browsable; import edu.mit.csail.sdg.ast.Clause; @@ -76,6 +78,7 @@ import edu.mit.csail.sdg.ast.ExprList; import edu.mit.csail.sdg.ast.ExprQt; import edu.mit.csail.sdg.ast.ExprUnary; +import edu.mit.csail.sdg.ast.ExprUnary.Op; import edu.mit.csail.sdg.ast.ExprVar; import edu.mit.csail.sdg.ast.Func; import edu.mit.csail.sdg.ast.Module; @@ -243,7 +246,7 @@ public String path() { private final Map macros = new LinkedHashMap(); /** Each assertion name is mapped to its Expr. */ - private final Map asserts = new LinkedHashMap(); + private final Map asserts = new LinkedHashMap(); /** * The list of facts; each fact is either an untypechecked Exp or a typechecked @@ -384,7 +387,7 @@ public Expr resolve(final Pos pos, final String name) { match = rootmodule.globals.get(name); if (match != null) { if (match instanceof Macro) - return ((Macro) match).changePos(pos); + return (match);//.changePos(pos); match = ExprUnary.Op.NOOP.make(pos, match); return ExprChoice.make(isIntsNotUsed, pos, asList(match), asList(name)); } @@ -486,9 +489,14 @@ public Expr visit(ExprITE x) throws Err { public Expr visit(ExprBadJoin x) throws Err { Expr left = visitThis(x.left); Expr right = visitThis(x.right); + Expr rightInner = ignoreNoops(right); // If it's a macro invocation, instantiate it - if (right instanceof Macro) - return ((Macro) right).addArg(left).instantiate(this, warns); + if (rightInner instanceof Macro){ + Expr instantiated = ((Macro) rightInner).addArg(left).instantiate(this, warns); + Expr res = ExprUnary.Op.NOOP.make(right.pos, instantiated); + res.setReferenced(right.referenced()); + return res; + } // check to see if it is the special builtin function "Int[]" if (left.type().is_int() && right.isSame(Sig.SIGINT)) return left; // [AM] .cast2sigint(); @@ -499,6 +507,15 @@ public Expr visit(ExprBadJoin x) throws Err { return process(x.pos, x.closingBracket, right.pos, ((ExprChoice) right).choices, ((ExprChoice) right).reasons, left); } + public static Expr ignoreNoops(Expr e){ + if (e instanceof ExprUnary){ + ExprUnary eu = (ExprUnary) e; + if( eu.op == Op.NOOP){ + return ignoreNoops(eu.sub); + } + } + return e; + } /** {@inheritDoc} */ @Override public Expr visit(ExprBinary x) throws Err { @@ -506,8 +523,13 @@ public Expr visit(ExprBinary x) throws Err { Expr right = visitThis(x.right); if (x.op == ExprBinary.Op.JOIN) { // If it's a macro invocation, instantiate it - if (right instanceof Macro) - return ((Macro) right).addArg(left).instantiate(this, warns); + Expr rightInner = ignoreNoops(right); + if (rightInner instanceof Macro){ + Expr instantiated = ((Macro) rightInner).addArg(left).instantiate(this, warns); + Expr res = ExprUnary.Op.NOOP.make(right.pos, instantiated); + res.setReferenced(right.referenced()); + return res; + } // check to see if it is the special builtin function "Int[]" if (left.type().is_int() && right.isSame(Sig.SIGINT)) return left; // [AM] .cast2sigint(); @@ -632,20 +654,9 @@ public Expr visit(ExprVar x) throws Err { if (obj instanceof Macro) { Macro macro = ((Macro) obj).copy(); Expr instantiated = macro.instantiate(this, warns); - instantiated.setReferenced(new Clause() { - - @Override - public Pos pos() { - return instantiated.pos; - } - - @Override - public String explain() { - return instantiated.toString(); - } - - }); - return instantiated; + Expr res = ExprUnary.Op.NOOP.make(x.pos, instantiated); + res.setReferenced(new Clause.Custom(macro.pos, macro.toString())); + return res; } else return obj; } @@ -674,6 +685,21 @@ public Expr visit(Sig x) { return x; } + @Override + public Expr visit(Func x) throws Err { + return x; + } + + @Override + public Expr visit(Assert x) throws Err { + return x; + } + + @Override + public Expr visit(Macro x) throws Err { + return x; + } + /** {@inheritDoc} */ @Override public Expr visit(Field x) { @@ -890,9 +916,9 @@ public String getHTML() { } if (asserts.size() > 0) { x = new ArrayList(asserts.size()); - for (Map.Entry e : asserts.entrySet()) { - Pos sp = e.getValue().span(); - x.add(make(sp, sp, "assert " + e.getKey(), e.getValue())); + for (Map.Entry e : asserts.entrySet()) { + Pos sp = e.getValue().expr.span(); + x.add(make(sp, sp, "assert " + e.getKey(), e.getValue().expr)); } ans.add(make("" + x.size() + (x.size() > 1 ? " asserts" : " assert"), x)); } @@ -933,7 +959,7 @@ static ErrorSyntax hint(Pos pos, String name) { } /** - * Parse one expression by starting fromt this module as the root module. + * Parse one expression by starting from this module as the root module. */ @Override public Expr parseOneExpressionFromString(String input) throws Err, FileNotFoundException, IOException { @@ -993,7 +1019,7 @@ private Object unique(Pos pos, String name, List objs) throws Err { } else if (x instanceof Func) { Func y = (Func) x; msg.append(y.isPred ? "pred " : "fun ").append(y.label).append("\n" + "at ").append(y.pos.toShortString()); - } else if (x instanceof Expr) { + } else if (x instanceof Assert) { Expr y = (Expr) x; msg.append("assertion at ").append(y.pos.toShortString()); } @@ -1095,7 +1121,7 @@ private List getRawNQS(CompModule start, final int r, String name) { ans.add(x); } if ((r & 2) != 0) { - Expr x = m.asserts.get(name); + Assert x = m.asserts.get(name); if (x != null) ans.add(x); } @@ -1130,7 +1156,7 @@ private List getRawQS(final int r, String name) { ans.add(x); } if ((r & 2) != 0) { - Expr x = u.asserts.get(name); + Assert x = u.asserts.get(name); if (x != null) ans.add(x); } @@ -1241,7 +1267,7 @@ void addModelName(Pos pos, String moduleName, List list) throws Err { String name = expr.label; dup(expr.span(), name, true); if (path.length() == 0) { - Sig newSig = addSig(name, null, null, null, null, WHERE.make(expr.span())); + Sig newSig = addSig(null, name, null, null, null, null, WHERE.make(expr.span())); if (nextIsExact) exactSigs.add(newSig); } else { @@ -1447,7 +1473,8 @@ void addGhostSig() throws Err { sigs.put(Sig.GHOST.label, Sig.GHOST); } - Sig addSig(String name, ExprVar par, List parents, List fields, Expr fact, Attr... attributes) throws Err { + Sig addSig(Pos namePos, String name, ExprVar par, List parents, List fields, Expr fact, Attr... attributes) throws Err { + Sig obj; Pos pos = Pos.UNKNOWN.merge(WHERE.find(attributes)); status = 3; @@ -1469,14 +1496,15 @@ Sig addSig(String name, ExprVar par, List parents, List fields, E if (subset != null) { attributes = Util.append(attributes, SUBSET.makenull(subset)); List newParents = new ArrayList(parents == null ? 0 : parents.size()); - if (parents != null) - for (ExprVar p : parents) - newParents.add(new PrimSig(p.label, WHERE.make(p.pos))); - obj = new SubsetSig(full, newParents, attributes); + if (parents == null) parents = Arrays.asList(); + for (ExprVar p : parents) + newParents.add(new PrimSig(p.label, WHERE.make(p.pos))); + obj = new SubsetSig(namePos, full, parents.stream().map(p -> p.pos).collect(Collectors.toList()), newParents, attributes); } else { attributes = Util.append(attributes, SUBSIG.makenull(subsig)); PrimSig newParent = (parents != null && parents.size() > 0) ? (new PrimSig(parents.get(0).label, WHERE.make(parents.get(0).pos))) : UNIV; - obj = new PrimSig(full, newParent, attributes); + Pos parentPos = (parents != null && parents.size() > 0) ? parents.get(0).pos : Pos.UNKNOWN; + obj = new PrimSig(namePos, full, parentPos, newParent, attributes); } sigs.put(name, obj); old2fields.put(obj, fields); @@ -1491,9 +1519,9 @@ void addEnum(Pos pos, Pos priv, ExprVar name, List atoms, Pos closingBr List THESE = Arrays.asList(THIS); if (atoms == null || atoms.size() == 0) throw new ErrorSyntax(pos, "Enumeration must contain at least one name."); - addSig(name.label, null, null, null, null, WHERE.make(name.pos), ABSTRACT.make(name.pos), PRIVATE.makenull(priv), Attr.ENUM); + addSig(null, name.label, null, null, null, null, WHERE.make(name.pos), ABSTRACT.make(name.pos), PRIVATE.makenull(priv), Attr.ENUM); for (ExprVar a : atoms) - addSig(a.label, EXTENDS, THESE, null, null, WHERE.make(a.pos), ONE.make(a.pos), PRIVATE.makenull(priv)); + addSig(null, a.label, EXTENDS, THESE, null, null, WHERE.make(a.pos), ONE.make(a.pos), PRIVATE.makenull(priv)); int oldStatus = status; status = 0; try { @@ -1520,18 +1548,20 @@ private static Sig resolveSig(CompModule res, Set topo, Sig oldS, final throw new ErrorType(pos, "Sig " + oldS + " is involved in a cyclic inheritance."); if (oldS instanceof SubsetSig) { List parents = new ArrayList(); - for (Sig n : ((SubsetSig) oldS).parents) { + SubsetSig oldSS = (SubsetSig) oldS; + for (Sig n : oldSS.parents) { Sig parentAST = u.getRawSIG(n.pos, n.label); if (parentAST == null) throw new ErrorSyntax(n.pos, "The sig \"" + n.label + "\" cannot be found."); parents.add(resolveSig(res, topo, parentAST, warns)); } - realSig = new SubsetSig(fullname, parents, oldS.attributes.toArray(new Attr[0])); + realSig = new SubsetSig(oldSS.pos, fullname, oldSS.parentRefPoss, parents, oldS.attributes.toArray(new Attr[0])); for (Sig n : parents) if (n != UNIV && n.isVariable != null && realSig.isVariable == null) warns.add(new ErrorWarning(realSig.isSubset, "Part of " + n.label + " is static.\n" + "Sig " + realSig.label + " is static but " + n.label + " is variable.")); } else { - Sig sup = ((PrimSig) oldS).parent; + PrimSig oldSP = (PrimSig) oldS; + Sig sup = oldSP.parent; Sig parentAST = u.getRawSIG(sup.pos, sup.label); if (parentAST == null) throw new ErrorSyntax(sup.pos, "The sig \"" + sup.label + "\" cannot be found."); @@ -1539,7 +1569,7 @@ private static Sig resolveSig(CompModule res, Set topo, Sig oldS, final if (!(parent instanceof PrimSig)) throw new ErrorSyntax(sup.pos, "Cannot extend the subset signature \"" + parent + "\".\n" + "A signature can only extend a toplevel signature or a subsignature."); PrimSig p = (PrimSig) parent; - realSig = new PrimSig(fullname, p, oldS.attributes.toArray(new Attr[0])); + realSig = new PrimSig(oldSP.labelPos, fullname, oldSP.parentRefPos, p, oldS.attributes.toArray(new Attr[0])); if (parent != UNIV && parent.isVariable != null && realSig.isVariable == null) warns.add(new ErrorWarning(realSig.isSubsig, "Part of " + parent.label + " is static.\n" + "Sig " + realSig.label + " is static but " + parent.label + " is variable.")); if (parent != UNIV && parent.isVariable == null && realSig.isVariable != null) @@ -1573,26 +1603,30 @@ public SafeList getAllSigs() { // ============================================================================================================================// /** Add a MACRO declaration. */ - void addMacro(Pos p, Pos isPrivate, String n, List decls, Expr v) throws Err { + void addMacro(Pos p, Pos isPrivate, Pos labelPos, String label, List decls, Expr v) throws Err { if (!Version.experimental) throw new ErrorSyntax(p, "LET declaration is allowed only inside a toplevel paragraph."); ConstList ds = ConstList.make(decls); status = 3; - dup(p, n, false); + dup(p, label, false); for (int i = 0; i < ds.size(); i++) for (int j = i + 1; j < ds.size(); j++) if (ds.get(i).label.equals(ds.get(j).label)) throw new ErrorSyntax(ds.get(j).span(), "The parameter name \"" + ds.get(j).label + "\" cannot appear more than once."); - Macro ans = new Macro(p, isPrivate, this, n, ds, v); - Macro old = macros.put(n, ans); + Macro ans = new Macro(p, isPrivate, this, labelPos, label, ds, v); + Macro old = macros.put(label, ans); if (old != null) { - macros.put(n, old); - throw new ErrorSyntax(p, "You cannot declare more than one macro with the same name \"" + n + "\" in the same file."); + macros.put(label, old); + throw new ErrorSyntax(p, "You cannot declare more than one macro with the same name \"" + label + "\" in the same file."); } } + public SafeList getAllMacros() { + return new SafeList(macros.values()); + } + /** Add a FUN or PRED declaration. */ - void addFunc(Pos p, Pos isPrivate, String n, Expr f, List decls, Expr t, Expr v) throws Err { + void addFunc(Pos p, Pos isPrivate, ExprVar n, Expr f, List decls, Expr t, Expr v) throws Err { if (decls == null) decls = new ArrayList(); else @@ -1610,15 +1644,15 @@ void addFunc(Pos p, Pos isPrivate, String n, Expr f, List decls, Expr t, E } } status = 3; - dup(p, n, false); + dup(p, n.label, false); ExprHasName dup = Decl.findDuplicateName(decls); if (dup != null) throw new ErrorSyntax(dup.span(), "The parameter name \"" + dup.label + "\" cannot appear more than once."); - Func ans = new Func(p, isPrivate, n, decls, t, v); - ArrayList list = funcs.get(n); + Func ans = new Func(p, isPrivate, n.pos, n.label, decls, t, v); + ArrayList list = funcs.get(n.label); if (list == null) { list = new ArrayList(); - funcs.put(n, list); + funcs.put(n.label, list); } list.add(ans); } @@ -1663,7 +1697,7 @@ private JoinableList resolveFuncDecls(A4Reporter rep, JoinableList err if (err) continue; try { - f = new Func(f.pos, f.isPrivate, fullname, tmpdecls.makeConst(), ret, f.getBody()); + f = new Func(f.pos, f.isPrivate, f.labelPos, fullname, tmpdecls.makeConst(), ret, f.getBody()); list.set(listi, f); rep.typecheck("" + f + ", RETURN: " + f.returnDecl.type() + "\n"); } catch (Err ex) { @@ -1727,12 +1761,12 @@ public SafeList getAllFunc() { // ============================================================================================================================// /** Add an ASSERT declaration. */ - String addAssertion(Pos pos, String name, Expr value) throws Err { + String addAssertion(Pos pos, Pos labelPos, String name, Expr value) throws Err { status = 3; if (name == null || name.length() == 0) name = "assert$" + (1 + asserts.size()); dup(pos, name, false); - Expr old = asserts.put(name, ExprUnary.Op.NOOP.make(value.span().merge(pos), value)); + Assert old = asserts.put(name, new Assert(pos.merge(value.span()), labelPos, name, ExprUnary.Op.NOOP.make(value.span(), value))); if (old != null) { asserts.put(name, old); throw new ErrorSyntax(pos, "\"" + name + "\" is already the name of an assertion in this module."); @@ -1746,11 +1780,12 @@ String addAssertion(Pos pos, String name, Expr value) throws Err { */ private JoinableList resolveAssertions(A4Reporter rep, JoinableList errors, List warns) throws Err { Context cx = new Context(this, warns); - for (Map.Entry e : asserts.entrySet()) { - Expr expr = e.getValue(); + for (Map.Entry e : asserts.entrySet()) { + Assert _assert = e.getValue(); + Expr expr = _assert.expr; expr = cx.check(expr).resolve_as_formula(warns); if (expr.errors.isEmpty()) { - e.setValue(expr); + e.setValue(new Assert(_assert.pos, _assert.labelPos, _assert.label, expr)); rep.typecheck("Assertion " + e.getKey() + ": " + expr.type() + "\n"); } else errors = errors.make(expr.errors); @@ -1762,10 +1797,10 @@ private JoinableList resolveAssertions(A4Reporter rep, JoinableList er * Return an unmodifiable list of all assertions in this module. */ @Override - public ConstList> getAllAssertions() { - TempList> ans = new TempList>(asserts.size()); - for (Map.Entry e : asserts.entrySet()) { - ans.add(new Pair(e.getKey(), e.getValue())); + public ConstList getAllAssertions() { + TempList ans = new TempList(asserts.size()); + for (Assert a : asserts.values()) { + ans.add(a); } return ans.makeConst(); } @@ -1851,7 +1886,8 @@ public Expr getAllReachableFacts() { // ============================================================================================================================// /** Add a COMMAND declaration. */ - void addCommand(boolean followUp, Pos pos, ExprVar name, boolean check, int overall, int bitwidth, int seq, int tmn, int tmx, int exp, List scopes, ExprVar label) throws Err { + void addCommand(boolean followUp, Pos pos, ExprVar name, ExprVar commandKeyword, int overall, int bitwidth, int seq, int tmn, int tmx, int exp, List scopes, ExprVar label) throws Err { + boolean check = commandKeyword.label.equals("c"); if (followUp && !Version.experimental) throw new ErrorSyntax(pos, "Syntax error encountering => symbol."); if (label != null) @@ -1863,7 +1899,7 @@ void addCommand(boolean followUp, Pos pos, ExprVar name, boolean check, int over throw new ErrorSyntax(pos, "Predicate/assertion name cannot contain \'@\'"); String labelName = (label == null || label.label.length() == 0) ? name.label : label.label; Command parent = followUp ? commands.get(commands.size() - 1) : null; - Command newcommand = new Command(pos, name, labelName, check, overall, bitwidth, seq, tmn, tmx, exp, scopes, null, name, parent); + Command newcommand = new Command(pos, name, labelName, check, overall, bitwidth, seq, tmn, tmx, exp, scopes, null, commandKeyword, name, parent); if (parent != null) commands.set(commands.size() - 1, newcommand); else @@ -1871,8 +1907,8 @@ void addCommand(boolean followUp, Pos pos, ExprVar name, boolean check, int over } /** Add a COMMAND declaration. */ - void addCommand(boolean followUp, Pos pos, Expr e, boolean check, int overall, int bitwidth, int seq, int tmn, int tmx, int expects, List scopes, ExprVar label) throws Err { - + void addCommand(boolean followUp, Pos pos, Expr e, ExprVar commandKeyword, int overall, int bitwidth, int seq, int tmn, int tmx, int expects, List scopes, ExprVar label) throws Err { + boolean check = commandKeyword.label.equals("c"); if (followUp && !Version.experimental) throw new ErrorSyntax(pos, "Syntax error encountering => symbol."); @@ -1882,12 +1918,12 @@ void addCommand(boolean followUp, Pos pos, Expr e, boolean check, int overall, i status = 3; String n; if (check) - n = addAssertion(pos, "check$" + (1 + commands.size()), e); + n = addAssertion(pos, null, "check$" + (1 + commands.size()), e); else - addFunc(e.span().merge(pos), Pos.UNKNOWN, n = "run$" + (1 + commands.size()), null, new ArrayList(), null, e); + addFunc(e.span().merge(pos), Pos.UNKNOWN, ExprVar.make( Pos.UNKNOWN, n = "run$" + (1 + commands.size())), null, new ArrayList(), null, e); String labelName = (label == null || label.label.length() == 0) ? n : label.label; Command parent = followUp ? commands.get(commands.size() - 1) : null; - Command newcommand = new Command(e.span().merge(pos), e, labelName, check, overall, bitwidth, seq, tmn, tmx, expects, scopes, null, ExprVar.make(null, n), parent); + Command newcommand = new Command(e.span().merge(pos), e, labelName, check, overall, bitwidth, seq, tmn, tmx, expects, scopes, null, commandKeyword, ExprVar.make(null, n), parent); if (parent != null) commands.set(commands.size() - 1, newcommand); else @@ -1896,8 +1932,9 @@ void addCommand(boolean followUp, Pos pos, Expr e, boolean check, int overall, i public void addDefaultCommand() { if (commands.isEmpty()) { - addFunc(Pos.UNKNOWN, Pos.UNKNOWN, "$$Default", null, new ArrayList(), null, ExprConstant.TRUE); - commands.add(new Command(Pos.UNKNOWN, ExprConstant.TRUE, "Default", false, 4, 4, 4, -1, -1, 1, null, null, ExprVar.make(null, "$$Default"), null)); + addFunc(Pos.UNKNOWN, Pos.UNKNOWN, ExprVar.make(Pos.UNKNOWN, "$$Default"), null, new ArrayList(), null, ExprConstant.TRUE); + ExprVar check = ExprVar.make(Pos.UNKNOWN, "check"); + commands.add(new Command(Pos.UNKNOWN, ExprConstant.TRUE, "Default", false, 4, 4, 4, -1, -1, 1, null, null, check, ExprVar.make(null, "$$Default"), null)); } } @@ -1917,7 +1954,14 @@ private Command resolveCommand(Command cmd, ConstList exactSigs, Expr globa if (m.size() < 1) throw new ErrorSyntax(cmd.pos, "The assertion \"" + cname + "\" cannot be found."); - Expr expr = (Expr) (m.get(0)); + Expr expr; + if (m.get(0) instanceof Assert){ + Assert _assert = (Assert) m.get(0); + expr = _assert.expr; + declaringClause = _assert; + }else{ + expr = (Expr) m.get(0); + } e = expr.not(); } else { List m = getRawQS(4, cname); // We prefer fun/pred in the @@ -1947,13 +1991,13 @@ private Command resolveCommand(Command cmd, ConstList exactSigs, Expr globa throw new ErrorSyntax(cmd.pos, "Mutable sig " + et.sig + " is not top-level thus cannot have scopes assigned."); if (et.isExact && s.isVariable != null) throw new ErrorSyntax(cmd.pos, "Sig " + et.sig + " is variable thus scope cannot be exact."); - sc.add(new CommandScope(null, s, et.isExact, et.startingScope, et.endingScope, et.increment)); + sc.add(new CommandScope(et.pos, et.sigPos, s, et.isExact, et.startingScope, et.endingScope, et.increment)); } if (cmd.nameExpr != null) { cmd.nameExpr.setReferenced(declaringClause); } - return new Command(cmd.pos, cmd.nameExpr, cmd.label, cmd.check, cmd.overall, cmd.bitwidth, cmd.maxseq, cmd.minprefix, cmd.maxprefix, cmd.expects, sc.makeConst(), exactSigs, globalFacts.and(e), parent); + return new Command(cmd.pos, cmd.nameExpr, cmd.label, cmd.check, cmd.overall, cmd.bitwidth, cmd.maxseq, cmd.minprefix, cmd.maxprefix, cmd.expects, sc.makeConst(), exactSigs, cmd.commandKeyword, globalFacts.and(e), parent); } @@ -2024,10 +2068,10 @@ private static void resolveFieldDecl(CompModule res, final A4Reporter rep, final cx.put("this", s.decl.get()); Expr bound = cx.check(d.expr).resolve_as_set(warns); cx.remove("this"); - String[] names = new String[d.names.size()]; - for (int i = 0; i < names.length; i++) - names[i] = d.names.get(i).label; - Field[] fields = s.addTrickyField(d.span(), d.isPrivate, d.disjoint, d.disjoint2, null, d.isVar, names, bound); + // String[] names = new String[d.names.size()]; + // for (int i = 0; i < names.length; i++) + // names[i] = d.names.get(i).label; + Field[] fields = s.addTrickyField(d.span(), d.isPrivate, d.disjoint, d.disjoint2, null, d.isVar, d.names, bound); final VisitQuery q = new VisitQuery() { @Override @@ -2039,9 +2083,9 @@ public final Sig visit(Sig x) { } }; Sig qr = q.visitThis(bound); - if (d.isVar == null && qr != null) + if (d.isVar == null && qr != null) warns.add(new ErrorWarning(d.span(), "Static field types with variable bound.\n" + "Field " + d.names.get(0) + " is static but " + qr.label + " is variable.")); - if (d.isVar == null && s.isVariable != null) + if (d.isVar == null && s.isVariable != null) warns.add(new ErrorWarning(d.span(), "Static field inside variable sig.\n" + "Field " + d.names.get(0) + " is static but " + s.label + " is variable.")); for (Field f : fields) { rep.typecheck("Sig " + s + ", Field " + f.label + ": " + f.type() + "\n"); @@ -2088,7 +2132,7 @@ private static void resolveMeta(final CompModule root) throws Err { for (CompModule m : root.allModules) for (Sig s : new ArrayList(m.sigs.values())) if (m != root || (s != root.metaSig && s != root.metaField)) { - PrimSig ka = new PrimSig(s.label + "$", root.metaSig, Attr.ONE, PRIVATE.makenull(s.isPrivate), Attr.META); + PrimSig ka = new PrimSig(Pos.UNKNOWN, s.label + "$", Pos.UNKNOWN, root.metaSig, Attr.ONE, PRIVATE.makenull(s.isPrivate), Attr.META); sig2meta.put(s, ka); ka.addDefinedField(Pos.UNKNOWN, null, Pos.UNKNOWN, "value", s); m.new2old.put(ka, ka); @@ -2099,7 +2143,7 @@ private static void resolveMeta(final CompModule root) throws Err { Pos priv = field.isPrivate; if (priv == null) priv = s.isPrivate; - PrimSig kb = new PrimSig(s.label + "$" + field.label, root.metaField, Attr.ONE, PRIVATE.makenull(priv), Attr.META); + PrimSig kb = new PrimSig(Pos.UNKNOWN, s.label + "$" + field.label, Pos.UNKNOWN, root.metaField, Attr.ONE, PRIVATE.makenull(priv), Attr.META); field2meta.put(field, kb); m.new2old.put(kb, kb); m.sigs.put(base(kb), kb); @@ -2413,6 +2457,14 @@ public T visitExpressions(VisitReturn visitor) { d.expr.accept(visitor); }); s.getFacts().forEach(f -> f.accept(visitor)); + + if(s instanceof SubsetSig){ + SubsetSig ss = (SubsetSig) s; + ss.parentRefs().forEach( p -> p.accept(visitor)); + }else{ + PrimSig ps = (PrimSig) s; + ps.parentRef().accept(visitor); + } }); funcs.values().forEach(funs -> { @@ -2430,6 +2482,7 @@ public T visitExpressions(VisitReturn visitor) { }); asserts.values().forEach(assrt -> { assrt.accept(visitor); + assrt.expr.accept(visitor); }); commands.forEach(cmd -> { if (cmd.nameExpr != null) @@ -2445,13 +2498,81 @@ public T visitExpressions(VisitReturn visitor) { if (open.expressions != null) open.expressions.stream().filter(x -> x != null).forEach(ex -> ex.accept(visitor)); }); + + // macros are not visitable for now ( accept() throws an exception) macros.values().forEach(macro -> { - macro.accept(visitor); + macro.accept(visitor); }); params.values().forEach(x -> x.accept(visitor)); return null; } + interface Action{ void call();} + private void tryIgnore(Action action) {try { action.call();} catch(Exception ex) {}} + + public void visitExpressionsResilient(VisitReturn visitor) { + sigs.values().forEach(s -> { + s.accept(visitor); + s.getFieldDecls().forEach(d -> { + d.names.forEach(x -> tryIgnore(() -> x.accept(visitor))); + tryIgnore( () -> d.expr.accept(visitor)); + }); + s.getFacts().forEach(f -> tryIgnore(() -> f.accept(visitor))); + + if(s instanceof SubsetSig){ + SubsetSig ss = (SubsetSig) s; + ss.parentRefs().forEach( p -> tryIgnore( () -> p.accept(visitor))); + }else { + PrimSig ps = (PrimSig) s; + tryIgnore ( () -> ps.parentRef().accept(visitor)); + } + + }); + + funcs.values().forEach(funs -> { + funs.forEach(fun -> { + + //System.out.println("visiting func " + fun.label + ". label pos: " + fun.labelExpr().pos); + //tryIgnore ( () -> fun.labelExpr().accept(visitor)); + fun.accept(visitor); + fun.getBody().accept(visitor); + fun.decls.forEach(d -> { + tryIgnore( () -> d.expr.accept(visitor)); + d.names.forEach(n -> tryIgnore ( () -> n.accept(visitor))); + }); + tryIgnore( () -> fun.returnDecl.accept(visitor)); + }); + }); + facts.forEach(fact -> { + tryIgnore ( () -> fact.b.accept(visitor)); + }); + asserts.values().forEach(assrt -> { + tryIgnore ( () -> assrt.accept(visitor)); + tryIgnore ( () -> assrt.expr.accept(visitor)); + }); + commands.forEach(cmd -> { + if (cmd.nameExpr != null) + tryIgnore ( () -> cmd.nameExpr.accept(visitor)); + + cmd.additionalExactScopes.forEach(sig -> tryIgnore( () -> sig.accept(visitor))); + tryIgnore( () -> cmd.formula.accept(visitor)); + cmd.scope.forEach(scope -> { + tryIgnore( () -> scope.sigRef().accept(visitor)); + }); + }); + opens.values().forEach(open -> { + if (open.expressions != null) + open.expressions.stream().filter(x -> x != null).forEach(ex -> tryIgnore( () -> ex.accept(visitor))); + }); + + // macros are not visitable for now ( accept() throws an exception) + macros.values().forEach(macro -> { + tryIgnore( () -> macro.accept(visitor)); + }); + params.values().forEach(x -> tryIgnore( () -> x.accept(visitor))); + } + + public Expr find(Pos pos) { if (pos == null) return null; @@ -2463,7 +2584,7 @@ class Holder { } Holder holder = new Holder(); - visitExpressions(new VisitQueryOnce() { + visitExpressionsResilient(new VisitQueryOnce() { @Override public boolean visited(Expr expr) { diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompUtil.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompUtil.java index 65f04d3e1..ff1190e07 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompUtil.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompUtil.java @@ -498,4 +498,8 @@ static CompModule parse(List seenDollar, Map loaded, Map< module.addDefaultCommand(); return module; } + + public static CompModule nullModule() { + return new CompModule(null, "", ""); + } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/Macro.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/Macro.java index 5dc8fa7b1..1f8689ade 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/Macro.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/Macro.java @@ -30,11 +30,12 @@ import edu.mit.csail.sdg.ast.ExprBad; import edu.mit.csail.sdg.ast.ExprCustom; import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.VisitReturn; import edu.mit.csail.sdg.parser.CompModule.Context; /** Immutable; this class represents a macro. */ -final class Macro extends ExprCustom { +public final class Macro extends ExprCustom { /** If nonnull, this is a private macro. */ final Pos isPrivate; @@ -43,7 +44,9 @@ final class Macro extends ExprCustom { private final CompModule realModule; /** The name of the macro. */ - private final String name; + public final String name; + + public final Pos namePos; /** The list of parameters (can be an empty list) */ private final ConstList params; @@ -52,33 +55,34 @@ final class Macro extends ExprCustom { * The list of arguments (can be an empty list) (must be equal or shorter than * this.params) */ - private final ConstList args; + public final ConstList args; /** The macro body. */ - private final Expr body; + public final Expr body; /** Construct a new Macro object. */ - private Macro(Pos pos, Pos isPrivate, CompModule realModule, String name, List params, List args, Expr body) { + private Macro(Pos pos, Pos isPrivate, CompModule realModule, Pos namePos, String name, List params, List args, Expr body) { super(pos, new ErrorFatal(pos, "Incomplete call on the macro \"" + name + "\"")); this.realModule = realModule; this.isPrivate = isPrivate; this.name = name; + this.namePos = namePos; this.params = ConstList.make(params); this.args = ConstList.make(args); this.body = body; } /** Construct a new Macro object. */ - Macro(Pos pos, Pos isPrivate, CompModule realModule, String name, List params, Expr body) { - this(pos, isPrivate, realModule, name, params, null, body); + Macro(Pos pos, Pos isPrivate, CompModule realModule, Pos namePos, String name, List params, Expr body) { + this(pos, isPrivate, realModule, namePos, name, params, null, body); } Macro addArg(Expr arg) { - return new Macro(pos, isPrivate, realModule, name, params, Util.append(args, arg), body); + return new Macro(pos, isPrivate, realModule, namePos, name, params, Util.append(args, arg), body); } Expr changePos(Pos pos) { - return new Macro(pos, isPrivate, realModule, name, params, args, body); + return new Macro(pos, isPrivate, realModule, namePos, name, params, args, body); } /** @@ -132,7 +136,16 @@ public int getDepth() { /** {@inheritDoc} */ @Override public String toString() { - return name; + StringBuilder sb = new StringBuilder(); + sb.append(name); + if (! this.params.isEmpty()){ + sb.append("["); + sb.append( String.join(", ", this.params.stream().map(p -> p.label).toArray(String[]::new)) ); + sb.append("]"); + } + sb.append(" = "); + sb.append(this.body.toString()); + return sb.toString(); } /** {@inheritDoc} */ @@ -148,7 +161,12 @@ public String getHTML() { } public Macro copy() { - return new Macro(pos, isPrivate, realModule, name, params, args, body); + return new Macro(pos, isPrivate, realModule, namePos, name, params, args, body); } + + @Override + public T accept(VisitReturn visitor) throws Err { + return visitor.visit(this); + } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/MarkdownHandler.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/MarkdownHandler.java index a25f751b4..02ffc92ad 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/MarkdownHandler.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/MarkdownHandler.java @@ -78,7 +78,7 @@ public static String strip(String content) { while ((line = br.readLine()) != null) { state = state.process(line, yaml, alloy); if (state == null) - return content; + return ""; } } return alloy.toString(); diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/sim/SimInstance.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/sim/SimInstance.java index 407e6b710..99639e017 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/sim/SimInstance.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/sim/SimInstance.java @@ -37,6 +37,7 @@ import edu.mit.csail.sdg.alloy4.ErrorType; import edu.mit.csail.sdg.alloy4.Pair; import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.ast.Assert; import edu.mit.csail.sdg.ast.Decl; import edu.mit.csail.sdg.ast.Expr; import edu.mit.csail.sdg.ast.ExprBinary; @@ -56,6 +57,7 @@ import edu.mit.csail.sdg.ast.Sig.PrimSig; import edu.mit.csail.sdg.ast.Sig.SubsetSig; import edu.mit.csail.sdg.ast.VisitReturn; +import edu.mit.csail.sdg.parser.Macro; /** Mutable; represents an instance. */ @@ -912,6 +914,21 @@ public SimTupleset visit(Sig x) throws Err { throw new ErrorFatal("Unknown sig " + x + " encountered during evaluation."); } + @Override + public Object visit(Func x) throws Err { + return null; + } + + @Override + public Object visit(Assert x) throws Err { + return null; + } + + @Override + public Object visit(Macro x) throws Err { + return null; + } + /** {@inheritDoc} */ @Override public SimTupleset visit(Field x) throws Err { diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4SolutionReader.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4SolutionReader.java index ce191c022..5ed67403c 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4SolutionReader.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4SolutionReader.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -39,6 +40,7 @@ import edu.mit.csail.sdg.alloy4.XMLNode; import edu.mit.csail.sdg.ast.Attr; import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprHasName; import edu.mit.csail.sdg.ast.ExprVar; import edu.mit.csail.sdg.ast.Sig; import edu.mit.csail.sdg.ast.Sig.Field; @@ -217,7 +219,7 @@ private Sig parseSig(String id, int depth) throws IOException, Err { break; } if (ans == null) { - ans = new PrimSig(label, (PrimSig) parent, isAbstract, isLone, isOne, isSome, isPrivate, isMeta, isEnum, isVar); + ans = new PrimSig(null, label, Pos.UNKNOWN, (PrimSig) parent, isAbstract, isLone, isOne, isSome, isPrivate, isMeta, isEnum, isVar); allsigs.add(ans); } } else { @@ -228,7 +230,7 @@ private Sig parseSig(String id, int depth) throws IOException, Err { break; } if (ans == null) { - ans = new SubsetSig(label, parents, isExact, isLone, isOne, isSome, isPrivate, isMeta, isVar); + ans = new SubsetSig(null, label, null, parents, isExact, isLone, isOne, isSome, isPrivate, isMeta, isVar); allsigs.add(ans); } } @@ -302,10 +304,11 @@ private Field parseField(String id) throws IOException, Err { choices.remove(f); break; } - if (field == null) - field = parent.addTrickyField(Pos.UNKNOWN, isPrivate, null, null, isMeta, isVar, new String[] { - label - }, UNIV.join(type))[0]; + if (field == null){ + ExprHasName labelExpr = ExprVar.make(null, label); + field = parent.addTrickyField(Pos.UNKNOWN, isPrivate, null, null, isMeta, isVar, Arrays.asList(labelExpr) + , UNIV.join(type))[0]; + } TupleSet ts = parseTuples(node, arity); expr2ts.put(field, ts); return field; diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/ConvToConjunction.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/ConvToConjunction.java index 6ca1362d4..b090d65cf 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/ConvToConjunction.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/ConvToConjunction.java @@ -17,6 +17,7 @@ import edu.mit.csail.sdg.alloy4.Err; import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Assert; import edu.mit.csail.sdg.ast.Expr; import edu.mit.csail.sdg.ast.ExprBinary; import edu.mit.csail.sdg.ast.ExprCall; @@ -27,9 +28,11 @@ import edu.mit.csail.sdg.ast.ExprQt; import edu.mit.csail.sdg.ast.ExprUnary; import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Func; import edu.mit.csail.sdg.ast.Sig; import edu.mit.csail.sdg.ast.Sig.Field; import edu.mit.csail.sdg.ast.VisitReturn; +import edu.mit.csail.sdg.parser.Macro; /** * Immutable; this class rearranges the AST to promote as many clauses up to the @@ -122,6 +125,21 @@ public Expr visit(Sig x) { return x; } + @Override + public Expr visit(Func x) throws Err { + return x; + } + + @Override + public Expr visit(Assert x) throws Err { + return x; + } + + @Override + public Expr visit(Macro x) throws Err { + return x; + } + /** {@inheritDoc} */ @Override public Expr visit(Field x) { diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/TranslateAlloyToKodkod.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/TranslateAlloyToKodkod.java index 5f7825f8e..95765c113 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/TranslateAlloyToKodkod.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/TranslateAlloyToKodkod.java @@ -36,6 +36,7 @@ import edu.mit.csail.sdg.alloy4.Pair; import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.ast.Assert; import edu.mit.csail.sdg.ast.Command; import edu.mit.csail.sdg.ast.CommandScope; import edu.mit.csail.sdg.ast.Decl; @@ -55,6 +56,7 @@ import edu.mit.csail.sdg.ast.Sig.Field; import edu.mit.csail.sdg.ast.Type; import edu.mit.csail.sdg.ast.VisitReturn; +import edu.mit.csail.sdg.parser.Macro; import kodkod.ast.BinaryExpression; import kodkod.ast.Decls; import kodkod.ast.ExprToIntCast; @@ -821,7 +823,7 @@ public Object visit(ExprConstant x) throws Err { case EMPTYNESS : return Expression.NONE; case IDEN : - return Expression.IDEN.intersection(a2k(UNIV).product(Expression.UNIV)); + return Expression.IDEN.intersection(a2k(UNIV).product(Expression.UNIV)); //this makes bad decompositions, makes static expressions variable case STRING : Expression ans = s2k(x.string); if (ans == null) @@ -890,7 +892,7 @@ public Object visit(ExprUnary x) throws Err { case CAST2INT : return sum(cset(x.sub)); case RCLOSURE : - Expression iden = Expression.IDEN.intersection(a2k(UNIV).product(Expression.UNIV)); + Expression iden = Expression.IDEN.intersection(a2k(UNIV).product(Expression.UNIV)); //this makes bad decompositions, makes static expressions variable return cset(x.sub).closure().union(iden); case CLOSURE : return cset(x.sub).closure(); @@ -950,6 +952,21 @@ public Object visit(Sig x) throws Err { return ans; } + @Override + public Object visit(Func x) throws Err { + return null; + } + + @Override + public Object visit(Assert x) throws Err { + return null; + } + + @Override + public Object visit(Macro x) throws Err { + return null; + } + /* ============================= */ /* Evaluates an ExprCall node. */ /* ============================= */ diff --git a/org.alloytools.alloy.core/src/test/java/org/alloytools/alloy/core/AlloyModelsTest.java b/org.alloytools.alloy.core/src/test/java/org/alloytools/alloy/core/AlloyModelsTest.java index a2a367cf0..8362fac9d 100644 --- a/org.alloytools.alloy.core/src/test/java/org/alloytools/alloy/core/AlloyModelsTest.java +++ b/org.alloytools.alloy.core/src/test/java/org/alloytools/alloy/core/AlloyModelsTest.java @@ -6,6 +6,8 @@ import edu.mit.csail.sdg.alloy4.A4Reporter; import edu.mit.csail.sdg.ast.Command; import edu.mit.csail.sdg.ast.Module; +import edu.mit.csail.sdg.ast.VisitQuery; +import edu.mit.csail.sdg.ast.VisitReturn; import edu.mit.csail.sdg.parser.CompModule; import edu.mit.csail.sdg.parser.CompUtil; import edu.mit.csail.sdg.translator.A4Options; @@ -48,4 +50,40 @@ public void minimalAlloyDoc() throws Exception { return; } } + + + @Test + public void minimalAlloyDoc2() throws Exception { + CompModule world = CompUtil.parseEverything_fromString(A4Reporter.NOP, + //" \n" + + "let nx[foo] { foo.next }\n" + + "sig Foo { next: Foo} \n" + + "check TT{ some foo : Foo | some foo.next }\n"); + + + + VisitReturn visitor = new VisitQuery() {}; + world.getAllSigs().forEach(sig -> sig.accept(visitor)); + //world.getAllMacros().forEach(macro -> {macro.toString();}); + //world.getAllMacros().forEach(macro -> macro.accept(visitor)); + world.getAllCommands().forEach(cmd -> { + System.out.println("nameExpr:" + cmd.nameExpr.toString()); + System.out.println("formula: " + cmd.formula.toString()); + System.out.println("label: " + cmd.label); +// if (cmd.nameExpr != null) +// cmd.nameExpr.accept(visitor); + + //cmd.additionalExactScopes.forEach(sig -> sig.accept(visitor)); + cmd.formula.accept(visitor); +// cmd.scope.forEach(scope -> { +// scope.sig.accept(visitor); +// }); + + }); + //world.visitExpressions(new VisitQuery() {}); + + //Expr expr = world.find(new Pos(null, 12, 3, 15, 3)); + + } + } From 79bbdb2496db641d717ecf4a9a8dc9b0a526cf3e Mon Sep 17 00:00:00 2001 From: Nigel Kerr Date: Sun, 16 Jan 2022 14:32:06 -0500 Subject: [PATCH 002/129] Re-establishing code I wrote entirely myself from previous attempt. --- .../sdg/alloy4whole/PreferencesDialog.java | 2 ++ .../mit/csail/sdg/alloy4whole/SimpleGUI.java | 13 +++++++++++- .../mit/csail/sdg/alloy4/A4Preferences.java | 3 +++ .../mit/csail/sdg/alloy4/OurSyntaxWidget.java | 13 ++++++++++-- .../sdg/alloy4/OurTabbedSyntaxWidget.java | 21 ++++++++++++++++--- 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java index 499f47bb0..d3ce7ca32 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java @@ -10,6 +10,7 @@ import static edu.mit.csail.sdg.alloy4.A4Preferences.ImplicitThis; import static edu.mit.csail.sdg.alloy4.A4Preferences.InferPartialInstance; import static edu.mit.csail.sdg.alloy4.A4Preferences.LAF; +import static edu.mit.csail.sdg.alloy4.A4Preferences.LineNumbers; import static edu.mit.csail.sdg.alloy4.A4Preferences.NoOverflow; import static edu.mit.csail.sdg.alloy4.A4Preferences.RecordKodkod; import static edu.mit.csail.sdg.alloy4.A4Preferences.SkolemDepth; @@ -420,6 +421,7 @@ protected Component initEditorPane() { JPanel p = OurUtil.makeGrid(2, gbc().make(), mkCombo(FontName), mkCombo(FontSize), mkCombo(TabSize)); addToGrid(p, mkCheckBox(SyntaxDisabled), gbc().pos(0, 3).gridwidth(2)); addToGrid(p, mkCheckBox(AntiAlias), gbc().pos(0, 4).gridwidth(2)); + addToGrid(p, mkCheckBox(LineNumbers), gbc().pos(0, 5).gridwidth(2)); // JPanel p = new JPanel(new GridBagLayout()); // addToGrid(p, mkCheckBox(SyntaxDisabled), gbc().pos(0, diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java index 2fc53db2c..8a60a547e 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java @@ -29,6 +29,7 @@ import static edu.mit.csail.sdg.alloy4.A4Preferences.ImplicitThis; import static edu.mit.csail.sdg.alloy4.A4Preferences.InferPartialInstance; import static edu.mit.csail.sdg.alloy4.A4Preferences.LAF; +import static edu.mit.csail.sdg.alloy4.A4Preferences.LineNumbers; import static edu.mit.csail.sdg.alloy4.A4Preferences.Model0; import static edu.mit.csail.sdg.alloy4.A4Preferences.Model1; import static edu.mit.csail.sdg.alloy4.A4Preferences.Model2; @@ -1440,6 +1441,7 @@ private Runner doRefreshOption() { else addToMenu(optmenu, AntiAlias); addToMenu(optmenu, A4Preferences.LAF); + addToMenu(optmenu, LineNumbers); optmenu.addSeparator(); @@ -1493,6 +1495,14 @@ private Runner doOptRefreshFont() { return null; } + private Runner doOptRefreshLineNumbers() { + if ( wrap ) { + return wrapMe(); + } + text.enableLineNumbers(LineNumbers.get()); + return null; + } + /** This method toggles the "antialias" checkbox. */ private Runner doOptAntiAlias() { if (!wrap) { @@ -2220,7 +2230,7 @@ private void finishInit(String[] args, int width) { PreferencesDialog.logOnChange(log, A4Preferences.allUserPrefs().toArray(new Pref< ? >[0])); // Create the text area - text = new OurTabbedSyntaxWidget(fontName, fontSize, TabSize.get(), frame); + text = new OurTabbedSyntaxWidget(fontName, fontSize, TabSize.get(), LineNumbers.get(), frame); text.listeners.add(this); text.enableSyntax(!SyntaxDisabled.get()); @@ -2282,6 +2292,7 @@ private void finishInit(String[] args, int width) { prefDialog.addChangeListener(wrapToChangeListener(doOptAntiAlias()), AntiAlias); prefDialog.addChangeListener(wrapToChangeListener(doOptSyntaxHighlighting()), SyntaxDisabled); prefDialog.addChangeListener(wrapToChangeListener(doLookAndFeel()), LAF); + prefDialog.addChangeListener(wrapToChangeListener(doOptRefreshLineNumbers()), LineNumbers); } finally { wrap = false; } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java index 75365e8fc..8e4cd24b8 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java @@ -572,6 +572,9 @@ public void actionPerformed(ActionEvent e) { /** The latest tab distance of the Alloy Analyzer. */ public static final IntChoicePref TabSize = IntChoicePref.range("TabSize", "Tab size", 1, 1, 16, 4); + /** The latest line-number mode selection of the Alloy Analyzer. */ + public static final BooleanPref LineNumbers = new BooleanPref("Line-numbers", "Show line numbers in editors"); + /** The latest welcome screen that the user has seen. */ public static final BooleanPref Welcome = new BooleanPref("Welcome", "Show welcome message at start up"); diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java index 002607726..9d650e06d 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java @@ -124,7 +124,7 @@ public final class OurSyntaxWidget { * Constructs a syntax-highlighting widget. */ public OurSyntaxWidget(OurTabbedSyntaxWidget parent) { - this(parent, true, "", "Monospaced", 14, 4, null, null); + this(parent, true, "", "Monospaced", 14, 4, false, null, null); } /** @@ -133,7 +133,7 @@ public OurSyntaxWidget(OurTabbedSyntaxWidget parent) { * @param parent */ @SuppressWarnings("serial" ) - public OurSyntaxWidget(OurTabbedSyntaxWidget parent, boolean enableSyntax, String text, String fontName, int fontSize, int tabSize, JComponent obj1, JComponent obj2) { + public OurSyntaxWidget(OurTabbedSyntaxWidget parent, boolean enableSyntax, String text, String fontName, int fontSize, int tabSize, boolean lineNumbers, JComponent obj1, JComponent obj2) { pane.addKeyListener(new KeyListener() { @Override @@ -327,6 +327,9 @@ public void focusGained(FocusEvent e) { component.setFocusable(false); component.setMinimumSize(new Dimension(50, 50)); component.setViewportView(pane); + + // do our new thing here for line number display. + modified = false; } @@ -575,6 +578,10 @@ void enableSyntax(boolean flag) { doc.do_enableSyntax(flag); } + void enableLineNumbers(boolean flag) { + // something + } + /** * Return the number of lines represented by the current text (where partial * line counts as a line). @@ -865,4 +872,6 @@ public String getTooltip(MouseEvent event) { } return null; } + + } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurTabbedSyntaxWidget.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurTabbedSyntaxWidget.java index 5becd5587..b2cc396fd 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurTabbedSyntaxWidget.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurTabbedSyntaxWidget.java @@ -85,6 +85,11 @@ public final class OurTabbedSyntaxWidget { */ private boolean syntaxHighlighting; + /** + * Whether line numbers are currently enable to displayr or not. + */ + private boolean lineNumbers; + /** The list of clickable tabs. */ private final JPanel tabBar; @@ -157,7 +162,7 @@ public Object do_action(Object sender, Event e, Object arg) { private final JFrame parent; /** Constructs a tabbed editor pane. */ - public OurTabbedSyntaxWidget(String fontName, int fontSize, int tabSize, JFrame parent) { + public OurTabbedSyntaxWidget(String fontName, int fontSize, int tabSize, boolean lineNumbers, JFrame parent) { this.parent = parent; component.setBorder(null); component.setLayout(new BorderLayout()); @@ -174,6 +179,7 @@ public OurTabbedSyntaxWidget(String fontName, int fontSize, int tabSize, JFrame tabBarScroller.setFocusable(false); tabBarScroller.setBorder(null); setFont(fontName, fontSize, tabSize); + this.lineNumbers = lineNumbers; newtab(null); tabBarScroller.addComponentListener(new ComponentListener() { @@ -377,9 +383,18 @@ public void enableSyntax(boolean flag) { t.enableSyntax(flag); } + public void enableLineNumbers(boolean flag) { + lineNumbers = flag; + for ( OurSyntaxWidget t : tabs) { + t.enableLineNumbers(flag); + } + } + /** Returns the JTextArea of the current text buffer. */ public OurSyntaxWidget get() { - return (me >= 0 && me < tabs.size()) ? tabs.get(me) : new OurSyntaxWidget(this); + return (me >= 0 && me < tabs.size()) ? tabs.get(me) : + new OurSyntaxWidget(this, + syntaxHighlighting, "", fontName, fontSize, tabSize, lineNumbers, null, null); } /** @@ -438,7 +453,7 @@ public void mousePressed(MouseEvent e) { JPanel pan = Util.onMac() ? OurUtil.makeVL(null, 2, OurUtil.makeHB(h1, lb, h2)) : OurUtil.makeVL(null, 2, OurUtil.makeHB(h1, lb, h2, GRAY), GRAY); pan.setAlignmentX(0.0f); pan.setAlignmentY(1.0f); - OurSyntaxWidget text = new OurSyntaxWidget(this, syntaxHighlighting, "", fontName, fontSize, tabSize, lb, pan); + OurSyntaxWidget text = new OurSyntaxWidget(this, syntaxHighlighting, "", fontName, fontSize, tabSize, lineNumbers, lb, pan); tabBar.add(pan, tabs.size()); tabs.add(text); text.listeners.add(listener); // add listener AFTER we've updated From 1fa2626e97b0d6a8b616ae207d668e9d8a28a4a3 Mon Sep 17 00:00:00 2001 From: Nigel Kerr Date: Sun, 16 Jan 2022 15:59:50 -0500 Subject: [PATCH 003/129] Add Line-Numbers to the Alloy Editor Add line numbers to the editor display, configured with a preference, issue #79 "Feature Request: Line Numbers." The OurLineNumberWidget class is added, providing a rowHeader to the JScrollPane component of OurSyntaxWidget, based on data and events from the JTextPane pane also of OurSyntaxWidget. OurLineNumberWidget receives updates to the line-numbers preference, and also to the font-name and font-size preference, because we draw the line-number display in the same font as the main document. OurLineNumberWidget follows the anti-aliasing strategy expressed by the OurAntiAlias class, by anti-aliasing when we believe we are on a Mac or on Windows. The view of the line numbers scrolls with the contents of the text pane. The line of text where the caret is will have it's line number in yellow on a black background. The OurLineNumberWidget sets itself to 0 width, or a calculated width, depending on whether OurSyntaxWidget constructed or informs it later whether to display. The code itself does not place a restriction on how many lines there are in the file or displaying the current line number. The width of OurLineNumberWidget grows or shrinks depending on the current number to display with the most digits. This author has tested up to seven digits. The highlighting of the line of the caret could certainly be changed if there is need or preference. The preference for displaying line-numbers is in the Alloy Preferences window, in the Editor tab, at the end of the list of preferences there. The current value appears in the Options menu at the end of the third section, in the same section with the preferences from the Editor tab. Signed-off-by: Nigel Kerr --- .../csail/sdg/alloy4/OurLineNumberWidget.java | 277 ++++++++++++++++++ .../mit/csail/sdg/alloy4/OurSyntaxWidget.java | 10 +- 2 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java new file mode 100644 index 000000000..ca5baf266 --- /dev/null +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java @@ -0,0 +1,277 @@ +package edu.mit.csail.sdg.alloy4; + +import javax.swing.*; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; +import javax.swing.text.Utilities; +import java.awt.*; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.font.FontRenderContext; +import java.util.Collections; +import java.util.Objects; + +public class OurLineNumberWidget extends JComponent implements DocumentListener, CaretListener, ComponentListener { + + /** + * combine the two submitted objects with a new OurLineNumberWidget and return + * that widget. We assume that other code has already connected these components appropriately. + * + * While callers could send any fontName and size that they wanted, here in Allow in the context of + * the editor the assumption is that the font preference set by the user for the whole app is + * applying here as well, so OurSyntaxWidget will be sending the same font that it receives to use. + * + * @param textPane the text pane that has the lines we want to draw numbers for + * @param scrollPane the scroll pane we will set a header row for to draw the line numbers for textPane + * @param display line numbers should display if true, should not otherwise + * @param fontName the fontName to be used to draw line numbers. + * @return the OurLineNumberWidget linking the two components, with the display and font set. + */ + public static OurLineNumberWidget build(JTextPane textPane, JScrollPane scrollPane, boolean display, String fontName, int fontSize) { + Objects.requireNonNull(textPane); + Objects.requireNonNull(textPane.getDocument()); + Objects.requireNonNull(scrollPane); + Objects.requireNonNull(fontName); + if ( fontSize < 1 ) { + throw new IllegalArgumentException("Font size must be at least 1"); + } + + OurLineNumberWidget ourLineNumberWidget = new OurLineNumberWidget(textPane, display, fontName, fontSize); + scrollPane.setRowHeaderView(ourLineNumberWidget); + return ourLineNumberWidget; + } + + private static final boolean antiAlias = Util.onMac() || Util.onWindows(); + + private final JTextPane textPane; + private boolean display; + private String fontName; + private int fontSize; + private int width = 0; + private Font font; + /** assume we start showing 1 digit. */ + private int currentMaxDigits = 1; + private int descentAdjust; + + OurLineNumberWidget(JTextPane textPane, boolean display, String fontName, int fontSize) { + this.textPane = textPane; + this.display = display; + this.fontName = fontName; + this.fontSize = fontSize; + + // falls back to 'Dialog' on not being able to find. + this.font = new Font(this.fontName, Font.PLAIN, this.fontSize); + this.descentAdjust = makeDescentAdjust(); + + textPane.getDocument().addDocumentListener(this); + textPane.addComponentListener(this); + textPane.addCaretListener(this); + + update(); + } + + /** use current font to decide a width for the line-number view itself, + * based on how many digits are submitted. + * @param numberOfDigits + * @return + */ + private int calculateWidthForDigits(int numberOfDigits) { + if ( display ) { + String numberOfDigitsLong = String.join("", Collections.nCopies(numberOfDigits, "0")); + return (int)Math.ceil( + font.getStringBounds(numberOfDigitsLong, new FontRenderContext(null, false, false)).getWidth() * 1.2); + } else { + return 0; + } + } + + /** capture the descent of the current font, used to adjust (negative y) where the + * line number is drawn. Only needs to change when the font changes. + * @return + */ + private int makeDescentAdjust() { + return getFontMetrics(font).getDescent(); + } + + @Override + protected void paintComponent(final Graphics g) { + + if ( ! display ) { return; } + + if ( g instanceof Graphics2D && antiAlias ) { + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } + + super.paintComponent(g); + // antiAlias at some point + + Rectangle bounds = g.getClipBounds(); + final int startDocumentLocation = textPane.viewToModel(new Point(0, bounds.y)); + final int endDocumentLocation = textPane.viewToModel(new Point(0, bounds.y + bounds.height)); + + int docLoc = startDocumentLocation; + int maxDigits = 0; + + while ( docLoc <= endDocumentLocation ) { + try { + Element rootElement = textPane.getDocument().getDefaultRootElement(); + final int lineIndex = rootElement.getElementIndex(docLoc); + final Element line = rootElement.getElement(lineIndex); + if (line.getStartOffset() == docLoc) { + int x = niceX(); + int y = niceY(docLoc); + + String formattedLineNumber = formatLineNumberFromIndex(lineIndex); + if ( formattedLineNumber.length() > maxDigits ) { + maxDigits = formattedLineNumber.length(); + } + + g.setColor(Color.BLACK); + if (ifCaretOnSameLine(docLoc, rootElement)) { + Rectangle currentLineViewRec = textPane.modelToView(docLoc); + g.fillRect(0, currentLineViewRec.y, width, currentLineViewRec.height-1 ); + g.setColor(Color.YELLOW); + } + g.setFont(font); + g.drawString(formattedLineNumber, x, y); + } + docLoc = Utilities.getRowEnd(textPane, docLoc) + 1; + } catch (BadLocationException e) { + // what is the right thing to do here? + } + } + if ( maxDigits != currentMaxDigits ) { + currentMaxDigits = maxDigits; + update(); + } + } + + private boolean ifCaretOnSameLine(int docLoc, Element rootElement) { + return rootElement.getElementIndex(docLoc) == rootElement.getElementIndex(textPane.getCaretPosition()); + } + + /** a judgement about where in the x direction is good + * to start drawing the line number. + * @return + */ + private int niceX() { + return getInsets().left + 3; + } + + /** a judgement about where in the y direction is good + * to start drawing the line number for the given document location. + * @param docLoc + * @return + * @throws BadLocationException + */ + private int niceY(int docLoc) throws BadLocationException { + Rectangle viewRec = textPane.modelToView(docLoc); + return viewRec.y + viewRec.height - descentAdjust; + } + + private String formatLineNumberFromIndex(int lineIndex) { + return String.format("%d", (lineIndex + 1)); + } + + /** Make a new width value, set new current preferred size and size, + * and try to get this component repainted. + * Currently all listener events incur this, which might be more + * than strictly needed. + */ + private void update() { + width = calculateWidthForDigits(currentMaxDigits); + Dimension size = new Dimension(width, textPane.getHeight()); + setPreferredSize(size); + setSize(size); + SwingUtilities.invokeLater(this::repaint); + } + + // component listener events + @Override + public void componentResized(ComponentEvent e) { + update(); + } + + @Override + public void componentMoved(ComponentEvent e) { + update(); + } + + @Override + public void componentShown(ComponentEvent e) { + update(); + } + + @Override + public void componentHidden(ComponentEvent e) { + update(); + } + + // caret listener events + @Override + public void caretUpdate(CaretEvent e) { + update(); + } + + // document listener events + @Override + public void insertUpdate(DocumentEvent e) { + update(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + update(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + update(); + } + + /** + * Set whether this widget should display or not display line numbers, + * incur an update() call if there is a change. + * @param flag + */ + public void setDisplay(boolean flag) { + boolean oldDisplay = display; + this.display = flag; + if ( this.display != oldDisplay ) { + update(); + } + } + + /** + * Set the fontName and fontSize for this widget. If the + * submitted name and size amount to a change of the font itself, + * incure an update() call. + * @param fontName + * @param fontSize + */ + public void updateFontNameAndSize(String fontName, int fontSize) { + if ( fontSize < 1 ) { + if ( fontName == null || fontName.isEmpty() ) { + fontName = Font.MONOSPACED; + } + fontSize = 14; + } + String oldFontName = this.fontName; + int oldFontSize = this.fontSize; + + this.fontName = fontName; + this.fontSize = fontSize; + + if ( !this.fontName.equals(oldFontName) || this.fontSize != oldFontSize ) { + font = new Font(this.fontName, Font.PLAIN, this.fontSize); + descentAdjust = makeDescentAdjust(); + update(); + } + } + + +} diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java index 9d650e06d..104fd15a1 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java @@ -120,6 +120,8 @@ public final class OurSyntaxWidget { private volatile CompModule module; + private OurLineNumberWidget ourLineNumberWidget; + /** * Constructs a syntax-highlighting widget. */ @@ -328,7 +330,7 @@ public void focusGained(FocusEvent e) { component.setMinimumSize(new Dimension(50, 50)); component.setViewportView(pane); - // do our new thing here for line number display. + ourLineNumberWidget = OurLineNumberWidget.build(pane, component, lineNumbers, fontName, fontSize); modified = false; } @@ -568,8 +570,10 @@ public boolean isFile() { * Changes the font name, font size, and tab size for the document. */ void setFont(String fontName, int fontSize, int tabSize) { - if (doc != null) + if (doc != null) { doc.do_setFont(fontName, fontSize, tabSize); + ourLineNumberWidget.updateFontNameAndSize(fontName, fontSize); + } } /** Enables or disables syntax highlighting. */ @@ -579,7 +583,7 @@ void enableSyntax(boolean flag) { } void enableLineNumbers(boolean flag) { - // something + ourLineNumberWidget.setDisplay(flag); } /** From 737269493ec2c93f7b12920d41286a3a8dbc77ba Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Tue, 4 Jan 2022 16:18:33 +0100 Subject: [PATCH 004/129] [api] project ... We need to start separating the Api and implementations. There is a PR that has been deprecated since release 6 because of too many changes. This is a new start. Much of it can be salvaged. --- org.alloytools.api/.classpath | 12 + org.alloytools.api/.project | 23 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.core.runtime.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 456 ++++++++++++++++++ .../.settings/org.eclipse.jdt.ui.prefs | 131 +++++ org.alloytools.api/bnd.bnd | 4 + .../alloy/context/api/AlloyContext.java | 9 + .../alloy/context/api/package-info.java | 7 + .../alloy/infrastructure/api/AlloyMain.java | 41 ++ .../infrastructure/api/package-info.java | 7 + 11 files changed, 694 insertions(+) create mode 100644 org.alloytools.api/.classpath create mode 100644 org.alloytools.api/.project create mode 100644 org.alloytools.api/.settings/org.eclipse.core.resources.prefs create mode 100644 org.alloytools.api/.settings/org.eclipse.core.runtime.prefs create mode 100644 org.alloytools.api/.settings/org.eclipse.jdt.core.prefs create mode 100644 org.alloytools.api/.settings/org.eclipse.jdt.ui.prefs create mode 100644 org.alloytools.api/bnd.bnd create mode 100644 org.alloytools.api/src/main/java/org/alloytools/alloy/context/api/AlloyContext.java create mode 100644 org.alloytools.api/src/main/java/org/alloytools/alloy/context/api/package-info.java create mode 100644 org.alloytools.api/src/main/java/org/alloytools/alloy/infrastructure/api/AlloyMain.java create mode 100644 org.alloytools.api/src/main/java/org/alloytools/alloy/infrastructure/api/package-info.java diff --git a/org.alloytools.api/.classpath b/org.alloytools.api/.classpath new file mode 100644 index 000000000..bcafe71e5 --- /dev/null +++ b/org.alloytools.api/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/org.alloytools.api/.project b/org.alloytools.api/.project new file mode 100644 index 000000000..8ad83fa6d --- /dev/null +++ b/org.alloytools.api/.project @@ -0,0 +1,23 @@ + + + org.alloytools.api + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/org.alloytools.api/.settings/org.eclipse.core.resources.prefs b/org.alloytools.api/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..99f26c020 --- /dev/null +++ b/org.alloytools.api/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/org.alloytools.api/.settings/org.eclipse.core.runtime.prefs b/org.alloytools.api/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 000000000..5a0ad22d2 --- /dev/null +++ b/org.alloytools.api/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +line.separator=\n diff --git a/org.alloytools.api/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.api/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..2f809de6d --- /dev/null +++ b/org.alloytools.api/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,456 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=error +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled +org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled +org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL +org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=4 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=true +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=51 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=50 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=2 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=2 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=51 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=2 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=2 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=2 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=50 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=2 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=140 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=3 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.alloytools.api/.settings/org.eclipse.jdt.ui.prefs b/org.alloytools.api/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..4282c280f --- /dev/null +++ b/org.alloytools.api/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,131 @@ +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_functional_interfaces=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=false +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.insert_inferred_type_arguments=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=false +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_redundant_type_arguments=true +cleanup.remove_trailing_whitespaces=false +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_anonymous_class_creation=false +cleanup.use_blocks=false +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_lambda=true +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup.use_type_arguments=false +cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile +cleanup_settings_version=2 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_Alloy +formatter_settings_version=14 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=false +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=false +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/org.alloytools.api/bnd.bnd b/org.alloytools.api/bnd.bnd new file mode 100644 index 000000000..da51f16cb --- /dev/null +++ b/org.alloytools.api/bnd.bnd @@ -0,0 +1,4 @@ +-includepackage *;from:=classes +-buildpath: \ + org.osgi.annotation.bundle,\ + osgi.annotation \ No newline at end of file diff --git a/org.alloytools.api/src/main/java/org/alloytools/alloy/context/api/AlloyContext.java b/org.alloytools.api/src/main/java/org/alloytools/alloy/context/api/AlloyContext.java new file mode 100644 index 000000000..8865d4286 --- /dev/null +++ b/org.alloytools.api/src/main/java/org/alloytools/alloy/context/api/AlloyContext.java @@ -0,0 +1,9 @@ +package org.alloytools.alloy.context.api; + + +public interface AlloyContext { + + boolean isDebug(); + + +} diff --git a/org.alloytools.api/src/main/java/org/alloytools/alloy/context/api/package-info.java b/org.alloytools.api/src/main/java/org/alloytools/alloy/context/api/package-info.java new file mode 100644 index 000000000..956dc28cd --- /dev/null +++ b/org.alloytools.api/src/main/java/org/alloytools/alloy/context/api/package-info.java @@ -0,0 +1,7 @@ +@Version("1.0.0" ) +@Export +package org.alloytools.alloy.context.api; + +import org.osgi.annotation.bundle.Export; +import org.osgi.annotation.versioning.Version; + diff --git a/org.alloytools.api/src/main/java/org/alloytools/alloy/infrastructure/api/AlloyMain.java b/org.alloytools.api/src/main/java/org/alloytools/alloy/infrastructure/api/AlloyMain.java new file mode 100644 index 000000000..cc3f754b7 --- /dev/null +++ b/org.alloytools.api/src/main/java/org/alloytools/alloy/infrastructure/api/AlloyMain.java @@ -0,0 +1,41 @@ +package org.alloytools.alloy.infrastructure.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.osgi.annotation.bundle.Capability; + +/** + * + * @author aqute + * + */ + +@Capability( + namespace = AlloyMain.NAMESPACE, + attribute = { + AlloyMain.FQN + "=${@class}" + } ) +@Retention(RetentionPolicy.RUNTIME ) +@Target(ElementType.TYPE ) +@Repeatable(AlloyMain.AlloyMains.class ) +public @interface AlloyMain { + + @Retention(RetentionPolicy.RUNTIME ) + @Target(ElementType.TYPE ) + @interface AlloyMains { + + AlloyMain[] value(); + } + + String NAMESPACE = "alloy.main"; + String FQN = "fqn"; + + + String name(); + + boolean isDefault() default false; +} diff --git a/org.alloytools.api/src/main/java/org/alloytools/alloy/infrastructure/api/package-info.java b/org.alloytools.api/src/main/java/org/alloytools/alloy/infrastructure/api/package-info.java new file mode 100644 index 000000000..74809842f --- /dev/null +++ b/org.alloytools.api/src/main/java/org/alloytools/alloy/infrastructure/api/package-info.java @@ -0,0 +1,7 @@ +@Version("1.0.0" ) +@Export +package org.alloytools.alloy.infrastructure.api; + +import org.osgi.annotation.bundle.Export; +import org.osgi.annotation.versioning.Version; + From 42d15abb781fd3e46e57696d1ec1108247271fca Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Tue, 4 Jan 2022 16:19:23 +0100 Subject: [PATCH 005/129] [eclipse] preferences --- .../.settings/org.eclipse.jdt.core.prefs | 1 + .../org.eclipse.core.resources.prefs | 2 +- .../.settings/org.eclipse.core.runtime.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 446 +++++++++++++++++- .../.settings/org.eclipse.jdt.ui.prefs | 131 +++++ 5 files changed, 580 insertions(+), 2 deletions(-) create mode 100644 org.alloytools.alloy.wrappers/.settings/org.eclipse.core.runtime.prefs create mode 100644 org.alloytools.alloy.wrappers/.settings/org.eclipse.jdt.ui.prefs diff --git a/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs index 6f9e91618..2f809de6d 100644 --- a/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs @@ -133,6 +133,7 @@ org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL diff --git a/org.alloytools.alloy.wrappers/.settings/org.eclipse.core.resources.prefs b/org.alloytools.alloy.wrappers/.settings/org.eclipse.core.resources.prefs index 1554c6f84..99f26c020 100644 --- a/org.alloytools.alloy.wrappers/.settings/org.eclipse.core.resources.prefs +++ b/org.alloytools.alloy.wrappers/.settings/org.eclipse.core.resources.prefs @@ -1,2 +1,2 @@ eclipse.preferences.version=1 -encoding/bnd.bnd=UTF-8 +encoding/=UTF-8 diff --git a/org.alloytools.alloy.wrappers/.settings/org.eclipse.core.runtime.prefs b/org.alloytools.alloy.wrappers/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 000000000..5a0ad22d2 --- /dev/null +++ b/org.alloytools.alloy.wrappers/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +line.separator=\n diff --git a/org.alloytools.alloy.wrappers/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.wrappers/.settings/org.eclipse.jdt.core.prefs index af07d5f5e..2f809de6d 100644 --- a/org.alloytools.alloy.wrappers/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.wrappers/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,456 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=error +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled +org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled +org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL +org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=4 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=true +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=51 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=50 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=2 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=2 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=51 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=2 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=2 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=2 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=50 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=2 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=140 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=3 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.alloytools.alloy.wrappers/.settings/org.eclipse.jdt.ui.prefs b/org.alloytools.alloy.wrappers/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..4282c280f --- /dev/null +++ b/org.alloytools.alloy.wrappers/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,131 @@ +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_functional_interfaces=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=false +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.insert_inferred_type_arguments=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=false +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_redundant_type_arguments=true +cleanup.remove_trailing_whitespaces=false +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_anonymous_class_creation=false +cleanup.use_blocks=false +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_lambda=true +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup.use_type_arguments=false +cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile +cleanup_settings_version=2 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_Alloy +formatter_settings_version=14 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=false +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=false +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false From c8c155b3d91703131f7c0e7c88a20764fed66708 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Tue, 4 Jan 2022 16:19:43 +0100 Subject: [PATCH 006/129] Rename of the Alloy class to the core. --- .../org/alloytools/alloy/core/infra}/Alloy.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) rename {org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole => org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra}/Alloy.java (72%) diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Alloy.java b/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/Alloy.java similarity index 72% rename from org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Alloy.java rename to org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/Alloy.java index 191d56ef8..df3cb4228 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/Alloy.java +++ b/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/Alloy.java @@ -1,4 +1,4 @@ -package edu.mit.csail.sdg.alloy4whole; +package org.alloytools.alloy.core.infra; import java.io.File; import java.io.IOException; @@ -8,6 +8,16 @@ import aQute.lib.io.IO; +/** + * This class is the main class for the JAR. Its name is the name shown in the + * GUI on MacOS, so do not change it. + *

+ * This class is an entry point and should not be renamed. It should also _NOT_ + * touch any other classes. We're creating a special class loader to allow the + * dynamic libraries to be found. If you link this class to any othe class + * you're bound to create trouble. + * + */ public class Alloy { static ClassLoader old = Alloy.class.getClassLoader(); @@ -54,8 +64,8 @@ protected String findLibrary(String libname) { public static void main(String args[]) throws Exception { AlloyClassLoader l1 = new AlloyClassLoader(); - Class< ? > simpleGui = l1.loadClass("edu.mit.csail.sdg.alloy4whole.SimpleGUI"); - Method main = simpleGui.getMethod("main", String[].class); + Class< ? > dispatcher = l1.loadClass("org.alloytools.alloy.core.infra.AlloyDispatcher"); + Method main = dispatcher.getMethod("main", String[].class); main.invoke(null, (Object) args); } } From 01a590b270346290e9e9198e5dff7bfbf1761017 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Tue, 4 Jan 2022 16:20:05 +0100 Subject: [PATCH 007/129] [build] Update of build files --- cnf/build.bnd | 6 +----- cnf/central.mvn | 4 +++- org.alloytools.alloy.application/bnd.bnd | 3 ++- org.alloytools.alloy.core/bnd.bnd | 14 +++++++++----- org.alloytools.alloy.dist/bnd.bnd | 11 +++++++++-- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/cnf/build.bnd b/cnf/build.bnd index 21510a285..7910c0762 100644 --- a/cnf/build.bnd +++ b/cnf/build.bnd @@ -61,8 +61,4 @@ usr = ${env;REPOSITORY_USERNAME;} -connection-settings: ${if;${pwd};server;-dummy};id=https://oss.sonatype.org;username=${usr};password=${pwd}, -bnd -# -# Install a copy in the local Maven repository (~/.m2/repository) -# - - +-includepackage *;from:=classes diff --git a/cnf/central.mvn b/cnf/central.mvn index 37dea4666..eb410737f 100644 --- a/cnf/central.mvn +++ b/cnf/central.mvn @@ -9,4 +9,6 @@ org.alloytools:pardinus.core:1.3.0 org.alloytools:pardinus.nativesat:1.3.0 biz.aQute:biz.aQute.wrapper.hamcrest:1.3 biz.aQute:biz.aQute.wrapper.junit:4.13.1 -biz.aQute.bnd:aQute.libg:6.0.0 \ No newline at end of file +biz.aQute.bnd:aQute.libg:6.1.0 +org.osgi:org.osgi.annotation.bundle:1.1.1 +org.osgi:osgi.annotation:8.0.1 \ No newline at end of file diff --git a/org.alloytools.alloy.application/bnd.bnd b/org.alloytools.alloy.application/bnd.bnd index ff7ee2679..c3abc7b49 100644 --- a/org.alloytools.alloy.application/bnd.bnd +++ b/org.alloytools.alloy.application/bnd.bnd @@ -5,7 +5,8 @@ lib/apple-osx-ui.jar;version=file,\ org.alloytools:pardinus.core;version='1.3.0',\ org.alloytools.alloy.core;version=latest,\ - aQute.libg + aQute.libg,\ + org.alloytools.api -testpath: \ biz.aQute.wrapper.junit, \ biz.aQute.wrapper.hamcrest, \ diff --git a/org.alloytools.alloy.core/bnd.bnd b/org.alloytools.alloy.core/bnd.bnd index 00b1a105b..2876a0084 100644 --- a/org.alloytools.alloy.core/bnd.bnd +++ b/org.alloytools.alloy.core/bnd.bnd @@ -3,11 +3,14 @@ -includeresource: \ src/main/resources, \ @${repo;slf4j.api}, \ - + -buildpath: \ - org.alloytools:pardinus.core;version=1.3.0,\ - org.alloytools:pardinus.nativesat;version=1.3.0,\ - org.eclipse.jdt.annotation + org.alloytools:pardinus.core;version='1.3.0',\ + org.alloytools:pardinus.nativesat;version='1.3.0',\ + org.eclipse.jdt.annotation,\ + aQute.libg,\ + org.alloytools.api,\ + slf4j.api -testpath: \ biz.aQute.wrapper.junit, \ @@ -24,7 +27,8 @@ Export-Package: \ edu.mit.csail.sdg.sim,\ edu.mit.csail.sdg.translator,\ org.alloytools.util.table,\ - org.alloytools.alloy.core + org.alloytools.alloy.core, \ + org.alloytools.alloy.core.util Private-Package: \ java_cup.runtime diff --git a/org.alloytools.alloy.dist/bnd.bnd b/org.alloytools.alloy.dist/bnd.bnd index a5f310311..c4bcb056a 100644 --- a/org.alloytools.alloy.dist/bnd.bnd +++ b/org.alloytools.alloy.dist/bnd.bnd @@ -1,19 +1,22 @@ -Main-Class: edu.mit.csail.sdg.alloy4whole.Alloy +Main-Class: org.alloytools.alloy.core.infra.Alloy +JPM-Command: alloy -buildpath: \ org.alloytools.alloy.application,\ org.alloytools.alloy.core,\ org.alloytools.alloy.extra,\ + org.alloytools.api,\ aQute.libg, \ slf4j.api, \ slf4j.simple -sources: false --conditionalpackage: aQute.lib*, org.apache.commmons.cli, slf4j* +-conditionalpackage: aQute.*, org.apache.commmons.cli, slf4j* -includeresource: \ + @${repo;org.alloytools.api}, \ @${repo;org.alloytools.alloy.application}, \ @${repo;org.alloytools.alloy.core}, \ @${repo;org.alloytools.alloy.extra}, \ @@ -22,4 +25,8 @@ Main-Class: edu.mit.csail.sdg.alloy4whole.Alloy @${repo;org.sat4j.core}, \ @${repo;org.sat4j.maxsat}, \ @${repo;org.sat4j.pb}, \ + @${repo;slf4j.api}, \ + @${repo;slf4j.simple}, \ LICENSES + +-dependson: * \ No newline at end of file From ad2426b26cfbe642b1ebde4a39c79a07f4e36a41 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Tue, 4 Jan 2022 16:21:35 +0100 Subject: [PATCH 008/129] [gui] - Accepts any file names from command line - Support special codes in path (.. & ~) of opened files in a platform independent way - Made constructor package private --- .../edu/mit/csail/sdg/alloy4whole/SimpleGUI.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java index 8a60a547e..11af74912 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java @@ -124,6 +124,8 @@ import org.alloytools.alloy.core.AlloyCore; +import aQute.lib.io.IO; + //import com.apple.eawt.Application; //import com.apple.eawt.ApplicationAdapter; //import com.apple.eawt.ApplicationEvent; @@ -2013,7 +2015,7 @@ public void run() { * The constructor; this method will be called by the AWT event thread, using * the "invokeLater" method. */ - private SimpleGUI(final String[] args) { + SimpleGUI(final String[] args) { UIManager.put("ToolTip.font", new FontUIResource("Courier New", Font.PLAIN, 14)); @@ -2323,12 +2325,11 @@ private void finishInit(String[] args, int width) { frame.setJMenuBar(bar); // Open the given file, if a filename is given in the command line - for (String f : args) - if (f.toLowerCase(Locale.US).endsWith(".als")) { - File file = new File(f); - if (file.exists() && file.isFile()) - doOpenFile(file.getPath()); - } + for (String f : args) { + File file = IO.getFile(f); + if (file.isFile()) + doOpenFile(file.getPath()); + } // Update the title and status bar notifyChange(); From ed36d1bdbcd67fc2c6d76ac21379446e0a84a44c Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Tue, 4 Jan 2022 16:24:53 +0100 Subject: [PATCH 009/129] [main] Adds a facade to start the SimplGUI. This is not in SimpleGUI because the SimplGUI initializes the graphic framework when we create an instance. The facade just exports the `gui` command command and it is the default. --- .../mit/csail/sdg/alloy4whole/CLIFacade.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/CLIFacade.java diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/CLIFacade.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/CLIFacade.java new file mode 100644 index 000000000..f344f5586 --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/CLIFacade.java @@ -0,0 +1,30 @@ +package edu.mit.csail.sdg.alloy4whole; + +import javax.swing.SwingUtilities; + +import org.alloytools.alloy.infrastructure.api.AlloyMain; + +import aQute.lib.getopt.Options; + + +@AlloyMain( + name = "gui", + isDefault = true ) +public class CLIFacade { + + interface GuiOptions extends Options { + + } + + public void _gui(GuiOptions options) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + new SimpleGUI(options._arguments().toArray(new String[0])); + } + }); + + } +} + From 347832189f7d84a8c962d09d1344da2994356f70 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Tue, 4 Jan 2022 16:40:44 +0100 Subject: [PATCH 010/129] [main] Dispatcher To support the main class that runs in the distribution JAR we need two indirections. 1) We need to make sure we can load any native library. For this it is necessary to insert a class loader in the chain that knows where we can find the natives that come from the jar. 2) Since we are getting a Language Server Protocol extension and a Shell and some other goodies it is necessary to not couple everything to everything. For this reason, we now have an API with an AlloyMain annotation. If this is put on a class and the distribution is build with bnd, there will be a header in the manifest. The Alloy Dispatcher class, which is the first loaded class from our class loader, will get all the AlloyMain annotated classes. It will then figure out the command line options and flags. The option handling is through a library in aQute.lib. This allows you to write a simple Java method that takes an interface. Options are methods on this interface and flags are methods returning boolean. Annotating the interface with @Arguments and the fields with @Description will allow the library to handle all the help information. --- .../mit/csail/sdg/alloy4/A4Preferences.java | 33 +- .../alloy/core/infra/AlloyDispatcher.java | 418 ++++++++++++++++++ 2 files changed, 442 insertions(+), 9 deletions(-) create mode 100644 org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/AlloyDispatcher.java diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java index 8e4cd24b8..52268d447 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/A4Preferences.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.prefs.Preferences; import javax.swing.AbstractAction; @@ -807,14 +808,28 @@ public final String toString() { return ans; } - // /** The visualization algorithm */ - // public static final StringChoicePref VisualizationAlgorithm = new - // StringChoicePref("VizAlg", "Visualization algorightm", - // Arrays.asList("Sugiyama", "Circle", "Grid"), "Sugiyama"); - // - // public static final IntPref GridLayoutRows = new - // IntPref("GridLayoutRows", 1, 5, 100); - // public static final IntPref GridLayoutCols = new - // IntPref("GridLayoutCols", 1, 5, 100); + /** + * Convenience method to set a value by string + * + * @param id the id of the preference + * @param value the value in string form + * @return an error message or null if all ok + */ + + public static String set(String id, String value) { + Optional> pref = allPrefs().stream().filter(p -> p.id.equals(id)).findAny(); + if (pref.isPresent()) { + try { + Pref p = (Pref) pref.get(); + T parsed = (T) pref.get().parse(value); + p.set(parsed); + } catch (Exception e) { + return e.getMessage(); + } + } else { + return "no such preference"; + } + return null; + } } diff --git a/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/AlloyDispatcher.java b/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/AlloyDispatcher.java new file mode 100644 index 000000000..6cdb72dc8 --- /dev/null +++ b/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/AlloyDispatcher.java @@ -0,0 +1,418 @@ +package org.alloytools.alloy.core.infra; + + +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.Arrays; +import java.util.Formatter; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.TreeMap; +import java.util.jar.Manifest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.alloytools.alloy.context.api.AlloyContext; +import org.alloytools.alloy.infrastructure.api.AlloyMain; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import aQute.lib.getopt.Arguments; +import aQute.lib.getopt.CommandLine; +import aQute.lib.getopt.Description; +import aQute.lib.getopt.Options; +import aQute.lib.io.IO; +import aQute.lib.justif.Justif; +import aQute.lib.strings.Strings; +import aQute.libg.parameters.Attributes; +import aQute.libg.parameters.ParameterMap; +import aQute.libg.reporter.ReporterAdapter; +import edu.mit.csail.sdg.alloy4.A4Preferences; +import edu.mit.csail.sdg.alloy4.A4Preferences.Pref; +import edu.mit.csail.sdg.translator.A4Options; +import edu.mit.csail.sdg.translator.A4Options.SatSolver; + +/** + * Since the Alloy code is used for many different situations, we do not assume + * we know how the world looks like. This class uses the AlloyMain annotation to + * find any class that can be called from the command line that was added to the + * distribution jar. + * + */ +public class AlloyDispatcher extends ReporterAdapter { + + final static Logger log = LoggerFactory.getLogger(AlloyDispatcher.class); + PrintStream out = System.out; + PrintStream err = System.err; + AlloyContext context; + Optional manifest; + + + + static class MainDef implements AutoCloseable { + + public final String name; + public final Object instance; + public final boolean deflt; + + public MainDef(Object instance, String name, boolean deflt) { + this.instance = instance; + this.name = name; + this.deflt = deflt; + } + + @Override + public String toString() { + return "MainDef [name=" + name + ", instance=" + instance + "]"; + } + + @Override + public void close() throws Exception { + if (instance instanceof AutoCloseable) + IO.close((AutoCloseable) instance); + } + } + + enum Levels { + off, + trace, + debug, + info, + warn, + error; + } + + + + @Description("The Alloy command line" ) + @Arguments( + arg = { + "[sub-cmd]", "..." + } ) + interface BaseOptions extends Options { + + @Description("Activate debugging mode" ) + boolean debug(); + + @Description("Set the default log level: off, trace, debug, info, warn, error. If not set, defaults to error" ) + Levels defaultLevel(Levels deflt); + + @Description("Set per logger log level. The syntax is =, where level is off, trace, debug, info, warn, error" ) + String[] log(); + + @Description("A comma separated string with Alloy preferences. Preference id's (and their values) can be found with the `prefs` sub command. Usually enclosed in quotes to prevent the shell from breaking them up. Preferences are stored persistently." ) + String preferences(); + } + + public static void main(String[] args) { + AlloyDispatcher dispatcher = new AlloyDispatcher(); + CommandLine cl = new CommandLine(dispatcher); + try { + String help = cl.execute(dispatcher, "alloy", Arrays.asList(args)); + if (help != null) { + System.err.println(help); + } + } catch (Exception e) { + dispatcher.exception(e, "invocation failed %s", e.getMessage()); + } + dispatcher.report(System.out); + } + + public void _alloy(BaseOptions options) throws Exception { + if (options.debug()) + System.setProperty("debug", "yes"); + + setslf4j(options.defaultLevel(Levels.error), options.log()); + + CommandLine cl = options._command(); + AlloyContext context = getContext(options); + Map mains = getMains(context, cl); + + doPreferences(options.preferences()); + + try { + + + List arguments = options._arguments(); + + MainDef selected; + if (arguments.isEmpty()) { + selected = mains.entrySet().stream().filter(e -> e.getValue().deflt).map(e -> e.getValue()).findAny().orElse(null); + if (selected == null) { + error("invalid JAR, could not find a main that is the default and no command was given. Main classes found %s", mains); + return; + } + } else { + String _name = arguments.remove(0); + String name = _name.equals("help") ? "_help" : _name; // 'help' is built in but we override it + selected = mains.entrySet().stream().filter(e -> e.getValue().name.equals(name)).map(e -> e.getValue()).findAny().orElse(null); + if (selected == null) { + error("No such command: %s, available commands are %s", name, mains.keySet()); + return; + } + } + + if (!isOk()) { + return; + } + + log.info("selected main {} is with arguments {}", selected, arguments); + + String execute = cl.execute(selected.instance, selected.name, arguments); + if (execute != null) { + err.println(execute); + } + + } finally { + mains.values().forEach(IO::close); + } + } + + + @Arguments( + arg = {} ) + @Description("Display the current version" ) + interface VersionOptions extends Options { + + @Description("Show the full major.minor.micro.qualifier version, normal it does not print the qualifier" ) + boolean full(); + } + + public void _version(VersionOptions options) { + String version = getVersion(); + if (!options.full()) { + int n = version.lastIndexOf('.'); + if (n > 0) + version = version.substring(0, n); + } + out.println(version); + } + + private AlloyContext getContext(BaseOptions options) { + if (context == null) { + context = new AlloyContext() { + + @Override + public boolean isDebug() { + return options.debug(); + } + }; + } + return context; + } + + + @Description("Show the preferences or modify them" ) + @Arguments( + arg = {} ) + interface PreferencesOptions extends Options { + + @Description("Show the preferences in a comma separated format as used by the alloy `-p` preferences option. You can then copy the output and paste it in the -p option" ) + boolean cli(); + } + + + public void _prefs(PreferencesOptions options) { + if (options.cli()) { + StringBuilder sb = new StringBuilder(); + sb.append("\""); + String del = ""; + for (Pref< ? > pref : A4Preferences.allUserPrefs()) { + sb.append(del).append(pref.id).append("=").append(pref.get()); + del = ","; + } + sb.append("\""); + out.println(sb); + } else { + for (Pref< ? > pref : A4Preferences.allPrefs()) { + out.printf("%-30s %-50s %s%n", pref.id, pref.title, pref.get()); + } + } + } + + + + @Description("Show the list of solvers" ) + @Arguments( + arg = {} ) + interface SolverOptions extends Options { + } + + + public void _solvers(SolverOptions options) { + StringBuilder sb = new StringBuilder(); + for (SatSolver o : A4Options.SatSolver.values()) { + out.printf("%s%n", o); + } + } + + + + @Description("Show help information about the available sub commands" ) + @Arguments( + arg = { + "[sub-cmd]" + } ) + interface HelpOptions extends Options { + + } + + public void __help(HelpOptions options) { + List arguments = options._arguments(); + CommandLine cl = options._command(); + Map mains = getMains(context, cl); + Justif j = new Justif(80); + try (Formatter f = j.formatter()) { + + if (arguments.isEmpty()) { + cl.help(f, this, "alloy"); + f.format("Sub commands are: %s%n", mains.keySet().stream().collect(Collectors.joining(", ")).replace("_help", "help")); + f.format("Do 'help to get more information about a particular sub command%n", mains.keySet().stream().collect(Collectors.joining(", "))); + } else { + for (Map.Entry e : mains.entrySet()) { + String name = e.getKey(); + if (!arguments.contains(name)) + continue; + + MainDef main = e.getValue(); + if (main.deflt) + f.format("[default]"); + cl.help(f, main.instance, name); + } + } + out.println(j.wrap()); + } + } + + + private Map getMains(AlloyContext context, CommandLine cl) { + Map result = new TreeMap<>(); + localCommands(cl, result); + globalCommands(context, result); + return result; + } + + private void globalCommands(AlloyContext context, Map result) { + ParameterMap header = getHeader("Provide-Capability"); + + header.entrySet().stream().filter(e -> e.getKey().startsWith(AlloyMain.NAMESPACE)).forEach(e -> { + try { + Attributes attrs = e.getValue(); + String fqn = attrs.get(AlloyMain.FQN); + if (fqn == null) + throw new RuntimeException("Expected a fqn in the capability " + e); + + Class< ? > mainClass = AlloyDispatcher.class.getClassLoader().loadClass(fqn); + AlloyMain mainAnn = mainClass.getAnnotation(AlloyMain.class); + if (mainAnn != null) { + Object instance = getInstance(context, e, mainClass); + MainDef main = new MainDef(instance, mainAnn.name(), mainAnn.isDefault()); + result.put(main.name, main); + log.debug("found main class {}", main); + } else { + throw new RuntimeException("Main class " + mainClass + " is listed in capability " + e + " but does not have an AlloyMain annotation"); + } + } catch (ClassNotFoundException e1) { + throw new RuntimeException("In capability " + e + ", the fqn cannot be located as class in the current JAR: " + e1); + } + }); + } + + private void localCommands(CommandLine cl, Map result) { + Map commands = cl.getCommands(this); + for (Map.Entry e : commands.entrySet()) { + String cmd = e.getKey(); + if (cmd.equals("alloy")) + continue; + + MainDef md = new MainDef(this, cmd, false); + result.put(cmd, md); + } + } + + private Object getInstance(AlloyContext context, Entry e, Class< ? > mainClass) { + try { + return mainClass.getConstructor(AlloyContext.class).newInstance(context); + } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) { + try { + return mainClass.newInstance(); + } catch (InstantiationException | IllegalAccessException e2) { + throw new RuntimeException("Capability " + e + " specifies class " + mainClass + " but that class has no default constructor nor one that takes AlloyContext"); + } + } + } + + final static Pattern PREF_P = Pattern.compile("\\s*(?[^=]+)\\s*(=\\s*(?.*)\\s*)"); + + private void doPreferences(String preferences) { + if (preferences == null) + return; + + for (String pref : Strings.splitQuoted(preferences)) { + Matcher m = PREF_P.matcher(pref); + if (!m.matches()) { + error("cannot match preferences '%s', particularly `%s`", preferences, pref); + } else { + String id = m.group("id"); + String value = m.group("value"); + if (value == null) + value = "true"; + + String result = A4Preferences.set(id, value); + if (result != null) { + error("Setting pref %s failed: %s", id, result); + } + } + } + + } + + private ParameterMap getHeader(String name) { + return getManifest().map(m -> new ParameterMap(m.getMainAttributes().getValue(name))).orElse(new ParameterMap()); + } + + private String getVersion() { + return getManifest().map(m -> m.getMainAttributes().getValue("Bundle-Version")).orElse("0.0.0.unknown"); + } + + private Optional getManifest() { + if (manifest != null) + return manifest; + + try { + URL resource = AlloyDispatcher.class.getResource("/META-INF/MANIFEST.MF"); + if (resource == null) + return Optional.empty(); + + Manifest manifest = new Manifest(resource.openStream()); + return this.manifest = Optional.of(manifest); + } catch (IOException e) { + log.error("No Manifest found {}", e, e); + return Optional.empty(); + } + } + + + static final Pattern TARGET_P = Pattern.compile("\\s*(?[^=]+)\\s*=\\s*(?off|trace|debug|info|warn|error)\\s*"); + + public static void setslf4j(Levels deflt, String... targets) { + System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", deflt.toString()); + if (targets != null) + for (String target : targets) { + Matcher m = TARGET_P.matcher(target); + if (m.matches()) { + String key = m.group("name"); + Levels level = Levels.valueOf(m.group("level")); + System.setProperty("org.slf4j.simpleLogger.log." + key, level.toString()); + } else { + System.err.println("invalid slf4j target definition " + target + ", expect " + TARGET_P); + } + } + } +} From fc0172a97ee21c284803ba0f18e8d7e741c01eb1 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Wed, 19 Jan 2022 09:31:34 +0100 Subject: [PATCH 011/129] LSP server --- cnf/build.bnd | 2 + cnf/central.mvn | 19 +- .../mit/csail/sdg/alloy4whole/SimpleGUI.java | 6 +- .../csail/sdg/alloy4whole/SimpleReporter.java | 6 +- org.alloytools.alloy.dist/bnd.bnd | 14 +- org.alloytools.alloy.lsp/.classpath | 12 + org.alloytools.alloy.lsp/.project | 23 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.core.runtime.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 456 +++++ .../.settings/org.eclipse.jdt.ui.prefs | 135 ++ org.alloytools.alloy.lsp/bnd.bnd | 14 + .../alloy/lsp/provider/AlloyAppUtil.java | 128 ++ .../alloy/lsp/provider/AlloyLSMessage.java | 23 + .../lsp/provider/AlloyLSMessageType.java | 9 + .../lsp/provider/AlloyLanguageClient.java | 35 + .../lsp/provider/AlloyLanguageServer.java | 135 ++ .../lsp/provider/AlloyLanguageServerUtil.java | 94 + .../provider/AlloyTextDocumentService.java | 1599 +++++++++++++++++ .../alloy/lsp/provider/Lsp4jUtil.java | 59 + .../src/test/java/.gitignore | 0 21 files changed, 2761 insertions(+), 12 deletions(-) create mode 100644 org.alloytools.alloy.lsp/.classpath create mode 100644 org.alloytools.alloy.lsp/.project create mode 100644 org.alloytools.alloy.lsp/.settings/org.eclipse.core.resources.prefs create mode 100644 org.alloytools.alloy.lsp/.settings/org.eclipse.core.runtime.prefs create mode 100644 org.alloytools.alloy.lsp/.settings/org.eclipse.jdt.core.prefs create mode 100644 org.alloytools.alloy.lsp/.settings/org.eclipse.jdt.ui.prefs create mode 100644 org.alloytools.alloy.lsp/bnd.bnd create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyAppUtil.java create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLSMessage.java create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLSMessageType.java create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageClient.java create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServer.java create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServerUtil.java create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyTextDocumentService.java create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/Lsp4jUtil.java create mode 100644 org.alloytools.alloy.lsp/src/test/java/.gitignore diff --git a/cnf/build.bnd b/cnf/build.bnd index 7910c0762..4ca8bea32 100644 --- a/cnf/build.bnd +++ b/cnf/build.bnd @@ -12,6 +12,7 @@ javac.source: 1.8 javac.target: 1.8 javac.compliance: 1.8 javac.debug: on +-sources false Git-Descriptor: ${system-allow-fail;git describe --dirty --always} Git-SHA: ${system-allow-fail;git rev-list -1 HEAD} @@ -27,6 +28,7 @@ Bundle-Version: ${base.version}.${tstamp} # Remove -SNAPSHOT for release version -pom: version=${base.version}-SNAPSHOT -groupid: org.alloytools +-includepackage *;from:=classes # diff --git a/cnf/central.mvn b/cnf/central.mvn index eb410737f..5a3e7c377 100644 --- a/cnf/central.mvn +++ b/cnf/central.mvn @@ -1,8 +1,23 @@ +biz.aQute.bnd:aQute.libg:6.0.0 +biz.aQute:biz.aQute.wrapper.hamcrest:1.3 +biz.aQute:biz.aQute.wrapper.junit:4.13.1 +com.google.code.gson:gson:2.8.9 +com.google.code.gson:gson:2.8.9 +commons-io:commons-io:jar:2.6 +commons-io:commons-io:jar:2.6 +de.jflex:jflex:1.6.1 +org.alloytools:pardinus.core:1.3.0 +org.alloytools:pardinus.nativesat:1.3.0 +org.eclipse.equinox:org.eclipse.equinox.common:jar:3.6.0 +org.eclipse.equinox:org.eclipse.equinox.common:jar:3.6.0 org.eclipse.jdt:org.eclipse.jdt.annotation:2.1.100 +org.eclipse.lsp4j:org.eclipse.lsp4j.jsonrpc:0.4.1 +org.eclipse.lsp4j:org.eclipse.lsp4j.jsonrpc:0.4.1 +org.eclipse.lsp4j:org.eclipse.lsp4j:0.4.1 +org.eclipse.lsp4j:org.eclipse.lsp4j:0.4.1 org.sat4j:org.sat4j.core:2.3.1 org.sat4j:org.sat4j.maxsat:2.3.1 org.sat4j:org.sat4j.pb:2.3.1 -de.jflex:jflex:1.6.1 org.slf4j:slf4j-api:1.7.28 org.slf4j:slf4j-simple:1.7.5 org.alloytools:pardinus.core:1.3.0 @@ -11,4 +26,4 @@ biz.aQute:biz.aQute.wrapper.hamcrest:1.3 biz.aQute:biz.aQute.wrapper.junit:4.13.1 biz.aQute.bnd:aQute.libg:6.1.0 org.osgi:org.osgi.annotation.bundle:1.1.1 -org.osgi:osgi.annotation:8.0.1 \ No newline at end of file +org.osgi:osgi.annotation:8.0.1 diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java index 11af74912..29dc8a8cf 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleGUI.java @@ -600,7 +600,7 @@ public void run() { * Find a temporary directory to store Alloy files; it's guaranteed to be a * canonical absolute path. */ - private static synchronized String alloyHome(JFrame parent) { + public static synchronized String alloyHome(JFrame parent) { if (alloyHome != null) return alloyHome; String temp = System.getProperty("java.io.tmpdir"); @@ -629,7 +629,7 @@ private static synchronized String alloyHome(JFrame parent) { * Create an empty temporary directory for use, designate it "deleteOnExit", * then return it. It is guaranteed to be a canonical absolute path. */ - private static String maketemp(JFrame parent) { + public static String maketemp(JFrame parent) { Random r = new Random(new Date().getTime()); while (true) { int i = r.nextInt(1000000); @@ -1853,7 +1853,7 @@ private static SimTupleset convert(Object object) throws Err { } /** Converts an A4Solution into a SimInstance object. */ - private static SimInstance convert(Module root, A4Solution ans) throws Err { + public static SimInstance convert(Module root, A4Solution ans) throws Err { SimInstance ct = new SimInstance(root, ans.getBitwidth(), ans.getMaxSeq()); for (Sig s : ans.getAllReachableSigs()) { if (!s.builtin) diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java index 2a5ddf8ba..9c19e83e2 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SimpleReporter.java @@ -78,7 +78,7 @@ * parallel problem) */ -final class SimpleReporter extends A4Reporter { +public final class SimpleReporter extends A4Reporter { public static final class SimpleCallback1 implements WorkerCallback { @@ -601,7 +601,7 @@ private static void writeXML(A4Reporter rep, Module mod, String filename, A4Solu private int warn = 0; /** Task that performs solution enumeration. */ - static final class SimpleTask2 implements WorkerTask { + public static final class SimpleTask2 implements WorkerTask { private static final long serialVersionUID = 0; public int index = -1; // [electrum] registers which iteration operation to perform @@ -683,7 +683,7 @@ private static void validate(String filename) throws Exception { } /** Task that perform one command. */ - static final class SimpleTask1 implements WorkerTask { + public static final class SimpleTask1 implements WorkerTask { private static final long serialVersionUID = 0; public A4Options options; diff --git a/org.alloytools.alloy.dist/bnd.bnd b/org.alloytools.alloy.dist/bnd.bnd index c4bcb056a..014cf6ac2 100644 --- a/org.alloytools.alloy.dist/bnd.bnd +++ b/org.alloytools.alloy.dist/bnd.bnd @@ -4,13 +4,13 @@ JPM-Command: alloy -buildpath: \ org.alloytools.alloy.application,\ - org.alloytools.alloy.core,\ + org.alloytools.alloy.core,\ org.alloytools.alloy.extra,\ org.alloytools.api,\ aQute.libg, \ slf4j.api, \ - slf4j.simple - + slf4j.simple,\ + org.alloytools.alloy.lsp -sources: false -conditionalpackage: aQute.*, org.apache.commmons.cli, slf4j* @@ -20,6 +20,7 @@ JPM-Command: alloy @${repo;org.alloytools.alloy.application}, \ @${repo;org.alloytools.alloy.core}, \ @${repo;org.alloytools.alloy.extra}, \ + @${repo;org.alloytools.alloy.lsp}, \ @${repo;org.alloytools:pardinus.core}, \ @${repo;org.alloytools:pardinus.nativesat}, \ @${repo;org.sat4j.core}, \ @@ -27,6 +28,11 @@ JPM-Command: alloy @${repo;org.sat4j.pb}, \ @${repo;slf4j.api}, \ @${repo;slf4j.simple}, \ + @${repo;org.eclipse.lsp4j}, \ + @${repo;org.eclipse.lsp4j.jsonrpc}, \ + @${repo;com.google.gson}, \ + @${repo;org.eclipse.equinox.common}, \ + @${repo;org.apache.commons.io}, \ LICENSES --dependson: * \ No newline at end of file +-dependson: * diff --git a/org.alloytools.alloy.lsp/.classpath b/org.alloytools.alloy.lsp/.classpath new file mode 100644 index 000000000..bcafe71e5 --- /dev/null +++ b/org.alloytools.alloy.lsp/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/org.alloytools.alloy.lsp/.project b/org.alloytools.alloy.lsp/.project new file mode 100644 index 000000000..2f98f1715 --- /dev/null +++ b/org.alloytools.alloy.lsp/.project @@ -0,0 +1,23 @@ + + + org.alloytools.alloy.application + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/org.alloytools.alloy.lsp/.settings/org.eclipse.core.resources.prefs b/org.alloytools.alloy.lsp/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..99f26c020 --- /dev/null +++ b/org.alloytools.alloy.lsp/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/org.alloytools.alloy.lsp/.settings/org.eclipse.core.runtime.prefs b/org.alloytools.alloy.lsp/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 000000000..5a0ad22d2 --- /dev/null +++ b/org.alloytools.alloy.lsp/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +line.separator=\n diff --git a/org.alloytools.alloy.lsp/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.lsp/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..2f809de6d --- /dev/null +++ b/org.alloytools.alloy.lsp/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,456 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=error +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled +org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled +org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL +org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=4 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=true +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=51 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=50 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_assignment=2 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=2 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=51 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=2 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=2 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=2 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=50 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=2 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=2 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=4 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=140 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=3 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/org.alloytools.alloy.lsp/.settings/org.eclipse.jdt.ui.prefs b/org.alloytools.alloy.lsp/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..5ba47fdd1 --- /dev/null +++ b/org.alloytools.alloy.lsp/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,135 @@ +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_functional_interfaces=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=false +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.insert_inferred_type_arguments=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=false +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_redundant_modifiers=false +cleanup.remove_redundant_semicolons=false +cleanup.remove_redundant_type_arguments=false +cleanup.remove_trailing_whitespaces=false +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_anonymous_class_creation=false +cleanup.use_blocks=false +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_lambda=true +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup.use_type_arguments=false +cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile +cleanup_settings_version=2 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_Alloy +formatter_settings_version=14 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.javadoc=false +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.overrideannotation=true +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=false +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=true +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_modifiers=false +sp_cleanup.remove_redundant_semicolons=false +sp_cleanup.remove_redundant_type_arguments=false +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/org.alloytools.alloy.lsp/bnd.bnd b/org.alloytools.alloy.lsp/bnd.bnd new file mode 100644 index 000000000..672cc2acd --- /dev/null +++ b/org.alloytools.alloy.lsp/bnd.bnd @@ -0,0 +1,14 @@ + +-buildpath: \ + org.alloytools.alloy.application;version=latest,\ + org.alloytools.alloy.core;version=latest,\ + org.eclipse.lsp4j,\ + org.eclipse.lsp4j.jsonrpc,\ + com.google.gson,\ + org.eclipse.equinox.common, \ + org.apache.commons.io + +-testpath: \ + biz.aQute.wrapper.junit, \ + biz.aQute.wrapper.hamcrest, \ + org.sat4j.core \ No newline at end of file diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyAppUtil.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyAppUtil.java new file mode 100644 index 000000000..755f4a03b --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyAppUtil.java @@ -0,0 +1,128 @@ +package org.alloytools.alloy.lsp.provider; + +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Random; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.OurDialog; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Module; +import edu.mit.csail.sdg.ast.Sig; +import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.sim.SimInstance; +import edu.mit.csail.sdg.sim.SimTuple; +import edu.mit.csail.sdg.sim.SimTupleset; +import edu.mit.csail.sdg.translator.A4Solution; +import edu.mit.csail.sdg.translator.A4Tuple; +import edu.mit.csail.sdg.translator.A4TupleSet; + +public class AlloyAppUtil { + + /** + * This variable caches the result of alloyHome() function call. + */ + private static String alloyHome = null; + + /** + * Find a temporary directory to store Alloy files; it's guaranteed to be a + * canonical absolute path. + */ + public static synchronized String alloyHome() { + if (alloyHome != null) + return alloyHome; + String temp = System.getProperty("java.io.tmpdir"); + if (temp == null || temp.length() == 0) + OurDialog.fatal(null, "Error. JVM need to specify a temporary directory using java.io.tmpdir property."); + String username = System.getProperty("user.name"); + File tempfile = new File(temp + File.separatorChar + "alloy4tmp40-" + (username == null ? "" : username)); + tempfile.mkdirs(); + String ans = Util.canon(tempfile.getPath()); + if (!tempfile.isDirectory()) { + OurDialog.fatal(null, "Error. Cannot create the temporary directory " + ans); + } + if (!Util.onWindows()) { + String[] args = { + "chmod", "700", ans + }; + try { + Runtime.getRuntime().exec(args).waitFor(); + } catch (Throwable ex) { + } // We only intend to make a best effort. + } + return alloyHome = ans; + } + + /** + * Create an empty temporary directory for use, designate it "deleteOnExit", + * then return it. It is guaranteed to be a canonical absolute path. + */ + public static String maketemp() { + Random r = new Random(new Date().getTime()); + while (true) { + int i = r.nextInt(1000000); + String dest = AlloyAppUtil.alloyHome() + File.separatorChar + "tmp" + File.separatorChar + i; + File f = new File(dest); + if (f.mkdirs()) { + f.deleteOnExit(); + return Util.canon(dest); + } + } + } + + /** Converts an A4TupleSet into a SimTupleset object. */ + public static SimTupleset convert(Object object) throws Err { + if (!(object instanceof A4TupleSet)) + throw new ErrorFatal("Unexpected type error: expecting an A4TupleSet."); + A4TupleSet s = (A4TupleSet) object; + if (s.size() == 0) + return SimTupleset.EMPTY; + List list = new ArrayList(s.size()); + int arity = s.arity(); + for (A4Tuple t : s) { + String[] array = new String[arity]; + for (int i = 0; i < t.arity(); i++) + array[i] = t.atom(i); + list.add(SimTuple.make(array)); + } + return SimTupleset.make(list); + } + + /** Converts an A4Solution into a SimInstance object. */ + public static SimInstance convert(Module root, A4Solution ans) throws Err { + SimInstance ct = new SimInstance(root, ans.getBitwidth(), ans.getMaxSeq()); + for (Sig s : ans.getAllReachableSigs()) { + if (!s.builtin) + ct.init(s, convert(ans.eval(s))); + for (Field f : s.getFields()) + if (!f.defined) + ct.init(f, convert(ans.eval(f))); + } + for (ExprVar a : ans.getAllAtoms()) + ct.init(a, convert(ans.eval(a))); + for (ExprVar a : ans.getAllSkolems()) + ct.init(a, convert(ans.eval(a))); + return ct; + } + + + public interface Func0 { + + public T call() throws Exception; + } + + public static T uncheckedRun(Func0 func) { + try { + return func.call(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLSMessage.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLSMessage.java new file mode 100644 index 000000000..bc68a87a6 --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLSMessage.java @@ -0,0 +1,23 @@ +package org.alloytools.alloy.lsp.provider; + +public class AlloyLSMessage { + public AlloyLSMessageType messageType; + public String message; + public String link; + + public boolean bold; + public boolean replaceLast; + public boolean lineBreak = true; + + public AlloyLSMessage(AlloyLSMessageType messageType, String message, String link) { + this.messageType = messageType; + this.message = message; + this.link = link; + } + + public AlloyLSMessage(AlloyLSMessageType messageType, String message) { + this(messageType, message, null); + } + +} + diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLSMessageType.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLSMessageType.java new file mode 100644 index 000000000..6bcff5ff8 --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLSMessageType.java @@ -0,0 +1,9 @@ +package org.alloytools.alloy.lsp.provider; + +enum AlloyLSMessageType{ + RunStarted, + RunInProgress, + RunResult, + RunCompleted, + Warning +} \ No newline at end of file diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageClient.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageClient.java new file mode 100644 index 000000000..0138af37b --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageClient.java @@ -0,0 +1,35 @@ +package org.alloytools.alloy.lsp.provider; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; +import org.eclipse.lsp4j.services.LanguageClient; + +public interface AlloyLanguageClient extends LanguageClient { + @JsonNotification("alloy/showExecutionOutput") + CompletableFuture showExecutionOutput(AlloyLSMessage params); + + @JsonNotification("alloy/commandsListResult") + CompletableFuture commandsListResult(CommandsListResult commands); + + public class CommandsListResult{ + public List commands; + + public CommandsListResult(List commands) { + this.commands = commands; + } + + } + public class CommandsListResultItem{ + public String title; + public Command command; + + public CommandsListResultItem(String title, Command command) { + this.title = title; + this.command = command; + } + + } +} diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServer.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServer.java new file mode 100644 index 000000000..5ebc7146c --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServer.java @@ -0,0 +1,135 @@ +package org.alloytools.alloy.lsp.provider; + +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.fileUriToPath; + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + +import org.eclipse.lsp4j.CodeLensOptions; +import org.eclipse.lsp4j.DocumentLinkOptions; +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4j.InitializeResult; +import org.eclipse.lsp4j.ServerCapabilities; +import org.eclipse.lsp4j.TextDocumentSyncKind; +import org.eclipse.lsp4j.jsonrpc.Launcher; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.lsp4j.launch.LSPLauncher; +import org.eclipse.lsp4j.launch.LSPLauncher.Builder; +import org.eclipse.lsp4j.services.LanguageClient; +import org.eclipse.lsp4j.services.LanguageClientAware; +import org.eclipse.lsp4j.services.LanguageServer; +import org.eclipse.lsp4j.services.TextDocumentService; +import org.eclipse.lsp4j.services.WorkspaceService; + +public class AlloyLanguageServer implements LanguageServer, LanguageClientAware { + + private AlloyLanguageClient client; + private AlloyTextDocumentService alloyTextDocumentService; + + @Override + public CompletableFuture initialize(InitializeParams params) { + + service().directory = params.getRootUri() != null ? fileUriToPath(params.getRootUri()) : null; + + InitializeResult res = new InitializeResult(); + ServerCapabilities caps = new ServerCapabilities(); + + caps.setTextDocumentSync(Either.forLeft(TextDocumentSyncKind.Full)); + + caps.setDefinitionProvider(true); + caps.setHoverProvider(true); + caps.setCodeLensProvider(new CodeLensOptions()); + caps.setDocumentLinkProvider(new DocumentLinkOptions()); + caps.setReferencesProvider(true); + caps.setRenameProvider(true); + //caps.setDocumentHighlightProvider(true); + caps.setWorkspaceSymbolProvider(true); + caps.setDocumentSymbolProvider(true); + + res.setCapabilities(caps); + return CompletableFuture.completedFuture(res); + } + + @Override + public CompletableFuture shutdown() { + return CompletableFuture.completedFuture(null); + } + + @Override + public void exit() { + System.exit(0); + } + + @Override + public TextDocumentService getTextDocumentService() { + return service(); + } + + private AlloyTextDocumentService service() { + if (alloyTextDocumentService == null) + alloyTextDocumentService = new AlloyTextDocumentService(client); + return alloyTextDocumentService; + } + + @Override + public WorkspaceService getWorkspaceService() { + return service(); + } + + + + // LanguageClientAware + @Override + public void connect(LanguageClient client) { + System.err.println("AlloyLanguageServer.connect() called"); + this.client = (AlloyLanguageClient) client; + + if (this.alloyTextDocumentService != null) { + this.alloyTextDocumentService.connect(this.client); + } + + } + + public static void main(String[] args) throws Exception { + if (args.length == 2) { + int port = Integer.parseInt(args[1]); + InputStream inputStream; + OutputStream outputStream; + AlloyLanguageServer langserv = new AlloyLanguageServer(); + try (java.net.Socket socket = new Socket("localhost", port)) { + inputStream = socket.getInputStream(); + outputStream = socket.getOutputStream(); + System.err.println("connected!"); + Launcher launcher = createServerLauncher(langserv, AlloyLanguageClient.class, inputStream, outputStream); + System.err.println("Starting Alloy Language Server!"); + langserv.connect(launcher.getRemoteProxy()); + Future res = launcher.startListening(); + System.err.println("Alloy Language Server Started!"); + res.get(); + System.err.println("########Exited Alloy Language Server!"); + } + } else { + AlloyLanguageServer server = new AlloyLanguageServer(); + Launcher l = LSPLauncher.createServerLauncher(server, System.in, System.out); + server.connect(l.getRemoteProxy()); + Future< ? > startListening = l.startListening(); + startListening.get(); + } + } + + /** + * Create a new Launcher for a language server and an input and output stream. + * + * @param server - the server that receives method calls from the remote client + * @param in - input stream to listen for incoming messages + * @param out - output stream to send outgoing messages + */ + public static Launcher createServerLauncher(LanguageServer server, Class< ? extends TLangClient> clientType, InputStream in, OutputStream out) { + return new Builder().setLocalService(server).setRemoteInterface(clientType).setInput(in).setOutput(out).create(); + } +} + + diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServerUtil.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServerUtil.java new file mode 100644 index 000000000..47393148b --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServerUtil.java @@ -0,0 +1,94 @@ +package org.alloytools.alloy.lsp.provider; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.file.Paths; + +import org.eclipse.lsp4j.Location; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.jsonrpc.messages.Either; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4whole.SimpleGUI; + +public class AlloyLanguageServerUtil { + public static Pos positionToPos(Position position) { + return positionToPos(position, null); + } + + public static Pos positionToPos(Position position, String fileName) { + return new Pos(fileName, position.getCharacter() + 1, position.getLine() + 1); + } + + public static Location posToLocation(Pos pos){ + Location res= new Location(); + res.setRange(createRangeFromPos(pos)); + res.setUri(filePathToUri(pos.filename)); + return res; + } + + public static org.eclipse.lsp4j.Position posToPosition(edu.mit.csail.sdg.alloy4.Pos pos) { + Position position = new Position(); + position.setLine(pos.y - 1); + position.setCharacter(pos.x - 1); + return position; + } + public static Range createRange(Position start, Position end) { + Range res = new Range(); + res.setStart(start); + res.setEnd(end); + return res; + } + public static Range createRangeFromPos(Pos pos) { + Range res = new Range(); + res.setStart(posToPosition(pos)); + + Position endPosition = new Position(); + endPosition.setLine(pos.y2 - 1); + endPosition.setCharacter(pos.x2 - 1 + 1 /* end position appears to be exclusive in Range */); + + res.setEnd(endPosition); + return res; + } + + public static String filePathToUri(String absolutePath) { + return Paths.get(absolutePath).toUri().toString(); + } + + public static String fileUriToPath(String fileUri) { + try { + File file = new File(new URI(fileUri)); + try { + return file.getCanonicalPath(); + } catch (IOException ex) { + return file.getAbsolutePath(); + } + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + public static String filePathResolved(String filename) { + return filename.replace(Util.jarPrefix(), SimpleGUI.alloyHome(null) + fs); + } + + /** + * Return .getLeft() of the Either object, or throw .getRight() + * @return .getLeft() of the Either object if it isLeft() + * @throws TErr + */ + public static TRes getResult(Either val) throws TErr{ + if (val.isRight()) throw val.getRight(); + return val.getLeft(); + } + + /** + * The system-specific file separator (forward-slash on UNIX, back-slash on + * Windows, etc.) + */ + public static final String fs = System.getProperty("file.separator"); + +} \ No newline at end of file diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyTextDocumentService.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyTextDocumentService.java new file mode 100644 index 000000000..c85666cfa --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyTextDocumentService.java @@ -0,0 +1,1599 @@ +package org.alloytools.alloy.lsp.provider; + +import static edu.mit.csail.sdg.alloy4.A4Preferences.CoreGranularity; +import static edu.mit.csail.sdg.alloy4.A4Preferences.CoreMinimization; +import static edu.mit.csail.sdg.alloy4.A4Preferences.ImplicitThis; +import static edu.mit.csail.sdg.alloy4.A4Preferences.InferPartialInstance; +import static edu.mit.csail.sdg.alloy4.A4Preferences.NoOverflow; +import static edu.mit.csail.sdg.alloy4.A4Preferences.RecordKodkod; +import static edu.mit.csail.sdg.alloy4.A4Preferences.SkolemDepth; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Solver; +import static edu.mit.csail.sdg.alloy4.A4Preferences.SubMemory; +import static edu.mit.csail.sdg.alloy4.A4Preferences.SubStack; +import static edu.mit.csail.sdg.alloy4.A4Preferences.Unrolls; +import static edu.mit.csail.sdg.alloy4.A4Preferences.VerbosityPref; +import static edu.mit.csail.sdg.alloy4.A4Preferences.WarningNonfatal; +import static org.alloytools.alloy.lsp.provider.AlloyLSMessageType.RunCompleted; +import static org.alloytools.alloy.lsp.provider.AlloyLSMessageType.RunResult; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.createRange; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.createRangeFromPos; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.filePathResolved; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.filePathToUri; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.fileUriToPath; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.fs; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.getResult; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.posToLocation; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.posToPosition; +import static org.alloytools.alloy.lsp.provider.AlloyLanguageServerUtil.positionToPos; +import static org.alloytools.alloy.lsp.provider.Lsp4jUtil.newDiagnostic; +import static org.alloytools.alloy.lsp.provider.Lsp4jUtil.newMessageParams; +import static org.alloytools.alloy.lsp.provider.Lsp4jUtil.newPublishDiagnosticsParams; +import static org.alloytools.alloy.lsp.provider.Lsp4jUtil.newSymbolInformation; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Scanner; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.alloytools.alloy.core.AlloyCore; +import org.alloytools.alloy.lsp.provider.AlloyLanguageClient.CommandsListResult; +import org.alloytools.alloy.lsp.provider.AlloyLanguageClient.CommandsListResultItem; +import org.apache.commons.io.FilenameUtils; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.lsp4j.CodeActionParams; +import org.eclipse.lsp4j.CodeLens; +import org.eclipse.lsp4j.CodeLensParams; +import org.eclipse.lsp4j.Command; +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionList; +import org.eclipse.lsp4j.CompletionParams; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DiagnosticSeverity; +import org.eclipse.lsp4j.DidChangeConfigurationParams; +import org.eclipse.lsp4j.DidChangeTextDocumentParams; +import org.eclipse.lsp4j.DidChangeWatchedFilesParams; +import org.eclipse.lsp4j.DidCloseTextDocumentParams; +import org.eclipse.lsp4j.DidOpenTextDocumentParams; +import org.eclipse.lsp4j.DidSaveTextDocumentParams; +import org.eclipse.lsp4j.DocumentFormattingParams; +import org.eclipse.lsp4j.DocumentHighlight; +import org.eclipse.lsp4j.DocumentHighlightKind; +import org.eclipse.lsp4j.DocumentLink; +import org.eclipse.lsp4j.DocumentLinkParams; +import org.eclipse.lsp4j.DocumentOnTypeFormattingParams; +import org.eclipse.lsp4j.DocumentRangeFormattingParams; +import org.eclipse.lsp4j.DocumentSymbolParams; +import org.eclipse.lsp4j.Hover; +import org.eclipse.lsp4j.Location; +import org.eclipse.lsp4j.MarkupContent; +import org.eclipse.lsp4j.MessageType; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.ReferenceParams; +import org.eclipse.lsp4j.RenameParams; +import org.eclipse.lsp4j.SignatureHelp; +import org.eclipse.lsp4j.SymbolInformation; +import org.eclipse.lsp4j.SymbolKind; +import org.eclipse.lsp4j.TextDocumentPositionParams; +import org.eclipse.lsp4j.TextEdit; +import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.lsp4j.WorkspaceSymbolParams; +import org.eclipse.lsp4j.jsonrpc.messages.Either; +import org.eclipse.lsp4j.jsonrpc.services.JsonRequest; +import org.eclipse.lsp4j.services.LanguageClient; +import org.eclipse.lsp4j.services.LanguageClientAware; +import org.eclipse.lsp4j.services.TextDocumentService; +import org.eclipse.lsp4j.services.WorkspaceService; + +import com.google.gson.Gson; +import com.google.gson.JsonPrimitive; + +import edu.mit.csail.sdg.alloy4.A4Preferences.Verbosity; +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.Computer; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.OurDialog; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.alloy4.WorkerEngine; +import edu.mit.csail.sdg.alloy4.WorkerEngine.WorkerCallback; +import edu.mit.csail.sdg.alloy4.XMLNode; +import edu.mit.csail.sdg.alloy4viz.VizGUI; +import edu.mit.csail.sdg.alloy4whole.SimpleGUI; +import edu.mit.csail.sdg.alloy4whole.SimpleReporter.SimpleTask1; +import edu.mit.csail.sdg.alloy4whole.SimpleReporter.SimpleTask2; +import edu.mit.csail.sdg.ast.Assert; +import edu.mit.csail.sdg.ast.Clause; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprBad; +import edu.mit.csail.sdg.ast.ExprConstant; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Func; +import edu.mit.csail.sdg.ast.Module; +import edu.mit.csail.sdg.ast.Sig; +import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.ast.VisitQueryOnce; +import edu.mit.csail.sdg.parser.CompModule; +import edu.mit.csail.sdg.parser.CompUtil; +import edu.mit.csail.sdg.parser.Macro; +import edu.mit.csail.sdg.sim.SimInstance; +import edu.mit.csail.sdg.translator.A4Options; +import edu.mit.csail.sdg.translator.A4Solution; +import edu.mit.csail.sdg.translator.A4SolutionReader; + +class AlloyTextDocumentService implements TextDocumentService, WorkspaceService, LanguageClientAware { + + public AlloyLanguageClient client; + public String directory; + private int subMemoryNow; + private int subStackNow; + + public AlloyTextDocumentService(AlloyLanguageClient client) { + this.client = client; + } + + // LanguageClientAware + @Override + public void connect(LanguageClient client) { + log("AlloyTextDocumentService.connect() called"); + this.client = (AlloyLanguageClient) client; + } + + @Override + public CompletableFuture,CompletionList>> completion(CompletionParams position) { + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture resolveCompletionItem(CompletionItem unresolved) { + return CompletableFuture.completedFuture(unresolved); + } + + Either cachedCompModuleForFileUri = null; + + /** + * the file uri of the cached module. If this is not null, the cached module is + * valid for the uri + */ + String cachedCompModuleForFileUri_Uri = null; + + CompModule getCompModuleForFileUri(String uri) { + // log("getCompModuleForFileUri (" + uri + ")"); + if (uri.equals(cachedCompModuleForFileUri_Uri)) { + return getResult(cachedCompModuleForFileUri); + } + + try { + String path = fileUriToPath(uri); + + // Try to return a nullModule object for non-AlloyMarkdown files. + // Not a big deal if the file has not been cached + String contents = fileContents.get(uri); + if (contents != null && !isAlloyFile(path, contents)) { + return CompUtil.nullModule(); + } + + cachedCompModuleForFileUri = Either.forLeft(CompUtil.parseEverything_fromFile(null, fileContentsPathBased(), path, 2)); + + } catch (Err err) { + log("getCompModuleForFileUri(): error in parsing: " + err.toString()); + fileUrisOfLastPublishedDiagnostics.add(uri); + + client.publishDiagnostics(toPublishDiagnosticsParams(err)); + + if (err instanceof ErrorSyntax) + latestFileUrisWithSyntaxError.add(uri); + + cachedCompModuleForFileUri = Either.forRight(err); + throw err; + } + + if (latestFileUrisWithSyntaxError.contains(uri)) { + client.publishDiagnostics(newPublishDiagnosticsParams(uri, Arrays.asList())); + latestFileUrisWithSyntaxError.remove(uri); + } + cachedCompModuleForFileUri_Uri = uri; + return getResult(cachedCompModuleForFileUri); + } + + @Override + public CompletableFuture hover(TextDocumentPositionParams position) { + //log("hover request"); + String hoverStr = null; + try { + + String uri = position.getTextDocument().getUri(); + String text = fileContents.get(uri); + CompModule module = getCompModuleForFileUri(uri); + + Pos pos = positionToPos(position.getPosition()); + Expr expr = module.find(pos); + if (expr instanceof ExprBad) { + hoverStr = expr.toString(); + } else if (expr != null) { + Clause referenced = expr.referenced(); + if (referenced != null) { + hoverStr = referenced.explain(); + } else if (expr instanceof ExprConstant) { + String token = pos.substring(text); + if (token != null) { + String match = expr.toString(); + if (!Objects.equals(token, match)) + hoverStr = match; + } + } + } + } catch (Exception e) { + // ignore compile errors etc. + } + if (hoverStr != null) { + MarkupContent markupContent = new MarkupContent(); + markupContent.setKind("markdown"); + + hoverStr = "```\n" + hoverStr + "\n```"; + + markupContent.setValue(hoverStr); + Hover res = new Hover(); + res.setContents(markupContent); + return CompletableFuture.completedFuture(res); + } else { + return CompletableFuture.completedFuture(null); + } + } + + @Override + public CompletableFuture signatureHelp(TextDocumentPositionParams position) { + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture> definition(TextDocumentPositionParams position) { + try { + String uri = position.getTextDocument().getUri(); + String text = fileContents.get(uri); + String path = fileUriToPath(uri); + + CompModule module = getCompModuleForFileUri(uri); + Pos pos = positionToPos(position.getPosition(), path); + pos = getCurrentWordSelectionAsPos(text, pos); + Expr expr = module.find(pos); + + log("definition request for: " + expr); + + if (expr != null) { + Clause clause = expr.referenced(); + if (clause != null) { + Pos where = clause.pos(); + + //if path includes the jar, replace it by the created temp dir containing alloy models + String fileName = filePathResolved(where.filename); + + String targetUri = where.sameFile(module.pos()) ? uri : filePathToUri(fileName); + Location res = Lsp4jUtil.newLocation(createRangeFromPos(where), targetUri); + return CompletableFuture.completedFuture(Arrays.asList(res)); + } + } + + } catch (Exception ex) { + System.err.println("Error in providing definition: " + ex.toString()); + } + return CompletableFuture.completedFuture(Arrays.asList()); + } + + + + @Override + public CompletableFuture> references(ReferenceParams params) { + + String uri = params.getTextDocument().getUri(); + String text = fileContents.get(uri); + String path = fileUriToPath(uri); + + try { + CompModule module = getCompModuleForFileUri(params.getTextDocument().getUri()); + + Pos pos = getPosOfSymbolFromPositionInOpenDoc(params.getTextDocument().getUri(), params.getPosition()); + pos = getCurrentWordSelectionAsPos(text, pos).withFilename(path); + + String dir = this.directory != null ? this.directory : new File(path).getParent(); + List res = findAllReferencesGlobally(module, pos, dir, true, true).stream().map(ref -> posToLocation(ref)).collect(Collectors.toList()); + return CompletableFuture.completedFuture(res); + } catch (Err err) { + client.showMessage(newMessageParams("There are errors. Fix them first.", MessageType.Warning)); + return CompletableFuture.completedFuture(null); + } + } + + @Override + public CompletableFuture rename(RenameParams params) { + String uri = params.getTextDocument().getUri(); + String text = fileContents.get(uri); + String path = fileUriToPath(uri); + + try { + CompModule module = getCompModuleForFileUri(uri); + + Pos pos = getPosOfSymbolFromPositionInOpenDoc(uri, params.getPosition()); + pos = getCurrentWordSelectionAsPos(text, pos).withFilename(path); + + Expr expr = module.find(pos); + Pos targetPos = expr.referenced() != null ? expr.referenced().pos() : expr.pos; + + CompModule targetModule = CompUtil.parseEverything_fromFile(null, fileContentsPathBased(), filePathResolved(targetPos.filename)); + + Expr targetExpr = targetModule.find(targetPos); + + Map> changes = new HashMap<>(); + + String dir = this.directory != null ? this.directory : new File(path).getParent(); + List refs = findAllReferencesGlobally(module, pos, dir, false, false); + + if (targetExpr instanceof Sig) { + targetPos = ((Sig) targetExpr).labelPos; + } else if (targetExpr instanceof Field) { + targetPos = ((Field) targetExpr).labelPos; + } else if (targetExpr instanceof Func) { + targetPos = ((Func) targetExpr).labelPos; + } else if (targetExpr instanceof Assert) { + targetPos = ((Assert) targetExpr).labelPos; + } else if (targetExpr instanceof Macro) { + targetPos = ((Macro) targetExpr).namePos; + } + + WorkspaceEdit wEdit = new WorkspaceEdit(); + Stream.concat(refs.stream().distinct(), Stream.of(targetPos)).forEach(refPos -> { + TextEdit edit = new TextEdit(); + + edit.setRange(createRangeFromPos(refPos)); + edit.setNewText(params.getNewName()); + + String refUri = filePathToUri(filePathResolved(refPos.filename)); + + if (!changes.containsKey(refUri)) + changes.put(refUri, new ArrayList<>()); + changes.get(refUri).add(edit); + }); + + wEdit.setChanges(changes); + + return CompletableFuture.completedFuture(wEdit); + + } catch (Err err) { + client.showMessage(newMessageParams("Cannot rename symbol while there are errors. Fix the errors first.", MessageType.Warning)); + return CompletableFuture.completedFuture(null); + } + } + + Pos getPosOfSymbolFromPositionInOpenDoc(String uri, Position position) { + String path = fileUriToPath(uri); + String text = fileContents.get(uri); + + Pos pos = positionToPos(position, path); + pos = getCurrentWordSelectionAsPos(text, pos); + return pos; + } + + @Override + public CompletableFuture> documentHighlight(TextDocumentPositionParams position) { + + try { + CompModule module = getCompModuleForFileUri(position.getTextDocument().getUri()); + + Pos pos = getPosOfSymbolFromPositionInOpenDoc(position.getTextDocument().getUri(), position.getPosition()); + List refs = findAllReferences(module, pos, true); + + String path = fileUriToPath(position.getTextDocument().getUri()); + List res = refs.stream().filter(ref -> path.equals(ref.pos.filename)).map(ref -> { + DocumentHighlight highlight = new DocumentHighlight(); + + highlight.setKind(DocumentHighlightKind.Text); + highlight.setRange(createRangeFromPos(ref.pos)); + return highlight; + }).collect(Collectors.toList()); + + return CompletableFuture.completedFuture(res); + + } catch (Exception ex) { + return CompletableFuture.completedFuture(null); + } + } + + @Override + public CompletableFuture> documentSymbol(DocumentSymbolParams params) { + try { + CompModule module = getCompModuleForFileUri(params.getTextDocument().getUri()); + return CompletableFuture.completedFuture(moduleSymbols(module)); + } catch (Exception ex) { + return CompletableFuture.completedFuture(null); + } + } + + private List folderSymbols(String dir) { + List res = new ArrayList<>(); + + for (File child : alloyFilesInDir(dir)) { + String filePath = fileUriToPath(child.toURI().toString()); + try { + CompModule module = CompUtil.parseEverything_fromFile(null, fileContentsPathBased(), filePath); + res.addAll(moduleSymbols(module)); + } catch (Exception ex) { + log("error parsing " + child); + } + } + + return res; + } + + private static List moduleSymbols(CompModule module) { + Stream commands = module.getAllCommands().stream().map(c -> newSymbolInformation(c.label, posToLocation(c.pos), SymbolKind.Event)); + + Stream sigs = module.getAllSigs().makeConstList().stream().map(sig -> newSymbolInformation(sig.label, posToLocation(sig.pos), sig.isEnum != null ? SymbolKind.Enum : sig.isEnumMember() ? SymbolKind.EnumMember : sig.isOne != null || sig.isLone != null ? SymbolKind.Object : SymbolKind.Class)); + + Stream fields = module.getAllSigs().makeConstList().stream().flatMap(sig -> sig.getFields().makeConstList().stream()).map(field -> { + SymbolInformation symbolInfo = newSymbolInformation(field.label, posToLocation(field.pos), SymbolKind.Field); + symbolInfo.setContainerName(removeThisPrefix(field.sig.label)); + return symbolInfo; + }); + + Stream funcs = module.getAllFunc().makeConstList().stream().map(func -> newSymbolInformation(func.label, posToLocation(func.pos), func.isPred ? SymbolKind.Boolean : SymbolKind.Function)); + + Stream macros = module.getAllMacros().makeConstList().stream().map(macro -> newSymbolInformation(macro.name, posToLocation(macro.pos), SymbolKind.Constructor)); + + Stream assertions = module.getAllAssertions().stream().map(assertion -> newSymbolInformation(assertion.label, posToLocation(assertion.pos), SymbolKind.Property)); + + return Stream.of(commands, sigs, fields, funcs, assertions, macros).flatMap(x -> x).map(x -> { + x.setName(removeThisPrefix(x.getName())); + return x; + }) + //.sorted((sym1,sym2) -> positionCompare(sym1.getLocation().getRange().getStart(), sym2.getLocation().getRange().getStart())) + .collect(Collectors.toList()); + } + + @Override + public CompletableFuture> codeAction(CodeActionParams params) { + return CompletableFuture.completedFuture(null); + } + + List> getCommands(String uri) { + CompModule module; + + try { + module = getCompModuleForFileUri(uri); + } catch (Exception e) { + return Arrays.asList(); + } + + ConstList commands = module.getAllCommands(); + + ArrayList> res = new ArrayList<>(); + + for (int i = 0; i < commands.size(); i++) { + edu.mit.csail.sdg.ast.Command command = commands.get(i); + Position position = posToPosition(command.pos); + CodeLens codeLens = new CodeLens(); + codeLens.setRange(createRange(position, position)); + Command vsCommand = new Command("Execute", "ExecuteAlloyCommand"); + vsCommand.setArguments(Arrays.asList(uri, i, position.getLine(), position.getCharacter())); + codeLens.setCommand(vsCommand); + + res.add(new Pair<>(command, vsCommand)); + } + + if (latestFileUrisWithSyntaxError.contains(uri)) { + client.publishDiagnostics(newPublishDiagnosticsParams(uri, Arrays.asList())); + latestFileUrisWithSyntaxError.remove(uri); + } + return res; + } + + @Override + public CompletableFuture> codeLens(CodeLensParams params) { + + List res = getCommands(params.getTextDocument().getUri()).stream().map(pair -> { + edu.mit.csail.sdg.ast.Command command = pair.a; + Command vsCommand = pair.b; + + CodeLens codeLens = new CodeLens(); + codeLens.setRange(createRangeFromPos(command.pos)); + codeLens.setCommand(vsCommand); + + return codeLens; + }).collect(Collectors.toList()); + + return CompletableFuture.completedFuture(res); + } + + @Override + public CompletableFuture> documentLink(DocumentLinkParams params) { + + List links = getCommands(params.getTextDocument().getUri()).stream().map(pair -> { + edu.mit.csail.sdg.ast.Command command = pair.a; + Command vsCommand = pair.b; + + DocumentLink link = new DocumentLink(); + link.setRange(createRangeFromPos(command.commandKeyword.pos)); + List args = vsCommand.getArguments(); + Gson gson = new Gson(); + try { + java.net.URI path = new java.net.URI((String) args.get(0)); + args.set(0, path.toString()); + System.err.println("gson.toJson(args): " + gson.toJson(args)); + link.setTarget("command:" + vsCommand.getCommand() + "?" + gson.toJson(args)); + // URLEncoder.encode(gson.toJson(args), "UTF-8") ); + // } catch (UnsupportedEncodingException e1) { + } catch (URISyntaxException e) { + } + + return link; + }).collect(Collectors.toList()); + + return CompletableFuture.completedFuture(links); + + } + + @JsonRequest + public CompletableFuture ListAlloyCommands(JsonPrimitive documentUri) { + log("ListAlloyCommands called with " + documentUri + ", of type " + documentUri.getClass().getName()); + List res = getCommands(documentUri.getAsString()).stream().map(pair -> new CommandsListResultItem(pair.a.toString(), pair.b)).collect(Collectors.toList()); + + client.commandsListResult(new CommandsListResult(res)); + return CompletableFuture.completedFuture(null); + } + + private final HashSet fileUrisOfLastPublishedDiagnostics = new HashSet<>(); + private final Set latestFileUrisWithSyntaxError = new HashSet<>(); + + @JsonRequest + public CompletableFuture ExecuteAlloyCommand(com.google.gson.JsonArray params) { + log("ExecuteAlloyCommand() called with " + params + ", " + params.getClass()); + String uri = params.get(0).getAsString(); + int ind = params.get(1).getAsInt(); + int line = params.get(2).getAsInt(), character = params.get(3).getAsInt(); + + Position position = new Position(line, character); + Pos pos = positionToPos(position); + String fileString = fileContents.get(uri); + // Ugly hack to make the uri look like what it was if invoked through links + // if (fileString == null) { + // java.net.URI uriObj = new java.net.URI(uri); + // String newPath = uriObj.getRawPath().replace(":", "%3A"); + // String newUri = uriObj.getScheme() + newPath; + // fileString = fileContents.get(newUri); + // } + // Another ugly hack to make things work if invoked through links (which makes the uri look different) + if (fileString == null) { + String uriPath = fileUriToPath(uri); + for (Map.Entry entry : fileContents.entrySet()) { + if (fileUriToPath(entry.getKey()).equals(uriPath)) { + fileString = entry.getValue(); + uri = entry.getKey(); + break; + } + } + } + if (fileString == null) { + System.err.println("Error in ExecuteAlloyCommand: failed to retrieve file contents for " + uri); + return CompletableFuture.completedFuture(null); + } + CompModule module = CompUtil.parseOneModule(fileString); + ConstList commands = module.getAllCommands(); + edu.mit.csail.sdg.ast.Command command = commands.stream().filter(comm -> comm.pos().y == pos.y && comm.pos.x == pos.x).findFirst().orElse(null); + if (command != null || ind == -1) { + String uriToShutUpStupidJava = uri; + CompletableFuture.runAsync(() -> doRun(uriToShutUpStupidJava, ind)); + } else { + System.err.println("no matching command found"); + } + + return CompletableFuture.completedFuture(null); + } + + @JsonRequest + public CompletableFuture StopExecution(Object o) { + log("Stop req received"); + doStop(2); + + AlloyLSMessage alloyMsg = new AlloyLSMessage(RunCompleted, "Stopped"); + alloyMsg.bold = true; + client.showExecutionOutput(alloyMsg); + + return CompletableFuture.completedFuture(null); + } + + @JsonRequest + public CompletableFuture OpenModel(com.google.gson.JsonPrimitive link) { + log("OpenModel() called with " + link.getAsString()); + log(" , of type" + link.getClass().getName()); + doVisualize(link.getAsString()); + return CompletableFuture.completedFuture(null); + } + + + + @Override + public CompletableFuture resolveCodeLens(CodeLens unresolved) { + return CompletableFuture.completedFuture(unresolved); + } + + @Override + public CompletableFuture> formatting(DocumentFormattingParams params) { + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture> rangeFormatting(DocumentRangeFormattingParams params) { + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture> onTypeFormatting(DocumentOnTypeFormattingParams params) { + return CompletableFuture.completedFuture(null); + } + + + private Map fileContentsPathBased() { + HashMap res = new HashMap(); + fileContents.entrySet().stream().forEach(entry -> res.put(fileUriToPath(entry.getKey()), entry.getValue())); + return res; + } + + private HashMap fileContents = new HashMap<>(); + + @Override + public void didOpen(DidOpenTextDocumentParams params) { + String text = params.getTextDocument().getText(); + String uri = params.getTextDocument().getUri(); + fileContents.put(uri, text); + } + + @Override + public void didChange(DidChangeTextDocumentParams params) { + // https://raw.githubusercontent.com/eclipse/eclipse.jdt.ls/0ed1bf259b3edb4f184804a9df14c95ef468d4e9/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandler.java + String text = params.getContentChanges().get(0).getText(); + String uri = params.getTextDocument().getUri(); + fileContents.put(uri, text); + + cachedCompModuleForFileUri = null; + cachedCompModuleForFileUri_Uri = null; + } + + @Override + public void didSave(DidSaveTextDocumentParams params) { + String text = params.getText(); + + if (text != null) { + String uri = params.getTextDocument().getUri(); + fileContents.put(uri, text); + + cachedCompModuleForFileUri = null; + cachedCompModuleForFileUri_Uri = null; + } + } + + // WorkspaceService methods + @Override + public void didClose(DidCloseTextDocumentParams params) { + fileContents.remove(params.getTextDocument().getUri()); + } + + @Override + public CompletableFuture> symbol(WorkspaceSymbolParams params) { + + if (this.directory == null) + return CompletableFuture.completedFuture(null); + + List res = folderSymbols(this.directory).stream().filter(symbol -> { + return symbol.getName().toLowerCase().contains(params.getQuery().toLowerCase()); + }).collect(Collectors.toList()); + + return CompletableFuture.completedFuture(res); + } + + @Override + public void didChangeConfiguration(DidChangeConfigurationParams params) { + } + + @Override + public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) { + } + + static String removeThisPrefix(String name) { + if (name.startsWith("this/")) { + return name.substring("this/".length()); + } + return name; + } + + private PublishDiagnosticsParams toPublishDiagnosticsParams(Err err) { + return toPublishDiagnosticsParamsList(Arrays.asList(err)).get(0); + } + + private List toPublishDiagnosticsParamsList(List errors) { + + Map> map = errors.stream().collect(Collectors.groupingBy(warning -> warning.pos.filename)); + return map.entrySet().stream().map(entry -> { + + List diags = entry.getValue().stream().map(err -> { + Diagnostic diag = newDiagnostic(err.msg, createRangeFromPos(err.pos)); + diag.setSeverity(err instanceof ErrorWarning ? DiagnosticSeverity.Warning : DiagnosticSeverity.Error); + + return diag; + }).collect(Collectors.toList()); + + return newPublishDiagnosticsParams(filePathToUri(entry.getKey()), diags); + }).collect(Collectors.toList()); + } + + private String newInstance; + private VizGUI viz; + + // edu.mit.csail.sdg.alloy4whole.SimpleGUI.doRun(Integer) + private void doRun(String fileURI, Integer commandIndex) { + CompModule module = CompUtil.parseOneModule(fileContents.get(fileURI)); + ConstList commands = module.getAllCommands(); + + final int index = commandIndex; + if (WorkerEngine.isBusy() || (commands == null)) + return; + if (commands.size() == 0 && index != -2 && index != -3) { + // log.logRed("There are no commands to execute.\n\n"); + return; + } + int i = index; + if (i >= commands.size()) + i = commands.size() - 1; + // SimpleCallback1 cb = new SimpleCallback1(this, null, log, + // VerbosityPref.get().ordinal(), latestAlloyVersionName, latestAlloyVersion); + SimpleTask1 task = new SimpleTask1(); + A4Options opt = new A4Options(); + opt.tempDirectory = SimpleGUI.alloyHome(null) + fs + "tmp"; + opt.solverDirectory = SimpleGUI.alloyHome(null) + fs + "binary"; + opt.recordKodkod = RecordKodkod.get(); + opt.noOverflow = NoOverflow.get(); + opt.unrolls = Version.experimental ? Unrolls.get() : (-1); + opt.skolemDepth = SkolemDepth.get(); + opt.coreMinimization = CoreMinimization.get(); + opt.inferPartialInstance = InferPartialInstance.get(); + opt.coreGranularity = CoreGranularity.get(); + + log("cwd :" + Paths.get("").toAbsolutePath()); + + String fileNameDecoded; + try { + fileNameDecoded = URIUtil.toFile(new URI(fileURI)).getPath(); + + } catch (Exception ex) { + System.err.println("failed to parse uri"); + return; + } + log("fileNameDecoded:" + fileNameDecoded); + + opt.originalFilename = fileNameDecoded;// new File(decodeUrl(uri)).getPath();// Util.canon(decodeUrl(uri)); + opt.solver = Solver.get(); + task.bundleIndex = i; + task.bundleWarningNonFatal = WarningNonfatal.get(); + // task.map = text.takeSnapshot(); + task.options = opt.dup(); + task.resolutionMode = (Version.experimental && ImplicitThis.get()) ? 2 : 1; + task.tempdir = SimpleGUI.maketemp(null); + + try { + int newmem = SubMemory.get(), newstack = SubStack.get(); + if (newmem != subMemoryNow || newstack != subStackNow) + WorkerEngine.stop(); + + WorkerCallback cb = getWorkerCallback(); + + log("actually running the task"); + // if (AlloyCore.isDebug() && VerbosityPref.get() == Verbosity.FULLDEBUG) + //WorkerEngine.runLocally(task, cb); + // else + WorkerEngine.run(task, newmem, newstack, SimpleGUI.alloyHome(null) + fs + "binary", "", cb); + subMemoryNow = newmem; + subStackNow = newstack; + } catch (Throwable ex) { + WorkerEngine.stop(); + System.err.println("Fatal Error: Solver failed due to unknown reason. exception: \n" + ex.toString()); + // log.logBold("Fatal Error: Solver failed due to unknown reason.\n" + "One + // possible cause is that, in the Options menu, your specified\n" + "memory size + // is larger than the amount allowed by your OS.\n" + "Also, please make sure + // \"java\" is in your program path.\n"); + // log.logDivider(); + // log.flush(); + doStop(2); + } + return; + } + + private WorkerCallback getVizWorkerCallback() { + return new WorkerCallback() { + + @Override + public void fail() { + AlloyLSMessage alloyMsg = new AlloyLSMessage(AlloyLSMessageType.RunCompleted, "failure"); + client.showExecutionOutput(alloyMsg); + + } + + @Override + public void done() { + viz.loadXML(newInstance, true); + + } + + @Override + public void callback(Object msg) { + Either,Err> alloyMsgOrWarning = solverCallbackMsgToAlloyMsg(msg); + + if (alloyMsgOrWarning.isLeft()) { + for (AlloyLSMessage alloyMsg : alloyMsgOrWarning.getLeft()) { + if (alloyMsg.message != null && !alloyMsg.message.isEmpty()) + //client.showExecutionOutput(alloyMsg); + client.logMessage(newMessageParams(alloyMsg.message, MessageType.Log)); + } + + } else { + //warnings.add(alloyMsgOrWarning.getRight()); + } + + } + }; + } + + private WorkerCallback getWorkerCallback() { + return new WorkerCallback() { + + List warnings = new ArrayList<>(); + + @Override + public void callback(Object msg) { + + // MessageParams messageParams= new MessageParams(); + // messageParams.setMessage(solverCallbackMsgToString(msg)); + // client.showMessage(messageParams); + // if(messageParams.getMessage() != null && !messageParams.getMessage().isEmpty()) + // client.showAlloyOutput(messageParams); + + Either,Err> alloyMsgOrWarning = solverCallbackMsgToAlloyMsg(msg); + + if (alloyMsgOrWarning.isLeft()) { + for (AlloyLSMessage alloyMsg : alloyMsgOrWarning.getLeft()) { + if (alloyMsg.message != null && !alloyMsg.message.isEmpty()) + client.showExecutionOutput(alloyMsg); + } + + } else { + Err err = alloyMsgOrWarning.getRight(); + + if (Pos.UNKNOWN.equals(err.pos) || err.pos == null) { + AlloyLSMessage errMsg = new AlloyLSMessage(AlloyLSMessageType.Warning, err.msg + "\n"); + errMsg.bold = true; + client.showExecutionOutput(errMsg); + } + warnings.add(alloyMsgOrWarning.getRight()); + } + } + + @Override + public void done() { + // MessageParams messageParams= new MessageParams(); + // messageParams.setMessage("done"); + // client.showMessage(messageParams); + // client.showAlloyOutput(messageParams); + if (warnings.size() > 0) + client.showExecutionOutput(new AlloyLSMessage(AlloyLSMessageType.RunResult, "There were errors/warnings!")); + + client.showExecutionOutput(new AlloyLSMessage(AlloyLSMessageType.RunCompleted, "")); + + publishDiagnostics(); + } + + @Override + public void fail() { + AlloyLSMessage alloyMsg = new AlloyLSMessage(AlloyLSMessageType.RunCompleted, "failure"); + client.showExecutionOutput(alloyMsg); + publishDiagnostics(); + } + + void publishDiagnostics() { + + //cleaning previously reported diagnostics + if (fileUrisOfLastPublishedDiagnostics != null) + fileUrisOfLastPublishedDiagnostics.stream().forEach(item -> { + PublishDiagnosticsParams diagnostics = new PublishDiagnosticsParams(); + diagnostics.setUri(item); + client.publishDiagnostics(diagnostics); + }); + + List diagnosticsParamsList = toPublishDiagnosticsParamsList(warnings); + + diagnosticsParamsList.forEach(diagsParams -> client.publishDiagnostics(diagsParams)); + + fileUrisOfLastPublishedDiagnostics.clear(); + fileUrisOfLastPublishedDiagnostics.addAll(diagnosticsParamsList.stream().map(item -> item.getUri()).collect(Collectors.toList())); + + } + + }; + } + + // edu.mit.csail.sdg.alloy4whole.SimpleReporter.SimpleCallback1.callback(Object) + public Either,Err> solverCallbackMsgToAlloyMsg(Object msg) { + StringBuilder span = new StringBuilder(); + AlloyLSMessage alloyMsg = new AlloyLSMessage(AlloyLSMessageType.RunInProgress, null); + + List resMsgs = new ArrayList<>(); + resMsgs.add(alloyMsg); + + final int verbosity = 0; + if (msg == null) { + span.append("Done\n"); + } else if (msg instanceof String) { + span.append(((String) msg).trim() + "\n"); + } else if (msg instanceof Throwable) { + for (Throwable ex = (Throwable) msg; ex != null; ex = ex.getCause()) { + if (ex instanceof OutOfMemoryError) { + span.append("\nFatal Error: the solver ran out of memory!\n" + "Try simplifying your model or reducing the scope,\n" + "or increase memory under the Options menu.\n"); + } + if (ex instanceof StackOverflowError) { + span.append("\nFatal Error: the solver ran out of stack space!\n" + "Try simplifying your model or reducing the scope,\n" + "or increase stack under the Options menu.\n"); + } + } + if (msg instanceof Err) { + log("Err msg from solver: " + msg.toString()); + Err ex = (Err) msg; + String text = "fatal"; + boolean fatal = false; + if (ex instanceof ErrorSyntax) + text = "syntax"; + else if (ex instanceof ErrorType) + text = "type"; + else + fatal = true; + if (ex.pos == Pos.UNKNOWN) + span.append("A " + text + " error has occurred: "); + else + span.append("A " + text + " error has occurred: " + "POS: " + ex.pos.x + " " + ex.pos.y + " " + ex.pos.x2 + " " + ex.pos.y2 + " " + ex.pos.filename); + // if (verbosity > 2) { + // span.log("(see the "); + // span.logLink("stacktrace", "MSG: " + ex.dump()); + // span.log(")\n"); + // } else { + // span.log("\n"); + // } + span.append(ex.msg.trim()); // logIndented + return Either.forRight(ex); + //span.append("\n"); + // if (fatal && latestVersion > Version.buildNumber()) + // span.logBold("\nNote: You are running Alloy build#" + Version.buildNumber() + ",\nbut the most recent is Alloy build#" + latestVersion + ":\n( version " + latestName + " )\nPlease try to upgrade to the newest version," + "\nas the problem may have been fixed already.\n"); + + // if (!fatal) + // gui.doVisualize("POS: " + ex.pos.x + " " + ex.pos.y + " " + ex.pos.x2 + " " + ex.pos.y2 + " " + ex.pos.filename); + } else /* if (msg instanceof Throwable) */ { + log("exception msg from solver: " + msg.toString()); + Throwable ex = (Throwable) msg; + span.append(ex.toString().trim() + "\n"); + // span.flush(); + } + } else if ((msg instanceof Object[])) { + Object[] array = (Object[]) msg; + if (array[0].equals("pop")) { + // span.setLength(len2); + String x = (String) (array[1]); + span.append(x); + alloyMsg.replaceLast = true; + // if (viz != null && x.length() > 0) + // OurDialog.alert(x); + } + if (array[0].equals("declare")) { + //gui.doSetLatest((String) (array[1])); + newInstance = (String) (array[1]); + // ========== + } + if (array[0].equals("S2")) { + // len3 = len2 = span.getLength(); + span.append("" + array[1]); + } + if (array[0].equals("R3")) { + //span.setLength(len3); + span.append("" + array[1]); + } + if (array[0].equals("link")) { + log("link message!!!"); + //span.logLink((String) (array[1]), (String) (array[2])); + span.append(array[1].toString()); + alloyMsg.link = (String) array[2]; + alloyMsg.messageType = AlloyLSMessageType.RunResult; + + } + if (array[0].equals("bold")) { + span.append("" + array[1]); + alloyMsg.bold = true; + //alloyMsg.replaceLast = true; + } + if (array[0].equals("")) { + span.append("" + array[1]); + } + if (array[0].equals("scope") && verbosity > 0) { + span.append(" " + array[1]); + } + if (array[0].equals("bound") && verbosity > 1) { + span.append(" " + array[1]); + } + if (array[0].equals("resultCNF")) { + // results.add(null); + // span.setLength(len3); + // span.log(" File written to " + array[1] + "\n\n"); + } + if (array[0].equals("debug") && verbosity > 2) { + span.append(" " + array[1] + "\n"); + // len2 = len3 = span.getLength(); + } + if (array[0].equals("translate")) { + span.append(" " + array[1]); + // len3 = span.getLength(); + span.append(" Generating CNF...\n"); + } + if (array[0].equals("solve")) { + // span.setLength(len3); + span.append(" " + array[1]); + // len3 = span.getLength(); + span.append(" Solving...\n"); + } + if (array[0].equals("warnings")) { + // if (warnings.size() == 0) + // span.setLength(len2); + // else if (warnings.size() > 1) + // span.logBold("Note: There were " + warnings.size() + " compilation warnings. Please scroll up to see them.\n\n"); + // else + // span.append("Note: There was 1 compilation wrearning. Please scroll up to see + // them.\n\n"); + // span.append("There were warnings!"); + // if (warnings.size() > 0 && Boolean.FALSE.equals(array[1])) { + // Pos e = warnings.iterator().next().pos; + // gui.doVisualize("POS: " + e.x + " " + e.y + " " + e.x2 + " " + e.y2 + " " + e.filename); + // span.logBold("Warnings often indicate errors in the model.\n" + "Some warnings can affect the soundness of the analysis.\n" + "To proceed despite the warnings, go to the Options menu.\n"); + // } + } + if (array[0].equals("warning")) { + ErrorWarning e = (ErrorWarning) (array[1]); + // if (!warnings.add(e)) + // return; + Pos p = e.pos; + // span.logLink("Warning #" + warnings.size(), "POS: " + p.x + " " + p.y + " " + p.x2 + " " + p.y2 + " " + p.filename); + span.append("Warning " + e.msg.trim());// #" + warnings.size(), "POS: " + p.x + " " + p.y + " " + p.x2 + + // " " + p.y2 + " " + p.filename); + return Either.forRight(e); + // span.log("\n"); + // span.logIndented(e.msg.trim()); + // span.log("\n\n"); + } + if (array[0].equals("sat")) { + boolean chk = Boolean.TRUE.equals(array[1]); + int expects = (Integer) (array[2]); + String filename = (String) (array[3]), formula = (String) (array[4]); + // results.add(filename); + (new File(filename)).deleteOnExit(); + // gui.doSetLatest(filename); + // span.setLength(len3); + span.append(" "); + // span.logLink(chk ? "Counterexample" : "Instance", "XML: " + filename); + span.append(chk ? "Counterexample" : "Instance");// , "XML: " + filename); + alloyMsg.link = "XML: " + filename; + alloyMsg.messageType = AlloyLSMessageType.RunResult; + alloyMsg.replaceLast = true; + alloyMsg.bold = true; + span.append(" found. "); + // span.logLink(chk ? "Assertion" : "Predicate", formula); + span.append(chk ? "Assertion" : "Predicate");// , formula); + span.append(chk ? " is invalid" : " is consistent"); + if (expects == 0) + span.append(", contrary to expectation"); + else if (expects == 1) + span.append(", as expected"); + span.append(". "); + //span.append(". " + array[5] + "ms.\n\n"); + alloyMsg.lineBreak = false; + resMsgs.add(new AlloyLSMessage(AlloyLSMessageType.RunResult, array[5] + "ms.\n\n")); + } + if (array[0].equals("metamodel")) { + // String outf = (String) (array[1]); + // span.setLength(len2); + // (new File(outf)).deleteOnExit(); + // gui.doSetLatest(outf); + // span.logLink("Metamodel", "XML: " + outf); + // span.log(" successfully generated.\n\n"); + } + if (array[0].equals("minimizing")) { + boolean chk = Boolean.TRUE.equals(array[1]); + // int expects = (Integer) (array[2]); + // span.setLength(len3); + // span.log(chk ? " No counterexample found." : " No instance found."); + span.append(chk ? " No counterexample found. " : " No instance found. "); + if (chk) + span.append(" Assertion may be valid"); + else + span.append(" Predicate may be inconsistent"); + // if (expects == 1) + // span.log(", contrary to expectation"); + // else if (expects == 0) + // span.log(", as expected"); + span.append(". " + array[4] + "ms.\n"); + // span.logBold(" Minimizing the unsat core of " + array[3] + " entries...\n"); + } + if (array[0].equals("unsat")) { + boolean chk = Boolean.TRUE.equals(array[1]); + int expects = (Integer) (array[2]); + String formula = (String) (array[4]); + // span.setLength(len3); + alloyMsg.messageType = AlloyLSMessageType.RunResult; + alloyMsg.replaceLast = true; + alloyMsg.bold = true; + span.append(chk ? " No counterexample found. " : " No instance found. "); + span.append(chk ? "Assertion" : "Predicate");// , formula); + span.append(chk ? " may be valid" : " may be inconsistent"); + if (expects == 1) + span.append(", contrary to expectation"); + else if (expects == 0) + span.append(", as expected"); + if (array.length == 5) { + span.append(". "); + alloyMsg.lineBreak = false; + resMsgs.add(new AlloyLSMessage(RunResult, array[3] + "ms.\n\n")); + // span.flush(); + } else { + String core = (String) (array[5]); + int mbefore = (Integer) (array[6]), mafter = (Integer) (array[7]); + span.append(". " + array[3] + "ms.\n"); + if (core.length() == 0) { + // results.add(""); + span.append(" No unsat core is available in this case. "); + + resMsgs.add(new AlloyLSMessage(RunResult, array[8] + "ms.\n\n")); + // span.flush(); + } else { + + // results.add(core); + (new File(core)).deleteOnExit(); + span.append(" "); + //span.append("Core");// , core); + + AlloyLSMessage coreLinkMsg = new AlloyLSMessage(RunResult, "core"); + coreLinkMsg.link = core; + resMsgs.add(coreLinkMsg); + + AlloyLSMessage nextMsg = new AlloyLSMessage(RunResult, null); + if (mbefore <= mafter) + nextMsg.message = (" contains " + mafter + " top-level formulas. " + array[8] + "ms.\n\n"); + else + nextMsg.message = (" reduced from " + mbefore + " to " + mafter + " top-level formulas. " + array[8] + "ms.\n\n"); + resMsgs.add(nextMsg); + } + } + } + } + alloyMsg.message = span.toString(); + return Either.forLeft(resMsgs); + } + + /** + * This method stops the current run or check (how==0 means DONE, how==1 means + * FAIL, how==2 means STOP). + */ + void doStop(Integer how) { + int h = how; + if (h != 0) { + if (h == 2 && WorkerEngine.isBusy()) { + WorkerEngine.stop(); + //log.logBold("\nSolving Stopped.\n"); + //log.logDivider(); + } + WorkerEngine.stop(); + } + // runmenu.setEnabled(true); + // runbutton.setVisible(true); + // showbutton.setEnabled(true); + // stopbutton.setVisible(false); + // if (latestAutoInstance.length() > 0) { + // String f = latestAutoInstance; + // latestAutoInstance = ""; + // if (subrunningTask == 2) + // viz.loadXML(f, true); + // else if (AutoVisualize.get() || subrunningTask == 1) + // doVisualize("XML: " + f); + // } + } + + // edu.mit.csail.sdg.alloy4whole.SimpleGUI.doVisualize(String) for handling + // instance visualization links + + private void doVisualize(String arg) { + log("doVisualize() called with " + arg); + if (arg.startsWith("CORE: ")) { // CORE: filename + String filename = Util.canon(arg.substring(6)); + Pair,Set> hCore; + // Set lCore; + InputStream is = null; + ObjectInputStream ois = null; + try { + is = new FileInputStream(filename); + ois = new ObjectInputStream(is); + hCore = (Pair,Set>) ois.readObject(); + // lCore = (Set) ois.readObject(); + List errs = Stream.concat(hCore.a.stream().map(pos -> new ErrorWarning(pos, "part of unsat core")), hCore.b.stream().map(pos -> new ErrorWarning(pos, "possibly part of unsat core"))).collect(Collectors.toList()); + + List publishDiags = this.toPublishDiagnosticsParamsList(errs); + + fileUrisOfLastPublishedDiagnostics.clear(); + fileUrisOfLastPublishedDiagnostics.addAll(publishDiags.stream().map(PublishDiagnosticsParams::getUri).collect(Collectors.toList())); + + publishDiags.forEach(client::publishDiagnostics); + + } catch (Throwable ex) { + System.err.println("Error reading or parsing the core \"" + filename + "\"\n"); + // return null; + } finally { + Util.close(ois); + Util.close(is); + } + + + + // text.clearShade(); + // text.shade(hCore.b, subCoreColor, false); + // text.shade(hCore.a, coreColor, false); + // // shade again, because if not all files were open, some shadings + // // will have no effect + // text.shade(hCore.b, subCoreColor, false); + // text.shade(hCore.a, coreColor, false); + } + if (arg.startsWith("POS: ")) { // POS: x1 y1 x2 y2 filename + Scanner s = new Scanner(arg.substring(5)); + int x1 = s.nextInt(), y1 = s.nextInt(), x2 = s.nextInt(), y2 = s.nextInt(); + String f = s.nextLine(); + if (f.length() > 0 && f.charAt(0) == ' ') + f = f.substring(1); // Get rid of the space after Y2 + Pos p = new Pos(Util.canon(f), x1, y1, x2, y2); + + } + if (arg.startsWith("CNF: ")) { // CNF: filename + String filename = Util.canon(arg.substring(5)); + try { + String text = Util.readAll(filename); + OurDialog.showtext("Text Viewer", text); + } catch (IOException ex) { + System.err.println("Error reading the file \"" + filename + "\"\n"); + } + } + if (arg.startsWith("XML: ")) { // XML: filename + + // from SimpleGui + // VizGUI viz = new VizGUI(false, "", windowmenu2, enumerator, evaluator); + if (viz == null) + viz = new VizGUI(false, "", null, enumerator, evaluator, 1); + viz.loadXML(Util.canon(arg.substring(5)), false); + } + } + + /** This object performs solution enumeration. */ + private final Computer enumerator = new Computer() { + + @Override + public String compute(Object input) { + final String[] arg = (String[]) input; + //OurUtil.show(frame); + if (WorkerEngine.isBusy()) + throw new RuntimeException("Alloy4 is currently executing a SAT solver command. Please wait until that command has finished."); + //SimpleCallback1 cb = new SimpleCallback1(SimpleGUI.this, viz, log, VerbosityPref.get().ordinal(), latestAlloyVersionName, latestAlloyVersion); + WorkerCallback cb = getVizWorkerCallback(); + SimpleTask2 task = new SimpleTask2(); + task.filename = arg[0]; + task.index = Integer.valueOf(arg[1]); + try { + if (AlloyCore.isDebug()) + WorkerEngine.runLocally(task, cb); + else + WorkerEngine.run(task, SubMemory.get(), SubStack.get(), SimpleGUI.alloyHome(null) + fs + "binary", "", cb); + // task.run(cb); + } catch (Throwable ex) { + WorkerEngine.stop(); + System.err.println("Fatal Error: Solver failed due to unknown reason.\n" + "One possible cause is that, in the Options menu, your specified\n" + "memory size is larger than the amount allowed by your OS.\n" + "Also, please make sure \"java\" is in your program path.\n"); + //log.logBold("Fatal Error: Solver failed due to unknown reason.\n" + "One possible cause is that, in the Options menu, your specified\n" + "memory size is larger than the amount allowed by your OS.\n" + "Also, please make sure \"java\" is in your program path.\n"); + //log.logDivider(); + //log.flush(); + doStop(2); + return arg[0]; + } + /* + * subrunningTask + * = + * 2; + * runmenu + * . + * setEnabled + * ( + * false + * ) + * ; + * runbutton + * . + * setVisible + * ( + * false + * ) + * ; + * showbutton + * . + * setEnabled + * ( + * false + * ) + * ; + * stopbutton + * . + * setVisible + * ( + * true + * ) + * ; + */ + return arg[0]; + } + }; + + + /** This object performs expression evaluation. */ + private static Computer evaluator = new Computer() { + + private String filename = null; + + @Override + public final Object compute(final Object input) throws Exception { + if (input instanceof File) { + filename = ((File) input).getAbsolutePath(); + return ""; + } + if (!(input instanceof String[])) + return ""; + final String[] strs = (String[]) input; + if (strs[0].trim().length() == 0) + return ""; // Empty line + Module root = null; + A4Solution ans = null; + try { + Map fc = new LinkedHashMap(); + XMLNode x = new XMLNode(new File(filename)); + if (!x.is("alloy")) + throw new Exception(); + String mainname = null; + for (XMLNode sub : x) + if (sub.is("instance")) { + mainname = sub.getAttribute("filename"); + break; + } + if (mainname == null) + throw new Exception(); + for (XMLNode sub : x) + if (sub.is("source")) { + String name = sub.getAttribute("filename"); + String content = sub.getAttribute("content"); + fc.put(name, content); + } + root = CompUtil.parseEverything_fromFile(A4Reporter.NOP, fc, mainname, (Version.experimental && ImplicitThis.get()) ? 2 : 1); + ans = A4SolutionReader.read(root.getAllReachableSigs(), x); + for (ExprVar a : ans.getAllAtoms()) { + root.addGlobal(a.label, a); + } + for (ExprVar a : ans.getAllSkolems()) { + root.addGlobal(a.label, a); + } + } catch (Throwable ex) { + throw new ErrorFatal("Failed to read or parse the XML file."); + } + try { + Expr e = CompUtil.parseOneExpression_fromString(root, strs[0]); + if (AlloyCore.isDebug() && VerbosityPref.get() == Verbosity.FULLDEBUG) { + SimInstance simInst = SimpleGUI.convert(root, ans); + if (simInst.wasOverflow()) + return simInst.visitThis(e).toString() + " (OF)"; + } + return ans.eval(e, Integer.valueOf(strs[1])).toString(); + } catch (Exception ex) { + throw new ErrorType("Parsing ", ex); + } + } + }; + + static Pos getCurrentWordSelectionAsPos(String text, Pos pos) { + int[] sel = getCurrentWordSelection(text, pos); + pos = Pos.toPos(text, sel[0], sel[1]); + return pos; + } + + // from OurSyntaxWidget + static int[] getCurrentWordSelection(String text, Pos pos) { + + int[] startEnd = pos.toStartEnd(text); + int selectionStart = startEnd[0]; + int selectionEnd = startEnd[1]; + + if (!isValidSelection(text, selectionStart, selectionEnd)) + return null; + + while (isValidSelection(text, selectionStart - 1, selectionEnd) && inWord(text.charAt(selectionStart - 1))) + selectionStart--; + + while (isValidSelection(text, selectionStart, selectionEnd + 1) && inWord(text.charAt(selectionEnd))) + selectionEnd++; + + if (!isValidSelection(text, selectionStart, selectionEnd)) + return null; + return new int[] { + selectionStart, selectionEnd + }; + } + + // from OurSyntaxWidget + static boolean isValidSelection(String text, int start, int end) { + return start >= 0 && start <= end && end >= start && end <= text.length(); + } + + // from OurSyntaxWidget + private static boolean inWord(char c) { + return Character.isAlphabetic(c) || Character.isDigit(c) || Character.isIdentifierIgnorable(c) || Character.isJavaIdentifierPart(c) || c == '\'' || c == '"'; + } + + + private static void log(String s) { + System.err.println("thread: " + Thread.currentThread().getId() + "| " + s); + } + + + static List findAllReferences(CompModule module, Pos pos, boolean includeSelf) { + + List references = new ArrayList(); + + if (module == null) + return references; + Expr expr = module.find(pos); + if (expr == null) + return references; + Expr referencedExpr = expr.referenced() != null ? module.find(expr.referenced().pos()) : expr; + + + if (includeSelf) + references.add(referencedExpr); + module.visitExpressionsResilient(new VisitQueryOnce() { + + @Override + public boolean visited(Expr expr) { + boolean visited = super.visited(expr); + if (visited) + return visited; + + if (expr.referenced() != null && expr.referenced().pos().equals(referencedExpr.pos)) { + log("reference: " + expr.toString()); + references.add(expr); + } + return visited; + } + }); + return references; + } + + List findAllReferencesGlobally(CompModule module, Pos pos, String rootDir, boolean includeSelf, boolean continueOnError) throws Err { + + List references = new ArrayList(); + + Expr expr = module.find(pos); + + log("finding references to " + pos.toRangeString() + ", expr: " + expr); + + if (expr == null) + return references; + + if (expr.referenced() != null) + log("expr.referenced(): " + expr.referenced().toString()); + + + Pos targetPos = expr.referenced() != null ? expr.referenced().pos() : expr.pos; + log("targetPos: " + targetPos.toRangeString()); + + if (targetPos.equals(Pos.UNKNOWN)) + return references; + + if (includeSelf) + references.add(targetPos); + + for (File child : alloyFilesInDir(rootDir)) { + + String filePath = fileUriToPath(child.toURI().toString()); + try { + CompModule childModule = getCompModuleForFileUri(child.toURI().toString()); + + childModule.visitExpressionsResilient(new VisitQueryOnce() { + + @Override + public boolean visited(Expr expr) { + boolean visited = super.visited(expr); + if (visited) + return visited; + + if (expr.referenced() != null) { + Pos rpos = expr.referenced().pos(); + if (rpos.equals(targetPos)) { + log("reference: " + expr.toString() + "; to file: " + rpos.filename); + references.add(expr.pos); + } + } + return visited; + } + }); + } catch (Exception ex) { + log("exception parsing" + child.toString() + ": " + ex.toString()); + if (!continueOnError) + throw ex; + } + } + return references; + } + + static List alloyFilesInDir(String dir) { + File[] directoryListing = new File(dir).listFiles(); + return Arrays.stream(directoryListing).filter(child -> child.isFile() && (FilenameUtils.isExtension(child.getAbsolutePath(), new String[] { + "als" + }) || isAlloyMarkdownFile(child.getAbsolutePath()))).collect(Collectors.toList()); + } + + static boolean isAlloyMarkdownFile(String filename) { + if (!FilenameUtils.isExtension(filename, new String[] { + "md" + })) + return false; + + try (BufferedReader br = new BufferedReader(new FileReader(filename))) { + return "---".equals(br.readLine()); + } catch (IOException ex) { + return false; + } + } + + static boolean isAlloyFile(String filename, String contents) { + if (FilenameUtils.isExtension(filename, new String[] { + "als" + }) || (FilenameUtils.isExtension(filename, new String[] { + "md" + }) && contents.startsWith("---"))) + return true; + + return false; + } + + +} \ No newline at end of file diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/Lsp4jUtil.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/Lsp4jUtil.java new file mode 100644 index 000000000..09280c713 --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/Lsp4jUtil.java @@ -0,0 +1,59 @@ +package org.alloytools.alloy.lsp.provider; + +import java.util.List; + +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.Location; +import org.eclipse.lsp4j.MessageParams; +import org.eclipse.lsp4j.MessageType; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.SymbolInformation; +import org.eclipse.lsp4j.SymbolKind; + +public class Lsp4jUtil { + public static PublishDiagnosticsParams newPublishDiagnosticsParams(String uri, List diagnostics) { + PublishDiagnosticsParams diagnosticsParams = new PublishDiagnosticsParams(); + diagnosticsParams.setDiagnostics(diagnostics); + diagnosticsParams.setUri(uri); + return diagnosticsParams; + } + + public static Diagnostic newDiagnostic(String message, Range range) { + Diagnostic res = new Diagnostic(); + res.setMessage(message); + res.setRange(range); + return res; + } + + public static MessageParams newMessageParams(String message, MessageType type) { + MessageParams res = new MessageParams(); + res.setMessage(message); + res.setType(type); + return res; + } + + public static Location newLocation(Range range, String uri) { + Location location = new Location(); + location.setRange(range); + location.setUri(uri); + return location; + } + + public static SymbolInformation newSymbolInformation(String name, Location location, SymbolKind kind) { + SymbolInformation symbolInfo = new SymbolInformation(); + symbolInfo.setLocation(location); + symbolInfo.setName(name); + symbolInfo.setKind(kind); + return symbolInfo; + } + + + public static int positionCompare(Position p1, Position p2){ + return p1.getLine() < p2.getLine() ? -1 : p1.getLine() > p2.getLine() ? 1 : + p1.getCharacter() < p2.getCharacter() ? -1 : + p1.getCharacter() > p2.getCharacter() ? 1 : + 0; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.lsp/src/test/java/.gitignore b/org.alloytools.alloy.lsp/src/test/java/.gitignore new file mode 100644 index 000000000..e69de29bb From 0c98e819c6a52775f8639548f107f9495dc7b538 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Wed, 19 Jan 2022 10:24:18 +0100 Subject: [PATCH 012/129] [infra] Integrated the Language Server with the CLI support --- .../alloy/core/infra/AlloyDispatcher.java | 2 +- org.alloytools.alloy.lsp/bnd.bnd | 16 +++++++------ .../lsp/provider/AlloyLanguageServer.java | 10 ++++---- .../alloy/lsp/provider/CLIFacade.java | 23 +++++++++++++++++++ 4 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/CLIFacade.java diff --git a/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/AlloyDispatcher.java b/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/AlloyDispatcher.java index 6cdb72dc8..1f88a806d 100644 --- a/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/AlloyDispatcher.java +++ b/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/AlloyDispatcher.java @@ -162,7 +162,7 @@ public void _alloy(BaseOptions options) throws Exception { return; } - log.info("selected main {} is with arguments {}", selected, arguments); + log.debug("selected main {} is with arguments {}", selected, arguments); String execute = cl.execute(selected.instance, selected.name, arguments); if (execute != null) { diff --git a/org.alloytools.alloy.lsp/bnd.bnd b/org.alloytools.alloy.lsp/bnd.bnd index 672cc2acd..b608c0af9 100644 --- a/org.alloytools.alloy.lsp/bnd.bnd +++ b/org.alloytools.alloy.lsp/bnd.bnd @@ -1,12 +1,14 @@ -buildpath: \ - org.alloytools.alloy.application;version=latest,\ - org.alloytools.alloy.core;version=latest,\ - org.eclipse.lsp4j,\ - org.eclipse.lsp4j.jsonrpc,\ - com.google.gson,\ - org.eclipse.equinox.common, \ - org.apache.commons.io + org.alloytools.alloy.application;version=latest,\ + org.alloytools.alloy.core;version=latest,\ + org.eclipse.lsp4j,\ + org.eclipse.lsp4j.jsonrpc,\ + com.google.gson,\ + org.eclipse.equinox.common,\ + org.apache.commons.io,\ + org.alloytools.api,\ + aQute.libg -testpath: \ biz.aQute.wrapper.junit, \ diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServer.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServer.java index 5ebc7146c..4e0c39691 100644 --- a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServer.java +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyLanguageServer.java @@ -79,12 +79,12 @@ public WorkspaceService getWorkspaceService() { return service(); } - - // LanguageClientAware @Override public void connect(LanguageClient client) { System.err.println("AlloyLanguageServer.connect() called"); + Class< ? >[] interfaces = client.getClass().getInterfaces(); + this.client = (AlloyLanguageClient) client; if (this.alloyTextDocumentService != null) { @@ -94,8 +94,8 @@ public void connect(LanguageClient client) { } public static void main(String[] args) throws Exception { - if (args.length == 2) { - int port = Integer.parseInt(args[1]); + if (args.length == 1) { + int port = Integer.parseInt(args[0]); InputStream inputStream; OutputStream outputStream; AlloyLanguageServer langserv = new AlloyLanguageServer(); @@ -113,7 +113,7 @@ public static void main(String[] args) throws Exception { } } else { AlloyLanguageServer server = new AlloyLanguageServer(); - Launcher l = LSPLauncher.createServerLauncher(server, System.in, System.out); + Launcher l = new LSPLauncher.Builder().setLocalService(server).setRemoteInterface(AlloyLanguageClient.class).setInput(System.in).setOutput(System.out).create(); server.connect(l.getRemoteProxy()); Future< ? > startListening = l.startListening(); startListening.get(); diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/CLIFacade.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/CLIFacade.java new file mode 100644 index 000000000..031b39b0d --- /dev/null +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/CLIFacade.java @@ -0,0 +1,23 @@ +package org.alloytools.alloy.lsp.provider; + +import org.alloytools.alloy.infrastructure.api.AlloyMain; + +import aQute.lib.getopt.Arguments; +import aQute.lib.getopt.Description; +import aQute.lib.getopt.Options; + +@AlloyMain( + name = "lsp" ) +public class CLIFacade { + + @Description("Language Server for Alloy. " ) + @Arguments( + arg = "[port]" ) + interface LSPOptions extends Options { + + } + + public void _lsp(LSPOptions options) throws Exception { + AlloyLanguageServer.main(options._arguments().toArray(new String[0])); + } +} \ No newline at end of file From a3e778bce7fdc7fe9c7c698718692356894a6dbb Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Fri, 4 Nov 2022 10:58:17 +0100 Subject: [PATCH 013/129] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 49bb2c2b2..15da593af 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ enroute.zip .idea *.iml +languageServers-log/AlloyLanguageServer.log From b1cb710c216cc4a58d6b8a4239f457f483d11001 Mon Sep 17 00:00:00 2001 From: Sergey Bronnikov Date: Tue, 10 Jan 2023 15:51:59 +0300 Subject: [PATCH 014/129] Fix typos --- .../edu/mit/csail/sdg/alloy4graph/GraphViewer.java | 2 +- .../java/edu/mit/csail/sdg/alloy4viz/AlloyModel.java | 4 ++-- .../java/edu/mit/csail/sdg/alloy4viz/MagicLayout.java | 4 ++-- .../mit/csail/sdg/alloy4viz/StaticInstanceReader.java | 2 +- .../edu/mit/csail/sdg/alloy4whole/SwingLogPanel.java | 2 +- org.alloytools.alloy.core/parser/Alloy.cup | 2 +- .../edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java | 2 +- .../java/edu/mit/csail/sdg/alloy4/OurPDFWriter.java | 2 +- .../edu/mit/csail/sdg/alloy4/OurSyntaxDocument.java | 2 +- .../csail/sdg/alloy4/OurSyntaxUndoableDocument.java | 4 ++-- .../src/main/java/edu/mit/csail/sdg/alloy4/Runner.java | 4 ++-- .../src/main/java/edu/mit/csail/sdg/alloy4/Util.java | 10 +++++----- .../src/main/java/edu/mit/csail/sdg/ast/Clause.java | 2 +- .../src/main/java/edu/mit/csail/sdg/ast/Expr.java | 2 +- .../src/main/java/edu/mit/csail/sdg/ast/ExprList.java | 2 +- .../main/java/edu/mit/csail/sdg/parser/CompModule.java | 4 ++-- .../main/java/edu/mit/csail/sdg/parser/CompUtil.java | 2 +- .../main/java/edu/mit/csail/sdg/sim/SimInstance.java | 10 +++++----- .../java/edu/mit/csail/sdg/translator/A4Solution.java | 2 +- .../edu/mit/csail/sdg/translator/A4SolutionReader.java | 2 +- .../csail/sdg/translator/TranslateAlloyToKodkod.java | 4 ++-- .../src/main/java/java_cup/runtime/lr_parser.java | 2 +- .../java/java_cup/runtime/virtual_parse_stack.java | 2 +- .../java/org/alloytools/alloy/core/infra/Alloy.java | 2 +- .../src/main/resources/models/util/graph.als | 2 +- org.alloytools.alloy.extra/extra/help/a4.html | 8 ++++---- org.alloytools.alloy.extra/extra/help/gui.html | 2 +- org.alloytools.alloy.extra/extra/help/skolem.html | 2 +- org.alloytools.alloy.extra/extra/help/treeview.html | 2 +- org.alloytools.alloy.extra/extra/help/util.html | 2 +- .../extra/models/examples/algorithms/messaging.als | 2 +- .../extra/models/examples/algorithms/opt_spantree.als | 4 ++-- .../models/examples/algorithms/stable_mutex_ring.als | 2 +- .../models/examples/case_studies/chordbugmodel.als | 2 +- 34 files changed, 52 insertions(+), 52 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4graph/GraphViewer.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4graph/GraphViewer.java index e6ef4cdf6..a074b07f3 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4graph/GraphViewer.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4graph/GraphViewer.java @@ -615,7 +615,7 @@ public void actionPerformed(ActionEvent e) { } Util.setCurrentDirectory(filename.getParentFile()); } catch (Throwable ex) { - OurDialog.alert(parent, "An error has occured in writing the output file:\n" + ex); + OurDialog.alert(parent, "An error has occurred in writing the output file:\n" + ex); } } diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/AlloyModel.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/AlloyModel.java index 4b696e846..8294b0fbc 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/AlloyModel.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/AlloyModel.java @@ -58,8 +58,8 @@ public final class AlloyModel { * If A extends B, then "(A,B)" will be in this map. *

* AlloyModel's constructor ensures the following:
- * (1) hierachy.keySet() is always a subset of this.types
- * (2) hierachy.valueSet() is always a subset of this.types
+ * (1) hierarchy.keySet() is always a subset of this.types
+ * (2) hierarchy.valueSet() is always a subset of this.types
* (3) "univ" is never in the keySet
* (4) null is never in the keySet nor valueSet
* (5) there is no cycle in this relation diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/MagicLayout.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/MagicLayout.java index 3e1fdbbd7..48d9fa42a 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/MagicLayout.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/MagicLayout.java @@ -191,7 +191,7 @@ private final boolean hasLikelyProjectionTypeName(final String n) { *

    *
  • interesting example: 2d game grid *
  • ex: toplogical sort -- layout tree and list, not cnxn between them - *
  • look for homogenius binary relation (a -> a) + *
  • look for homogeneous binary relation (a -> a) *
  • may be several relations defining the spine *
*/ @@ -210,7 +210,7 @@ private void spine() { if (!enumerationTypes.contains(targetType)) { spines.add(r); } - // however, binary relations named parent should be layed + // however, binary relations named parent should be laid // out backwards if (r.getName().equals("parent")) { vizState.layoutBack.put(r, true); diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/StaticInstanceReader.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/StaticInstanceReader.java index 713516543..19ad35595 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/StaticInstanceReader.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4viz/StaticInstanceReader.java @@ -66,7 +66,7 @@ public final class StaticInstanceReader { private final LinkedHashMap sig2type = new LinkedHashMap(); /** - * This maps each Sig ot its corresponding unique VIsualizer AlloyAtom (if + * This maps each Sig to its corresponding unique VIsualizer AlloyAtom (if * isMeta is true). */ private final LinkedHashMap sig2atom = new LinkedHashMap(); diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SwingLogPanel.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SwingLogPanel.java index ae0a6a30d..3f9c1c149 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SwingLogPanel.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/SwingLogPanel.java @@ -453,7 +453,7 @@ public void copy() { log.copy(); } - /** Removes any messages writtin in "red" style. */ + /** Removes any messages written in "red" style. */ public void clearError() { if (log == null) return; diff --git a/org.alloytools.alloy.core/parser/Alloy.cup b/org.alloytools.alloy.core/parser/Alloy.cup index a59b4fd44..a2796b4f7 100644 --- a/org.alloytools.alloy.core/parser/Alloy.cup +++ b/org.alloytools.alloy.core/parser/Alloy.cup @@ -786,7 +786,7 @@ SigQual ::= PRIVATE:x {: RESULT=new ArrayList(6); RESULT.ad SigQual ::= VAR:x {: RESULT=new ArrayList(6); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); :}; SigQuals ::= SIG {: RESULT=new ArrayList(6); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; -SigQuals ::= SigQual:a SigQuals:b {: RESULT=a; for(int i=0;i<6;i++) if (a.get(i)==null) a.set(i,b.get(i)); else if (b.get(i)!=null) throw new ErrorSyntax(b.get(i), "The same qualifer cannot be specified more than once for the same sig."); :}; +SigQuals ::= SigQual:a SigQuals:b {: RESULT=a; for(int i=0;i<6;i++) if (a.get(i)==null) a.set(i,b.get(i)); else if (b.get(i)!=null) throw new ErrorSyntax(b.get(i), "The same qualifier cannot be specified more than once for the same sig."); :}; SigIn ::= EXTENDS:a SigRef:x {: RESULT=new ArrayList(2); RESULT.add(x); RESULT.add(ExprVar.make(a, "extends")); :}; SigIn ::= IN:a SigRefu:x {: RESULT=x; x.add(ExprVar.make(a,"in")); :}; diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java index ca5baf266..4301aaa10 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurLineNumberWidget.java @@ -249,7 +249,7 @@ public void setDisplay(boolean flag) { /** * Set the fontName and fontSize for this widget. If the * submitted name and size amount to a change of the font itself, - * incure an update() call. + * incur an update() call. * @param fontName * @param fontSize */ diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurPDFWriter.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurPDFWriter.java index deccdd9e6..de3961c66 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurPDFWriter.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurPDFWriter.java @@ -226,7 +226,7 @@ public OurPDFWriter drawShape(Shape shape, boolean fillOrNot) { * given matrix; for example, [1 0 0 1 dx dy] means "translation to dx dy" $R $G * $B RG --> sets the stroke color (where 0 <= $R <= 1, etc) $R $G $B rg --> * sets the fill color (where 0 <= $R <= 1, etc) Q --> restores the current - * graphics state Page Object (3 because PAGE is #3) (4 beacuse PAGES is #4) (2 + * graphics state Page Object (3 because PAGE is #3) (4 because PAGES is #4) (2 * because CONTENTS is #2) * ========================================================= ================ * ============ 3 0 obj << /Type /Page /Parent 4 0 R /Contents 2 0 R >> diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxDocument.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxDocument.java index eeb66807e..24fedaf94 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxDocument.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxDocument.java @@ -577,7 +577,7 @@ else if (tabSize > 100) } /** - * Overriden to return the full text of the document. + * Overridden to return the full text of the document. * * @return the entire text */ diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxUndoableDocument.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxUndoableDocument.java index 11ca13341..11227e6fe 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxUndoableDocument.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxUndoableDocument.java @@ -60,7 +60,7 @@ final class OurSyntaxUndoableDocument extends OurSyntaxDocument { private int now; /** - * The number of undoable opeartions that are currently "undone". + * The number of undoable operations that are currently "undone". */ private int undone; @@ -219,7 +219,7 @@ public void replace(int offset, int length, String string, AttributeSet attrs) t } /** - * Overriden to return the full text of the document. + * Overridden to return the full text of the document. * * @return the entire text */ diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Runner.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Runner.java index 34aa02822..ed9f14c41 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Runner.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Runner.java @@ -45,14 +45,14 @@ public abstract class Runner extends AbstractAction implements Runnable, WindowL public Runner() {} /** - * This method should be overriden to provide the default action that this + * This method should be overridden to provide the default action that this * Runner would perform. */ @Override public abstract void run(); /** - * This method should be overriden to provide the default action that this + * This method should be overridden to provide the default action that this * Runner would perform given an argument. */ public abstract void run(Object arg); diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Util.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Util.java index 191bd54be..47d0ce2bd 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Util.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/Util.java @@ -403,17 +403,17 @@ else if (b.equals("in")) } else if (b.startsWith("this/")) { return 1; } - int acount = 0, bcount = 0; + int account = 0, bcount = 0; for (int i = 0; i < a.length(); i++) { if (a.charAt(i) == '/') - acount++; + account++; } for (int i = 0; i < b.length(); i++) { if (b.charAt(i) == '/') bcount++; } - if (acount != bcount) - return (acount < bcount) ? -1 : 1; + if (account != bcount) + return (account < bcount) ? -1 : 1; int result = a.compareToIgnoreCase(b); return result != 0 ? result : a.compareTo(b); } @@ -821,7 +821,7 @@ public static int min(int bitwidth) { /** * Returns a mask of the form 000..0011..11 where the number of 1s is equal to - * the number of significant bits of the highest integer withing the given + * the number of significant bits of the highest integer within the given * bitwidth */ public static int shiftmask(int bitwidth) { diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Clause.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Clause.java index a512d2399..8a05d182d 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Clause.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Clause.java @@ -4,7 +4,7 @@ /** * Unfortunately not all objects are Expr. However, from the UI we want to be - * able to locae the clauses in the text file and what they refer to. + * able to locate the clauses in the text file and what they refer to. * * @author aqute * diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java index f4a27bade..b5cb023e5 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java @@ -240,7 +240,7 @@ public final Expr typecheck_as_set() { /** * Resolves this expression if ambiguous. (And if t.size()>0, it represents the - * set of tuples whose presence/absence is relevent to the parent expression) + * set of tuples whose presence/absence is relevant to the parent expression) * (Note: it's possible for t to be EMPTY, or even ambiguous!) *

* On success: the return value will be well-typed and unambiguous diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprList.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprList.java index 52ddfaa80..8bb6c5b93 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprList.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/ExprList.java @@ -32,7 +32,7 @@ /** * Immutable; represents disjoint[] or pred/totalOrder[] or (... and ... and ..) - * and other similar list of arugments. + * and other similar list of arguments. *

* Invariant: type!=EMPTY => (all x:args | x.mult==0) */ diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java index 658b35222..e742d0996 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java @@ -1330,7 +1330,7 @@ void addOpen(Pos pos, Pos isPrivate, ExprVar name, List args, ExprVar a if (arg.label.length() == 0) throw new ErrorSyntax(arg.span(), "Argument cannot be empty."); if (arg.label.indexOf('@') >= 0) - throw new ErrorSyntax(arg.span(), "Argument cannot contain the \'@\' chracter."); + throw new ErrorSyntax(arg.span(), "Argument cannot contain the \'@\' character."); newlist.add(arg.label); } Open x = opens.get(as); @@ -1347,7 +1347,7 @@ void addOpen(Pos pos, Pos isPrivate, ExprVar name, List args, ExprVar a opens.put(as, x); } - /** Do any post-parsing processig. */ + /** Do any post-parsing processing. */ void doneParsing() { status = 3; LinkedHashMap copy = new LinkedHashMap(opens); diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompUtil.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompUtil.java index ff1190e07..d068a7db7 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompUtil.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompUtil.java @@ -70,7 +70,7 @@ private CompUtil() { // =============================================================================================================// /** - * Go up the directory hierachy 0 or more times.
+ * Go up the directory hierarchy 0 or more times.
* For example, on a UNIX machine, goUp("/home/abc/def",1) will return * "/home/abc"
* For example, on a UNIX machine, goUp("/home/abc/def",2) will return "/home" diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/sim/SimInstance.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/sim/SimInstance.java index 99639e017..66b87bbae 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/sim/SimInstance.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/sim/SimInstance.java @@ -522,7 +522,7 @@ private int trunc(int i) { } /** - * Convenience method that evalutes x and casts the result to be a boolean. + * Convenience method that evaluates x and casts the result to be a boolean. * * @return the boolean - if x evaluates to a boolean * @throws ErrorFatal - if x does not evaluate to a boolean @@ -537,7 +537,7 @@ public boolean cform(Expr x) throws Err { } /** - * Convenience method that evalutes x and cast the result to be a int. + * Convenience method that evaluates x and cast the result to be a int. * * @return the int - if x evaluates to an int * @throws ErrorFatal - if x does not evaluate to an int @@ -554,7 +554,7 @@ public int cint(Expr x) throws Err { } /** - * Convenience method that evalutes x and cast the result to be a tupleset + * Convenience method that evaluates x and cast the result to be a tupleset * * @return the tupleset - if x evaluates to a tupleset * @throws ErrorFatal - if x does not evaluate to a tupleset @@ -961,7 +961,7 @@ public SimTupleset visit(Field x) throws Err { } /** - * Helper method for enumerating all possibilties for a + * Helper method for enumerating all possibilities for a * quantification-expression. */ private int enumerate(final TempList store, int sum, final ExprQt x, final Expr body, final int i) throws Err { // if op is ALL NO SOME ONE LONE then it always returns @@ -1341,7 +1341,7 @@ public String validate(Module world) { } return ""; } catch (Err ex) { - return "An internal error has occured:\n" + ex.dump(); + return "An internal error has occurred:\n" + ex.dump(); } } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4Solution.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4Solution.java index 3ca5e1ae0..15df281fd 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4Solution.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4Solution.java @@ -1698,7 +1698,7 @@ public synchronized void solvingCNF(int step, int primaryVars, int vars, int cla inst = new TemporalInstance(Arrays.asList(inst), 0, 1); // To ensure no more output during SolutionEnumeration solver.options().setReporter(oldReporter); - // If unsatisfiable, then retreive the unsat core if desired + // If unsatisfiable, then retrieve the unsat core if desired if (inst == null && solver.options().solver() == SATFactory.MiniSatProver) { try { lCore = new LinkedHashSet(); diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4SolutionReader.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4SolutionReader.java index 5ed67403c..772230ffe 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4SolutionReader.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/A4SolutionReader.java @@ -518,7 +518,7 @@ public static A4Solution read(Iterable sigs, XMLNode xml) throws Err { if (ex instanceof Err) throw ((Err) ex); else - throw new ErrorFatal("Fatal error occured: " + ex, ex); + throw new ErrorFatal("Fatal error occurred: " + ex, ex); } } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/TranslateAlloyToKodkod.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/TranslateAlloyToKodkod.java index 95765c113..b1cad7bda 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/TranslateAlloyToKodkod.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/translator/TranslateAlloyToKodkod.java @@ -660,7 +660,7 @@ public static Object alloy2kodkod(A4Solution sol, Expr expr) throws Err { // ==============================================================================================================// /** - * Convenience method that evalutes x and casts the result to be a Kodkod + * Convenience method that evaluates x and casts the result to be a Kodkod * Formula. * * @return the formula - if x evaluates to a Formula @@ -676,7 +676,7 @@ private Formula cform(Expr x) throws Err { } /** - * Convenience method that evalutes x and cast the result to be a Kodkod + * Convenience method that evaluates x and cast the result to be a Kodkod * IntExpression. * * @return the integer expression - if x evaluates to an IntExpression diff --git a/org.alloytools.alloy.core/src/main/java/java_cup/runtime/lr_parser.java b/org.alloytools.alloy.core/src/main/java/java_cup/runtime/lr_parser.java index 3429b6ee5..7de344de4 100644 --- a/org.alloytools.alloy.core/src/main/java/java_cup/runtime/lr_parser.java +++ b/org.alloytools.alloy.core/src/main/java/java_cup/runtime/lr_parser.java @@ -397,7 +397,7 @@ public void user_init() throws java.lang.Exception {} * Get the next Symbol from the input (supplied by generated subclass). Once end * of file has been reached, all subsequent calls to scan should return an EOF * Symbol (which is Symbol number 0). By default this method returns - * getScanner().next_token(); this implementation can be overriden by the + * getScanner().next_token(); this implementation can be overridden by the * generated parser using the code declared in the "scan with" clause. Do not * recycle objects; every call to scan() should return a fresh object. */ diff --git a/org.alloytools.alloy.core/src/main/java/java_cup/runtime/virtual_parse_stack.java b/org.alloytools.alloy.core/src/main/java/java_cup/runtime/virtual_parse_stack.java index 8dc9fb1e0..0a0b2913c 100644 --- a/org.alloytools.alloy.core/src/main/java/java_cup/runtime/virtual_parse_stack.java +++ b/org.alloytools.alloy.core/src/main/java/java_cup/runtime/virtual_parse_stack.java @@ -91,7 +91,7 @@ protected void get_from_real() { if (real_next >= real_stack.size()) return; - /* get a copy of the first Symbol we have not transfered */ + /* get a copy of the first Symbol we have not transferred */ stack_sym = (Symbol) real_stack.elementAt(real_stack.size() - 1 - real_next); /* record the transfer */ diff --git a/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/Alloy.java b/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/Alloy.java index df3cb4228..bb105ce54 100644 --- a/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/Alloy.java +++ b/org.alloytools.alloy.core/src/main/java/org/alloytools/alloy/core/infra/Alloy.java @@ -14,7 +14,7 @@ *

* This class is an entry point and should not be renamed. It should also _NOT_ * touch any other classes. We're creating a special class loader to allow the - * dynamic libraries to be found. If you link this class to any othe class + * dynamic libraries to be found. If you link this class to any other class * you're bound to create trouble. * */ diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/graph.als b/org.alloytools.alloy.core/src/main/resources/models/util/graph.als index 712dfd14c..52fed9137 100644 --- a/org.alloytools.alloy.core/src/main/resources/models/util/graph.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/graph.als @@ -1,7 +1,7 @@ module util/graph[node] /* - * Utilities for some common operations and contraints + * Utilities for some common operations and constraints * on graphs. * * author: Greg Dennis diff --git a/org.alloytools.alloy.extra/extra/help/a4.html b/org.alloytools.alloy.extra/extra/help/a4.html index 309faf5ba..7915d9fe5 100644 --- a/org.alloytools.alloy.extra/extra/help/a4.html +++ b/org.alloytools.alloy.extra/extra/help/a4.html @@ -194,7 +194,7 @@

Additional Changes

For example, if the following model is /Desktop/MyProject/main.als,
then we will infer that the "helper" module is - located at /Desktop/MyProject/additonal/helper.als + located at /Desktop/MyProject/additional/helper.als

    module MyProject/main
@@ -218,8 +218,8 @@ 

Additional Changes

Example 2: -

In this example, the first line is optional. But its presense - or absense will affect where Alloy 4 searches for imported modules. +

In this example, the first line is optional. But its presence + or absence will affect where Alloy 4 searches for imported modules.

module MyProject/main
open MyProject/library/helper
@@ -250,7 +250,7 @@

Additional Changes

  check NOTEQUAL for 3

These are called "anonymous" assertions and predicates.
- Alternatively, you can prepend an explcit label if you wish.
+ Alternatively, you can prepend an explicit label if you wish.
For example:

somelabel: check { A != B } for 3
diff --git a/org.alloytools.alloy.extra/extra/help/gui.html b/org.alloytools.alloy.extra/extra/help/gui.html index a2a4170bc..c93116c26 100644 --- a/org.alloytools.alloy.extra/extra/help/gui.html +++ b/org.alloytools.alloy.extra/extra/help/gui.html @@ -140,7 +140,7 @@

Options and Preferences

  • Record the Kodkod Input/output: If this option is enabled, after executing any command,
    then Alloy Analyzer will record the Kodkod input model generated for that command,
    - as well as the Kodkod solution correspoding to that command. + as well as the Kodkod solution corresponding to that command.

  • diff --git a/org.alloytools.alloy.extra/extra/help/skolem.html b/org.alloytools.alloy.extra/extra/help/skolem.html index d77a2c241..5924f4c6b 100644 --- a/org.alloytools.alloy.extra/extra/help/skolem.html +++ b/org.alloytools.alloy.extra/extra/help/skolem.html @@ -24,7 +24,7 @@

    Introduction

    }

    The "some" formula may be equivalently expressed as:

        x' in A && no x'.r 
    -

    x' is the skolem reation in this case. The existential quantifier "some" is not needed because the analysis will search for the existence of the skolem realtion x'.

    +

    x' is the skolem relation in this case. The existential quantifier "some" is not needed because the analysis will search for the existence of the skolem relationx'.

     

    Determining the names of skolem relations

    The Alloy Analyzer automatically generates and assigns names to skolem relations.
    diff --git a/org.alloytools.alloy.extra/extra/help/treeview.html b/org.alloytools.alloy.extra/extra/help/treeview.html index 9d19b0ddd..cfc092443 100644 --- a/org.alloytools.alloy.extra/extra/help/treeview.html +++ b/org.alloytools.alloy.extra/extra/help/treeview.html @@ -16,7 +16,7 @@

    Tree View

    The nodes of the tree may be expanded/collapsed to reveal/hide the values of relations. A relation node (such as that for a signature or a field) is expanded to reveal its tuples, and an atom may be expanded to reveal -the value of joining the atom with the fields defined in its correponding +the value of joining the atom with the fields defined in its corresponding signature.

    diff --git a/org.alloytools.alloy.extra/extra/help/util.html b/org.alloytools.alloy.extra/extra/help/util.html index 1e3153da3..98e61d3e3 100644 --- a/org.alloytools.alloy.extra/extra/help/util.html +++ b/org.alloytools.alloy.extra/extra/help/util.html @@ -28,7 +28,7 @@

    Utility Modules

    module util/graph[node]
    - Utilities for common operations and contraints on graphs. + Utilities for common operations and constraints on graphs.
    module util/integer diff --git a/org.alloytools.alloy.extra/extra/models/examples/algorithms/messaging.als b/org.alloytools.alloy.extra/extra/models/examples/algorithms/messaging.als index a69df8d6e..47e1db6c4 100644 --- a/org.alloytools.alloy.extra/extra/models/examples/algorithms/messaging.als +++ b/org.alloytools.alloy.extra/extra/models/examples/algorithms/messaging.als @@ -104,7 +104,7 @@ fact MsgMovementConstraints { // Return addresses are correct all n: Node | t.sent[n].state.from in n - // messages sent to a node on a tick become visible to that node on some subseqent tick, + // messages sent to a node on a tick become visible to that node on some subsequent tick, // and permanently stop being visible to that node on the tick after that node reads the message all n: Node, m: Msg | { // message starts being visible to node n no earlier than it is sent; diff --git a/org.alloytools.alloy.extra/extra/models/examples/algorithms/opt_spantree.als b/org.alloytools.alloy.extra/extra/models/examples/algorithms/opt_spantree.als index e7e44ceb3..488416065 100644 --- a/org.alloytools.alloy.extra/extra/models/examples/algorithms/opt_spantree.als +++ b/org.alloytools.alloy.extra/extra/models/examples/algorithms/opt_spantree.als @@ -5,7 +5,7 @@ module examples/algorithms/opt_spantree * over arbitrary network topologies * * Each process has a parent and a level, both of which are - * initally null. A distinct root node exists at which the + * initially null. A distinct root node exists at which the * algorithm starts. In the first step, the root assigns itself * the level of zero and sends its level to its neighbors. * Subsequently, if a node reads a message with level k, it sets @@ -17,7 +17,7 @@ module examples/algorithms/opt_spantree * * We model communication through a state-reading model, in which * nodes can directly read the state of their neighbors. Messages - * are not explicity modelled. This makes no difference for this + * are not explicitly modelled. This makes no difference for this * algorithm since once a node sends a message, the state of the * node stays the same as the contents of the message. */ diff --git a/org.alloytools.alloy.extra/extra/models/examples/algorithms/stable_mutex_ring.als b/org.alloytools.alloy.extra/extra/models/examples/algorithms/stable_mutex_ring.als index 4fc875652..4b93ebdd2 100644 --- a/org.alloytools.alloy.extra/extra/models/examples/algorithms/stable_mutex_ring.als +++ b/org.alloytools.alloy.extra/extra/models/examples/algorithms/stable_mutex_ring.als @@ -72,7 +72,7 @@ sig Tick { val: Process -> one Val, runs: set Process, // processes scheduled to run on this tick // for visualization - priv: set Process // the set of priviledged processes on this tick + priv: set Process // the set of privileged processes on this tick } { priv = { p : Process | Privileged[p, this] } diff --git a/org.alloytools.alloy.extra/extra/models/examples/case_studies/chordbugmodel.als b/org.alloytools.alloy.extra/extra/models/examples/case_studies/chordbugmodel.als index 586338339..95b5006f5 100644 --- a/org.alloytools.alloy.extra/extra/models/examples/case_studies/chordbugmodel.als +++ b/org.alloytools.alloy.extra/extra/models/examples/case_studies/chordbugmodel.als @@ -175,7 +175,7 @@ there is exactly one node. What happens here is that the model requires that a closest preceding finger node has a distinct identifier from the input identifier, but this cannot happen if there is exactly one node and if the input -identifer equals that of the node. +identifier equals that of the node. \subsection faulty \tt From dcbe4d5e3e34f1215e3aa32c0cf612e45af7e30a Mon Sep 17 00:00:00 2001 From: Joe Eli McIlvain Date: Mon, 30 May 2022 09:21:38 -0700 Subject: [PATCH 015/129] Show both state panes in the VizGUI Currently, the Language server invocation of the VizGUI differs from that in the main program because it currently only shows the "current" state in temporal models, rather than showing both the "current" and the "next" state. Seeing the "next" state is important because it allows you to see what you're switching between when you use the "Next Fork" feature, as it is the "next" state that you are causing to differ when you click this. Changing the `VizGUI` invocation from `panes=1` to `panes=2` makes the invocation match the one used by the main Alloy program. --- .../alloy/lsp/provider/AlloyTextDocumentService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyTextDocumentService.java b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyTextDocumentService.java index c85666cfa..06b3e18e7 100644 --- a/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyTextDocumentService.java +++ b/org.alloytools.alloy.lsp/src/main/java/org/alloytools/alloy/lsp/provider/AlloyTextDocumentService.java @@ -1296,7 +1296,7 @@ private void doVisualize(String arg) { // from SimpleGui // VizGUI viz = new VizGUI(false, "", windowmenu2, enumerator, evaluator); if (viz == null) - viz = new VizGUI(false, "", null, enumerator, evaluator, 1); + viz = new VizGUI(false, "", null, enumerator, evaluator, 2); viz.loadXML(Util.canon(arg.substring(5)), false); } } @@ -1596,4 +1596,4 @@ static boolean isAlloyFile(String filename, String contents) { } -} \ No newline at end of file +} From 6ee0215918a0d7c02cd4d6a64e7311d87ad3aca3 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Wed, 1 Mar 2023 19:43:58 +0100 Subject: [PATCH 016/129] Restore Expr.eventually() and Expr.after() --- .../src/main/java/edu/mit/csail/sdg/ast/Expr.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java index b5cb023e5..9a4939175 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java @@ -1180,6 +1180,10 @@ public final Expr eventually() { *

    * this must be a formula */ + public final Expr after() { + return ExprUnary.Op.AFTER.make(span(), this); + } + /** * Returns the formula (before this) *

    @@ -1194,6 +1198,10 @@ public final Expr before() { *

    * this must be a formula */ + public final Expr historically() { + return ExprUnary.Op.HISTORICALLY.make(span(), this); + } + /** * Returns the formula (once this) *

    From b5fe6a9f37a3bf99ea9f66d5882c90cc35affe4f Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Wed, 1 Mar 2023 19:57:23 +0100 Subject: [PATCH 017/129] Updates instructions for Intellij See #187 for details. Copied without verification since I do not use Intellij --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4eaf33cef..db8fc6338 100644 --- a/README.md +++ b/README.md @@ -78,12 +78,12 @@ Bndtools will continuously create the final executable. The projects are setup t Ensure you have the [Osmorc] plugin is enabled, as this plugin is needed for Bndtools support. It should be enabled by default. -1. Choose "Import Project" -2. Select the `org.alloytools.alloy` directory. +1. Choose `Import project from existing Sources` by using `Ctrl + Shift + a`. +2. Select the root folder (default folder name is `org.alloytools.alloy`). 3. Choose "Import project from external model: Bnd/Bndtools" and click "Next" -4. For "Select Bnd/Bndtools project to import", all projects should be checked - by default, click "Next" +4. For "Select Bnd/Bndtools project to import", all projects should be checked by default, click "Next" 5. For project SDK, Choose "1.8", Click Finish +6. Select folder `org/alloytools/kodkod/nativesat/jni` as `Resource Folder` by selecting module `org.alloytools.kodkod.nativesat`, selecting folder `jni` -> `right click` -> `Mark Directory As` -> `Resource Root`. Note: do *not* link the Gradle project, as this will prevent you from running Alloy within IDEA. From 017070f7fad258e8edf69d50f19c994c452f88a0 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Wed, 1 Mar 2023 20:03:42 +0100 Subject: [PATCH 018/129] If the PATH contains a file path with an error we skip it --- .../edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java index d3ce7ca32..04c3af904 100644 --- a/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java +++ b/org.alloytools.alloy.application/src/main/java/edu/mit/csail/sdg/alloy4whole/PreferencesDialog.java @@ -346,13 +346,17 @@ private static boolean staticLibrary(String name) { } } // check if in system path - for (String str : (System.getenv("PATH")).split(Pattern.quote(File.pathSeparator))) { + for (String str : (System.getenv("PATH")).split(Pattern.quote(File.pathSeparator))) + try { Path pth = Paths.get(str); if (Files.exists(pth.resolve(name))) { if (isDebug) System.out.println("Loaded: " + name + " at " + pth); return true; } + } catch (java.nio.file.InvalidPathException e) { + if (isDebug) + System.out.println("Invalid file path on PATH: " + str + ", ignoring"); } if (isDebug) From fc8bc480b321f83ba9918e0f77e05335d18e6539 Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Wed, 1 Mar 2023 20:44:59 +0100 Subject: [PATCH 019/129] #105 Commenting a selection of code misses the last line of code --- .../main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java index 104fd15a1..2723bf9eb 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/alloy4/OurSyntaxWidget.java @@ -437,14 +437,14 @@ private void doComment() { if (s != null && s.length() > 0) { StringBuilder sb = new StringBuilder(s); int i = 0; - while (i < sb.length() - 1) { + while (i < sb.length()) { if (sb.charAt(i) == '/' && sb.charAt(i + 1) == '/') { sb.delete(i, i + 2); } else { sb.insert(i, "//"); i += 2; } - while (i < sb.length() - 1) { + while (i < sb.length()) { if (sb.charAt(i) == '\n') { i++; break; From 29c7759b9ca1b5b15530345725a30e5ce12e4d5b Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 8 Mar 2023 10:48:48 -0500 Subject: [PATCH 020/129] Changes to Alloy code: - changed two bnd.bnd files to include Dash - made a number of classes in CompModule.java public for access in Dash code - changed name of parameter in sequniv.als from "from" to "frm" b/c "from" is a Dash keyword Added Dash code for parsing (org.alloytools.alloy.dash) Added a Dash CLI (org.alloytools.alloy.application/src/main/java/ca/) Added new util files needed for Dash Added pbuild.sh, which does the file concatentation needed to build Dash.cup and Dash.lex from Alloy.cup and Alloy.lex and new fragments prior to calling ./gradlew build. (not needed for regular building, only for development of parser) --- org.alloytools.alloy.application/bnd.bnd | 2 + .../edu/mit/csail/sdg/parser/CompModule.java | 42 +++++++++---------- .../main/resources/models/util/sequniv.als | 4 +- org.alloytools.alloy.dist/bnd.bnd | 2 + 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/org.alloytools.alloy.application/bnd.bnd b/org.alloytools.alloy.application/bnd.bnd index c3abc7b49..d22a42e87 100644 --- a/org.alloytools.alloy.application/bnd.bnd +++ b/org.alloytools.alloy.application/bnd.bnd @@ -5,6 +5,7 @@ lib/apple-osx-ui.jar;version=file,\ org.alloytools:pardinus.core;version='1.3.0',\ org.alloytools.alloy.core;version=latest,\ + org.alloytools.alloy.dash;version=latest,\ aQute.libg,\ org.alloytools.api -testpath: \ @@ -16,3 +17,4 @@ Private-Package: \ edu.mit.csail.sdg.alloy4graph,\ edu.mit.csail.sdg.alloy4viz,\ edu.mit.csail.sdg.alloy4whole,\ + ca.uwaterloo.watform.dash4whole,\ \ No newline at end of file diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java index e742d0996..1652f4b2d 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java @@ -117,7 +117,7 @@ * variable argument is passed */ -public final class CompModule extends Browsable implements Module { +public class CompModule extends Browsable implements Module { // These fields are shared by all Modules that point to each other @@ -194,7 +194,7 @@ public String path() { * The position of the "MODULE" line at the top of the file; Pos.UNKNOWN if the * line has not been parsed from the file yet. */ - private Pos modulePos = Pos.UNKNOWN; + public Pos modulePos = Pos.UNKNOWN; /** * The text of the "MODULE" line at the top of the file; "unknown" if the line @@ -205,7 +205,7 @@ public String path() { /** * Whether we have seen a name containing a dollar sign or not. */ - boolean seenDollar = false; + public boolean seenDollar = false; /** * Each param is mapped to its corresponding Sig (or null if we have not @@ -225,7 +225,7 @@ public String path() { private final Map opens = new LinkedHashMap(); /** Each sig name is mapped to its corresponding SigAST. */ - private final Map sigs = new LinkedHashMap(); + public final Map sigs = new LinkedHashMap(); /** * The list of params in this module whose scope shall be deemed "exact" @@ -235,7 +235,7 @@ public String path() { /** * The current name resolution mode (0=pure) (1=Alloy 4.1.3 and older) (2=new) */ - int resolution = 1; + public int resolution = 1; /** * Each func name is mapped to a nonempty list of FunAST objects. @@ -771,7 +771,7 @@ private Open(Pos pos, boolean isPrivate, String alias, ConstList args, S /** * Connect this OPEN statement to a module that it points to. */ - void connect(CompModule realModule) throws Err { + public void connect(CompModule realModule) throws Err { if (this.realModule != null && this.realModule != realModule) throw new ErrorFatal("Internal error (import mismatch)"); this.realModule = realModule; @@ -814,7 +814,7 @@ public String explain() { * @param filename - the filename corresponding to this module * @param path - one of the path pointing to this module */ - CompModule(CompModule world, String filename, String path) throws Err { + public CompModule(CompModule world, String filename, String path) throws Err { if (world == null) { if (path.length() > 0) throw new ErrorFatal("Root module misparsed by parser."); @@ -951,7 +951,7 @@ private static String base(Sig sig) { /** * Generate an error message saying the given keyword is no longer supported. */ - static ErrorSyntax hint(Pos pos, String name) { + public static ErrorSyntax hint(Pos pos, String name) { String msg = "The name \"" + name + "\" cannot be found."; if ("exh".equals(name) || "exhaustive".equals(name) || "part".equals(name) || "partition".equals(name)) msg = msg + " If you are migrating from Alloy 3, please see Help->QuickGuide on how to translate models that use the \"" + name + "\" keyword."; @@ -1252,7 +1252,7 @@ public ConstList getOpens() { } /** Add the "MODULE" declaration. */ - void addModelName(Pos pos, String moduleName, List list) throws Err { + public void addModelName(Pos pos, String moduleName, List list) throws Err { if (status > 0) throw new ErrorSyntax(pos, "The \"module\" declaration must occur at the top,\n" + "and can occur at most once."); this.moduleName = moduleName; @@ -1282,7 +1282,7 @@ void addModelName(Pos pos, String moduleName, List list) throws Err { } /** Add util/sequniv to the list of declarations. */ - void addSeq(Pos pos) throws Err { + public void addSeq(Pos pos) throws Err { int oldStatus = status; status = 0; try { @@ -1293,7 +1293,7 @@ void addSeq(Pos pos) throws Err { } /** Add an OPEN declaration. */ - void addOpen(Pos pos, Pos isPrivate, ExprVar name, List args, ExprVar alias) throws Err { + public void addOpen(Pos pos, Pos isPrivate, ExprVar name, List args, ExprVar alias) throws Err { if (status > 2) throw new ErrorSyntax(pos, "The \"open\" declaration must occur before any\n" + "sig/pred/fun/fact/assert/check/run command."); String as = (alias == null ? "" : alias.label); @@ -1348,7 +1348,7 @@ void addOpen(Pos pos, Pos isPrivate, ExprVar name, List args, ExprVar a } /** Do any post-parsing processing. */ - void doneParsing() { + public void doneParsing() { status = 3; LinkedHashMap copy = new LinkedHashMap(opens); opens.clear(); @@ -1469,11 +1469,11 @@ private static void resolveModules(A4Reporter rep, List modules) { // ============================================================================================================================// /** Add a sig declaration. */ - void addGhostSig() throws Err { + public void addGhostSig() throws Err { sigs.put(Sig.GHOST.label, Sig.GHOST); } - Sig addSig(Pos namePos, String name, ExprVar par, List parents, List fields, Expr fact, Attr... attributes) throws Err { + public Sig addSig(Pos namePos, String name, ExprVar par, List parents, List fields, Expr fact, Attr... attributes) throws Err { Sig obj; Pos pos = Pos.UNKNOWN.merge(WHERE.find(attributes)); @@ -1513,7 +1513,7 @@ Sig addSig(Pos namePos, String name, ExprVar par, List parents, List atoms, Pos closingBracket) throws Err { + public void addEnum(Pos pos, Pos priv, ExprVar name, List atoms, Pos closingBracket) throws Err { ExprVar EXTENDS = ExprVar.make(null, "extends"); ExprVar THIS = ExprVar.make(null, "this/" + name); List THESE = Arrays.asList(THIS); @@ -1603,7 +1603,7 @@ public SafeList getAllSigs() { // ============================================================================================================================// /** Add a MACRO declaration. */ - void addMacro(Pos p, Pos isPrivate, Pos labelPos, String label, List decls, Expr v) throws Err { + public void addMacro(Pos p, Pos isPrivate, Pos labelPos, String label, List decls, Expr v) throws Err { if (!Version.experimental) throw new ErrorSyntax(p, "LET declaration is allowed only inside a toplevel paragraph."); ConstList ds = ConstList.make(decls); @@ -1626,7 +1626,7 @@ public SafeList getAllMacros() { } /** Add a FUN or PRED declaration. */ - void addFunc(Pos p, Pos isPrivate, ExprVar n, Expr f, List decls, Expr t, Expr v) throws Err { + public void addFunc(Pos p, Pos isPrivate, ExprVar n, Expr f, List decls, Expr t, Expr v) throws Err { if (decls == null) decls = new ArrayList(); else @@ -1761,7 +1761,7 @@ public SafeList getAllFunc() { // ============================================================================================================================// /** Add an ASSERT declaration. */ - String addAssertion(Pos pos, Pos labelPos, String name, Expr value) throws Err { + public String addAssertion(Pos pos, Pos labelPos, String name, Expr value) throws Err { status = 3; if (name == null || name.length() == 0) name = "assert$" + (1 + asserts.size()); @@ -1808,7 +1808,7 @@ public ConstList getAllAssertions() { // ============================================================================================================================// /** Add a FACT declaration. */ - void addFact(Pos pos, String name, Expr value) throws Err { + public void addFact(Pos pos, String name, Expr value) throws Err { status = 3; if (name == null || name.length() == 0) name = "fact$" + (1 + facts.size()); @@ -1886,7 +1886,7 @@ public Expr getAllReachableFacts() { // ============================================================================================================================// /** Add a COMMAND declaration. */ - void addCommand(boolean followUp, Pos pos, ExprVar name, ExprVar commandKeyword, int overall, int bitwidth, int seq, int tmn, int tmx, int exp, List scopes, ExprVar label) throws Err { + public void addCommand(boolean followUp, Pos pos, ExprVar name, ExprVar commandKeyword, int overall, int bitwidth, int seq, int tmn, int tmx, int exp, List scopes, ExprVar label) throws Err { boolean check = commandKeyword.label.equals("c"); if (followUp && !Version.experimental) throw new ErrorSyntax(pos, "Syntax error encountering => symbol."); @@ -1907,7 +1907,7 @@ void addCommand(boolean followUp, Pos pos, ExprVar name, ExprVar commandKeyword, } /** Add a COMMAND declaration. */ - void addCommand(boolean followUp, Pos pos, Expr e, ExprVar commandKeyword, int overall, int bitwidth, int seq, int tmn, int tmx, int expects, List scopes, ExprVar label) throws Err { + public void addCommand(boolean followUp, Pos pos, Expr e, ExprVar commandKeyword, int overall, int bitwidth, int seq, int tmn, int tmx, int expects, List scopes, ExprVar label) throws Err { boolean check = commandKeyword.label.equals("c"); if (followUp && !Version.experimental) throw new ErrorSyntax(pos, "Syntax error encountering => symbol."); diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/sequniv.als b/org.alloytools.alloy.core/src/main/resources/models/util/sequniv.als index cd2a3cba5..0f91e398e 100644 --- a/org.alloytools.alloy.core/src/main/resources/models/util/sequniv.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/sequniv.als @@ -131,7 +131,7 @@ fun append [s1, s2: Int -> univ] : s1+s2 { * returns the subsequence of s between from and to, inclusive * Precondition: 0 <= from <= to < #s */ -fun subseq [s: Int -> univ, from, to: Int] : s { - let shift = {i", i: seq/Int | int[i"] = ui/sub[int[i], int[from]] } | +fun subseq [s: Int -> univ, frm, to: Int] : s { + let shift = {i", i: seq/Int | int[i"] = ui/sub[int[i], int[frm]] } | shift.((seq/Int - ui/nexts[to]) <: s) } diff --git a/org.alloytools.alloy.dist/bnd.bnd b/org.alloytools.alloy.dist/bnd.bnd index 014cf6ac2..3e2419198 100644 --- a/org.alloytools.alloy.dist/bnd.bnd +++ b/org.alloytools.alloy.dist/bnd.bnd @@ -5,6 +5,7 @@ JPM-Command: alloy -buildpath: \ org.alloytools.alloy.application,\ org.alloytools.alloy.core,\ + org.alloytools.alloy.dash,\ org.alloytools.alloy.extra,\ org.alloytools.api,\ aQute.libg, \ @@ -19,6 +20,7 @@ JPM-Command: alloy @${repo;org.alloytools.api}, \ @${repo;org.alloytools.alloy.application}, \ @${repo;org.alloytools.alloy.core}, \ + @${repo;org.alloytools.alloy.dash}, \ @${repo;org.alloytools.alloy.extra}, \ @${repo;org.alloytools.alloy.lsp}, \ @${repo;org.alloytools:pardinus.core}, \ From fe98daf07e1124131b4e22ff91281be88efe1a4e Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 8 Mar 2023 10:58:15 -0500 Subject: [PATCH 021/129] adding the Dash parsing files/CLI now (forgot in last commit) --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 183 +++ .../src/main/resources/models/util/buffer.als | 68 + .../src/main/resources/models/util/ctl.als | 94 ++ .../main/resources/models/util/ctl_path.als | 101 ++ .../resources/models/util/ctl_subgraph.als | 92 ++ .../src/main/resources/models/util/ctlfc.als | 81 + .../main/resources/models/util/ctlfc_path.als | 112 ++ .../resources/models/util/ctlfc_subgraph.als | 103 ++ .../src/main/resources/models/util/ring.als | 8 + .../src/main/resources/models/util/traces.als | 47 + org.alloytools.alloy.dash/.classpath | 18 + org.alloytools.alloy.dash/.project | 40 + org.alloytools.alloy.dash/bnd.bnd | 44 + .../parser/Dash-cup-grammar.txt | 182 +++ .../parser/Dash-cup-imports.txt | 8 + .../parser/Dash-cup-nonterminals.txt | 15 + .../parser/Dash-cup-symbols.txt | 30 + .../parser/Dash-cup-terminals.txt | 30 + .../parser/Dash-lex-addition.txt | 27 + .../parser/Dash-lex-imports.txt | 2 + org.alloytools.alloy.dash/parser/Dash.cup | 1444 +++++++++++++++++ org.alloytools.alloy.dash/parser/Dash.lex | 297 ++++ org.alloytools.alloy.dash/parser/README.md | 10 + .../parser/install-alloy-files.sh | 64 + .../alloyasthelper/AlloyDeclHelper.java | 25 + .../alloyasthelper/AlloyExprHelper.java | 134 ++ .../java/ca/uwaterloo/watform/ast/Dash.java | 19 + .../ca/uwaterloo/watform/ast/DashAction.java | 29 + .../watform/ast/DashBufferDecls.java | 39 + .../uwaterloo/watform/ast/DashCondition.java | 29 + .../java/ca/uwaterloo/watform/ast/DashDo.java | 26 + .../uwaterloo/watform/ast/DashEventDecls.java | 33 + .../ca/uwaterloo/watform/ast/DashExpr.java | 95 ++ .../ca/uwaterloo/watform/ast/DashFrom.java | 16 + .../ca/uwaterloo/watform/ast/DashGoto.java | 17 + .../ca/uwaterloo/watform/ast/DashInit.java | 29 + .../ca/uwaterloo/watform/ast/DashInv.java | 32 + .../java/ca/uwaterloo/watform/ast/DashOn.java | 17 + .../ca/uwaterloo/watform/ast/DashSend.java | 32 + .../ca/uwaterloo/watform/ast/DashState.java | 218 +++ .../ca/uwaterloo/watform/ast/DashTrans.java | 33 + .../uwaterloo/watform/ast/DashVarDecls.java | 36 + .../ca/uwaterloo/watform/ast/DashWhen.java | 17 + .../uwaterloo/watform/core/DashOptions.java | 19 + .../uwaterloo/watform/core/DashSituation.java | 23 + .../uwaterloo/watform/core/DashStrings.java | 104 ++ .../watform/mainfunctions/MainFunctions.java | 95 ++ .../watform/parser/CompModuleHelper.java | 244 +++ .../uwaterloo/watform/parser/DashFilter.java | 473 ++++++ .../uwaterloo/watform/parser/DashModule.java | 264 +++ .../ca/uwaterloo/watform/parser/DashUtil.java | 513 ++++++ .../uwaterloo/watform/parser/SymbolTable.java | 109 ++ .../watform/parser/install-alloy-files.sh | 65 + pbuild.sh | 8 + 54 files changed, 5893 insertions(+) create mode 100644 org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java create mode 100644 org.alloytools.alloy.core/src/main/resources/models/util/buffer.als create mode 100644 org.alloytools.alloy.core/src/main/resources/models/util/ctl.als create mode 100755 org.alloytools.alloy.core/src/main/resources/models/util/ctl_path.als create mode 100755 org.alloytools.alloy.core/src/main/resources/models/util/ctl_subgraph.als create mode 100755 org.alloytools.alloy.core/src/main/resources/models/util/ctlfc.als create mode 100755 org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_path.als create mode 100755 org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_subgraph.als create mode 100644 org.alloytools.alloy.core/src/main/resources/models/util/ring.als create mode 100644 org.alloytools.alloy.core/src/main/resources/models/util/traces.als create mode 100644 org.alloytools.alloy.dash/.classpath create mode 100644 org.alloytools.alloy.dash/.project create mode 100644 org.alloytools.alloy.dash/bnd.bnd create mode 100644 org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt create mode 100644 org.alloytools.alloy.dash/parser/Dash-cup-imports.txt create mode 100644 org.alloytools.alloy.dash/parser/Dash-cup-nonterminals.txt create mode 100644 org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt create mode 100644 org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt create mode 100644 org.alloytools.alloy.dash/parser/Dash-lex-addition.txt create mode 100644 org.alloytools.alloy.dash/parser/Dash-lex-imports.txt create mode 100644 org.alloytools.alloy.dash/parser/Dash.cup create mode 100644 org.alloytools.alloy.dash/parser/Dash.lex create mode 100644 org.alloytools.alloy.dash/parser/README.md create mode 100755 org.alloytools.alloy.dash/parser/install-alloy-files.sh create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyDeclHelper.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyExprHelper.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/Dash.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashUtil.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/SymbolTable.java create mode 100755 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh create mode 100755 pbuild.sh diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java new file mode 100644 index 000000000..123c862b9 --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -0,0 +1,183 @@ +package ca.uwaterloo.watform.dash4whole; + +import java.util.*; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.Files; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4viz.VizGUI; +import edu.mit.csail.sdg.ast.Command; +import edu.mit.csail.sdg.parser.CompModule; +import edu.mit.csail.sdg.translator.A4Options; +import edu.mit.csail.sdg.translator.A4Solution; +import edu.mit.csail.sdg.translator.TranslateAlloyToKodkod; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.mainfunctions.MainFunctions; + + + + +public class Dash { + + @SuppressWarnings("resource" ) + + public static void main(String args[]) throws Exception { + + if(args.length == 0) { + System.out.println("Arguments: (-m traces|tcmc|electrum) (-c #) (-p) (-t) filename(s); -c is cmdnum; -t is translateOnly"); + System.exit(0); + } + + // simple roll-our-own argument parser + // to avoid having to import an external package + + List filelist = new ArrayList<>(); + + // default values + String method = "traces"; + Integer cmdnum = 0; + Boolean translateOnly = false; + Boolean printOnly = false; + + for (int i=0; i 0) { + System.err.println("Expected a Dash file with 'dsh' or 'als' extension: "+filename); + break; + } else { + filename = filename + ".dsh"; + } + } + + Path f = Paths.get(filename); + + if (Files.notExists(f)) { + System.err.println(filename + " : does not exist"); + return; + } + + Path directory = f.toAbsolutePath().getParent(); + if (directory.toString() != null) + DashOptions.dashModelLocation = directory.toString(); + + //Parse+typecheck the model + //System.out.println("Reading: " + filename ); + + A4Reporter rep = new A4Reporter(); + CompModule alloymodule = null; + DashModule d = MainFunctions.parseFile(filename.toString(), rep); + if (printOnly) { + if (d != null) { + String o = MainFunctions.dumpString(d); + System.out.println(o); + // System.out.println("File parsed successfully."); + } + } else { + try { + alloymodule = MainFunctions.translateToAlloy(d, rep); + } catch (Exception e) { + System.err.println(e); + System.exit(1); + } + if (alloymodule == null) { + System.err.println("Something went wrong"); + System.exit(1); + } + if (translateOnly) { + try { + // have to fix output name + String outfilename = filename.substring(0,filename.length()-4) + "-" + method + ".als"; + File out = new File(outfilename); + if (!out.exists()) { + out.createNewFile(); + } + System.out.println("Creating: " + outfilename); + // NAD tmp + //String content = new DashModuleToString(true).getString(alloymodule); + //FileWriter fw = new FileWriter(out.getAbsoluteFile()); + //BufferedWriter bw = new BufferedWriter(fw); + //bw.write(content); + //bw.close(); + } catch(Exception e){ + System.err.println(e); + } + } else { + // execute command(s) + + // Choose some default options for how you want to execute the commands + A4Options options = new A4Options(); + + List commands = alloymodule.getAllCommands(); + // this is an annoying way to convert a list to an array + Integer i = 1; + for (Command cmd : commands) { + if (i == cmdnum | cmdnum == 0) { + System.out.println("Executing command: " + cmd); + A4Solution ans = MainFunctions.executeCommand(cmd,alloymodule,rep, options); + if (ans.satisfiable()) { + System.out.println("Result: SAT"); + } else { + System.out.println("Result: UNSAT"); + } + } + i++; + } + if (cmdnum >= i) { + System.err.println("Command number: " + cmdnum + " does not exist in file"); + } + } + } + } + } +} + diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/buffer.als b/org.alloytools.alloy.core/src/main/resources/models/util/buffer.als new file mode 100644 index 000000000..865c201be --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/buffer.als @@ -0,0 +1,68 @@ +module util/buffer[elem, BufIdx] + +open util/ordering[BufIdx] as ord + +/** returns all the elements in this sequence */ +fun elems [R: BufIdx->elem]: set elem { BufIdx.(R) } + +/** returns the first element in the sequence */ +fun firstElem [R: BufIdx->elem]: lone elem { ord/first.R } + +/** returns the last element in the sequence */ +fun lastElem [R: BufIdx->elem]: lone elem { R.at[R.lastIdx] } + +/** true if the sequence is empty */ +pred isEmpty [R: BufIdx -> elem] { no R} + +/** returns last index occupied by this sequence */ +fun lastIdx [R: BufIdx->elem] : lone BufIdx { ord/max[R.elem] } + +/** returns all the indices occupied by this sequence */ +fun inds [R: BufIdx->elem] : set BufIdx { elem.~(R) } + +/** returns element at the given index */ +fun at [R: BufIdx->elem, i: BufIdx]: lone elem { i.(R) } + +/** + * returns the index after the last index + * if this sequence is empty, returns the first index, + * if this sequence is full, returns empty set + */ +fun afterLastIdx [R: BufIdx->elem] : lone BufIdx { + ord/min[BufIdx - R.inds] +} + +/** true if this sequence has duplicates */ +pred hasDups [R: BufIdx->elem] { # elems[R] < # inds[R] } + +/** added is the result of appending e to the end of R */ +pred add [R: BufIdx->elem, R_next: BufIdx->elem, e: elem] { + R_next = R + (R.afterLastIdx -> e) +} + +/** + * Set the first element in R_next + * Copy over the remaning elements from R to R_next +*/ +pred addFirst [R: BufIdx->elem, R_next: BufIdx->elem, e: elem] { + R_next.firstElem = e + some R => { (all i: R.inds - firstIdx | R_next.at[i] = R.at[ord/prev[i]]) and R_next.at[R.afterLastIdx] = R.lastElem } +} + +/** Substract the relation (lastIndex -> lastElem) from the set of relations in R */ +pred remove [R: BufIdx->elem, R_next: BufIdx->elem] { + R_next = R - (lastIdx[R] -> lastElem[R]) +} + +/** + * R_next[index - 1] = R[index] for each index > 0 in R. The first index is not copied since we are removing it + * The lastIndex in R_next is equal to (lastIndex - 1) in R +*/ +pred removeFirst [R: BufIdx->elem, R_next: BufIdx->elem] { + one R.inds => (no R_next.inds) else { + (all i: R.inds - ord/first | R_next.at[ord/prev[i]] = R.at[i]) + lastIdx[R_next] = ord/prev[lastIdx[R]] + } +} + +fun firstIdx: BufIdx { ord/first } diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctl.als b/org.alloytools.alloy.core/src/main/resources/models/util/ctl.als new file mode 100644 index 000000000..204f642e5 --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/ctl.als @@ -0,0 +1,94 @@ +/* +/* + * Copyright (c) 2012, Amirhossein Vakili + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module util/ctl[S] + +//********************KRIPKE STRUCTURE DEF*************************// + +one sig TS{ + S0: some S, + sigma: S -> S, +} + +//********************MODEL SET UP FUNCTIONS*************************// +// set by users in their model files + +fun ks_s0: some S {TS.S0} + +fun ks_sigma: S -> S {TS.sigma} + +//********************HELPER FUNCTIONS*************************// + +private fun bound[R: S -> S, X: S]: S -> S {X <: R} +private fun id[X:S]: S->S{bound[iden,X]} +private fun loop[R: S -> S]: S {S.(^R & id[S])} +--private fun loop[R: S -> S]: S {{a:S | (a->a) in ^R}} + +//********************LOGICAL OPERATORS*************************// + +fun not_ctl[phi: S]: S {S - phi} +fun and_ctl[phi, si: S]: S {phi & si} +fun or_ctl[phi, si: S]: S {phi + si} +fun imp_ctl[phi, si: S]: S {not_ctl[phi] + si} + +//********************TEMPORAL OPERATORS*************************// + +fun ex[phi: S]: S {TS.sigma.phi} + +fun ax[phi:S]:S {not_ctl[ex[not_ctl[phi]]]} + +fun ef[phi: S]: S {(*(TS.sigma)).phi } + +fun eg[phi: S]: S { + let R= bound[TS.sigma,phi]| + let Loop = loop[R]| + (*R).Loop +} + +fun af[phi: S]: S {not_ctl[eg[not_ctl[phi]]]} + +fun ag[phi: S]: S {not_ctl[ef[not_ctl[phi]]]} + +fun eu[phi, si: S]: S {(*(bound[TS.sigma, phi])).si} + +fun au[phi, si: S]: S { + not_ctl[ + or_ctl[ + eg[not_ctl[si]], + eu[ + not_ctl[si], + not_ctl[or_ctl[phi, si]] + ] + ] + ] +} + +//********************MODEL CHECKING CONSTRAINT*************************// +// called by users for mc in their model file +pred ctl_mc[phi: S]{TS.S0 in phi} diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctl_path.als b/org.alloytools.alloy.core/src/main/resources/models/util/ctl_path.als new file mode 100755 index 000000000..dd25ecc2c --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/ctl_path.als @@ -0,0 +1,101 @@ +/* + * Original work Copyright (c) 2017, Amirhossein Vakili, Sabria Farheen, + * Nancy A. Day, Ali Abbassi + * Modified work Copyright (c) 2019, Mitchell Kember, Thi My Linh Tran, + * Yuezhou Gao, Nancy A. Day + * This file is part of the TCMC-Path project, which is released under the + * FreeBSD License. See LICENSE.txt for full license details, or visit + * https://opensource.org/licenses/BSD-2-Clause. + */ + +module ctl_path[S] + +// ********** Kripke structure ************************************************* + +one sig TS { + S0: some S, + sigma: S -> S, +} + +// ********* Path definition *************************************************** + +// The path is a linked list of nodes. +sig PathNode { + // Each node has 0 or 1 successor. + nextNode: lone PathNode, + // Each node points to a different state. + nodeState: disj one S +} + +// The path has a start node. +one sig P0 in PathNode {} + +// We can project PathNode onto the transition system. +fun pathState: S { PathNode.nodeState } +fun pathSigma: S -> S { ~nodeState.nextNode.nodeState } + +fact { + // The path respects transitions. + pathSigma in TS.sigma + // The start node is in an initial state. + P0.nodeState in TS.S0 + // The path is connected. + P0.*nextNode = PathNode +} + +// Allow the user to optionally enforce a finite path. +pred finitePath { + some p : PathNode | no p.nextNode +} + +// ********** Model setup functions ******************************************** + +// Set by users in their model files. + +fun ks_s0: S { TS.S0 } + +fun ks_sigma: S -> S { TS.sigma } + +// ********** Helper functions ************************************************* + +private fun domainRes[R: S -> S, X: S]: S -> S { X <: R } +private fun id[X:S]: S -> S { domainRes[iden,X] } + +// ********** Logical operators ************************************************ + +fun not_[phi: S]: S { S - phi } +fun and_[phi, si: S]: S { phi & si } +fun or_[phi, si: S]: S { phi + si } +fun imp_[phi, si: S]: S { not_[phi] + si } + +// ********** Temporal operators *********************************************** + +fun ex[phi: S]: S { pathSigma.phi } + +fun ax[phi:S]: S { not_[ex[not_[phi]]] } + +fun ef[phi: S]: S { (*(pathSigma)).phi } + +fun eg[phi:S]: S { + let R = domainRes[pathSigma, phi] | + *R.((^R & id[S]).S) +} + +fun af[phi: S]: S { not_[eg[not_[phi]]] } + +fun ag[phi: S]: S { not_[ef[not_[phi]]] } + +fun eu[phi, si: S]: S { + (*(domainRes[pathSigma, phi])).si +} + +// TODO: Why was this only defined in ctlfc.als and not ctl.als? +fun au[phi, si: S]: S { + not_[or_[eg[not_[si]], + eu[not_[si], not_[or_[phi, si]]]]] +} + +// ********** Model checking constraint **************************************** + +// Called by users for model checking in their model file. +pred ctl_mc[phi: S] { TS.S0 in phi } diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctl_subgraph.als b/org.alloytools.alloy.core/src/main/resources/models/util/ctl_subgraph.als new file mode 100755 index 000000000..451e4a880 --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/ctl_subgraph.als @@ -0,0 +1,92 @@ +/* + * Original work Copyright (c) 2017, Amirhossein Vakili, Sabria Farheen, + * Nancy A. Day, Ali Abbassi + * Modified work Copyright (c) 2019, Mitchell Kember, Thi My Linh Tran, + * Yuezhou Gao, Nancy A. Day + * This file is part of the TCMC-Path project, which is released under the + * FreeBSD License. See LICENSE.txt for full license details, or visit + * https://opensource.org/licenses/BSD-2-Clause. + */ + +module ctl_subgraph[S] + +// ********** Kripke structure ************************************************* + +one sig TS { + S0: some S, + sigma: S -> S, +} + +// ********* Subgraph definition *********************************************** + +// Reify the transition relation as a signature. +sig Transition { + transFrom: S, + transTo: S +} + +// We can project Transition onto the transition system. +fun subState: S { Transition.(transFrom + transTo) } +fun subSigma: S -> S { ~transFrom.transTo } + +fact { + // The subgraph respects transitions. + subSigma in TS.sigma + // There are no duplicate Transition elements. + all t, t': Transition | + t.transFrom = t'.transFrom && t.transTo = t'.transTo => t = t' + // The subgraph is connected. + some s: S | s.~transFrom.(*(transTo.~transFrom)) = Transition +} + +// ********** Model setup functions ******************************************** + +// Set by users in their model files. + +fun initialState: S { TS.S0 } + +fun nextState: S -> S { TS.sigma } + +// ********** Helper functions ************************************************* + +private fun domainRes[R: S -> S, X: S]: S -> S { X <: R } +private fun id[X:S]: S -> S { domainRes[iden,X] } + +// ********** Logical operators ************************************************ + +fun not_[phi: S]: S { S - phi } +fun and_[phi, si: S]: S { phi & si } +fun or_[phi, si: S]: S { phi + si } +fun imp_[phi, si: S]: S { not_[phi] + si } + +// ********** Temporal operators *********************************************** + +fun ex[phi: S]: S { subSigma.phi } + +fun ax[phi:S]: S { not_[ex[not_[phi]]] } + +fun ef[phi: S]: S { (*(subSigma)).phi } + +fun eg[phi:S]: S { + let R = domainRes[subSigma, phi] | + *R.((^R & id[S]).S) +} + +fun af[phi: S]: S { not_[eg[not_[phi]]] } + +fun ag[phi: S]: S { not_[ef[not_[phi]]] } + +fun eu[phi, si: S]: S { + (*(domainRes[subSigma, phi])).si +} + +// TODO: Why was this only defined in ctlfc.als and not ctl.als? +fun au[phi, si: S]: S { + not_[or_[eg[not_[si]], + eu[not_[si], not_[or_[phi, si]]]]] +} + +// ********** Model checking constraint **************************************** + +// Called by users for model checking in their model file. +pred ctl_mc[phi: S] { TS.S0 in phi } diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc.als b/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc.als new file mode 100755 index 000000000..59967619d --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc.als @@ -0,0 +1,81 @@ +/* + * Original work Copyright (c) 2017, Amirhossein Vakili, Sabria Farheen, + * Nancy A. Day, Ali Abbassi + * Modified work Copyright (c) 2019, Mitchell Kember, Thi My Linh Tran, + * Yuezhou Gao, Nancy A. Day + * This file is part of the TCMC-Path project, which is released under the + * FreeBSD License. See LICENSE.txt for full license details, or visit + * https://opensource.org/licenses/BSD-2-Clause. + */ + +module ctlfc[S] + +// ********** Kripke structure ************************************************* + +one sig TS { + S0: some S, + sigma: S -> S, + FC: set S +} + +// ********** Model setup functions ******************************************** + +// Set by users in their model files. + +fun initialState: S { TS.S0 } + +fun nextState: S -> S { TS.sigma } + +fun fc: S { TS.FC } + +// ********** Helper functions ************************************************* + +private fun domainRes[R: S -> S, X: S]: S -> S { X <: R } +private fun id[X:S]: S -> S { domainRes[iden,X] } + +// ********** Fair states definition ******************************************* + +// Fair is EcG true. +private fun Fair: S { + let R = TS.sigma | + *R.((^R & id[S]).S & TS.FC) +} + +// ********** Logical operators ************************************************ + +fun not_[phi: S]: S { S - phi } +fun and_[phi, si: S]: S { phi & si } +fun or_[phi, si: S]: S { phi + si } +fun imp_[phi, si: S]: S { not_[phi] + si } + +// ********** Temporal operators *********************************************** + +fun ex[phi: S]: S { TS.sigma.(phi & Fair) } + +fun ax[phi:S]: S { not_[ex[not_[phi]]] } + +fun ef[phi: S]: S { (*(TS.sigma)).(phi & Fair) } + +fun eg[phi:S]: S { + let R = domainRes[TS.sigma, phi] | + *R.(((^R & id[S]).S & TS.FC)) +} + +fun af[phi: S]: S { not_[eg[not_[phi]]] } + +fun ag[phi: S]: S { not_[ef[not_[phi]]] } + +fun eu[phi, si: S]: S { + (*(domainRes[TS.sigma, phi])).(si & Fair) +} + +// TODO: Why was this only defined in ctlfc.als and not ctl.als? +fun au[phi, si: S]: S { + not_[or_[eg[not_[si]], + eu[not_[si], not_[or_[phi, si]]]]] +} + +// ********** Model checking constraint **************************************** + +// Called by users for model checking in their model file. +pred ctlfc_mc[phi: S] { TS.S0 in phi } diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_path.als b/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_path.als new file mode 100755 index 000000000..68bcb80d7 --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_path.als @@ -0,0 +1,112 @@ +/* + * Original work Copyright (c) 2017, Amirhossein Vakili, Sabria Farheen, + * Nancy A. Day, Ali Abbassi + * Modified work Copyright (c) 2019, Mitchell Kember, Thi My Linh Tran, + * Yuezhou Gao, Nancy A. Day + * This file is part of the TCMC-Path project, which is released under the + * FreeBSD License. See LICENSE.txt for full license details, or visit + * https://opensource.org/licenses/BSD-2-Clause. + */ + +module ctlfc_path[S] + +// ********** Kripke structure ************************************************* + +one sig TS { + S0: some S, + sigma: S -> S, + FC: set S +} + +// ********* Path definition *************************************************** + +// The path is a linked list of nodes. +sig PathNode { + // Each node has 0 or 1 successor. + nextNode: lone PathNode, + // Each node points to a different state. + nodeState: disj one S +} + +// The path has a start node. +one sig P0 in PathNode {} + +// We can project PathNode onto the transition system. +fun pathState: S { PathNode.nodeState } +fun pathSigma: S -> S { ~nodeState.nextNode.nodeState } + +fact { + // The path respects transitions. + pathSigma in TS.sigma + // The start node is in an initial state. + P0.nodeState in TS.S0 + // The path is connected. + P0.*nextNode = PathNode +} + +// Allow the user to optionally enforce a finite path. +pred finitePath { + some p : PathNode | no p.nextNode +} + +// ********** Model setup functions ******************************************** + +// Set by users in their model files. + +fun initialState: S { TS.S0 } + +fun nextState: S -> S { TS.sigma } + +fun fc: S { TS.FC } + +// ********** Helper functions ************************************************* + +private fun domainRes[R: S -> S, X: S]: S -> S { X <: R } +private fun id[X:S]: S -> S { domainRes[iden,X] } + +// ********** Fair states definition ******************************************* + +// Fair is EcG true. +private fun Fair: S { + let R = pathSigma | + *R.((^R & id[S]).S & TS.FC) +} + +// ********** Logical operators ************************************************ + +fun not_[phi: S]: S { S - phi } +fun and_[phi, si: S]: S { phi & si } +fun or_[phi, si: S]: S { phi + si } +fun imp_[phi, si: S]: S { not_[phi] + si } + +// ********** Temporal operators *********************************************** + +fun ex[phi: S]: S { pathSigma.(phi & Fair) } + +fun ax[phi:S]: S { not_[ex[not_[phi]]] } + +fun ef[phi: S]: S { (*(pathSigma)).(phi & Fair) } + +fun eg[phi:S]: S { + let R = domainRes[pathSigma, phi] | + *R.(((^R & id[S]).S & TS.FC)) +} + +fun af[phi: S]: S { not_[eg[not_[phi]]] } + +fun ag[phi: S]: S { not_[ef[not_[phi]]] } + +fun eu[phi, si: S]: S { + (*(domainRes[pathSigma, phi])).(si & Fair) +} + +// TODO: Why was this only defined in ctlfc.als and not ctl.als? +fun au[phi, si: S]: S { + not_[or_[eg[not_[si]], + eu[not_[si], not_[or_[phi, si]]]]] +} + +// ********** Model checking constraint **************************************** + +// Called by users for model checking in their model file. +pred ctlfc_mc[phi: S] { TS.S0 in phi } diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_subgraph.als b/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_subgraph.als new file mode 100755 index 000000000..a26d50f31 --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_subgraph.als @@ -0,0 +1,103 @@ +/* + * Original work Copyright (c) 2017, Amirhossein Vakili, Sabria Farheen, + * Nancy A. Day, Ali Abbassi + * Modified work Copyright (c) 2019, Mitchell Kember, Thi My Linh Tran, + * Yuezhou Gao, Nancy A. Day + * This file is part of the TCMC-Path project, which is released under the + * FreeBSD License. See LICENSE.txt for full license details, or visit + * https://opensource.org/licenses/BSD-2-Clause. + */ + +module ctlfc_subgraph[S] + +// ********** Kripke structure ************************************************* + +one sig TS { + S0: some S, + sigma: S -> S, + FC: set S +} + +// ********* Subgraph definition *********************************************** + +// Reify the transition relation as a signature. +sig Transition { + transFrom: S, + transTo: S +} + +// We can project Transition onto the transition system. +fun subState: S { Transition.(transFrom + transTo) } +fun subSigma: S -> S { ~transFrom.transTo } + +fact { + // The subgraph respects transitions. + subSigma in TS.sigma + // There are no duplicate Transition elements. + all t, t': Transition | + t.transFrom = t'.transFrom && t.transTo = t'.transTo => t = t' + // The subgraph is connected. + some s: S | s.~transFrom.(*(transTo.~transFrom)) = Transition +} + +// ********** Model setup functions ******************************************** + +// Set by users in their model files. + +fun initialState: S { TS.S0 } + +fun nextState: S -> S { TS.sigma } + +fun fc: S { TS.FC } + +// ********** Helper functions ************************************************* + +private fun domainRes[R: S -> S, X: S]: S -> S { X <: R } +private fun id[X:S]: S -> S { domainRes[iden,X] } + +// ********** Fair states definition ******************************************* + +// Fair is EcG true. +private fun Fair: S { + let R = subSigma | + *R.((^R & id[S]).S & TS.FC) +} + +// ********** Logical operators ************************************************ + +fun not_[phi: S]: S { S - phi } +fun and_[phi, si: S]: S { phi & si } +fun or_[phi, si: S]: S { phi + si } +fun imp_[phi, si: S]: S { not_[phi] + si } + +// ********** Temporal operators *********************************************** + +fun ex[phi: S]: S { subSigma.(phi & Fair) } + +fun ax[phi:S]: S { not_[ex[not_[phi]]] } + +fun ef[phi: S]: S { (*(subSigma)).(phi & Fair) } + +fun eg[phi:S]: S { + let R = domainRes[subSigma, phi] | + *R.(((^R & id[S]).S & TS.FC)) +} + +fun af[phi: S]: S { not_[eg[not_[phi]]] } + +fun ag[phi: S]: S { not_[ef[not_[phi]]] } + +fun eu[phi, si: S]: S { + (*(domainRes[subSigma, phi])).(si & Fair) +} + +// TODO: Why was this only defined in ctlfc.als and not ctl.als? +fun au[phi, si: S]: S { + not_[or_[eg[not_[si]], + eu[not_[si], not_[or_[phi, si]]]]] +} + +// ********** Model checking constraint **************************************** + +// Called by users for model checking in their model file. +pred ctlfc_mc[phi: S] { TS.S0 in phi } diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ring.als b/org.alloytools.alloy.core/src/main/resources/models/util/ring.als new file mode 100644 index 000000000..857a236f1 --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/ring.als @@ -0,0 +1,8 @@ +module util/ring[exactly elem] +open util/ordering[elem] as order + +fun nextRing [ie: elem] : lone elem { + {m: elem | no order/next[ie] implies m = order/first + else m = order/next[ie] + } +} diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/traces.als b/org.alloytools.alloy.core/src/main/resources/models/util/traces.als new file mode 100644 index 000000000..a5e8ccab2 --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/traces.als @@ -0,0 +1,47 @@ +/* + Src: ??? + Modified to change s' to s_next for Alloy 6 +*/ +module util/traces[exactly elem] + +private one sig Ord { + First: set elem, + Next: elem -> elem +} { + pred/totalOrder[elem,First,Next] +} + +lone sig back in elem {} + +fun loop : elem -> elem { + last -> back +} + +fun first: one elem { Ord.First } + +fun last: one elem { elem - ((Ord.Next).elem) } + +fun next : elem->elem { Ord.Next + loop } + +fun prev : elem->elem { ~this/next } + +fun past : elem->elem { ^(~this/next) } + +fun future : elem -> elem { elem <: *this/next } + +fun upto[s,s_next : elem] : set elem { + (s_next in s.*(Ord.Next) or finite) implies s.future & ^(Ord.Next).s_next else s.*(Ord.Next) + (^(Ord.Next).s_next & back.*(Ord.Next)) +} + + +pred finite { + no loop +} + +pred infinite { + some loop +} + +check total { + finite implies pred/totalOrder[elem,first,next] +} diff --git a/org.alloytools.alloy.dash/.classpath b/org.alloytools.alloy.dash/.classpath new file mode 100644 index 000000000..c50c180fc --- /dev/null +++ b/org.alloytools.alloy.dash/.classpath @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/org.alloytools.alloy.dash/.project b/org.alloytools.alloy.dash/.project new file mode 100644 index 000000000..91acaca33 --- /dev/null +++ b/org.alloytools.alloy.dash/.project @@ -0,0 +1,40 @@ + + + org.alloytools.alloy.dash + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + org.eclipse.buildship.core.gradleprojectnature + + + + 1678133835920 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/org.alloytools.alloy.dash/bnd.bnd b/org.alloytools.alloy.dash/bnd.bnd new file mode 100644 index 000000000..fb25c92bd --- /dev/null +++ b/org.alloytools.alloy.dash/bnd.bnd @@ -0,0 +1,44 @@ +-dependson org.alloytools.alloy.wrappers + +-includeresource: \ + src/main/resources, \ + @${repo;slf4j.api}, \ + +-buildpath: \ + org.alloytools:pardinus.core;version='1.3.0',\ + org.alloytools:pardinus.nativesat;version='1.3.0',\ + org.eclipse.jdt.annotation,\ + org.alloytools.alloy.core;version=latest,\ + com.io7m.jpplib.io7m-jpplib-core;version=0.7.4,\ + +-testpath: \ + biz.aQute.wrapper.junit, \ + biz.aQute.wrapper.hamcrest, \ + src/main/resources;version=file, \ + slf4j.api, \ + org.sat4j.core, \ + +Export-Package: \ + ca.uwaterloo.watform.alloyasthelper,\ + ca.uwaterloo.watform.core,\ + ca.uwaterloo.watform.ast,\ + ca.uwaterloo.watform.parser,\ + ca.uwaterloo.watform.dashtoalloy,\ + ca.uwaterloo.watform.mainfunctions,\ + de.uka.ilkd.pp,\ + +Private-Package: \ + java_cup.runtime + + +src=${^src},gen/java + +-generate: \ + parser/; \ + output=gen/java/; \ + workingdir=gen/java/ca/uwaterloo/watform/parser; \ + generate= \ + "JFlex.Main -d . -nobak ./parser/Dash.lex; \ + java_cup.Main -dump -parser DashParser -symbols DashSym -compact_red <./parser/Dash.cup 2>target/report" + +-fixupmessages: "Export ca.uwaterloo.watform.parser" diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt new file mode 100644 index 000000000..0cf322f68 --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -0,0 +1,182 @@ + + +//DASH grammar ------------------------------------------------------------------------ + +// besides creating a DashState; the parsing also has count buffers and create indexes +// for those buffers in order to have the correct open statements + +// adding a case for the Spec +Spec ::= Spec StateRoot:o ; + +// Root State Declaration +StateRoot ::= STATE:o Name:n LBRACE RBRACE:e // empty state + {: + parser.dashmodule.rootStartLine = o.y; + parser.dashmodule.rootEndLine = e.y; + parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT)); + :}; +StateRoot ::= STATE:o Name:n LBRACE StateItemList:c RBRACE:e + {: + parser.dashmodule.rootStartLine = o.y; + parser.dashmodule.rootEndLine = e.y; + parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.NOTDEFAULT, c)); + :}; + +StateItemList ::= StateItem:x + {: List xList = new ArrayList(); xList.add(x); RESULT= xList; :}; +StateItemList ::= StateItemList:c StateItem:s + {: c.add(s); RESULT = c; :}; + +// empty state +StateItem ::= STATE:o Name:n LBRACE RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT ); :}; + +StateItem ::= STATE:o Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.NOTDEFAULT, c); :}; + +// empty state +StateItem ::= DEF STATE:o Name:n LBRACE RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.DefKind.DEFAULT); :}; + +StateItem ::= DEF STATE:o Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.DEFAULT, c); :}; + +// non parametrized state +StateItem ::= CONC:o STATE Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.StateKind.AND, DashStrings.DefKind.NOTDEFAULT, c); :}; + +// parametrized state +StateItem ::= CONC:o STATE Name:n LBRACKET Name:m RBRACKET LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, n.label, m.label, c); :}; + +// event decls +StateItem ::= EVENT:o Names:n LBRACE RBRACE + {: ArrayList ll = new ArrayList(); + for (ExprVar x: n) ll.add(x.label); + RESULT = new DashEventDecls(o, ll, DashStrings.IntEnvKind.INT); :}; +StateItem ::= ENV EVENT:o Names:n LBRACE RBRACE + {: ArrayList ll = new ArrayList(); + for (ExprVar x: n) ll.add(x.label); + RESULT = new DashEventDecls(o, ll, DashStrings.IntEnvKind.ENV); :}; + +// var decls +StateItem ::= + // we don't support the full variations of declarations here + // don't know what the pos should be for this one + Names:n COLON:o Expr:b + {: ArrayList ll = new ArrayList(); + for (ExprVar x: n) ll.add(x.label); + RESULT = new DashVarDecls(o, ll ,b, DashStrings.IntEnvKind.INT); :}; +StateItem ::= ENV:o Names:n COLON Expr:b + {: ArrayList ll = new ArrayList(); + for (ExprVar x: n) ll.add(x.label); + RESULT = new DashVarDecls(o, ll, b, DashStrings.IntEnvKind.ENV); :}; + +//buffer decls +StateItem ::= Names:n COLON:o BUF LBRACKET Name:m RBRACKET + {: + ArrayList ll = new ArrayList(); + for (ExprVar x: n) { + ll.add(x.label); + DashSituation.bufferElements.add(x.label); + } + RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.INT); + :}; +StateItem ::= Names:n COLON:o BUF LBRACKET SIGINT RBRACKET + {: + ArrayList ll = new ArrayList(); + for (ExprVar x: n) { + ll.add(x.label); + DashSituation.bufferElements.add(x.label); + } + RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT); + :}; +StateItem ::= ENV:o Names:n COLON BUF LBRACKET Name:m RBRACKET + {: + ArrayList ll = new ArrayList(); + for (ExprVar x: n) { + ll.add(x.label); + DashSituation.bufferElements.add(x.label); + } + RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV); + :}; + +StateItem ::= ENV:o Names:n COLON BUF LBRACKET SIGINT RBRACKET + {: + ArrayList ll = new ArrayList(); + for (ExprVar x: n) { + ll.add(x.label); + DashSituation.bufferElements.add(x.label); + } + RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV); + :}; + +// init +// Super is a list of expressions joined by conjunction +StateItem ::= INIT:o Super:v + {: RESULT = new DashInit(o, v); :}; + +// invariant +StateItem ::= INVARIANT:o Super:v + {: RESULT = new DashInv(o, v); :}; + +StateItem ::= INVARIANT:o Name:n Super:v + {: RESULT = new DashInv(o, n.label, v); :}; + +// action +StateItem ::= ACTION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE + {: RESULT = new DashAction(o, n.label, e); :}; + +// condition +StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE + {: RESULT = new DashCondition(o, n.label, e); :}; + +// transition +StateItem ::= TRANS:o Name:n LBRACE TransItemList:c RBRACE + {: RESULT = new DashTrans(o, n.label, c); :}; + +TransItemList ::= TransItem:x + {: RESULT = new ArrayList(); RESULT.add(x); :}; +TransItemList ::= TransItemList:c TransItem:x + {: c.add(x); RESULT = c; :}; + +TransItem ::= FROM:o Name:n + {: RESULT = new DashFrom(o, n.label); :}; + +TransItem ::= ON:o Expr:e + {: RESULT = new DashOn(o, e); :}; + +TransItem ::= WHEN:o Expr:v + {: RESULT = new DashWhen(o, v); :}; + +TransItem ::= DO:o Expr:v + {: RESULT = new DashDo(o, v); :}; + + +TransItem ::= GOTO:o Name:n + {: RESULT = new DashGoto(o, n.label); :}; + + +// this allows Send x.ev1 and "Send n" in parsing but will have to sort out later to see if correct +TransItem ::= SEND:o Expr:v + {: RESULT = new DashSend(o, v); :}; + +// DASH PLUS PROCESS VARIABLE REFERENCE +// ParamConcState[Param]/Variable +// result Param.ParamConcState/Variable +// not sure why a BadJoin is used here; but Alloy parsing rules use ExprBadJoins, not ExprJoins +// note PRIME is a special token in grammar and we want to support v' +BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e + {: + if (b.size() > 1) throw new ErrorSyntax(o,"Two many args to reference to sibling state"); + RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label)); + :}; +BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e PRIME + {: + if (b.size() > 1) throw new ErrorSyntax(o,"Two many args to reference to sibling state"); + // probably have to fix PRIME here later when turning to Alloy + RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label + "'")); + :}; + +//DASH end grammar --------------------------------------------------------------------- + diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt b/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt new file mode 100644 index 000000000..924616a1d --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt @@ -0,0 +1,8 @@ +import java.util.Arrays; + +import edu.mit.csail.sdg.parser.CompModule; +import edu.mit.csail.sdg.parser.MarkdownHandler; + +import ca.uwaterloo.watform.ast.*; +import ca.uwaterloo.watform.core.*; + diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-nonterminals.txt b/org.alloytools.alloy.dash/parser/Dash-cup-nonterminals.txt new file mode 100644 index 000000000..0910f094e --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash-cup-nonterminals.txt @@ -0,0 +1,15 @@ + + +//DASH nonterminals -------------------------------------------- + +nonterminal StateRoot; + +nonterminal Object StateItem; +nonterminal List StateItemList; + +nonterminal Object TransItem; +nonterminal List TransItemList; + + +//DASH end nonterminals ------------------------------------------ + diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt b/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt new file mode 100644 index 000000000..531514f61 --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt @@ -0,0 +1,30 @@ + + + //DASH syntax --------------------------------- + + // must match DASH terminals + + ch.put(DashSym.STATE, "state"); + ch.put(DashSym.CONC, "conc"); + ch.put(DashSym.DEF, "default"); + + ch.put(DashSym.EVENT, "event"); + ch.put(DashSym.ENV, "env"); + ch.put(DashSym.BUF, "buf"); + + ch.put(DashSym.INIT, "init"); + ch.put(DashSym.INVARIANT, "invariant"); + ch.put(DashSym.ACTION, "action"); + ch.put(DashSym.CONDITION, "condition"); + + ch.put(DashSym.TRANS, "trans"); + + ch.put(DashSym.FROM, "from"); + ch.put(DashSym.ON, "on"); + ch.put(DashSym.WHEN, "when"); + ch.put(DashSym.DO, "do"); + ch.put(DashSym.GOTO, "goto"); + ch.put(DashSym.SEND, "send"); + + //DASH end syntax ------------------------------ + diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt b/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt new file mode 100644 index 000000000..ffa42b34a --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt @@ -0,0 +1,30 @@ + + +//DASH terminals ----------------------------------- + +// must match DASH symbols + +terminal Pos STATE; +terminal Pos CONC; +terminal Pos DEF; + +terminal Pos EVENT; +terminal Pos ENV; +terminal Pos BUF; + +terminal Pos INIT; +terminal Pos INVARIANT; +terminal Pos ACTION; +terminal Pos CONDITION; + +terminal Pos TRANS; + +terminal Pos FROM; +terminal Pos ON; +terminal Pos WHEN; +terminal Pos DO; +terminal Pos GOTO; +terminal Pos SEND; + +//DASH end terminals --------------------------------- + diff --git a/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt b/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt new file mode 100644 index 000000000..e4ce2d2c5 --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt @@ -0,0 +1,27 @@ +//DASH SYNTAX ADDITIONS + +"state" { return alloy_sym(yytext(), DashSym.STATE );} +"conc" { return alloy_sym(yytext(), DashSym.CONC );} +"default" { return alloy_sym(yytext(), DashSym.DEF );} + +"event" { return alloy_sym(yytext(), DashSym.EVENT );} +"env" { return alloy_sym(yytext(), DashSym.ENV );} +"buf" { return alloy_sym(yytext(), DashSym.BUF );} + +"init" { return alloy_sym(yytext(), DashSym.INIT );} +"invariant" { return alloy_sym(yytext(), DashSym.INVARIANT );} +"action" { return alloy_sym(yytext(), DashSym.ACTION );} +"condition" { return alloy_sym(yytext(), DashSym.CONDITION );} + +"trans" { return alloy_sym(yytext(), DashSym.TRANS );} + +"from" { return alloy_sym(yytext(), DashSym.FROM );} +"on" { return alloy_sym(yytext(), DashSym.ON );} +"when" { return alloy_sym(yytext(), DashSym.WHEN );} +"do" { return alloy_sym(yytext(), DashSym.DO );} +"goto" { return alloy_sym(yytext(), DashSym.GOTO );} +"send" { return alloy_sym(yytext(), DashSym.SEND );} + + +//END DASH SYNTAX ADDITIONS + diff --git a/org.alloytools.alloy.dash/parser/Dash-lex-imports.txt b/org.alloytools.alloy.dash/parser/Dash-lex-imports.txt new file mode 100644 index 000000000..09432174f --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash-lex-imports.txt @@ -0,0 +1,2 @@ +import edu.mit.csail.sdg.parser.CompModule; + diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup new file mode 100644 index 000000000..62c6f923e --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -0,0 +1,1444 @@ +/* + * DO NOT EDIT THIS FILE + * DASH: file copied from Alloy src with replacements for Dash - see install-alloy-files.sh + */ + + +/* Alloy Analyzer 4 -- Copyright (c) 2006-2008, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Warning: this file alone is not enough to correctly parse Alloy4 since the actual + * language is not LALR(1); instead, we have to pre-process the token stream + * using DashFilter.java to rearrange/transform the token stream, and then we can + * parse the transformed token stream using this LALR(1) grammar. For more information, + * please refer to DashFilter.java + */ + +package ca.uwaterloo.watform.parser; + +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; +import java.util.Locale; +import java.util.TreeSet; +import java.util.Map; +import java.util.LinkedHashMap; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.Reader; +import java.io.IOException; +import java.io.StringReader; +import java_cup.runtime.*; +import org.alloytools.alloy.core.AlloyCore; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.ast.Attr.AttrType; +import edu.mit.csail.sdg.ast.CommandScope; +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprBadJoin; +import edu.mit.csail.sdg.ast.ExprITE; +import edu.mit.csail.sdg.ast.ExprLet; +import edu.mit.csail.sdg.ast.ExprBinary; +import edu.mit.csail.sdg.ast.ExprList; +import edu.mit.csail.sdg.ast.ExprConstant; +import edu.mit.csail.sdg.ast.ExprQt; +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Sig; +import edu.mit.csail.sdg.ast.Sig.PrimSig; +import java.util.Arrays; + +import edu.mit.csail.sdg.parser.CompModule; +import edu.mit.csail.sdg.parser.MarkdownHandler; + +import ca.uwaterloo.watform.ast.*; +import ca.uwaterloo.watform.core.*; + + +// @modified [electrum] added temporal operators to the AST (unary temporal operators +// have the same precedence as other unary operators, binary ones have the +// highest precedence); also added a trace sequence operator which has the +// lowest precedence (not actually translated into AST but expanded during +// parsing) added time scopes to commands (reused scope ranges but extended +// to open ranges); support for open ended time scopes; additional syntax +// errors: trace scope increments must be 1; trace scope must be larger than +// 0; open ended trace scopes must start at 1 + +//===========================================================================// + +parser code {: + + public DashModule dashmodule=null; + + @Override public Symbol parse() throws java.lang.Exception { + int act; // current action code + Symbol lhs_sym = null; // the Symbol/stack element returned by a reduce + short handle_size, lhs_sym_num; // information about production being reduced with + boolean logging = AlloyCore.isDebug(); + production_tab = production_table(); + action_tab = action_table(); + reduce_tab = reduce_table(); + init_actions(); + user_init(); + // start + cur_token = scan(); + stack.removeAllElements(); + stack.push(getSymbolFactory().startSymbol("START", 0, start_state())); + tos = 0; + for (_done_parsing = false; !_done_parsing; ) { + act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); + if (act > 0) { // "shift"; thus, we shift to the encoded state by pushing it on the stack + // if (logging) System.out.println("shift " + cur_token.sym); + cur_token.parse_state = act-1; + stack.push(cur_token); + tos++; + cur_token = scan(); + } else if (act<0) { // "reduce" + // if (logging) System.out.println("reduce " + ((-act)-1)); + lhs_sym = do_action((-act)-1, this, stack, tos); + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + for (int i = 0; i < handle_size; i++) { stack.pop(); tos--; } + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + lhs_sym.parse_state = act; + stack.push(lhs_sym); + tos++; + } else { // "error" + if (logging) System.out.println("error"); + syntax_error(cur_token); + done_parsing(); + } + } + return lhs_sym; + } + + public void syntax_error(Symbol x) throws Err { + Map ch = new LinkedHashMap(); + ch.put(DashSym.ARROW, "->"); + ch.put(DashSym.ANY_ARROW_SOME, "->"); + ch.put(DashSym.ANY_ARROW_ONE, "->"); + ch.put(DashSym.ANY_ARROW_LONE, "->"); + ch.put(DashSym.SOME_ARROW_ANY, "some"); + ch.put(DashSym.SOME_ARROW_SOME, "some"); + ch.put(DashSym.SOME_ARROW_ONE, "some"); + ch.put(DashSym.SOME_ARROW_LONE, "some"); + ch.put(DashSym.ONE_ARROW_ANY, "one"); + ch.put(DashSym.ONE_ARROW_SOME, "one"); + ch.put(DashSym.ONE_ARROW_ONE, "one"); + ch.put(DashSym.ONE_ARROW_LONE, "one"); + ch.put(DashSym.LONE_ARROW_ANY, "lone"); + ch.put(DashSym.LONE_ARROW_SOME, "lone"); + ch.put(DashSym.LONE_ARROW_ONE, "lone"); + ch.put(DashSym.LONE_ARROW_LONE, "lone"); + ch.put(DashSym.INTADD, "fun"); + ch.put(DashSym.INTSUB, "fun"); + ch.put(DashSym.INTMUL, "fun"); + ch.put(DashSym.INTDIV, "fun"); + ch.put(DashSym.INTREM, "fun"); + ch.put(DashSym.INTMIN, "fun"); + ch.put(DashSym.INTMAX, "fun"); + ch.put(DashSym.INTNEXT, "fun"); + ch.put(DashSym.TOTALORDER, "pred"); + ch.put(DashSym.ABSTRACT, "abstract"); + ch.put(DashSym.ALL, "all"); + ch.put(DashSym.ALL2, "all"); + ch.put(DashSym.AMPERSAND, "&"); + ch.put(DashSym.AND, "&&"); + ch.put(DashSym.AS, "as"); + ch.put(DashSym.ASSERT, "assert"); + ch.put(DashSym.AT, "@"); + ch.put(DashSym.BAR, "|"); + ch.put(DashSym.BUT, "but"); + ch.put(DashSym.CARET, "^"); + ch.put(DashSym.CHECK, "check"); + ch.put(DashSym.COLON, ":"); + ch.put(DashSym.COMMA, ", "); + ch.put(DashSym.DISJ, "disj"); + ch.put(DashSym.DOMAIN, "<:"); + ch.put(DashSym.DOT, "."); + ch.put(DashSym.ELSE, "else"); + ch.put(DashSym.ENUM, "enum"); + ch.put(DashSym.EQUALS, "="); + ch.put(DashSym.EXACTLY, "exactly"); + ch.put(DashSym.EXH, "exh"); + ch.put(DashSym.EXPECT, "expect"); + ch.put(DashSym.EXTENDS, "extends"); + ch.put(DashSym.FACT, "fact"); + ch.put(DashSym.FOR, "for"); + ch.put(DashSym.FUN, "fun"); + ch.put(DashSym.GT, ">"); + ch.put(DashSym.GTE, ">="); + ch.put(DashSym.HASH, "#"); + ch.put(DashSym.IDEN, "iden"); + ch.put(DashSym.IFF, "iff"); + ch.put(DashSym.IMPLIES, "=>"); + ch.put(DashSym.IN, "in"); + ch.put(DashSym.INT, "int"); + ch.put(DashSym.LBRACE, "{"); + ch.put(DashSym.LBRACKET, "["); + ch.put(DashSym.LET, "let"); + ch.put(DashSym.LONE2, "lone"); + ch.put(DashSym.LONE, "lone"); + ch.put(DashSym.LPAREN, "("); + ch.put(DashSym.LT, "<"); + ch.put(DashSym.LTE, "<="); + ch.put(DashSym.MINUS, "-"); + ch.put(DashSym.MODULE, "module"); + ch.put(DashSym.NO2, "no"); + ch.put(DashSym.NO, "no"); + ch.put(DashSym.NONE, "none"); + ch.put(DashSym.NOT, "!"); + ch.put(DashSym.NOTEQUALS, "!"); + ch.put(DashSym.NOTGT, "!"); + ch.put(DashSym.NOTGTE, "!"); + ch.put(DashSym.NOTIN, "!"); + ch.put(DashSym.NOTLT, "!"); + ch.put(DashSym.NOTLTE, "!"); + ch.put(DashSym.ONE2, "one"); + ch.put(DashSym.ONE, "one"); + ch.put(DashSym.OPEN, "open"); + ch.put(DashSym.OR, "||"); + ch.put(DashSym.PART, "part"); + ch.put(DashSym.PLUS, "+"); + ch.put(DashSym.PLUSPLUS, "++"); + ch.put(DashSym.PRED, "pred"); + ch.put(DashSym.PRIVATE, "private"); + ch.put(DashSym.RANGE, ":>"); + ch.put(DashSym.RBRACE, "}"); + ch.put(DashSym.RBRACKET, "]"); + ch.put(DashSym.RPAREN, ")"); + ch.put(DashSym.RUN, "run"); + ch.put(DashSym.SEQ, "seq"); + ch.put(DashSym.SET, "set"); + ch.put(DashSym.SHL, "<<"); + ch.put(DashSym.SHR, ">>>"); + ch.put(DashSym.SHA, ">>"); + ch.put(DashSym.SIG, "sig"); + ch.put(DashSym.SIGINT, "Int"); + ch.put(DashSym.SLASH, "/"); + ch.put(DashSym.SOME2, "some"); + ch.put(DashSym.SOME, "some"); + ch.put(DashSym.STAR, "*"); + ch.put(DashSym.STRING, "String"); + ch.put(DashSym.SUM2, "sum"); + ch.put(DashSym.SUM, "sum"); + ch.put(DashSym.THIS, "this"); + ch.put(DashSym.TILDE, "~"); + ch.put(DashSym.UNIV, "univ"); + ch.put(DashSym.ID, "NAME"); + ch.put(DashSym.NUMBER, "NUMBER"); + ch.put(DashSym.STR, "STRING"); + ch.put(DashSym.VAR, "var"); + ch.put(DashSym.ALWAYS, "always"); + ch.put(DashSym.EVENTUALLY, "eventually"); + ch.put(DashSym.AFTER, "after"); + ch.put(DashSym.BEFORE, "before"); + ch.put(DashSym.HISTORICALLY, "historically"); + ch.put(DashSym.ONCE, "once"); + ch.put(DashSym.RELEASES, "releases"); + ch.put(DashSym.UNTIL, "until"); + ch.put(DashSym.SINCE, "since"); + ch.put(DashSym.TRIGGERED, "triggered"); + ch.put(DashSym.TRCSEQ, ";"); + ch.put(DashSym.PRIME, "'"); + ch.put(DashSym.TIME, "steps"); + + + //DASH syntax --------------------------------- + + // must match DASH terminals + + ch.put(DashSym.STATE, "state"); + ch.put(DashSym.CONC, "conc"); + ch.put(DashSym.DEF, "default"); + + ch.put(DashSym.EVENT, "event"); + ch.put(DashSym.ENV, "env"); + ch.put(DashSym.BUF, "buf"); + + ch.put(DashSym.INIT, "init"); + ch.put(DashSym.INVARIANT, "invariant"); + ch.put(DashSym.ACTION, "action"); + ch.put(DashSym.CONDITION, "condition"); + + ch.put(DashSym.TRANS, "trans"); + + ch.put(DashSym.FROM, "from"); + ch.put(DashSym.ON, "on"); + ch.put(DashSym.WHEN, "when"); + ch.put(DashSym.DO, "do"); + ch.put(DashSym.GOTO, "goto"); + ch.put(DashSym.SEND, "send"); + + //DASH end syntax ------------------------------ + + TreeSet list = new TreeSet(); + Pos p=Pos.UNKNOWN; + if (x!=null && x.value instanceof Pos) p=(Pos)(x.value); + else if (x!=null && x.value instanceof Expr) p=((Expr)(x.value)).pos; + else if (x!=null) p=x.pos; + if (!stack.empty()) for(Map.Entry e:ch.entrySet()) { + int key=e.getKey(), act=get_action(((Symbol)stack.peek()).parse_state, key); + if (act==0) continue; + try { + if (act>0 || alloy_confirm(key)) list.add(e.getValue()); + } catch(Throwable ex) { + // If the parser is really really confused, alloy_confirm() could fail with array out-of-bound exception, etc. + } + } + String result="There are "+list.size()+" possible tokens that can appear here:\n"; + for(String item:list) result=result+item+" "; + throw new ErrorSyntax(p, (list.size()!=0)?result:""); + } + + private boolean alloy_confirm(int key) { + int state = ((Symbol)stack.peek()).parse_state; + Stack newstack=new Stack(); for(Object x:stack) newstack.push(x); + while(true) { + int act = get_action(state, key); + if (act>0) return true; + if (act==0) return false; + int lhs_sym_num = production_tab[(-act)-1][0]; + int handle_size = production_tab[(-act)-1][1]; + for (int i = 0; i < handle_size; i++) { if (newstack.empty()) return false; newstack.pop(); } + if (newstack.empty()) return false; + if (newstack.peek() instanceof Symbol) state=((Symbol)newstack.peek()).parse_state; + state=get_reduce(state, lhs_sym_num); + newstack.push(null); + } + } + + static final String INT_LIB_NAME = "util" + java.io.File.separator + "integer"; + static DashModule alloy_parseStream (List seenDollar, + Map loaded, Map fc, CompModule root, + int lineOffset, String filename, String prefix, int initialResolutionMode) throws Err, FileNotFoundException, IOException { + Reader isr=null; + try { + if (root==null && prefix.length()!=0) throw new ErrorFatal("Internal error (parse subfile with root==null)"); + if (root!=null && prefix.length()==0) throw new ErrorFatal("Internal error (parse topfile with root!=null)"); + DashModule u = new DashModule(root, filename, prefix); + if (!filename.endsWith(INT_LIB_NAME + ".als")) + u.addOpen(null, null, ExprVar.make(null, INT_LIB_NAME), null, ExprVar.make(null, "integer")); + u.resolution = initialResolutionMode; + String content = fc!=null ? fc.get(filename) : null; + if (content==null && loaded!=null) content = loaded.get(filename); + if (content==null) content = Util.readAll(filename); + if (loaded!=null) loaded.put(filename,content); + if (content.startsWith("---") || filename.toLowerCase(Locale.ROOT).endsWith(".md")) content = MarkdownHandler.strip(content); + content = Util.convertLineBreak(content); + isr = new StringReader(content); + DashFilter s = new DashFilter(u, seenDollar, filename, lineOffset, new BufferedReader(isr)); + DashParser p = new DashParser(s); + p.dashmodule=u; + try {p.parse();} catch(Throwable ex) {if (ex instanceof Err) throw (Err)ex; throw new ErrorFatal("Parser Exception", ex);} + return u; + } finally { + Util.close(isr); + } + } + +:}; + +action code {: + /** This function is needed to handle a difficult parsing ambiguity. + * + *

    + * "some EXPR", "one EXPR", and "lone EXPR" + * can be either formulas (saying the EXPR has at least 1, exactly 1, or at most 1 tuple), + * or multiplicity constraints (saying something else has this multiplicity). + * + *

    + * So we let the parser generate the former by default. + * And whenever we construct a Decl "x: y" object, + * or an binary expression "x in y", or a function return type, + * we call this method on y to convert it into a multiplicity constraint. + * + *

    + * This is safe, because in all 3 cases, a formula would be illegal. + * So the first form is always wrong. + * + *

    + * And this is sufficient, because those are the only 3 places + * where a mulitplicity constraint is allowed to appear. + * + * @return a newly formed multiplciity constraint (if this.op==SOME or LONE or ONE), + * otherwise it just returns the original node. + */ + private Expr mult(Expr x) throws Err { + if (x instanceof ExprUnary) { + ExprUnary y=(ExprUnary)x; + if (y.op==ExprUnary.Op.SOME) return ExprUnary.Op.SOMEOF.make(y.pos, y.sub); + if (y.op==ExprUnary.Op.LONE) return ExprUnary.Op.LONEOF.make(y.pos, y.sub); + if (y.op==ExprUnary.Op.ONE) return ExprUnary.Op.ONEOF.make(y.pos, y.sub); + } + return x; + } + private void nod(ExprVar name) throws Err { + if (name.label.indexOf('$')>=0) throw new ErrorSyntax(name.pos, "The name cannot contain the '$' symbol."); + } + private void nod(List names) throws Err { + if (names!=null) for(ExprVar n:names) if (n!=null && n.label.indexOf('$')>=0) throw new ErrorSyntax(n.pos, "The name cannot contain the '$' symbol."); + } + private void c(boolean follow, ExprVar o, ExprVar x, ExprVar n, Expr e, List s, ExprConstant c) throws Err { + if (n!=null) nod(n); + int bitwidth=(-1), maxseq=(-1), overall=(-1), expects=(c==null ? -1 : c.num); + int maxtime = (-1), mintime = (-1); + Pos p = o.pos.merge(n!=null ? n.span() : e.span()); + for(int i=s.size()-1; i>=0; i--) { + Sig j=s.get(i).sig; int k=s.get(i).startingScope; + p=p.merge(j.pos); + if (j.label.equals("univ")) { overall=k; s.remove(i); continue; } + if (j.label.equals("int")) { if (bitwidth>=0) throw new ErrorSyntax(j.pos, "The bitwidth cannot be specified more than once."); bitwidth=k; s.remove(i); continue; } + if (j.label.equals("seq")) { if (maxseq>=0) throw new ErrorSyntax(j.pos, "The maximum sequence length cannot be specified more than once."); maxseq=k; s.remove(i); continue; } + // [electrum] process time scopes + if (j.label.equals("steps")) { + if (s.get(i).endingScope == Integer.MAX_VALUE && s.get(i).startingScope != 1) throw new ErrorSyntax(j.pos, "Unbounded time scope must start at 1."); + if (s.get(i).increment != 1) throw new ErrorSyntax(j.pos, "Step scopes must be incremented by 1."); + if (k<1) throw new ErrorSyntax(j.pos, "Trace solutions must contain at least one step."); + if (maxtime>=0) throw new ErrorSyntax(j.pos, "Steps scope cannot be specified more than once."); + maxtime=k; + if (s.get(i).isExact) mintime = k; + else if (s.get(i).endingScope != s.get(i).startingScope) { + maxtime = s.get(i).endingScope; mintime = s.get(i).startingScope; } + s.remove(i); continue; + } + } + if (n!=null) + parser.dashmodule.addCommand(follow, p, n, o, overall, bitwidth, maxseq, mintime, maxtime, expects, s, x); + else + parser.dashmodule.addCommand(follow, p, e, o, overall, bitwidth, maxseq, mintime, maxtime, expects, s, x); + } + private Expr t(Pos pos, Pos oldClosing, Expr left, Expr right, Pos close) throws Err { + if (right instanceof ExprVar) { + String n = ((ExprVar)right).label; + if (n.equals("int")) return ExprUnary.Op.CAST2INT.make(pos, left); + if (n.equals("disj")) return ExprList.makeDISJOINT(pos, close, Util.asList(left)); + if (n.equals("pred/totalOrder")) return ExprList.makeTOTALORDER(pos, close, Util.asList(left)); + } + else if (right instanceof ExprList) { + return ((ExprList)right).addArg(left); + } + return ExprBadJoin.make(pos, oldClosing, left, right); + } +:}; + +//===========================================================================// + +terminal Pos ARROW; // -> +terminal Pos ANY_ARROW_SOME; // ->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ANY_ARROW_ONE; // ->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ANY_ARROW_LONE; // ->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_ANY; // some-> // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_SOME; // some->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_ONE; // some->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos SOME_ARROW_LONE; // some->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_ANY; // one-> // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_SOME; // one->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_ONE; // one->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos ONE_ARROW_LONE; // one->lone // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_ANY; // lone->any // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_SOME; // lone->some // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_ONE; // lone->one // The filter allows whitespace/comment in these 15 "*->*" tokens +terminal Pos LONE_ARROW_LONE; // lone->lone // The filter allows whitespace/comment in these 15 "*->*" tokens + +terminal Pos INTADD; +terminal Pos INTSUB; +terminal Pos INTMUL; +terminal Pos INTDIV; +terminal Pos INTREM; +terminal Pos INTMIN; +terminal Pos INTMAX; +terminal Pos INTNEXT; +terminal Pos TOTALORDER; + +terminal Pos ABSTRACT; // abstract +terminal Pos ALL; // all // The filter enables us to disambiguate +terminal Pos ALL2; // all // The filter enables us to disambiguate +terminal Pos AMPERSAND; // & +terminal Pos AND; // && and +terminal Pos AS; // as +terminal Pos ASSERT; // assert +terminal Pos AT; // @ +terminal Pos BAR; // | +terminal Pos BUT; // but +terminal Pos CARET; // ^ +terminal Pos CHECK; // check +terminal Pos COLON; // : +terminal Pos COMMA; // , +terminal Pos DISJ; // disj disjoint +terminal Pos DOMAIN; // <: +terminal Pos DOT; // . +terminal Pos ELSE; // else +terminal Pos ENUM; // enum +terminal Pos EQUALS; // = == +terminal Pos EXACTLY; // exactly +terminal Pos EXH; // exh exhaustive +terminal Pos EXPECT; // expect +terminal Pos EXTENDS; // extends +terminal Pos FACT; // fact +terminal Pos FOR; // for +terminal Pos FUN; // fun +terminal Pos GT; // > +terminal Pos GTE; // >= +terminal Pos HASH; // # +terminal Pos IDEN; // iden +terminal Pos IFF; // <=> iff +terminal Pos IMPLIES; // => implies +terminal Pos IN; // in +terminal Pos INT; // int +terminal Pos LBRACE; // { +terminal Pos LBRACKET; // [ +terminal Pos LET; // let +terminal Pos LONE2; // lone // The filter enables us to disambiguate +terminal Pos LONE; // lone // The filter enables us to disambiguate +terminal Pos LPAREN; // ( +terminal Pos LT; // < +terminal Pos LTE; // <= =< +terminal Pos MINUS; // - +terminal Pos MODULE; // module +terminal Pos NO2; // no // The filter enables us to disambiguate +terminal Pos NO; // no // The filter enables us to disambiguate +terminal Pos NONE; // none +terminal Pos NOT; // ! not +terminal Pos NOTEQUALS; // != not= // The filter allows whitespace/comment in between +terminal Pos NOTGT; // !> not> // The filter allows whitespace/comment in between +terminal Pos NOTGTE; // !>= not>= // The filter allows whitespace/comment in between +terminal Pos NOTIN; // !in notin // The filter allows whitespace/comment in between +terminal Pos NOTLT; // !< not< // The filter allows whitespace/comment in between +terminal Pos NOTLTE; // !=< not=< // The filter allows whitespace/comment in between +terminal Pos ONE2; // one // The filter enables us to disambiguate +terminal Pos ONE; // one // The filter enables us to disambiguate +terminal Pos OPEN; // open +terminal Pos OR; // || or +terminal Pos PART; // part partition +terminal Pos PLUS; // + +terminal Pos PLUSPLUS; // ++ +terminal Pos PRED; // pred +terminal Pos PRIVATE; // private +terminal Pos RANGE; // :> +terminal Pos RBRACE; // } +terminal Pos RBRACKET; // ] +terminal Pos RPAREN; // ) +terminal Pos RUN; // run +terminal Pos SEQ; // seq +terminal Pos SET; // set +terminal Pos SHL; // << +terminal Pos SHR; // >>> +terminal Pos SHA; // >> +terminal Pos SIG; // sig +terminal Pos SIGINT; // Int +terminal Pos SLASH; // / +terminal Pos SOME2; // some // The filter enables us to disambiguate +terminal Pos SOME; // some // The filter enables us to disambiguate +terminal Pos STAR; // * +terminal Pos STRING; // String +terminal Pos SUM2; // sum // The filter enables us to disambiguate +terminal Pos SUM; // sum // The filter enables us to disambiguate +terminal Pos THIS; // this +terminal Pos TILDE; // ~ +terminal Pos UNIV; // univ + +terminal Pos VAR; // var +terminal Pos ALWAYS; // always +terminal Pos EVENTUALLY; // eventually +terminal Pos AFTER; // after +terminal Pos ONCE; // once +terminal Pos HISTORICALLY; // historically +terminal Pos BEFORE; // before +terminal Pos RELEASES; // releases +terminal Pos UNTIL; // until +terminal Pos SINCE; // since +terminal Pos TRIGGERED; // triggered +terminal Pos TRCSEQ; // trace seq +terminal Pos TIME; // steps +terminal Pos PRIME; // ' + +terminal ExprVar ID; + +terminal ExprConstant NUMBER, STR; + + +//DASH terminals ----------------------------------- + +// must match DASH symbols + +terminal Pos STATE; +terminal Pos CONC; +terminal Pos DEF; + +terminal Pos EVENT; +terminal Pos ENV; +terminal Pos BUF; + +terminal Pos INIT; +terminal Pos INVARIANT; +terminal Pos ACTION; +terminal Pos CONDITION; + +terminal Pos TRANS; + +terminal Pos FROM; +terminal Pos ON; +terminal Pos WHEN; +terminal Pos DO; +terminal Pos GOTO; +terminal Pos SEND; + +//DASH end terminals --------------------------------- + + +//===========================================================================// + +nonterminal Expr AndExprA; +nonterminal Expr AndExprB; +nonterminal Expr BaseExpr; +nonterminal Expr Bind; +nonterminal Expr BracketExprA; +nonterminal Expr BracketExprB; +nonterminal Expr CompareExprA; +nonterminal Expr CompareExprB; +nonterminal Command; +nonterminal ExprVar CommandPrefix; +nonterminal Decl Decla; +nonterminal Decl Declb; +nonterminal List Declp; +nonterminal List Decls; +nonterminal List Declz; +nonterminal Expr DomainExprA; +nonterminal Expr DomainExprB; +nonterminal Expr DotExprA; +nonterminal Expr DotExprB; +nonterminal Expr EquivExprA; +nonterminal Expr EquivExprB; +nonterminal ExprConstant Expects; +nonterminal Expr Expr; +nonterminal Expr Super; +nonterminal Expr SuperOpt; +nonterminal Expr SuperP; +nonterminal Expr SuperOrBar; +nonterminal List Exprs; +nonterminal List Exprp; +nonterminal Function; +nonterminal Expr ImpliesExprA; +nonterminal Expr ImpliesExprB; +nonterminal Expr ImpliesExprCloseA; +nonterminal Expr ImpliesExprCloseB; +nonterminal Expr ImpliesExprOpenA; +nonterminal Expr ImpliesExprOpenB; +nonterminal Expr IntersectExprA; +nonterminal Expr IntersectExprB; +nonterminal Expr Let; +nonterminal Macro; +nonterminal Expr MacroBody; +nonterminal ExprVar Name; +nonterminal ExprVar NameHelper; +nonterminal List Names; +nonterminal List Namex; +nonterminal Expr UnaryExprA; +nonterminal Expr UnaryExprB; +nonterminal Expr NumUnopExprA; +nonterminal Expr NumUnopExprB; +nonterminal Expr OrExprA; +nonterminal Expr OrExprB; +nonterminal Expr OverrideExprA; +nonterminal Expr OverrideExprB; +nonterminal Predicate; +nonterminal Expr RangeExprA; +nonterminal Expr RangeExprB; +nonterminal Pair RelOp; +nonterminal Expr RelationExprA; +nonterminal Expr RelationExprB; +nonterminal List Scope; +nonterminal Sig; +nonterminal List SigIn; +nonterminal List SigQual; +nonterminal List SigQuals; +nonterminal ExprVar SigRef; +nonterminal List SigRefp; +nonterminal List SigRefs; +nonterminal List SigRefu; +nonterminal File; +nonterminal Spec; +nonterminal CommandScope TypeNumber; +nonterminal CommandScope Typescope; +nonterminal List Typescopes; +nonterminal Expr ShiftExprA; +nonterminal Expr ShiftExprB; +nonterminal Expr MulExprA; +nonterminal Expr MulExprB; +nonterminal Expr UnionDiffExprA; +nonterminal Expr UnionDiffExprB; +nonterminal Expr UnopExprA; +nonterminal Expr UnopExprB; +nonterminal Pos Vis; +nonterminal Expr TempBinaryA; +nonterminal Expr TempBinaryB; +nonterminal Expr ExprNoSeq; + + +//DASH nonterminals -------------------------------------------- + +nonterminal StateRoot; + +nonterminal Object StateItem; +nonterminal List StateItemList; + +nonterminal Object TransItem; +nonterminal List TransItemList; + + +//DASH end nonterminals ------------------------------------------ + + +precedence right TRCSEQ; +precedence nonassoc BAR; +precedence left OR; +precedence left IFF; +precedence right IMPLIES; +precedence left AND; +precedence nonassoc RELEASES, SINCE, UNTIL, TRIGGERED; +precedence nonassoc AFTER, ALWAYS, EVENTUALLY, BEFORE, HISTORICALLY, ONCE; +precedence nonassoc NOT; +precedence nonassoc EQUALS, NOTEQUALS, IN, NOTIN; +precedence nonassoc NO, SOME, LONE, ONE; +precedence nonassoc PRIME; +precedence nonassoc TILDE, CARET, STAR; + +//===========================================================================// + +File ::= Spec {: parser.dashmodule.doneParsing(); :}; + +Spec ::= Spec MODULE:o Name:n {: nod(n); parser.dashmodule.addModelName(o.merge(n.pos) , n.label , new ArrayList()); :}; +Spec ::= Spec MODULE:o Name:n LBRACKET Namex:b RBRACKET:r {: nod(n); nod(b); parser.dashmodule.addModelName(o.merge(r) , n.label , b ); :}; +Spec ::= Spec Vis:p OPEN:o Name:a {: nod(a); parser.dashmodule.addOpen(o.merge(a.pos), p, a, null, null); :}; +Spec ::= Spec Vis:p OPEN:o Name:a AS Name:c {: nod(a); nod(c); parser.dashmodule.addOpen(o.merge(c.pos), p, a, null, c); :}; +Spec ::= Spec Vis:p OPEN:o Name:a LBRACKET SigRefs:b RBRACKET:c {: nod(a); parser.dashmodule.addOpen(o.merge(c), p, a, b, null); :}; +Spec ::= Spec Vis:p OPEN:o Name:a LBRACKET SigRefs:b RBRACKET AS Name:c {: nod(a); nod(c); parser.dashmodule.addOpen(o.merge(c.pos), p, a, b, c); :}; +Spec ::= Spec Vis:p ENUM:o Name:a LBRACE Names:n RBRACE:c {: nod(a); parser.dashmodule.addEnum(o.merge(c), p, a, n, c); :}; +Spec ::= Spec Vis:p ENUM:o Name:a LBRACE RBRACE:c {: nod(a); parser.dashmodule.addEnum(o.merge(c), p, a, null, c); :}; +Spec ::= Spec FACT:o Super:e {: parser.dashmodule.addFact (o , "" , e); :}; +Spec ::= Spec FACT:o Name:n Super:e {: nod(n); parser.dashmodule.addFact (o , n.label , e); :}; +Spec ::= Spec FACT:o STR:n Super:e {: parser.dashmodule.addFact (o , n.string , e); :}; +Spec ::= Spec ASSERT:o Super:e {: parser.dashmodule.addAssertion (o , null , "" , e); :}; +Spec ::= Spec ASSERT:o Name:n Super:e {: nod(n); parser.dashmodule.addAssertion (o , n.pos, n.label , e); :}; +Spec ::= Spec ASSERT:o STR:n Super:e {: parser.dashmodule.addAssertion (o , null, n.string , e); :}; +Spec ::= Spec Sig ; +Spec ::= Spec Function ; +Spec ::= Spec Predicate ; +Spec ::= Spec Macro ; +Spec ::= Spec Command ; +Spec ::= ; + +CommandPrefix ::= CHECK:c {: RESULT = ExprVar.make(c, "c"); :}; +CommandPrefix ::= RUN:r {: RESULT = ExprVar.make(r, "r"); :}; + +Command ::= CommandPrefix:o Name:x Super:e Scope:s Expects:c {: c(false,o,x ,null,e ,s,c); :}; +Command ::= CommandPrefix:o Super:e Scope:s Expects:c {: c(false,o,null,null,e ,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:x Super:e Scope:s Expects:c {: c(true ,o,x ,null,e ,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Super:e Scope:s Expects:c {: c(true ,o,null,null,e ,s,c); :}; +Command ::= CommandPrefix:o Name:x Name:n Scope:s Expects:c {: c(false,o,x ,n ,null,s,c); :}; +Command ::= CommandPrefix:o Name:n Scope:s Expects:c {: c(false,o,null,n ,null,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:x Name:n Scope:s Expects:c {: c(true ,o,x ,n ,null,s,c); :}; +Command ::= Command IMPLIES CommandPrefix:o Name:n Scope:s Expects:c {: c(true ,o,null,n ,null,s,c); :}; + +Expects ::= {: RESULT=null; :}; +Expects ::= EXPECT NUMBER:a {: RESULT=a; :}; + +Scope ::= FOR NUMBER:a {: RESULT=new ArrayList(); RESULT.add(new CommandScope(a.pos, Pos.UNKNOWN, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; +Scope ::= FOR NUMBER:a BUT Typescopes:b {: RESULT=b; b.add(new CommandScope(a.pos, Pos.UNKNOWN, new PrimSig("univ", AttrType.WHERE.make(a.pos)), true, a.num, a.num, 1)); :}; +Scope ::= FOR Typescopes:b {: RESULT=b; :}; +Scope ::= {: RESULT=new ArrayList(); :}; + +Typescopes ::= Typescope:a {: RESULT=new ArrayList(); RESULT.add(a); :}; +Typescopes ::= Typescopes:a COMMA Typescope:b {: RESULT=a; a.add(b); :}; + +Typescope ::= TypeNumber:a Name:b {: + nod(b); + RESULT = new CommandScope(a.pos.merge(b.pos), b.pos, new PrimSig(b.label, AttrType.WHERE.make(a.pos.merge(b.pos))), a.isExact, a.startingScope, a.endingScope, a.increment); +:}; + +//[AM]: INT -> SIGINT +Typescope ::= TypeNumber:a SIGINT:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); + RESULT = new CommandScope(p, b, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:a INT:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"Int\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the integer bitwidth must be exact."); + RESULT = new CommandScope(p, b, new PrimSig("int", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:a SEQ:b {: + Pos p = a.pos.merge(b); + if (a.endingScope>a.startingScope) throw new ErrorSyntax(p, "Cannot specify a growing scope for \"seq\""); + if (a.isExact) throw new ErrorSyntax(p, "The exactly keyword is redundant here since the number of sequence index has to be exact."); + RESULT = new CommandScope(p, b, new PrimSig("seq", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.startingScope, 1); +:}; + +Typescope ::= TypeNumber:e UNIV:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on univ."); :}; + +Typescope ::= TypeNumber:a STRING:b {: RESULT = new CommandScope(a.pos.merge(b), b, new PrimSig("String", AttrType.WHERE.make(a.pos.merge(b))), a.isExact, a.startingScope, a.endingScope, a.increment); :}; + +// [electrum] scope on Time +Typescope ::= TypeNumber:a TIME:b {: + Pos p = a.pos.merge(b); + RESULT = new CommandScope(p, Pos.UNKNOWN, new PrimSig("steps", AttrType.WHERE.make(p)), a.isExact, a.startingScope, a.endingScope, a.increment); +:}; + +//[AM] Typescope ::= TypeNumber:e SIGINT:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You can no longer set a scope on Int; the number of Int atoms is always exactly equal to 2^(integer bitwidth).\n"); :}; + +Typescope ::= TypeNumber:e NONE:f {: if (1==1) throw new ErrorSyntax(e.pos.merge(f), "You cannot set a scope on none."); :}; + +// [electrum] distinguish between "n" and "n..n", the latter become exact; open ended scopes "n.." +TypeNumber ::= EXACTLY:e NUMBER:a {: RESULT = new CommandScope( e.merge(a.pos), Pos.UNKNOWN, Sig.NONE, true, a.num, a.num, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(b.pos), Pos.UNKNOWN, Sig.NONE, true, a.num, b.num, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e , Pos.UNKNOWN, Sig.NONE, true, a.num, Integer.MAX_VALUE, 1 ); :}; +TypeNumber ::= EXACTLY:e NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Pos.UNKNOWN, Sig.NONE, true, a.num, b.num, i.num); :}; +TypeNumber ::= EXACTLY:e NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope( e.merge(i.pos), Pos.UNKNOWN, Sig.NONE, true, a.num, Integer.MAX_VALUE, i.num); :}; +TypeNumber ::= NUMBER:a {: RESULT = new CommandScope(a.pos , Pos.UNKNOWN, Sig.NONE, false, a.num, a.num, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT NUMBER:b {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(b.pos), Pos.UNKNOWN, Sig.NONE, a.num == b.num, a.num, b.num, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos , Pos.UNKNOWN, Sig.NONE, false, a.num, Integer.MAX_VALUE, 1 ); :}; +TypeNumber ::= NUMBER:a DOT DOT NUMBER:b COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Pos.UNKNOWN, Sig.NONE, a.num == b.num, a.num, b.num, i.num); :}; +TypeNumber ::= NUMBER:a COLON NUMBER:i {: if (!Version.experimental) throw new ErrorSyntax(a.pos, "Syntax error here."); RESULT = new CommandScope(a.pos.merge(i.pos), Pos.UNKNOWN, Sig.NONE, false, a.num, Integer.MAX_VALUE, i.num); :}; + +Macro ::= Vis:p LET:o Name:n LPAREN Names:d RPAREN MacroBody:v {: nod(n); parser.dashmodule.addMacro(o.merge(v.span()), p, n.pos, n.label, d , v); :}; +Macro ::= Vis:p LET:o Name:n LPAREN RPAREN MacroBody:v {: nod(n); parser.dashmodule.addMacro(o.merge(v.span()), p, n.pos, n.label, null , v); :}; +Macro ::= Vis:p LET:o Name:n LBRACKET Names:d RBRACKET MacroBody:v {: nod(n); parser.dashmodule.addMacro(o.merge(v.span()), p, n.pos, n.label, d , v); :}; +Macro ::= Vis:p LET:o Name:n LBRACKET RBRACKET MacroBody:v {: nod(n); parser.dashmodule.addMacro(o.merge(v.span()), p, n.pos, n.label, null , v); :}; +Macro ::= Vis:p LET:o Name:n MacroBody:v {: nod(n); parser.dashmodule.addMacro(o.merge(v.span()), p, n.pos, n.label, null , v); :}; + +MacroBody ::= Super:a {: RESULT=a; :}; +MacroBody ::= EQUALS Expr:a {: RESULT=a; :}; + +Function ::= Vis:p FUN:o Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, null, d , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, null, d , mult(r), v); :}; +Function ::= Vis:p FUN:o Name:n COLON Expr:r Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, null, null , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN COLON Expr:r Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, f , d , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET COLON Expr:r Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, f , d , mult(r), v); :}; +Function ::= Vis:p FUN:o SigRef:f DOT Name:n COLON Expr:r Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, f , null , mult(r), v); :}; + +Predicate ::= Vis:p PRED:o Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, null, d , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, null, d , null, v); :}; +Predicate ::= Vis:p PRED:o Name:n Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, null, null , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LPAREN Decls:d RPAREN Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, f , d , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n LBRACKET Decls:d RBRACKET Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, f , d , null, v); :}; +Predicate ::= Vis:p PRED:o SigRef:f DOT Name:n Super:v {: nod(n); parser.dashmodule.addFunc(o.merge(v.span()), p, n, f , null , null, v); :}; + +Vis ::= {: RESULT=null; :}; +Vis ::= PRIVATE:p {: RESULT=p; :}; + +Sig ::= SigQuals:a Names:b SigIn:c LBRACE Decls:d RBRACE:o SuperOpt:e + {: + if (e==null) e = ExprConstant.Op.TRUE.make(o, 0); + ExprVar cc = (c!=null && c.size()>0) ? c.remove(c.size()-1) : null; + for(ExprVar bb:b) { + parser.dashmodule.addSig(bb.pos, bb.label, cc, c, d, e, + AttrType.WHERE .makenull(bb.pos.merge(e==null ? o : e.span())), + AttrType.ABSTRACT.makenull(a.get(0)), + AttrType.LONE .makenull(a.get(1)), + AttrType.ONE .makenull(a.get(2)), + AttrType.SOME .makenull(a.get(3)), + AttrType.PRIVATE .makenull(a.get(4)), + AttrType.VARIABLE.makenull(a.get(5))); + } + :}; + +// [electrum] additional attribute for variable sigs +SigQual ::= ABSTRACT:x {: RESULT=new ArrayList(6); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= LONE:x {: RESULT=new ArrayList(6); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= ONE:x {: RESULT=new ArrayList(6); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= SOME:x {: RESULT=new ArrayList(6); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); RESULT.add(null); :}; +SigQual ::= PRIVATE:x {: RESULT=new ArrayList(6); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); RESULT.add(null); :}; +SigQual ::= VAR:x {: RESULT=new ArrayList(6); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(x); :}; + +SigQuals ::= SIG {: RESULT=new ArrayList(6); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); RESULT.add(null); :}; +SigQuals ::= SigQual:a SigQuals:b {: RESULT=a; for(int i=0;i<6;i++) if (a.get(i)==null) a.set(i,b.get(i)); else if (b.get(i)!=null) throw new ErrorSyntax(b.get(i), "The same qualifier cannot be specified more than once for the same sig."); :}; + +SigIn ::= EXTENDS:a SigRef:x {: RESULT=new ArrayList(2); RESULT.add(x); RESULT.add(ExprVar.make(a, "extends")); :}; +SigIn ::= IN:a SigRefu:x {: RESULT=x; x.add(ExprVar.make(a,"in")); :}; +SigIn ::= EQUALS:a SigRefu:x {: RESULT=x; x.add(ExprVar.make(a,"=")); :}; +SigIn ::= {: RESULT=null; :}; + +SigRef ::= Name:x {: RESULT=x; :}; +SigRef ::= UNIV:x {: RESULT=ExprVar.make(x, "univ"); :}; +SigRef ::= STRING:x {: RESULT=ExprVar.make(x, "String"); :}; +SigRef ::= TIME:x {: RESULT=ExprVar.make(x, "steps"); :}; +SigRef ::= SIGINT:x {: RESULT=ExprVar.make(x, "Int"); :}; +SigRef ::= SEQ:a SLASH SIGINT:b {: RESULT=ExprVar.make(a.merge(b), "seq/Int"); :}; +SigRef ::= NONE:x {: RESULT=ExprVar.make(x, "none"); :}; + +SigRefs ::= {: RESULT=new ArrayList(); :}; +SigRefs ::= SigRefp:x {: RESULT=x; :}; + +SigRefp ::= SigRef:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +SigRefp ::= SigRefp:a COMMA SigRef:b {: a.add(b); RESULT=a; :}; + +SigRefu ::= SigRef:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +SigRefu ::= SigRefu:a PLUS SigRef:b {: a.add(b); RESULT=a; :}; + +Name ::= NameHelper:x {: RESULT=x; :}; +Name ::= THIS:a SLASH NameHelper:b {: RESULT=ExprVar.make(a.merge(b.pos), "this/"+b.label); :}; +Name ::= SEQ:a SLASH NameHelper:b {: RESULT=ExprVar.make(a.merge(b.pos), "seq/"+b.label); :}; + +NameHelper ::= ID:x {: RESULT=x; :}; +NameHelper ::= NameHelper:a SLASH ID:b {: RESULT=ExprVar.make(a.pos.merge(b.pos), a.label+"/"+b.label); :}; + +Names ::= Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(x); :}; +Names ::= Names:a COMMA Name:b {: nod(b); a.add(b); RESULT=a; :}; + +Namex ::= Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(x); :}; +Namex ::= EXACTLY Name:x {: nod(x); RESULT=new ArrayList(); RESULT.add(null); RESULT.add(x); :}; +Namex ::= Namex:a COMMA Name:b {: nod(b); a.add(b); RESULT=a; :}; +Namex ::= Namex:a COMMA EXACTLY Name:b {: nod(b); a.add(null); a.add(b); RESULT=a; :}; + +// [electrum] additional parameter for variable declarations (for fields) +Decla ::= PART:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Decla ::= EXH:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Decla ::= DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(null, k, null, null, a, mult(b)); :}; +Decla ::= PRIVATE:p DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(p, k, null, null, a, mult(b)); :}; +Decla ::= PRIVATE:p Names:a COLON Expr:b {: RESULT=new Decl(p, null, null, null, a, mult(b)); :}; +Decla ::= Names:a COLON Expr:b {: RESULT=new Decl(null, null, null, null, a, mult(b)); :}; + +Decla ::= VAR:v DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(null, k, null, v, a, mult(b)); :}; +Decla ::= VAR:v PRIVATE:p DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(p, k, null, v, a, mult(b)); :}; +Decla ::= VAR:v PRIVATE:p Names:a COLON Expr:b {: RESULT=new Decl(p, null, null, v, a, mult(b)); :}; +Decla ::= VAR:v Names:a COLON Expr:b {: RESULT=new Decl(null, null, null, v, a, mult(b)); :}; + +Decla ::= PART:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Decla ::= EXH:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Decla ::= DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, k, d, null, a, mult(b)); :}; +Decla ::= PRIVATE:p DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, k, d, null, a, mult(b)); :}; +Decla ::= PRIVATE:p Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, null, d, null, a, mult(b)); :}; +Decla ::= Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, null, d, null, a, mult(b)); :}; + +Decla ::= VAR:v DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, k, d, v, a, mult(b)); :}; +Decla ::= VAR:v PRIVATE:p DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, k, d, v, a, mult(b)); :}; +Decla ::= VAR:v PRIVATE:p Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, null, d, v, a, mult(b)); :}; +Decla ::= VAR:v Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, null, d, v, a, mult(b)); :}; + +Declb ::= Decla:x {: RESULT=x; :}; + +Declb ::= PART:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Declb ::= EXH:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Declb ::= DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE:p Names:a EQUALS Expr:b {: RESULT=new Decl(p, null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; +Declb ::= Names:a EQUALS Expr:b {: RESULT=new Decl(null, null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; + +Declb ::= PART:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; +Declb ::= EXH:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; +Declb ::= DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= PRIVATE Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; +Declb ::= Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; + +Declz ::= Declz:x COMMA Decla:y {: RESULT=x; RESULT.add(y); :}; +Declz ::= Decla:y {: RESULT=new ArrayList(); RESULT.add(y); :}; + +Declp ::= Declp:x COMMA Declb:y {: RESULT=x; RESULT.add(y); :}; +Declp ::= Declb:y {: RESULT=new ArrayList(); RESULT.add(y); :}; + +Decls ::= {: RESULT=new ArrayList(); :}; +Decls ::= Declb:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +Decls ::= Declb:x COMMA Decls:y {: RESULT=y; RESULT.add(0,x); :}; +Decls ::= COMMA Decls:y {: RESULT=y; :}; + +Let ::= Name:a EQUALS:o Expr:b SuperOrBar:x {: + nod(a); + if (a.label.indexOf('/')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'/\'"); + if (a.label.indexOf('@')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'@\'"); + RESULT = ExprLet.make(o, ExprVar.make(a.pos, a.label), b, x); +:}; + +Let ::= Name:a EQUALS:o Expr:b COMMA Let:x {: + nod(a); + if (a.label.indexOf('/')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'/\'"); + if (a.label.indexOf('@')>=0) throw new ErrorSyntax(a.pos, "Let variable name cannot contain \'@\'"); + RESULT = ExprLet.make(o, ExprVar.make(a.pos, a.label), b, x); +:}; + +// [electrum] temporal seq expressions have the lowest precedence +SuperOpt ::= {: RESULT=null; :}; +SuperOpt ::= Super:x {: RESULT=x; :}; +Super ::= LBRACE:a SuperP:x RBRACE:b {: RESULT=ExprUnary.Op.NOOP.make(a.merge(b), x); :}; +Super ::= LBRACE:a RBRACE:b {: RESULT=ExprConstant.Op.TRUE.make(a.merge(b), 0); :}; +SuperP ::= Expr:a {: RESULT=a; :}; +SuperP ::= SuperP:a Expr:b {: RESULT=ExprBinary.Op.AND.make(null, null, a, b); :}; +SuperP ::= Expr:a TRCSEQ:o SuperP:b {: RESULT=ExprBinary.Op.AND.make(o, null, a, ExprUnary.Op.AFTER.make(o, b)); :}; + +SuperOrBar ::= BAR ExprNoSeq:x {: RESULT=x; :}; +SuperOrBar ::= Super:x {: RESULT=x; :}; +SuperOrBar ::= BAR ExprNoSeq:x TRCSEQ:o Expr:y {: RESULT=ExprBinary.Op.AND.make(o, null, x, ExprUnary.Op.AFTER.make(o, y)); :}; + +Exprs ::= {: RESULT=new ArrayList(); :}; +Exprs ::= Exprp:x {: RESULT=x; :}; +Exprp ::= Expr:x {: RESULT=new ArrayList(); RESULT.add(x); :}; +Exprp ::= Exprp:a COMMA Expr:b {: a.add(b); RESULT=a; :}; + +//============================================================================= + +Expr ::= ExprNoSeq:a {: RESULT=a; :}; +Expr ::= ExprNoSeq:a TRCSEQ:o Expr:b {: RESULT=ExprBinary.Op.AND.make(o, null, a, ExprUnary.Op.AFTER.make(o, b)); :}; + +ExprNoSeq ::= OrExprA:x {: RESULT = x; :}; +ExprNoSeq ::= OrExprB:x {: RESULT = x; :}; +ExprNoSeq ::= Bind:x {: RESULT = x; :}; +Bind ::= LET Let:x {: RESULT = x; :}; +Bind ::= ALL2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.ALL .make(o, null, a, b); :}; +Bind ::= NO2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.NO .make(o, null, a, b); :}; +Bind ::= SOME2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.SOME.make(o, null, a, b); :}; +Bind ::= LONE2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.LONE.make(o, null, a, b); :}; +Bind ::= ONE2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.ONE .make(o, null, a, b); :}; +Bind ::= SUM2:o Declp:a SuperOrBar:b {: RESULT = ExprQt.Op.SUM .make(o, null, a, b); :}; + +OrExprA ::= EquivExprA:a {: RESULT=a; :}; +OrExprA ::= OrExprB:a OR:o Bind:b {: RESULT=ExprBinary.Op.OR.make(o, null, a, b); :}; +OrExprB ::= EquivExprB:b {: RESULT=b; :}; +OrExprB ::= OrExprB:a OR:o EquivExprB:b {: RESULT=ExprBinary.Op.OR.make(o, null, a, b); :}; + +EquivExprA ::= ImpliesExprA:b {: RESULT=b; :}; +EquivExprA ::= EquivExprB:a IFF:o Bind:b {: RESULT=ExprBinary.Op.IFF.make(o, null, a, b); :}; +EquivExprB ::= ImpliesExprB:b {: RESULT=b; :}; +EquivExprB ::= EquivExprB:a IFF:o ImpliesExprB:b {: RESULT=ExprBinary.Op.IFF.make(o, null, a, b); :}; + +ImpliesExprA ::= ImpliesExprCloseA:a {: RESULT=a; :}; +ImpliesExprA ::= ImpliesExprOpenA:a {: RESULT=a; :}; +ImpliesExprCloseA ::= AndExprA:a {: RESULT=a; :}; +ImpliesExprCloseA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprCloseA:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprOpenA:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o ImpliesExprA:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +ImpliesExprCloseA ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE Bind:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenA ::= AndExprB:a IMPLIES:o Bind:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +ImpliesExprB ::= ImpliesExprCloseB:a {: RESULT=a; :}; +ImpliesExprB ::= ImpliesExprOpenB:a {: RESULT=a; :}; +ImpliesExprCloseB ::= AndExprB:a {: RESULT=a; :}; +ImpliesExprCloseB ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprCloseB:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenB ::= AndExprB:a IMPLIES:o ImpliesExprCloseB:b ELSE ImpliesExprOpenB:c {: RESULT = ExprITE.make(o,a,b,c); :}; +ImpliesExprOpenB ::= AndExprB:a IMPLIES:o ImpliesExprB:b {: RESULT = ExprBinary.Op.IMPLIES.make(o, null, a, b); :}; + +AndExprA ::= TempBinaryA:a {: RESULT=a; :}; +AndExprA ::= AndExprB:a AND:o Bind:b {: RESULT=ExprBinary.Op.AND.make(o, null, a, b); :}; +AndExprB ::= TempBinaryB:b {: RESULT=b; :}; +AndExprB ::= AndExprB:a AND:o TempBinaryB:b {: RESULT=ExprBinary.Op.AND.make(o, null, a, b); :}; + +// [electrum] binary temporal formulas, highest precedence among binary operators +TempBinaryA ::= UnaryExprA:a {: RESULT=a; :}; +TempBinaryA ::= TempBinaryB:a UNTIL:o Bind:b {: RESULT=ExprBinary.Op.UNTIL .make(o, null, a, b); :}; +TempBinaryA ::= TempBinaryB:a SINCE:o Bind:b {: RESULT=ExprBinary.Op.SINCE .make(o, null, a, b); :}; +TempBinaryA ::= TempBinaryB:a TRIGGERED:o Bind:b {: RESULT=ExprBinary.Op.TRIGGERED.make(o, null, a, b); :}; +TempBinaryA ::= TempBinaryB:a RELEASES:o Bind:b {: RESULT=ExprBinary.Op.RELEASES .make(o, null, a, b); :}; +TempBinaryB ::= UnaryExprB:b {: RESULT=b; :}; +TempBinaryB ::= TempBinaryB:a UNTIL:o UnaryExprB:b {: RESULT=ExprBinary.Op.UNTIL .make(o, null, a, b); :}; +TempBinaryB ::= TempBinaryB:a SINCE:o UnaryExprB:b {: RESULT=ExprBinary.Op.SINCE .make(o, null, a, b); :}; +TempBinaryB ::= TempBinaryB:a RELEASES:o UnaryExprB:b {: RESULT=ExprBinary.Op.RELEASES .make(o, null, a, b); :}; +TempBinaryB ::= TempBinaryB:a TRIGGERED:o UnaryExprB:b {: RESULT=ExprBinary.Op.TRIGGERED.make(o, null, a, b); :}; + +// [electrum] unary temporal formulas, same precedence as other unary operators +UnaryExprA ::= CompareExprA:b {: RESULT=b; :}; +UnaryExprA ::= NOT:o Bind:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; +UnaryExprA ::= NOT:o UnaryExprA:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; +UnaryExprA ::= ALWAYS:o Bind:b {: RESULT=ExprUnary.Op.ALWAYS.make(o, b); :}; +UnaryExprA ::= ALWAYS:o UnaryExprA:b {: RESULT=ExprUnary.Op.ALWAYS.make(o, b); :}; +UnaryExprA ::= EVENTUALLY:o Bind:b {: RESULT=ExprUnary.Op.EVENTUALLY.make(o, b); :}; +UnaryExprA ::= EVENTUALLY:o UnaryExprA:b {: RESULT=ExprUnary.Op.EVENTUALLY.make(o, b); :}; +UnaryExprA ::= AFTER:o Bind:b {: RESULT=ExprUnary.Op.AFTER.make(o, b); :}; +UnaryExprA ::= AFTER:o UnaryExprA:b {: RESULT=ExprUnary.Op.AFTER.make(o, b); :}; +UnaryExprA ::= HISTORICALLY:o Bind:b {: RESULT=ExprUnary.Op.HISTORICALLY.make(o, b); :}; +UnaryExprA ::= HISTORICALLY:o UnaryExprA:b {: RESULT=ExprUnary.Op.HISTORICALLY.make(o, b); :}; +UnaryExprA ::= ONCE:o Bind:b {: RESULT=ExprUnary.Op.ONCE.make(o, b); :}; +UnaryExprA ::= ONCE:o UnaryExprA:b {: RESULT=ExprUnary.Op.ONCE.make(o, b); :}; +UnaryExprA ::= BEFORE:o Bind:b {: RESULT=ExprUnary.Op.BEFORE.make(o, b); :}; +UnaryExprA ::= BEFORE:o UnaryExprA:b {: RESULT=ExprUnary.Op.BEFORE.make(o, b); :}; +UnaryExprB ::= CompareExprB:b {: RESULT=b; :}; +UnaryExprB ::= NOT:o UnaryExprB:b {: RESULT=ExprUnary.Op.NOT.make(o, b); :}; +UnaryExprB ::= ALWAYS:o UnaryExprB:b {: RESULT=ExprUnary.Op.ALWAYS.make(o, b); :}; +UnaryExprB ::= EVENTUALLY:o UnaryExprB:b {: RESULT=ExprUnary.Op.EVENTUALLY.make(o, b); :}; +UnaryExprB ::= AFTER:o UnaryExprB:b {: RESULT=ExprUnary.Op.AFTER.make(o, b); :}; +UnaryExprB ::= HISTORICALLY:o UnaryExprB:b {: RESULT=ExprUnary.Op.HISTORICALLY.make(o, b); :}; +UnaryExprB ::= ONCE:o UnaryExprB:b {: RESULT=ExprUnary.Op.ONCE.make(o, b); :}; +UnaryExprB ::= BEFORE:o UnaryExprB:b {: RESULT=ExprUnary.Op.BEFORE.make(o, b); :}; + +CompareExprA ::= CompareExprB:a IN:o ShiftExprA:b {: RESULT=ExprBinary.Op.IN .make(o, null, a, mult(b)); :}; +CompareExprA ::= CompareExprB:a EQUALS:o ShiftExprA:b {: RESULT=ExprBinary.Op.EQUALS .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a LT:o ShiftExprA:b {: RESULT=ExprBinary.Op.LT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a GT:o ShiftExprA:b {: RESULT=ExprBinary.Op.GT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a LTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.LTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a GTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.GTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTIN:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_IN .make(o, null, a, mult(b)); :}; +CompareExprA ::= CompareExprB:a NOTEQUALS:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_EQUALS.make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTLT:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_LT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTGT:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_GT .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTLTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_LTE .make(o, null, a, b); :}; +CompareExprA ::= CompareExprB:a NOTGTE:o ShiftExprA:b {: RESULT=ExprBinary.Op.NOT_GTE .make(o, null, a, b); :}; +CompareExprA ::= ALL:o ShiftExprA {: if (1==1) throw new ErrorSyntax(o,"The \"all x\" construct is no longer supported. If you know the range of possible values of x, consider rewriting it as \"x == set_of_all_possible_values\"."); :}; +CompareExprA ::= NO:o ShiftExprA:b {: RESULT=ExprUnary.Op.NO .make(o, b); :}; +CompareExprA ::= SOME:o ShiftExprA:b {: RESULT=ExprUnary.Op.SOME .make(o, b); :}; +CompareExprA ::= LONE:o ShiftExprA:b {: RESULT=ExprUnary.Op.LONE .make(o, b); :}; +CompareExprA ::= ONE:o ShiftExprA:b {: RESULT=ExprUnary.Op.ONE .make(o, b); :}; +CompareExprA ::= SET:o ShiftExprA:b {: RESULT=ExprUnary.Op.SETOF.make(o, b); :}; +CompareExprA ::= SEQ:o ShiftExprA:b {: RESULT=ExprBinary.Op.ISSEQ_ARROW_LONE.make(o, null, ExprVar.make(o, "seq/Int"), b); parser.dashmodule.addSeq(o); :}; +CompareExprA ::= ShiftExprA:b {: RESULT=b; :}; + +CompareExprB ::= CompareExprB:a IN:o ShiftExprB:b {: RESULT=ExprBinary.Op.IN .make(o, null, a, mult(b)); :}; +CompareExprB ::= CompareExprB:a EQUALS:o ShiftExprB:b {: RESULT=ExprBinary.Op.EQUALS .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a LT:o ShiftExprB:b {: RESULT=ExprBinary.Op.LT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a GT:o ShiftExprB:b {: RESULT=ExprBinary.Op.GT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a LTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.LTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a GTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.GTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTIN:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_IN .make(o, null, a, mult(b)); :}; +CompareExprB ::= CompareExprB:a NOTEQUALS:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_EQUALS.make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTLT:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_LT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTGT:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_GT .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTLTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_LTE .make(o, null, a, b); :}; +CompareExprB ::= CompareExprB:a NOTGTE:o ShiftExprB:b {: RESULT=ExprBinary.Op.NOT_GTE .make(o, null, a, b); :}; +CompareExprB ::= ALL:o ShiftExprB {: if (1==1) throw new ErrorSyntax(o,"The \"all x\" construct is no longer supported. If you know the range of possible values of x, consider rewriting it as \"x == set_of_all_possible_values\"."); :}; +CompareExprB ::= NO:o ShiftExprB:b {: RESULT=ExprUnary.Op.NO .make(o, b); :}; +CompareExprB ::= SOME:o ShiftExprB:b {: RESULT=ExprUnary.Op.SOME .make(o, b); :}; +CompareExprB ::= LONE:o ShiftExprB:b {: RESULT=ExprUnary.Op.LONE .make(o, b); :}; +CompareExprB ::= ONE:o ShiftExprB:b {: RESULT=ExprUnary.Op.ONE .make(o, b); :}; +CompareExprB ::= SET:o ShiftExprB:b {: RESULT=ExprUnary.Op.SETOF.make(o, b); :}; +CompareExprB ::= SEQ:o ShiftExprB:b {: RESULT=ExprBinary.Op.ISSEQ_ARROW_LONE.make(o, null, ExprVar.make(o,"seq/Int"), b); parser.dashmodule.addSeq(o); :}; +CompareExprB ::= ShiftExprB:b {: RESULT=b; :}; + +ShiftExprA ::= UnionDiffExprA:b {: RESULT=b; :}; +ShiftExprA ::= ShiftExprB:a SHL:o Bind:b {: RESULT=ExprBinary.Op.SHL.make(o, null, a, b); :}; +ShiftExprA ::= ShiftExprB:a SHR:o Bind:b {: RESULT=ExprBinary.Op.SHR.make(o, null, a, b); :}; +ShiftExprA ::= ShiftExprB:a SHA:o Bind:b {: RESULT=ExprBinary.Op.SHA.make(o, null, a, b); :}; +ShiftExprB ::= UnionDiffExprB:b {: RESULT=b; :}; +ShiftExprB ::= ShiftExprB:a SHL:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHL.make(o, null, a, b); :}; +ShiftExprB ::= ShiftExprB:a SHR:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHR.make(o, null, a, b); :}; +ShiftExprB ::= ShiftExprB:a SHA:o UnionDiffExprB:b {: RESULT=ExprBinary.Op.SHA.make(o, null, a, b); :}; + +UnionDiffExprA ::= MulExprA:b {: RESULT=b; :}; +UnionDiffExprA ::= UnionDiffExprB:a PLUS:o Bind:b {: RESULT=ExprBinary.Op.PLUS .make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a MINUS:o Bind:b {: RESULT=ExprBinary.Op.MINUS.make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a INTADD:o Bind:b {: RESULT=ExprBinary.Op.IPLUS.make(o, null, a, b); :}; +UnionDiffExprA ::= UnionDiffExprB:a INTSUB:o Bind:b {: RESULT=ExprBinary.Op.IMINUS.make(o, null, a, b); :}; +UnionDiffExprB ::= MulExprB:b {: RESULT=b; :}; +UnionDiffExprB ::= UnionDiffExprB:a PLUS:o MulExprB:b {: RESULT=ExprBinary.Op.PLUS .make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a MINUS:o MulExprB:b {: RESULT=ExprBinary.Op.MINUS.make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a INTADD:o MulExprB:b {: RESULT=ExprBinary.Op.IPLUS.make(o, null, a, b); :}; +UnionDiffExprB ::= UnionDiffExprB:a INTSUB:o MulExprB:b {: RESULT=ExprBinary.Op.IMINUS.make(o, null, a, b); :}; + +MulExprA ::= NumUnopExprA:b {: RESULT=b; :}; +MulExprA ::= MulExprB:a INTMUL:o Bind:b {: RESULT=ExprBinary.Op.MUL .make(o, null, a, b); :}; +MulExprA ::= MulExprB:a INTDIV:o Bind:b {: RESULT=ExprBinary.Op.DIV .make(o, null, a, b); :}; +MulExprA ::= MulExprB:a INTREM:o Bind:b {: RESULT=ExprBinary.Op.REM .make(o, null, a, b); :}; +MulExprB ::= NumUnopExprB:b {: RESULT=b; :}; +MulExprB ::= MulExprB:a INTMUL:o NumUnopExprB:b {: RESULT=ExprBinary.Op.MUL .make(o, null, a, b); :}; +MulExprB ::= MulExprB:a INTDIV:o NumUnopExprB:b {: RESULT=ExprBinary.Op.DIV .make(o, null, a, b); :}; +MulExprB ::= MulExprB:a INTREM:o NumUnopExprB:b {: RESULT=ExprBinary.Op.REM .make(o, null, a, b); :}; + +NumUnopExprA ::= OverrideExprA:b {: RESULT=b; :}; +NumUnopExprA ::= HASH:o Bind:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprA ::= SUM:o Bind:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprA ::= INT:o Bind:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +NumUnopExprA ::= HASH:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprA ::= SUM:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprA ::= INT:o NumUnopExprA:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +NumUnopExprB ::= OverrideExprB:b {: RESULT=b; :}; +NumUnopExprB ::= HASH:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CARDINALITY.make(o, b); :}; +NumUnopExprB ::= SUM:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; +//[AM]: INT->SIGINT +NumUnopExprB ::= INT:o NumUnopExprB:b {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, b)); :}; + +OverrideExprA ::= IntersectExprA:b {: RESULT=b; :}; +OverrideExprA ::= OverrideExprB:a PLUSPLUS:o Bind:b {: RESULT=ExprBinary.Op.PLUSPLUS.make(o, null, a, b); :}; +OverrideExprB ::= IntersectExprB:b {: RESULT=b; :}; +OverrideExprB ::= OverrideExprB:a PLUSPLUS:o IntersectExprB:b {: RESULT=ExprBinary.Op.PLUSPLUS.make(o, null, a, b); :}; + +IntersectExprA ::= RelationExprA:b {: RESULT=b; :}; +IntersectExprA ::= IntersectExprB:a AMPERSAND:o Bind:b {: RESULT=ExprBinary.Op.INTERSECT.make(o, null, a, b); :}; +IntersectExprB ::= RelationExprB:b {: RESULT=b; :}; +IntersectExprB ::= IntersectExprB:a AMPERSAND:o RelationExprB:b {: RESULT=ExprBinary.Op.INTERSECT.make(o, null, a, b); :}; + +RelOp ::= ARROW:o {: RESULT=new Pair(o, ExprBinary.Op.ARROW ); :}; +RelOp ::= ANY_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_SOME ); :}; +RelOp ::= ANY_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_ONE ); :}; +RelOp ::= ANY_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.ANY_ARROW_LONE ); :}; +RelOp ::= SOME_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_ANY ); :}; +RelOp ::= SOME_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_SOME); :}; +RelOp ::= SOME_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_ONE ); :}; +RelOp ::= SOME_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.SOME_ARROW_LONE); :}; +RelOp ::= ONE_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_ANY ); :}; +RelOp ::= ONE_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_SOME ); :}; +RelOp ::= ONE_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_ONE ); :}; +RelOp ::= ONE_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.ONE_ARROW_LONE ); :}; +RelOp ::= LONE_ARROW_ANY:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_ANY ); :}; +RelOp ::= LONE_ARROW_SOME:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_SOME); :}; +RelOp ::= LONE_ARROW_ONE:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_ONE ); :}; +RelOp ::= LONE_ARROW_LONE:o {: RESULT=new Pair(o, ExprBinary.Op.LONE_ARROW_LONE); :}; + +RelationExprA ::= DomainExprA:a {: RESULT=a; :}; +RelationExprA ::= DomainExprB:a RelOp:o Bind:b {: RESULT=o.b.make(o.a, null, a, b); :}; +RelationExprB ::= DomainExprB:a {: RESULT=a; :}; +RelationExprB ::= DomainExprB:a RelOp:o RelationExprB:b {: RESULT=o.b.make(o.a, null, a, b); :}; + +DomainExprA ::= RangeExprA:b {: RESULT=b; :}; +DomainExprA ::= DomainExprB:a DOMAIN:o Bind:b {: RESULT=ExprBinary.Op.DOMAIN.make(o, null, a, b); :}; +DomainExprB ::= RangeExprB:b {: RESULT=b; :}; +DomainExprB ::= DomainExprB:a DOMAIN:o RangeExprB:b {: RESULT=ExprBinary.Op.DOMAIN.make(o, null, a, b); :}; + +RangeExprA ::= BracketExprA:b {: RESULT=b; :}; +RangeExprA ::= RangeExprB:a RANGE:o Bind:b {: RESULT=ExprBinary.Op.RANGE.make(o, null, a, b); :}; +RangeExprB ::= BracketExprB:b {: RESULT=b; :}; +RangeExprB ::= RangeExprB:a RANGE:o BracketExprB:b {: RESULT=ExprBinary.Op.RANGE.make(o, null, a, b); :}; + +BracketExprA ::= DotExprA:b {: RESULT=b; :}; +BracketExprB ::= DotExprB:b {: RESULT=b; :}; +BracketExprB ::= BracketExprB:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=a; for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +BracketExprB ::= DISJ:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "disj"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +BracketExprB ::= TOTALORDER:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "pred/totalOrder"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=aa; :}; +//[AM]: INT->SIGINT +BracketExprB ::= INT:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "int"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=ExprUnary.Op.CAST2SIGINT.make(a, aa); :}; +BracketExprB ::= SUM:a LBRACKET Exprs:b RBRACKET:c {: Expr aa=ExprVar.make(a, "int"); for(Expr bb:b) aa=t(aa.span().merge(bb.span()), c, bb, aa, c); RESULT=ExprUnary.Op.CAST2SIGINT.make(a, aa); :}; + +DotExprA ::= UnopExprA:b {: RESULT=b; :}; +DotExprA ::= BracketExprB:a DOT:o Bind:b {: RESULT=t(o, null, a, b, null); :}; +DotExprB ::= UnopExprB:b {: RESULT=b; :}; +DotExprB ::= BracketExprB:a DOT:o UnopExprB:b {: RESULT=t(o, null, a, b, null); :}; +DotExprB ::= BracketExprB:a DOT:o DISJ:b {: RESULT=t(o, null, a, ExprVar.make(b, "disj"), null); :}; +DotExprB ::= BracketExprB:a DOT:o TOTALORDER:b {: RESULT=t(o, null, a, ExprVar.make(b, "pred/totalOrder"), null); :}; +//[AM]: INT->SIGINT +DotExprB ::= BracketExprB:a DOT:o INT {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, a)); :}; +DotExprB ::= BracketExprB:a DOT:o SUM {: RESULT=ExprUnary.Op.CAST2SIGINT.make(o, ExprUnary.Op.CAST2INT.make(o, a)); :}; + +// [electrum] unary temporal expressions, same precedence as other unary operators +UnopExprA ::= TILDE:o Bind:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprA ::= STAR:o Bind:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprA ::= CARET:o Bind:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; +UnopExprA ::= TILDE:o UnopExprA:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprA ::= STAR:o UnopExprA:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprA ::= CARET:o UnopExprA:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; +UnopExprB ::= BaseExpr:b {: RESULT=b; :}; +UnopExprB ::= TILDE:o UnopExprB:b {: RESULT=ExprUnary.Op.TRANSPOSE.make(o,b); :}; +UnopExprB ::= STAR:o UnopExprB:b {: RESULT=ExprUnary.Op.RCLOSURE .make(o,b); :}; +UnopExprB ::= CARET:o UnopExprB:b {: RESULT=ExprUnary.Op.CLOSURE .make(o,b); :}; +UnopExprA ::= Bind:b PRIME:o {: RESULT=ExprUnary.Op.PRIME .make(o,b); :}; +UnopExprA ::= UnopExprA:b PRIME:o {: RESULT=ExprUnary.Op.PRIME .make(o,b); :}; +UnopExprB ::= UnopExprB:b PRIME:o {: RESULT=ExprUnary.Op.PRIME .make(o,b); :}; + +BaseExpr ::= NUMBER:x {: RESULT = x; :}; +BaseExpr ::= STR:x {: RESULT = x; :}; +BaseExpr ::= IDEN:o {: RESULT = ExprVar.make(o, "iden"); :}; +BaseExpr ::= THIS:o {: RESULT = ExprVar.make(o, "this"); :}; +BaseExpr ::= INTMIN:o {: RESULT = ExprConstant.Op.MIN.make(o, 0); :}; +BaseExpr ::= INTMAX:o {: RESULT = ExprConstant.Op.MAX.make(o, 0); :}; +BaseExpr ::= INTNEXT:o {: RESULT = ExprConstant.Op.NEXT.make(o, 0); :}; +BaseExpr ::= LPAREN Expr:x RPAREN {: RESULT = x; :}; +BaseExpr ::= SigRef:x {: RESULT = x; :}; +BaseExpr ::= AT:o Name:x {: nod(x); RESULT = ExprVar.make(o.merge(x.pos), "@"+x.label); :}; +BaseExpr ::= Super:x {: RESULT = x; :}; +BaseExpr ::= LBRACE:o Declz:a SuperOrBar:b RBRACE:c {: RESULT = ExprQt.Op.COMPREHENSION.make(o, c, a, b); :}; +BaseExpr ::= LBRACE:o Declz:a RBRACE:c {: RESULT = ExprQt.Op.COMPREHENSION.make(o, c, a, ExprConstant.TRUE); :}; + +//============================================================================= + + +//DASH grammar ------------------------------------------------------------------------ + +// besides creating a DashState; the parsing also has count buffers and create indexes +// for those buffers in order to have the correct open statements + +// adding a case for the Spec +Spec ::= Spec StateRoot:o ; + +// Root State Declaration +StateRoot ::= STATE:o Name:n LBRACE RBRACE:e // empty state + {: + parser.dashmodule.rootStartLine = o.y; + parser.dashmodule.rootEndLine = e.y; + parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT)); + :}; +StateRoot ::= STATE:o Name:n LBRACE StateItemList:c RBRACE:e + {: + parser.dashmodule.rootStartLine = o.y; + parser.dashmodule.rootEndLine = e.y; + parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.NOTDEFAULT, c)); + :}; + +StateItemList ::= StateItem:x + {: List xList = new ArrayList(); xList.add(x); RESULT= xList; :}; +StateItemList ::= StateItemList:c StateItem:s + {: c.add(s); RESULT = c; :}; + +// empty state +StateItem ::= STATE:o Name:n LBRACE RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT ); :}; + +StateItem ::= STATE:o Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.NOTDEFAULT, c); :}; + +// empty state +StateItem ::= DEF STATE:o Name:n LBRACE RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.DefKind.DEFAULT); :}; + +StateItem ::= DEF STATE:o Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.DEFAULT, c); :}; + +// non parametrized state +StateItem ::= CONC:o STATE Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, n.label, DashStrings.StateKind.AND, DashStrings.DefKind.NOTDEFAULT, c); :}; + +// parametrized state +StateItem ::= CONC:o STATE Name:n LBRACKET Name:m RBRACKET LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, n.label, m.label, c); :}; + +// event decls +StateItem ::= EVENT:o Names:n LBRACE RBRACE + {: ArrayList ll = new ArrayList(); + for (ExprVar x: n) ll.add(x.label); + RESULT = new DashEventDecls(o, ll, DashStrings.IntEnvKind.INT); :}; +StateItem ::= ENV EVENT:o Names:n LBRACE RBRACE + {: ArrayList ll = new ArrayList(); + for (ExprVar x: n) ll.add(x.label); + RESULT = new DashEventDecls(o, ll, DashStrings.IntEnvKind.ENV); :}; + +// var decls +StateItem ::= + // we don't support the full variations of declarations here + // don't know what the pos should be for this one + Names:n COLON:o Expr:b + {: ArrayList ll = new ArrayList(); + for (ExprVar x: n) ll.add(x.label); + RESULT = new DashVarDecls(o, ll ,b, DashStrings.IntEnvKind.INT); :}; +StateItem ::= ENV:o Names:n COLON Expr:b + {: ArrayList ll = new ArrayList(); + for (ExprVar x: n) ll.add(x.label); + RESULT = new DashVarDecls(o, ll, b, DashStrings.IntEnvKind.ENV); :}; + +//buffer decls +StateItem ::= Names:n COLON:o BUF LBRACKET Name:m RBRACKET + {: + ArrayList ll = new ArrayList(); + for (ExprVar x: n) { + ll.add(x.label); + DashSituation.bufferElements.add(x.label); + } + RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.INT); + :}; +StateItem ::= Names:n COLON:o BUF LBRACKET SIGINT RBRACKET + {: + ArrayList ll = new ArrayList(); + for (ExprVar x: n) { + ll.add(x.label); + DashSituation.bufferElements.add(x.label); + } + RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT); + :}; +StateItem ::= ENV:o Names:n COLON BUF LBRACKET Name:m RBRACKET + {: + ArrayList ll = new ArrayList(); + for (ExprVar x: n) { + ll.add(x.label); + DashSituation.bufferElements.add(x.label); + } + RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV); + :}; + +StateItem ::= ENV:o Names:n COLON BUF LBRACKET SIGINT RBRACKET + {: + ArrayList ll = new ArrayList(); + for (ExprVar x: n) { + ll.add(x.label); + DashSituation.bufferElements.add(x.label); + } + RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV); + :}; + +// init +// Super is a list of expressions joined by conjunction +StateItem ::= INIT:o Super:v + {: RESULT = new DashInit(o, v); :}; + +// invariant +StateItem ::= INVARIANT:o Super:v + {: RESULT = new DashInv(o, v); :}; + +StateItem ::= INVARIANT:o Name:n Super:v + {: RESULT = new DashInv(o, n.label, v); :}; + +// action +StateItem ::= ACTION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE + {: RESULT = new DashAction(o, n.label, e); :}; + +// condition +StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE + {: RESULT = new DashCondition(o, n.label, e); :}; + +// transition +StateItem ::= TRANS:o Name:n LBRACE TransItemList:c RBRACE + {: RESULT = new DashTrans(o, n.label, c); :}; + +TransItemList ::= TransItem:x + {: RESULT = new ArrayList(); RESULT.add(x); :}; +TransItemList ::= TransItemList:c TransItem:x + {: c.add(x); RESULT = c; :}; + +TransItem ::= FROM:o Name:n + {: RESULT = new DashFrom(o, n.label); :}; + +TransItem ::= ON:o Expr:e + {: RESULT = new DashOn(o, e); :}; + +TransItem ::= WHEN:o Expr:v + {: RESULT = new DashWhen(o, v); :}; + +TransItem ::= DO:o Expr:v + {: RESULT = new DashDo(o, v); :}; + + +TransItem ::= GOTO:o Name:n + {: RESULT = new DashGoto(o, n.label); :}; + + +// this allows Send x.ev1 and "Send n" in parsing but will have to sort out later to see if correct +TransItem ::= SEND:o Expr:v + {: RESULT = new DashSend(o, v); :}; + +// DASH PLUS PROCESS VARIABLE REFERENCE +// ParamConcState[Param]/Variable +// result Param.ParamConcState/Variable +// not sure why a BadJoin is used here; but Alloy parsing rules use ExprBadJoins, not ExprJoins +// note PRIME is a special token in grammar and we want to support v' +BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e + {: + if (b.size() > 1) throw new ErrorSyntax(o,"Two many args to reference to sibling state"); + RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label)); + :}; +BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e PRIME + {: + if (b.size() > 1) throw new ErrorSyntax(o,"Two many args to reference to sibling state"); + // probably have to fix PRIME here later when turning to Alloy + RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label + "'")); + :}; + +//DASH end grammar --------------------------------------------------------------------- + diff --git a/org.alloytools.alloy.dash/parser/Dash.lex b/org.alloytools.alloy.dash/parser/Dash.lex new file mode 100644 index 000000000..228d8bfd0 --- /dev/null +++ b/org.alloytools.alloy.dash/parser/Dash.lex @@ -0,0 +1,297 @@ +/* + * DO NOT EDIT THIS FILE + * DASH: file copied from Alloy src with replacements for Dash - see install-alloy-files.sh + */ + + +// Alloy Analyzer 4 -- Copyright (c) 2006-2008, Felix Chang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package ca.uwaterloo.watform.parser; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Version; +import edu.mit.csail.sdg.ast.ExprConstant; +import edu.mit.csail.sdg.ast.ExprVar; +import java.util.List; +import java_cup.runtime.*; +import edu.mit.csail.sdg.parser.CompModule; + + +/** Autogenerated by JFlex 1.4.1 */ + +// @modified [electrum] added temporal keywords and operators (single quotes also +// interpreted as primes); forbade primes in identifiers + +%% + +// There are 3 sets of "special tokens" that the lexer will not output. +// But the Parser expects them. +// So a special Filter class is written that sits between Lexer and Parser. +// The Filter class observes the stream of tokens, and intelligently +// merges or changes some primitive tokens into special tokens. +// For more details, refer to the main documentation. +// +// But, very briefly, here are the 3 groups: +// +// (1) The lexer will generate only ALL, NO, LONE, ONE, SUM, SOME. +// It will not output ALL2, NO2, LONE2, ONE2, SUM2, SOME2. +// (The Filter class will change some ONE into ONE2, etc) +// +// (2) The lexer won't output NOTEQUALS, NOTIN, NOTLT, NOTLTE, NOTGT, NOTGTE. +// Instead it outputs them as separate tokens (eg. "NOT" "EQUALS"). +// (The Filter class is used to merge them into a single "NOTEQUALS" token) +// +// (3) The lexer willn't output the 15 special arrows (eg. ONE_ARROW_ONE) +// Instead it outputs them as separate tokens (eg. "ONE", "ARROW", "ONE") +// (The Filter class is used to merge them into a single "ONE_ARROW_ONE" token) + +%class DashLexer // The ordering of these directives is important +%cupsym DashSym +%cup +%eofval{ + return new Symbol(DashSym.EOF, alloy_here(" "), alloy_here(" ")); +%eofval} +%public +%final +%unicode +%line +%column +%pack + +%{ + public String alloy_filename=""; + public int alloy_lineoffset=0; // If not zero, it is added to the current LINE NUMBER + public List alloy_seenDollar; + public CompModule alloy_module; + private final Pos alloy_here(String txt) { + return new Pos(alloy_filename,yycolumn+1,yyline+1+alloy_lineoffset,yycolumn+txt.length(),yyline+1); + } + private final Symbol alloy_sym(String txt, int type) { + Pos p = alloy_here(txt); return new Symbol(type, p, p); + } + private final Symbol alloy_string(String txt) throws Err { + Pos p = alloy_here(txt); + if (!Version.experimental) throw new ErrorSyntax(p, "String literal is not currently supported."); + StringBuilder sb = new StringBuilder(txt.length()); + for(int i=0; i=txt.length()) throw new ErrorSyntax(p, "String literal cannot end with a single \\"); + c = txt.charAt(i); + if (c=='n') c='\n'; else if (c!='\"' && c!='\\') throw new ErrorSyntax(p, "String literal currently only supports\nthree escape sequences: \\\\, \\n, and \\\""); + } + sb.append(c); + } + txt = sb.toString(); + if (txt.length()==2) throw new ErrorSyntax(p, "Empty string is not allowed; try rewriting your model to use an empty set instead."); + return new Symbol(DashSym.STR, p, ExprConstant.Op.STRING.make(p, txt)); + } + private final Symbol alloy_id(String txt) throws Err { + Pos p=alloy_here(txt); + if (alloy_seenDollar.size()==0 && txt.indexOf('$')>=0) alloy_seenDollar.add(null); + return new Symbol(DashSym.ID, p, ExprVar.make(p,txt)); + } + private final Symbol alloy_num(String txt) throws Err { + Pos p=alloy_here(txt); + int n=0; + try { + txt = txt.replaceAll("_",""); + n=Integer.parseInt(txt); + } catch(NumberFormatException ex) { + throw new ErrorSyntax(p, "The number "+txt+" " + ex); + } + return new Symbol(DashSym.NUMBER, p, ExprConstant.Op.NUMBER.make(p, n)); + } + private final Symbol alloy_hexnum(String txt) throws Err { + Pos p=alloy_here(txt); + int n=0; + try { + txt = txt.substring(2).replaceAll("_",""); + n=Integer.parseInt(txt, 16); + } catch(NumberFormatException ex) { + throw new ErrorSyntax(p, "The hex number "+txt+" " + ex); + } + return new Symbol(DashSym.NUMBER, p, ExprConstant.Op.NUMBER.make(p, n)); + } + private final Symbol alloy_binarynum(String txt) throws Err { + Pos p=alloy_here(txt); + int n=0; + try { + txt = txt.substring(2).replaceAll("_",""); + n=Integer.parseInt(txt, 2); + } catch(NumberFormatException ex) { + throw new ErrorSyntax(p, "The binary number "+txt+" " + ex); + } + return new Symbol(DashSym.NUMBER, p, ExprConstant.Op.NUMBER.make(p, n)); + } +%} + +%% + +"!" { return alloy_sym(yytext(), DashSym.NOT );} +"#" { return alloy_sym(yytext(), DashSym.HASH );} +"&&" { return alloy_sym(yytext(), DashSym.AND );} +"&" { return alloy_sym(yytext(), DashSym.AMPERSAND );} +"(" { return alloy_sym(yytext(), DashSym.LPAREN );} +")" { return alloy_sym(yytext(), DashSym.RPAREN );} +"*" { return alloy_sym(yytext(), DashSym.STAR );} +"++" { return alloy_sym(yytext(), DashSym.PLUSPLUS );} +"+" { return alloy_sym(yytext(), DashSym.PLUS );} +"," { return alloy_sym(yytext(), DashSym.COMMA );} +"->" { return alloy_sym(yytext(), DashSym.ARROW );} +"-" { return alloy_sym(yytext(), DashSym.MINUS );} +"." { return alloy_sym(yytext(), DashSym.DOT );} +"/" { return alloy_sym(yytext(), DashSym.SLASH );} +"::" { return alloy_sym(yytext(), DashSym.DOT );} +":>" { return alloy_sym(yytext(), DashSym.RANGE );} +":" { return alloy_sym(yytext(), DashSym.COLON );} +"<=>" { return alloy_sym(yytext(), DashSym.IFF );} +"<=" { return alloy_sym(yytext(), DashSym.LTE );} +"<:" { return alloy_sym(yytext(), DashSym.DOMAIN );} +"<<" { return alloy_sym(yytext(), DashSym.SHL );} +"<" { return alloy_sym(yytext(), DashSym.LT );} +"=<" { return alloy_sym(yytext(), DashSym.LTE );} +"=>" { return alloy_sym(yytext(), DashSym.IMPLIES );} +"=" { return alloy_sym(yytext(), DashSym.EQUALS );} +">>>" { return alloy_sym(yytext(), DashSym.SHR );} +">>" { return alloy_sym(yytext(), DashSym.SHA );} +">=" { return alloy_sym(yytext(), DashSym.GTE );} +">" { return alloy_sym(yytext(), DashSym.GT );} +"@" { return alloy_sym(yytext(), DashSym.AT );} +"[" { return alloy_sym(yytext(), DashSym.LBRACKET );} +"]" { return alloy_sym(yytext(), DashSym.RBRACKET );} +"^" { return alloy_sym(yytext(), DashSym.CARET );} +"{" { return alloy_sym(yytext(), DashSym.LBRACE );} +"||" { return alloy_sym(yytext(), DashSym.OR );} +"|" { return alloy_sym(yytext(), DashSym.BAR );} +"}" { return alloy_sym(yytext(), DashSym.RBRACE );} +"~" { return alloy_sym(yytext(), DashSym.TILDE );} +"abstract" { return alloy_sym(yytext(), DashSym.ABSTRACT );} +"all" { return alloy_sym(yytext(), DashSym.ALL );} +"and" { return alloy_sym(yytext(), DashSym.AND );} +"assert" { return alloy_sym(yytext(), DashSym.ASSERT );} +"as" { return alloy_sym(yytext(), DashSym.AS );} +"but" { return alloy_sym(yytext(), DashSym.BUT );} +"check" { return alloy_sym(yytext(), DashSym.CHECK );} +"disjoint" { return alloy_sym(yytext(), DashSym.DISJ );} +"disj" { return alloy_sym(yytext(), DashSym.DISJ );} +"else" { return alloy_sym(yytext(), DashSym.ELSE );} +"enum" { return alloy_sym(yytext(), DashSym.ENUM );} +"exactly" { return alloy_sym(yytext(), DashSym.EXACTLY );} +"exhaustive" { return alloy_sym(yytext(), DashSym.EXH );} +"exh" { return alloy_sym(yytext(), DashSym.EXH );} +"expect" { return alloy_sym(yytext(), DashSym.EXPECT );} +"extends" { return alloy_sym(yytext(), DashSym.EXTENDS );} +"fact" { return alloy_sym(yytext(), DashSym.FACT );} +"for" { return alloy_sym(yytext(), DashSym.FOR );} +"fun" { return alloy_sym(yytext(), DashSym.FUN );} +"iden" { return alloy_sym(yytext(), DashSym.IDEN );} +"iff" { return alloy_sym(yytext(), DashSym.IFF );} +"implies" { return alloy_sym(yytext(), DashSym.IMPLIES );} +"Int" { return alloy_sym(yytext(), DashSym.SIGINT );} +"int" { return alloy_sym(yytext(), DashSym.INT );} +"in" { return alloy_sym(yytext(), DashSym.IN );} +"let" { return alloy_sym(yytext(), DashSym.LET );} +"lone" { return alloy_sym(yytext(), DashSym.LONE );} +"module" { return alloy_sym(yytext(), DashSym.MODULE );} +"none" { return alloy_sym(yytext(), DashSym.NONE );} +"not" { return alloy_sym(yytext(), DashSym.NOT );} +"no" { return alloy_sym(yytext(), DashSym.NO );} +"one" { return alloy_sym(yytext(), DashSym.ONE );} +"open" { return alloy_sym(yytext(), DashSym.OPEN );} +"or" { return alloy_sym(yytext(), DashSym.OR );} +"partition" { return alloy_sym(yytext(), DashSym.PART );} +"part" { return alloy_sym(yytext(), DashSym.PART );} +"pred" { return alloy_sym(yytext(), DashSym.PRED );} +"private" { return alloy_sym(yytext(), DashSym.PRIVATE );} +"run" { return alloy_sym(yytext(), DashSym.RUN );} +"seq" { return alloy_sym(yytext(), DashSym.SEQ );} +"set" { return alloy_sym(yytext(), DashSym.SET );} +"sig" { return alloy_sym(yytext(), DashSym.SIG );} +"some" { return alloy_sym(yytext(), DashSym.SOME );} +"String" { return alloy_sym(yytext(), DashSym.STRING );} +"sum" { return alloy_sym(yytext(), DashSym.SUM );} +"this" { return alloy_sym(yytext(), DashSym.THIS );} +"univ" { return alloy_sym(yytext(), DashSym.UNIV );} +"always" { return alloy_sym(yytext(), DashSym.ALWAYS );} +"after" { return alloy_sym(yytext(), DashSym.AFTER );} +"eventually" { return alloy_sym(yytext(), DashSym.EVENTUALLY );} +"historically" { return alloy_sym(yytext(), DashSym.HISTORICALLY);} +"before" { return alloy_sym(yytext(), DashSym.BEFORE );} +"once" { return alloy_sym(yytext(), DashSym.ONCE );} +"releases" { return alloy_sym(yytext(), DashSym.RELEASES );} +"until" { return alloy_sym(yytext(), DashSym.UNTIL );} +"since" { return alloy_sym(yytext(), DashSym.SINCE );} +"triggered" { return alloy_sym(yytext(), DashSym.TRIGGERED );} +";" { return alloy_sym(yytext(), DashSym.TRCSEQ );} +"var" { return alloy_sym(yytext(), DashSym.VAR );} +"steps" { return alloy_sym(yytext(), DashSym.TIME );} +"'" { return alloy_sym(yytext(), DashSym.PRIME );} +"‘" { return alloy_sym(yytext(), DashSym.PRIME );} +"’" { return alloy_sym(yytext(), DashSym.PRIME );} + +//DASH SYNTAX ADDITIONS + +"state" { return alloy_sym(yytext(), DashSym.STATE );} +"conc" { return alloy_sym(yytext(), DashSym.CONC );} +"default" { return alloy_sym(yytext(), DashSym.DEF );} + +"event" { return alloy_sym(yytext(), DashSym.EVENT );} +"env" { return alloy_sym(yytext(), DashSym.ENV );} +"buf" { return alloy_sym(yytext(), DashSym.BUF );} + +"init" { return alloy_sym(yytext(), DashSym.INIT );} +"invariant" { return alloy_sym(yytext(), DashSym.INVARIANT );} +"action" { return alloy_sym(yytext(), DashSym.ACTION );} +"condition" { return alloy_sym(yytext(), DashSym.CONDITION );} + +"trans" { return alloy_sym(yytext(), DashSym.TRANS );} + +"from" { return alloy_sym(yytext(), DashSym.FROM );} +"on" { return alloy_sym(yytext(), DashSym.ON );} +"when" { return alloy_sym(yytext(), DashSym.WHEN );} +"do" { return alloy_sym(yytext(), DashSym.DO );} +"goto" { return alloy_sym(yytext(), DashSym.GOTO );} +"send" { return alloy_sym(yytext(), DashSym.SEND );} + + +//END DASH SYNTAX ADDITIONS + +[\"] ([^\\\"] | ("\\" .))* [\"] [\$0-9a-zA-Z_\"] [\$0-9a-zA-Z_\"]* { throw new ErrorSyntax(alloy_here(yytext()),"String literal cannot be followed by a legal identifier character."); } +[\"] ([^\\\"] | ("\\" .))* [\"] { return alloy_string(yytext()); } +[\"] ([^\\\"] | ("\\" .))* { throw new ErrorSyntax(alloy_here(yytext()),"String literal is missing its closing \" character"); } +[0]"x"([_]|([0-9A-Fa-f][0-9A-Fa-f]))+ { return alloy_hexnum (yytext()); } +[0]"b"[01_]+ { return alloy_binarynum (yytext()); } +[0-9][0-9]*[\$a-zA-Z_\"][\$0-9a-zA-Z_\"]* { throw new ErrorSyntax(alloy_here(yytext()),"Name cannot start with a number."); } +[0-9][0-9_]* { return alloy_num (yytext()); } +[:jletter:][[:jletterdigit:]\"]* { return alloy_id (yytext()); } + + +"/**" ~"*/" { } + +"/*" ~"*/" { } + +("//"|"--") [^\r\n]* [\r\n] { } + +("//"|"--") [^\r\n]* { } // This rule is shorter than the previous rule, + // so it will only apply if the final line of a file is missing the \n or \r character. + +[ \t\f\r\n] { } + +. { throw new ErrorSyntax(alloy_here(" "), "Syntax error at the "+yytext()+" character. HEX: \\u"+Integer.toString(yytext().charAt(0),16)+")"); } diff --git a/org.alloytools.alloy.dash/parser/README.md b/org.alloytools.alloy.dash/parser/README.md new file mode 100644 index 000000000..fd054aed6 --- /dev/null +++ b/org.alloytools.alloy.dash/parser/README.md @@ -0,0 +1,10 @@ +# README.md + +Dash.cup and Dash.lex were created by the script install-alloy.files.sh, +which does some renaming and integrates the various parts of the lexer/grammar needed for Dash. + +Do NOT edit Dash.lex or Dash.cup directly. + +If Alloy is updated, rerun this script. + +If any of Dash-cup-*.txt or Dash-lex-*.txt are edited, rerun this script. \ No newline at end of file diff --git a/org.alloytools.alloy.dash/parser/install-alloy-files.sh b/org.alloytools.alloy.dash/parser/install-alloy-files.sh new file mode 100755 index 000000000..b2b20773c --- /dev/null +++ b/org.alloytools.alloy.dash/parser/install-alloy-files.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# The purpose of this script is to copy the Alloy files that we use +# but have to do some slight renaming in them +# rerun this script whenever Alloy updates these files + +# /g means multiple places on line + +# it's tricky when to convert to turn CompModule into DCModule (the original CompModule with renaming) +# vs DashModule (our code, which is an extension of DCModule) + +# Maintenance +# When Alloy.lex, Alloy.cup change the line numbers below will have to change! + +p=../../org.alloytools.alloy.core/parser/ +msg=$'/*\n * DO NOT EDIT THIS FILE\n * DASH: file copied from Alloy src with replacements for Dash - see install-alloy-files.sh \n */\n\n' + + +cp $p/Alloy.lex . + +sed -i -e 's/package edu.mit.csail.sdg.parser/package ca.uwaterloo.watform.parser/' Alloy.lex + +sed -i -e 's/CompLexer/DashLexer/g' Alloy.lex +sed -i -e 's/CompSym/DashSym/g' Alloy.lex +#sed -i -e 's/CompModule/DashModule/g' Alloy.lex + +# FILE LINE NUMBER DEPENDENCE BELOW +sed -n -e '1,24p' Alloy.lex > part1.txt +sed -n -e '25,240p' Alloy.lex > part2.txt +sed -n -e '241,$p' Alloy.lex > part3.txt +{ echo "$msg"; cat part1.txt Dash-lex-imports.txt part2.txt Dash-lex-addition.txt part3.txt ; } > Dash.lex +rm Alloy.lex part*.txt +rm *.lex-e + +# -------------- + +cp $p/Alloy.cup . + +sed -i -e 's/package edu.mit.csail.sdg.parser/package ca.uwaterloo.watform.parser/' Alloy.cup + +sed -i -e 's/CompLexer/DashLexer/g' Alloy.cup +sed -i -e 's/CompSym/DashSym/g' Alloy.cup +sed -i -e 's/CompParser/DashParser/g' Alloy.cup +sed -i -e 's/CompFilter/DashFilter/g' Alloy.cup + +sed -i -e 's/alloymodule/dashmodule/g' Alloy.cup +sed -i -e 's/public CompModule dashmodule=null;/public DashModule dashmodule=null;/g' Alloy.cup +sed -i -e 's/static CompModule alloy_parseStream/static DashModule alloy_parseStream/' Alloy.cup +sed -i -e 's/CompModule u = new CompModule(root, filename, prefix);/DashModule u = new DashModule(root, filename, prefix);/' Alloy.cup + +# split it up and put it back together +# FILE LINE NUMBER DEPENDENCE BELOW +sed -n -e '1,61p' Alloy.cup > part1.txt # to end of symbols +sed -n -e '62,249p' Alloy.cup > part2.txt +sed -n -e '250,533p' Alloy.cup > part3.txt # to end of terminals +sed -n -e '534,621p' Alloy.cup > part4.txt # to end of Dash-cup-nonterminals +sed -n -e '622,$p' Alloy.cup > part5.txt # to end of file +{ echo "$msg"; cat part1.txt Dash-cup-imports.txt part2.txt Dash-cup-symbols.txt part3.txt Dash-cup-terminals.txt part4.txt Dash-cup-nonterminals.txt part5.txt Dash-cup-grammar.txt; } > Dash.cup +rm Alloy.cup part*.txt +rm *.cup-e + + + + diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyDeclHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyDeclHelper.java new file mode 100644 index 000000000..b5cdb8856 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyDeclHelper.java @@ -0,0 +1,25 @@ +package ca.uwaterloo.watform.alloyasthelper; + +import java.util.Arrays; +import java.util.ArrayList; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprVar; + +import ca.uwaterloo.watform.alloyasthelper.AlloyExprHelper; + +public class AlloyDeclHelper { + + public static Decl createDecl(ExprVar v, Expr e) { + // not sure if mult is needed on last arg + return new Decl(null, null, null, null, new ArrayList<>(Arrays.asList(v)) , e); + } + public static Decl createOneDecl(String v, String typ) { + return createDecl(AlloyExprHelper.createVar(v), AlloyExprHelper.createOne(AlloyExprHelper.createVar(typ))); + } + public static Decl createSetDecl(String v, String typ) { + return createDecl(AlloyExprHelper.createVar(v), AlloyExprHelper.createSet(AlloyExprHelper.createVar(typ))); + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyExprHelper.java new file mode 100644 index 000000000..6ffdb9208 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyExprHelper.java @@ -0,0 +1,134 @@ +package ca.uwaterloo.watform.alloyasthelper; + +import java.util.ArrayList; +import java.util.Collections; + +import edu.mit.csail.sdg.alloy4.Pos; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprBadJoin; +import edu.mit.csail.sdg.ast.ExprBinary; +import edu.mit.csail.sdg.ast.ExprITE; +import edu.mit.csail.sdg.ast.ExprList; +import edu.mit.csail.sdg.ast.ExprQt; +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.ExprBinary; + +// Expr is not final so we can extend it +public class AlloyExprHelper { + + public static ExprVar createTrue() { + return ExprVar.make(Pos.UNKNOWN, "True"); + } + public static ExprVar createVar(String v) { + return ExprVar.make(Pos.UNKNOWN, v); + } + public static ArrayList createVarList(ArrayList vList) { + ArrayList retList = new ArrayList(); + for (String v: vList) { + retList.add(createVar(v)); + } + return retList; + } + + /* generic ones */ + public static Expr createBinaryExpr(Expr left, ExprBinary.Op op, Expr right) { + return (ExprBinary) op.make(Pos.UNKNOWN, Pos.UNKNOWN,left,right); + } + public static Expr createUnaryExpr(ExprUnary.Op op, Expr sub) { + return (ExprUnary) op.make(Pos.UNKNOWN, sub); + } + // dunno why this one is different in Alloy code + public static Expr createExprList(ExprList.Op op, ArrayList args) { + return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, op, args); + } + public static Expr createExprQt(ExprQt.Op op, ArrayList decls, Expr expr) { + return op.make(Pos.UNKNOWN, Pos.UNKNOWN, decls,expr); + } + + /* a few useful specific ones */ + public static Expr createOne(Expr sub) { + return (ExprUnary) ExprUnary.Op.ONE.make(Pos.UNKNOWN, sub); + } + public static Expr createSet(Expr sub) { + return (ExprUnary) ExprUnary.Op.SETOF.make(Pos.UNKNOWN, sub); + } + public static ExprBinary createJoin(Expr left, Expr right) { + return (ExprBinary) ExprBinary.Op.JOIN.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + public static Expr createJoinList(ArrayList elist) { + Expr ret = null; + assert(elist!=null); + ret = elist.get(0); + for (Expr el: elist.subList(1,elist.size()-1)) { + ret = createJoin(ret,el); + } + return ret; + } + public static Expr createPlusList(ArrayList elist) { + Expr ret = null; + assert(elist!=null); + ret = elist.get(0); + for (Expr el: elist.subList(1,elist.size())) { + ret = createPlus(ret,el); + } + return ret; + } + public static ExprBinary createEquals(Expr left, Expr right) { + return (ExprBinary) ExprBinary.Op.EQUALS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + public static ExprBinary createNotEquals(Expr left, Expr right) { + return (ExprBinary) ExprBinary.Op.NOT_EQUALS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + public static ExprBinary createAnd(Expr left, Expr right) { + return (ExprBinary) ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + public static Expr createAnd(ArrayList args) { + return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); + } + public static ExprBinary createOr(Expr left, Expr right) { + return (ExprBinary) ExprBinary.Op.OR.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + public static Expr createOr(ArrayList args) { + return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); + } + public static ExprBinary createArrow(Expr left,Expr right) { + return (ExprBinary) ExprBinary.Op.ARROW.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + public static ExprBinary createPlus(Expr left,Expr right) { + return (ExprBinary) ExprBinary.Op.PLUS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + public static ExprBinary createIn(Expr left,Expr right) { + return (ExprBinary) ExprBinary.Op.IN.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + // {x,y,z} + // returns x -> (y -> z) + public static Expr createArrowList(ArrayList eList) { + assert(eList != null); + Collections.reverse(eList); + Expr o = createVar(eList.get(0)); + for (String e: eList.subList(1,eList.size()-1)) { + o = createArrow(createVar(e), o); + } + return o; + } + + + public static ExprITE createITE(Expr cond, Expr impliesExpr, Expr elseExpr) { + return (ExprITE) ExprITE.make(Pos.UNKNOWN, cond, impliesExpr, elseExpr); + } + + public static ExprQt createAll(ArrayList decls, Expr expr) { + return (ExprQt) ExprQt.Op.ALL.make(Pos.UNKNOWN, Pos.UNKNOWN, decls, expr); + } + public static ExprQt createSome(ArrayList decls, Expr expr) { + return (ExprQt) ExprQt.Op.SOME.make(Pos.UNKNOWN, Pos.UNKNOWN, decls, expr); + } + + public static ExprUnary createAlways(Expr expr) { + return (ExprUnary) ExprUnary.Op.ALWAYS.make(Pos.UNKNOWN, expr); + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/Dash.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/Dash.java new file mode 100644 index 000000000..a31b5ddc0 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/Dash.java @@ -0,0 +1,19 @@ +package ca.uwaterloo.watform.ast; + + +import edu.mit.csail.sdg.alloy4.Pos; + +public class Dash { + // methods that all of Dash AST should have + + /** + * The filename, line, and column position in the original Alloy model file + * (cannot be null). + */ + public Pos pos; + + public final Pos pos() { + return pos; + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java new file mode 100644 index 000000000..95b97dbb5 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java @@ -0,0 +1,29 @@ +/* + These classes are used only during parsing because + we do not know what order items within a state will be parsed in. +*/ + +package ca.uwaterloo.watform.ast; + +import ca.uwaterloo.watform.core.DashStrings; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +public class DashAction extends Dash { + + public String name; + public Expr expr; + + public DashAction(Pos p, String n, Expr e) { + this.pos = p; + this.name = n; + this.expr = e; + } + public String toString() { + String s = new String(); + s += DashStrings.actionName + " " + name + " [\n"; + s += expr.toString() + "\n"; + return s + "] { }\n"; + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java new file mode 100644 index 000000000..6dfa7543f --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java @@ -0,0 +1,39 @@ +package ca.uwaterloo.watform.ast; + +import java.util.List; +import java.util.StringJoiner; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashBufferDecls extends Dash { + /** + * The filename, line, and column position in the original Alloy model file + * (cannot be null). + */ + + private List names; + private String element; + private DashStrings.IntEnvKind kind; + + public DashBufferDecls(Pos pos, List n, String element, DashStrings.IntEnvKind k) { + this.pos = pos; + this.names = n; + this.element = element; + this.kind = k; + } + + + public String toString() { + String s = new String(""); + if (kind == DashStrings.IntEnvKind.ENV) { + s += DashStrings.envName + " "; + } + StringJoiner sj = new StringJoiner(",\n"); + names.forEach(n -> sj.add(n)); + s += sj.toString() + ":" + DashStrings.bufName + "[" + element + "]"; + return s; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java new file mode 100644 index 000000000..c3e3c8e37 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java @@ -0,0 +1,29 @@ +/* + These classes are used only during parsing because + we do not know what order items within a state will be parsed in. +*/ + +package ca.uwaterloo.watform.ast; + +import ca.uwaterloo.watform.core.DashStrings; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +public class DashCondition extends Dash { + + public String name; + public Expr expr; + + public DashCondition(Pos p, String n, Expr e) { + this.pos = p; + this.name = n; + this.expr = e; + } + public String toString() { + String s = new String(); + s += DashStrings.conditionName + " " + name + " [\n"; + s += expr.toString() + "\n"; + return s + "] { }\n"; + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java new file mode 100644 index 000000000..05bdce17f --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java @@ -0,0 +1,26 @@ +package ca.uwaterloo.watform.ast; + + + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashDo extends Dash { + public Expr action; + + public DashDo(Pos pos,Expr a) { + this.pos = pos; + this.action = a; + + } + public String toString() { + String s = new String(); + s += DashStrings.doName + " "; + s += "{\n"; + s += action.toString() + "\n"; + s += "}\n"; + return s; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java new file mode 100644 index 000000000..0b0c02690 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java @@ -0,0 +1,33 @@ +package ca.uwaterloo.watform.ast; + +import java.util.List; +import java.util.StringJoiner; + +import edu.mit.csail.sdg.alloy4.Pos; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashEventDecls extends Dash { + + + + private List names; + private DashStrings.IntEnvKind kind; + + public DashEventDecls(Pos pos, List n, DashStrings.IntEnvKind kind) { + this.pos = pos; + this.names = n; + this.kind = kind; + } + + public String toString() { + String s = new String(""); + if (kind == DashStrings.IntEnvKind.ENV) { + s += DashStrings.envName + " "; + } + StringJoiner sj = new StringJoiner(",\n"); + names.forEach(n -> sj.add(n)); + s += DashStrings.eventName + " " + sj.toString() +"{ }\n"; + return s; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java new file mode 100644 index 000000000..52bb721c0 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java @@ -0,0 +1,95 @@ +package ca.uwaterloo.watform.ast; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +public class DashExpr extends Dash { + /* a wrapper around an Alloy Expr */ + + private Expr ae; + + public DashExpr(Pos pos,Expr a) { + this.pos = pos; + this.ae = a; + + } + + public String toString() { + return ae.toString(); + } + /* + private Expr recurseResolveAll(Expr e, Set ignore, String pth, symbolTable) { + // replace var names by FQNs + // replace "this" with ... + // replace buffers with ... + + // do not need to record params b/c that will be in SymbolTable + // ignore is the set of bound variables + + if (e isinstance ExprVar) { + if (not (ignore.contains(e.label)) { + if e.label.endsWith(DashStrings.PRIME) String x = e.label.substring(0,e.label.size()-1); + else String x = e.label; + if (!isFQN(x)) { + // replace var with FQN + //NAD we are assuming that it has a no type + if e.label.endsWith(DashStrings.PRIME) Expr exp = createVar(fqn(pth,x) + DashStrings.PRIME) + else exp = createVar(fqn(pth + e.label.substring(0,e.label.size()-1))); + } + symbolTable.addUsed(x); + return exp; + } else return e; + } else if (e isinstance ExprUnary) { + return e.op.make(recurseResolveAll(e.sub, ignore,pth)); + } else if (e isinstance ExprBinary) { + Expr left = recurseResolveAll(e.left,ignore,pth); + Expr right = recurseResolveAll(e.right,ignore,path); + return e.op.make(left,right); + } else if (e isinstance ExprITE) { + Expr cond = recurseResolveAll(e.cond,ignore,pth); + Expr left = recurseResolveAll(e.left,ignore,pth); + Expr right = recurseResolveAll(e.right,ignore,path); + return createITE(cond,left,right); + } else if (e isinstance ExprQT) { + Set ig = new HashSet(); + for (d: e.decls) for (x: d.names) ig.all(x.label); + Expr sub = recurseResolveAll(e.sub, ignore.addAll(ig),pth); + return createExprQT(e.op,e.decls,sub); + } else { + // expr type not yet covered in code + } + } + + public Expr resolveAll(String pth, symbolTable) { + return DashExpr(recurseResolveAll(ae,emptySet(),pth)); + } + + private Set recurseGetDynamicSymbols(Expr e, Set ignore) { + // ignore is the set of bound variables + if (e isinstance ExprVar && not(ignore.contains(e.label)) { + if e.label.endsWith(DashStrings.PRIME) { + Set hs = new HashSet() + return hs.add(e) + } else return emtpySet(); + } else if (e isinstance ExprUnary) { + return recurseGetDynamicSymbols(e.sub, ignore) + } else if (e isinstance ExprBinary) { + return recurseGetDynamicSymbols(e.left,ignore).addAll(recurseGetDynamicSymbols(e.right, ignore)) + } else if (e isinstance ExprITE) { + return recurseGetDynamicSymbols(e.left,ignore).addAll(recurseGetDynamicSymbols(e.right.ignore)).addAll(recurseGetDynamicSymbols(e.cond,ignore)) + } else if (e isinstance ExprQT) { + Set ig = new HashSet(); + for (d: e.decls) for (x: d.names) ig.all(x.label) + return recurseGetDynamicSymbols(e.sub,ignore.addAll(ig)) + } else { + // expr type not yet covered in code + } + } + public Set getDynamicSymbols() { + // look for which unbound vars (fully qualified name + params) in the symbol table are used in this expression + assert(resolved == true); + return recurseGetDynamicSymbols(ae, emptySet()); + } + */ + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java new file mode 100644 index 000000000..5c02f3a43 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java @@ -0,0 +1,16 @@ +package ca.uwaterloo.watform.ast; + +import edu.mit.csail.sdg.alloy4.Pos; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashFrom extends Dash { + public String src; + public DashFrom(Pos pos,String f) { + this.pos = pos; + this.src = f; + } + public String toString() { + return DashStrings.fromName + " " + src + "\n"; + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java new file mode 100644 index 000000000..359f22b79 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java @@ -0,0 +1,17 @@ +package ca.uwaterloo.watform.ast; + +import edu.mit.csail.sdg.alloy4.Pos; + +import ca.uwaterloo.watform.core.DashStrings; + + +public class DashGoto extends Dash { + public String dest; + public DashGoto(Pos pos,String g) { + this.pos = pos; + this.dest = g; + } + public String toString() { + return DashStrings.gotoName + " " + dest + "\n"; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java new file mode 100644 index 000000000..afb5afdef --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java @@ -0,0 +1,29 @@ +/* + These classes are used only during parsing because + we do not know what order items within a state will be parsed in. +*/ + +package ca.uwaterloo.watform.ast; + + + +import ca.uwaterloo.watform.core.DashStrings; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +public class DashInit extends Dash { + + public Expr init; + + public DashInit(Pos pos, Expr init) { + this.pos = pos; + this.init = init; + } + public String toString() { + String s = new String(); + s += DashStrings.initName + " {\n"; + s += init.toString() + "\n"; + return s + "}\n"; + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java new file mode 100644 index 000000000..c67d7ebfe --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java @@ -0,0 +1,32 @@ +package ca.uwaterloo.watform.ast; + + + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashInv extends Dash { + + public Expr inv; + public String name; // has no meaning + public DashInv(Pos pos, Expr inv) { + this.pos = pos; + this.name = null; + this.inv = inv; + } + public DashInv(Pos pos, String n, Expr inv) { + this.pos = pos; + this.name = n; + this.inv = inv; + } + public String toString() { + String s = new String(); + s += DashStrings.invariantName +" "; + if (name != null) s += name; + s += " {\n"; + s += inv.toString() + "\n"; + return s + "}\n"; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java new file mode 100644 index 000000000..a99060f36 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java @@ -0,0 +1,17 @@ +package ca.uwaterloo.watform.ast; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashOn extends Dash { + public Expr ev; + public DashOn(Pos pos,Expr e) { + this.pos = pos; + this.ev = e; + } + public String toString() { + return DashStrings.onName + " " + ev + "\n"; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java new file mode 100644 index 000000000..80ef1dbf8 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java @@ -0,0 +1,32 @@ +/* + This class is used only during parsing but is necessary because + we do not know what order items of a transitions will be parsed in. +*/ + +package ca.uwaterloo.watform.ast; + + +import java.util.ArrayList; +import java.util.StringJoiner; + +import ca.uwaterloo.watform.core.DashStrings; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +// send P[x]/ev1 +// send ev1 +// send y.x.ev1 + +public class DashSend extends Dash { + + public Expr eventExpr; + public DashSend(Pos pos,Expr ev) { + this.pos = pos; + this.eventExpr = ev; + } + public String toString() { + return DashStrings.sendName + " " + eventExpr.toString() + "\n"; + } +} + diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java new file mode 100644 index 000000000..7eea48ad2 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -0,0 +1,218 @@ +package ca.uwaterloo.watform.ast; + +//tmp +import java.util.*; + +import java.util.List; +import java.util.ArrayList; +import java.util.StringJoiner; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashState extends Dash { + + // stuff from parsing + private String name; + private String param; + private DashStrings.StateKind kind; // basic state = OR with no subStates + private DashStrings.DefKind def; + private List items; + private int tabsize = 2; + + // fully general constructor + // 6 args + public DashState(Pos p, String n, String prm, DashStrings.StateKind k, DashStrings.DefKind d, List i) { + this.pos = p; + this.name = n; + this.param = prm; + this.kind = k; + this.def = d; + this.items = i; + + } + // basic state - default or non-default + // 3 args + public DashState(Pos p, String n, DashStrings.DefKind d) { + this.pos = p; + this.name = n; + this.param = null; + this.kind = DashStrings.StateKind.BASIC; + this.def = d; + this.items = null; + } + // and/or state; non-parameterized + // 5 args + public DashState(Pos p, String n, DashStrings.StateKind k, DashStrings.DefKind d, List i) { + this.pos = p; + this.name = n; + this.param = null; + this.kind = DashStrings.StateKind.OR; + this.def = d; + this.items = i; + } + // and state; parameterized + // 4 args + public DashState(Pos p, String n, String prm, List i) { + assert(p != null); + this.pos = p; + this.name = n; + this.param = prm; + this.kind = DashStrings.StateKind.AND; + this.def = DashStrings.DefKind.NOTDEFAULT; + this.items = i; + } + + public String toString() { + String s = new String(""); + //s += s.join("", Collections.nCopies(tab*tabsize, " ")); + if (def == DashStrings.DefKind.DEFAULT) { + s += DashStrings.defaultName + " "; + } + if (kind == DashStrings.StateKind.AND) { + s += DashStrings.concName +" "; + } + if (items == null) { + s += DashStrings.stateName + " " + name + " { }\n"; + } else { + s += DashStrings.stateName + " " + name; + if (param == null) s += " {\n"; + else s += " [" + param + "] {\n"; + StringJoiner j = new StringJoiner(""); + items.forEach(i -> j.add(i.toString())); + s += j.toString() + "}\n"; + + } + return s; + } + + /* + public String getParam() { + return params(1) + } + public String getParams() { + return params; + } + public String getFullyQualName() { + return pathHere+"/"+name; + } + + public getAllTransitions() { + returns allTransitions; + } + + public getAllEvents() { + return allEvents; + } + + public getAllParams() { + return allParams; + } + + + // correctness checks + public boolean allSubStatesSameKind() { + if (subStates != null) { + StateKind k = substates(1).getKind(); + for (s:subStates) { + if (k != s.getKind()) { + error + } + } + return true; + } else { + return false; + } + } + + public getDefaultBasicStates() { + switch (kind): + case StateKind.BASIC: + return getFullyQualifiedName() + case StateKind.OR: + return getDefaultState + + + } else if (kind == StateKind.OR) { + + } else { + // error + } + } + } + public void resolveVars(String pth, List prs) { + for (d:dynvars) { + d.setPathToHere(pth); + d.setParams(params) + } + } + + public void resolveEvents(String pth) { + for (e:events) { + e.setPathToHere(pth); + } + } + public void resolveTrans(String pth, List prs) { + for (t:transitions) { + t.setPathToHere(pth); + t.setParems(params); + // calculate scope to put in table + // reject transition as crossing from one concurrent component to another if children of scope are concurrent !! + } + // what if no transitions + } + + // 1) all sibling states must be same type + + // env events cannot be generated + // env vars cannot be primed anywhere + // must have at least one transition (could be looping on Root ...) + + public void resolveAll(String pth, List prs, String parent) { + List params = prs.add(prm); + st.add(fulQualName(pth,name),params,parent, children) + + if (isBasicState()) { + allTransitions = new ArrayList(); + symbolTable = ??; + allEvents = new ArrayList(); + stateTable.add(s, {s}, {s}) + return; + } else { + allSubStatesSameKind() + // set the pathtohere and params of variables + // set the FQNs of src and dest of transitions + resolveVars(pth,prs); + resolveEvents(pth); + resolveTrans(pth,prs); + String defName = null; + for (s:substates) { + s.resolveAll(pathToHere, params); + // collect all the stuff from below + // set trans src/dest FQNs + allTransitions.addAll(s.getAllTransitions()); + symbolTable.addAll(s.getSymbolTable()); + allEvents.addAll(s.getAllEvents()); + allParams.addAll(s.getAllParams()); + // calculate all basic states entered/exited and pass up? + // or do that in StateTableResolve all?? + if (s.kind == StateKind.OR) { + if (defName == null) { + defName = s.getFullyQualName(); + } else { + // error multiple default states + } + } else { + defN + } + stateTable.merge(s.getStateTable()); + // what about parameters of states??? + } + stateTable.add(s,) + } + isResolved = true; + } + */ +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java new file mode 100644 index 000000000..bce1cf6ac --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java @@ -0,0 +1,33 @@ +package ca.uwaterloo.watform.ast; + +import java.util.List; +import java.util.StringJoiner; + +import ca.uwaterloo.watform.core.DashStrings; + +import edu.mit.csail.sdg.alloy4.Pos; + +public class DashTrans extends Dash { + String name; + List items; + + public DashTrans(Pos pos,String name, List items) { + this.pos = pos; + this.name = name; + this.items = items; + } + + public String toString() { + String s = new String(""); + if (items == null) { + s += DashStrings.transName + " " + name + " { }\n"; + } else { + s += DashStrings.transName + " " + name + "{\n"; + StringJoiner j = new StringJoiner(""); + items.forEach(i -> j.add(i.toString())); + s += j.toString() + "}\n"; + } + return s; + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java new file mode 100644 index 000000000..fbdb1620a --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java @@ -0,0 +1,36 @@ +package ca.uwaterloo.watform.ast; + +import java.util.List; +import java.util.StringJoiner; + +import ca.uwaterloo.watform.core.DashStrings; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +public class DashVarDecls extends Dash { + + + private List names; + private Expr typ; + private DashStrings.IntEnvKind kind; + + + + public DashVarDecls (Pos pos, List n, Expr e, DashStrings.IntEnvKind k) { + this.pos = pos; + this.names = n; + this.typ = e; + this.kind = k; + } + + + public String toString() { + String s = new String(""); + if (kind == DashStrings.IntEnvKind.ENV) { + s += DashStrings.envName + " "; + } + StringJoiner sj = new StringJoiner(",\n"); + names.forEach(n -> sj.add(n)); + return s + sj.toString() + ":" + typ.toString() + "\n"; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java new file mode 100644 index 000000000..3e4a5c234 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java @@ -0,0 +1,17 @@ +package ca.uwaterloo.watform.ast; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashWhen extends Dash { + public Expr when; + public DashWhen(Pos pos,Expr w) { + this.pos = pos; + this.when = w; + } + public String toString() { + return DashStrings.whenName + " " + when.toString() + "\n"; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java new file mode 100644 index 000000000..11571a19b --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java @@ -0,0 +1,19 @@ +package ca.uwaterloo.watform.core; + +// everything must be static +public class DashOptions { + + + public static String dashModelLocation = ""; + + public static boolean isElectrum = false; + public static boolean isTcmc = false; + public static boolean isTraces = true; + + //NAD other stuff that might be removed + //public static boolean variablesUnchanged = true; + //public static boolean assumeSingleInput = false; + //public static boolean generateSigAxioms = false; + //public static boolean reachabilityCheck = false; + +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java new file mode 100644 index 000000000..f0d79c4b1 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java @@ -0,0 +1,23 @@ +package ca.uwaterloo.watform.core; + +import java.util.*; + +// everything must be static +public class DashSituation { + + // we need a little bit of knowledge of the state of the process + // open statements have to be done before anything else in an + // Alloy file, but we don't know how many buffers we have + // so we have to run parsing once to count buffers + // and then a second time with the appropriate open statements + // we don't want to put this state within the DashModule because + // then we'd have to pass the dash module into the parser + // which isn't available at the parseFromFile in DashUtil (copied from CompUtil) + // so we set this after the first parse run + // and check it during the second parse run + public static boolean haveCountedBuffers = false; + // buffer elements in order of buffers + public static List bufferElements = new ArrayList(); + // we will need more here to know the names of the elements + // of the buffers for the open statements +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java new file mode 100644 index 000000000..f484c5c5f --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -0,0 +1,104 @@ +/* string names used in Dash and conversion to Alloy */ + +package ca.uwaterloo.watform.core; + +public class DashStrings { + + // used for printing: parts of Dash syntax + // must be in sync with Dash-cup-symbols.txt + public static String stateName = "state"; + public static String concName = "conc"; + public static String defaultName = "default"; + + public static String eventName = "event"; + public static String envName = "env"; + public static String bufName = "buf"; + + public static String initName = "init"; + public static String invariantName = "inv"; + public static String actionName = "action"; + public static String conditionName = "condition"; + + public static String transName = "trans"; + public static String fromName = "from"; + public static String onName = "on"; + public static String whenName = "when"; + public static String doName = "do"; + public static String gotoName = "goto"; + public static String sendName = "send"; + + + + + + // used for translation to Alloy + public static String qualChar = "/"; + // predicate names + + public static String smallStepName = "small_step"; + public static String stableName = "stable"; + public static String equalsName = "equals"; + public static String isEnabled = "isEnabled"; + + // sig names + public static String snapshotName = "Snapshot"; + public static String confName = "confName"; + public static String takenName = "taken"; + + public static String stateLabelName = "StateLabel"; + public static String systemStateName = "SystemState"; + + public static String bufferIndexName = "bufIndex"; + // how to name parameter variables + public static String pName = "p"; + public static String eventsName = "events"; + public static String eventLabelName = "EventLabel"; + public static String envEventLabelName = "EnvironmentalEvent"; + public static String intEventLabelName = "InternalEvent"; + + + public static String preName = "_pre"; + public static String postName = "_post"; + public static String semanticsName = "_semantics"; + public static String testIfNextStableName = "testIfNextStable"; + public static String isEnabledAfterStep = "_ isEnabledAfterStep"; + public static String tName = "t"; + public static String geName = "ge"; + + /* alloy keywords */ + public static String extendsName = "extends"; + public static String inName = "in"; + public static String abstractName = "abstract"; + public static String oneName = "one"; + public static String varName = "var"; + public static String boolName = "boolean"; + public static String intName = "int"; + public static String utilBooleanName = "util/boolean"; + public static String utilCTLpathName = "util/ctl_path"; + public static String utilOrderingName = "util/ordering"; + public static String utilBufferName = "util/buffer"; + + public static String tracesName = "traces"; + + public static String sCur = "s"; + public static String sNext = "sNext"; + public static String prime(String a) { + return a+"'"; + }; + + public static enum IntEnvKind { + INT, + ENV + } + + public static enum StateKind { + AND, + OR, + BASIC + } + + public static enum DefKind { + DEFAULT, + NOTDEFAULT + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java new file mode 100644 index 000000000..853489825 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -0,0 +1,95 @@ +package ca.uwaterloo.watform.mainfunctions; + +// drop this when removed print stmts here +import java.util.*; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.ast.Command; +import edu.mit.csail.sdg.parser.CompModule; + +import edu.mit.csail.sdg.translator.A4Options; +import edu.mit.csail.sdg.translator.A4Options.SatSolver; +import edu.mit.csail.sdg.translator.A4Solution; +import edu.mit.csail.sdg.translator.TranslateAlloyToKodkod; + +import ca.uwaterloo.watform.core.DashSituation; +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.parser.DashModule; + + +// no io in these! + + +public class MainFunctions { + + // both these function expect DashOptions to be set + + public static DashModule parseFile(String filename, A4Reporter rep) { + DashModule dash = null; + try { + DashOptions.isTraces = true; + DashSituation.haveCountedBuffers = false; + DashSituation.bufferElements = new ArrayList(); + dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); + if (dash == null) { + System.err.println("Empty Alloy file"); + } else { + DashSituation.haveCountedBuffers = true; + dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); + //System.out.println(filename + " parsed successfully."); + // well-formedness checks + //dash.resolveAll(d); + ; + } + } catch (Exception e) { + System.err.println(e); + System.exit(1); + } + return dash; + } + public static String dumpString(DashModule dash) { + String s = null; + try { + if (dash != null) { + s = dash.toString(); + } + } catch (Exception e) { + System.err.println(e); + } + return s; + } + + //NAD this should be more general and take a String + public static CompModule translateToAlloy(DashModule dash, A4Reporter rep) { + try { + DashOptions.isTraces = true; + if (dash == null) { + System.err.println("Cannot translate to Alloy."); + System.exit(1); + } + //CompModule alloy = new CoreDashToAlloy(dash).translate(); + //alloy.resolveAll(rep == null ? A4Reporter.NOP : rep, ); + } catch (Exception e) { + System.err.println(e); + System.exit(1); + } + + //CompModule alloy = null; + return null; + } + + public static A4Solution executeCommand(Command cmd, CompModule alloy, A4Reporter rep, A4Options options) { + + + //TODO this should be an option also + options.solver = A4Options.SatSolver.SAT4J; + + A4Solution ans = TranslateAlloyToKodkod.execute_command(rep, alloy.getAllReachableSigs(), cmd, options); + return ans; + + } + + + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java new file mode 100644 index 000000000..7edfdc971 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -0,0 +1,244 @@ +// No state here +// just helper functions for adding elements to the module + +package ca.uwaterloo.watform.parser; + +// tmp +import java.util.*; + +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import java.lang.StringBuilder; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Attr.AttrType; +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprVar; + +import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.ast.Sig.PrimSig; +import edu.mit.csail.sdg.ast.Sig; +import edu.mit.csail.sdg.parser.CompModule; + +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.alloyasthelper.AlloyExprHelper; + + +public class CompModuleHelper extends CompModule { + + // this class is never instantiated + public CompModuleHelper(CompModule world, String filename, String path) { + super(world,filename,path); + } + + /** + * adding signatures + * in CompModule, a signature has multiple related parts so can't just return a signature + * and let calling function add it to the module + * Alloy public Sig addSig(Pos namePos, String name, ExprVar par, + * List parents, List fields, Expr fact, Attr... attributes) throws Err { + */ + public void addSigSimple(String name) { + addSig( + Pos.UNKNOWN, + name, + null, + null, + new ArrayList(), + null, + null, + null, + null, + null, + null, + null); + } + + public void addAbstractSigSimple(String name) { + addSig( + Pos.UNKNOWN, + name, + null, + null, + new ArrayList(), + null, + AttrType.ABSTRACT.makenull(Pos.UNKNOWN), + null, + null, + null, + null, + null); + } + + public void addAbstractExtendsSigSimple(String extension, String extended) { + addSig( + Pos.UNKNOWN, + extension, + AlloyExprHelper.createVar(DashStrings.extendsName), + AlloyExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), + new ArrayList(), + null, + AttrType.ABSTRACT.makenull(Pos.UNKNOWN), + null, + null, + null, + null, + null); + } + + public void addOneExtendsSigSimple(String extension, String extended) { + addSig( + Pos.UNKNOWN, + extension, + AlloyExprHelper.createVar(DashStrings.extendsName), + AlloyExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), + new ArrayList(), + null, + null, + null, + AttrType.ONE.makenull(Pos.UNKNOWN), + null, + null, + null); + } + public void addSigWithDeclsSimple(String name, ArrayList decls) { + addSig( + Pos.UNKNOWN, + name, + null, + null, + decls, + null, + null, + null, + null, + null, + null, + null); + } + /* + public Sig addSig(Pos namePos, String name, ExprVar par, + List parents, List fields, Expr fact, Attr... attributes) + */ + public void addVarSigSimple(String name, ExprVar typ) { + // Electrum: var sig s in typ; + addSig( + Pos.UNKNOWN, + name, + AlloyExprHelper.createVar(DashStrings.inName), + Arrays.asList(typ), + new ArrayList(), + null, + null, + null, + null, + null, + null, + AttrType.VARIABLE.makenull(Pos.UNKNOWN) + ); + } + + public void addOpenSimple(String name, List args, String aliasName) { + ExprVar alias = (aliasName == null) ? null : AlloyExprHelper.createVar(aliasName); + List argsExprList = new ArrayList(); + if (args != null) + for (String a: args) { + argsExprList.add(AlloyExprHelper.createVar(a)); + } + // problem: we can't add opens after other stuff has been parsed in the Alloy module + addOpen(null, null, AlloyExprHelper.createVar(name), argsExprList, alias); + } + + /** + * adding functions/predicates + * + * Alloy: void addFunc(Pos p, Pos isPrivate, ExprVar n, Expr f, List decls, Expr t, Expr v) + * f is a label + * t is return type; null if predicate + */ + public void addPredSimple(String name, List decls, ArrayList eList) { + Expr body = AlloyExprHelper.createAnd(eList); + addFunc(Pos.UNKNOWN, Pos.UNKNOWN, AlloyExprHelper.createVar(name), null, decls, null, body); + } + + /** + * adding facts + * + * Alloy: void addFact(Pos pos, String name, Expr value) + */ + /* + public void addFactSimple(String name, List eList) { + Expr body = createAnd(eList); + alloy.addFact(Pos.UNKNOWN,name,body); + } + */ + + // Helper method to change "{path/label}" to "label" + private String cleanLabel(String label) { + if (!label.contains("this/")) { + return label; + } + if (label.endsWith("}") && label.startsWith("{")){ + label = label.substring(1,label.length()-1); + } + int index = label.lastIndexOf('/'); + if (index > -1) { + label = label.substring(index+1); + } + return label; + } + + public String getFilePath() { + // complete path + filename of input file is + // Pos of the "module" statement in CompModule + return modulePos.filename; + } + // this seems incomplete -> DROP IT EVENTUALLY + // also need to print facts + public String sigsToString() { + StringBuilder sb = new StringBuilder(""); + for(Sig sig: sigs.values()) { + if(sig.isVariable != null) + sb.append("var "); + if (sig.builtin) + sb.append("builtin "); + if (sig.isPrivate != null) + sb.append("private "); + if (sig.isAbstract != null) + sb.append("abstract "); + + if (sig.isLone != null) + sb.append("lone "); + + if (sig.isOne != null) + sb.append("one "); + + if (sig.isOne != null) + sb.append("some "); + + if (sig.isEnum != null) + sb.append("enum "); + sb.append("sig "); + sb.append(cleanLabel(sig.label)).append(" "); + if (sig.isSubsig != null && ((PrimSig) sig).parent.equals("univ")) { + sb.append("extends "); + sb.append(((PrimSig) sig).parent); + } else if (sig.isSubset != null) { + sb.append("in "); + sb.append(((PrimSig) sig).parent); + } + + sb.append(" {"); + for (Field f : sig.getFields()) { + StringJoiner namesJoiner = new StringJoiner(",\n"); + f.decl().names.forEach(name -> namesJoiner.add(cleanLabel(name.label))); + sb.append(namesJoiner.toString()); + } + sb.append(cleanLabel(sig.label)).append("}\n"); + + } + return sb.toString(); + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java new file mode 100644 index 000000000..767717f42 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java @@ -0,0 +1,473 @@ +/* + * DO NOT EDIT THIS FILE + * DASH: file copied from Alloy src with replacements for DashModule - see install-alloy-files.sh + */ + + +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package ca.uwaterloo.watform.parser; + +import static edu.mit.csail.sdg.parser.CompSym.ALL; +import static edu.mit.csail.sdg.parser.CompSym.ALL2; +import static edu.mit.csail.sdg.parser.CompSym.ANY_ARROW_LONE; +import static edu.mit.csail.sdg.parser.CompSym.ANY_ARROW_ONE; +import static edu.mit.csail.sdg.parser.CompSym.ANY_ARROW_SOME; +import static edu.mit.csail.sdg.parser.CompSym.ARROW; +import static edu.mit.csail.sdg.parser.CompSym.CHECK; +import static edu.mit.csail.sdg.parser.CompSym.COLON; +import static edu.mit.csail.sdg.parser.CompSym.COMMA; +import static edu.mit.csail.sdg.parser.CompSym.DISJ; +import static edu.mit.csail.sdg.parser.CompSym.EOF; +import static edu.mit.csail.sdg.parser.CompSym.EQUALS; +import static edu.mit.csail.sdg.parser.CompSym.EXH; +import static edu.mit.csail.sdg.parser.CompSym.FUN; +import static edu.mit.csail.sdg.parser.CompSym.GT; +import static edu.mit.csail.sdg.parser.CompSym.GTE; +import static edu.mit.csail.sdg.parser.CompSym.ID; +import static edu.mit.csail.sdg.parser.CompSym.IDEN; +import static edu.mit.csail.sdg.parser.CompSym.IN; +import static edu.mit.csail.sdg.parser.CompSym.INT; +import static edu.mit.csail.sdg.parser.CompSym.INTADD; +import static edu.mit.csail.sdg.parser.CompSym.INTDIV; +import static edu.mit.csail.sdg.parser.CompSym.INTMAX; +import static edu.mit.csail.sdg.parser.CompSym.INTMIN; +import static edu.mit.csail.sdg.parser.CompSym.INTMUL; +import static edu.mit.csail.sdg.parser.CompSym.INTNEXT; +import static edu.mit.csail.sdg.parser.CompSym.INTREM; +import static edu.mit.csail.sdg.parser.CompSym.INTSUB; +import static edu.mit.csail.sdg.parser.CompSym.LBRACE; +import static edu.mit.csail.sdg.parser.CompSym.LONE; +import static edu.mit.csail.sdg.parser.CompSym.LONE2; +import static edu.mit.csail.sdg.parser.CompSym.LONE_ARROW_ANY; +import static edu.mit.csail.sdg.parser.CompSym.LONE_ARROW_LONE; +import static edu.mit.csail.sdg.parser.CompSym.LONE_ARROW_ONE; +import static edu.mit.csail.sdg.parser.CompSym.LONE_ARROW_SOME; +import static edu.mit.csail.sdg.parser.CompSym.LT; +import static edu.mit.csail.sdg.parser.CompSym.LTE; +import static edu.mit.csail.sdg.parser.CompSym.MINUS; +import static edu.mit.csail.sdg.parser.CompSym.NO; +import static edu.mit.csail.sdg.parser.CompSym.NO2; +import static edu.mit.csail.sdg.parser.CompSym.NONE; +import static edu.mit.csail.sdg.parser.CompSym.NOT; +import static edu.mit.csail.sdg.parser.CompSym.NOTEQUALS; +import static edu.mit.csail.sdg.parser.CompSym.NOTGT; +import static edu.mit.csail.sdg.parser.CompSym.NOTGTE; +import static edu.mit.csail.sdg.parser.CompSym.NOTIN; +import static edu.mit.csail.sdg.parser.CompSym.NOTLT; +import static edu.mit.csail.sdg.parser.CompSym.NOTLTE; +import static edu.mit.csail.sdg.parser.CompSym.NUMBER; +import static edu.mit.csail.sdg.parser.CompSym.ONE; +import static edu.mit.csail.sdg.parser.CompSym.ONE2; +import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_ANY; +import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_LONE; +import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_ONE; +import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_SOME; +import static edu.mit.csail.sdg.parser.CompSym.PART; +import static edu.mit.csail.sdg.parser.CompSym.PRED; +import static edu.mit.csail.sdg.parser.CompSym.PRIVATE; +import static edu.mit.csail.sdg.parser.CompSym.RBRACE; +import static edu.mit.csail.sdg.parser.CompSym.RBRACKET; +import static edu.mit.csail.sdg.parser.CompSym.RPAREN; +import static edu.mit.csail.sdg.parser.CompSym.RUN; +import static edu.mit.csail.sdg.parser.CompSym.SET; +import static edu.mit.csail.sdg.parser.CompSym.SIGINT; +import static edu.mit.csail.sdg.parser.CompSym.SLASH; +import static edu.mit.csail.sdg.parser.CompSym.SOME; +import static edu.mit.csail.sdg.parser.CompSym.SOME2; +import static edu.mit.csail.sdg.parser.CompSym.SOME_ARROW_ANY; +import static edu.mit.csail.sdg.parser.CompSym.SOME_ARROW_LONE; +import static edu.mit.csail.sdg.parser.CompSym.SOME_ARROW_ONE; +import static edu.mit.csail.sdg.parser.CompSym.SOME_ARROW_SOME; +import static edu.mit.csail.sdg.parser.CompSym.STR; +import static edu.mit.csail.sdg.parser.CompSym.SUM; +import static edu.mit.csail.sdg.parser.CompSym.SUM2; +import static edu.mit.csail.sdg.parser.CompSym.THIS; +import static edu.mit.csail.sdg.parser.CompSym.TOTALORDER; +import static edu.mit.csail.sdg.parser.CompSym.UNIV; + +import java.io.Reader; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.ast.ExprConstant; +import edu.mit.csail.sdg.ast.ExprVar; +import java_cup.runtime.Scanner; +import java_cup.runtime.Symbol; + +/** + * This class sits between the lexer and the parser. + *

    + * Reason: there are 3 sets of "special tokens" that the lexer will not output. + * But the Parser expects them. So this filter class observes the stream of + * tokens, and intelligently merges or changes some primitive tokens into + * special tokens. + *

    + * For more details, refer to the main documentation. But, very briefly, here + * are the 3 groups: + *

    + * (1) The lexer will generate only ALL, NO, LONE, ONE, SUM, SOME. It will not + * output ALL2, NO2, LONE2, ONE2, SUM2, SOME2. (The Filter class will change ONE + * into ONE2 when appropriate) + *

    + * (2) The lexer won't output NOTEQUALS, NOTIN, NOTLT, NOTLTE, NOTGT, NOTGTE. + * Instead it outputs them as separate tokens (eg. "NOT" "EQUALS"). (The Filter + * class is used to merge them into a single "NOTEQUALS" token) + *

    + * (3) The lexer won't output the 15 special arrows (eg. ONE_ARROW_ONE) Instead + * it outputs them as separate tokens (eg. "ONE", "ARROW", "ONE") (The Filter + * class is used to merge them into a single "ONE_ARROW_ONE" token) + */ + +public final class DashFilter implements Scanner { + + // ===================== PHASE 1 + // ================================================================================== + + /** The underlying lexer. */ + private final Scanner r; + + /** + * A list of tokens that we prefetched from the underlying lexer. + */ + private final LinkedList undo = new LinkedList(); + + /** + * Stores the latest token passed from phase 1 to phase 2. + */ + private Symbol last = null; + + /** + * Reads a token from the underlying lexer; if the undo list is not empty, we + * take it from there instead. + */ + private Symbol myread() throws Err { + if (!undo.isEmpty()) + return undo.removeFirst(); + try { + return r.next_token(); + } catch (Exception ex) { + if (ex instanceof Err) + throw (Err) ex; + else + throw new ErrorFatal("IO error: " + ex.getMessage(), ex); + } + } + + /** + * Reads one or more tokens from the underlying lexer, transform them if + * necessarly. + */ + @Override + public Symbol next_token() throws Err { + Symbol a = myread(), b; + int c; + if (last == null || (last.sym != COLON && last.sym != DISJ)) { + if (a.sym == NO) + c = NO2; + else if (a.sym == ALL) + c = ALL2; + else if (a.sym == SUM) + c = SUM2; + else if (a.sym == LONE) + c = LONE2; + else if (a.sym == ONE) + c = ONE2; + else if (a.sym == SOME) + c = SOME2; + else + return last = a; + final ArrayList temp = new ArrayList(); + temp.add(b = myread()); + if (b.sym == PRIVATE) + temp.add(b = myread()); + if (b.sym == DISJ || b.sym == PART || b.sym == EXH) + temp.add(b = myread()); + while (b.sym == ID) { + temp.add(b = myread()); + if (b.sym == COMMA) + temp.add(b = myread()); + else if (b.sym == COLON) { + a.sym = c; + break; + } else { + break; + } + } + for (int i = temp.size() - 1; i >= 0; i--) + undo.add(0, temp.get(i)); + } + return last = a; + } + + /** + * Change a.pos to be the merger of a.pos and b.pos, then change a.sym to be + * sym, then return a. + */ + private static Symbol merge(Symbol a, Symbol b, int sym) { + a.pos = a.pos.merge(b.pos); + a.sym = sym; + return a; + } + + /** + * Construct a filter for the tokens from the given file. + */ + public DashFilter(DashModule module, List seenDollar, String filename, int lineOffset, Reader i) throws Err { + final DashLexer L = new DashLexer(i); + L.alloy_module = module; + L.alloy_filename = filename; + L.alloy_lineoffset = lineOffset; + L.alloy_seenDollar = seenDollar; + // Replace "ID : RUN/CHECK ID" with "RUN/CHECK ID ID" + // Replace "ID : RUN/CHECK {" WITH "RUN/CHECK ID {" + final Scanner A = new Scanner() { + + private Symbol a, b, c, d; + + @Override + public final Symbol next_token() throws Exception { + if (a == null) + a = L.next_token(); + if (a.sym == EOF) { + b = a; + c = a; + d = a; + } + if (b == null) + b = L.next_token(); + if (b.sym == EOF) { + c = b; + d = b; + } + if (c == null) + c = L.next_token(); + if (c.sym == EOF) { + d = c; + } + if (d == null) + d = L.next_token(); + if (a.sym == ID && b.sym == COLON && (c.sym == RUN || c.sym == CHECK) && (d.sym == ID || d.sym == LBRACE)) { + Symbol x = c; + b = d; + c = null; + d = null; + return x; + } + Symbol x = a; + a = b; + b = c; + c = d; + d = null; + return x; + } + }; + // Merges "pred" "/" "xxx" into the actual symbol + // Merges "fun" "/" "xxx" into the actual symbol + // Merges ! { in = < <= > >= } into a single symbol + // Merges {..}=>{..} into a single symbol + final Scanner B = new Scanner() { + + private Symbol undo; + + @Override + public final Symbol next_token() throws Exception { + Symbol x = undo; + undo = null; + if (x == null) + x = A.next_token(); + if (x.sym == NOT) { + Symbol y = A.next_token(); + if (y.sym == IN) + return merge(x, y, NOTIN); + if (y.sym == EQUALS) + return merge(x, y, NOTEQUALS); + if (y.sym == LT) + return merge(x, y, NOTLT); + if (y.sym == LTE) + return merge(x, y, NOTLTE); + if (y.sym == GT) + return merge(x, y, NOTGT); + if (y.sym == GTE) + return merge(x, y, NOTGTE); + undo = y; + } else if (x.sym == PRED) { + Symbol y = A.next_token(); + if (y.sym != SLASH) { + undo = y; + return x; + } + Symbol z = A.next_token(); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("totalOrder")) + return merge(x, z, TOTALORDER); + undo = z; + } else if (x.sym == FUN) { + Symbol y = A.next_token(); + if (y.sym != SLASH) { + undo = y; + return x; + } + Symbol z = A.next_token(); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("add")) + return merge(x, z, INTADD); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("sub")) + return merge(x, z, INTSUB); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("mul")) + return merge(x, z, INTMUL); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("div")) + return merge(x, z, INTDIV); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("rem")) + return merge(x, z, INTREM); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("min")) + return merge(x, z, INTMIN); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("max")) + return merge(x, z, INTMAX); + if (z.sym == ID && ((ExprVar) (z.value)).label.equals("next")) + return merge(x, z, INTNEXT); + } else if (x.sym == ONE) { + Symbol y = A.next_token(); + if (y.sym != ARROW) { + undo = y; + return x; + } + Symbol z = A.next_token(); + if (z.sym == ONE) + return merge(x, z, ONE_ARROW_ONE); + if (z.sym == LONE) + return merge(x, z, ONE_ARROW_LONE); + if (z.sym == SOME) + return merge(x, z, ONE_ARROW_SOME); + if (z.sym == SET) + return merge(x, z, ONE_ARROW_ANY); + else { + undo = z; + return merge(x, y, ONE_ARROW_ANY); + } + } else if (x.sym == LONE) { + Symbol y = A.next_token(); + if (y.sym != ARROW) { + undo = y; + return x; + } + Symbol z = A.next_token(); + if (z.sym == ONE) + return merge(x, z, LONE_ARROW_ONE); + if (z.sym == LONE) + return merge(x, z, LONE_ARROW_LONE); + if (z.sym == SOME) + return merge(x, z, LONE_ARROW_SOME); + if (z.sym == SET) + return merge(x, z, LONE_ARROW_ANY); + else { + undo = z; + return merge(x, y, LONE_ARROW_ANY); + } + } else if (x.sym == SOME) { + Symbol y = A.next_token(); + if (y.sym != ARROW) { + undo = y; + return x; + } + Symbol z = A.next_token(); + if (z.sym == ONE) + return merge(x, z, SOME_ARROW_ONE); + if (z.sym == LONE) + return merge(x, z, SOME_ARROW_LONE); + if (z.sym == SOME) + return merge(x, z, SOME_ARROW_SOME); + if (z.sym == SET) + return merge(x, z, SOME_ARROW_ANY); + else { + undo = z; + return merge(x, y, SOME_ARROW_ANY); + } + } else if (x.sym == SET) { + Symbol y = A.next_token(); + if (y.sym != ARROW) { + undo = y; + return x; + } + Symbol z = A.next_token(); + if (z.sym == ONE) + return merge(x, z, ANY_ARROW_ONE); + if (z.sym == LONE) + return merge(x, z, ANY_ARROW_LONE); + if (z.sym == SOME) + return merge(x, z, ANY_ARROW_SOME); + if (z.sym == SET) + return merge(x, z, ARROW); + else { + undo = z; + return merge(x, y, ARROW); + } + } else if (x.sym == ARROW) { + Symbol z = A.next_token(); + if (z.sym == ONE) + return merge(x, z, ANY_ARROW_ONE); + if (z.sym == LONE) + return merge(x, z, ANY_ARROW_LONE); + if (z.sym == SOME) + return merge(x, z, ANY_ARROW_SOME); + if (z.sym == SET) + return merge(x, z, ARROW); + else { + undo = z; + } + } + return x; + } + }; + // Merge "- number" into "-number" whenever it is not immediately + // following ")" "]" "}" DISJ TOTALORDER INT SUM ID NUMBER STR IDEN THIS + // INTMIN INTMAX INTNEXT UNIV SIGINT NONE + final Scanner C = new Scanner() { + + private Symbol last, undo; + + @Override + public final Symbol next_token() throws Exception { + Symbol x = undo; + undo = null; + if (x == null) + x = B.next_token(); + if (last != null) { + if (last.sym == RPAREN || last.sym == RBRACKET || last.sym == RBRACE || last.sym == DISJ || last.sym == TOTALORDER || last.sym == INT) + return last = x; + if (last.sym == SUM || last.sym == ID || last.sym == NUMBER || last.sym == STR || last.sym == IDEN || last.sym == THIS) + return last = x; + if (last.sym == INTMIN || last.sym == INTMAX || last.sym == INTNEXT || last.sym == UNIV || last.sym == SIGINT || last.sym == NONE) + return last = x; + } + if (x.sym == MINUS) { + Symbol y = B.next_token(); + if (y.sym == NUMBER) { + ExprConstant num = (ExprConstant) (y.value); + y.pos = x.pos.merge(y.pos); + y.value = ExprConstant.Op.NUMBER.make(y.pos, 0 - num.num); + return last = y; + } + undo = y; + return last = x; + } + return last = x; + } + }; + this.r = C; + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java new file mode 100644 index 000000000..3a076c240 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -0,0 +1,264 @@ +package ca.uwaterloo.watform.parser; + +// tmp +import java.util.*; + +import java.io.FileReader; +import java.io.BufferedReader; + +import java.io.FileNotFoundException; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + + +import edu.mit.csail.sdg.parser.CompModule; + +import ca.uwaterloo.watform.core.DashSituation; +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.ast.*; + +import ca.uwaterloo.watform.parser.CompModuleHelper; + +public class DashModule extends CompModuleHelper { + + // besides creating a DashState; parsing also has count buffers and create indexes + // for those buffers in order to have the correct open statements + + private DashState root = null; + public String filename = null; + public Integer rootStartLine = null; + public Integer rootEndLine = null; + private int numBuffers = 0; + private SymbolTable symbolTable; + + // can't ever be initialized with another world + public DashModule(String filename) { + super(null,filename,null); + assert (!DashOptions.isElectrum && (DashOptions.isTcmc || DashOptions.isTraces)); + // do the open stmts for Dash after we know how many buffers + if (DashSituation.haveCountedBuffers) { + importModules(DashSituation.bufferElements); + // because DashModule is created again for every recursive call + // make sure we only do this once on second parsing pass + DashSituation.haveCountedBuffers = false; + } + + } + public DashModule(CompModule world, String filename, String path) { + // super must be first statement in constructor + super(world,filename,path); + // this function is just for compatibility with copied CompUtil -> DashUtil + assert(world == null && path == null); + // do the open stmts for Dash after we know how many buffers + if (DashSituation.haveCountedBuffers) { + importModules(DashSituation.bufferElements); + // because DashModule is created again for every recursive call + // make sure we only do this once on second parsing pass + DashSituation.haveCountedBuffers = false; + } + } + public int nextBufferIndex() { + numBuffers++; + return numBuffers - 1; + } + public int getNumBuffers() { + return numBuffers; + } + public void setRoot(DashState r) { + assert(r != null); + root = r; + + } + + public String toString() { + String s = ""; + + try { + if (root != null) { + BufferedReader br = new BufferedReader(new FileReader(getFilePath())); + for (int i = 0; i < rootStartLine-1; i++) { + s += br.readLine() + "\n"; + } + + // eventually print everything + if (root != null) { + s += root.toString(); + } + // skip stuff + for (int i = 0; i <= rootEndLine - rootStartLine+1; i++) { + br.readLine(); + } + // add the rest of the lines + String k; + while ((k = br.readLine()) != null) { + s += k + "\n"; + } + } else { + // just put all the lines in the string + BufferedReader br = new BufferedReader(new FileReader(getFilePath())); + String k; + while ((k = br.readLine()) != null) { + s += k + "\n"; + } + } + } catch (Exception FileNotFoundException) { + // we know the file exists so this exception should never be thrown + // Fix this + System.err.println("File Not Found"); + } + /* + if (rootStartLine != null) { + s += "Path " + getFilePath() +"\n"; + s += "Dash file start line " + rootStartLine + "\n"; + s += "Dash end line " + rootEndLine +"\n"; + } + */ + // how to print the Alloy stuff we add? + // s += sigsToString(); + return s; + } + // helper functions for creating parts of module + /* + public static createDecl(ExprVar v, Expr e) { + return new Decl(null, null, null, null, v, mult(e)); + } + public static createOneDecl(String v, String typ) { + return createDecl(createVar(v), createOne(createVar(typ)); + } + public static createSetDecl(String v, String typ) { + return createDecl(createVar(v), createSet(createVar(typ)); + } + */ + + + public void importModules(List bufElements) { + String noAlias = null; + this.addOpenSimple(DashStrings.utilBooleanName, null, noAlias); + if (DashOptions.isTcmc) { + this.addOpenSimple(DashStrings.utilCTLpathName, Arrays.asList(DashStrings.snapshotName), noAlias); + } + else if (DashOptions.isTraces) { + this.addOpenSimple(DashStrings.utilOrderingName, Arrays.asList(DashStrings.snapshotName),DashStrings.snapshotName); + } + // add the open statements for the buffers + // if (bufElements != null ) + //for (String name: bufElements) { + // perhaps this can be simplified + //this.addOpen(DashStrings.utilBufferName, Arrays.asList("fix this", "fixthis"), "fix this"); + //} + } + /* + private List params; + private StateTable stateTable; + private TransTable transTable; + private SymbolTable symbolTable; + private EventTable eventTable; + public boolean hasConcurrency; + + + private int bufferMax; + // everything else is stored in the root State + + public void DashModule(DashState r) { + this.root = r; + // 0 is the first buffer number + this.bufferMax = -1 ; + } + + public String getRoot() { + return root.name(); // as root it is already FQN + } + public boolean hasInternalEvents() { + return (eventTable.hasInternalEvents()); + } + public boolean hasEnvironmentalEvents() { + return (eventTable.hasExternalEvents()); + } + public boolean hasEvents() { + return (hasInternalEvents() || hasEnvironmentalEvents()) + } + public List getAllInternalEventNames() { + assert(r.hasAllInternalEvents()); + return eventTable.getInternalEvent(); + } + public List getAllEnvironmentalEventNames() { + assert(r.hasAllExternalEvents()); + return eventTable.getEnvironmentalEvents(); + } + public List getTransitionNames() { + return transTable.getNames(); + } + public List getTransTriggerEvents(String t){ + return transTable.get(t).trigger(); + } + public List getTransGenEvents(String t) { + return transTable.get(t).genEvents(); + } + public List getEventParams(String e) { + return eventTable.get(e).getParams(); + } + public List getAllParams() { + return params; + } + public int getNumParams() { + return params.size(); + } + public List getBufferIndices() { + List iList; + for (i = 0; i <= r.getBufferMax(); i++) { + iList.add(DashStrings.bufferIndexName + i) + return iList; + } + public boolean hasConcurrency() { + ///???? at least one concurrent state + } + + public List getDynSymbols() { + return symbolTable.values(); + } + public List getBuffers() { + + } + public List getInvariants() { + /???? + } + public List getTransitionsAtLevel(int i) { + ArrayList o = transTable.keys().stream().filter(t -> transTable.get(t).params.size() == i).collect(Collectors.toList()); + return o; + } + public List getTransParams(String t) { + return transTable.get(t).getParams(); + } + public ArrayList getBasicStatesEnteredAtLevel(i){ + ArrayList bs = stateTable.get(root).basicStatesEntered; + ArrayList o = bs.stream().filter(s -> s.params.size() == i).collect(Collectors.toList()); + return o; + } + public List createStateArrow(String s) { + return createArrow(stateTable.get(s).params.add(s)); + } + + + public boolean hasBuffers() { + return (bufferMax != -1); + } + public int getBufferMax() { + return bufferMax; + } + + public void resolveAll() { + root.resolveAll(); + // if root has no substates? + // if no transitions? + stateTable.resolveAll(); + transTable.resolveAll(); + } + + public boolean isBasic(String s) { + return (stateTable.get(s).immediateChildren == null); + } + */ +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashUtil.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashUtil.java new file mode 100644 index 000000000..3117e9e69 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashUtil.java @@ -0,0 +1,513 @@ +/* + * DO NOT EDIT THIS FILE + * DASH: file copied from Alloy src with replacements for DashModule - see install-alloy-files.sh + */ + + +/* Alloy Analyzer 4 -- Copyright (c) 2006-2009, Felix Chang + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package ca.uwaterloo.watform.parser; + +import static edu.mit.csail.sdg.ast.Sig.SEQIDX; +import static edu.mit.csail.sdg.ast.Sig.SIGINT; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Util; +import edu.mit.csail.sdg.ast.Command; +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprBinary; +import edu.mit.csail.sdg.ast.ExprCall; +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.mit.csail.sdg.ast.ExprUnary.Op; +import edu.mit.csail.sdg.ast.Module; +import edu.mit.csail.sdg.ast.Sig; +import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.ast.Type.ProductType; +import edu.mit.csail.sdg.ast.VisitQueryOnce; +import edu.mit.csail.sdg.parser.CompModule.Open; + +/** + * This class provides convenience methods for calling the parser and the + * compiler. + * + * @modified [electrum] helper method to determine whether a model is fully + * static (classic Alloy); + */ + +public class DashUtil { + + /** + * Constructor is private, since this class never needs to be instantiated. + */ + public DashUtil() { + } + + // =============================================================================================================// + + /** + * Go up the directory hierarchy 0 or more times.
    + * For example, on a UNIX machine, goUp("/home/abc/def",1) will return + * "/home/abc"
    + * For example, on a UNIX machine, goUp("/home/abc/def",2) will return "/home" + * + * @param filepath - this must be an absolute path + * @param numberOfSteps - the number of steps to go up + */ + private static String up(String filepath, int numberOfSteps) { + while (numberOfSteps > 0) { + numberOfSteps--; + int i = filepath.lastIndexOf(File.separatorChar); + if (i <= 0) + return ""; + filepath = filepath.substring(0, i); + } + return filepath; + } + + // =============================================================================================================// + + /** + * Given the name of a module, and the filename for that module, compute the + * filename for another module + * + * @param moduleA - must be a legal Alloy modulepath (eg. name) (eg. + * name/name/name) (must not start or end in '/') + * @param fileA - the filename corresponding to moduleA + * @param moduleB - must be a legal Alloy modulepath (eg. name) (eg. + * name/name/name) (must not start or end in '/') + * @return the filename corresponding to moduleB + */ + private static String computeModulePath(String moduleA, String fileA, String moduleB) { + fileA = Util.canon(fileA); // Make sure it's a canonical absolute path + if (moduleA.length() == 0) + moduleA = "anything"; // Harmonizes the boundary case + while (moduleA.length() > 0 && moduleB.length() > 0) { + int a = moduleA.indexOf('/'), b = moduleB.indexOf('/'); + String headOfA = (a >= 0) ? moduleA.substring(0, a) : moduleA; + String headOfB = (b >= 0) ? moduleB.substring(0, b) : moduleB; + if (!headOfA.equals(headOfB) || a < 0 || b < 0) { + // eg. util/boolean==/home/models/util/boolean.als, then + // test=>/home/models/test.als" + // eg. util/boolean==/home/models/util/boolean.als, then + // sub/test=>/home/models/sub/test.als + // eg. main==/home/models/main.als, then + // test=>/home/models/test.als + // eg. main==/home/models/main.als, then + // sub/test=>/home/models/sub/test.als" + int numberOfSlash = 0; + for (int i = 0; i < moduleA.length(); i++) + if (moduleA.charAt(i) == '/') + numberOfSlash++; + return up(fileA, numberOfSlash + 1) + File.separatorChar + moduleB.replace('/', File.separatorChar) + ".als"; + } + moduleA = moduleA.substring(a + 1); + moduleB = moduleB.substring(b + 1); + } + return ""; // This shouldn't happen, since there should always be some + // character after '/' in the module name + } + + // =============================================================================================================// + + /** + * Whether or not Int appears in the relation types found in these sigs + */ + public static boolean areIntsUsed(Iterable sigs, Command cmd) { + /* check for Int-typed relations */ + for (Sig s : sigs) { + for (Field f : s.getFields()) { + for (ProductType pt : f.type()) { + for (int k = 0; k < pt.arity(); k++) { + if (pt.get(k) == SIGINT || pt.get(k) == SEQIDX) + return true; + } + } + } + } + + if (cmd == null) + return false; + + /* check expressions; look for CAST2SIGING (Int[]) */ + try { + Object intTriggerNode; + intTriggerNode = cmd.formula.accept(new VisitQueryOnce() { + + @Override + public Object visit(ExprCall x) throws Err { + // skip integer arithmetic functions, because their + // arguments are always explicitly cast to SIGINT using + // Int[] + if (x.fun.label.startsWith("integer/")) + return null; + return super.visit(x); + } + + @Override + public Object visit(ExprUnary x) throws Err { + if (x.op == Op.CAST2SIGINT) + return x; + return super.visit(x); + } + }); + if (intTriggerNode != null) + return true; + } catch (Err e) { + } + + return false; + } + + /** + * Whether the given command is a temporal model (either there are variable + * sigs/fields or temporal operators in the formula). + */ + public static boolean isTemporalModel(Iterable sigs, Command cmd) { + for (Sig sig : sigs) { + if (sig.isVariable != null && !sig.builtin) + return true; + else { + for (Decl dec : sig.getFieldDecls()) { + if (dec.isVar != null) + return true; + } + } + } + Object varTriggerNode; + varTriggerNode = cmd.formula.accept(new VisitQueryOnce() { + + @Override + public Object visit(ExprUnary x) throws Err { + if (x.op == Op.AFTER || x.op == Op.BEFORE || x.op == Op.PRIME || x.op == Op.HISTORICALLY || x.op == Op.ALWAYS || x.op == Op.ONCE || x.op == Op.EVENTUALLY) + return x; + return super.visit(x); + } + + @Override + public Object visit(ExprBinary x) throws Err { + if (x.op == ExprBinary.Op.UNTIL || x.op == ExprBinary.Op.SINCE || x.op == ExprBinary.Op.TRIGGERED || x.op == ExprBinary.Op.RELEASES) + return x; + return super.visit(x); + } + }); + if (varTriggerNode != null) + return true; + + return false; + } + + // =============================================================================================================// + + /** + * Helper method that recursively parse a file and all its included subfiles + * + * @param loaded - this stores the text files we've loaded while parsing; cannot + * be null + * @param fc - if a file cannot be found, we consult this cache first before + * attempting to load it from disk/jar; cannot be null + * @param pos - the position of the "open" statement + * @param filename - the filename to open + * @param root - the root module (this field is ignored if prefix=="") + * @param prefix - the prefix for the file we are about to parse + * @param thispath - the set of filenames involved in the current + * chain_of_file_opening + */ + private static DashModule parseRecursivelyDash(List seenDollar, Map loaded, Map fc, Pos pos, String filename, DashModule root, String prefix, Set thispath, int initialResolution) throws Err, FileNotFoundException, IOException { + // Add the filename into a ArrayList, so that we can detect cycles in + // the module import graph + // How? I'll argue that (filename appears > 1 time along a chain) <=> + // (infinite loop in the import graph) + // => As you descend down the chain via OPEN, if you see the same FILE + // twice, then + // you will go into an infinite loop (since, regardless of the + // instantiating parameter, + // that file will attempt to OPEN the exact same set of files. leading + // back to itself, etc. etc.) + // <= If there is an infinite loop, that means there is at least 1 + // infinite chain of OPEN (from root). + // Since the number of files is finite, at least 1 filename will be + // repeated. + if (thispath.contains(filename)) + throw new ErrorSyntax(pos, "Circular dependency in module import. The file \"" + (new File(filename)).getName() + "\" is imported infinitely often."); + thispath.add(filename); + // No cycle detected so far. So now we parse the file. + DashModule u = DashUtil.parse(seenDollar, loaded, fc, root, 0, filename, prefix, initialResolution); + if (prefix.length() == 0) + root = u; + + // Here, we recursively open the included files + for (Open x : u.getOpens()) { + String cp = Util.canon(computeModulePath(u.getModelName(), filename, x.filename)), content = fc.get(cp); + try { + if (content == null) { + content = loaded.get(cp); + } + if (content == null) { + content = fc.get(x.filename); + if (content != null) + cp = x.filename; + } + if (content == null) { + content = loaded.get(x.filename); + if (content != null) + cp = x.filename; + } + if (content == null) { + content = Util.readAll(cp); + } + } catch (IOException ex1) { + try { + String newCp = cp.replaceAll("\\.als$", ".md"); + content = Util.readAll(newCp); + } catch (IOException exx) { + + try { + String newCp = (Util.jarPrefix() + "models/" + x.filename + ".als").replace('/', File.separatorChar); + content = Util.readAll(newCp); + cp = newCp; + } catch (IOException ex) { + } + } + } + loaded.put(cp, content); + x.setResolvedFilePath(cp); + DashModule y = parseRecursivelyDash(seenDollar, loaded, fc, x.pos, cp, root, (prefix.length() == 0 ? x.alias : prefix + "/" + x.alias), thispath, initialResolution); + x.connect(y); + } + thispath.remove(filename); // Remove this file from the CYCLE DETECTION + // LIST. + return u; + } + + // =============================================================================================================// + + /** + * Parses 1 module from the input string (without loading any subfiles) + * + * @return an array of 0 or more Command if no error occurred + */ + public static ConstList parseOneModule_fromString(String content) throws Err { + DashModule u = parseOneModule(content); + return ConstList.make(u.getAllCommands()); + } + + public static DashModule parseOneModule(String content) throws Err { + try { + Map fc = new LinkedHashMap(); + fc.put("", content); + return DashUtil.parse(new ArrayList(), null, fc, null, 0, "", "", 1); + } catch (IOException ex) { + throw new ErrorFatal("IOException occurred: " + ex.getMessage(), ex); + } catch (Throwable ex) { + if (ex instanceof Err) + throw (Err) ex; + else + throw new ErrorFatal("Unknown exception occurred: " + ex, ex); + } + } + + // =============================================================================================================// + + /** + * Parses 1 module from the file (without loading any subfiles) + * + * @return an array of 0 or more Command if no error occurred + */ + public static ConstList parseOneModule_fromFile(String filename) throws Err { + try { + DashModule u = DashUtil.parse(new ArrayList(), null, null, null, 0, filename, "", 1); + return ConstList.make(u.getAllCommands()); + } catch (IOException ex) { + throw new ErrorFatal("IOException occurred: " + ex.getMessage(), ex); + } catch (Throwable ex) { + if (ex instanceof Err) + throw (Err) ex; + else + throw new ErrorFatal("Unknown exception occurred: " + ex, ex); + } + } + + // =============================================================================================================// + + /** + * Parses then typecheck the given input String as an Alloy expression from that + * world + * + * @return the fully-typechecked expression if no error occurred + * @throws Err if world==null or if any other error occurred + */ + public static Expr parseOneExpression_fromString(Module world, String input) throws Err { + try { + if (world == null) + throw new ErrorFatal("Cannot parse an expression with null world."); + return world.parseOneExpressionFromString(input); + } catch (IOException ex) { + throw new ErrorFatal("IOException occurred: " + ex.getMessage(), ex); + } catch (Throwable ex) { + if (ex instanceof Err) + throw (Err) ex; + else + throw new ErrorFatal("Unknown exception occurred: " + ex, ex); + } + } + + // =============================================================================================================// + + /** + * Read everything from "file" and parse it; if it mentions submodules, open + * them and parse them too. + * + * @param rep - if nonnull, we will report compilation progress messages to it + * @param loaded - a cache of files that have been pre-fetched (can be null if + * there were no prefetching) + * @param filename - the main module we are parsing + * @return the root Module which contains pointers to all submodules + * @throws Err if an error occurred + *

    + * And if loaded!=null, it will contain all the files needed for + * this parse, and furthermore, other entries will be deleted. + */ + public static DashModule parseEverything_fromFileDash(A4Reporter rep, Map loaded, String filename) throws Err { + try { + filename = Util.canon(filename); + Set thispath = new LinkedHashSet(); + if (loaded == null) + loaded = new LinkedHashMap(); + Map fc = new LinkedHashMap(loaded); + loaded.clear(); + List seenDollar = new ArrayList(); + DashModule root = parseRecursivelyDash(seenDollar, loaded, fc, new Pos(filename, 1, 1), filename, null, "", thispath, 1); + root.seenDollar = seenDollar.size() > 0; + //return CompModule.resolveAll(rep == null ? A4Reporter.NOP : rep, root); + return root; //DASH: resolveAll is done later + } catch (FileNotFoundException ex) { + throw new ErrorSyntax("File cannot be found.\n" + ex.getMessage(), ex); + } catch (IOException ex) { + throw new ErrorFatal("IOException occurred: " + ex.getMessage(), ex); + } catch (Throwable ex) { + if (ex instanceof Err) + throw (Err) ex; + else + throw new ErrorFatal("Unknown exception occurred: " + ex, ex); + } + } + + /** + * Read everything from "file" and parse it; if it mentions submodules, open + * them and parse them too. + * + * @param rep - if nonnull, we will report compilation progress messages to it + * @param loaded - a cache of files that have been pre-fetched (can be null if + * there were no prefetching) + * @param filename - the main module we are parsing + * @param initialResolutionMode - use 1 for the historical behavior, and 2 for + * Alloy 4.2's new "universal implicit this" name resolution behavior + * @return the root DashModule which contains pointers to all submodules + * @throws Err if an error occurred + *

    + * And if loaded!=null, it will contain all the files needed for + * this parse, and furthermore, other entries will be deleted. + */ + public static DashModule parseEverything_fromFileDash(A4Reporter rep, Map loaded, String filename, int initialResolutionMode) throws Err { + try { + filename = Util.canon(filename); + Set thispath = new LinkedHashSet(); + if (loaded == null) + loaded = new LinkedHashMap(); + Map fc = new LinkedHashMap(loaded); + loaded.clear(); + List seenDollar = new ArrayList(); + DashModule root = parseRecursivelyDash(seenDollar, loaded, fc, new Pos(filename, 1, 1), filename, null, "", thispath, initialResolutionMode); + // if no sigs are defined by the user, add one + if (root.getAllReachableUserDefinedSigs().isEmpty()) { + root.addGhostSig(); + } + root.seenDollar = seenDollar.size() > 0; + //return CompModule.resolveAll(rep == null ? A4Reporter.NOP : rep, root); + return root; //DASH: resolveAll is done later + } catch (FileNotFoundException ex) { + throw new ErrorSyntax("File cannot be found.\n" + ex.getMessage(), ex); + } catch (IOException ex) { + throw new ErrorFatal("IOException occurred: " + ex.getMessage(), ex); + } catch (Throwable ex) { + if (ex instanceof Err) + throw (Err) ex; + else + throw new ErrorFatal("Unknown exception occurred: " + ex, ex); + } + } + + /** + * @param rep - may be null + * @param content - alloy model + */ + public static DashModule parseEverything_fromStringDash(A4Reporter rep, String content) throws Err { + if (rep == null) + rep = new A4Reporter(); + try { + File tmpAls = flushModelToFile(content, null); + return DashUtil.parseEverything_fromFileDash(rep, null, tmpAls.getAbsolutePath()); + } catch (IOException ex) { + throw new ErrorFatal("IOException occurred: " + ex.getMessage(), ex); + } + } + + /** + * Saves the given alloy model to a file. + * + * @param model - alloy model + * @param tmpAls - if null, a temporary file will be created and returned + */ + public static File flushModelToFile(String model, File tmpAls) throws IOException { + if (tmpAls == null) { + tmpAls = File.createTempFile("alloy_heredoc", ".als"); + tmpAls.deleteOnExit(); + } + try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tmpAls))) { + bos.write(model.getBytes()); + bos.flush(); + return tmpAls; + } + } + + static DashModule parse(List seenDollar, Map loaded, Map fc, DashModule root, int lineOffset, String filename, String prefix, int initialResolutionMode) throws Err, FileNotFoundException, IOException { + DashModule module = DashParser.alloy_parseStream(seenDollar, loaded, fc, root, lineOffset, filename, prefix, initialResolutionMode); + module.addDefaultCommand(); + return module; + } + + public static DashModule nullModule() { + return new DashModule(null, "", ""); + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/SymbolTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/SymbolTable.java new file mode 100644 index 000000000..8c5dafc43 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/SymbolTable.java @@ -0,0 +1,109 @@ +package ca.uwaterloo.watform.parser; + +import java.util.ArrayList; +import java.util.HashMap; + +import edu.mit.csail.sdg.ast.Expr; +import ca.uwaterloo.watform.core.DashStrings; + +public class SymbolTable { + + private HashMap table; + private int NOTBUFFER = -1; + + public class DynSymbol { + + private int index; // used for buffers + // tmp + private String typ; + // private DashExpr exp; // type expression + private DashStrings.IntEnvKind kind; + + // for variables + public DynSymbol(Expr e, DashStrings.IntEnvKind k) { + this.index = NOTBUFFER; + // tmp + this.typ = null; + this.kind = k; + + } + // for buffers + public DynSymbol(int idx, DashStrings.IntEnvKind k, String elements) { + this.index = idx; + // temporary + this.typ = elements; + // this.typ = DashExpr(createArrow(DashStrings.bufferIndexName+idx, elements)); + this.kind = k; + + } + } + public SymbolTable() { + this.table = new HashMap(); + } + /* + public void addDeclaredVar(String n, List prs, Expr e, EventVarKind k) { + if (!table.keys().contains(n)) { + table.put(n,DynVar(i,prs,e,k)) + } else { + if (table.get(n).declared) // err declared twice + else table.get(n) = DynVar(i,prs,e,k); + } + } + */ + public void addDeclaredBuffer(String n, int idx, DashStrings.IntEnvKind k, String elements) { + if (!table.keySet().contains(n)) { + table.put(n,new DynSymbol(idx,k,elements)); + } else { + if (table.get(n) != null) { ; } // err declared twice + else table.put(n, new DynSymbol(idx,k,elements)); + } + } + /* + public void addUsedVar(String n) { + if ( !(table.keys().contains(n))) table.put(n,null); + } + public void addUsedBuffer(String n) { + if ( !(table.keys().contains(n))) table.put(n,null); + } + public void resolveAll() { + // check for any vars used but not declared + for (e:table.keys()) { + if (table.get(e) == null) { + // err used but not declared + } + } + } + */ + /* + creates the fully qualified name + uses snapshot or not for Electrum + joins with params + */ + /* + public AlloyExpr createAlloyExprVar(boolean primed) { + String n = pathHere+"/"+name; + if (DashOptions.isElectrum() && primed) { + n = DashStrings.prime(n) ; + } + ExprVar e = createVar(n) + if (!DashOptions.isElectrum()) { + if (!primed) { + s = DashStrings.sCur; + e = AlloyExprHelper.createExprJoin(s,e) + } else { + s = DashStrings.sNext; + e = AlloyExprHelper.createExprJoin(s,e) + } + } + // turn all the params into vars + return AlloyExprHelper.createExprJoin (p0.p1.p2.e) + } + + // used for snapshot declarations + // probably will have to return exp and then convert + public Expr createAlloyTyp(symboltable) { + // does it have to convert anything?? + return typ.convertToAlloy(symboltable) + } + */ +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh new file mode 100755 index 000000000..f097ee44d --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# The purpose of this script is to copy the Alloy files that we use +# but have to do some slight renaming in them +# rerun this script whenever Alloy updates these files + +# /g means multiple places on line + +# it's tricky when to convert to turn CompModule into DCModule (the original CompModule with renaming) +# vs DashModule (our code, which is an extension of DCModule) + +p=../../../../../../../../org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/ +msg=$'/*\n * DO NOT EDIT THIS FILE\n * DASH: file copied from Alloy src with replacements for DashModule - see install-alloy-files.sh \n */\n\n' + +# -------------- +# the filter sits between the Lexer and the Parser - to get it to call our DashLexer, we have to make a copy of the file +cp $p/CompFilter.java . + +sed -i -e 's/package edu.mit.csail.sdg.parser/package ca.uwaterloo.watform.parser/' CompFilter.java + +sed -i -e 's/CompLexer/DashLexer/g' CompFilter.java +sed -i -e 's/CompModule/DashModule/g' CompFilter.java +sed -i -e 's/CompFilter/DashFilter/g' CompFilter.java +# just adding a comment to the line -- could delete this if comment not relevant anymore +# sed -i -e 's/L.alloy_module = module;/L.alloy_module = module; \/\/NAD: Tamjid had this line commented out/' CompFilter.java +{ echo "$msg"; cat CompFilter.java; } > DashFilter.java +rm CompFilter.java + +# -------------- +cp $p/CompUtil.java . +# order matters here +sed -i -e 's/package edu.mit.csail.sdg.parser/package ca.uwaterloo.watform.parser/' CompUtil.java +#sed -i -e 's/import edu.mit.csail.sdg.parser.CompModule.Context;/import ca.uwaterloo.watform.parser.DCModule.Context;/' CompUtil.java +#sed -i -e 's/edu.mit.csail.sdg.parser.CompModule.Open/ca.uwaterloo.watform.parser.DCModule.Open/' CompUtil.java + +# because resolveAll is done later for Dash processing +sed -i -e 's/return CompModule.resolveAll(rep == null ? A4Reporter.NOP : rep, root);/\/\/return CompModule.resolveAll(rep == null ? A4Reporter.NOP : rep, root);\n return root; \/\/DASH: resolveAll is done later/' CompUtil.java + +# careful to have space after this so we don't catch import edu.mit.csail.sdg.parser.Compodule.Open; +sed -i -e 's/CompModule /DashModule /g' CompUtil.java + +# one place CompModule is used other than in types +sed -it -e 's/return new CompModule(null, "", "");/return new DashModule(null, "", "");/' CompUtil.java + +sed -i -e 's/CompUtil/DashUtil/g' CompUtil.java + +sed -i -e 's/CompParser/DashParser/g' CompUtil.java + +sed -i -e 's/parseRecursively/parseRecursivelyDash/' CompUtil.java + +sed -i -e 's/parseEverything_fromFile/parseEverything_fromFileDash/' CompUtil.java + +sed -i -e 's/parseEverything_fromString/parseEverything_fromStringDash/' CompUtil.java + +{ echo "$msg"; cat CompUtil.java; } > DashUtil.java + +rm CompUtil.java + + + +rm *.java-e + +# make DashModule an extension of DashCompModule + + diff --git a/pbuild.sh b/pbuild.sh new file mode 100755 index 000000000..82b4bc80a --- /dev/null +++ b/pbuild.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# tmp while working on grammar/parser + +cd org.alloytools.alloy.dash/parser +./install-alloy-files.sh +cd ../.. +./gradlew build \ No newline at end of file From c8747ca8357fed59e22181c130dfdacae20b340f Mon Sep 17 00:00:00 2001 From: Peter Kriens Date: Wed, 1 Mar 2023 20:29:42 +0100 Subject: [PATCH 022/129] Remove the unused EXH and PART tokens --- org.alloytools.alloy.core/parser/Alloy.cup | 12 ------------ org.alloytools.alloy.core/parser/Alloy.lex | 4 ---- .../java/edu/mit/csail/sdg/parser/CompFilter.java | 4 +--- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/org.alloytools.alloy.core/parser/Alloy.cup b/org.alloytools.alloy.core/parser/Alloy.cup index a2796b4f7..12e02e32b 100644 --- a/org.alloytools.alloy.core/parser/Alloy.cup +++ b/org.alloytools.alloy.core/parser/Alloy.cup @@ -165,7 +165,6 @@ parser code {: ch.put(CompSym.ENUM, "enum"); ch.put(CompSym.EQUALS, "="); ch.put(CompSym.EXACTLY, "exactly"); - ch.put(CompSym.EXH, "exh"); ch.put(CompSym.EXPECT, "expect"); ch.put(CompSym.EXTENDS, "extends"); ch.put(CompSym.FACT, "fact"); @@ -203,7 +202,6 @@ parser code {: ch.put(CompSym.ONE, "one"); ch.put(CompSym.OPEN, "open"); ch.put(CompSym.OR, "||"); - ch.put(CompSym.PART, "part"); ch.put(CompSym.PLUS, "+"); ch.put(CompSym.PLUSPLUS, "++"); ch.put(CompSym.PRED, "pred"); @@ -447,7 +445,6 @@ terminal Pos ELSE; // else terminal Pos ENUM; // enum terminal Pos EQUALS; // = == terminal Pos EXACTLY; // exactly -terminal Pos EXH; // exh exhaustive terminal Pos EXPECT; // expect terminal Pos EXTENDS; // extends terminal Pos FACT; // fact @@ -485,7 +482,6 @@ terminal Pos ONE2; // one // The filter enables us to di terminal Pos ONE; // one // The filter enables us to disambiguate terminal Pos OPEN; // open terminal Pos OR; // || or -terminal Pos PART; // part partition terminal Pos PLUS; // + terminal Pos PLUSPLUS; // ++ terminal Pos PRED; // pred @@ -826,8 +822,6 @@ Namex ::= Namex:a COMMA Name:b {: nod(b); a.add(b); RESULT= Namex ::= Namex:a COMMA EXACTLY Name:b {: nod(b); a.add(null); a.add(b); RESULT=a; :}; // [electrum] additional parameter for variable declarations (for fields) -Decla ::= PART:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; -Decla ::= EXH:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; Decla ::= DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(null, k, null, null, a, mult(b)); :}; Decla ::= PRIVATE:p DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(p, k, null, null, a, mult(b)); :}; Decla ::= PRIVATE:p Names:a COLON Expr:b {: RESULT=new Decl(p, null, null, null, a, mult(b)); :}; @@ -838,8 +832,6 @@ Decla ::= VAR:v PRIVATE:p DISJ:k Names:a COLON Expr:b {: RESULT Decla ::= VAR:v PRIVATE:p Names:a COLON Expr:b {: RESULT=new Decl(p, null, null, v, a, mult(b)); :}; Decla ::= VAR:v Names:a COLON Expr:b {: RESULT=new Decl(null, null, null, v, a, mult(b)); :}; -Decla ::= PART:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; -Decla ::= EXH:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; Decla ::= DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, k, d, null, a, mult(b)); :}; Decla ::= PRIVATE:p DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, k, d, null, a, mult(b)); :}; Decla ::= PRIVATE:p Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, null, d, null, a, mult(b)); :}; @@ -852,15 +844,11 @@ Decla ::= VAR:v Names:a COLON DISJ:d Expr:b {: RESULT Declb ::= Decla:x {: RESULT=x; :}; -Declb ::= PART:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; -Declb ::= EXH:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; Declb ::= DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; Declb ::= PRIVATE DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; Declb ::= PRIVATE:p Names:a EQUALS Expr:b {: RESULT=new Decl(p, null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; Declb ::= Names:a EQUALS Expr:b {: RESULT=new Decl(null, null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; -Declb ::= PART:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; -Declb ::= EXH:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; Declb ::= DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; Declb ::= PRIVATE DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; Declb ::= PRIVATE Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; diff --git a/org.alloytools.alloy.core/parser/Alloy.lex b/org.alloytools.alloy.core/parser/Alloy.lex index 4ec7c4cac..f0f8f2a65 100644 --- a/org.alloytools.alloy.core/parser/Alloy.lex +++ b/org.alloytools.alloy.core/parser/Alloy.lex @@ -186,8 +186,6 @@ import java_cup.runtime.*; "else" { return alloy_sym(yytext(), CompSym.ELSE );} "enum" { return alloy_sym(yytext(), CompSym.ENUM );} "exactly" { return alloy_sym(yytext(), CompSym.EXACTLY );} -"exhaustive" { return alloy_sym(yytext(), CompSym.EXH );} -"exh" { return alloy_sym(yytext(), CompSym.EXH );} "expect" { return alloy_sym(yytext(), CompSym.EXPECT );} "extends" { return alloy_sym(yytext(), CompSym.EXTENDS );} "fact" { return alloy_sym(yytext(), CompSym.FACT );} @@ -208,8 +206,6 @@ import java_cup.runtime.*; "one" { return alloy_sym(yytext(), CompSym.ONE );} "open" { return alloy_sym(yytext(), CompSym.OPEN );} "or" { return alloy_sym(yytext(), CompSym.OR );} -"partition" { return alloy_sym(yytext(), CompSym.PART );} -"part" { return alloy_sym(yytext(), CompSym.PART );} "pred" { return alloy_sym(yytext(), CompSym.PRED );} "private" { return alloy_sym(yytext(), CompSym.PRIVATE );} "run" { return alloy_sym(yytext(), CompSym.RUN );} diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompFilter.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompFilter.java index 44e1491df..cfbab9411 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompFilter.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompFilter.java @@ -27,7 +27,6 @@ import static edu.mit.csail.sdg.parser.CompSym.DISJ; import static edu.mit.csail.sdg.parser.CompSym.EOF; import static edu.mit.csail.sdg.parser.CompSym.EQUALS; -import static edu.mit.csail.sdg.parser.CompSym.EXH; import static edu.mit.csail.sdg.parser.CompSym.FUN; import static edu.mit.csail.sdg.parser.CompSym.GT; import static edu.mit.csail.sdg.parser.CompSym.GTE; @@ -70,7 +69,6 @@ import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_LONE; import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_ONE; import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_SOME; -import static edu.mit.csail.sdg.parser.CompSym.PART; import static edu.mit.csail.sdg.parser.CompSym.PRED; import static edu.mit.csail.sdg.parser.CompSym.PRIVATE; import static edu.mit.csail.sdg.parser.CompSym.RBRACE; @@ -191,7 +189,7 @@ else if (a.sym == SOME) temp.add(b = myread()); if (b.sym == PRIVATE) temp.add(b = myread()); - if (b.sym == DISJ || b.sym == PART || b.sym == EXH) + if (b.sym == DISJ) temp.add(b = myread()); while (b.sym == ID) { temp.add(b = myread()); From d1b06bcc3022871fbe89ea317bfbe1535fa1cf23 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 17 Mar 2023 10:51:40 -0400 Subject: [PATCH 023/129] in process but need to sync with master --- cnf/central.mvn | 1 + .../ca/uwaterloo/watform/dash4whole/Dash.java | 2 +- org.alloytools.alloy.core/bnd.bnd | 3 +- .../main/java/edu/mit/csail/sdg/ast/Decl.java | 2 +- .../src/main/resources/models/util/traces.als | 2 +- org.alloytools.alloy.dash/bnd.bnd | 5 +- .../parser/Dash-cup-grammar.txt | 36 +- .../parser/Dash-cup-imports.txt | 2 + org.alloytools.alloy.dash/parser/Dash.cup | 38 +- .../alloyasthelper/AlloyDeclHelper.java | 25 - .../watform/alloyasthelper/DeclExt.java | 52 ++ .../watform/alloyasthelper/ExprExt.old | 39 ++ .../{AlloyExprHelper.java => ExprHelper.java} | 56 +- .../watform/alloyasthelper/ExprToString.java | 373 +++++++++++++ .../ca/uwaterloo/watform/ast/DashAction.java | 1 + .../watform/ast/DashBufferDecls.java | 3 +- .../uwaterloo/watform/ast/DashCondition.java | 1 + .../java/ca/uwaterloo/watform/ast/DashDo.java | 1 + .../uwaterloo/watform/ast/DashEventDecls.java | 1 + .../ca/uwaterloo/watform/ast/DashExpr.java | 3 + .../ca/uwaterloo/watform/ast/DashFrom.java | 1 + .../ca/uwaterloo/watform/ast/DashGoto.java | 1 + .../ca/uwaterloo/watform/ast/DashInit.java | 7 +- .../ca/uwaterloo/watform/ast/DashInv.java | 5 +- .../java/ca/uwaterloo/watform/ast/DashOn.java | 1 + .../ca/uwaterloo/watform/ast/DashSend.java | 1 + .../ca/uwaterloo/watform/ast/DashState.java | 312 ++++++++--- .../ca/uwaterloo/watform/ast/DashTrans.java | 20 +- .../uwaterloo/watform/ast/DashVarDecls.java | 1 + .../ca/uwaterloo/watform/ast/DashWhen.java | 1 + .../ca/uwaterloo/watform/core/DashErrors.java | 92 ++++ .../ca/uwaterloo/watform/core/DashFQN.java | 81 +++ .../uwaterloo/watform/core/DashSituation.java | 6 + .../uwaterloo/watform/core/DashStrings.java | 59 ++- .../uwaterloo/watform/core/DashUtilFcns.java | 59 +++ .../watform/dashtoalloy/DashToAlloy.java | 492 ++++++++++++++++++ .../watform/mainfunctions/MainFunctions.java | 25 +- .../watform/parser/CompModuleHelper.java | 169 ++++-- .../uwaterloo/watform/parser/DashFilter.java | 2 +- .../uwaterloo/watform/parser/DashModule.java | 348 +++++++++---- .../ca/uwaterloo/watform/parser/DashUtil.java | 4 +- .../uwaterloo/watform/parser/StateTable.java | 326 ++++++++++++ .../uwaterloo/watform/parser/TransTable.java | 131 +++++ .../watform/parser/install-alloy-files.sh | 2 +- .../alloy/dash/DashCoreFQNTests.java | 31 ++ pbuild.sh | 7 + 46 files changed, 2516 insertions(+), 314 deletions(-) delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyDeclHelper.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprExt.old rename org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/{AlloyExprHelper.java => ExprHelper.java} (72%) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java create mode 100644 org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java diff --git a/cnf/central.mvn b/cnf/central.mvn index 5a3e7c377..f3fa8700b 100644 --- a/cnf/central.mvn +++ b/cnf/central.mvn @@ -27,3 +27,4 @@ biz.aQute:biz.aQute.wrapper.junit:4.13.1 biz.aQute.bnd:aQute.libg:6.1.0 org.osgi:org.osgi.annotation.bundle:1.1.1 org.osgi:osgi.annotation:8.0.1 +com.io7m.jpplib:io7m-jpplib-core:0.7.4 diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index 123c862b9..7e3907e05 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -124,7 +124,7 @@ public static void main(String args[]) throws Exception { } } else { try { - alloymodule = MainFunctions.translateToAlloy(d, rep); + alloymodule = MainFunctions.translate(d, rep); } catch (Exception e) { System.err.println(e); System.exit(1); diff --git a/org.alloytools.alloy.core/bnd.bnd b/org.alloytools.alloy.core/bnd.bnd index 2876a0084..164412e55 100644 --- a/org.alloytools.alloy.core/bnd.bnd +++ b/org.alloytools.alloy.core/bnd.bnd @@ -28,7 +28,8 @@ Export-Package: \ edu.mit.csail.sdg.translator,\ org.alloytools.util.table,\ org.alloytools.alloy.core, \ - org.alloytools.alloy.core.util + org.alloytools.alloy.core.util, \ + com.io7m.jpplib.core, \ Private-Package: \ java_cup.runtime diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Decl.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Decl.java index 37c5b1d32..544a0148c 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Decl.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Decl.java @@ -29,7 +29,7 @@ * variable). */ -public final class Decl { +public class Decl { /** * If nonnull, then this decl is private (and this.isPrivate is the location of diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/traces.als b/org.alloytools.alloy.core/src/main/resources/models/util/traces.als index a5e8ccab2..1a2f20636 100644 --- a/org.alloytools.alloy.core/src/main/resources/models/util/traces.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/traces.als @@ -1,5 +1,5 @@ /* - Src: ??? + Src: Bounded Model Checking of Temporal Formulas with Alloy by Alcino Cunha Modified to change s' to s_next for Alloy 6 */ module util/traces[exactly elem] diff --git a/org.alloytools.alloy.dash/bnd.bnd b/org.alloytools.alloy.dash/bnd.bnd index fb25c92bd..99d17893d 100644 --- a/org.alloytools.alloy.dash/bnd.bnd +++ b/org.alloytools.alloy.dash/bnd.bnd @@ -8,8 +8,7 @@ org.alloytools:pardinus.core;version='1.3.0',\ org.alloytools:pardinus.nativesat;version='1.3.0',\ org.eclipse.jdt.annotation,\ - org.alloytools.alloy.core;version=latest,\ - com.io7m.jpplib.io7m-jpplib-core;version=0.7.4,\ + org.alloytools.alloy.core;version=latest, -testpath: \ biz.aQute.wrapper.junit, \ @@ -25,7 +24,7 @@ Export-Package: \ ca.uwaterloo.watform.parser,\ ca.uwaterloo.watform.dashtoalloy,\ ca.uwaterloo.watform.mainfunctions,\ - de.uka.ilkd.pp,\ + com.io7m.jpplib.core, \ Private-Package: \ java_cup.runtime diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt index 0cf322f68..56ccdf13b 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -11,9 +11,15 @@ Spec ::= Spec StateRoot:o ; // Root State Declaration StateRoot ::= STATE:o Name:n LBRACE RBRACE:e // empty state {: + // first line in file is line 1 parser.dashmodule.rootStartLine = o.y; parser.dashmodule.rootEndLine = e.y; - parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT)); + if (!parser.dashmodule.hasRoot()) + // a basic state + parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT)); + else + DashErrors.onlyOneState(o); + :}; StateRoot ::= STATE:o Name:n LBRACE StateItemList:c RBRACE:e {: @@ -73,12 +79,21 @@ StateItem ::= ENV:o Names:n COLON Expr:b RESULT = new DashVarDecls(o, ll, b, DashStrings.IntEnvKind.ENV); :}; //buffer decls +//we have to know the number of buffers for the open statements, +//which have to be loaded at the beginning of parsing +//Soln: parse twice +//first time stores buffer names, element types in DashSituation +//second time includes the appropriate opens (based on values in DashSituation) +//when do new DashModule() before start parsing +//collection here is the same regardless of parsing pass StateItem ::= Names:n COLON:o BUF LBRACKET Name:m RBRACKET {: ArrayList ll = new ArrayList(); for (ExprVar x: n) { ll.add(x.label); - DashSituation.bufferElements.add(x.label); + // it will do this the same way both passes through parsing + DashSituation.bufferElements.add(m.label); + DashSituation.bufferNames.add(x.label); } RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.INT); :}; @@ -87,7 +102,9 @@ StateItem ::= Names:n COLON:o BUF LBRACKET SIGINT RBRACKET ArrayList ll = new ArrayList(); for (ExprVar x: n) { ll.add(x.label); - DashSituation.bufferElements.add(x.label); + // it will do this the same way both passes through parsing + DashSituation.bufferElements.add(DashStrings.intName); + DashSituation.bufferNames.add(x.label); } RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT); :}; @@ -96,17 +113,20 @@ StateItem ::= ENV:o Names:n COLON BUF LBRACKET Name:m RBRACKET ArrayList ll = new ArrayList(); for (ExprVar x: n) { ll.add(x.label); - DashSituation.bufferElements.add(x.label); + // it will do this the same way both passes through parsing + DashSituation.bufferElements.add(m.label); + DashSituation.bufferNames.add(x.label); } RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV); :}; - StateItem ::= ENV:o Names:n COLON BUF LBRACKET SIGINT RBRACKET {: ArrayList ll = new ArrayList(); for (ExprVar x: n) { ll.add(x.label); - DashSituation.bufferElements.add(x.label); + // it will do this the same way both passes through parsing + DashSituation.bufferElements.add(DashStrings.intName); + DashSituation.bufferNames.add(x.label); } RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV); :}; @@ -168,12 +188,12 @@ TransItem ::= SEND:o Expr:v // note PRIME is a special token in grammar and we want to support v' BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e {: - if (b.size() > 1) throw new ErrorSyntax(o,"Two many args to reference to sibling state"); + if (b.size() > 1) DashErrors.crossRefMoreThanOneArg(o,e.label); RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label)); :}; BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e PRIME {: - if (b.size() > 1) throw new ErrorSyntax(o,"Two many args to reference to sibling state"); + if (b.size() > 1) DashErrors.crossRefMoreThanOneArg(o,e.label); // probably have to fix PRIME here later when turning to Alloy RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label + "'")); :}; diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt b/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt index 924616a1d..72defeb8f 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt @@ -1,4 +1,6 @@ import java.util.Arrays; +import edu.mit.csail.sdg.alloy4.Pair; + import edu.mit.csail.sdg.parser.CompModule; import edu.mit.csail.sdg.parser.MarkdownHandler; diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index 62c6f923e..9a927d7bf 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -66,6 +66,8 @@ import edu.mit.csail.sdg.ast.ExprVar; import edu.mit.csail.sdg.ast.Sig; import edu.mit.csail.sdg.ast.Sig.PrimSig; import java.util.Arrays; +import edu.mit.csail.sdg.alloy4.Pair; + import edu.mit.csail.sdg.parser.CompModule; import edu.mit.csail.sdg.parser.MarkdownHandler; @@ -1273,9 +1275,15 @@ Spec ::= Spec StateRoot:o ; // Root State Declaration StateRoot ::= STATE:o Name:n LBRACE RBRACE:e // empty state {: + // first line in file is line 1 parser.dashmodule.rootStartLine = o.y; parser.dashmodule.rootEndLine = e.y; - parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT)); + if (!parser.dashmodule.hasRoot()) + // a basic state + parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT)); + else + DashErrors.onlyOneState(o); + :}; StateRoot ::= STATE:o Name:n LBRACE StateItemList:c RBRACE:e {: @@ -1335,12 +1343,21 @@ StateItem ::= ENV:o Names:n COLON Expr:b RESULT = new DashVarDecls(o, ll, b, DashStrings.IntEnvKind.ENV); :}; //buffer decls +//we have to know the number of buffers for the open statements, +//which have to be loaded at the beginning of parsing +//Soln: parse twice +//first time stores buffer names, element types in DashSituation +//second time includes the appropriate opens (based on values in DashSituation) +//when do new DashModule() before start parsing +//collection here is the same regardless of parsing pass StateItem ::= Names:n COLON:o BUF LBRACKET Name:m RBRACKET {: ArrayList ll = new ArrayList(); for (ExprVar x: n) { ll.add(x.label); - DashSituation.bufferElements.add(x.label); + // it will do this the same way both passes through parsing + DashSituation.bufferElements.add(m.label); + DashSituation.bufferNames.add(x.label); } RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.INT); :}; @@ -1349,7 +1366,9 @@ StateItem ::= Names:n COLON:o BUF LBRACKET SIGINT RBRACKET ArrayList ll = new ArrayList(); for (ExprVar x: n) { ll.add(x.label); - DashSituation.bufferElements.add(x.label); + // it will do this the same way both passes through parsing + DashSituation.bufferElements.add(DashStrings.intName); + DashSituation.bufferNames.add(x.label); } RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT); :}; @@ -1358,17 +1377,20 @@ StateItem ::= ENV:o Names:n COLON BUF LBRACKET Name:m RBRACKET ArrayList ll = new ArrayList(); for (ExprVar x: n) { ll.add(x.label); - DashSituation.bufferElements.add(x.label); + // it will do this the same way both passes through parsing + DashSituation.bufferElements.add(m.label); + DashSituation.bufferNames.add(x.label); } RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV); :}; - StateItem ::= ENV:o Names:n COLON BUF LBRACKET SIGINT RBRACKET {: ArrayList ll = new ArrayList(); for (ExprVar x: n) { ll.add(x.label); - DashSituation.bufferElements.add(x.label); + // it will do this the same way both passes through parsing + DashSituation.bufferElements.add(DashStrings.intName); + DashSituation.bufferNames.add(x.label); } RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV); :}; @@ -1430,12 +1452,12 @@ TransItem ::= SEND:o Expr:v // note PRIME is a special token in grammar and we want to support v' BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e {: - if (b.size() > 1) throw new ErrorSyntax(o,"Two many args to reference to sibling state"); + if (b.size() > 1) DashErrors.crossRefMoreThanOneArg(o,e.label); RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label)); :}; BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e PRIME {: - if (b.size() > 1) throw new ErrorSyntax(o,"Two many args to reference to sibling state"); + if (b.size() > 1) DashErrors.crossRefMoreThanOneArg(o,e.label); // probably have to fix PRIME here later when turning to Alloy RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label + "'")); :}; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyDeclHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyDeclHelper.java deleted file mode 100644 index b5cdb8856..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyDeclHelper.java +++ /dev/null @@ -1,25 +0,0 @@ -package ca.uwaterloo.watform.alloyasthelper; - -import java.util.Arrays; -import java.util.ArrayList; - -import edu.mit.csail.sdg.ast.Decl; -import edu.mit.csail.sdg.ast.Expr; -import edu.mit.csail.sdg.ast.ExprVar; - -import ca.uwaterloo.watform.alloyasthelper.AlloyExprHelper; - -public class AlloyDeclHelper { - - public static Decl createDecl(ExprVar v, Expr e) { - // not sure if mult is needed on last arg - return new Decl(null, null, null, null, new ArrayList<>(Arrays.asList(v)) , e); - } - public static Decl createOneDecl(String v, String typ) { - return createDecl(AlloyExprHelper.createVar(v), AlloyExprHelper.createOne(AlloyExprHelper.createVar(typ))); - } - public static Decl createSetDecl(String v, String typ) { - return createDecl(AlloyExprHelper.createVar(v), AlloyExprHelper.createSet(AlloyExprHelper.createVar(typ))); - } - -} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java new file mode 100644 index 000000000..880e6a352 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java @@ -0,0 +1,52 @@ +package ca.uwaterloo.watform.alloyasthelper; + +import java.util.*; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.StringJoiner; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprVar; + +import ca.uwaterloo.watform.core.DashErrors; + +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; + +public class DeclExt extends Decl { + + public DeclExt(ExprVar v, Expr e) { + super(null, null, null, null, new ArrayList<>(Arrays.asList(v)) , e); + } + public String toString() { + // Decl does not have a toString() + String x = new String(); + StringJoiner sj = new StringJoiner(", "); + names.forEach(n -> sj.add(n.toString())); + x += sj.toString(); + x += " : "; + x += expr.toString(); + return x; + } + + public DeclExt(String v, Expr e) { + // not sure if mult is needed on last arg + super(null, null, null, null, new ArrayList<>(Arrays.asList(ExprHelper.createVar(v))) , e); + } + // default is "one" + public DeclExt(String v, String typ) { + super(null, null, null, null, new ArrayList<>(Arrays.asList(ExprHelper.createVar(v))), ExprHelper.createOne(ExprHelper.createVar(typ))); + } + public static DeclExt newOneDeclExt(String v, String typ) { + return new DeclExt(v, ExprHelper.createOne(ExprHelper.createVar(typ))); + } + public static DeclExt newOneDeclExt(String v, Expr typ) { + return new DeclExt(v, typ); + } + public static DeclExt newSetDeclExt(String v, String typ) { + return new DeclExt(v, ExprHelper.createSet(ExprHelper.createVar(typ))); + } + public static DeclExt newSetDeclExt(String v, Expr typ) { + return new DeclExt(v, typ); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprExt.old b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprExt.old new file mode 100644 index 000000000..1114403ef --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprExt.old @@ -0,0 +1,39 @@ +package ca.uwaterloo.watform.alloyasthelper; + +import java.util.*; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.StringJoiner; + + +import edu.mit.csail.sdg.ast.Expr; + + +import ca.uwaterloo.watform.core.DashErrors; + +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; + +// this is necessary to make a better toString method for +// Joins where brackets are printed +// we will have to use this within any expressions in actions or guards or event parameters +public class ExprExt extends Expr { + + public Expr exp; + + public ExprExt(Expr e) { + this.exp = e; + } + + public String toString() { + if (this.exp isinstance ExprJoin) { + s = new String(); + s += this.exp.left.toString(); + s += " . "; + if (this.exp.right isinstance ExprJoin) { + s += "( "; + s += this.exp.right.toString(); + s += " )"; + } + } else return e.toString(); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java similarity index 72% rename from org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyExprHelper.java rename to org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 6ffdb9208..76ad0375a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/AlloyExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -1,6 +1,7 @@ package ca.uwaterloo.watform.alloyasthelper; import java.util.ArrayList; +import java.util.List; import java.util.Collections; import edu.mit.csail.sdg.alloy4.Pos; @@ -16,17 +17,28 @@ import edu.mit.csail.sdg.ast.ExprVar; import edu.mit.csail.sdg.ast.ExprBinary; -// Expr is not final so we can extend it -public class AlloyExprHelper { +import ca.uwaterloo.watform.core.DashStrings; + +// these are all static +// don't want to make them an extension +// because then would have to put them in all different classes + + +public class ExprHelper { + + // useful in development + public static Expr createNullExpr() { + return createEquals(createTrue(),createTrue()); + } public static ExprVar createTrue() { - return ExprVar.make(Pos.UNKNOWN, "True"); + return ExprVar.make(Pos.UNKNOWN, DashStrings.trueName); } public static ExprVar createVar(String v) { return ExprVar.make(Pos.UNKNOWN, v); } - public static ArrayList createVarList(ArrayList vList) { - ArrayList retList = new ArrayList(); + public static List createVarList(List vList) { + List retList = new ArrayList(); for (String v: vList) { retList.add(createVar(v)); } @@ -41,10 +53,10 @@ public static Expr createUnaryExpr(ExprUnary.Op op, Expr sub) { return (ExprUnary) op.make(Pos.UNKNOWN, sub); } // dunno why this one is different in Alloy code - public static Expr createExprList(ExprList.Op op, ArrayList args) { + public static Expr createExprList(ExprList.Op op, List args) { return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, op, args); } - public static Expr createExprQt(ExprQt.Op op, ArrayList decls, Expr expr) { + public static Expr createExprQt(ExprQt.Op op, List decls, Expr expr) { return op.make(Pos.UNKNOWN, Pos.UNKNOWN, decls,expr); } @@ -58,16 +70,17 @@ public static Expr createSet(Expr sub) { public static ExprBinary createJoin(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.JOIN.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static Expr createJoinList(ArrayList elist) { + public static Expr createJoinList(List elist) { Expr ret = null; assert(elist!=null); + Collections.reverse(elist); ret = elist.get(0); - for (Expr el: elist.subList(1,elist.size()-1)) { + for (Expr el: elist.subList(1,elist.size())) { ret = createJoin(ret,el); } return ret; } - public static Expr createPlusList(ArrayList elist) { + public static Expr createPlusList(List elist) { Expr ret = null; assert(elist!=null); ret = elist.get(0); @@ -85,13 +98,13 @@ public static ExprBinary createNotEquals(Expr left, Expr right) { public static ExprBinary createAnd(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static Expr createAnd(ArrayList args) { + public static Expr createAnd(List args) { return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); } public static ExprBinary createOr(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.OR.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static Expr createOr(ArrayList args) { + public static Expr createOr(List args) { return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); } public static ExprBinary createArrow(Expr left,Expr right) { @@ -105,7 +118,7 @@ public static ExprBinary createIn(Expr left,Expr right) { } // {x,y,z} // returns x -> (y -> z) - public static Expr createArrowList(ArrayList eList) { + public static Expr createArrowList(List eList) { assert(eList != null); Collections.reverse(eList); Expr o = createVar(eList.get(0)); @@ -120,10 +133,10 @@ public static ExprITE createITE(Expr cond, Expr impliesExpr, Expr elseExpr) { return (ExprITE) ExprITE.make(Pos.UNKNOWN, cond, impliesExpr, elseExpr); } - public static ExprQt createAll(ArrayList decls, Expr expr) { + public static ExprQt createAll(List decls, Expr expr) { return (ExprQt) ExprQt.Op.ALL.make(Pos.UNKNOWN, Pos.UNKNOWN, decls, expr); } - public static ExprQt createSome(ArrayList decls, Expr expr) { + public static ExprQt createSome(List decls, Expr expr) { return (ExprQt) ExprQt.Op.SOME.make(Pos.UNKNOWN, Pos.UNKNOWN, decls, expr); } @@ -131,4 +144,17 @@ public static ExprUnary createAlways(Expr expr) { return (ExprUnary) ExprUnary.Op.ALWAYS.make(Pos.UNKNOWN, expr); } + public static Expr createPredCall(String name, List elist) { + // using ExprCall.make is overkill + // b/c it required the entire function definition to be passed + // as an argument + // joins are equivalent but not as nice to look at :-) + // order of joins is tricky + Expr o = createVar(name); + for (Expr e:elist) { + o = createJoin(e,o); + } + return o; + } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java new file mode 100644 index 000000000..a9d205ec8 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -0,0 +1,373 @@ +package ca.uwaterloo.watform.alloyasthelper; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.StringJoiner; + +import com.io7m.jpplib.core.Layouter; +import com.io7m.jpplib.core.Backend; + +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.ast.*; +import edu.mit.csail.sdg.ast.Sig.Field; +import edu.mit.csail.sdg.ast.Sig.PrimSig; + +import ca.uwaterloo.watform.core.DashErrors; + +public class ExprToString { + + int indent; + int lineWidth; + Layouter out; + Boolean isAfterAlloyResolveAll; + + public ExprToString(boolean isAfterAlloyResolveAll) { + this.isAfterAlloyResolveAll = isAfterAlloyResolveAll; + this.indent = 4; + this.lineWidth = 120; + Backend back = new Backend(lineWidth); + this.out = new Layouter(back, indent); + } + + public String toString(Expr e) throws IOException { + out.beginC(0); + ExprToOut(e); + out.end().close(); + return back.getString(); + } + private void ExprToOut(Expr expr) { + /* + if (expr instanceof ExprBad){ + ExprBadToOut((ExprBad)expr); + } else if (expr instanceof ExprBadCall){ + ExprBadCallToOut((ExprBadCall)expr); + } else if (expr instanceof ExprBadJoin){ + ExprBadJoinToOut((ExprBadJoin)expr); + } else + */ + if (expr instanceof ExprBinary){ + ExprBinaryToOut((ExprBinary)expr); + } else if (expr instanceof ExprCall){ + ExprCallToOut((ExprCall)expr); + } else if (expr instanceof ExprChoice){ + ExprChoiceToOut((ExprChoice)expr); + } else if (expr instanceof ExprConstant){ + ExprConstantToOut((ExprConstant)expr); + } else if (expr instanceof ExprITE){ + ExprITEToOut((ExprITE)expr); + } else if (expr instanceof ExprLet){ + ExprLetToOut((ExprLet)expr); + } else if (expr instanceof ExprList){ + ExprListToOut((ExprList)expr); + } else if (expr instanceof ExprQt){ + ExprQtToOut((ExprQt)expr); + } else if (expr instanceof ExprUnary){ + ExprUnaryToOut((ExprUnary)expr); + } else if (expr instanceof ExprVar){ + ExprVarToOut((ExprVar)expr); + } else if (expr instanceof Sig){ + SigToOut((Sig)expr); + } else if (expr instanceof Field){ + FieldToOut((Field)expr); + } else DashErrors.missingExpr("ExprToOut "); + } + /* + private void ExprBad(ExprBad expr) { + StringBuilder tempOut = new StringBuilder(); + expr.toString(tempOut, -1); + out.print(tempOut.toString()); + } + + private void ExprBadCall(ExprBadCall expr) { + out.print(cleanLabel(expr.fun.label)).print('[').beginCInd(); + for (int i = 0; i < expr.args.size(); i++) { + if (i > 0) + out.print(", "); + Expr(expr.args.get(i)); + } + out.end().print(']'); + } + + private void ExprBadJoin(ExprBadJoin expr) { + Expr(expr.left); + out.print('.'); + Expr(expr.right); + } + */ + private Boolean isBinary(Expr e) { + return (e instanceof ExprBinary); + } + private void ExprBinaryToOut(ExprBinary expr) { + if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { + out.print("seq "); + ExprToOut(expr.right); + } + else if (expr.op == ExprBinary.Op.JOIN) + ExprBinaryJoinToOut(expr); + else if (expr.op == ExprBinary.Op.IMPLIES) { + ExprToOut(expr.left); + out.print(" => ").print("{ "); + ExprToOut(expr.right); + out.print(" } "); + } + // This used to ensure that binary expressions have proper braces around them + else if ( isBinary(expr.right) || isBinary(expr.left) ) { + if ( isBinary(expr.left) && !(exprOp(expr.left) == exprOp(expr)) && !(exprOp(expr.left) == ExprBinary.Op.JOIN)) { + out.print('{').print(' '); + ExprToOut(expr.left); + out.print(' ').print("}").print(' ').print(expr.op).print(' '); + } else { + ExprToOut(expr.left); + out.print(' ').print(expr.op).print(' '); + } + if (isBinary(expr.right) && !(exprOp(expr.right) == exprOp(expr)) && !(exprOp(expr.right) == ExprBinary.Op.JOIN)){ + out.print('{').print(' '); + ExprToOut(expr.right); + out.print(' ').print("}"); + } else { + ExprToOut(expr.right); + } + } + else { + ExprToOut(expr.left); + out.print(' ').print(expr.op).print(' '); + ExprToOut(expr.right); + } + } + + private void ExprBinaryJoinToOut(ExprBinary expr) { + // The Alloy resolve dot joins (this) to a variable reference in a variable. We should not bring the ("this") + // We also do not print (Snapshot <: ...) + boolean clean = (expr.left.toString().equals("this") && isAfterAlloyResolveAll); + + if (expr.right.toString().charAt(0) == '(') { + if (!clean) { + ExprToOut(expr.left); + out.print(expr.op); + } + ExprToOut(expr.right); + } + else { + if (!clean) { + ExprToOut(expr.left); + out.print(expr.op).print(' ').print('('); + } + ExprToOut(expr.right); + if (!clean) { + out.print(")"); + } + } + } + + private void ExprCallToOut(ExprCall expr) { + out.print(cleanLabel(expr.fun.label)); + if (expr.args.size() == 0) + return; + out.print('[').beginCInd(); + for (int i = 0; i < expr.args.size(); i++) { + if (i > 0) + out.print(", "); + ExprToOut(expr.args.get(i)); + } + out.print(']').end(); + } + + private void ExprChoiceToOut(ExprChoice expr) { + out.print("<"); + for (Expr e : expr.choices) { + ExprToOut(e); + out.print(";"); + } + out.print(">"); + } + + private void ExprConstantToOut(ExprConstant expr) { + if (expr.op == ExprConstant.Op.NUMBER) + out.print(expr.num); + else if (expr.op == ExprConstant.Op.STRING) + out.print(expr.string); + else + out.print(expr.op); + } + + private void ExprITEToOut(ExprITE expr) { + out.print('(').beginCInd(); + ExprToOut(expr.cond); + out.print(" => ").brk(1,0); + ExprToOut(expr.left); + out.brk(1,-indent).print(" else ").print("{").brk(1,0); + ExprToOut(expr.right); + out.print(" }"); + out.brk(1,-indent).end().print(')'); + } + + private void ExprLetToOut(ExprLet expr) { + out.print("(let ").print(cleanLabel(expr.var.label)).print("= ").print(expr.toString()).print(" | "); + ExprToOut(expr.sub); + out.print(')'); + } + + private void ExprListToOut(ExprList expr) { + if (expr.op == ExprList.Op.AND ) { + String op = " and"; + for (int i = 0; i < expr.args.size(); i++) { + if (i > 0) + out.print(op).brk(1,0); + ExprToOut(expr.args.get(i)); + } + } + else if (expr.op == ExprList.Op.OR) { + String op = " or"; + out.print("{ "); + for (int i = 0; i < expr.args.size(); i++) { + if (i > 0) + out.print(op).brk(1,0); + ExprToOut(expr.args.get(i)); + } + out.print(" }"); + } + else { + out.print(expr.op).print("[").beginCInd().brk(1,0); + for (int i = 0; i < expr.args.size(); i++) { + if (i > 0) + out.print(",").brk(1,0); + ExprToOut(expr.args.get(i)); + } + out.brk(1,-indent).end().print(']'); + } + } + + private void ExprQtToOut(ExprQt expr) { + boolean first = true; + if (expr.op != ExprQt.Op.COMPREHENSION) + out.print('(').print(expr.op).print(' ').beginCInd(); + else + out.print('{').beginCInd(); + DeclsToOut(expr.decls); + if (expr.op != ExprQt.Op.COMPREHENSION || !(expr.sub instanceof ExprConstant) || ((ExprConstant) expr.sub).op != ExprConstant.Op.TRUE) { + out.print(" | "); + ExprToOut(expr.sub); + } + if (expr.op != ExprQt.Op.COMPREHENSION) + out.end().print(')'); + else + out.end().print('}'); + } + + private void ExprUnaryToOut(ExprUnary expr) { + switch (expr.op) { + case SOMEOF : + out.print("some "); + break; + case LONEOF : + out.print("lone "); + break; + case ONEOF : + out.print("one "); + break; + case SETOF : + out.print("set "); + break; + case EXACTLYOF : + out.print("exactly "); + break; + case CAST2INT : + out.print("int["); + ExprToOut(expr.sub); + out.print(']'); + return; + case CAST2SIGINT : + out.print("Int["); + ExprToOut(expr.sub); + out.print(']'); + return; + case PRIME : + out.print('('); + ExprToOut(expr.sub); + out.print(")'"); + return; + case RCLOSURE : + out.print("* ("); + ExprToOut(expr.sub); + out.print(")"); + return; + case TRANSPOSE : + out.print("~ ("); + ExprToOut(expr.sub); + out.print(")"); + return; + case CLOSURE : + out.print("^ ("); + ExprToOut(expr.sub); + out.print(")"); + return; + case NOT : + out.print("! {"); + ExprToOut(expr.sub); + out.print("}"); + return; + case NOOP : + break; + default : + out.print(expr.op).print(' '); + } + ExprToOut(expr.sub); + } + + private void ExprVarToOut(ExprVar expr) { + out.print(cleanLabel(expr.label)); + } + + private void SigToOut(Sig sig) { + out.print(cleanLabel(sig.label)); + } + + private void FieldToOut(Field field) { + out.print("(").print(cleanLabel(field.label)).print(")"); + } + + // Helper method to print a list of declarations + private void DeclsToOut(ConstList decls) { + boolean first = true; + for (Decl decl : decls) { + StringJoiner namesJoiner = new StringJoiner(","); + if (decl.disjoint != null) { + out.print("disj").print(" "); + } + decl.names.forEach(name -> namesJoiner.add(cleanLabel(name.label))); + if (!first) { + out.print(","); + } + first = false; + out.print(namesJoiner.toString()); + out.print(": "); + ExprToOut(decl.expr, out); + } + } + + // Helper method to change "{path/label}" to "label" + private String cleanLabel(String label) { + if (!label.contains("this/")) { + return label; + } + if (label.endsWith("}") && label.startsWith("{")){ + label = label.substring(1,label.length()-1); + } + int index = label.lastIndexOf('/'); + if (index > -1) { + label = label.substring(index+1); + } + return label; + } + + + private ExprBinary.Op exprOp (Expr expr) { + if (expr instanceof ExprBinary) + return ((ExprBinary) expr).op; + return null; + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java index 95b97dbb5..e1d8a5eee 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java @@ -16,6 +16,7 @@ public class DashAction extends Dash { public Expr expr; public DashAction(Pos p, String n, Expr e) { + assert(n != null & e != null); this.pos = p; this.name = n; this.expr = e; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java index 6dfa7543f..45cb8ff1a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java @@ -19,6 +19,7 @@ public class DashBufferDecls extends Dash { private DashStrings.IntEnvKind kind; public DashBufferDecls(Pos pos, List n, String element, DashStrings.IntEnvKind k) { + assert (n != null && element != null); this.pos = pos; this.names = n; this.element = element; @@ -33,7 +34,7 @@ public String toString() { } StringJoiner sj = new StringJoiner(",\n"); names.forEach(n -> sj.add(n)); - s += sj.toString() + ":" + DashStrings.bufName + "[" + element + "]"; + s += sj.toString() + ":" + DashStrings.bufName + "[" + element + "]\n"; return s; } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java index c3e3c8e37..837eb0d1e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java @@ -16,6 +16,7 @@ public class DashCondition extends Dash { public Expr expr; public DashCondition(Pos p, String n, Expr e) { + assert(n != null && e != null); this.pos = p; this.name = n; this.expr = e; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java index 05bdce17f..8a6e43a40 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java @@ -11,6 +11,7 @@ public class DashDo extends Dash { public Expr action; public DashDo(Pos pos,Expr a) { + assert (a != null); this.pos = pos; this.action = a; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java index 0b0c02690..132a3cdf6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java @@ -15,6 +15,7 @@ public class DashEventDecls extends Dash { private DashStrings.IntEnvKind kind; public DashEventDecls(Pos pos, List n, DashStrings.IntEnvKind kind) { + assert(n != null); this.pos = pos; this.names = n; this.kind = kind; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java index 52bb721c0..691de29d5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java @@ -1,3 +1,5 @@ +/* is this used? */ + package ca.uwaterloo.watform.ast; import edu.mit.csail.sdg.alloy4.Pos; @@ -9,6 +11,7 @@ public class DashExpr extends Dash { private Expr ae; public DashExpr(Pos pos,Expr a) { + assert(a != null); this.pos = pos; this.ae = a; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java index 5c02f3a43..0ca6c985f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java @@ -7,6 +7,7 @@ public class DashFrom extends Dash { public String src; public DashFrom(Pos pos,String f) { + assert(f != null); this.pos = pos; this.src = f; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java index 359f22b79..ff9a41087 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java @@ -8,6 +8,7 @@ public class DashGoto extends Dash { public String dest; public DashGoto(Pos pos,String g) { + assert(g != null); this.pos = pos; this.dest = g; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java index afb5afdef..3c6309d19 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java @@ -16,9 +16,10 @@ public class DashInit extends Dash { public Expr init; - public DashInit(Pos pos, Expr init) { - this.pos = pos; - this.init = init; + public DashInit(Pos p, Expr i) { + assert(i != null); + this.pos = p; + this.init = i; } public String toString() { String s = new String(); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java index c67d7ebfe..ccaf59721 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java @@ -16,10 +16,11 @@ public DashInv(Pos pos, Expr inv) { this.name = null; this.inv = inv; } - public DashInv(Pos pos, String n, Expr inv) { + public DashInv(Pos p, String n, Expr i) { + assert(n != null && i != null); this.pos = pos; this.name = n; - this.inv = inv; + this.inv = i; } public String toString() { String s = new String(); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java index a99060f36..eb34eed2d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java @@ -8,6 +8,7 @@ public class DashOn extends Dash { public Expr ev; public DashOn(Pos pos,Expr e) { + assert(e != null); this.pos = pos; this.ev = e; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java index 80ef1dbf8..2d7ae59e1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java @@ -22,6 +22,7 @@ public class DashSend extends Dash { public Expr eventExpr; public DashSend(Pos pos,Expr ev) { + assert(ev != null); this.pos = pos; this.eventExpr = ev; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index 7eea48ad2..65c66f7a0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -6,16 +6,23 @@ import java.util.List; import java.util.ArrayList; import java.util.StringJoiner; +import java.util.Collections; +import java.util.stream.Collectors; + import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Expr; -import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.*; + +import ca.uwaterloo.watform.parser.StateTable; +import ca.uwaterloo.watform.parser.TransTable; public class DashState extends Dash { // stuff from parsing - private String name; + public String name; + private String sfqn; // set during resolveAllState private String param; private DashStrings.StateKind kind; // basic state = OR with no subStates private DashStrings.DefKind def; @@ -24,45 +31,53 @@ public class DashState extends Dash { // fully general constructor // 6 args + // probably not used? public DashState(Pos p, String n, String prm, DashStrings.StateKind k, DashStrings.DefKind d, List i) { + assert(n != null && prm != null & i != null); this.pos = p; this.name = n; this.param = prm; this.kind = k; this.def = d; this.items = i; + //System.out.println("here1 creating "+this.name+" "+ this.kind); } // basic state - default or non-default // 3 args public DashState(Pos p, String n, DashStrings.DefKind d) { + assert(n != null); this.pos = p; this.name = n; this.param = null; - this.kind = DashStrings.StateKind.BASIC; + this.kind = DashStrings.StateKind.OR; this.def = d; - this.items = null; + this.items = null; // no substates here makes it a basic state + //System.out.println("here2 creating "+this.name+" "+ this.kind); } - // and/or state; non-parameterized + // non-parametrized and/or/basic state // 5 args public DashState(Pos p, String n, DashStrings.StateKind k, DashStrings.DefKind d, List i) { + assert(n != null && i != null); this.pos = p; this.name = n; this.param = null; - this.kind = DashStrings.StateKind.OR; + this.kind = k; this.def = d; this.items = i; + //System.out.println("here3 creating "+this.name+" "+ this.kind); } - // and state; parameterized + // parametrized and state (cannot be default state) // 4 args public DashState(Pos p, String n, String prm, List i) { - assert(p != null); + assert(n != null && prm != null & i != null); this.pos = p; this.name = n; this.param = prm; this.kind = DashStrings.StateKind.AND; this.def = DashStrings.DefKind.NOTDEFAULT; this.items = i; + //System.out.println("here4 creating "+this.name+" "+ this.kind); } public String toString() { @@ -88,6 +103,233 @@ public String toString() { return s; } + // env events cannot be generated + // env vars cannot be primed anywhere + // must have at least one transition (could be looping on Root ...) + + /* + * check for errors in the state hierarchy + * and put all states in the state table + * also sets this state's fqn here + */ + public void resolveAllStates(StateTable st, List params, List ances) { + if (DashFQN.alreadyFQN(name)) DashErrors.stateNameCantBeFQN(pos, name); + sfqn = DashFQN.fqn(ances,name); + System.out.println("Resolving state "+sfqn); + + List newParams = new ArrayList(params); + if (param != null) newParams.add(param); + + // process the children + // have to make a copy so that recursion does not just + // continue to add to list everywhere + List newAnces = new ArrayList(ances); + newAnces.add(name); + + + List substatesList = new ArrayList(); + if (items != null) + substatesList = + items.stream() + .filter(i -> i instanceof DashState) + .map(p -> (DashState) p) + .collect(Collectors.toList()); + + if (substatesList.isEmpty() ) { + + if (kind == DashStrings.StateKind.AND) + DashErrors.concStateNoChildren(sfqn); + else if (param != null) + DashErrors.basicStateParam(sfqn); + else + st.add(sfqn, kind, params, null, DashFQN.fqn(ances), null); + + } else { + + // all sibling states must have different names + ArrayList childFQNs = new ArrayList(); + substatesList.forEach(i -> childFQNs.add(DashFQN.fqn(ances,name, i.name))); + // DashUtilFcns.myprint("childFQNS: "+childFQNs); + Set dups = DashUtilFcns.findDuplicates(childFQNs); + if (!dups.isEmpty()) + DashErrors.dupSiblingNames(DashUtilFcns.strCommaList(dups.stream().collect(Collectors.toList()))); + + // all sibling names must be the same type + Set k = new HashSet(); + substatesList.forEach(i -> k.add(i.kind)); + if (k.size() != 1) + DashErrors.siblingsSameKind(sfqn); + + // if substates are OR, then must be a default unless there is only one substate + // parent kind does not matter + String def = null; + if (k.contains(DashStrings.StateKind.OR) && substatesList.size() != 1) { + // names of the default states + List defaultsList = + substatesList.stream() + .filter(i -> (i.def == DashStrings.DefKind.DEFAULT)) + .map(i -> i.name) + .collect(Collectors.toList()); + if (defaultsList.size() > 1) DashErrors.tooManyDefaults(sfqn); + else if (defaultsList.isEmpty()) DashErrors.noDefaultState(sfqn); + else def = defaultsList.get(0); + } else if (k.contains(DashStrings.StateKind.OR) && substatesList.size() == 1) { + def = substatesList.get(0).name; + } + st.add(sfqn,kind, newParams,def, DashFQN.fqn(ances), childFQNs); + + for (DashState s: substatesList) s.resolveAllStates(st, newParams, newAnces); + } + + /* + + // set the pathtohere and params of variables + // set the FQNs of src and dest of transitions + resolveVars(pth,prs); + resolveEvents(pth); + resolveTrans(pth,prs); + String defName = null; + for (s:substates) { + s.resolveAll(pathToHere, params); + // collect all the stuff from below + // set trans src/dest FQNs + allTransitions.addAll(s.getAllTransitions()); + symbolTable.addAll(s.getSymbolTable()); + allEvents.addAll(s.getAllEvents()); + allParams.addAll(s.getAllParams()); + // calculate all basic states entered/exited and pass up? + // or do that in StateTableResolve all?? + if (s.kind == StateKind.OR) { + if (defName == null) { + defName = s.getFullyQualName(); + } else { + // error multiple default states + } + } else { + defN + } + stateTable.merge(s.getStateTable()); + // what about parameters of states??? + } + stateTable.add(s,) + */ + } + + /* + * check for errors and put all the trans that are at this level + * in the trans table + * must be done after resolveAllState + * this fcn does not modify anything in this object + */ + public void resolveAllTrans(StateTable st, TransTable tt) { + + if (items == null ) return; + List transList = + items.stream() + .filter(i -> i instanceof DashTrans) + .map(p -> (DashTrans) p) + .collect(Collectors.toList()); + // all trans must have different names + ArrayList transFQNs = new ArrayList(); + transList.forEach(i -> transFQNs.add(DashFQN.fqn(sfqn, i.name))); + Set dups = DashUtilFcns.findDuplicates(transFQNs); + if (!dups.isEmpty()) + DashErrors.dupTransNames(DashUtilFcns.strCommaList(dups.stream().collect(Collectors.toList()))); + + for (DashTrans t: transList) { + String tfqn = DashFQN.fqn(sfqn,t.name); + + // transition src/dest have to be resolved here rather than in DashTrans because + // this src and dest are contextual + + List fromList = + t.items.stream() + .filter(i -> i instanceof DashFrom) + .map(p -> ((DashFrom) p).src) + .collect(Collectors.toList()); + String src = setSrcDest("from", fromList, st, sfqn, tfqn); + assert(src != null); // should have thrown an exception + st.add(src); + + List gotoList = + t.items.stream() + .filter(i -> i instanceof DashGoto) + .map(p -> ((DashGoto) p).dest) + .collect(Collectors.toList()); + String dest = setSrcDest("goto", gotoList, st, sfqn, tfqn); + assert(dest != null); // should have thrown an exception + st.add(dest); + + // note that this is not newAnces; states referenced by t can be siblings to the state + // that t is within + + // check if it is an AND-cross transition + List srcAnces = st.getAllAnces(src); + System.out.println("src="+src+" srcAnces= "+srcAnces); + List destAnces = st.getAllAnces(dest); + System.out.println("dest="+dest+" destAnces= "+destAnces); + int i = 0; + while (i< srcAnces.size() && i < destAnces.size() && srcAnces.get(i).equals(destAnces.get(i))) i++; + for (int j=i; j < srcAnces.size();j++) + if (st.getKind(srcAnces.get(i)) == DashStrings.StateKind.AND) + DashErrors.andCrossTransition(tfqn); + for (int j=i; j < destAnces.size(); j++) + if (st.getKind(destAnces.get(i)) == DashStrings.StateKind.AND) + DashErrors.andCrossTransition(tfqn); + tt.add(tfqn,st.getParams(sfqn),src,dest); + } + if (items != null ) { + List substatesList = + items.stream() + .filter(i -> i instanceof DashState) + .map(p -> (DashState) p) + .collect(Collectors.toList()); + for (DashState s: substatesList) s.resolveAllTrans(st, tt); + } + // t.resolveAll(st, tt, newParams, ances); + + + } + + /* + * this fcn figures out the src/dest of a transition + * from its context + * if it has no src/dest, the parent state is used + * if it is already FQN, it is returned directly + * Otherwise, it looks at all uniquely named states up to an ancestor conc state + * Requires state table to have been built already + */ + public String setSrcDest(String xType, List ll, StateTable st, String parentFQN, String tfqn) { + + if (ll.size() > 1) { + DashErrors.moreThanOneSrcDest(xType, tfqn); + return null; + } else if (ll.isEmpty()) + // could be root + return sfqn; + else { + // if has slashes, turn to "-" + String xName = ll.get(0); + if (DashFQN.alreadyFQN(xName)) return xName; + else { + List matches = new ArrayList(); + for (String s:st.getAllNonConcStatesWithinThisState(st.getClosestConcAnces(parentFQN))) { + if (xName.equals(DashFQN.chopNameFromFQN(s))) matches.add(s); + } + if (matches.size() > 1) { + DashErrors.ambiguousSrcDest(xType, tfqn); + return null; + } else if (matches.isEmpty()) { + //DashUtilFcns.myprint(st.toString()); + DashErrors.unknownSrcDest(xName,xType,tfqn); + return null; + } else { + return matches.get(0); + } + } + } + } + /* public String getParam() { return params(1) @@ -95,9 +337,7 @@ public String getParam() { public String getParams() { return params; } - public String getFullyQualName() { - return pathHere+"/"+name; - } + public getAllTransitions() { returns allTransitions; @@ -164,55 +404,5 @@ public void resolveTrans(String pth, List prs) { // what if no transitions } - // 1) all sibling states must be same type - - // env events cannot be generated - // env vars cannot be primed anywhere - // must have at least one transition (could be looping on Root ...) - - public void resolveAll(String pth, List prs, String parent) { - List params = prs.add(prm); - st.add(fulQualName(pth,name),params,parent, children) - - if (isBasicState()) { - allTransitions = new ArrayList(); - symbolTable = ??; - allEvents = new ArrayList(); - stateTable.add(s, {s}, {s}) - return; - } else { - allSubStatesSameKind() - // set the pathtohere and params of variables - // set the FQNs of src and dest of transitions - resolveVars(pth,prs); - resolveEvents(pth); - resolveTrans(pth,prs); - String defName = null; - for (s:substates) { - s.resolveAll(pathToHere, params); - // collect all the stuff from below - // set trans src/dest FQNs - allTransitions.addAll(s.getAllTransitions()); - symbolTable.addAll(s.getSymbolTable()); - allEvents.addAll(s.getAllEvents()); - allParams.addAll(s.getAllParams()); - // calculate all basic states entered/exited and pass up? - // or do that in StateTableResolve all?? - if (s.kind == StateKind.OR) { - if (defName == null) { - defName = s.getFullyQualName(); - } else { - // error multiple default states - } - } else { - defN - } - stateTable.merge(s.getStateTable()); - // what about parameters of states??? - } - stateTable.add(s,) - } - isResolved = true; - } */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java index bce1cf6ac..51032325d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java @@ -2,8 +2,13 @@ import java.util.List; import java.util.StringJoiner; +import java.util.Collections; +import java.util.stream.Collectors; -import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.*; + +import ca.uwaterloo.watform.parser.StateTable; +import ca.uwaterloo.watform.parser.TransTable; import edu.mit.csail.sdg.alloy4.Pos; @@ -11,10 +16,11 @@ public class DashTrans extends Dash { String name; List items; - public DashTrans(Pos pos,String name, List items) { - this.pos = pos; - this.name = name; - this.items = items; + public DashTrans(Pos p,String n, List i) { + assert(n != null && i != null); + this.pos = p; + this.name = n; + this.items = i; } public String toString() { @@ -29,5 +35,9 @@ public String toString() { } return s; } + public void resolveAll(StateTable st, TransTable tt, List params, List ances) { + String tfqn = DashFQN.fqn(ances,name); + System.out.println("Resolving trans "+tfqn); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java index fbdb1620a..f392de941 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java @@ -17,6 +17,7 @@ public class DashVarDecls extends Dash { public DashVarDecls (Pos pos, List n, Expr e, DashStrings.IntEnvKind k) { + assert(n != null && e != null); this.pos = pos; this.names = n; this.typ = e; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java index 3e4a5c234..bded691c0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java @@ -8,6 +8,7 @@ public class DashWhen extends Dash { public Expr when; public DashWhen(Pos pos,Expr w) { + assert(w != null); this.pos = pos; this.when = w; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java new file mode 100644 index 000000000..0aafc0634 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -0,0 +1,92 @@ +/* + * All the errors that can be thrown in Dash code + */ + +package ca.uwaterloo.watform.core; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorFatal; + +public class DashErrors { + + // syntax errors -------------------------------------------- + + public static void stateNameCantBeFQN(Pos o, String name) throws Err { + throw new ErrorSyntax(o,"State name "+name+" when declared cannot have slash"); + } + public static void onlyOneState(Pos o) throws Err { + throw new ErrorSyntax(o,"Model can only have one 'state' section"); + } + public static void dupSiblingNames(String dups) throws Err { + throw new ErrorSyntax("Duplicate sibling state names: " + dups); + } + public static void dupTransNames(String dups) throws Err { + throw new ErrorSyntax("Duplicate sibling state names: " + dups); + } + public static void siblingsSameKind(String fqn) throws Err { + throw new ErrorSyntax("Children of "+fqn+" must all be of concurrent or not concurrent"); + } + public static void crossRefMoreThanOneArg(Pos o, String n) throws Err { + throw new ErrorSyntax(o,"Two many args to reference to "+n+" in sibling state"); + } + public static void moreThanOneSrcDest(String x, String n) throws Err { + throw new ErrorSyntax("Transition "+n+" has more than one "+ x); + } + public static void noTrans() throws Err { + throw new ErrorSyntax("Model does not contain any transitions."); + } + public static void transUsesNonExistentState(String n) throws Err { + throw new ErrorSyntax("Some transition has from/goto to state "+n+" which doesn't exist"); + } + public static void tooManyDefaults(String fqn) throws Err { + throw new ErrorSyntax("State "+fqn+" has more than one default state"); + } + public static void noDefaultState(String fqn) throws Err { + throw new ErrorSyntax("State "+fqn+" does not have a default state"); + } + public static void unknownSrcDest(String x, String t, String tfqn) throws Err { + throw new ErrorSyntax("Trans "+tfqn+" "+t+" "+x+ " is unknown"); + } + public static void ambiguousSrcDest(String x, String tfqn) throws Err { + throw new ErrorSyntax("Trans "+tfqn+" "+x+" dest name is ambiguous: could be child of of parent state or sibling of parent state"); + } + public static void andCrossTransition(String tfqn) throws Err { + throw new ErrorSyntax("Trans "+tfqn+" goes between concurrent states"); + } + + // parts of the code that should be unreachable ------------- + + public static void concStateNoChildren(String fqn) throws Err { + throw new ErrorFatal("Concurrent state "+fqn+" must have substates"); + } + public static void basicStateParam(String fqn) throws Err { + throw new ErrorFatal("Basic state "+fqn+" has parameter"); + } + public static void toAlloyNoDash() throws Err { + throw new ErrorFatal("Translating to Alloy when no Dash part"); + } + public static void addStateToStateTableDup(String fqn) throws Err { + throw new ErrorFatal(fqn + "entered more than once in StateTable"); + } + public static void nonBasicEmptyChildren(String fqn) throws Err { + throw new ErrorFatal(fqn + " empty children for non-basic state"); + } + public static void isBasicNotExist(String q) throws Err { + throw new ErrorFatal(q + " isBasicState of state that does not exist"); + } + public static void transTableDup(String n) throws Err { + throw new ErrorFatal("tried to add trans "+n+" to trans table twice"); + } + public static void stateDoesNotExist(String s1, String n) throws Err { + throw new ErrorFatal("for function "+s1+", state "+n+ " does not exist in state table"); + } + public static void transDoesNotExist(String s1, String n) throws Err { + throw new ErrorFatal("for function "+s1+", trans "+n+ " does not exist in trans table"); + } + public static void missingExpr(String s) throws Err { + throw new ErrorFatal("Missing expr type in "+s); + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java new file mode 100644 index 000000000..a01d2c3d8 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java @@ -0,0 +1,81 @@ +package ca.uwaterloo.watform.core; + +import java.util.StringJoiner; +import java.util.List; +import java.util.Collection; +import java.util.Set; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.stream.Collectors; + + +public class DashFQN { + + // used for translation to Alloy + //NAD TODO this should match the qualChar used in parsing for vars and state names + private static String inputQualChar = "/"; + private static String outputQualChar = "_"; + + public static String convertFQN(String n) { + return n.replace(inputQualChar, outputQualChar); + } + public static Boolean alreadyFQN(String n) { + return n.contains(inputQualChar); + } + public static String fqn(List pth) { + if (pth.isEmpty()) return null; // for root + StringJoiner sj = new StringJoiner(inputQualChar); + pth.forEach(n -> sj.add(n)); + return sj.toString(); + } + public static String fqn(String s1,String s2) { + String q = new String(s1); + q += inputQualChar; + q += s2; + return q; + } + public static String fqn(List pth, String name) { + if (alreadyFQN(name)) + //return name.replace(inputQualChar,outputQualChar); + return name; + else { + StringJoiner sj = new StringJoiner(inputQualChar); + pth.forEach(n -> sj.add(n)); + sj.add(name); + return sj.toString(); + } + } + public static String fqn(List pth, String parent, String child) { + if (alreadyFQN(child)) + //return child.replace(inputQualChar,outputQualChar); + return child; + else { + StringJoiner sj = new StringJoiner(inputQualChar); + pth.forEach(n -> sj.add(n)); + sj.add(parent); + sj.add(child); + return sj.toString(); + } + } + public static List splitFQN(String fqn) { + return Arrays.asList(fqn.split(inputQualChar)); + } + public static String chopNameFromFQN(String fqn) { + // this is from an output FQN + return DashUtilFcns.last(splitFQN(fqn)); + } + // can't just take longest prefix because states may have similar names + // such as Bit1 and Bit2 + public static String longestCommonFQN(String a, String b) { + List aSplit = splitFQN(a); + List bSplit = splitFQN(b); + String result = new String(); + int minLength = Math.min(aSplit.size(), bSplit.size()); + int i = 0; + while (i < minLength && aSplit.get(i).equals(bSplit.get(i))) i++; + return fqn(aSplit.subList(0,i)); + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java index f0d79c4b1..d0cd0fecc 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java @@ -1,6 +1,7 @@ package ca.uwaterloo.watform.core; import java.util.*; +import edu.mit.csail.sdg.alloy4.Pair; // everything must be static public class DashSituation { @@ -17,6 +18,11 @@ public class DashSituation { // and check it during the second parse run public static boolean haveCountedBuffers = false; // buffer elements in order of buffers + // its a pain to make a pair in Alloy (Pair class is difficult) + // or Java where javafx.util.Pair does not seem to be available + // for this version of Alloy + // so just keep two lists insync + public static List bufferNames = new ArrayList(); public static List bufferElements = new ArrayList(); // we will need more here to know the names of the elements // of the buffers for the open statements diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index f484c5c5f..d2821a2a2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -1,9 +1,28 @@ -/* string names used in Dash and conversion to Alloy */ + /* string names used in Dash and conversion to Alloy */ package ca.uwaterloo.watform.core; public class DashStrings { + /* alloy keywords */ + public static String moduleName = "module"; + public static String extendsName = "extends"; + public static String inName = "in"; + public static String abstractName = "abstract"; + public static String oneName = "one"; + public static String varName = "var"; + public static String openName = "open"; + public static String asName = "as"; + public static String boolName = "boolean/Bool"; + public static String trueName = "boolean/True"; + public static String intName = "int"; + public static String utilBooleanName = "util/boolean"; + public static String utilCTLpathName = "util/ctl_path"; + public static String utilOrderingName = "util/ordering"; + public static String utilBufferName = "util/buffer"; + public static String sigName = "sig"; + public static String predName = "pred"; + // used for printing: parts of Dash syntax // must be in sync with Dash-cup-symbols.txt public static String stateName = "state"; @@ -26,13 +45,10 @@ public class DashStrings { public static String doName = "do"; public static String gotoName = "goto"; public static String sendName = "send"; + public static String SLASH = "/"; - - - // used for translation to Alloy - public static String qualChar = "/"; // predicate names public static String smallStepName = "small_step"; @@ -47,8 +63,8 @@ public class DashStrings { public static String stateLabelName = "StateLabel"; public static String systemStateName = "SystemState"; - - public static String bufferIndexName = "bufIndex"; + public static String transitionLabelName = "TransitionLabel"; + public static String identifierName = "Identifiers"; // how to name parameter variables public static String pName = "p"; public static String eventsName = "events"; @@ -61,27 +77,19 @@ public class DashStrings { public static String postName = "_post"; public static String semanticsName = "_semantics"; public static String testIfNextStableName = "testIfNextStable"; - public static String isEnabledAfterStep = "_ isEnabledAfterStep"; + public static String isEnabledAfterStepName = "_isEnabledAfterStep"; public static String tName = "t"; public static String geName = "ge"; - /* alloy keywords */ - public static String extendsName = "extends"; - public static String inName = "in"; - public static String abstractName = "abstract"; - public static String oneName = "one"; - public static String varName = "var"; - public static String boolName = "boolean"; - public static String intName = "int"; - public static String utilBooleanName = "util/boolean"; - public static String utilCTLpathName = "util/ctl_path"; - public static String utilOrderingName = "util/ordering"; - public static String utilBufferName = "util/buffer"; + public static String bufferName = "buffer"; + public static String bufferIndexName = "bufIdx"; + + public static String tracesName = "traces"; - public static String sCur = "s"; - public static String sNext = "sNext"; + public static String sCurName = "s"; + public static String sNextName = "sNext"; public static String prime(String a) { return a+"'"; }; @@ -93,10 +101,13 @@ public static enum IntEnvKind { public static enum StateKind { AND, - OR, - BASIC + OR + // basic is determined if no children } + // this distinct is only used at parsing + // within StateTable the default of a state is String name + // or null public static enum DefKind { DEFAULT, NOTDEFAULT diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java new file mode 100644 index 000000000..e8a4d670d --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java @@ -0,0 +1,59 @@ +/* + * For the util functions used many places + */ + +package ca.uwaterloo.watform.core; + +import java.util.StringJoiner; +import java.util.List; +import java.util.Collection; +import java.util.Set; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.stream.Collectors; + +public class DashUtilFcns { + + + + public static String last(List ll) { + return ll.get(ll.size() - 1 ); + } + + /* copied from https://stackoverflow.com/questions/7414667/identify-duplicates-in-a-list */ + public static Set findDuplicates(Collection collection) { + + Set duplicates = new LinkedHashSet<>(); + Set uniques = new HashSet<>(); + + for(T t : collection) + if(!uniques.add(t)) + duplicates.add(t); + return duplicates; + } + + public static String strCommaList(List ll) { + StringJoiner sj = new StringJoiner(", "); + ll.forEach(n -> sj.add(n)); + return sj.toString(); + } + public static Set listToSet(List ll) { + return ll.stream().collect(Collectors.toSet()); + } + + public static List setToList(Set ll) { + return new ArrayList(ll); + } + + public static void myprint(String s) { + // debugging output + System.out.println(s); + } + public static List newListWith(List ll, T s) { + List x = new ArrayList(ll); + x.add(s); + return x; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java new file mode 100644 index 000000000..ba4d61d54 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -0,0 +1,492 @@ +/* + * Functions for translating Dash to Alloy + * The translation is done in place so the Dash + * module contains the original "state" and its + * translation to Alloy but there + * is too much code to put this all in one file + */ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; +import ca.uwaterloo.watform.core.*; + + +import ca.uwaterloo.watform.alloyasthelper.*; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +public class DashToAlloy { + private DashModule d; + + public DashToAlloy(DashModule dash) { + this.d = dash; + } + + public void translate() { + assert(d.hasRoot()); + // translation is done in place + createSpaceSignatures(); // state, transition, parameter, buffer space + createSnapshotSig(); + for (String t: d.getTransNames()) { + createTransPre(t); + createTransPost(t); + createTransSemantics(t); + createTransIsEnabledAfterStep(t); + createTransPred(t); + } + createSmallStep(); + } + + // make it shorter internally + private String fqn(String s) { + // internally we use "/" to separate FQN parts + // because Alloy names might use "_" + // but we can't output "/" in Alloy identifiers + // so before outputting we convert "/" to "_" + // for everything + return DashFQN.convertFQN(s); + } + private void createSpaceSignatures() { + // abstract sig Statelabel + d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); + // abstract sig SystemState extend StateLabel + d.alloyString += d.addAbstractExtendsSigSimple(DashStrings.systemStateName,DashStrings.stateLabelName); + + recurseCreateStateSpaceSigs(DashStrings.stateLabelName, fqn(d.getRootName())); + + d.alloyString += "\n"; + + d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); + for (String t : d.getTransNames()) { + d.alloyString += d.addOneExtendsSigSimple(fqn(t), DashStrings.transitionLabelName); + } + d.alloyString += "\n"; + if (d.getMaxDepthParams() != 0) d.alloyString += d.addAbstractSigSimple(DashStrings.identifierName); + if (!d.getAllParams().isEmpty()) + for (String s: d.getAllParams()) + d.alloyString += d.addExtendsSigSimple(s, DashStrings.identifierName); + d.alloyString += "\n"; + /* + if (d.hasEvents()) { + addAbstractSigSimple(eventLabelName); + if (d.hasInternalEvents()) { + addAbstractExtendsSigSimple( environmentEventName, eventLabelName); + for (e: d.getInternalEventNames()) { + addOneExtendsSigSimple(e,internalEventName) + } + } + if (d.hasExternalEvents()){ + addAbstractExtendsSigSimple( internalEventName, eventLabelName); + for (e: d.getExternalEventNames()) { + addOneExtendsSigSimple(e,internalEventName) + } + } + } + + + + if (d.hasBuffers()) { + for (String i: d.getBufferIndices()) { + addSigSimple( i); + } + } + */ + } + private void recurseCreateStateSpaceSigs(String parent, String child) { + if (d.isBasicState(child)) d.alloyString += d.addOneExtendsSigSimple(fqn(child),fqn(parent)); + else { + d.alloyString += d.addAbstractExtendsSigSimple(fqn(child), fqn(parent)); + for (String grandchild: d.getImmChildren(child)) recurseCreateStateSpaceSigs(child, grandchild); + } + } + private void createSnapshotSig(){ + if (DashOptions.isElectrum) { + // if Electrum add var sigs + // taken0, conf0, event0 + d.alloyString += d.addVarSigSimple(DashStrings.takenName+"0", ExprHelper.createVar(DashStrings.transitionLabelName)); + d.alloyString += d.addVarSigSimple(DashStrings.confName+"0", ExprHelper.createVar(DashStrings.stateLabelName)); + if (d.hasEvents()) + d.alloyString += d.addVarSigSimple(DashStrings.eventName+"0", ExprHelper.createVar(DashStrings.eventLabelName)); + if (d.getMaxDepthParams() != 0) { + for (int i = 1; i < d.getMaxDepthParams()+1; i++) { + List cop = new ArrayList (Collections.nCopies(i,ExprHelper.createVar(DashStrings.identifierName))); + // taken 1, etc. + d.alloyString += d.addVarSigSimple( + DashStrings.takenName+Integer.toString(i), + DashUtilFcns.newListWith(cop, ExprHelper.createVar(DashStrings.transitionLabelName))); + // conf 1, etc. + d.alloyString += d.addVarSigSimple( + DashStrings.confName+Integer.toString(i), + DashUtilFcns.newListWith(cop, ExprHelper.createVar(DashStrings.stateLabelName))); + // event 1, etc. + if (d.hasEvents()) + d.alloyString += d.addVarSigSimple( + DashStrings.eventName+Integer.toString(i), + DashUtilFcns.newListWith(cop, ExprHelper.createVar(DashStrings.eventLabelName))); + } + } + // stable: one boolean; + if (d.hasConcurrency()) { + //TODO now to make this one boolean + d.alloyString += d.addVarSigSimple(DashStrings.stableName, ExprHelper.createVar(DashStrings.boolName)); + } + // add dynamic symbols (vars and buffers) + /* + for (DashDynSymbols v: getDynSymbols()) { + List prms = Collections.nCopies(DashStrings.IdentifiersName, v.getParams().size()); + addVarSigSimple( + v.getFullyQualName(), + createArrowList(prms+v.createAlloyTyp())); + } + */ + } else { + // if traces/tcmc sig Snapshot {} with fields + List decls = new ArrayList(); + + // taken0, conf0, event0 + decls.add(DeclExt.newSetDeclExt(DashStrings.takenName+"0", DashStrings.transitionLabelName)); + decls.add(DeclExt.newSetDeclExt(DashStrings.confName+"0", DashStrings.stateLabelName)); + if (d.hasEvents()) + decls.add(DeclExt.newSetDeclExt(DashStrings.eventName+"0", DashStrings.eventLabelName)); + if (d.getMaxDepthParams() != 0) { + for (int i = 1; i < d.getMaxDepthParams()+1; i++) { + List cop = Collections.nCopies(i+1,DashStrings.identifierName); + // taken 1, etc. + decls.add(DeclExt.newSetDeclExt( + DashStrings.takenName+Integer.toString(i), + ExprHelper.createArrowList(DashUtilFcns.newListWith(cop, DashStrings.transitionLabelName)))); + // conf 1, etc. + decls.add(DeclExt.newSetDeclExt( + DashStrings.confName+Integer.toString(i), + ExprHelper.createArrowList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName)))); + // event 1, etc. + if (d.hasEvents()) + decls.add(new DeclExt( + DashStrings.eventName+Integer.toString(i), + ExprHelper.createArrowList(DashUtilFcns.newListWith(cop, DashStrings.eventLabelName)))); + } + } + // stable: one boolean; + if (d.hasConcurrency()) { + decls.add(new DeclExt(DashStrings.stableName, ExprHelper.createOne(ExprHelper.createVar(DashStrings.boolName)))); + } + // add dynamic symbols (vars and buffers) + /* + for (DashDynSymbols v: getDynSymbols()) { + List prms = Collections.nCopies(DashStrings.IdentifiersName, v.getParams().size()); + decls.add(createDecl( + v.getFullyQualName(), + createArrowList(prms+v.createAlloyTyp()))); + } + */ + + d.alloyString += d.addSigWithDeclsSimple( DashStrings.snapshotName, decls); + } + d.alloyString += "\n"; + } + // -------------------------------------------------------------------------------------- + /* + pred pre_t1[s:Snapshot,pparam0:Param0, ...] { + src_state_t1 in .s.conf + guard_cond_t1 [s] + s.stable = True => + { // beginning of a big step + // transition can be triggered only by environmental events + .trig_events_t1 in (s.events & EnvironmentalEvent ) + } else { + // intermediate snapshot + // transition can be triggered by any type of event + .trig_events_t1 in s.events + } + } + Assumption: prs for src state and trig events are a subset of prs for trans + */ + private void createTransPre(String t) { + List prs = d.getTransParams(t); + List o = new ArrayList(); + + /* + // p3 -> p2 -> p1 -> src in s.confVar(i) + // src does not have to be a basic state + Expr src = createVar(d.getTransSrc(t)); + ArrayList psList = createVars(prs); + o.add(createIn(createArrowList(createVars(prs).add(src)),curConf(prs.size()))); + + // guard_cond_t1 [s] + o.add(d.getTransGuard(t).convertToAlloy(d.symbolTable, sCurVar(), sNextVar())); + + // events + if (d.hasConcurrency() && d.getTransTrigger(t) != null && d.hasEnvironmentalEvents()) { + // trig_events_t1 + ArrayList trigEvents = new ArrayList(); + for (e:d.getTransTriggerEvents(t)) { + // p3 -> p2 -> p1 -> event + trigEvents.add(createArrowList(createVars(d.getEventParams(e)).add(createVar(e)))); + } + Expr te = createPlus(trigEvents); + o.add(createITE( + createEquals(curStable(),createTrue()) + // have to look at different levels!! + createIn(te, createAnd(curEvents(),createVar(DashStrings.environmentEventName))), + createIn(te, curEvents())) + ); + } + Expr body = createAnd(o); + */ + + // tmp + List body = Arrays.asList(ExprHelper.createNullExpr()); + + d.alloyString += d.addPredSimple(DashFQN.convertFQN(t)+DashStrings.preName, curParamsDecls(prs), body); + d.alloyString += "\n"; + } + private void createTransPost(String t) { + List prs = d.getTransParams(t); + + // tmp + List body = Arrays.asList(ExprHelper.createNullExpr()); + d.alloyString += d.addPredSimple(DashFQN.convertFQN(t)+DashStrings.postName,curNextParamsDecls(prs),body); + } + // ----------------------------------------------------------------------------- + /* + pred t1_semantics[s:Snapshot,s':Snapshot, pParam0: Param0, ... ] { + (s.stable = True) => { + s'.taken = t1 + } else { + s'.taken = s.taken + t1 + no t1.notOrthogonal & (s.taken0 + taken0 |> TransitionLabel + s.taken1 |> TransitionLabel + ...) + } + for all t in t1.higherPri + some p0. p1. !pre_higherpri_trans[s,p0,p1] + } + */ + private void createTransSemantics(String t) { + //List body = new ArrayList(); + List prs = d.getTransParams(t); + + /* + // s'.taken = s.taken + t1 + Expr elseExpr = createEquals(nextTaken(prs.size()),createPlus(curTaken(prs.size()),createParamsJoin(prs,t1))); + if (notOrthogonal != null) { + elseExpr = + createAnd( + elseExpr, + // no t1.notOrthogonal & (s.taken + s.taken1 |> TransitionLabel + taken2 |> TransitionLabel + ...) + createNo( + createAnd( + createNonOrthogonalExpr(t), + createChoppedGroup(prs.size(),DashStrings.takenName,DashStrings.transitionLabelName)))); + } + + body.add( + createITE(sCurStableTrue(), + // s'.taken = t1 + createEquals(nextTaken(prs.size()), createParamsJoin(prs,t1)), + elseExpr + ) + for (h: dash.transTable.get(t).getHigherPriority()) { + List prs = h.getParams(); + // some p0. p1. !pre_higherpri_trans[s,p0,p1] + body.add(createSome(paramsDecls(prs), createNot(curJoinParams(prs,h+DashStrings.preName)))) + } + */ + // tmp + List body = Arrays.asList(ExprHelper.createNullExpr()); + d.alloyString += d.addPredSimple(DashFQN.convertFQN(t)+DashStrings.semanticsName,curNextParamsDecls(prs),body); + d.alloyString += "\n"; + } + // --------------------------------------------------- + /* + // this is considering all instances of t1s (thus, the existential quantification) + pred t1_enabledAfterStep[ + s:Snapshot,s':Snapshot, + pParam0: Param0, ... + t:TransitionLabel, // parameters don't matter for orthogonality + ge:EventLabel ] + { // b/c below is exists params, the params don't matter + src_state_t1 in s'.confi // where i is depth of src_state, + guard_cond_t1[s'] // may depend on params + (s.stable = True) => + no t1.notOrthogonal & t + for all of t1's triggering events and forall n + (if trig_ev_t1 is internal, line below is false) + trig_ev_t1 in (chop0(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) ... + ge) + else { + no t1.notOrthogonal & (t + s.taken0 + s.taken1.TransLabel + s.taken2.TransLabel + s.taken3.TransLabel ...) + for all of t1's triggering events and forall n + trig_ev_t1 in (s.event0.EventLabel + s.event1.EventLabel + s.event2.EventLabel ... + ge) + } + } + */ + private void createTransIsEnabledAfterStep(String t) { + List prs = d.getTransParams(t); + /* + ArrayList o = new ArrayList(); + + + // src does not have to be a basic state + Expr src = createVar(dash.getTransSrc(t)); + ArrayList psList = createVars(prs); + List trig_ev = dash.transTable.get(t).getWhen(); + List int_trig_ev = trig_ev.stream().filter(ev -> ev.isInternal()).collect(Collectors.toList()); + + // p3 -> p2 -> p1 -> src in s'.confVar(i) + o.add(createIn(createArrowList(createVars(prs).add(src)),nextConf(prs.size()))); + + // guard_cond_t1 [s'] + // final parameter (usually s') should not be used in precondition + o.add(dash.getTransGuard(t).convertToAlloy(dash.symbolTable, sNextVar(), null, prs)); + + + // no t1.notOrthogonal & (t + s.taken + s.taken1 |> TransitionLabel + taken2 |> TransitionLabel + ...) + Expr elseExpr = createNo( + createAnd( + createNonOrthogonalExpr(t),createPlus(createVar(t), + createChoppedGroup(prs.size(),DashStrings.takenName,DashStrings.transitionLabelName)))); + elseExpr = createAnd( + elseExpr, + createIn( + createPlusList(createVarList(trig_ev)), + createPlus( + // chop(s.event0,EventLabel + chop(s.event1,EventLabel) + chop(s.event2,EventLabel) + createChoppedGroup(prs.size(),DashStrings.eventName,DashStrings.eventLabelName), + ge))); + + if (int_trig_ev == null) { + // no t1.notOrthogonal & t + Expr ifExpr = createNo(createAnd(createNonOrthogonalExpr(t),createVar(t))); + ifExpr = createAnd( + ifExpr, + createIn( + createPlusList(createVarList(trig_ev)), + // chop(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) + createPlus(createChoppedGroup(prs.size(),DashStrings.eventName,DashStrings.environmentEventName),ge))) + body.add(createITE(sStableTrue(),ifExpr,elseExpr)); + } else { + body.add(createITE(sStableTrue(),createFalse(),elseExpr)); + } + */ + List decls = curNextParamsDecls(prs); + decls.add((Decl) new DeclExt(DashStrings.tName, DashStrings.transitionLabelName)); + if (d.hasEvents()) + decls.add((Decl) DeclExt.newSetDeclExt(DashStrings.geName, DashStrings.eventLabelName)); + // tmp + List body = Arrays.asList(ExprHelper.createNullExpr()); + d.alloyString += d.addPredSimple(DashFQN.convertFQN(t)+DashStrings.isEnabledAfterStepName,decls,body); + d.alloyString += "\n"; + } + + // -------------------------------------------------------------------------------------- + /* + pred t1[s:Snapshot,s':Snapshot,pparam0:param0,pparam1:param1,pparam2:param2,...] = + pparam2.pparam1.pparam0.s.pre_1 and + pparam2.pparam1.pparam0.s'.s.post_1 and + pparam2.pparam1.pparam0.s'.s'.semantics_t1 + */ + private void createTransPred(String t) { + // t is FQN + // e.g. [ClientId,ServerId.,,,] + List prs = d.getTransParams(t); + List body = new ArrayList(); + String tfqn = DashFQN.convertFQN(t); + // pre_transName[s, p0, p1, p2] -> p2.p1.p0.s.pre_transName + body.add(ExprHelper.createPredCall(tfqn + DashStrings.preName, curParamsArgs(prs))); + // p2.p1.p0.s'.s.post_transName + body.add(ExprHelper.createPredCall(tfqn + DashStrings.preName, curNextParamsArgs(prs))); + // p2.p1.p0.s'.s.semantics_transName + body.add(ExprHelper.createPredCall(tfqn + DashStrings.preName, curNextParamsArgs(prs))); + d.alloyString += d.addPredSimple(tfqn, curNextParamsDecls(prs), body); + d.alloyString += "\n"; + } + + private void createSmallStep() { + ; + } + + // useful shortcuts + private Decl sCurDecl() { + return (Decl) new DeclExt(DashStrings.sCurName, DashStrings.snapshotName); + } + private Decl sNextDecl() { + return (Decl) new DeclExt(DashStrings.sNextName, DashStrings.snapshotName); + } + private Decl paramDecls(String n) { + return (Decl) new DeclExt(DashStrings.pName+n, n); + } + private List curParamsDecls(List prs) { + List o = new ArrayList(); + if (!DashOptions.isElectrum) o.add(sCurDecl()); + for (String n: prs) o.add(paramDecls(n)); + return o; + } + private List curNextParamsDecls(List prs) { + List o = new ArrayList(); + if (!DashOptions.isElectrum) { o.add(sCurDecl()); o.add(sNextDecl()); } + for (String n: prs) o.add(paramDecls(n)); + return o; + } + + private ExprVar sCurVar() { + return ExprHelper.createVar(DashStrings.sCurName); + } + private ExprVar sNextVar() { + return ExprHelper.createVar(DashStrings.sNextName); + } + private List convertParamsToVars(List names) { + List o = new ArrayList(); + for (String n: names) o.add(ExprHelper.createVar(DashStrings.pName+n)); + return o; + } + private List curParamsArgs(List params) { + List o = new ArrayList(); + o.add(sCurVar()); + o.addAll(convertParamsToVars(params)); + return o; + } + private List curNextParamsArgs(List params) { + List o = new ArrayList(); + o.add(sCurVar()); + o.add(sNextVar()); + o.addAll(convertParamsToVars(params)); + return o; + } + /* + private Expr predJoinCurParams(String name, List prs) { + //p2.p1.p0.s.name + Expr e = ExprHelper.createVar(name); + List prsVarList = convertParamsToVars(prs); + if (!DashOptions.isElectrum) e = ExprHelper.createJoin(sCurVar(),e); + if (prs!= null) { + Collections.reverse(prsVarList); + prsVarList.add(e); + System.out.println("predJoinCurParams: " +prsVarList); + Expr x = ExprHelper.createJoinList(prsVarList); + System.out.println("Join of prsVarList: " + x); + return ExprHelper.createJoinList(prsVarList) ; + } else return e; + } + private Expr predJoinCurNextParams(String name, List prs) { + //p2.p1.p0.s'.s.pre_transName + Expr e = ExprHelper.createVar(name); + List prsVarList = convertParamsToVars(prs); + if (!DashOptions.isElectrum) e = ExprHelper.createJoin(sNextVar(),ExprHelper.createJoin(sCurVar(),e)); + if (prs!=null) { + Collections.reverse(prsVarList); + prsVarList.add(e); + return ExprHelper.createJoinList(prsVarList) ; + } else return e; + } + */ + + +} + diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index 853489825..13d03fad3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -31,6 +31,7 @@ public static DashModule parseFile(String filename, A4Reporter rep) { DashOptions.isTraces = true; DashSituation.haveCountedBuffers = false; DashSituation.bufferElements = new ArrayList(); + DashSituation.bufferNames = new ArrayList(); dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); if (dash == null) { System.err.println("Empty Alloy file"); @@ -39,10 +40,11 @@ public static DashModule parseFile(String filename, A4Reporter rep) { dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); //System.out.println(filename + " parsed successfully."); // well-formedness checks - //dash.resolveAll(d); - ; + dash.resolveAllDash(rep); + //System.out.println(dash.toString()); } } catch (Exception e) { + e.printStackTrace(System.err); System.err.println(e); System.exit(1); } @@ -60,23 +62,22 @@ public static String dumpString(DashModule dash) { return s; } - //NAD this should be more general and take a String - public static CompModule translateToAlloy(DashModule dash, A4Reporter rep) { + public static DashModule translate(DashModule dash, A4Reporter rep) { try { DashOptions.isTraces = true; - if (dash == null) { - System.err.println("Cannot translate to Alloy."); - System.exit(1); + if (dash != null) { + // translates in place + dash.translate(); } - //CompModule alloy = new CoreDashToAlloy(dash).translate(); - //alloy.resolveAll(rep == null ? A4Reporter.NOP : rep, ); + // Alloy wff check + dash.resolveAllAlloy(rep == null ? A4Reporter.NOP : rep); + System.out.println(dash.toString()); } catch (Exception e) { + e.printStackTrace(System.err); System.err.println(e); System.exit(1); } - - //CompModule alloy = null; - return null; + return dash; } public static A4Solution executeCommand(Command cmd, CompModule alloy, A4Reporter rep, A4Options options) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 7edfdc971..133652696 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -1,5 +1,6 @@ // No state here // just helper functions for adding elements to the module +// return a string that is what the Alloy text would be; avoids us having to print all of Alloy constructs package ca.uwaterloo.watform.parser; @@ -10,6 +11,7 @@ import java.util.Arrays; import java.util.ArrayList; import java.lang.StringBuilder; +import java.util.StringJoiner; import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Attr.AttrType; @@ -23,16 +25,38 @@ import edu.mit.csail.sdg.parser.CompModule; import ca.uwaterloo.watform.core.DashStrings; -import ca.uwaterloo.watform.alloyasthelper.AlloyExprHelper; - +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; public class CompModuleHelper extends CompModule { + private String space = " "; + private String tab = " "; + // this class is never instantiated public CompModuleHelper(CompModule world, String filename, String path) { super(world,filename,path); } + public String addOpenSimple(String name, List args, String aliasName) { + ExprVar alias = (aliasName == null) ? null : ExprHelper.createVar(aliasName); + List argsExprList = new ArrayList(); + if (args != null) + for (String a: args) argsExprList.add(ExprHelper.createVar(a)); + addOpen(null, null, ExprHelper.createVar(name), argsExprList, alias); + // build the string that is this open + String s = DashStrings.openName + " "+name; + if (args != null) { + s += "["; + StringJoiner j = new StringJoiner(", "); + args.forEach(a -> j.add(a)); + s += j.toString(); + s += "]"; + } + if (aliasName != null) s += " " + DashStrings.asName + " " + aliasName; + return s+"\n"; + } + /** * adding signatures * in CompModule, a signature has multiple related parts so can't just return a signature @@ -40,7 +64,9 @@ public CompModuleHelper(CompModule world, String filename, String path) { * Alloy public Sig addSig(Pos namePos, String name, ExprVar par, * List parents, List fields, Expr fact, Attr... attributes) throws Err { */ - public void addSigSimple(String name) { + + public String addSigSimple(String name) { + // sig name {} addSig( Pos.UNKNOWN, name, @@ -54,9 +80,13 @@ public void addSigSimple(String name) { null, null, null); + String s = new String(); + s += DashStrings.sigName + space + name + " {}\n"; + return s; } - public void addAbstractSigSimple(String name) { + public String addAbstractSigSimple(String name) { + // abstract sig name {} addSig( Pos.UNKNOWN, name, @@ -70,14 +100,19 @@ public void addAbstractSigSimple(String name) { null, null, null); + String s = new String(); + s += DashStrings.abstractName + space + DashStrings.sigName + space; + s += name + " {}\n"; + return s; } - public void addAbstractExtendsSigSimple(String extension, String extended) { + public String addAbstractExtendsSigSimple(String extension, String extended) { + // abstract sig extension extends extended {} addSig( Pos.UNKNOWN, extension, - AlloyExprHelper.createVar(DashStrings.extendsName), - AlloyExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), + ExprHelper.createVar(DashStrings.extendsName), + ExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), new ArrayList(), null, AttrType.ABSTRACT.makenull(Pos.UNKNOWN), @@ -86,14 +121,42 @@ public void addAbstractExtendsSigSimple(String extension, String extended) { null, null, null); + String s = DashStrings.abstractName + space + DashStrings.sigName + space; + s += extension + space + DashStrings.extendsName + space; + s += extended; + s += " {} \n"; + return s; } - public void addOneExtendsSigSimple(String extension, String extended) { + public String addExtendsSigSimple(String extension, String extended) { + // one sig extension extends extended {} addSig( Pos.UNKNOWN, extension, - AlloyExprHelper.createVar(DashStrings.extendsName), - AlloyExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), + ExprHelper.createVar(DashStrings.extendsName), + ExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), + new ArrayList(), + null, + null, + null, + null, + null, + null, + null); + String s = DashStrings.sigName + space; + s += extension + space + DashStrings.extendsName + space; + s += extended; + s += " {} \n"; + return s; + } + + public String addOneExtendsSigSimple(String extension, String extended) { + // one sig extension extends extended {} + addSig( + Pos.UNKNOWN, + extension, + ExprHelper.createVar(DashStrings.extendsName), + ExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), new ArrayList(), null, null, @@ -102,8 +165,14 @@ public void addOneExtendsSigSimple(String extension, String extended) { null, null, null); + String s = DashStrings.oneName + space + DashStrings.sigName + space; + s += extension + space + DashStrings.extendsName + space; + s += extended; + s += " {} \n"; + return s; } - public void addSigWithDeclsSimple(String name, ArrayList decls) { + public String addSigWithDeclsSimple(String name, List decls) { + // sig name { decls } addSig( Pos.UNKNOWN, name, @@ -116,18 +185,20 @@ public void addSigWithDeclsSimple(String name, ArrayList decls) { null, null, null, - null); + null); + String s = DashStrings.sigName + space + name + space + "{\n"; + StringJoiner j = new StringJoiner(",\n"); + decls.forEach(i -> j.add(tab + i.toString())); + s += j.toString() + "\n}\n"; + return s; } - /* - public Sig addSig(Pos namePos, String name, ExprVar par, - List parents, List fields, Expr fact, Attr... attributes) - */ - public void addVarSigSimple(String name, ExprVar typ) { - // Electrum: var sig s in typ; + + public String addVarSigSimple(String name, ExprVar typ) { + // var sig s in typ {}; addSig( Pos.UNKNOWN, name, - AlloyExprHelper.createVar(DashStrings.inName), + ExprHelper.createVar(DashStrings.inName), Arrays.asList(typ), new ArrayList(), null, @@ -138,19 +209,38 @@ public void addVarSigSimple(String name, ExprVar typ) { null, AttrType.VARIABLE.makenull(Pos.UNKNOWN) ); + String s = DashStrings.varName + space + DashStrings.sigName + space; + s += name + space + DashStrings.inName + space; + s += typ.toString(); + s += " { }\n"; + return s; } - public void addOpenSimple(String name, List args, String aliasName) { - ExprVar alias = (aliasName == null) ? null : AlloyExprHelper.createVar(aliasName); - List argsExprList = new ArrayList(); - if (args != null) - for (String a: args) { - argsExprList.add(AlloyExprHelper.createVar(a)); - } - // problem: we can't add opens after other stuff has been parsed in the Alloy module - addOpen(null, null, AlloyExprHelper.createVar(name), argsExprList, alias); + public String addVarSigSimple(String name, List typ) { + // var sig s in typ {}; + addSig( + Pos.UNKNOWN, + name, + ExprHelper.createVar(DashStrings.inName), + typ, + new ArrayList(), + null, + null, + null, + null, + null, + null, + AttrType.VARIABLE.makenull(Pos.UNKNOWN) + ); + String s = DashStrings.varName + space + DashStrings.sigName + space; + s += name + space + DashStrings.inName + space; + s += typ.toString(); + s += " { }\n"; + return s; } + + /** * adding functions/predicates * @@ -158,9 +248,26 @@ public void addOpenSimple(String name, List args, String aliasName) { * f is a label * t is return type; null if predicate */ - public void addPredSimple(String name, List decls, ArrayList eList) { - Expr body = AlloyExprHelper.createAnd(eList); - addFunc(Pos.UNKNOWN, Pos.UNKNOWN, AlloyExprHelper.createVar(name), null, decls, null, body); + public String addPredSimple(String name, List decls, List eList) { + Expr body = ExprHelper.createAnd(eList); + addFunc(Pos.UNKNOWN, Pos.UNKNOWN, ExprHelper.createVar(name), null, decls, null, body); + String s = new String(); + s += DashStrings.predName + " " + name + "["; + StringJoiner j = new StringJoiner(", "); + decls.forEach(i -> j.add(i.toString())); + s += j.toString() + "] {\n"; + // s += body.toString(); + // as long as createAnd is working correctly this is okay + // and better formatted + s += tab; + StringJoiner sj = new StringJoiner("\n" + tab); + ExprToString eToString = new ExprToString(false); + for (Expr e: eList) { + sj.add(eToString.toString(e)); + } + s += sj.toString() + "\n"; + s+= "}\n"; + return s; } /** diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java index 767717f42..41f9f172b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java @@ -135,7 +135,7 @@ * class is used to merge them into a single "ONE_ARROW_ONE" token) */ -public final class DashFilter implements Scanner { +final class DashFilter implements Scanner { // ===================== PHASE 1 // ================================================================================== diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 3a076c240..8abfb595f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -2,113 +2,126 @@ // tmp import java.util.*; - import java.io.FileReader; import java.io.BufferedReader; - import java.io.FileNotFoundException; - import java.util.List; import java.util.ArrayList; import java.util.Arrays; +import java.util.Set; - +import edu.mit.csail.sdg.alloy4.Pair; +import edu.mit.csail.sdg.alloy4.A4Reporter; import edu.mit.csail.sdg.parser.CompModule; -import ca.uwaterloo.watform.core.DashSituation; -import ca.uwaterloo.watform.core.DashOptions; -import ca.uwaterloo.watform.core.DashStrings; + +import ca.uwaterloo.watform.core.*; import ca.uwaterloo.watform.ast.*; import ca.uwaterloo.watform.parser.CompModuleHelper; +import ca.uwaterloo.watform.dashtoalloy.DashToAlloy; public class DashModule extends CompModuleHelper { - // besides creating a DashState; parsing also has count buffers and create indexes - // for those buffers in order to have the correct open statements - private DashState root = null; + + // after parsing, these allow us to echo the Alloy-only parts + // of the file when printing public String filename = null; public Integer rootStartLine = null; public Integer rootEndLine = null; + + // derived during resolveAllDash phase private int numBuffers = 0; private SymbolTable symbolTable; + private StateTable stateTable = new StateTable(); + private TransTable transTable = new TransTable(); + + // once created and parsed, the following are + // the phases of a DashModule + // all operations happen in place + // to the final DashModule also contains the original + // parsed Dash + public static enum Status { + CREATED, + PARSED, + RESOLVED_DASH, + TRANSLATED_TO_ALLOY, + RESOLVED_ALLOY, + ERROR + } + private Status status = Status.CREATED; + + // strings for statements resulting from the translation + public String alloyString = new String(); + // the open statements added for Dash translation to Alloy + // go at the beginning of the model so these are separate from the others + private String opens = new String(); + // the statement for opening util/boolean is separate + // b/c we don't want to repeat it if the user has + // included it in the model + private String booleanOpen = new String(); // can't ever be initialized with another world public DashModule(String filename) { super(null,filename,null); - assert (!DashOptions.isElectrum && (DashOptions.isTcmc || DashOptions.isTraces)); - // do the open stmts for Dash after we know how many buffers - if (DashSituation.haveCountedBuffers) { - importModules(DashSituation.bufferElements); - // because DashModule is created again for every recursive call - // make sure we only do this once on second parsing pass - DashSituation.haveCountedBuffers = false; - } - + initializeDashModule(); } public DashModule(CompModule world, String filename, String path) { + // this function is just for compatibility with copied CompUtil -> DashUtil // super must be first statement in constructor super(world,filename,path); - // this function is just for compatibility with copied CompUtil -> DashUtil assert(world == null && path == null); + initializeDashModule(); + } + private void initializeDashModule() { + assert (!DashOptions.isElectrum && (DashOptions.isTcmc || DashOptions.isTraces)); // do the open stmts for Dash after we know how many buffers + // b/c the opens are parsed during parsing if (DashSituation.haveCountedBuffers) { - importModules(DashSituation.bufferElements); - // because DashModule is created again for every recursive call - // make sure we only do this once on second parsing pass + importModules(DashSituation.bufferElements, DashSituation.bufferNames); + // because a DashModule is created for every parse of a file + // including recursively for open stmts + // make sure we only do import on second parsing pass DashSituation.haveCountedBuffers = false; - } + } } - public int nextBufferIndex() { - numBuffers++; - return numBuffers - 1; - } - public int getNumBuffers() { - return numBuffers; - } - public void setRoot(DashState r) { - assert(r != null); - root = r; - } - + // printing ----------------------------------------------------- public String toString() { + if (status == Status.RESOLVED_ALLOY) return toStringAlloy(); + else return toStringRegular(); + } + public String toStringRegular() { String s = ""; - try { if (root != null) { BufferedReader br = new BufferedReader(new FileReader(getFilePath())); - for (int i = 0; i < rootStartLine-1; i++) { - s += br.readLine() + "\n"; - } - - // eventually print everything - if (root != null) { - s += root.toString(); - } - // skip stuff - for (int i = 0; i <= rootEndLine - rootStartLine+1; i++) { - br.readLine(); + String r; + for (int j= 0; j < rootStartLine-1; j++) { + r = br.readLine(); + s += r +"\n"; } + if (root != null) s += root.toString(); + // skip Dash stuff + for (int i = 0; i <= rootEndLine - rootStartLine+1; i++) br.readLine(); // add the rest of the lines - String k; - while ((k = br.readLine()) != null) { - s += k + "\n"; - } + String rr; + while ((rr = br.readLine()) != null) s += rr + "\n"; } else { - // just put all the lines in the string + // just put all the lines in the string because there is no Dash part BufferedReader br = new BufferedReader(new FileReader(getFilePath())); String k; - while ((k = br.readLine()) != null) { - s += k + "\n"; - } + while ((k = br.readLine()) != null) s += k + "\n"; } } catch (Exception FileNotFoundException) { // we know the file exists so this exception should never be thrown - // Fix this System.err.println("File Not Found"); } + return s; + } + public String toStringAlloy() { + String s = ""; /* if (rootStartLine != null) { s += "Path " + getFilePath() +"\n"; @@ -116,10 +129,172 @@ public String toString() { s += "Dash end line " + rootEndLine +"\n"; } */ - // how to print the Alloy stuff we add? - // s += sigsToString(); + + try { + if (root != null) { + BufferedReader br = new BufferedReader(new FileReader(getFilePath())); + // put the extra open statements at the beginning or right after 'module' + String r; + Integer k = 0; + Boolean writeBooleanOpen = true; + if (rootStartLine == 1) s += opens; + else { + for (int j= 0; j < rootStartLine-1; j++) { + k = j; + r = br.readLine(); + if (!(r.replaceAll("\\s+","").equals(""))) { + if (r.contains(DashStrings.moduleName) || r.contains(DashStrings.openName)) { + if (r.contains(DashStrings.openName) && r.contains(DashStrings.utilBooleanName)) writeBooleanOpen = false; + s += r +"\n"; + } else { + if (writeBooleanOpen) s += booleanOpen; + s += opens + "\n"; + // have to write the line after module/opens + s += r +"\n"; + break; + } + } else s += "\n"; + } + // there was nothing before "state" + if (k == rootStartLine-1) s += opens; + if (k+1 < rootStartLine-1) { + for (int i = k+1; i < rootStartLine -1 ; i++) s += br.readLine() + "\n"; + } + } + + // skip Dash stuff + for (int i = 0; i <= rootEndLine - rootStartLine+1; i++) br.readLine(); + // add the rest of the lines + String rr; + while ((rr = br.readLine()) != null) s += rr + "\n"; + s += alloyString; + } else { + // just put all the lines in the string because there is no Dash part + BufferedReader br = new BufferedReader(new FileReader(getFilePath())); + String k; + while ((k = br.readLine()) != null) s += k + "\n"; + } + } catch (Exception FileNotFoundException) { + // we know the file exists so this exception should never be thrown + System.err.println("File Not Found"); + } return s; } + + // needed during parsing ------------------------- + + public void importModules(List bufElements, List bufNames) { + System.out.println("Adding open stmts"); + String noAlias = null; + booleanOpen = this.addOpenSimple(DashStrings.utilBooleanName, null, noAlias); + if (DashOptions.isTcmc) + opens += this.addOpenSimple(DashStrings.utilCTLpathName, Arrays.asList(DashStrings.snapshotName), noAlias); + else if (DashOptions.isTraces) + opens += this.addOpenSimple(DashStrings.utilOrderingName, Arrays.asList(DashStrings.snapshotName),DashStrings.snapshotName); + // add the open statements for the buffers + if (bufElements != null ) + for (int i = 0; i < bufElements.size(); i++) + opens += this.addOpenSimple(DashStrings.utilBufferName, Arrays.asList(DashStrings.bufferIndexName+i, bufElements.get(i)), bufNames.get(i)); + } + + // constructors/accessor functions ------------------ + + public void setRoot(DashState r) { + assert(r == null); + root = r; + } + public boolean hasRoot() { + return (root != null); + } + public String getRootName() { + if (root != null) return root.name; + else { DashErrors.toAlloyNoDash(); return null; } + } + public int getNumBuffers() { + return numBuffers; + } + + public boolean isBasicState(String s) { + return (stateTable.isBasicState(s)); + } + + public List getImmChildren(String parent) { + return stateTable.getImmChildren(parent); + } + public Set getTransNames() { + return transTable.getTransNames(); + } + public boolean hasInternalEvents() { + return false; // (eventTable.hasInternalEvents()); + } + public boolean hasEnvironmentalEvents() { + return false; //(eventTable.hasExternalEvents()); + } + public boolean hasEvents() { + return false; //(hasInternalEvents() || hasEnvironmentalEvents()) + } + public boolean hasConcurrency() { + return stateTable.hasConcurrency(root.name); + } + public int getMaxDepthParams() { + // could precalculate this + return stateTable.getMaxDepthParams(); + } + public List getTransParams(String t) { + return transTable.getParams(t); + } + public List getAllParams() { + return stateTable.getAllParams(); + } + // processes --------------------------------------- + + public void resolveAllDash(A4Reporter rep) { + assert(status == Status.PARSED); + System.out.println("Resolving Dash"); + if (root != null ) { + // passed with empty set of params, empty set of ancestors + stateTable.setRoot(root.name); + root.resolveAllStates(stateTable,new ArrayList(),new ArrayList()); + // have to do states first so siblings of trans parent state + // are in place to search for src/dest + root.resolveAllTrans(stateTable,transTable); + System.out.println(stateTable.toString()); + System.out.println(transTable.toString()); + // if root has no substates? + // if no transitions? + stateTable.resolveAll(getRootName()); + transTable.resolveAll(); + } + status = Status.RESOLVED_DASH; + } + + public void translate() { + assert(status == Status.RESOLVED_DASH); + System.out.println("Translating to Alloy"); + // this is so we can partition the translation + // code into a different file + DashToAlloy d = new DashToAlloy(this); + // translation is done in place + d.translate(); + // if no errors + status = Status.TRANSLATED_TO_ALLOY; + } + public void resolveAllAlloy(A4Reporter rep) { + // this method in CompModule is static and takes a CompModule as + // input and returns one as output even though it makes all the + // changes in place on the input CompModule and then just + // returns it as the output + // so here we cast DashModule to CompModule and ignore the + // output CompModule + assert(status == Status.TRANSLATED_TO_ALLOY); + System.out.println("Resolving Alloy"); + // this quits if it throws an error + //resolveAll(rep == null ? A4Reporter.NOP : rep, this); + // if no errors + status = Status.RESOLVED_ALLOY; + } + + // helper functions for creating parts of module /* public static createDecl(ExprVar v, Expr e) { @@ -134,22 +309,7 @@ public static createSetDecl(String v, String typ) { */ - public void importModules(List bufElements) { - String noAlias = null; - this.addOpenSimple(DashStrings.utilBooleanName, null, noAlias); - if (DashOptions.isTcmc) { - this.addOpenSimple(DashStrings.utilCTLpathName, Arrays.asList(DashStrings.snapshotName), noAlias); - } - else if (DashOptions.isTraces) { - this.addOpenSimple(DashStrings.utilOrderingName, Arrays.asList(DashStrings.snapshotName),DashStrings.snapshotName); - } - // add the open statements for the buffers - // if (bufElements != null ) - //for (String name: bufElements) { - // perhaps this can be simplified - //this.addOpen(DashStrings.utilBufferName, Arrays.asList("fix this", "fixthis"), "fix this"); - //} - } + /* private List params; private StateTable stateTable; @@ -159,27 +319,11 @@ else if (DashOptions.isTraces) { public boolean hasConcurrency; - private int bufferMax; - // everything else is stored in the root State - - public void DashModule(DashState r) { - this.root = r; - // 0 is the first buffer number - this.bufferMax = -1 ; - } public String getRoot() { return root.name(); // as root it is already FQN } - public boolean hasInternalEvents() { - return (eventTable.hasInternalEvents()); - } - public boolean hasEnvironmentalEvents() { - return (eventTable.hasExternalEvents()); - } - public boolean hasEvents() { - return (hasInternalEvents() || hasEnvironmentalEvents()) - } + public List getAllInternalEventNames() { assert(r.hasAllInternalEvents()); return eventTable.getInternalEvent(); @@ -200,9 +344,7 @@ public List getTransGenEvents(String t) { public List getEventParams(String e) { return eventTable.get(e).getParams(); } - public List getAllParams() { - return params; - } + public int getNumParams() { return params.size(); } @@ -212,9 +354,7 @@ public List getBufferIndices() { iList.add(DashStrings.bufferIndexName + i) return iList; } - public boolean hasConcurrency() { - ///???? at least one concurrent state - } + public List getDynSymbols() { return symbolTable.values(); @@ -249,16 +389,8 @@ public int getBufferMax() { return bufferMax; } - public void resolveAll() { - root.resolveAll(); - // if root has no substates? - // if no transitions? - stateTable.resolveAll(); - transTable.resolveAll(); - } - public boolean isBasic(String s) { - return (stateTable.get(s).immediateChildren == null); - } + + */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashUtil.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashUtil.java index 3117e9e69..a82764965 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashUtil.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashUtil.java @@ -65,12 +65,12 @@ * static (classic Alloy); */ -public class DashUtil { +public final class DashUtil { /** * Constructor is private, since this class never needs to be instantiated. */ - public DashUtil() { + private DashUtil() { } // =============================================================================================================// diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java new file mode 100644 index 000000000..a206db660 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -0,0 +1,326 @@ +/* The StateTable maps: + FullyQualStateName -> info about state + + It is created during the resolveAll phase. +*/ + +package ca.uwaterloo.watform.parser; + +import java.io.*; + +import java.util.Set; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Collections; + +import ca.uwaterloo.watform.core.*; + +public class StateTable { + private HashMap table; + private boolean isResolved; + private String root; + + private String space = " "; + + /* nested class for elementes in the state table */ + public class StateElement { + // better than a tuple + private DashStrings.StateKind kind; // must exist AND/OR + private List params; // null if none + private String def; // null if none + // these all use fullQual names to point to trans in TransTable + // or states in this StateTable + private String parent; // null if none + // this could be a set b/c there are no dups and order + // doesn't matter, but lists are easier to work with + private List immChildren; // empty if none + private ArrayList transWithThisSrc; + private ArrayList transWithThisScope; + // all trans with this scope or descendant scope + private ArrayList allTransWithinState; + private ArrayList basicStatesEntered; // following defaults + private ArrayList basicStatesExited; + + + public StateElement( + DashStrings.StateKind k, + List prms, + String d, + String p, + List iChildren) { + assert(k != null); + assert(prms == null || !prms.isEmpty()); + assert(def == null || !def.isEmpty()); + assert(parent == null || !parent.isEmpty()); + assert(immChildren != null); // could be empty + this.kind = k; + this.params = prms; + this.def = d; + this.parent = p; + this.immChildren = iChildren; + this.transWithThisSrc = null; + this.transWithThisScope = null; + this.allTransWithinState = null; + this.basicStatesEntered = null; + this.basicStatesExited = null; + } + public String toString() { + String s = new String(); + s += "kind: "+kind +"\n"; + s += "params: "+params +"\n"; + s += "default: "+def+"\n"; + s += "parent: "+parent +"\n"; + s += "immChildren: "+immChildren +"\n"; + // add more + return s; + } + /* + this.substates = new ArrayList(); + this.dynSymbols = new ArrayList(); + this.events = new ArrayList(); + this.transitions = new ArrayList(); + this.init = new ArrayList(); + this.invariants = new ArrayList(); + + for (Object i: items) { + if (item instanceof DashState) { + this.substates.add(i); + } else if (item instanceof DashDecl) { + this.dynSymbols.add(i); + } else if (item instanceof DashEvent) { + this.events.add(i); + } else if (item instanceof DashTrans) { + this.transitions.add(i); + } else if (item instanceof DashInit) { + this.inits.add(i); + } else if (item instanceof DashInv) { + this.invariants.add(i); + } else { + // error + } + } + */ + public Boolean allAttributesEmpty() { + return (kind == null || + params == null || + def == null || + parent == null || + immChildren == null || + transWithThisSrc == null || + transWithThisScope == null || + allTransWithinState == null || + basicStatesEntered == null || + basicStatesExited == null); + } + public Boolean attributesSame(DashStrings.StateKind k,List prms, String d, String p, List iChildren) { + return (kind == k && + params.equals(prms) && + def.equals(d) && + parent.equals(p) && + immChildren.equals(iChildren)); + } + } + + + public StateTable() { + this.table = new HashMap(); + this.isResolved = false; + } + public void setRoot(String s) { + root = s; + } + public String getRoot() { + return root; + } + public String toString() { + String s = new String("STATE TABLE\n"); + for (String k:table.keySet()) { + s += " ----- \n"; + //System.out.println(s); + s += k + "\n"; + //System.out.println(s); + s += table.get(k).toString(); + //System.out.println(s); + } + return s; + } + public void add(String fqn) { + assert(!fqn.isEmpty()); + if (!table.containsKey(fqn)) + table.put(fqn,null); + // System.out.println("adding State table: "+fqn); + } + public void add( + String fqn, + DashStrings.StateKind k, + List prms, + String d, + String p, + List iChildren) { + // if its null, make it empty to not throw exceptions + if (iChildren == null) iChildren = new ArrayList(); + if (table.containsKey(fqn)) { + StateElement se = table.get(fqn); + if (se.allAttributesEmpty()) + table.replace(fqn, new StateElement(k,prms,d, p,iChildren)); + else if (!se.attributesSame(k,prms,d,p,iChildren)) + // hopefully not possible + DashErrors.addStateToStateTableDup(fqn); + } + else + table.put(fqn, new StateElement(k,prms,d,p,iChildren)); + System.out.println("adding to State table: "+fqn+space+prms+space+d+space+p+iChildren); + } + + public boolean containsKey(String q) { + return table.containsKey(q); + } + public boolean isBasicState(String q) { + if (table.containsKey(q)) + // shouldn't really need the check for OR here + return (table.get(q).kind == DashStrings.StateKind.OR && table.get(q).immChildren == null); + else { DashErrors.isBasicNotExist(q); return false; } + } + public List getParams(String s) { + if (table.containsKey(s)) + return table.get(s).params; + else { DashErrors.stateDoesNotExist("getParams", s); return null; } + } + public Boolean hasConcurrency(String s) { + if (table.containsKey(s)) { + if (table.get(s).kind == DashStrings.StateKind.AND) return true; + else + for (String k: table.get(s).immChildren) { + if (hasConcurrency(k)) return true; + } + return false; + } else { DashErrors.stateDoesNotExist("hasConcurrency", s); return null; } + } + public String getParent(String child) { + if (table.containsKey(child)) + return table.get(child).parent; // could be null if root + else { DashErrors.stateDoesNotExist("getParent", child); return null; } + } + public List getImmChildren(String parent) { + if (table.containsKey(parent)) + return table.get(parent).immChildren; + else { DashErrors.stateDoesNotExist("getImmChildren", parent); return null; } + } + public List getAllAnces(String fqn) { + // do not need to walk over tree for this operation; can just use FQNs + List fqnSplit = DashFQN.splitFQN(fqn); + List x = new ArrayList(); + // don't want to include the state itself + if (fqnSplit.size()-1 > 0) for (int i=0; i < fqnSplit.size()-1; i++) x.add(DashFQN.fqn(fqnSplit.subList(0,i+1))); + // list is in order from root, ...., fqn-1 on path + return x; + } + public String getClosestConcAnces(String s) { + // getAllAnces returns list from Root, ..., parentFQN-1 on path + // could also just walk back through parents + List allAnces = getAllAnces(s); + allAnces.add(s); + Collections.reverse(allAnces); + + String concAnces = null; + // allAnces cannot be empty b/c must have Root in it + for (String a:allAnces) { + if (getKind(a) == DashStrings.StateKind.AND) { + concAnces = a; + break; + } + } + return concAnces; // might be null + } + public List getAllNonConcStatesWithinThisState(String concAnces) { + if (concAnces!=null) return getAllNonConcDesc(concAnces); + else + // went back to root + return getAllNonConcDesc(root); + } + + public List getAllNonConcDesc(String s) { + // get all the descendants not in concurrent states + // s is not included + System.out.println("getAllNonConcDesc "+s); + List desc = new ArrayList(); + if (table.containsKey(s)) { + if (!table.get(s).immChildren.isEmpty()) { + System.out.println("HERE " + table.get(s).immChildren); + if (table.get(table.get(s).immChildren.get(0)).kind != DashStrings.StateKind.AND) { + for (String c: table.get(s).immChildren) { + desc.addAll(getAllNonConcDesc(c)); + desc.add(c); + } + return desc; + } else return desc; // empty list + } else return desc; // empty list + } + else { DashErrors.stateDoesNotExist("getAllNonConcDesc", s); return null; } + } + public DashStrings.StateKind getKind(String s) { + if (table.containsKey(s)) + return table.get(s).kind; + else { DashErrors.stateDoesNotExist("getKind", s); return null; } + } + public int getMaxDepthParams() { + return getMaxDepthParams(root); + } + public int getMaxDepthParams(String s) { + int max = 0; + for (String c: getImmChildren(s)) { + if (getParams(c) != null) + if (max < getParams(c).size()) max = getParams(c).size(); + if (max < getMaxDepthParams(c)) max = getMaxDepthParams(c); + } + return max; + } + public List getAllParams() { + // variety of ways of doing this operation + Set allParams = new HashSet(); + for (String k: table.keySet()) { + if (table.get(k).params != null) allParams.addAll(table.get(k).params); + } + return DashUtilFcns.setToList(allParams); + } + public void resolveAll(String root) { + System.out.println("Resolving state table"); + for (String k: table.keySet()) + if (table.get(k) == null) DashErrors.transUsesNonExistentState(k); + // walk down parent to children and pass back info + isResolved = true; + } + /* + public void addEnterExit(String s, ArrayList enter, ArrayList exit) { + if (s in table.keys()) { + table.get(s).basicStatesEntered = enter; + table.get(s).basicStatesExited = exit; + } else { + // error + } + } + public ArrayList getParams(String s) { + assert(isResolved == true); + return table.get(s).params; + } + public ArrayList getBasicStatesEntered(String s) { + assert(isResolved == true); + return table.get(s).basicStatesEntered; + } + public ArrayList getBasicStatesExited(String s) { + assert(isResolved == true); + return table.get(s).basicStatesExited; + } + public Expr createStateArrow(String s) { + Expr e = createVar(s); + for (i:s.params.reverse()) { + e = createArrow(createVar(i),e); + } + return e; + } + + */ + +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java new file mode 100644 index 000000000..97bf805ca --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -0,0 +1,131 @@ +/* The StateTable maps: + FullyQualStateName -> info about state + + It is created during the resolveAll phase. +*/ + +package ca.uwaterloo.watform.parser; + +import java.io.*; + +import java.util.Set; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; + +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.*; +import ca.uwaterloo.watform.ast.*; + +public class TransTable { + + private HashMap table; + private boolean isResolved; + + public class TransElement { + public List params; // null if no params + public String src; // FQN + public String dest; // FQN + public Expr when; // just one? + public Expr on; + public List action; + public List send; + + /* + public List changedDynSymbols; // includes buffers + + // don't need scope - it is calculated from FQNs + public Set higherPriority; + public Set orthogonal; // keep both lists just in case + public Set notOrthogonal; + public Set changedDynSymbols; + */ + public TransElement( + List prms, + String s, // fqn + String d // fqn + ) + /* + DashEvent w, + DashExpr o, + List a, + List s + ) + */ + { + this.params = prms; + this.src = s; + this.dest = d; + /* + this.when = w; + this.on = o; + this.action = a; + this.send = s; + this.changedDynSymbols = null; // not yet known; consists of FQN list + this.higherPriorityTrans = null; // not yet known; FQNs + this.notOrthogonal = null; // not yet known; FQNs + this.orthogonal = null; + this.basicStatesEntered = null; + this.basicStatesExited = null; + */ + } + public String toString() { + String s = new String(); + s += "params: "+params +"\n"; + s += "src: "+src +"\n"; + s += "dest: "+dest +"\n"; + // add more + return s; + } + } + + public TransTable() { + table = new HashMap(); + isResolved = false; + } + public void add( + String fqn, + List params, + String s, + String d) + /* + DashEvent w, + DashExpr o, + List a, + List se) { + */ + { + System.out.println("Adding "+fqn); + assert(!fqn.isEmpty()); + assert(params == null | !params.isEmpty()); + assert(!s.isEmpty()); + assert(!d.isEmpty()); + if (table.containsKey(fqn)) DashErrors.transTableDup(fqn); + else table.put(fqn, new TransElement(params,s,d)); + } + public String toString() { + String s = new String(); + s += "TRANS TABLE\n"; + for (String k:table.keySet()) { + s += " ----- \n"; + s += k + "\n"; + s += table.get(k).toString(); + } + return s; + } + public Set getTransNames() { + return table.keySet(); + } + public List getParams(String t) { + if (table.containsKey(t)) return table.get(t).params; + else { DashErrors.transDoesNotExist("getParams", t); return null; } + } + public void resolveAll() { + System.out.println("Resolving trans table"); + if (getTransNames().isEmpty()) DashErrors.noTrans(); + // check all source and dest exist in state table + isResolved = true; + } + +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh index f097ee44d..7a83547fe 100755 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh @@ -58,7 +58,7 @@ rm CompUtil.java -rm *.java-e +rm *.java-e *.javat # make DashModule an extension of DashCompModule diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java new file mode 100644 index 000000000..a9ff38c8c --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java @@ -0,0 +1,31 @@ +package org.alloytools.alloy.dash; + +import java.util.*; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +import ca.uwaterloo.watform.core.*; + +public class DashCoreFQNTests { + + @Test + public void testFQN1() { + String k = DashFQN.longestCommonFQN("Root/A","Root/B"); + assertEquals(k,"Root"); + } + + @Test + public void testFQN2() { + String k = DashFQN.longestCommonFQN("Root/A/Bit","Root/B/Bit"); + assertEquals(k,"Root"); + } + + @Test + public void testFQN3() { + String k = DashFQN.longestCommonFQN("Root/B/Bit","Root/B/Bit"); + assertEquals(k,"Root/B/Bit"); + } + + +} \ No newline at end of file diff --git a/pbuild.sh b/pbuild.sh index 82b4bc80a..ba8291580 100755 --- a/pbuild.sh +++ b/pbuild.sh @@ -2,7 +2,14 @@ # tmp while working on grammar/parser +# copy DashFilter.java, DashUtil.java +cd org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser +./install-alloy-files.sh +cd ../../../../../../../../ + +# build Dash.cup, Dash.lex cd org.alloytools.alloy.dash/parser ./install-alloy-files.sh cd ../.. + ./gradlew build \ No newline at end of file From b50c6fd687b32cb0b12048745e30d32dc20aef38 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 17 Mar 2023 11:04:02 -0400 Subject: [PATCH 024/129] broken build but up to date with master --- org.alloytools.alloy.dash/parser/Dash.cup | 12 ------------ org.alloytools.alloy.dash/parser/Dash.lex | 6 +----- .../parser/install-alloy-files.sh | 16 ++++++++-------- .../ca/uwaterloo/watform/parser/DashFilter.java | 4 +--- 4 files changed, 10 insertions(+), 28 deletions(-) diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index 9a927d7bf..02ba2906c 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -181,7 +181,6 @@ parser code {: ch.put(DashSym.ENUM, "enum"); ch.put(DashSym.EQUALS, "="); ch.put(DashSym.EXACTLY, "exactly"); - ch.put(DashSym.EXH, "exh"); ch.put(DashSym.EXPECT, "expect"); ch.put(DashSym.EXTENDS, "extends"); ch.put(DashSym.FACT, "fact"); @@ -219,7 +218,6 @@ parser code {: ch.put(DashSym.ONE, "one"); ch.put(DashSym.OPEN, "open"); ch.put(DashSym.OR, "||"); - ch.put(DashSym.PART, "part"); ch.put(DashSym.PLUS, "+"); ch.put(DashSym.PLUSPLUS, "++"); ch.put(DashSym.PRED, "pred"); @@ -493,7 +491,6 @@ terminal Pos ELSE; // else terminal Pos ENUM; // enum terminal Pos EQUALS; // = == terminal Pos EXACTLY; // exactly -terminal Pos EXH; // exh exhaustive terminal Pos EXPECT; // expect terminal Pos EXTENDS; // extends terminal Pos FACT; // fact @@ -531,7 +528,6 @@ terminal Pos ONE2; // one // The filter enables us to di terminal Pos ONE; // one // The filter enables us to disambiguate terminal Pos OPEN; // open terminal Pos OR; // || or -terminal Pos PART; // part partition terminal Pos PLUS; // + terminal Pos PLUSPLUS; // ++ terminal Pos PRED; // pred @@ -917,8 +913,6 @@ Namex ::= Namex:a COMMA Name:b {: nod(b); a.add(b); RESULT= Namex ::= Namex:a COMMA EXACTLY Name:b {: nod(b); a.add(null); a.add(b); RESULT=a; :}; // [electrum] additional parameter for variable declarations (for fields) -Decla ::= PART:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; -Decla ::= EXH:k Names COLON Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; Decla ::= DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(null, k, null, null, a, mult(b)); :}; Decla ::= PRIVATE:p DISJ:k Names:a COLON Expr:b {: RESULT=new Decl(p, k, null, null, a, mult(b)); :}; Decla ::= PRIVATE:p Names:a COLON Expr:b {: RESULT=new Decl(p, null, null, null, a, mult(b)); :}; @@ -929,8 +923,6 @@ Decla ::= VAR:v PRIVATE:p DISJ:k Names:a COLON Expr:b {: RESULT Decla ::= VAR:v PRIVATE:p Names:a COLON Expr:b {: RESULT=new Decl(p, null, null, v, a, mult(b)); :}; Decla ::= VAR:v Names:a COLON Expr:b {: RESULT=new Decl(null, null, null, v, a, mult(b)); :}; -Decla ::= PART:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; -Decla ::= EXH:k Names COLON DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; Decla ::= DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(null, k, d, null, a, mult(b)); :}; Decla ::= PRIVATE:p DISJ:k Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, k, d, null, a, mult(b)); :}; Decla ::= PRIVATE:p Names:a COLON DISJ:d Expr:b {: RESULT=new Decl(p, null, d, null, a, mult(b)); :}; @@ -943,15 +935,11 @@ Decla ::= VAR:v Names:a COLON DISJ:d Expr:b {: RESULT Declb ::= Decla:x {: RESULT=x; :}; -Declb ::= PART:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; -Declb ::= EXH:k Names EQUALS Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; Declb ::= DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; Declb ::= PRIVATE DISJ:d Names EQUALS Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; Declb ::= PRIVATE:p Names:a EQUALS Expr:b {: RESULT=new Decl(p, null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; Declb ::= Names:a EQUALS Expr:b {: RESULT=new Decl(null, null, null, null, a, ExprUnary.Op.EXACTLYOF.make(null, b)); :}; -Declb ::= PART:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "part"); :}; -Declb ::= EXH:k Names EQUALS DISJ Expr {: if (1==1) throw CompModule.hint(k, "exh"); :}; Declb ::= DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; Declb ::= PRIVATE DISJ Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; Declb ::= PRIVATE Names EQUALS DISJ:d Expr {: if (1==1) throw new ErrorSyntax(d, "Defined fields cannot be disjoint."); :}; diff --git a/org.alloytools.alloy.dash/parser/Dash.lex b/org.alloytools.alloy.dash/parser/Dash.lex index 228d8bfd0..c241001b1 100644 --- a/org.alloytools.alloy.dash/parser/Dash.lex +++ b/org.alloytools.alloy.dash/parser/Dash.lex @@ -194,8 +194,6 @@ import edu.mit.csail.sdg.parser.CompModule; "else" { return alloy_sym(yytext(), DashSym.ELSE );} "enum" { return alloy_sym(yytext(), DashSym.ENUM );} "exactly" { return alloy_sym(yytext(), DashSym.EXACTLY );} -"exhaustive" { return alloy_sym(yytext(), DashSym.EXH );} -"exh" { return alloy_sym(yytext(), DashSym.EXH );} "expect" { return alloy_sym(yytext(), DashSym.EXPECT );} "extends" { return alloy_sym(yytext(), DashSym.EXTENDS );} "fact" { return alloy_sym(yytext(), DashSym.FACT );} @@ -216,8 +214,6 @@ import edu.mit.csail.sdg.parser.CompModule; "one" { return alloy_sym(yytext(), DashSym.ONE );} "open" { return alloy_sym(yytext(), DashSym.OPEN );} "or" { return alloy_sym(yytext(), DashSym.OR );} -"partition" { return alloy_sym(yytext(), DashSym.PART );} -"part" { return alloy_sym(yytext(), DashSym.PART );} "pred" { return alloy_sym(yytext(), DashSym.PRED );} "private" { return alloy_sym(yytext(), DashSym.PRIVATE );} "run" { return alloy_sym(yytext(), DashSym.RUN );} @@ -245,7 +241,6 @@ import edu.mit.csail.sdg.parser.CompModule; "'" { return alloy_sym(yytext(), DashSym.PRIME );} "‘" { return alloy_sym(yytext(), DashSym.PRIME );} "’" { return alloy_sym(yytext(), DashSym.PRIME );} - //DASH SYNTAX ADDITIONS "state" { return alloy_sym(yytext(), DashSym.STATE );} @@ -273,6 +268,7 @@ import edu.mit.csail.sdg.parser.CompModule; //END DASH SYNTAX ADDITIONS + [\"] ([^\\\"] | ("\\" .))* [\"] [\$0-9a-zA-Z_\"] [\$0-9a-zA-Z_\"]* { throw new ErrorSyntax(alloy_here(yytext()),"String literal cannot be followed by a legal identifier character."); } [\"] ([^\\\"] | ("\\" .))* [\"] { return alloy_string(yytext()); } [\"] ([^\\\"] | ("\\" .))* { throw new ErrorSyntax(alloy_here(yytext()),"String literal is missing its closing \" character"); } diff --git a/org.alloytools.alloy.dash/parser/install-alloy-files.sh b/org.alloytools.alloy.dash/parser/install-alloy-files.sh index b2b20773c..ddd5ad894 100755 --- a/org.alloytools.alloy.dash/parser/install-alloy-files.sh +++ b/org.alloytools.alloy.dash/parser/install-alloy-files.sh @@ -25,9 +25,9 @@ sed -i -e 's/CompSym/DashSym/g' Alloy.lex #sed -i -e 's/CompModule/DashModule/g' Alloy.lex # FILE LINE NUMBER DEPENDENCE BELOW -sed -n -e '1,24p' Alloy.lex > part1.txt -sed -n -e '25,240p' Alloy.lex > part2.txt -sed -n -e '241,$p' Alloy.lex > part3.txt +sed -n -e '1,24p' Alloy.lex > part1.txt # to the end of imports +sed -n -e '25,235p' Alloy.lex > part2.txt # to the end of tokens +sed -n -e '236,$p' Alloy.lex > part3.txt { echo "$msg"; cat part1.txt Dash-lex-imports.txt part2.txt Dash-lex-addition.txt part3.txt ; } > Dash.lex rm Alloy.lex part*.txt rm *.lex-e @@ -50,11 +50,11 @@ sed -i -e 's/CompModule u = new CompModule(root, filename, prefix);/DashModule u # split it up and put it back together # FILE LINE NUMBER DEPENDENCE BELOW -sed -n -e '1,61p' Alloy.cup > part1.txt # to end of symbols -sed -n -e '62,249p' Alloy.cup > part2.txt -sed -n -e '250,533p' Alloy.cup > part3.txt # to end of terminals -sed -n -e '534,621p' Alloy.cup > part4.txt # to end of Dash-cup-nonterminals -sed -n -e '622,$p' Alloy.cup > part5.txt # to end of file +sed -n -e '1,61p' Alloy.cup > part1.txt # to end of imports +sed -n -e '62,247p' Alloy.cup > part2.txt # to the end of symbols +sed -n -e '248,529p' Alloy.cup > part3.txt # to end of terminals +sed -n -e '530,617p' Alloy.cup > part4.txt # to end of nonterminals +sed -n -e '618,$p' Alloy.cup > part5.txt # to end of file { echo "$msg"; cat part1.txt Dash-cup-imports.txt part2.txt Dash-cup-symbols.txt part3.txt Dash-cup-terminals.txt part4.txt Dash-cup-nonterminals.txt part5.txt Dash-cup-grammar.txt; } > Dash.cup rm Alloy.cup part*.txt rm *.cup-e diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java index 41f9f172b..0f026a8d1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashFilter.java @@ -33,7 +33,6 @@ import static edu.mit.csail.sdg.parser.CompSym.DISJ; import static edu.mit.csail.sdg.parser.CompSym.EOF; import static edu.mit.csail.sdg.parser.CompSym.EQUALS; -import static edu.mit.csail.sdg.parser.CompSym.EXH; import static edu.mit.csail.sdg.parser.CompSym.FUN; import static edu.mit.csail.sdg.parser.CompSym.GT; import static edu.mit.csail.sdg.parser.CompSym.GTE; @@ -76,7 +75,6 @@ import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_LONE; import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_ONE; import static edu.mit.csail.sdg.parser.CompSym.ONE_ARROW_SOME; -import static edu.mit.csail.sdg.parser.CompSym.PART; import static edu.mit.csail.sdg.parser.CompSym.PRED; import static edu.mit.csail.sdg.parser.CompSym.PRIVATE; import static edu.mit.csail.sdg.parser.CompSym.RBRACE; @@ -197,7 +195,7 @@ else if (a.sym == SOME) temp.add(b = myread()); if (b.sym == PRIVATE) temp.add(b = myread()); - if (b.sym == DISJ || b.sym == PART || b.sym == EXH) + if (b.sym == DISJ) temp.add(b = myread()); while (b.sym == ID) { temp.add(b = myread()); From dd7d37ec3ee1305c48e21121611b13ffa5b5ae35 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 5 Apr 2023 10:45:21 -0400 Subject: [PATCH 025/129] adding testing --- .../watform/dash4whole/DashMainTest.java | 49 +++ .../ca/uwaterloo/watform/ast/DashRef.java | 44 +++ .../alloy/dash/DashParseFailTests.java | 105 +++++++ .../alloy/dash/DashPassParseWffTests.java | 56 ++++ .../alloytools/alloy/dash/DashStateTests.java | 283 ++++++++++++++++++ .../alloy/dash/DashWffFailTests.java | 101 +++++++ .../src/test/resources/parsefail/test11.dsh | 5 + .../parsefail/trivial-param-state-error.dsh | 6 + .../resources/pass/getAllNonConcDesc1.dsh | 21 ++ .../src/test/resources/pass/getRegion1.dsh | 23 ++ .../test/resources/pass/noDefaultNeeded1.dsh | 7 + .../test/resources/pass/noDefaultNeeded2.dsh | 7 + .../src/test/resources/pass/noSrc1.dsh | 8 + .../src/test/resources/pass/noSrc2.dsh | 12 + .../src/test/resources/pass/noSrcDest1.dsh | 3 + .../src/test/resources/pass/otherSrcDest1.dsh | 17 ++ .../src/test/resources/pass/paramSrcDest1.dsh | 5 + .../src/test/resources/pass/paramSrcDest2.dsh | 10 + .../src/test/resources/pass/paramSrcDest3.dsh | 10 + .../src/test/resources/pass/process-ref.dsh | 5 + .../src/test/resources/pass/scopeParam1.dsh | 10 + .../src/test/resources/pass/scopeParam2.dsh | 12 + .../src/test/resources/pass/scopeParam3.dsh | 12 + .../src/test/resources/pass/srcDestFQN1.dsh | 17 ++ .../src/test/resources/pass/test1.dsh | 11 + .../src/test/resources/pass/test2.dsh | 8 + .../wfffail/allConcDefaultStates1.dsh | 6 + .../wfffail/allConcDefaultStates2.dsh | 7 + .../resources/wfffail/ambiguousSrcDest1.dsh | 12 + .../wfffail/and-cross-trans-2-error.dsh | 15 + .../wfffail/and-cross-trans-error.dsh | 12 + .../test/resources/wfffail/buffer-error.dsh | 7 + .../resources/wfffail/dupSiblingNames1.dsh | 5 + .../resources/wfffail/dupSiblingNames2.dsh | 4 + .../test/resources/wfffail/dupTransName1.dsh | 4 + .../test/resources/wfffail/dupTransName2.dsh | 6 + .../fqnSrcDestMustHaveRightNumberParams1.dsh | 10 + .../resources/wfffail/moreThanOneSrcDest1.dsh | 8 + .../resources/wfffail/moreThanOneSrcDest2.dsh | 16 + .../resources/wfffail/moreThanOneSrcDest3.dsh | 7 + .../wfffail/noDefaultNeeded-traces.als | 0 .../resources/wfffail/noDefaultState1.dsh | 4 + .../resources/wfffail/noDefaultState2.dsh | 4 + .../src/test/resources/wfffail/noStates1.dsh | 1 + .../src/test/resources/wfffail/noStates2.dsh | 7 + .../src/test/resources/wfffail/noTrans1.dsh | 1 + .../src/test/resources/wfffail/noTrans2.dsh | 8 + .../src/test/resources/wfffail/one-guard.dsh | 16 + .../test/resources/wfffail/onlyOneState1.dsh | 7 + .../test/resources/wfffail/onlyOneState2.dsh | 2 + .../test/resources/wfffail/open1-error.dsh | 7 + .../test/resources/wfffail/open2-error.dsh | 11 + .../test/resources/wfffail/open3-error.dsh | 13 + .../test/resources/wfffail/open4-error.dsh | 9 + .../wfffail/srcDestCantHaveParam1.dsh | 10 + .../wfffail/srcDestUnknown4-traces.als | 81 +++++ .../resources/wfffail/stateNameCantBeFQN1.dsh | 4 + .../resources/wfffail/stateNameCantBeFQN2.dsh | 4 + .../src/test/resources/wfffail/test0.dsh | 5 + .../src/test/resources/wfffail/test10.dsh | 27 ++ .../src/test/resources/wfffail/test3.dsh | 6 + .../src/test/resources/wfffail/test5.dsh | 35 +++ .../src/test/resources/wfffail/test6.dsh | 24 ++ .../src/test/resources/wfffail/test7.dsh | 28 ++ .../src/test/resources/wfffail/test8.dsh | 19 ++ .../src/test/resources/wfffail/test9.dsh | 24 ++ .../wfffail/tooManyDefaultStates1.dsh | 5 + .../wfffail/tooManyDefaultStates2.dsh | 6 + .../wfffail/trivial-conc-2-error.dsh | 13 + .../resources/wfffail/trivial-conc-error.dsh | 9 + .../resources/wfffail/trivial-hier-error.dsh | 9 + .../resources/wfffail/unknownSrcDest1.dsh | 9 + .../resources/wfffail/unknownSrcDest2.dsh | 9 + .../resources/wfffail/unknownSrcDest3.dsh | 18 ++ .../resources/wfffail/unknownSrcDest4.dsh | 14 + 75 files changed, 1415 insertions(+) create mode 100644 org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java create mode 100644 org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashParseFailTests.java create mode 100644 org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashPassParseWffTests.java create mode 100644 org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java create mode 100644 org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java create mode 100644 org.alloytools.alloy.dash/src/test/resources/parsefail/test11.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/parsefail/trivial-param-state-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getAllNonConcDesc1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getRegion1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/noDefaultNeeded1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/noDefaultNeeded2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/noSrc1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/noSrc2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/noSrcDest1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/otherSrcDest1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest3.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/process-ref.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/scopeParam1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/scopeParam2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/scopeParam3.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/srcDestFQN1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/test1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/test2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/allConcDefaultStates1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/allConcDefaultStates2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/ambiguousSrcDest1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/and-cross-trans-2-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/and-cross-trans-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/buffer-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/dupSiblingNames1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/dupSiblingNames2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/dupTransName1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/dupTransName2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/fqnSrcDestMustHaveRightNumberParams1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest3.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultNeeded-traces.als create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultState1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultState2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/noStates1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/noStates2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/one-guard.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/onlyOneState1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/onlyOneState2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/open1-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/open2-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/open3-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/open4-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/srcDestCantHaveParam1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/srcDestUnknown4-traces.als create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/stateNameCantBeFQN1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/stateNameCantBeFQN2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test0.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test10.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test3.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test5.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test6.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test7.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test8.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test9.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/tooManyDefaultStates1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/tooManyDefaultStates2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-conc-2-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-conc-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-hier-error.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest3.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest4.dsh diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java new file mode 100644 index 000000000..b53a68fca --- /dev/null +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java @@ -0,0 +1,49 @@ +/* + The purpose of this code is to help + with debugging +*/ + +package ca.uwaterloo.watform.dash4whole; + +import java.util.*; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.Files; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; + +import edu.mit.csail.sdg.alloy4.A4Reporter; +import edu.mit.csail.sdg.alloy4viz.VizGUI; +import edu.mit.csail.sdg.ast.Command; +import edu.mit.csail.sdg.parser.CompModule; +import edu.mit.csail.sdg.translator.A4Options; +import edu.mit.csail.sdg.translator.A4Solution; +import edu.mit.csail.sdg.translator.TranslateAlloyToKodkod; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.mainfunctions.MainFunctions; + + + + +public class DashMainTest { + + + + + public static void main(String args[]) { + + System.out.println("Starting DashMainTest"); + A4Reporter rep = new A4Reporter(); + DashModule d = + MainFunctions.parseAndResolveDashFile( + "/Users/nday/UW/github/org.alloytools.alloy/org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans1.dsh",rep); + System.out.println("Finish DashMainTest"); + } +} + diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java new file mode 100644 index 000000000..634ee50a9 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java @@ -0,0 +1,44 @@ +package ca.uwaterloo.watform.ast; + +import java.util.List; +import java.util.ArrayList; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashUtilFcns; + +public class DashRef extends Dash { + private String name; + private List paramValues; + + public DashRef(Pos p, String n, List eList) { + this.pos = p; + this.name = n; + assert(n != null); + assert(!n.isEmpty()); + assert(eList != null); + this.paramValues = eList; + } + + public DashRef(String n, List eList) { + this.pos = Pos.UNKNOWN; + this.name = n; + this.paramValues = eList; + } + + public String getName() { + return name; + } + public List getParamValues() { + return paramValues; + } + public String toString() { + String r = ""; + r += name + "[" + DashUtilFcns.strCommaList(paramValues) +"]"; + return r; + } + public static List emptyParamValuesList() { + return new ArrayList(); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashParseFailTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashParseFailTests.java new file mode 100644 index 000000000..bd2a8b960 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashParseFailTests.java @@ -0,0 +1,105 @@ +/* + Tests for appropriate parsing failures. + + It tests every file in src/resources/parsefail + to make sure it fails parsing. +*/ + +package org.alloytools.alloy.dash; + +import java.util.*; +import java.io.IOException; +import java.io.File; +import java.nio.file.Files; +import java.nio.charset.Charset; +import java.util.stream.Stream; +import java.util.stream.IntStream; +import java.util.Collections; +import java.util.stream.Collectors; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import org.apache.commons.io.FileUtils; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; + +import java.net.URL; + + +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorFatal; + +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.DashUtil; + + + + +@RunWith(Parameterized.class) + +public class DashParseFailTests { + + private static String resourcePath = "src/test/resources/parsefail"; + private final String fileName; + + public DashParseFailTests(String f) { + this.fileName = f; + } + + // list of file names that are parameters to test + @Parameterized.Parameters + public static List fileNames() { + File dir = new File(resourcePath); + return Arrays.asList(dir.listFiles()).stream().filter(i -> !i.isHidden()).map (i -> i.getName()).collect(Collectors.toList()); + + } + + @Test + public void test() { + File dir = new File(resourcePath); + String absolutePath = new File(resourcePath).getAbsolutePath(); + assertThrows(ErrorSyntax.class, () -> { + DashUtil.parseEverything_fromFileDash(null,null,absolutePath+"/"+fileName); + }); + } + + + + + // leftover - not used because multiline strings in Java 1.8 are a pain + @Rule + public TemporaryFolder folder= new TemporaryFolder(); + + // leftover - not used because multiline strings in Java 1.8 are a pain + // uses static DashModule parseEverything_fromStringDash(A4Reporter rep, String content) + public DashModule parseFromString(String content) throws IOException { + File tmpFile = folder.newFile("myfile.txt"); + FileUtils.writeStringToFile(tmpFile, content, Charset.defaultCharset()); + return DashUtil.parseEverything_fromFileDash(null, null, tmpFile.getCanonicalPath()); + //Note: File is guaranteed to be deleted after the test finishes. + } + + /* + // src/test/resource is not getting copied to the classpath + // so we'll use an alternative + @Test + public void parseTest1() { + File dir = new File(resourcePath); + int fileCount = countFilesInCurrentDirectory(dir); + assertTrue(fileCount == 1); + // String absolutePath = new File(resourcePath).getAbsolutePath(); + //DashUtil.parseEverything_fromFileDash(null,null,absolutePath+"/test1.dsh"); + } + */ + + + } diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashPassParseWffTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashPassParseWffTests.java new file mode 100644 index 000000000..5ef076690 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashPassParseWffTests.java @@ -0,0 +1,56 @@ +/* + let's check that the tests in the pass directory + pass the parse and wff checks first +*/ + +package org.alloytools.alloy.dash; + +import java.util.*; +import java.io.File; +import java.util.Collections; +import java.util.stream.Collectors; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import ca.uwaterloo.watform.parser.DashUtil; + + + + +@RunWith(Parameterized.class) + +public class DashPassParseWffTests { + + private static String resourcePath = "src/test/resources/pass"; + private final String fileName; + + public DashPassParseWffTests(String f) { + this.fileName = f; + } + + // list of file names that are parameters to test + @Parameterized.Parameters + public static List fileNames() { + File dir = new File(resourcePath); + //int fileCount = countFilesInCurrentDirectory(dir); + // filenaming starts at 0 + return Arrays.asList(dir.listFiles()) + .stream() + .filter(i -> !i.isHidden()) + .map (i -> i.getName()) + .collect(Collectors.toList()); + + } + + @Test + public void test() { + File dir = new File(resourcePath); + String absolutePath = new File(resourcePath).getAbsolutePath(); + DashUtil.parseEverything_fromFileDash(null,null,absolutePath+"/"+fileName); + } + + + } diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java new file mode 100644 index 000000000..938b154b9 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java @@ -0,0 +1,283 @@ +/* + let's check that the tests in the pass directory + pass the parse and wff checks first +*/ + +package org.alloytools.alloy.dash; + +import java.util.*; +import java.io.File; +import java.util.Collections; +import java.util.stream.Collectors; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import edu.mit.csail.sdg.alloy4.A4Reporter; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.mainfunctions.MainFunctions; + +public class DashStateTests { + + private static String resourcePath = "src/test/resources/pass"; + + public static DashModule test(String fileName) { + File dir = new File(resourcePath); + String absolutePath = new File(resourcePath).getAbsolutePath(); + A4Reporter rep = new A4Reporter(); + return MainFunctions.parseAndResolveDashFile(absolutePath+"/"+fileName+".dsh", rep); + } + public List ll(String[] k) { + return Arrays.asList(k); + } + + // src/dest ------------------ + + public static String src(DashModule d, String s) { + return d.getTransSrc(s).toString(); + } + public static String dest(DashModule d, String s) { + return d.getTransDest(s).toString(); + } + + @Test + public void noDefaultNeededTest1() { + DashModule d = test("noDefaultNeeded1"); + List result = Arrays.asList(new String[]{"Root/S"}); + assertTrue(d.getDefaults("Root").equals(result)); + } + @Test + public void noDefaultNeededTest2() { + DashModule d = test("noDefaultNeeded2"); + List result = Arrays.asList(new String[]{"Root/C"}); + assertTrue(d.getDefaults("Root").equals(result)); + } + + @Test + public void noSrcDest1() { + DashModule d = test("noSrcDest1"); + assertTrue(src(d,"Root/t1").equals("Root[]")); + assertTrue(dest(d,"Root/t1").equals("Root[]")); + } + @Test + public void noSrc1() { + DashModule d = test("noSrc1"); + assertTrue(src(d,"Root/S1/t1").equals("Root/S1[]")); + assertTrue(dest(d,"Root/S1/t1").equals("Root/S2[]")); + } + @Test + public void noSrc2() { + DashModule d = test("noSrc2"); + assertTrue(src(d,"Root/S1/t1").equals("Root/S1[]")); + assertTrue(dest(d,"Root/S1/t1").equals("Root/S2/S3/S4[]")); + } + + @Test + public void otherSrcDest1() { + DashModule d = test("otherSrcDest1"); + assertTrue(src(d,"Root/S1/t1").equals("Root/S1[]")); + assertTrue(dest(d,"Root/S1/t1").equals("Root/S2/S3/S4[]")); + assertTrue(src(d,"Root/S2/t2").equals("Root/S2/S3[]")); + assertTrue(dest(d,"Root/S2/t2").equals("Root/S2[]")); + } + + @Test + public void srcDestFQN1() { + DashModule d = test("srcDestFQN1"); + assertTrue(src(d,"Root/S1/t1").equals("Root/S1[]")); + assertTrue(dest(d,"Root/S1/t1").equals("Root/S1/S7[]")); + assertTrue(src(d,"Root/S2/S3/S4/t2").equals("Root/S2/S3/S4[]")); + assertTrue(dest(d,"Root/S2/S3/S4/t2").equals("Root/S1/S7[]")); + } + + @Test + public void paramSrcDest1() { + DashModule d = test("paramSrcDest1"); + assertTrue(src(d,"Root/A/t1").equals("Root/A[pAPID]")); + assertTrue(dest(d,"Root/A/t1").equals("Root/A[pAPID]")); + } + @Test + public void paramSrcDest2() { + DashModule d = test("paramSrcDest2"); + assertTrue(src(d,"Root/A/t1").equals("Root/A[pAPID]")); + assertTrue(dest(d,"Root/A/t1").equals("Root/B/S1[x]")); + } + + // getAllAnces -------------- + + @Test + public void getAllAnces1() { + DashModule d = test("noSrc1"); + assertTrue(d.getAllAnces("Root/S1").equals(ll(new String[]{"Root", "Root/S1"}))); + } + + // getClosestConcAnces ---------------- + + @Test + public void getClosestConcAnces1() { + DashModule d = test("noSrc1"); + assertTrue(d.getClosestConcAnces("Root/S1").equals("Root")); + assertTrue(d.getClosestConcAnces("Root/S2").equals("Root")); + } + @Test + public void getClosestConcAnces2() { + DashModule d = test("scopeParam2"); + assertTrue(d.getClosestConcAnces("Root/A/B/S1").equals("Root/A/B")); + assertTrue(d.getClosestConcAnces("Root/A/B").equals("Root/A/B")); + } + + // getAllNonConcDesc -------------- + + @Test + public void getAllNonConcDesc1() { + DashModule d = test("getAllNonConcDesc1"); + assertTrue(d.getAllNonConcDesc("Root") + .equals(ll(new String[]{"Root", "Root/S1", "Root/S1/S2","Root/S3","Root/S3/S4", "Root/S3/S4/S5"}))); + } + + // getRegion ---------------------- + @Test + public void getRegion1() { + DashModule d = test("getRegion1"); + assertTrue(d.getRegion("Root/S1/S2") + .equals(ll(new String[]{"Root", "Root/S1", "Root/S1/S2","Root/S3","Root/S3/S4", "Root/S3/S4/S5"}))); + } + @Test + public void getRegion2() { + DashModule d = test("getAllNonConcDesc1"); + assertTrue(d.getRegion("Root/S1/S2") + .equals(ll(new String[]{"Root", "Root/S1", "Root/S1/S2","Root/S3","Root/S3/S4", "Root/S3/S4/S5"}))); + } + + // getLeafStatesExited -------------------- + + public List exited(DashModule d, String tfqn) { + return d.getLeafStatesExited(d.getTransSrc(tfqn)) + .stream() + .map (i -> i.toString()) + .collect(Collectors.toList()); + } + + @Test + public void getLeafStatesExited1() { + DashModule d = test("noSrc1"); + assertTrue( + exited(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S1[]" + }))); + } + @Test + public void getLeafStatesExited2() { + DashModule d = test("noSrc2"); + assertTrue( + exited(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S1[]" + }))); + } + @Test + public void getLeafStatesExited3() { + DashModule d = test("noDefaultNeeded2"); + assertTrue( + exited(d,"Root/C/t1") + .equals(ll(new String[]{ + "Root/C[]" + }))); + } + @Test + public void getLeafStatesExited4() { + DashModule d = test("noSrcDest1"); + assertTrue( + exited(d,"Root/t1") + .equals(ll(new String[]{ + "Root[]" + }))); + } + @Test + public void getLeafStatesExited5() { + DashModule d = test("otherSrcDest1"); + assertTrue( + exited(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S1[]" + }))); + assertTrue( + exited(d,"Root/S2/t2") + .equals(ll(new String[]{ + "Root/S2/S3/S4[]" + }))); + } + @Test + public void getLeafStatesExited6() { + DashModule d = test("paramSrcDest1"); + assertTrue( + exited(d,"Root/A/t1") + .equals(ll(new String[]{ + "Root/A[pAPID]" + }))); + } + @Test + public void getLeafStatesExited7() { + DashModule d = test("paramSrcDest3"); + assertTrue( + exited(d,"Root/A/t1") + .equals(ll(new String[]{ + "Root/B/S1[x]" + }))); + } + + // getScope ------------------------------- + @Test + public void getScope1() { + DashModule d = test("scopeParam1"); + assertTrue( + d.getScope("Root/A/S1/t1").toString() + .equals("Root/A[(pAPID = x => pAPID else APID)]")); + } + @Test + public void getScope2() { + DashModule d = test("scopeParam2"); + assertTrue( + d.getScope("Root/A/B/S1/t1").toString() + .equals("Root/A/B[(pAPID = x => pAPID else APID), (AND[pAPID = x, pBPID = y] => pBPID else BPID)]")); + } + @Test + public void getScope3() { + DashModule d = test("scopeParam3"); + assertTrue( + d.getScope("Root/A/B/S1/t1").toString() + .equals("Root/A/B[pAPID, pBPID]")); + } + + // getLeafStatesEntered ----------------- + public List entered(DashModule d, String tfqn) { + return d.getLeafStatesEntered(d.getTransDest(tfqn)) + .stream() + .map (i -> i.toString()) + .collect(Collectors.toList()); + } + + @Test + public void getLeafStatesEntered1() { + DashModule d = test("noSrc1"); + assertTrue( + entered(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2[]" + }))); + } + @Test + public void getLeafStatesEntered2() { + DashModule d = test("noSrc2"); + assertTrue( + entered(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/S3/S4[]" + }))); + } +} diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java new file mode 100644 index 000000000..ceb5bec79 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java @@ -0,0 +1,101 @@ +/* + The purpose of these tests is to check that wff errors (DashErrors) are caught. + All files tested here should pass parsing and raise DashErrors during resolveAllDash + All of these raise exceptions. +*/ + + +// junit 4 does not seem to have a way to assert that +// an exception is not thrown +// junit 5 has assertAll() + +package org.alloytools.alloy.dash; + +import java.util.*; +import java.io.File; +import java.util.Collections; +import java.util.stream.Collectors; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.A4Reporter; + +import static ca.uwaterloo.watform.core.DashErrors.*; +import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.mainfunctions.MainFunctions; + +@RunWith(Parameterized.class) + +public class DashWffFailTests { + + private static String resourcePath = "src/test/resources/wfffail"; + + public static void test(String fileName) { + File dir = new File(resourcePath); + String absolutePath = new File(resourcePath).getAbsolutePath(); + A4Reporter rep = new A4Reporter(); + DashModule d = MainFunctions.parseAndResolveDashFile(absolutePath+"/"+fileName, rep); + } + + private final String fileName; + private final String msg; + + public DashWffFailTests(String f, String msg) { + this.fileName = f; + this.msg = msg; + } + + // list of file names that are parameters to test + @Parameterized.Parameters + public static Collection fileNameMsg() { + return Arrays.asList(new Object[][] { + {"noStates1", noStatesMsg}, + {"noStates2", noStatesMsg}, + {"onlyOneState1", onlyOneStateMsg}, + {"onlyOneState2", onlyOneStateMsg}, + {"noTrans1", noTransMsg}, // 4 + {"noTrans2", noTransMsg}, + {"noDefaultState1", noDefaultStateMsg}, + {"noDefaultState2", noDefaultStateMsg}, + {"tooManyDefaultStates1", tooManyDefaultStatesMsg}, + {"tooManyDefaultStates2", tooManyDefaultStatesMsg}, + {"allConcDefaultStates1",allConcDefaultStatesMsg}, + {"allConcDefaultStates2",allConcDefaultStatesMsg}, + {"stateNameCantBeFQN1", stateNameCantBeFQNMsg}, + {"stateNameCantBeFQN2", stateNameCantBeFQNMsg}, + {"dupSiblingNames1", dupSiblingNamesMsg}, + {"dupSiblingNames2", dupSiblingNamesMsg}, + {"dupTransName1", dupTransNameMsg}, + {"dupTransName2", dupTransNameMsg}, // 17 + {"moreThanOneSrcDest1", moreThanOneSrcDestMsg}, + {"moreThanOneSrcDest2", moreThanOneSrcDestMsg}, // 19 + {"moreThanOneSrcDest3", moreThanOneSrcDestMsg}, + {"unknownSrcDest1", unknownSrcDestMsg}, + {"unknownSrcDest2", unknownSrcDestMsg}, + {"unknownSrcDest3", unknownSrcDestMsg}, + {"unknownSrcDest4", unknownSrcDestMsg}, + {"fqnSrcDestMustHaveRightNumberParams1", fqnSrcDestMustHaveRightNumberParamsMsg}, + {"srcDestCantHaveParam1", srcDestCantHaveParamMsg}, + {"ambiguousSrcDest1", ambiguousSrcDestMsg} + }); + } + + @Test + public void test() { + Exception exception = assertThrows(ErrorSyntax.class, () -> { + test(fileName + ".dsh"); + }); + String actualMessage = exception.getMessage(); + assertTrue(actualMessage.contains(msg)); + } + + } diff --git a/org.alloytools.alloy.dash/src/test/resources/parsefail/test11.dsh b/org.alloytools.alloy.dash/src/test/resources/parsefail/test11.dsh new file mode 100644 index 000000000..8ef96437d --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/parsefail/test11.dsh @@ -0,0 +1,5 @@ +conc Root { + conc A { + trans t1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/parsefail/trivial-param-state-error.dsh b/org.alloytools.alloy.dash/src/test/resources/parsefail/trivial-param-state-error.dsh new file mode 100644 index 000000000..605bdcca3 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/parsefail/trivial-param-state-error.dsh @@ -0,0 +1,6 @@ +sig A {} + +fact {} + +// should fail +state Root [A] {} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getAllNonConcDesc1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getAllNonConcDesc1.dsh new file mode 100644 index 000000000..e0ee9d16a --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getAllNonConcDesc1.dsh @@ -0,0 +1,21 @@ +state Root { + default state S1 { + state S2 { + trans t1 {} + } + } + state S3 { + default state S4 { + state S5 {} + } + conc A { + state S7 {} + } + conc B { + state S7 {} + } + conc C [CPID] { + state S7{} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getRegion1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getRegion1.dsh new file mode 100644 index 000000000..7e3d0950c --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getRegion1.dsh @@ -0,0 +1,23 @@ +state Root { + default state S1 { + state S2 { + trans t1 {} + } + } + state S3 { + default state S4 { + state S5 {} + } + conc A { + state S7 { + state S8 {} + } + } + conc B { + state S7 {} + } + conc C [CPID] { + state S7{} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/noDefaultNeeded1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/noDefaultNeeded1.dsh new file mode 100644 index 000000000..9c9be1b51 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/noDefaultNeeded1.dsh @@ -0,0 +1,7 @@ +state Root { + // no need to say this is default + state S { + trans t1 { + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/noDefaultNeeded2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/noDefaultNeeded2.dsh new file mode 100644 index 000000000..0046882cf --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/noDefaultNeeded2.dsh @@ -0,0 +1,7 @@ +state Root { + // no need to say this is default + conc C { + trans t1 { + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/noSrc1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/noSrc1.dsh new file mode 100644 index 000000000..4de72f15d --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/noSrc1.dsh @@ -0,0 +1,8 @@ +state Root { + default state S1 { + trans t1 { + goto S2 + } + } + state S2 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/noSrc2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/noSrc2.dsh new file mode 100644 index 000000000..9e6682c3e --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/noSrc2.dsh @@ -0,0 +1,12 @@ +state Root { + default state S1 { + trans t1 { + goto S4 + } + } + state S2 { + state S3 { + state S4 {} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/noSrcDest1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/noSrcDest1.dsh new file mode 100644 index 000000000..4d78f7aaa --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/noSrcDest1.dsh @@ -0,0 +1,3 @@ +state Root { + trans t1 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/otherSrcDest1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/otherSrcDest1.dsh new file mode 100644 index 000000000..a0226b9a7 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/otherSrcDest1.dsh @@ -0,0 +1,17 @@ +state Root { + default state S1 { + trans t1 { + from Root/S1 + goto S4 + } + } + state S2 { + state S3 { + state S4 {} + } + trans t2 { + from S3 + goto S2 + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest1.dsh new file mode 100644 index 000000000..2b91ad6a0 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest1.dsh @@ -0,0 +1,5 @@ +state Root { + conc A [APID] { + trans t1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest2.dsh new file mode 100644 index 000000000..54a36800e --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest2.dsh @@ -0,0 +1,10 @@ +state Root { + conc A [APID] { + trans t1 { + goto Root/B/S1[x] + } + } + conc B [BPID] { + state S1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest3.dsh new file mode 100644 index 000000000..56d85b71b --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/paramSrcDest3.dsh @@ -0,0 +1,10 @@ +state Root { + conc A [APID] { + trans t1 { + from Root/B/S1[x] + } + } + conc B [BPID] { + state S1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/process-ref.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/process-ref.dsh new file mode 100644 index 000000000..85ca6f9f6 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/process-ref.dsh @@ -0,0 +1,5 @@ +state Root { + trans t1 { + on Elevator[e0]/direction = Up + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam1.dsh new file mode 100644 index 000000000..93133c63c --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam1.dsh @@ -0,0 +1,10 @@ +state Root { + conc A [APID] { + default state S1 { + trans t1 { + goto Root/A/S2[x] + } + } + state S2 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam2.dsh new file mode 100644 index 000000000..2183e0e97 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam2.dsh @@ -0,0 +1,12 @@ +state Root { + conc A [APID] { + conc B [BPID] { + default state S1 { + trans t1 { + goto Root/A/B/S2[x,y] + } + } + state S2 {} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam3.dsh new file mode 100644 index 000000000..878266bbf --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/scopeParam3.dsh @@ -0,0 +1,12 @@ +state Root { + conc A [APID] { + conc B [BPID] { + default state S1 { + trans t1 { + goto S2 + } + } + state S2 {} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/srcDestFQN1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/srcDestFQN1.dsh new file mode 100644 index 000000000..2895c957e --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/srcDestFQN1.dsh @@ -0,0 +1,17 @@ +state Root { + conc S1 { + state S7 {} + trans t1 { + goto S7 + } + } + default state S2 { + state S3{ + state S4{ + trans t2 { + goto Root/S1/S7 + } + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/test1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/test1.dsh new file mode 100644 index 000000000..431e2c1e1 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/test1.dsh @@ -0,0 +1,11 @@ +state Root { + trans t1 { + do { + one n: Node - this | { + Elevator[n]/direction = Up + Elevator[e0]/direction = Up + N[n]/message' = this -> level + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/test2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/test2.dsh new file mode 100644 index 000000000..2cff40987 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/test2.dsh @@ -0,0 +1,8 @@ +state A { + trans t1 { + // these are all allowed + send ev1 + send P[x]/ev1 + send x.y.ev1 + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/allConcDefaultStates1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/allConcDefaultStates1.dsh new file mode 100644 index 000000000..acaa4bd1a --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/allConcDefaultStates1.dsh @@ -0,0 +1,6 @@ +state Root { + default conc S3 {} + state S1 {} + conc S2 {} + default conc S4 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/allConcDefaultStates2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/allConcDefaultStates2.dsh new file mode 100644 index 000000000..4d9bdeeba --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/allConcDefaultStates2.dsh @@ -0,0 +1,7 @@ +state Root { + default conc S3 {} + state S1 {} + default conc S2 {} + default conc S4 {} + conc S5 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/ambiguousSrcDest1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/ambiguousSrcDest1.dsh new file mode 100644 index 000000000..5f184c596 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/ambiguousSrcDest1.dsh @@ -0,0 +1,12 @@ +state Root { + state S1 { + state S2 {} + } + default state S3 { + state S1 {} + trans t1 { + from S1 + goto S2 + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/and-cross-trans-2-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/and-cross-trans-2-error.dsh new file mode 100644 index 000000000..07ba19ecf --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/and-cross-trans-2-error.dsh @@ -0,0 +1,15 @@ +state Root { + state S { + trans t1 { + // goto B // this works + //goto C // 'The name "Root_S_C" cannot be found.' + //goto D // 'The name "Root_S_D" cannot be found.' + goto Root/B/C/D // error + } + } + default state B { + conc C { + default state D {} + } + } +} diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/and-cross-trans-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/and-cross-trans-error.dsh new file mode 100644 index 000000000..8874ca22f --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/and-cross-trans-error.dsh @@ -0,0 +1,12 @@ +state Root { + conc state A { + state A1 { + trans t1 { + goto Root/B/B1 + } + } + } + conc state B { + state B1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/buffer-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/buffer-error.dsh new file mode 100644 index 000000000..10171085b --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/buffer-error.dsh @@ -0,0 +1,7 @@ +sig A, B {} + +state S1 { + b1 : buf[A] + b2 : buf[B] + env b3 : buf[B] +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/dupSiblingNames1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/dupSiblingNames1.dsh new file mode 100644 index 000000000..30dd5bf55 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/dupSiblingNames1.dsh @@ -0,0 +1,5 @@ +state Root { + conc A {} + state A {} + conc B {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/dupSiblingNames2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/dupSiblingNames2.dsh new file mode 100644 index 000000000..e8c75c16a --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/dupSiblingNames2.dsh @@ -0,0 +1,4 @@ +state Root { + state A {} + state A {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/dupTransName1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/dupTransName1.dsh new file mode 100644 index 000000000..77b30ab43 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/dupTransName1.dsh @@ -0,0 +1,4 @@ +state Root { + trans t1 {} + trans t1 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/dupTransName2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/dupTransName2.dsh new file mode 100644 index 000000000..393ed1f41 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/dupTransName2.dsh @@ -0,0 +1,6 @@ +state Root { + trans t1 {} + trans t2 {} + trans t3 {} + trans t1 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/fqnSrcDestMustHaveRightNumberParams1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/fqnSrcDestMustHaveRightNumberParams1.dsh new file mode 100644 index 000000000..e59ade166 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/fqnSrcDestMustHaveRightNumberParams1.dsh @@ -0,0 +1,10 @@ +state Root { + conc A [APID] { + trans t1 { + goto Root/B/S1[x,y] + } + } + conc B [BPID] { + state S1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest1.dsh new file mode 100644 index 000000000..1b8131f41 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest1.dsh @@ -0,0 +1,8 @@ +state Root { + state S1 {} + trans t1 { + from S1 + goto S1 + from S1 + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest2.dsh new file mode 100644 index 000000000..ad10b887c --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest2.dsh @@ -0,0 +1,16 @@ +state Root { + state C { + trans t1 { + from C + } + trans t2 { + from C + goto S + } + trans t3 { + goto S + goto S + } + } + default state S {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest3.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest3.dsh new file mode 100644 index 000000000..2af30a223 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/moreThanOneSrcDest3.dsh @@ -0,0 +1,7 @@ +state Root { + trans t1 { + goto Root + from Root + goto Root + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultNeeded-traces.als b/org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultNeeded-traces.als new file mode 100644 index 000000000..e69de29bb diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultState1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultState1.dsh new file mode 100644 index 000000000..e88eb6c98 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultState1.dsh @@ -0,0 +1,4 @@ +state Root { + state S1 {} + state S2 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultState2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultState2.dsh new file mode 100644 index 000000000..e053920b1 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/noDefaultState2.dsh @@ -0,0 +1,4 @@ +state Root { + state S1 {} + conc S2 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/noStates1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/noStates1.dsh new file mode 100644 index 000000000..a4dbe000a --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/noStates1.dsh @@ -0,0 +1 @@ +sig A {} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/noStates2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/noStates2.dsh new file mode 100644 index 000000000..2fa66576b --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/noStates2.dsh @@ -0,0 +1,7 @@ +module X + +sig A {} + +fact jj { + 1 = 1 +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans1.dsh new file mode 100644 index 000000000..28aaa2174 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans1.dsh @@ -0,0 +1 @@ +state Root {} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans2.dsh new file mode 100644 index 000000000..19c8f1931 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans2.dsh @@ -0,0 +1,8 @@ +sig A {} + +sig B {} + +state S {} + + + diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/one-guard.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/one-guard.dsh new file mode 100644 index 000000000..37c9924c7 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/one-guard.dsh @@ -0,0 +1,16 @@ +enum status {x, y} + +state Top { + env input: one status + default state OFF { } + state ON {} + trans t0 { + when input = x + goto ON + } + trans t1 { + when input = y + goto OFF + } + +} diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/onlyOneState1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/onlyOneState1.dsh new file mode 100644 index 000000000..dcd326e82 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/onlyOneState1.dsh @@ -0,0 +1,7 @@ +sig A {} + +state Root1 {} + +fact R {} + +state Root2 {} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/onlyOneState2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/onlyOneState2.dsh new file mode 100644 index 000000000..ac96cc895 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/onlyOneState2.dsh @@ -0,0 +1,2 @@ +state Root1 {} +state Root2 {} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/open1-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/open1-error.dsh new file mode 100644 index 000000000..19fc6e717 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/open1-error.dsh @@ -0,0 +1,7 @@ +sig A {} + +state S1 { + b1 : buf[A] + b2 : buf[B] + env b3 : buf[B] +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/open2-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/open2-error.dsh new file mode 100644 index 000000000..933126d96 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/open2-error.dsh @@ -0,0 +1,11 @@ + + +module X + +sig A {} + +state S1 { + b1 : buf[A] + b2 : buf[B] + env b3 : buf[B] +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/open3-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/open3-error.dsh new file mode 100644 index 000000000..2dcf2d993 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/open3-error.dsh @@ -0,0 +1,13 @@ + + +module X + +open util/boolean + +sig A {} + +state S1 { + b1 : buf[A] + b2 : buf[B] + env b3 : buf[B] +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/open4-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/open4-error.dsh new file mode 100644 index 000000000..8deb980e5 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/open4-error.dsh @@ -0,0 +1,9 @@ +open util/boolean + +sig A {} + +state S1 { + b1 : buf[A] + b2 : buf[B] + env b3 : buf[B] +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/srcDestCantHaveParam1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/srcDestCantHaveParam1.dsh new file mode 100644 index 000000000..869ecb6e3 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/srcDestCantHaveParam1.dsh @@ -0,0 +1,10 @@ +state Root { + conc A [APID] { + trans t1 { + goto Root[x,y] + } + } + conc B [BPID] { + state S1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/srcDestUnknown4-traces.als b/org.alloytools.alloy.dash/src/test/resources/wfffail/srcDestUnknown4-traces.als new file mode 100644 index 000000000..ef803898e --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/srcDestUnknown4-traces.als @@ -0,0 +1,81 @@ +open util/ordering[Snapshot] as Snapshot +abstract sig StateLabel {} +sig Root extends StateLabel {} +abstract sig Root_S1 extends Root {} +sig Root_S1_S7 extends Root_S1 {} +abstract sig Root_S2 extends Root {} +abstract sig Root_S2_S3 extends Root_S2 {} +abstract sig Root_S2_S3_S4 extends Root_S2_S3 {} + +abstract sig TransitionLabel {} +one sig Root_S1_t1 extends TransitionLabel {} +one sig Root_S2_S3_S4_t2 extends TransitionLabel {} + +sig Snapshot { + taken0 : set TransitionLabel, + conf0 : set StateLabel, + stable : one boolean/Bool +} + +pred Root_S1_t1_pre[s : one Snapshot] { + +} + + +pred Root_S1_t1_post[s : one Snapshot, sNext : one Snapshot] { + +} + +pred Root_S1_t1_semantics[s : one Snapshot, sNext : one Snapshot] { + (stable = boolean/True => + sNext. (taken0) = Root_S1_t1 + else { + sNext. (taken0) = { s. (taken0) + Root_S1_t1 } } +) +} + + +pred Root_S1_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { + +} + + +pred Root_S1_t1[s : one Snapshot, sNext : one Snapshot] { + s. (Root_S1_t1_pre) + sNext. (s. (Root_S1_t1_post)) + sNext. (s. (Root_S1_t1_semantics)) +} + +pred Root_S2_S3_S4_t2_pre[s : one Snapshot] { + +} + + +pred Root_S2_S3_S4_t2_post[s : one Snapshot, sNext : one Snapshot] { + +} + +pred Root_S2_S3_S4_t2_semantics[s : one Snapshot, sNext : one Snapshot] { + (stable = boolean/True => + sNext. (taken0) = Root_S2_S3_S4_t2 + else { + sNext. (taken0) = { s. (taken0) + Root_S2_S3_S4_t2 } } +) +} + + +pred Root_S2_S3_S4_t2_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { + +} + + +pred Root_S2_S3_S4_t2[s : one Snapshot, sNext : one Snapshot] { + s. (Root_S2_S3_S4_t2_pre) + sNext. (s. (Root_S2_S3_S4_t2_post)) + sNext. (s. (Root_S2_S3_S4_t2_semantics)) +} + +pred small_step[s : one Snapshot, sNext : one Snapshot] { + { sNext. (s. (Root_S1_t1)) or sNext. (s. (Root_S2_S3_S4_t2)) } +} + diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/stateNameCantBeFQN1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/stateNameCantBeFQN1.dsh new file mode 100644 index 000000000..5689a0696 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/stateNameCantBeFQN1.dsh @@ -0,0 +1,4 @@ +state Root { + state Root/A {} + state B {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/stateNameCantBeFQN2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/stateNameCantBeFQN2.dsh new file mode 100644 index 000000000..dab7c7f34 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/stateNameCantBeFQN2.dsh @@ -0,0 +1,4 @@ +state Root { + state A {} + conc Root/B/C {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test0.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test0.dsh new file mode 100644 index 000000000..cb42f3d71 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test0.dsh @@ -0,0 +1,5 @@ +state Root { + trans t1 { + do N[n,y]/message' = this -> level + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test10.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test10.dsh new file mode 100644 index 000000000..251fe39b6 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test10.dsh @@ -0,0 +1,27 @@ + + +state Top { + state Outer { + default state s0 { + trans t0 { + goto s1 + } + } + state s1 { + trans t1 { + goto s0 + } + } + trans t4 { + from s2 + } + trans t5 { + from s0 + } + } + default state s2 { + trans t3 { + goto Outer + } + } +} diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test3.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test3.dsh new file mode 100644 index 000000000..a0a26286e --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test3.dsh @@ -0,0 +1,6 @@ +state A { + trans t1 { + // should fail on x,y as a list + send P[x,y]/ev1 + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test5.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test5.dsh new file mode 100644 index 000000000..27ae28dec --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test5.dsh @@ -0,0 +1,35 @@ +// Identifiers are declared by translation + +state Root { + conc state A [AId] { + conc state A1 [A1ID] { + state S1 {} + default state S2 { + conc state C[CId] { + state C1 {} + default state C2 {} + trans t0 { + from C2 + goto C1 + } + } + } + trans t3 { + from S2 + goto S1 + } + trans t1 { + from S1 + goto S2 + } + } + } + conc state B [BId] { + state B1 {} + default state B2 {} + trans t2 { + from B1 + goto B2 + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test6.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test6.dsh new file mode 100644 index 000000000..3f99a3c6d --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test6.dsh @@ -0,0 +1,24 @@ + + +state Top { + conc state Outer { + default state s0 { + trans t0 { + goto s1 + } + } + state s1 { + trans t1 { + goto s0 + } + } + trans t4 { + goto s2 + } + } + default state s2 { + trans t3 { + goto Outer + } + } +} diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test7.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test7.dsh new file mode 100644 index 000000000..882c052c1 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test7.dsh @@ -0,0 +1,28 @@ +state Root { +conc state p1 { + + default state p1s0 { + trans p1t0 { + goto p1s1 + } + } + state p1s1 { + trans p1t1 { + goto p1s0 + } + } + +} +conc state p2 { + default state p2s0 { + trans p2t0 { + goto p2s1 + } + } + state p2s1 { + trans p2t1 { + goto p2s0 + } + } +} +} diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test8.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test8.dsh new file mode 100644 index 000000000..ea87bd45b --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test8.dsh @@ -0,0 +1,19 @@ + + +state Top { + default state s0 { + trans t0 { + goto s1 + } + } + state s1 { + trans t1 { + goto s2 + } + } + state s2 { + trans t3 { + goto s1 + } + } +} diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test9.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test9.dsh new file mode 100644 index 000000000..f7ce1fd52 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test9.dsh @@ -0,0 +1,24 @@ + + +state Top { + state Outer { + default state s0 { + trans t0 { + goto s1 + } + } + state s1 { + trans t1 { + goto s0 + } + } + trans t4 { + goto s2 + } + } + default state Outer { + trans t3 { + goto s1 + } + } +} diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/tooManyDefaultStates1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/tooManyDefaultStates1.dsh new file mode 100644 index 000000000..bb758f0cc --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/tooManyDefaultStates1.dsh @@ -0,0 +1,5 @@ +state Root { + default state S1 {} + state S2 {} + default state S3 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/tooManyDefaultStates2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/tooManyDefaultStates2.dsh new file mode 100644 index 000000000..dfe0c75a9 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/tooManyDefaultStates2.dsh @@ -0,0 +1,6 @@ +state Root { + state S1 {} + conc S2 {} + default state S3 {} + default conc S4 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-conc-2-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-conc-2-error.dsh new file mode 100644 index 000000000..d1fa8a008 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-conc-2-error.dsh @@ -0,0 +1,13 @@ +sig A {} + +fact {} + +state Root { + // not correct because must have substates + conc state A { + state A1 {} + } + conc state B { + state B1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-conc-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-conc-error.dsh new file mode 100644 index 000000000..fd1689d6b --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-conc-error.dsh @@ -0,0 +1,9 @@ +sig A {} + +fact {} + +state Root { + // not correct because must have substates + conc A {} + conc B {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-hier-error.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-hier-error.dsh new file mode 100644 index 000000000..99196d2d3 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/trivial-hier-error.dsh @@ -0,0 +1,9 @@ +sig A {} + +fact {} + + +state Root { + state A {} + state B {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest1.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest1.dsh new file mode 100644 index 000000000..bb9c5d6e9 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest1.dsh @@ -0,0 +1,9 @@ +// S2 is unknown b/c it is not within the same conc name space +state Root { + conc S1 { + trans t1 { + goto S2 + } + } + conc S2 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest2.dsh new file mode 100644 index 000000000..fafff521a --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest2.dsh @@ -0,0 +1,9 @@ +// S2 is unknown b/c it is not within the same conc name space +state Root { + conc S1 { + trans t1 { + goto S2 + } + } + default state S2 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest3.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest3.dsh new file mode 100644 index 000000000..d3c24c724 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest3.dsh @@ -0,0 +1,18 @@ +// S2 is unknown b/c it is not within the same conc name space +state Root { + conc S1 { + state S7 {} + trans t1 { + goto S7 + } + } + default state S2 { + state S3{ + state S4{ + trans t2 { + goto S7 + } + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest4.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest4.dsh new file mode 100644 index 000000000..8a501d596 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest4.dsh @@ -0,0 +1,14 @@ +state Root { + conc A [APID] { + conc B [BPID] { + default state S1 { + trans t1 { + goto S2 + } + } + conc C [CPID] { + state S2 {} + } + } + } +} \ No newline at end of file From 6ae0de48285ecfcbec2b63b2c68800eb125d8ef7 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 5 Apr 2023 10:45:52 -0400 Subject: [PATCH 026/129] adding testing --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 49 +- org.alloytools.alloy.dash/bnd.bnd | 7 +- .../parser/Dash-cup-grammar.txt | 169 ++++++- org.alloytools.alloy.dash/parser/Dash.cup | 169 ++++++- .../watform/alloyasthelper/ExprHelper.java | 48 +- .../watform/alloyasthelper/ExprToString.java | 24 +- .../java/ca/uwaterloo/watform/ast/Dash.java | 2 +- .../ca/uwaterloo/watform/ast/DashFrom.java | 15 +- .../ca/uwaterloo/watform/ast/DashGoto.java | 14 +- .../ca/uwaterloo/watform/ast/DashState.java | 186 +++++--- .../ca/uwaterloo/watform/core/DashErrors.java | 98 ++-- .../ca/uwaterloo/watform/core/DashFQN.java | 21 +- .../uwaterloo/watform/core/DashStrings.java | 7 +- .../uwaterloo/watform/core/DashUtilFcns.java | 13 +- .../watform/dashtoalloy/DashToAlloy.java | 427 ++++++++++++------ .../watform/mainfunctions/MainFunctions.java | 91 ++-- .../watform/parser/CompModuleHelper.java | 17 +- .../uwaterloo/watform/parser/DashModule.java | 201 +++++++-- .../uwaterloo/watform/parser/StateTable.java | 272 +++++++---- .../uwaterloo/watform/parser/TransTable.java | 86 +++- .../watform/parser/install-alloy-files.sh | 1 + org.alloytools.alloy.dist/bnd.bnd | 1 + 22 files changed, 1401 insertions(+), 517 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index 7e3907e05..ca3dd3998 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -19,7 +19,8 @@ import edu.mit.csail.sdg.translator.TranslateAlloyToKodkod; import ca.uwaterloo.watform.core.DashOptions; -import ca.uwaterloo.watform.parser.DashUtil; +// import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.core.DashUtilFcns; import ca.uwaterloo.watform.parser.DashModule; import ca.uwaterloo.watform.mainfunctions.MainFunctions; @@ -30,6 +31,7 @@ public class Dash { @SuppressWarnings("resource" ) + public static void main(String args[]) throws Exception { if(args.length == 0) { @@ -111,23 +113,31 @@ public static void main(String args[]) throws Exception { DashOptions.dashModelLocation = directory.toString(); //Parse+typecheck the model - //System.out.println("Reading: " + filename ); + System.out.println("Reading: " + filename ); A4Reporter rep = new A4Reporter(); CompModule alloymodule = null; - DashModule d = MainFunctions.parseFile(filename.toString(), rep); + DashModule d = null; + try { + d = MainFunctions.parseAndResolveDashFile(filename, rep); + } catch (Exception e) { + DashUtilFcns.handleException(e); + } if (printOnly) { if (d != null) { - String o = MainFunctions.dumpString(d); - System.out.println(o); - // System.out.println("File parsed successfully."); + try { + String o = MainFunctions.dumpString(d); + System.out.println(o); + System.out.println("File parsed successfully."); + } catch (Exception e) { + DashUtilFcns.handleException(e); + } } } else { try { alloymodule = MainFunctions.translate(d, rep); } catch (Exception e) { - System.err.println(e); - System.exit(1); + DashUtilFcns.handleException(e); } if (alloymodule == null) { System.err.println("Something went wrong"); @@ -142,14 +152,16 @@ public static void main(String args[]) throws Exception { out.createNewFile(); } System.out.println("Creating: " + outfilename); - // NAD tmp - //String content = new DashModuleToString(true).getString(alloymodule); - //FileWriter fw = new FileWriter(out.getAbsoluteFile()); - //BufferedWriter bw = new BufferedWriter(fw); - //bw.write(content); - //bw.close(); + FileWriter fw = new FileWriter(out.getAbsoluteFile()); + BufferedWriter bw = new BufferedWriter(fw); + bw.write(alloymodule.toString()); + bw.close(); + // temporarily, we'll check if it reads in as an AlloyModule okay + // should be no Dash in it + MainFunctions.parseAndResolveAlloyFile(outfilename, rep); + System.out.println("Parsed and Resolved Alloy output file"); } catch(Exception e){ - System.err.println(e); + DashUtilFcns.handleException(e); } } else { // execute command(s) @@ -163,7 +175,12 @@ public static void main(String args[]) throws Exception { for (Command cmd : commands) { if (i == cmdnum | cmdnum == 0) { System.out.println("Executing command: " + cmd); - A4Solution ans = MainFunctions.executeCommand(cmd,alloymodule,rep, options); + A4Solution ans = null; + try { + ans = MainFunctions.executeCommand(cmd,alloymodule,rep, options); + } catch (Exception e) { + DashUtilFcns.handleException(e); + } if (ans.satisfiable()) { System.out.println("Result: SAT"); } else { diff --git a/org.alloytools.alloy.dash/bnd.bnd b/org.alloytools.alloy.dash/bnd.bnd index 99d17893d..2c833e04e 100644 --- a/org.alloytools.alloy.dash/bnd.bnd +++ b/org.alloytools.alloy.dash/bnd.bnd @@ -8,7 +8,9 @@ org.alloytools:pardinus.core;version='1.3.0',\ org.alloytools:pardinus.nativesat;version='1.3.0',\ org.eclipse.jdt.annotation,\ - org.alloytools.alloy.core;version=latest, + org.alloytools.alloy.core;version=latest, \ + com.io7m.jpplib.io7m-jpplib-core;version=0.7.4,\ + org.apache.commons.io,\ -testpath: \ biz.aQute.wrapper.junit, \ @@ -24,7 +26,8 @@ Export-Package: \ ca.uwaterloo.watform.parser,\ ca.uwaterloo.watform.dashtoalloy,\ ca.uwaterloo.watform.mainfunctions,\ - com.io7m.jpplib.core, \ + + Private-Package: \ java_cup.runtime diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt index 56ccdf13b..b733dc9a5 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -5,6 +5,8 @@ // besides creating a DashState; the parsing also has count buffers and create indexes // for those buffers in order to have the correct open statements +// no DashErrors here -- all are checked in wff checks + // adding a case for the Spec Spec ::= Spec StateRoot:o ; @@ -14,18 +16,25 @@ StateRoot ::= STATE:o Name:n LBRACE RBRACE:e // empty state // first line in file is line 1 parser.dashmodule.rootStartLine = o.y; parser.dashmodule.rootEndLine = e.y; - if (!parser.dashmodule.hasRoot()) - // a basic state - parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT)); - else - DashErrors.onlyOneState(o); - + parser.dashmodule.addRoot( + new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.NOTDEFAULT, + DashState.noSubstates())); :}; StateRoot ::= STATE:o Name:n LBRACE StateItemList:c RBRACE:e {: parser.dashmodule.rootStartLine = o.y; parser.dashmodule.rootEndLine = e.y; - parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.NOTDEFAULT, c)); + parser.dashmodule.addRoot( + new DashState(o, + n.label, + null, + DashStrings.StateKind.OR, + DashStrings.DefKind.NOTDEFAULT, + c)); :}; StateItemList ::= StateItem:x @@ -33,27 +42,125 @@ StateItemList ::= StateItem:x StateItemList ::= StateItemList:c StateItem:s {: c.add(s); RESULT = c; :}; -// empty state +// or-state, non-default, empty StateItem ::= STATE:o Name:n LBRACE RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT ); :}; + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.NOTDEFAULT, + DashState.noSubstates() ); + :}; +// or-state, non-default, substates StateItem ::= STATE:o Name:n LBRACE StateItemList:c RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.NOTDEFAULT, c); :}; - -// empty state + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.NOTDEFAULT, + c); + :}; + +// or-state, default, empty state StateItem ::= DEF STATE:o Name:n LBRACE RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.DefKind.DEFAULT); :}; + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.DEFAULT, + DashState.noSubstates()); + :}; +// or-state, default, substates StateItem ::= DEF STATE:o Name:n LBRACE StateItemList:c RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.DEFAULT, c); :}; + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.DEFAULT, + c); + :}; + +// conc state, non-default, empty +StateItem ::= CONC:o Name:n LBRACE RBRACE + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.AND, + DashStrings.DefKind.NOTDEFAULT, + DashState.noSubstates()); + :}; + +// conc state, non-default, substates +StateItem ::= CONC:o Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.AND, + DashStrings.DefKind.NOTDEFAULT, + c); + :}; + +// conc state, default, empty +StateItem ::= DEF CONC:o Name:n LBRACE RBRACE + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.AND, + DashStrings.DefKind.DEFAULT, + DashState.noSubstates() ); + :}; + +// conc state, default, substates +StateItem ::= DEF CONC:o Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.AND, + DashStrings.DefKind.DEFAULT, + c); + :}; -// non parametrized state -StateItem ::= CONC:o STATE Name:n LBRACE StateItemList:c RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.StateKind.AND, DashStrings.DefKind.NOTDEFAULT, c); :}; +// parametrized state, non-default, empty +StateItem ::= CONC:o Name:n LBRACKET Name:m RBRACKET LBRACE RBRACE + {: RESULT = new DashState(o, + n.label, + m.label, + DashStrings.StateKind.AND, + DashStrings.DefKind.NOTDEFAULT, + DashState.noSubstates()); + :}; + +// parametrized state, non-default, substates +StateItem ::= CONC:o Name:n LBRACKET Name:m RBRACKET LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, + n.label, + m.label, + DashStrings.StateKind.AND, + DashStrings.DefKind.NOTDEFAULT, + c); + :}; + +// parametrized state, default, empty +StateItem ::= DEF CONC:o Name:n LBRACKET Name:m RBRACKET LBRACE RBRACE + {: RESULT = new DashState(o, + n.label, + m.label, + DashStrings.StateKind.AND, + DashStrings.DefKind.DEFAULT, + DashState.noSubstates()); + :}; -// parametrized state -StateItem ::= CONC:o STATE Name:n LBRACKET Name:m RBRACKET LBRACE StateItemList:c RBRACE - {: RESULT = new DashState(o, n.label, m.label, c); :}; +// parametrized state, default, empty +StateItem ::= DEF CONC:o Name:n LBRACKET Name:m RBRACKET LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, + n.label, + m.label, + DashStrings.StateKind.AND, + DashStrings.DefKind.DEFAULT, + c); + :}; // event decls StateItem ::= EVENT:o Names:n LBRACE RBRACE @@ -154,14 +261,30 @@ StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE // transition StateItem ::= TRANS:o Name:n LBRACE TransItemList:c RBRACE {: RESULT = new DashTrans(o, n.label, c); :}; +// transition +StateItem ::= TRANS:o Name:n LBRACE RBRACE + {: RESULT = new DashTrans(o, n.label, new ArrayList()); :}; TransItemList ::= TransItem:x {: RESULT = new ArrayList(); RESULT.add(x); :}; TransItemList ::= TransItemList:c TransItem:x {: c.add(x); RESULT = c; :}; - + +//Exprp is non-empty list of comma-separated Expr + TransItem ::= FROM:o Name:n - {: RESULT = new DashFrom(o, n.label); :}; + {: RESULT = new DashFrom(o, new DashRef(o, n.label,DashRef.emptyParamValuesList())); :}; + +TransItem ::= FROM:o Name:n LBRACKET Exprp:e RBRACKET + {: RESULT = new DashFrom(o, new DashRef(o,n.label,e)); :}; + +TransItem ::= GOTO:o Name:n + {: RESULT = new DashGoto(o, new DashRef(o,n.label,DashRef.emptyParamValuesList())); :}; + +TransItem ::= GOTO:o Name:n LBRACKET Exprp:e RBRACKET + {: + RESULT = new DashGoto(o, new DashRef(o, n.label,e)); + :}; TransItem ::= ON:o Expr:e {: RESULT = new DashOn(o, e); :}; @@ -173,8 +296,6 @@ TransItem ::= DO:o Expr:v {: RESULT = new DashDo(o, v); :}; -TransItem ::= GOTO:o Name:n - {: RESULT = new DashGoto(o, n.label); :}; // this allows Send x.ev1 and "Send n" in parsing but will have to sort out later to see if correct diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index 02ba2906c..619bd7e96 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -1257,6 +1257,8 @@ BaseExpr ::= LBRACE:o Declz:a RBRACE:c {: RESULT = ExprQt.Op.COMPRE // besides creating a DashState; the parsing also has count buffers and create indexes // for those buffers in order to have the correct open statements +// no DashErrors here -- all are checked in wff checks + // adding a case for the Spec Spec ::= Spec StateRoot:o ; @@ -1266,18 +1268,25 @@ StateRoot ::= STATE:o Name:n LBRACE RBRACE:e // empty state // first line in file is line 1 parser.dashmodule.rootStartLine = o.y; parser.dashmodule.rootEndLine = e.y; - if (!parser.dashmodule.hasRoot()) - // a basic state - parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT)); - else - DashErrors.onlyOneState(o); - + parser.dashmodule.addRoot( + new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.NOTDEFAULT, + DashState.noSubstates())); :}; StateRoot ::= STATE:o Name:n LBRACE StateItemList:c RBRACE:e {: parser.dashmodule.rootStartLine = o.y; parser.dashmodule.rootEndLine = e.y; - parser.dashmodule.setRoot(new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.NOTDEFAULT, c)); + parser.dashmodule.addRoot( + new DashState(o, + n.label, + null, + DashStrings.StateKind.OR, + DashStrings.DefKind.NOTDEFAULT, + c)); :}; StateItemList ::= StateItem:x @@ -1285,27 +1294,125 @@ StateItemList ::= StateItem:x StateItemList ::= StateItemList:c StateItem:s {: c.add(s); RESULT = c; :}; -// empty state +// or-state, non-default, empty StateItem ::= STATE:o Name:n LBRACE RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.DefKind.NOTDEFAULT ); :}; + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.NOTDEFAULT, + DashState.noSubstates() ); + :}; +// or-state, non-default, substates StateItem ::= STATE:o Name:n LBRACE StateItemList:c RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.NOTDEFAULT, c); :}; - -// empty state + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.NOTDEFAULT, + c); + :}; + +// or-state, default, empty state StateItem ::= DEF STATE:o Name:n LBRACE RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.DefKind.DEFAULT); :}; + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.DEFAULT, + DashState.noSubstates()); + :}; +// or-state, default, substates StateItem ::= DEF STATE:o Name:n LBRACE StateItemList:c RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.StateKind.OR, DashStrings.DefKind.DEFAULT, c); :}; + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.OR, + DashStrings.DefKind.DEFAULT, + c); + :}; + +// conc state, non-default, empty +StateItem ::= CONC:o Name:n LBRACE RBRACE + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.AND, + DashStrings.DefKind.NOTDEFAULT, + DashState.noSubstates()); + :}; + +// conc state, non-default, substates +StateItem ::= CONC:o Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.AND, + DashStrings.DefKind.NOTDEFAULT, + c); + :}; + +// conc state, default, empty +StateItem ::= DEF CONC:o Name:n LBRACE RBRACE + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.AND, + DashStrings.DefKind.DEFAULT, + DashState.noSubstates() ); + :}; + +// conc state, default, substates +StateItem ::= DEF CONC:o Name:n LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, + n.label, + DashState.noParam(), + DashStrings.StateKind.AND, + DashStrings.DefKind.DEFAULT, + c); + :}; -// non parametrized state -StateItem ::= CONC:o STATE Name:n LBRACE StateItemList:c RBRACE - {: RESULT = new DashState(o, n.label, DashStrings.StateKind.AND, DashStrings.DefKind.NOTDEFAULT, c); :}; +// parametrized state, non-default, empty +StateItem ::= CONC:o Name:n LBRACKET Name:m RBRACKET LBRACE RBRACE + {: RESULT = new DashState(o, + n.label, + m.label, + DashStrings.StateKind.AND, + DashStrings.DefKind.NOTDEFAULT, + DashState.noSubstates()); + :}; + +// parametrized state, non-default, substates +StateItem ::= CONC:o Name:n LBRACKET Name:m RBRACKET LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, + n.label, + m.label, + DashStrings.StateKind.AND, + DashStrings.DefKind.NOTDEFAULT, + c); + :}; + +// parametrized state, default, empty +StateItem ::= DEF CONC:o Name:n LBRACKET Name:m RBRACKET LBRACE RBRACE + {: RESULT = new DashState(o, + n.label, + m.label, + DashStrings.StateKind.AND, + DashStrings.DefKind.DEFAULT, + DashState.noSubstates()); + :}; -// parametrized state -StateItem ::= CONC:o STATE Name:n LBRACKET Name:m RBRACKET LBRACE StateItemList:c RBRACE - {: RESULT = new DashState(o, n.label, m.label, c); :}; +// parametrized state, default, empty +StateItem ::= DEF CONC:o Name:n LBRACKET Name:m RBRACKET LBRACE StateItemList:c RBRACE + {: RESULT = new DashState(o, + n.label, + m.label, + DashStrings.StateKind.AND, + DashStrings.DefKind.DEFAULT, + c); + :}; // event decls StateItem ::= EVENT:o Names:n LBRACE RBRACE @@ -1406,14 +1513,30 @@ StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE // transition StateItem ::= TRANS:o Name:n LBRACE TransItemList:c RBRACE {: RESULT = new DashTrans(o, n.label, c); :}; +// transition +StateItem ::= TRANS:o Name:n LBRACE RBRACE + {: RESULT = new DashTrans(o, n.label, new ArrayList()); :}; TransItemList ::= TransItem:x {: RESULT = new ArrayList(); RESULT.add(x); :}; TransItemList ::= TransItemList:c TransItem:x {: c.add(x); RESULT = c; :}; - + +//Exprp is non-empty list of comma-separated Expr + TransItem ::= FROM:o Name:n - {: RESULT = new DashFrom(o, n.label); :}; + {: RESULT = new DashFrom(o, new DashRef(o, n.label,DashRef.emptyParamValuesList())); :}; + +TransItem ::= FROM:o Name:n LBRACKET Exprp:e RBRACKET + {: RESULT = new DashFrom(o, new DashRef(o,n.label,e)); :}; + +TransItem ::= GOTO:o Name:n + {: RESULT = new DashGoto(o, new DashRef(o,n.label,DashRef.emptyParamValuesList())); :}; + +TransItem ::= GOTO:o Name:n LBRACKET Exprp:e RBRACKET + {: + RESULT = new DashGoto(o, new DashRef(o, n.label,e)); + :}; TransItem ::= ON:o Expr:e {: RESULT = new DashOn(o, e); :}; @@ -1425,8 +1548,6 @@ TransItem ::= DO:o Expr:v {: RESULT = new DashDo(o, v); :}; -TransItem ::= GOTO:o Name:n - {: RESULT = new DashGoto(o, n.label); :}; // this allows Send x.ev1 and "Send n" in parsing but will have to sort out later to see if correct diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 76ad0375a..073704dce 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -15,6 +15,7 @@ import edu.mit.csail.sdg.ast.ExprQt; import edu.mit.csail.sdg.ast.ExprUnary; import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.ExprHasName; import edu.mit.csail.sdg.ast.ExprBinary; @@ -34,6 +35,9 @@ public static Expr createNullExpr() { public static ExprVar createTrue() { return ExprVar.make(Pos.UNKNOWN, DashStrings.trueName); } + public static ExprVar createNone() { + return ExprVar.make(Pos.UNKNOWN, DashStrings.noneName); + } public static ExprVar createVar(String v) { return ExprVar.make(Pos.UNKNOWN, v); } @@ -44,7 +48,21 @@ public static List createVarList(List vList) { } return retList; } - + public static List createVarList(String prefix, List vList) { + List retList = new ArrayList(); + for (String v: vList) { + retList.add(createVar(prefix+v)); + } + return retList; + } + // to avoid the need to cast every ExprVar to an Expr + public static List createVarExprList(String prefix, List vList) { + List retList = new ArrayList(); + for (String v: vList) { + retList.add((Expr) createVar(prefix+v)); + } + return retList; + } /* generic ones */ public static Expr createBinaryExpr(Expr left, ExprBinary.Op op, Expr right) { return (ExprBinary) op.make(Pos.UNKNOWN, Pos.UNKNOWN,left,right); @@ -61,6 +79,9 @@ public static Expr createExprQt(ExprQt.Op op, List decls, Expr expr) { } /* a few useful specific ones */ + public static Expr createNot(Expr sub) { + return (ExprUnary) ExprUnary.Op.NOT.make(Pos.UNKNOWN, sub); + } public static Expr createOne(Expr sub) { return (ExprUnary) ExprUnary.Op.ONE.make(Pos.UNKNOWN, sub); } @@ -95,17 +116,18 @@ public static ExprBinary createEquals(Expr left, Expr right) { public static ExprBinary createNotEquals(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.NOT_EQUALS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static ExprBinary createAnd(Expr left, Expr right) { - return (ExprBinary) ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + // returns an ExprList + public static ExprList createAnd(Expr left, Expr right) { + return (ExprList) ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static Expr createAnd(List args) { - return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); + public static ExprList createAnd(List args) { + return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); } - public static ExprBinary createOr(Expr left, Expr right) { - return (ExprBinary) ExprBinary.Op.OR.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + public static ExprList createOr(Expr left, Expr right) { + return (ExprList) ExprBinary.Op.OR.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static Expr createOr(List args) { - return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); + public static ExprList createOr(List args) { + return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); } public static ExprBinary createArrow(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.ARROW.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); @@ -157,4 +179,12 @@ public static Expr createPredCall(String name, List elist) { return o; } + // simple equality: two var names are equal + public static boolean sEquals(Expr e1, Expr e2) { + return ( (e1 == e2) || + (e1 instanceof ExprVar && + e2 instanceof ExprVar && + ((ExprVar) e1).label.equals(((ExprVar) e2).label))) ; + } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index a9d205ec8..7290c0268 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -6,8 +6,10 @@ import java.util.ArrayList; import java.util.StringJoiner; -import com.io7m.jpplib.core.Layouter; -import com.io7m.jpplib.core.Backend; +import de.uka.ilkd.pp.DataLayouter; +import de.uka.ilkd.pp.NoExceptions; +import de.uka.ilkd.pp.StringBackend; + import edu.mit.csail.sdg.alloy4.ConstList; import edu.mit.csail.sdg.alloy4.Pair; @@ -19,20 +21,18 @@ public class ExprToString { - int indent; - int lineWidth; - Layouter out; + int indent = 4; + int lineWidth = 80; + StringBackend back = new StringBackend(lineWidth); + DataLayouter out = new DataLayouter(back, indent);; Boolean isAfterAlloyResolveAll; - + + public ExprToString(boolean isAfterAlloyResolveAll) { this.isAfterAlloyResolveAll = isAfterAlloyResolveAll; - this.indent = 4; - this.lineWidth = 120; - Backend back = new Backend(lineWidth); - this.out = new Layouter(back, indent); } - public String toString(Expr e) throws IOException { + public String toString(Expr e) { out.beginC(0); ExprToOut(e); out.end().close(); @@ -344,7 +344,7 @@ private void DeclsToOut(ConstList decls) { first = false; out.print(namesJoiner.toString()); out.print(": "); - ExprToOut(decl.expr, out); + ExprToOut(decl.expr); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/Dash.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/Dash.java index a31b5ddc0..d2e7248e1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/Dash.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/Dash.java @@ -12,7 +12,7 @@ public class Dash { */ public Pos pos; - public final Pos pos() { + public final Pos getPos() { return pos; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java index 0ca6c985f..14afa0aa9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java @@ -1,17 +1,22 @@ package ca.uwaterloo.watform.ast; +import java.util.List; + import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.DashStrings; public class DashFrom extends Dash { - public String src; - public DashFrom(Pos pos,String f) { - assert(f != null); + + public DashRef src; + public DashFrom(Pos pos,DashRef d) { + assert(d != null); this.pos = pos; - this.src = f; + this.src = d; } public String toString() { - return DashStrings.fromName + " " + src + "\n"; + return DashStrings.fromName + " " + src.toString() + "\n"; } + } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java index ff9a41087..8945fad45 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java @@ -1,18 +1,22 @@ package ca.uwaterloo.watform.ast; +import java.util.List; + import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; +import ca.uwaterloo.watform.core.DashUtilFcns.*; import ca.uwaterloo.watform.core.DashStrings; public class DashGoto extends Dash { - public String dest; - public DashGoto(Pos pos,String g) { - assert(g != null); + public DashRef dest; + public DashGoto(Pos pos,DashRef d) { + assert(d!=null); this.pos = pos; - this.dest = g; + this.dest = d; } public String toString() { - return DashStrings.gotoName + " " + dest + "\n"; + return DashStrings.gotoName + " " +dest.toString() + "\n"; } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index 65c66f7a0..b5f1c1e93 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -1,6 +1,5 @@ package ca.uwaterloo.watform.ast; -//tmp import java.util.*; import java.util.List; @@ -15,6 +14,7 @@ import ca.uwaterloo.watform.core.*; +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; import ca.uwaterloo.watform.parser.StateTable; import ca.uwaterloo.watform.parser.TransTable; @@ -33,7 +33,7 @@ public class DashState extends Dash { // 6 args // probably not used? public DashState(Pos p, String n, String prm, DashStrings.StateKind k, DashStrings.DefKind d, List i) { - assert(n != null && prm != null & i != null); + assert(n != null && i != null); this.pos = p; this.name = n; this.param = prm; @@ -43,6 +43,7 @@ public DashState(Pos p, String n, String prm, DashStrings.StateKind k, DashStrin //System.out.println("here1 creating "+this.name+" "+ this.kind); } + /* // basic state - default or non-default // 3 args public DashState(Pos p, String n, DashStrings.DefKind d) { @@ -79,7 +80,7 @@ public DashState(Pos p, String n, String prm, List i) { this.items = i; //System.out.println("here4 creating "+this.name+" "+ this.kind); } - + */ public String toString() { String s = new String(""); //s += s.join("", Collections.nCopies(tab*tabsize, " ")); @@ -103,6 +104,12 @@ public String toString() { return s; } + public static String noParam() { + return null; + } + public static List noSubstates() { + return new ArrayList(); + } // env events cannot be generated // env vars cannot be primed anywhere // must have at least one transition (could be looping on Root ...) @@ -110,22 +117,20 @@ public String toString() { /* * check for errors in the state hierarchy * and put all states in the state table - * also sets this state's fqn here + * also set this state's fqn here */ public void resolveAllStates(StateTable st, List params, List ances) { if (DashFQN.alreadyFQN(name)) DashErrors.stateNameCantBeFQN(pos, name); sfqn = DashFQN.fqn(ances,name); System.out.println("Resolving state "+sfqn); - - List newParams = new ArrayList(params); - if (param != null) newParams.add(param); - + // process the children // have to make a copy so that recursion does not just // continue to add to list everywhere List newAnces = new ArrayList(ances); - newAnces.add(name); - + newAnces.add(name); + List newParams = new ArrayList(params); + if (param != null) newParams.add(param); List substatesList = new ArrayList(); if (items != null) @@ -136,13 +141,8 @@ public void resolveAllStates(StateTable st, List params, List an .collect(Collectors.toList()); if (substatesList.isEmpty() ) { - - if (kind == DashStrings.StateKind.AND) - DashErrors.concStateNoChildren(sfqn); - else if (param != null) - DashErrors.basicStateParam(sfqn); - else - st.add(sfqn, kind, params, null, DashFQN.fqn(ances), null); + + st.add(sfqn, kind, param, newParams, def, DashFQN.fqn(ances), null); } else { @@ -153,32 +153,49 @@ else if (param != null) Set dups = DashUtilFcns.findDuplicates(childFQNs); if (!dups.isEmpty()) DashErrors.dupSiblingNames(DashUtilFcns.strCommaList(dups.stream().collect(Collectors.toList()))); - - // all sibling names must be the same type - Set k = new HashSet(); - substatesList.forEach(i -> k.add(i.kind)); - if (k.size() != 1) - DashErrors.siblingsSameKind(sfqn); - - // if substates are OR, then must be a default unless there is only one substate - // parent kind does not matter - String def = null; - if (k.contains(DashStrings.StateKind.OR) && substatesList.size() != 1) { - // names of the default states - List defaultsList = + + // add this state to the table + st.add(sfqn,kind, param, newParams,def, DashFQN.fqn(ances), childFQNs); + + // add all substates to the table + for (DashState s: substatesList) s.resolveAllStates(st, newParams, newAnces); + + // make sure defaults are correct + // if there's only one child it is automatically the default + if (substatesList.size() == 1) { + // make sure it is set as default + // this child should already be in the state table + // might already be set as duplicate but that's okay + // have to use the substate's FQN here + st.setAsDefault(childFQNs.get(0)); + } else { + // default states + List defaultsList = substatesList.stream() .filter(i -> (i.def == DashStrings.DefKind.DEFAULT)) - .map(i -> i.name) .collect(Collectors.toList()); - if (defaultsList.size() > 1) DashErrors.tooManyDefaults(sfqn); - else if (defaultsList.isEmpty()) DashErrors.noDefaultState(sfqn); - else def = defaultsList.get(0); - } else if (k.contains(DashStrings.StateKind.OR) && substatesList.size() == 1) { - def = substatesList.get(0).name; + List andList = + substatesList.stream() + .filter(i -> (i.kind == DashStrings.StateKind.AND)) + .collect(Collectors.toList()); + if (andList.equals(substatesList) && defaultsList.size() == 0) { + // all AND-states and non designated as defaults so all are defaults + for (String ch: childFQNs) st.setAsDefault(ch); + } else if (defaultsList.size() == 0) + DashErrors.noDefaultState(sfqn); + else { + // if defaults list contains an OR states, it should be size 1 + boolean flag = defaultsList.stream().anyMatch( (s) -> s.kind == DashStrings.StateKind.OR); + if (flag) { + if (defaultsList.size() != 1) DashErrors.tooManyDefaults(sfqn); + // o/w one OR state is default + } else { + // if defaults list is all c's, all c children should be included + + if (defaultsList != andList) DashErrors.allAndDefaults(sfqn); + } + } } - st.add(sfqn,kind, newParams,def, DashFQN.fqn(ances), childFQNs); - - for (DashState s: substatesList) s.resolveAllStates(st, newParams, newAnces); } /* @@ -242,40 +259,45 @@ public void resolveAllTrans(StateTable st, TransTable tt) { // transition src/dest have to be resolved here rather than in DashTrans because // this src and dest are contextual - List fromList = + List fromList = t.items.stream() .filter(i -> i instanceof DashFrom) .map(p -> ((DashFrom) p).src) .collect(Collectors.toList()); - String src = setSrcDest("from", fromList, st, sfqn, tfqn); - assert(src != null); // should have thrown an exception - st.add(src); + System.out.println(fromList); + DashRef src = setSrcDest("from", fromList, st, sfqn, tfqn); + assert(src != null); + st.add(src.getName()); - List gotoList = + List gotoList = t.items.stream() .filter(i -> i instanceof DashGoto) .map(p -> ((DashGoto) p).dest) .collect(Collectors.toList()); - String dest = setSrcDest("goto", gotoList, st, sfqn, tfqn); - assert(dest != null); // should have thrown an exception - st.add(dest); - - // note that this is not newAnces; states referenced by t can be siblings to the state - // that t is within + System.out.println(gotoList); + DashRef dest = setSrcDest("goto", gotoList, st, sfqn, tfqn); + assert(dest != null); + st.add(dest.getName()); + /* + // AND-cross transitions are now allowed // check if it is an AND-cross transition List srcAnces = st.getAllAnces(src); - System.out.println("src="+src+" srcAnces= "+srcAnces); + // System.out.println("src="+src+" srcAnces= "+srcAnces); List destAnces = st.getAllAnces(dest); - System.out.println("dest="+dest+" destAnces= "+destAnces); + // System.out.println("dest="+dest+" destAnces= "+destAnces); int i = 0; + // find closest common ances while (i< srcAnces.size() && i < destAnces.size() && srcAnces.get(i).equals(destAnces.get(i))) i++; + // are there any conc states between src/dest and the closest common ances? for (int j=i; j < srcAnces.size();j++) - if (st.getKind(srcAnces.get(i)) == DashStrings.StateKind.AND) + if (st.isAnd(srcAnces.get(i))) DashErrors.andCrossTransition(tfqn); for (int j=i; j < destAnces.size(); j++) - if (st.getKind(destAnces.get(i)) == DashStrings.StateKind.AND) + if (st.isAnd(st.getKind(destAnces.get(i)))) DashErrors.andCrossTransition(tfqn); + */ + tt.add(tfqn,st.getParams(sfqn),src,dest); } if (items != null ) { @@ -286,7 +308,7 @@ public void resolveAllTrans(StateTable st, TransTable tt) { .collect(Collectors.toList()); for (DashState s: substatesList) s.resolveAllTrans(st, tt); } - // t.resolveAll(st, tt, newParams, ances); + } @@ -299,37 +321,71 @@ public void resolveAllTrans(StateTable st, TransTable tt) { * Otherwise, it looks at all uniquely named states up to an ancestor conc state * Requires state table to have been built already */ - public String setSrcDest(String xType, List ll, StateTable st, String parentFQN, String tfqn) { + + public DashRef setSrcDest(String xType, List ll, StateTable st, String parentFQN, String tfqn) { + //System.out.println("Here"); + //System.out.println(ll); if (ll.size() > 1) { DashErrors.moreThanOneSrcDest(xType, tfqn); return null; } else if (ll.isEmpty()) - // could be root - return sfqn; + // can be a loop on root + return new DashRef(parentFQN, ExprHelper.createVarExprList(DashStrings.pName,st.getParams(parentFQN))); else { // if has slashes, turn to "-" - String xName = ll.get(0); - if (DashFQN.alreadyFQN(xName)) return xName; - else { + DashRef x = ll.get(0); + //System.out.println("Looking for: " + x); + if (DashFQN.alreadyFQN(x.getName())) { + // number of params provided must match number of params needed + if (x.getParamValues().size() != st.getParams(x.getName()).size()) { + DashErrors.fqnSrcDestMustHaveRightNumberParams(xType,tfqn); + return null; + } + return x; + } else { + // not fully qualified + // shouldn't have params in DashRef + // Root could be here but won't have params + if (!x.getParamValues().isEmpty()) { + DashErrors.srcDestCantHaveParam(xType,tfqn); + return null; + } + // Root ends up here List matches = new ArrayList(); - for (String s:st.getAllNonConcStatesWithinThisState(st.getClosestConcAnces(parentFQN))) { - if (xName.equals(DashFQN.chopNameFromFQN(s))) matches.add(s); + //String a = st.getClosestConcAnces(parentFQN); + //System.out.println("getClosestConcAnces: "+a); + //List b = st.getAllNonConcStatesWithinThisState(a); + //System.out.println("getAllNonConcStatesWithinThisState "+b); + for (String s:st.getRegion(parentFQN)) { + if (x.getName().equals(DashFQN.chopNameFromFQN(s))) matches.add(s); } + System.out.println("matches: " + matches); if (matches.size() > 1) { DashErrors.ambiguousSrcDest(xType, tfqn); return null; } else if (matches.isEmpty()) { //DashUtilFcns.myprint(st.toString()); - DashErrors.unknownSrcDest(xName,xType,tfqn); + DashErrors.unknownSrcDest(x.getName(),xType,tfqn); return null; } else { - return matches.get(0); + String m = matches.get(0); + //System.out.println(m); + // must have same param values as trans b/c in same conc region + return new DashRef(m, paramVars(st.getParams(m))); } } } } + // [n1,n2,...] + private List paramVars(List names) { + List o = new ArrayList(); + for (String n: names) o.add(ExprHelper.createVar(DashStrings.pName+n)); + return o; + } + + /* public String getParam() { return params(1) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 0aafc0634..552c17cc0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -13,57 +13,88 @@ public class DashErrors { // syntax errors -------------------------------------------- - public static void stateNameCantBeFQN(Pos o, String name) throws Err { - throw new ErrorSyntax(o,"State name "+name+" when declared cannot have slash"); - } + public static String onlyOneStateMsg = "Model can only have one 'state' section"; public static void onlyOneState(Pos o) throws Err { - throw new ErrorSyntax(o,"Model can only have one 'state' section"); + throw new ErrorSyntax(o,onlyOneStateMsg); } - public static void dupSiblingNames(String dups) throws Err { - throw new ErrorSyntax("Duplicate sibling state names: " + dups); + public static String noTransMsg = "Model does not contain any transitions."; + public static void noTrans() throws Err { + throw new ErrorSyntax(noTransMsg); } - public static void dupTransNames(String dups) throws Err { - throw new ErrorSyntax("Duplicate sibling state names: " + dups); + public static String noStatesMsg = "Model must have at least one state."; + public static void noStates() throws Err { + throw new ErrorSyntax(noStatesMsg); } - public static void siblingsSameKind(String fqn) throws Err { - throw new ErrorSyntax("Children of "+fqn+" must all be of concurrent or not concurrent"); + public static String tooManyDefaultStatesMsg = "Too many default states in state: "; + public static void tooManyDefaults(String fqn) throws Err { + throw new ErrorSyntax(tooManyDefaultStatesMsg+fqn); } - public static void crossRefMoreThanOneArg(Pos o, String n) throws Err { - throw new ErrorSyntax(o,"Two many args to reference to "+n+" in sibling state"); + public static String noDefaultStateMsg = "State does not have default state: "; + public static void noDefaultState(String fqn) throws Err { + throw new ErrorSyntax(noDefaultStateMsg+fqn); } - public static void moreThanOneSrcDest(String x, String n) throws Err { - throw new ErrorSyntax("Transition "+n+" has more than one "+ x); + public static String allConcDefaultStatesMsg = "All conc children of state must be defaults if one is for state: "; + public static void allAndDefaults(String sfqn) throws Err { + throw new ErrorSyntax(allConcDefaultStatesMsg+sfqn); } - public static void noTrans() throws Err { - throw new ErrorSyntax("Model does not contain any transitions."); + public static String stateNameCantBeFQNMsg = "When declared, state name cannot have slash: "; + public static void stateNameCantBeFQN(Pos o, String name) throws Err { + throw new ErrorSyntax(o,stateNameCantBeFQNMsg+name); } - public static void transUsesNonExistentState(String n) throws Err { - throw new ErrorSyntax("Some transition has from/goto to state "+n+" which doesn't exist"); + public static String dupSiblingNamesMsg = "Duplicate sibling state names: "; + public static void dupSiblingNames(String dups) throws Err { + throw new ErrorSyntax(dupSiblingNamesMsg + dups); } - public static void tooManyDefaults(String fqn) throws Err { - throw new ErrorSyntax("State "+fqn+" has more than one default state"); + public static String dupTransNameMsg = "Duplicate transition names: "; + public static void dupTransNames(String dups) throws Err { + throw new ErrorSyntax(dupTransNameMsg + dups); } - public static void noDefaultState(String fqn) throws Err { - throw new ErrorSyntax("State "+fqn+" does not have a default state"); + public static String moreThanOneSrcDestMsg = "Transition has more than one src or dest: "; + public static void moreThanOneSrcDest(String x, String n) throws Err { + throw new ErrorSyntax(moreThanOneSrcDestMsg + x); } + public static String unknownSrcDestMsg = "Src/Dest of trans is unknown: "; public static void unknownSrcDest(String x, String t, String tfqn) throws Err { - throw new ErrorSyntax("Trans "+tfqn+" "+t+" "+x+ " is unknown"); + throw new ErrorSyntax(unknownSrcDestMsg + "trans "+tfqn+" "+t+" "+x); } + public static String fqnSrcDestMustHaveRightNumberParamsMsg = "A fully qualified state name must have the right number of parameters: "; + public static void fqnSrcDestMustHaveRightNumberParams(String xType, String tfqn) throws Err { + throw new ErrorSyntax(fqnSrcDestMustHaveRightNumberParamsMsg + xType + " of transition "+ tfqn ); + } + public static String srcDestCantHaveParamMsg = "Non-fully qualified src/dest cannot have parameters: "; + public static void srcDestCantHaveParam(String xType, String tfqn) throws Err { + throw new ErrorSyntax(srcDestCantHaveParamMsg + xType + " of transition "+ tfqn ); + } + public static String ambiguousSrcDestMsg = "State name not unique within this conc/Root region: "; public static void ambiguousSrcDest(String x, String tfqn) throws Err { - throw new ErrorSyntax("Trans "+tfqn+" "+x+" dest name is ambiguous: could be child of of parent state or sibling of parent state"); + throw new ErrorSyntax(ambiguousSrcDestMsg + "trans "+tfqn+" "+x); } + // below this have not been tested + + + public static void siblingsSameKind(String fqn) throws Err { + throw new ErrorSyntax("Children of "+fqn+" must all be of concurrent or not concurrent"); + } + public static void crossRefMoreThanOneArg(Pos o, String n) throws Err { + throw new ErrorSyntax(o,"Two many args to reference to "+n+" in sibling state"); + } + + + public static void transUsesNonExistentState(String n) throws Err { + throw new ErrorSyntax("Some transition has from/goto to state "+n+" which doesn't exist"); + } + + + public static void andCrossTransition(String tfqn) throws Err { throw new ErrorSyntax("Trans "+tfqn+" goes between concurrent states"); } + + + // parts of the code that should be unreachable ------------- - public static void concStateNoChildren(String fqn) throws Err { - throw new ErrorFatal("Concurrent state "+fqn+" must have substates"); - } - public static void basicStateParam(String fqn) throws Err { - throw new ErrorFatal("Basic state "+fqn+" has parameter"); - } public static void toAlloyNoDash() throws Err { throw new ErrorFatal("Translating to Alloy when no Dash part"); } @@ -88,5 +119,10 @@ public static void transDoesNotExist(String s1, String n) throws Err { public static void missingExpr(String s) throws Err { throw new ErrorFatal("Missing expr type in "+s); } - + public static void tooHighParamDepth() throws Err { + throw new ErrorFatal("paramsDepthInUse called with too high a number"); + } + public static void ancesNotPrefix(String a, String d) throws Err { + throw new ErrorFatal(a + " must be prefix of " + d); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java index a01d2c3d8..a45aea5eb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java @@ -77,5 +77,24 @@ public static String longestCommonFQN(String a, String b) { while (i < minLength && aSplit.get(i).equals(bSplit.get(i))) i++; return fqn(aSplit.subList(0,i)); } - + public static List allPrefixes(String fqn) { + List prefixes = new ArrayList(); + // not including state itself + List splitfqn = splitFQN(fqn); + for (int i=0;i < splitfqn.size()-1; i++) { + StringJoiner sj = new StringJoiner(inputQualChar); + for (int j=0;j<=i;j++) { + sj.add(splitfqn.get(j)); + } + prefixes.add(sj.toString()); + } + return prefixes; + } + /* ances: A/B/C dest: A/B/C/D/E returns A/B/C/D */ + public static String getChildOfContextAncesOfDest(String ances, String dest) { + if (dest.startsWith(ances)) + // by going to ances, we are adding +1 + return fqn(splitFQN(dest).subList(0,splitFQN(ances).size())); + else { DashErrors.ancesNotPrefix(ances,dest); return null; } + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index d2821a2a2..a86bf439f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -15,6 +15,7 @@ public class DashStrings { public static String asName = "as"; public static String boolName = "boolean/Bool"; public static String trueName = "boolean/True"; + public static String noneName = "none"; public static String intName = "int"; public static String utilBooleanName = "util/boolean"; public static String utilCTLpathName = "util/ctl_path"; @@ -58,7 +59,7 @@ public class DashStrings { // sig names public static String snapshotName = "Snapshot"; - public static String confName = "confName"; + public static String confName = "conf"; public static String takenName = "taken"; public static String stateLabelName = "StateLabel"; @@ -88,8 +89,8 @@ public class DashStrings { public static String tracesName = "traces"; - public static String sCurName = "s"; - public static String sNextName = "sNext"; + public static String curName = "s"; + public static String nextName = "sNext"; public static String prime(String a) { return a+"'"; }; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java index e8a4d670d..33fc09747 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java @@ -34,9 +34,9 @@ public static Set findDuplicates(Collection collection) { return duplicates; } - public static String strCommaList(List ll) { + public static String strCommaList(List ll) { StringJoiner sj = new StringJoiner(", "); - ll.forEach(n -> sj.add(n)); + ll.forEach(n -> sj.add(n.toString())); return sj.toString(); } public static Set listToSet(List ll) { @@ -56,4 +56,13 @@ public static List newListWith(List ll, T s) { x.add(s); return x; } + public static String NoneStringIfNeeded(T x) { + return ( (x == null) ? "none" : x.toString()) ; + } + + public static void handleException(Exception e) { + e.printStackTrace(System.err); + System.exit(1); + } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index ba4d61d54..037ef5a2f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -16,10 +16,17 @@ import edu.mit.csail.sdg.ast.Decl; import edu.mit.csail.sdg.ast.ExprVar; import edu.mit.csail.sdg.ast.Expr; -import ca.uwaterloo.watform.core.*; +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; -import ca.uwaterloo.watform.alloyasthelper.*; +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.alloyasthelper.DeclExt; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; import ca.uwaterloo.watform.parser.DashModule; import ca.uwaterloo.watform.parser.CompModuleHelper; @@ -41,7 +48,7 @@ public void translate() { createTransPost(t); createTransSemantics(t); createTransIsEnabledAfterStep(t); - createTransPred(t); + createTrans(t); } createSmallStep(); } @@ -53,28 +60,35 @@ private String fqn(String s) { // but we can't output "/" in Alloy identifiers // so before outputting we convert "/" to "_" // for everything - return DashFQN.convertFQN(s); + return convertFQN(s); } private void createSpaceSignatures() { - // abstract sig Statelabel + // abstract sig Statelabel {} d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); - // abstract sig SystemState extend StateLabel - d.alloyString += d.addAbstractExtendsSigSimple(DashStrings.systemStateName,DashStrings.stateLabelName); - - recurseCreateStateSpaceSigs(DashStrings.stateLabelName, fqn(d.getRootName())); - + // Root + //if (d.hasConcurrency() || d.getImmChildren(d.getRootName()).isEmpty()) + //d.alloyString += d.addExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + //else + d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + recurseCreateStateSpaceSigs(d.getRootName()); d.alloyString += "\n"; + // abstract sig TransLabel {} d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); + // add all transitions as one sig extensions of TransLabel for (String t : d.getTransNames()) { d.alloyString += d.addOneExtendsSigSimple(fqn(t), DashStrings.transitionLabelName); } d.alloyString += "\n"; - if (d.getMaxDepthParams() != 0) d.alloyString += d.addAbstractSigSimple(DashStrings.identifierName); - if (!d.getAllParams().isEmpty()) + + // abstract sig Identifiers {} if this model has parameterized components + if (d.getMaxDepthParams() != 0) { + d.alloyString += d.addAbstractSigSimple(DashStrings.identifierName); for (String s: d.getAllParams()) d.alloyString += d.addExtendsSigSimple(s, DashStrings.identifierName); - d.alloyString += "\n"; + d.alloyString += "\n"; + } + /* if (d.hasEvents()) { addAbstractSigSimple(eventLabelName); @@ -101,43 +115,49 @@ private void createSpaceSignatures() { } */ } - private void recurseCreateStateSpaceSigs(String parent, String child) { - if (d.isBasicState(child)) d.alloyString += d.addOneExtendsSigSimple(fqn(child),fqn(parent)); - else { - d.alloyString += d.addAbstractExtendsSigSimple(fqn(child), fqn(parent)); - for (String grandchild: d.getImmChildren(child)) recurseCreateStateSpaceSigs(child, grandchild); + private void recurseCreateStateSpaceSigs(String parent) { + for (String child: d.getImmChildren(parent)) + if (d.isLeaf(child)) d.alloyString += d.addOneExtendsSigSimple(fqn(child),fqn(parent)); + else { + //if (d.isAnd(parent)) + //d.alloyString += d.addExtendsSigSimple(fqn(child), fqn(parent)); + //else + d.alloyString += d.addAbstractExtendsSigSimple(fqn(child), fqn(parent)); + recurseCreateStateSpaceSigs(child); } } private void createSnapshotSig(){ if (DashOptions.isElectrum) { // if Electrum add var sigs // taken0, conf0, event0 - d.alloyString += d.addVarSigSimple(DashStrings.takenName+"0", ExprHelper.createVar(DashStrings.transitionLabelName)); - d.alloyString += d.addVarSigSimple(DashStrings.confName+"0", ExprHelper.createVar(DashStrings.stateLabelName)); + + if (d.transAtThisParamDepth(0)) + d.alloyString += d.addVarSigSimple(DashStrings.takenName+"0", createVar(DashStrings.transitionLabelName)); + d.alloyString += d.addVarSigSimple(DashStrings.confName+"0", createVar(DashStrings.stateLabelName)); if (d.hasEvents()) - d.alloyString += d.addVarSigSimple(DashStrings.eventName+"0", ExprHelper.createVar(DashStrings.eventLabelName)); - if (d.getMaxDepthParams() != 0) { - for (int i = 1; i < d.getMaxDepthParams()+1; i++) { - List cop = new ArrayList (Collections.nCopies(i,ExprHelper.createVar(DashStrings.identifierName))); + d.alloyString += d.addVarSigSimple(DashStrings.eventName+"0", createVar(DashStrings.eventLabelName)); + List cop; + for (int i = 1; i <= d.getMaxDepthParams(); i++) { + cop = new ArrayList (Collections.nCopies(i+1,createVar(DashStrings.identifierName))); + if (d.transAtThisParamDepth(i)) // taken 1, etc. d.alloyString += d.addVarSigSimple( DashStrings.takenName+Integer.toString(i), - DashUtilFcns.newListWith(cop, ExprHelper.createVar(DashStrings.transitionLabelName))); + DashUtilFcns.newListWith(cop, createVar(DashStrings.transitionLabelName))); // conf 1, etc. + d.alloyString += d.addVarSigSimple( + DashStrings.confName+Integer.toString(i), + DashUtilFcns.newListWith(cop, createVar(DashStrings.stateLabelName))); + // event 1, etc. + if (d.hasEvents()) d.alloyString += d.addVarSigSimple( - DashStrings.confName+Integer.toString(i), - DashUtilFcns.newListWith(cop, ExprHelper.createVar(DashStrings.stateLabelName))); - // event 1, etc. - if (d.hasEvents()) - d.alloyString += d.addVarSigSimple( - DashStrings.eventName+Integer.toString(i), - DashUtilFcns.newListWith(cop, ExprHelper.createVar(DashStrings.eventLabelName))); - } + DashStrings.eventName+Integer.toString(i), + DashUtilFcns.newListWith(cop, createVar(DashStrings.eventLabelName))); } + // stable: one boolean; if (d.hasConcurrency()) { - //TODO now to make this one boolean - d.alloyString += d.addVarSigSimple(DashStrings.stableName, ExprHelper.createVar(DashStrings.boolName)); + d.alloyString += d.addVarSigSimple(DashStrings.stableName, createVar(DashStrings.boolName)); } // add dynamic symbols (vars and buffers) /* @@ -153,31 +173,32 @@ private void createSnapshotSig(){ List decls = new ArrayList(); // taken0, conf0, event0 - decls.add(DeclExt.newSetDeclExt(DashStrings.takenName+"0", DashStrings.transitionLabelName)); + if (d.transAtThisParamDepth(0)) + decls.add(DeclExt.newSetDeclExt(DashStrings.takenName+"0", DashStrings.transitionLabelName)); decls.add(DeclExt.newSetDeclExt(DashStrings.confName+"0", DashStrings.stateLabelName)); if (d.hasEvents()) decls.add(DeclExt.newSetDeclExt(DashStrings.eventName+"0", DashStrings.eventLabelName)); - if (d.getMaxDepthParams() != 0) { - for (int i = 1; i < d.getMaxDepthParams()+1; i++) { - List cop = Collections.nCopies(i+1,DashStrings.identifierName); - // taken 1, etc. + List cop; + for (int i = 1; i <= d.getMaxDepthParams(); i++) { + cop = Collections.nCopies(i+1,DashStrings.identifierName); + // taken 1, etc. + if (d.transAtThisParamDepth(i)) decls.add(DeclExt.newSetDeclExt( DashStrings.takenName+Integer.toString(i), - ExprHelper.createArrowList(DashUtilFcns.newListWith(cop, DashStrings.transitionLabelName)))); - // conf 1, etc. - decls.add(DeclExt.newSetDeclExt( - DashStrings.confName+Integer.toString(i), - ExprHelper.createArrowList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName)))); - // event 1, etc. - if (d.hasEvents()) - decls.add(new DeclExt( - DashStrings.eventName+Integer.toString(i), - ExprHelper.createArrowList(DashUtilFcns.newListWith(cop, DashStrings.eventLabelName)))); - } + createArrowList(DashUtilFcns.newListWith(cop, DashStrings.transitionLabelName)))); + // conf 1, etc. + decls.add(DeclExt.newSetDeclExt( + DashStrings.confName+Integer.toString(i), + createArrowList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName)))); + // event 1, etc. + if (d.hasEvents()) + decls.add(new DeclExt( + DashStrings.eventName+Integer.toString(i), + createArrowList(DashUtilFcns.newListWith(cop, DashStrings.eventLabelName)))); } // stable: one boolean; if (d.hasConcurrency()) { - decls.add(new DeclExt(DashStrings.stableName, ExprHelper.createOne(ExprHelper.createVar(DashStrings.boolName)))); + decls.add(new DeclExt(DashStrings.stableName, createOne(createVar(DashStrings.boolName)))); } // add dynamic symbols (vars and buffers) /* @@ -212,17 +233,17 @@ .trig_events_t1 in (s.events & EnvironmentalEvent ) */ private void createTransPre(String t) { List prs = d.getTransParams(t); - List o = new ArrayList(); + List body = new ArrayList(); - /* + // p3 -> p2 -> p1 -> src in s.confVar(i) // src does not have to be a basic state - Expr src = createVar(d.getTransSrc(t)); - ArrayList psList = createVars(prs); - o.add(createIn(createArrowList(createVars(prs).add(src)),curConf(prs.size()))); - + /* + body.add(createIn(paramsToXArrow(prs,convertFQN(d.getTransSrc(t))),curConf(prs.size()))); + */ + /* // guard_cond_t1 [s] - o.add(d.getTransGuard(t).convertToAlloy(d.symbolTable, sCurVar(), sNextVar())); + o.add(d.getTransGuard(t).convertToAlloy(d.symbolTable, curVar(), nextVar())); // events if (d.hasConcurrency() && d.getTransTrigger(t) != null && d.hasEnvironmentalEvents()) { @@ -243,18 +264,15 @@ private void createTransPre(String t) { Expr body = createAnd(o); */ - // tmp - List body = Arrays.asList(ExprHelper.createNullExpr()); - - d.alloyString += d.addPredSimple(DashFQN.convertFQN(t)+DashStrings.preName, curParamsDecls(prs), body); + d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.preName, curParamsDecls(prs), body); d.alloyString += "\n"; } private void createTransPost(String t) { List prs = d.getTransParams(t); // tmp - List body = Arrays.asList(ExprHelper.createNullExpr()); - d.alloyString += d.addPredSimple(DashFQN.convertFQN(t)+DashStrings.postName,curNextParamsDecls(prs),body); + List body = new ArrayList(); + d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.postName,curNextParamsDecls(prs),body); } // ----------------------------------------------------------------------------- /* @@ -266,16 +284,46 @@ private void createTransPost(String t) { no t1.notOrthogonal & (s.taken0 + taken0 |> TransitionLabel + s.taken1 |> TransitionLabel + ...) } for all t in t1.higherPri - some p0. p1. !pre_higherpri_trans[s,p0,p1] + // all have same param values (or prefixes) because these trans are from srcs + // that are ances of the src of this transition + !pre_higherpri_trans[s,pParam0,pParam1] + !pre_higherpri_trans[s,pParam0] + // it depends on the params of the src state not on t1's params! ACK!!! + // maybe it is okay because pre_ of the trans has the correct parameters (might be trans params or something user has provided) } */ private void createTransSemantics(String t) { - //List body = new ArrayList(); + List body = new ArrayList(); List prs = d.getTransParams(t); + String tfqn = convertFQN(t); // output FQN + - /* // s'.taken = s.taken + t1 - Expr elseExpr = createEquals(nextTaken(prs.size()),createPlus(curTaken(prs.size()),createParamsJoin(prs,t1))); + // or + // s'.taken2 = s.taken2 + p2 -> p1 -> tfqn + // and other takens stay the same + List takens = new ArrayList(); + for (int i=0;i <= d.getMaxDepthParams(); i++) + if (d.transAtThisParamDepth(i)) + if (i == prs.size()) + if (DashOptions.isElectrum) + takens.add(createEquals( + taken(i), + createPlus(taken(i),paramsToXArrow(prs,tfqn)))); + else takens.add(createEquals( + nextTaken(i), + createPlus(curTaken(i),paramsToXArrow(prs,tfqn)))); + else + if (DashOptions.isElectrum) takens.add(createEquals(taken(i), curTaken(i))); + else takens.add(createEquals(nextTaken(i), curTaken(i))); + Expr elseExpr = createAnd(takens); + + // no trans "below" the scope of this trans with the same params can be taken + // (other params are for other parts of state hierarchy at this depth) + + // for the rest of the non-orthogonal trans, param values don't matter + + /* if (notOrthogonal != null) { elseExpr = createAnd( @@ -286,22 +334,48 @@ private void createTransSemantics(String t) { createNonOrthogonalExpr(t), createChoppedGroup(prs.size(),DashStrings.takenName,DashStrings.transitionLabelName)))); } - - body.add( - createITE(sCurStableTrue(), - // s'.taken = t1 - createEquals(nextTaken(prs.size()), createParamsJoin(prs,t1)), - elseExpr - ) - for (h: dash.transTable.get(t).getHigherPriority()) { - List prs = h.getParams(); - // some p0. p1. !pre_higherpri_trans[s,p0,p1] - body.add(createSome(paramsDecls(prs), createNot(curJoinParams(prs,h+DashStrings.preName)))) + */ + takens = new ArrayList(); + for (int i=0;i <= d.getMaxDepthParams(); i++) + if (d.transAtThisParamDepth(i)) + if (i == prs.size()) + if (DashOptions.isElectrum) + takens.add(createEquals( + taken(i), + paramsToXArrow(prs,tfqn))); + else takens.add(createEquals( + nextTaken(i), + paramsToXArrow(prs,tfqn))); + else + if (DashOptions.isElectrum) takens.add(createEquals(taken(i), createNone())); + else takens.add(createEquals(nextTaken(i), createNone())); + Expr firsttaken = createAnd(takens); + if (d.hasConcurrency()) + body.add( + createITE(curStableTrue(), + // s'.taken = t1 + firsttaken, + elseExpr) + ); + else + // will only have taken0 in it + body.add(firsttaken); + + // priority + // depends on the src of this transition + for (String h: d.getHigherPriTrans(t)) { + List hprs = d.getTransParams(h); + // !pre_higherpri_trans[s,p0,p1] + // Note: all the parameter values will be the same + // only lower priority transitions could have more parameters + if (DashOptions.isElectrum) + body.add(createNot(createPredCall(convertFQN(h+DashStrings.preName),paramVars(hprs)))); + else + body.add(createNot(createPredCall(convertFQN(h+DashStrings.preName),curParamVars(hprs)))); } - */ - // tmp - List body = Arrays.asList(ExprHelper.createNullExpr()); - d.alloyString += d.addPredSimple(DashFQN.convertFQN(t)+DashStrings.semanticsName,curNextParamsDecls(prs),body); + + + d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.semanticsName,curNextParamsDecls(prs),body); d.alloyString += "\n"; } // --------------------------------------------------- @@ -344,7 +418,7 @@ private void createTransIsEnabledAfterStep(String t) { // guard_cond_t1 [s'] // final parameter (usually s') should not be used in precondition - o.add(dash.getTransGuard(t).convertToAlloy(dash.symbolTable, sNextVar(), null, prs)); + o.add(dash.getTransGuard(t).convertToAlloy(dash.symbolTable, nextVar(), null, prs)); // no t1.notOrthogonal & (t + s.taken + s.taken1 |> TransitionLabel + taken2 |> TransitionLabel + ...) @@ -380,8 +454,8 @@ private void createTransIsEnabledAfterStep(String t) { if (d.hasEvents()) decls.add((Decl) DeclExt.newSetDeclExt(DashStrings.geName, DashStrings.eventLabelName)); // tmp - List body = Arrays.asList(ExprHelper.createNullExpr()); - d.alloyString += d.addPredSimple(DashFQN.convertFQN(t)+DashStrings.isEnabledAfterStepName,decls,body); + List body = new ArrayList(); + d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.isEnabledAfterStepName,decls,body); d.alloyString += "\n"; } @@ -392,97 +466,196 @@ private void createTransIsEnabledAfterStep(String t) { pparam2.pparam1.pparam0.s'.s.post_1 and pparam2.pparam1.pparam0.s'.s'.semantics_t1 */ - private void createTransPred(String t) { + private void createTrans(String t) { // t is FQN // e.g. [ClientId,ServerId.,,,] List prs = d.getTransParams(t); List body = new ArrayList(); - String tfqn = DashFQN.convertFQN(t); - // pre_transName[s, p0, p1, p2] -> p2.p1.p0.s.pre_transName - body.add(ExprHelper.createPredCall(tfqn + DashStrings.preName, curParamsArgs(prs))); - // p2.p1.p0.s'.s.post_transName - body.add(ExprHelper.createPredCall(tfqn + DashStrings.preName, curNextParamsArgs(prs))); - // p2.p1.p0.s'.s.semantics_transName - body.add(ExprHelper.createPredCall(tfqn + DashStrings.preName, curNextParamsArgs(prs))); + String tfqn = convertFQN(t); // output FQN + + if (DashOptions.isElectrum) { + // pre_transName[ p0, p1, p2] -> p2.p1.p0.pre_transName + body.add(createPredCall(tfqn + DashStrings.preName, paramVars(prs))); + // p2.p1.p0.post_transName + body.add(createPredCall(tfqn + DashStrings.postName, paramVars(prs))); + // p2.p1.p0.semantics_transName + body.add(createPredCall(tfqn + DashStrings.semanticsName, paramVars(prs))); + } else { + // pre_transName[s, p0, p1, p2] -> p2.p1.p0.s.pre_transName + body.add(createPredCall(tfqn + DashStrings.preName, curParamVars(prs))); + // p2.p1.p0.s'.s.post_transName + body.add(createPredCall(tfqn + DashStrings.postName, curNextParamVars(prs))); + // p2.p1.p0.s'.s.semantics_transName + body.add(createPredCall(tfqn + DashStrings.semanticsName, curNextParamVars(prs))); + } d.alloyString += d.addPredSimple(tfqn, curNextParamsDecls(prs), body); - d.alloyString += "\n"; } + // -------------------------------------------------------------------------------------- + /* + pred small_step [s:Snapshot, s': Snapshot] { + some pparam0 : Param0 , pparam1 : Param1 ... | + { // for all t’s at level i with params Param5, Param6, ... + (or t[s, s_next, pparam5, pparam6 ]) + // loop? big-step issue? + } + */ private void createSmallStep() { - ; + + // list of FQN of transitions + // does not have to be done in order of number of parameters b/c all disjuncted + ArrayList e = new ArrayList(); + for (String t: d.getTransNames()) { + String tfqn = convertFQN(t); // output FQN + // p3.p2.p1.s'.s.t for parameters of this transition + if (DashOptions.isElectrum) e.add(createPredCall(tfqn,paramVars(d.getTransParams(t)))); + else e.add(createPredCall(tfqn,curNextParamVars(d.getTransParams(t)))); + } + List body = new ArrayList(); + if (d.getAllParams().isEmpty()) body.add(createOr(e)); + else body.add(createSome(paramDecls(d.getAllParams()),createOr(e))); + + //TODO add loop if all notenabled + d.alloyString += d.addPredSimple(DashStrings.smallStepName,curNextDecls(),body); } - // useful shortcuts - private Decl sCurDecl() { - return (Decl) new DeclExt(DashStrings.sCurName, DashStrings.snapshotName); + + + // common decls + private Decl curDecl() { + return (Decl) new DeclExt(DashStrings.curName, DashStrings.snapshotName); } - private Decl sNextDecl() { - return (Decl) new DeclExt(DashStrings.sNextName, DashStrings.snapshotName); + private Decl nextDecl() { + return (Decl) new DeclExt(DashStrings.nextName, DashStrings.snapshotName); } - private Decl paramDecls(String n) { + private Decl paramDecl(String n) { return (Decl) new DeclExt(DashStrings.pName+n, n); } + private List curNextDecls() { + List o = new ArrayList(); + if (!DashOptions.isElectrum) { + o.add(curDecl()); + o.add(nextDecl()); + } + return o; + } + private List paramDecls(List prs) { + List o = new ArrayList(); + for (String n: prs) o.add(paramDecl(n)); + return o; + } private List curParamsDecls(List prs) { List o = new ArrayList(); - if (!DashOptions.isElectrum) o.add(sCurDecl()); - for (String n: prs) o.add(paramDecls(n)); + if (!DashOptions.isElectrum) o.add(curDecl()); + o.addAll(paramDecls(prs)); return o; } private List curNextParamsDecls(List prs) { List o = new ArrayList(); - if (!DashOptions.isElectrum) { o.add(sCurDecl()); o.add(sNextDecl()); } - for (String n: prs) o.add(paramDecls(n)); + if (!DashOptions.isElectrum) { o.add(curDecl()); o.add(nextDecl()); } + o.addAll(paramDecls(prs)); return o; } - private ExprVar sCurVar() { - return ExprHelper.createVar(DashStrings.sCurName); + // common vars + // s + private ExprVar curVar() { + return createVar(DashStrings.curName); } - private ExprVar sNextVar() { - return ExprHelper.createVar(DashStrings.sNextName); + // s' + private ExprVar nextVar() { + return createVar(DashStrings.nextName); } - private List convertParamsToVars(List names) { + // [n1,n2,...] + private List paramVars(List names) { List o = new ArrayList(); - for (String n: names) o.add(ExprHelper.createVar(DashStrings.pName+n)); + for (String n: names) o.add(createVar(DashStrings.pName+n)); return o; } - private List curParamsArgs(List params) { + private List curParamVars(List params) { List o = new ArrayList(); - o.add(sCurVar()); - o.addAll(convertParamsToVars(params)); + o.add(curVar()); + o.addAll(paramVars(params)); return o; } - private List curNextParamsArgs(List params) { + private List curNextParamVars(List params) { List o = new ArrayList(); - o.add(sCurVar()); - o.add(sNextVar()); - o.addAll(convertParamsToVars(params)); + o.add(curVar()); + o.add(nextVar()); + o.addAll(paramVars(params)); return o; } + + private Expr taken(int size) { + return createVar(DashStrings.takenName + size); + } + private Expr conf(int size) { + return createVar(DashStrings.confName + size); + } + private Expr stable() { + return createVar(DashStrings.stableName); + } + // s.taken5 + private Expr curTaken(int size) { + return curJoinExpr(taken(size)); + } + // s'.taken5 + private Expr nextTaken(int size) { + return nextJoinExpr(taken(size)); + } + // s.conf4 + private Expr curConf(int size) { + return curJoinExpr(conf(size)); + } + // s'.conf3 + private Expr nextConf(int size) { + return nextJoinExpr(conf(size)); + } + // s.stable == boolean/True + private Expr curStableTrue() { + return createEquals(stable(),createTrue()); + } + // s.name + private Expr curJoinExpr(Expr e) { + return createJoin(curVar(), e); + } + //s'.name + private Expr nextJoinExpr(Expr e) { + return createJoin(nextVar(), e); + } + // p3 -> p2 -> p1 -> x + private Expr paramsToXArrow(List prs, String x) { + Collections.reverse(prs); + Expr e = createVar(x); + for (String p: prs) { + e = createArrow(createVar(p),e); + } + return e; + } /* private Expr predJoinCurParams(String name, List prs) { //p2.p1.p0.s.name - Expr e = ExprHelper.createVar(name); + Expr e = createVar(name); List prsVarList = convertParamsToVars(prs); - if (!DashOptions.isElectrum) e = ExprHelper.createJoin(sCurVar(),e); + if (!DashOptions.isElectrum) e = createJoin(curVar(),e); if (prs!= null) { Collections.reverse(prsVarList); prsVarList.add(e); System.out.println("predJoinCurParams: " +prsVarList); - Expr x = ExprHelper.createJoinList(prsVarList); + Expr x = createJoinList(prsVarList); System.out.println("Join of prsVarList: " + x); - return ExprHelper.createJoinList(prsVarList) ; + return createJoinList(prsVarList) ; } else return e; } private Expr predJoinCurNextParams(String name, List prs) { //p2.p1.p0.s'.s.pre_transName - Expr e = ExprHelper.createVar(name); + Expr e = createVar(name); List prsVarList = convertParamsToVars(prs); - if (!DashOptions.isElectrum) e = ExprHelper.createJoin(sNextVar(),ExprHelper.createJoin(sCurVar(),e)); + if (!DashOptions.isElectrum) e = createJoin(nextVar(),createJoin(curVar(),e)); if (prs!=null) { Collections.reverse(prsVarList); prsVarList.add(e); - return ExprHelper.createJoinList(prsVarList) ; + return createJoinList(prsVarList) ; } else return e; } */ diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index 13d03fad3..cdd7aea7b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -25,58 +25,69 @@ public class MainFunctions { // both these function expect DashOptions to be set - public static DashModule parseFile(String filename, A4Reporter rep) { + public static DashModule parseAndResolveDashFile(String filename, A4Reporter rep) { DashModule dash = null; - try { - DashOptions.isTraces = true; - DashSituation.haveCountedBuffers = false; - DashSituation.bufferElements = new ArrayList(); - DashSituation.bufferNames = new ArrayList(); + + DashOptions.isTraces = true; + DashSituation.haveCountedBuffers = false; + DashSituation.bufferElements = new ArrayList(); + DashSituation.bufferNames = new ArrayList(); + dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); + if (dash == null) { + System.err.println("Empty Alloy file"); + } else { + DashSituation.haveCountedBuffers = true; dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); - if (dash == null) { - System.err.println("Empty Alloy file"); + //System.out.println(filename + " parsed successfully."); + // well-formedness checks + dash.resolveAllDash(rep); + //System.out.println(dash.toString()); + } + + return dash; + } + // only needed for testing + public static void parseAndResolveAlloyFile(String filename, A4Reporter rep) { + DashModule dash = null; + + DashOptions.isTraces = true; + DashSituation.haveCountedBuffers = false; + DashSituation.bufferElements = new ArrayList(); + DashSituation.bufferNames = new ArrayList(); + dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); + if (dash == null) { + System.err.println("Error in parsing"); + System.exit(1); + } else { + if (dash.hasRoot()) { + System.err.println("Not a pure Alloy file"); + System.exit(1); } else { - DashSituation.haveCountedBuffers = true; - dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); - //System.out.println(filename + " parsed successfully."); - // well-formedness checks - dash.resolveAllDash(rep); - //System.out.println(dash.toString()); + dash.resolveAllAlloy(rep); } - } catch (Exception e) { - e.printStackTrace(System.err); - System.err.println(e); - System.exit(1); } - return dash; } public static String dumpString(DashModule dash) { - String s = null; - try { - if (dash != null) { - s = dash.toString(); - } - } catch (Exception e) { - System.err.println(e); - } + String s = null; + + if (dash != null) { + s = dash.toString(); + } + return s; } public static DashModule translate(DashModule dash, A4Reporter rep) { - try { - DashOptions.isTraces = true; - if (dash != null) { - // translates in place - dash.translate(); - } - // Alloy wff check - dash.resolveAllAlloy(rep == null ? A4Reporter.NOP : rep); - System.out.println(dash.toString()); - } catch (Exception e) { - e.printStackTrace(System.err); - System.err.println(e); - System.exit(1); + + DashOptions.isTraces = true; + if (dash != null) { + // translates in place + dash.translate(); } + // Alloy wff check + dash.resolveAllAlloy(rep == null ? A4Reporter.NOP : rep); + //System.out.println(dash.toString()); + return dash; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 133652696..add4d6160 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -256,17 +256,22 @@ public String addPredSimple(String name, List decls, List eList) { StringJoiner j = new StringJoiner(", "); decls.forEach(i -> j.add(i.toString())); s += j.toString() + "] {\n"; - // s += body.toString(); - // as long as createAnd is working correctly this is okay - // and better formatted + // we have to use our own printer + // rather than expr.toString() + // because that fcn does not include brackets + // appropriately to get the correct associativity for joins + // + // later we could do something nicer for pred calls + // but remember the predicate call to testIfNextStable is nested + // inside an ITE s += tab; - StringJoiner sj = new StringJoiner("\n" + tab); - ExprToString eToString = new ExprToString(false); + StringJoiner sj = new StringJoiner("\n" + tab); for (Expr e: eList) { + ExprToString eToString = new ExprToString(false); sj.add(eToString.toString(e)); } s += sj.toString() + "\n"; - s+= "}\n"; + s+= "}\n\n"; return s; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 8abfb595f..d117ad75e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -13,17 +13,20 @@ import edu.mit.csail.sdg.alloy4.Pair; import edu.mit.csail.sdg.alloy4.A4Reporter; import edu.mit.csail.sdg.parser.CompModule; - +import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.*; import ca.uwaterloo.watform.ast.*; +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; import ca.uwaterloo.watform.parser.CompModuleHelper; import ca.uwaterloo.watform.dashtoalloy.DashToAlloy; public class DashModule extends CompModuleHelper { - private DashState root = null; + // let it be a list so we can have a good error message in wff checks (resolveAllDash) + private List roots = new ArrayList(); + private DashState root = null; // normally first element of roots // after parsing, these allow us to echo the Alloy-only parts // of the file when printing @@ -33,6 +36,8 @@ public class DashModule extends CompModuleHelper { // derived during resolveAllDash phase private int numBuffers = 0; + private int maxDepthParams = 0; + private boolean[] transAtThisParamDepth; private SymbolTable symbolTable; private StateTable stateTable = new StateTable(); private TransTable transTable = new TransTable(); @@ -71,7 +76,10 @@ public DashModule(CompModule world, String filename, String path) { // this function is just for compatibility with copied CompUtil -> DashUtil // super must be first statement in constructor super(world,filename,path); - assert(world == null && path == null); + // this is violated so something in Alloy parsing must call this within a world + // assert(world == null && path == null); + // as long as super is doing copying from incoming world to current world + // this should be fine initializeDashModule(); } private void initializeDashModule() { @@ -197,12 +205,17 @@ else if (DashOptions.isTraces) opens += this.addOpenSimple(DashStrings.utilBufferName, Arrays.asList(DashStrings.bufferIndexName+i, bufElements.get(i)), bufNames.get(i)); } - // constructors/accessor functions ------------------ + // constructors - public void setRoot(DashState r) { - assert(r == null); - root = r; + public void addRoot(DashState r) { + roots.add(r); + } + public void setParsed() { + assert(status == Status.CREATED); + status = Status.PARSED; } + + // general query public boolean hasRoot() { return (root != null); } @@ -213,17 +226,6 @@ public String getRootName() { public int getNumBuffers() { return numBuffers; } - - public boolean isBasicState(String s) { - return (stateTable.isBasicState(s)); - } - - public List getImmChildren(String parent) { - return stateTable.getImmChildren(parent); - } - public Set getTransNames() { - return transTable.getTransNames(); - } public boolean hasInternalEvents() { return false; // (eventTable.hasInternalEvents()); } @@ -238,20 +240,134 @@ public boolean hasConcurrency() { } public int getMaxDepthParams() { // could precalculate this - return stateTable.getMaxDepthParams(); + return maxDepthParams; + } + public List getAllParams() { + return stateTable.getAllParams(); + } + + //stuff about states (some of these are to expose the stateTable for testing) + public boolean isLeaf(String s) { + return (stateTable.isLeaf(s)); + } + public boolean isAnd(String s) { + return stateTable.isAnd(s); + } + public boolean isRoot(String s) { + return stateTable.isRoot(s); + } + public List getImmChildren(String parent) { + return stateTable.getImmChildren(parent); + } + public List getLeafStatesExited(DashRef s) { + return stateTable.getLeafStatesExited(s); + } + public List getLeafStatesEntered(DashRef s) { + return stateTable.getLeafStatesEntered(s); + } + public List getLeafStatesEnteredWithContext(DashRef context, DashRef s) { + return stateTable.getLeafStatesEnteredWithContext(context, s); + } + public List getAllAnces(String sfqn) { + return stateTable.getAllAnces(sfqn); + } + public String getClosestConcAnces(String sfqn) { + return stateTable.getClosestConcAnces(sfqn); + } + public List getAllNonConcDesc(String sfqn) { + return stateTable.getAllNonConcDesc(sfqn); + } + public List getRegion(String sfqn) { + return stateTable.getRegion(sfqn); + } + + // stuff about transitions + public Set getTransNames() { + return transTable.getTransNames(); + } + public DashRef getTransSrc(String tfqn) { + return transTable.getSrc(tfqn); + } + public DashRef getTransDest(String tfqn) { + return transTable.getDest(tfqn); + } + public List getHigherPriTrans(String tfqn) { + return transTable.getHigherPriTrans(tfqn); + } + + public Boolean transAtThisParamDepth(int i) { + if (i > maxDepthParams) { DashErrors.tooHighParamDepth(); return null; } + else + return transAtThisParamDepth[i]; } public List getTransParams(String t) { return transTable.getParams(t); } - public List getAllParams() { - return stateTable.getAllParams(); + + // stuff about both states and trans + public DashRef getScope(String tfqn) { + DashRef src = getTransSrc(tfqn); + DashRef dest = getTransDest(tfqn); + String sc = DashFQN.longestCommonFQN(src.getName(),dest.getName()); + // maxCommonParams is max number of params that could have in common + // but they don't necessarily have the same values + Integer maxCommonParams = stateTable.getParams(sc).size(); + List scopeParams = new ArrayList(); + Expr equals = null; + Expr s = null; + Expr d = null; + for (int i=0;i exited(String tfqn) { + DashRef scope = getScope(tfqn); + return stateTable.getLeafStatesExited(scope); + } + // processes --------------------------------------- + // should we use the rep arg here? public void resolveAllDash(A4Reporter rep) { - assert(status == Status.PARSED); + System.out.println("Resolving Dash"); - if (root != null ) { + if (roots.isEmpty()) { + DashErrors.noStates(); + } else if (roots.size() > 1) { + DashErrors.onlyOneState(roots.get(1).getPos()); + } else { + root = roots.get(0); // passed with empty set of params, empty set of ancestors stateTable.setRoot(root.name); root.resolveAllStates(stateTable,new ArrayList(),new ArrayList()); @@ -260,10 +376,21 @@ public void resolveAllDash(A4Reporter rep) { root.resolveAllTrans(stateTable,transTable); System.out.println(stateTable.toString()); System.out.println(transTable.toString()); + for (String tfqn: getTransNames()) { + System.out.println(tfqn +" scope :" + getScope(tfqn)); + } + //System.out.println("getClosestConcAnces: "+getClosestConcAnces("Root/S1/S2")); + //System.out.println("getAllNonConcDesc: " +getAllNonConcDesc("Root")); + //System.out.println("getRegion of "+"Root/S1/S2: "+getRegion("Root/S1/S2")); + //System.out.println("exited" + getLeafStatesExitedTrans("Root/S1/t1")); + //System.out.println("entered" + getLeafStatesEntered(getTransDest("Root/S1/t1"))); // if root has no substates? // if no transitions? stateTable.resolveAll(getRootName()); transTable.resolveAll(); + maxDepthParams = stateTable.getMaxDepthParams(); + //transAtThisParamDepth = new boolean[maxDepthParams+1]; + transAtThisParamDepth = transTable.transAtThisParamDepth(maxDepthParams); } status = Status.RESOLVED_DASH; } @@ -286,7 +413,7 @@ public void resolveAllAlloy(A4Reporter rep) { // returns it as the output // so here we cast DashModule to CompModule and ignore the // output CompModule - assert(status == Status.TRANSLATED_TO_ALLOY); + //assert(status == Status.TRANSLATED_TO_ALLOY); System.out.println("Resolving Alloy"); // this quits if it throws an error //resolveAll(rep == null ? A4Reporter.NOP : rep, this); @@ -294,32 +421,14 @@ public void resolveAllAlloy(A4Reporter rep) { status = Status.RESOLVED_ALLOY; } - - // helper functions for creating parts of module - /* - public static createDecl(ExprVar v, Expr e) { - return new Decl(null, null, null, null, v, mult(e)); + // for testing + public List getDefaults(String s) { + return stateTable.getDefaults(s); } - public static createOneDecl(String v, String typ) { - return createDecl(createVar(v), createOne(createVar(typ)); - } - public static createSetDecl(String v, String typ) { - return createDecl(createVar(v), createSet(createVar(typ)); - } - */ - - - - /* - private List params; - private StateTable stateTable; - private TransTable transTable; - private SymbolTable symbolTable; - private EventTable eventTable; - public boolean hasConcurrency; + /* leftover public String getRoot() { return root.name(); // as root it is already FQN } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index a206db660..17fd14505 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -14,8 +14,17 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Collections; +import java.util.stream.Collectors; + +import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.*; +import static ca.uwaterloo.watform.core.DashUtilFcns.*; +import static ca.uwaterloo.watform.core.DashStrings.*; +import static ca.uwaterloo.watform.core.DashFQN.*; +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; + +import ca.uwaterloo.watform.ast.DashRef; public class StateTable { private HashMap table; @@ -28,51 +37,54 @@ public class StateTable { public class StateElement { // better than a tuple private DashStrings.StateKind kind; // must exist AND/OR - private List params; // null if none - private String def; // null if none + private String param; // may be empty + private List params; // null if none; param is last of params if it exists + private DashStrings.DefKind def; // these all use fullQual names to point to trans in TransTable // or states in this StateTable private String parent; // null if none // this could be a set b/c there are no dups and order // doesn't matter, but lists are easier to work with private List immChildren; // empty if none + /* private ArrayList transWithThisSrc; private ArrayList transWithThisScope; // all trans with this scope or descendant scope private ArrayList allTransWithinState; private ArrayList basicStatesEntered; // following defaults private ArrayList basicStatesExited; - + */ public StateElement( DashStrings.StateKind k, + String prm, List prms, - String d, + DashStrings.DefKind d, String p, List iChildren) { + assert(k != null); - assert(prms == null || !prms.isEmpty()); - assert(def == null || !def.isEmpty()); - assert(parent == null || !parent.isEmpty()); - assert(immChildren != null); // could be empty + assert(prm == null || !prm.isEmpty()); + assert(prms != null); + assert(p == null || !p.isEmpty()); + assert(iChildren != null); // could be empty + this.kind = k; + this.param = prm; this.params = prms; this.def = d; this.parent = p; this.immChildren = iChildren; - this.transWithThisSrc = null; - this.transWithThisScope = null; - this.allTransWithinState = null; - this.basicStatesEntered = null; - this.basicStatesExited = null; + } public String toString() { String s = new String(); s += "kind: "+kind +"\n"; - s += "params: "+params +"\n"; + s += "param:"+ NoneStringIfNeeded(param)+"\n"; + s += "params: "+ NoneStringIfNeeded(params) +"\n"; s += "default: "+def+"\n"; - s += "parent: "+parent +"\n"; - s += "immChildren: "+immChildren +"\n"; + s += "parent: "+ NoneStringIfNeeded(parent) +"\n"; + s += "immChildren: "+NoneStringIfNeeded(immChildren) +"\n"; // add more return s; } @@ -102,20 +114,19 @@ public String toString() { } } */ + /* public Boolean allAttributesEmpty() { - return (kind == null || - params == null || - def == null || - parent == null || - immChildren == null || - transWithThisSrc == null || - transWithThisScope == null || - allTransWithinState == null || - basicStatesEntered == null || - basicStatesExited == null); + return (kind == null && + param == null && + params == null && + def == null && + parent == null && + immChildren.isEmpty() ) ; } - public Boolean attributesSame(DashStrings.StateKind k,List prms, String d, String p, List iChildren) { + */ + public Boolean attributesSame(DashStrings.StateKind k, String prm, List prms, DashStrings.DefKind d, String p, List iChildren) { return (kind == k && + param.equals(prm) && params.equals(prms) && def.equals(d) && parent.equals(p) && @@ -134,6 +145,9 @@ public void setRoot(String s) { public String getRoot() { return root; } + public boolean isRoot(String s) { + return (s.equals(getRoot())); + } public String toString() { String s = new String("STATE TABLE\n"); for (String k:table.keySet()) { @@ -150,38 +164,66 @@ public void add(String fqn) { assert(!fqn.isEmpty()); if (!table.containsKey(fqn)) table.put(fqn,null); - // System.out.println("adding State table: "+fqn); + System.out.println("adding State table: "+fqn); } public void add( String fqn, DashStrings.StateKind k, + String prm, List prms, - String d, + DashStrings.DefKind d, String p, List iChildren) { // if its null, make it empty to not throw exceptions if (iChildren == null) iChildren = new ArrayList(); if (table.containsKey(fqn)) { StateElement se = table.get(fqn); - if (se.allAttributesEmpty()) - table.replace(fqn, new StateElement(k,prms,d, p,iChildren)); - else if (!se.attributesSame(k,prms,d,p,iChildren)) + if (se == null) + table.replace(fqn, new StateElement(k,prm, prms,d, p,iChildren)); + else if (!se.attributesSame(k,prm,prms,d,p,iChildren)) // hopefully not possible DashErrors.addStateToStateTableDup(fqn); } else - table.put(fqn, new StateElement(k,prms,d,p,iChildren)); - System.out.println("adding to State table: "+fqn+space+prms+space+d+space+p+iChildren); + table.put(fqn, new StateElement(k,prm, prms,d,p,iChildren)); + System.out.println("adding to State table: "+fqn+space+prm + space + prms+space+d+space+p+iChildren); } - public boolean containsKey(String q) { - return table.containsKey(q); + public boolean containsKey(String s) { + return table.containsKey(s); + } + public boolean setAsDefault(String s) { + if (table.containsKey(s)) { + table.get(s).def = DashStrings.DefKind.DEFAULT; + return true; + } + else { DashErrors.stateDoesNotExist("setDefault", s); return false; } } - public boolean isBasicState(String q) { - if (table.containsKey(q)) - // shouldn't really need the check for OR here - return (table.get(q).kind == DashStrings.StateKind.OR && table.get(q).immChildren == null); - else { DashErrors.isBasicNotExist(q); return false; } + public boolean isLeaf(String s) { + if (table.containsKey(s)) + return (table.get(s).immChildren.isEmpty()); + else { DashErrors.stateDoesNotExist("isLeaf", s); return false; } + } + public boolean isOr(String s) { + if (table.containsKey(s)) + return (table.get(s).kind == StateKind.OR); + else { DashErrors.stateDoesNotExist("isOr", s); return false; } + } + public boolean isAnd(String s) { + if (table.containsKey(s)) + return (table.get(s).kind == StateKind.AND); + else { DashErrors.stateDoesNotExist("isAnd",s); return false; } + } + public boolean isDefault(String s) { + if (table.containsKey(s)) + return (table.get(s).def == DefKind.DEFAULT); + else { DashErrors.stateDoesNotExist("isDefault",s); return false; } + } + + public String getParam(String s) { + if (table.containsKey(s)) + return table.get(s).param; + else { DashErrors.stateDoesNotExist("getParam", s); return null; } } public List getParams(String s) { if (table.containsKey(s)) @@ -212,63 +254,66 @@ public List getAllAnces(String fqn) { // do not need to walk over tree for this operation; can just use FQNs List fqnSplit = DashFQN.splitFQN(fqn); List x = new ArrayList(); - // don't want to include the state itself - if (fqnSplit.size()-1 > 0) for (int i=0; i < fqnSplit.size()-1; i++) x.add(DashFQN.fqn(fqnSplit.subList(0,i+1))); + // include the state itself (could be Root) + if (fqnSplit.size() > 0) for (int i=0; i < fqnSplit.size(); i++) x.add(DashFQN.fqn(fqnSplit.subList(0,i+1))); // list is in order from root, ...., fqn-1 on path + //System.out.println("getAllAnces of "+fqn+" is "+x); + // contains at least Root state return x; } public String getClosestConcAnces(String s) { - // getAllAnces returns list from Root, ..., parentFQN-1 on path + // getAllAnces returns list from Root, ..., parentFQN on path // could also just walk back through parents List allAnces = getAllAnces(s); - allAnces.add(s); + //allAnces.add(s); Collections.reverse(allAnces); String concAnces = null; // allAnces cannot be empty b/c must have Root in it for (String a:allAnces) { - if (getKind(a) == DashStrings.StateKind.AND) { + if (isAnd(a) || isRoot(a)) { concAnces = a; break; } } + //System.out.println("getClosestConcAnces: "+concAnces); return concAnces; // might be null } + /* public List getAllNonConcStatesWithinThisState(String concAnces) { if (concAnces!=null) return getAllNonConcDesc(concAnces); - else + else { // went back to root - return getAllNonConcDesc(root); + List x = getAllNonConcDesc(root); + //System.out.println("getAllNonConcStatesWithinThisState: "+x); + return x; + } } - + */ public List getAllNonConcDesc(String s) { - // get all the descendants not in concurrent states - // s is not included - System.out.println("getAllNonConcDesc "+s); + // get all the descendants not WITHIN concurrent states + // s is included + // have to be careful to avoid duplicates + // System.out.println("getAllNonConcDesc "+s); List desc = new ArrayList(); + desc.add(s); // could be Root or a conc state + //System.out.println("in getAllNonConcDesc: "+desc); if (table.containsKey(s)) { - if (!table.get(s).immChildren.isEmpty()) { - System.out.println("HERE " + table.get(s).immChildren); - if (table.get(table.get(s).immChildren.get(0)).kind != DashStrings.StateKind.AND) { - for (String c: table.get(s).immChildren) { - desc.addAll(getAllNonConcDesc(c)); - desc.add(c); - } - return desc; - } else return desc; // empty list - } else return desc; // empty list - } - else { DashErrors.stateDoesNotExist("getAllNonConcDesc", s); return null; } - } - public DashStrings.StateKind getKind(String s) { - if (table.containsKey(s)) - return table.get(s).kind; - else { DashErrors.stateDoesNotExist("getKind", s); return null; } + for (String c: table.get(s).immChildren) { + //System.out.println("in getAllNonConcDesc: "+c); + if (isOr(c)) desc.addAll(getAllNonConcDesc(c)); + } + return desc; + } else { DashErrors.stateDoesNotExist("getAllNonConcDesc", s); return null; } + } + public List getRegion(String sfqn) { + return getAllNonConcDesc(getClosestConcAnces(sfqn)); } public int getMaxDepthParams() { return getMaxDepthParams(root); } public int getMaxDepthParams(String s) { + // TODO: check this - seems to be not getting to full depth int max = 0; for (String c: getImmChildren(s)) { if (getParams(c) != null) @@ -292,27 +337,85 @@ public void resolveAll(String root) { // walk down parent to children and pass back info isResolved = true; } - /* - public void addEnterExit(String s, ArrayList enter, ArrayList exit) { - if (s in table.keys()) { - table.get(s).basicStatesEntered = enter; - table.get(s).basicStatesExited = exit; + + + public List getLeafStatesExited(DashRef s) { + List r = new ArrayList(); + System.out.println("exiting" + s.toString()); + if (isLeaf(s.getName())) { + r.add(s); + return r; } else { - // error + // exit everything below even if not currently in it + for (String ch:getImmChildren(s.getName())) { + // exit all copies of the params + List newParamValues = new ArrayList(s.getParamValues()); + newParamValues.add(ExprHelper.createVar(getParam(ch))); + r.addAll(getLeafStatesExited(new DashRef(ch, newParamValues))); + } + return r; } } - public ArrayList getParams(String s) { - assert(isResolved == true); - return table.get(s).params; + public List getDefaults(String s) { + if (!table.containsKey(s)) + { DashErrors.stateDoesNotExist("getDefaults",s); return null; } + // else if (isLeaf(s)) return null; + else { + assert(!isLeaf(s) || getImmChildren(s).isEmpty()); + return getImmChildren(s).stream() + .filter(c -> isDefault(c)) + .collect(Collectors.toList()); + } } - public ArrayList getBasicStatesEntered(String s) { - assert(isResolved == true); - return table.get(s).basicStatesEntered; + public List getLeafStatesEntered(DashRef s) { + List r = new ArrayList(); + if (isLeaf(s.getName())) + r.add(s); + else { + // enter every default below + // if enter one c/p state enter all + // might be one (if o) or many (if c/p) + List defaults = getDefaults(s.getName()); + assert(defaults != null); + for (String ch:defaults) { + // enter all copies of the param if a parameterized state + List newParamValues = new ArrayList(s.getParamValues()); + newParamValues.add(ExprHelper.createVar(getParam(ch))); + r.addAll(getLeafStatesEntered(new DashRef(ch, newParamValues))); + } + } + return r; } - public ArrayList getBasicStatesExited(String s) { - assert(isResolved == true); - return table.get(s).basicStatesExited; + /* + Assumption: context is an ancestor of dest + */ + public List getLeafStatesEnteredWithContext(DashRef context, DashRef dest) { + List r = new ArrayList(); + if (context.getName().equals(dest.getName())) + r.addAll(getLeafStatesEntered(dest)); + else { + // context must have children + List children = getImmChildren(context.getName()); + String chOfContext = DashFQN.getChildOfContextAncesOfDest(context.getName(),dest.getName()); + r.addAll(getLeafStatesEnteredWithContext(new DashRef(chOfContext,context.getParamValues()), dest)); + if (!isOr(chOfContext)) { + // enter all sibling c/p's + // treating c/p's the same + List andChildren = children.stream() + .filter(c -> isAnd(c)) + .collect(Collectors.toList()); + andChildren.remove(chOfContext); + for (String ch:children) { + List newParamValues = new ArrayList(); + // if a c, won't be any additional params + newParamValues.addAll(dest.getParamValues().subList(0, getParams(ch).size()-1)); + r.addAll(getLeafStatesEntered(new DashRef(ch, newParamValues))); + } + } + } + return r; } + /* seems like this goes in DashToAlloy public Expr createStateArrow(String s) { Expr e = createVar(s); for (i:s.params.reverse()) { @@ -320,7 +423,6 @@ public Expr createStateArrow(String s) { } return e; } - */ } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 97bf805ca..7cea72628 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -16,6 +16,8 @@ import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.*; +import static ca.uwaterloo.watform.core.DashUtilFcns.*; +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; import ca.uwaterloo.watform.ast.*; public class TransTable { @@ -25,8 +27,8 @@ public class TransTable { public class TransElement { public List params; // null if no params - public String src; // FQN - public String dest; // FQN + public DashRef src; + public DashRef dest; public Expr when; // just one? public Expr on; public List action; @@ -43,8 +45,8 @@ public class TransElement { */ public TransElement( List prms, - String s, // fqn - String d // fqn + DashRef s, + DashRef d ) /* DashEvent w, @@ -72,9 +74,9 @@ public TransElement( } public String toString() { String s = new String(); - s += "params: "+params +"\n"; - s += "src: "+src +"\n"; - s += "dest: "+dest +"\n"; + s += "params: " + params +"\n"; + s += "src: " + src.toString() + "\n"; + s += "dest: " + dest.toString() + "\n"; // add more return s; } @@ -87,8 +89,8 @@ public TransTable() { public void add( String fqn, List params, - String s, - String d) + DashRef s, + DashRef d) /* DashEvent w, DashExpr o, @@ -98,9 +100,9 @@ public void add( { System.out.println("Adding "+fqn); assert(!fqn.isEmpty()); - assert(params == null | !params.isEmpty()); - assert(!s.isEmpty()); - assert(!d.isEmpty()); + assert(params != null ); + assert(s != null); + assert(d != null); if (table.containsKey(fqn)) DashErrors.transTableDup(fqn); else table.put(fqn, new TransElement(params,s,d)); } @@ -121,11 +123,69 @@ public List getParams(String t) { if (table.containsKey(t)) return table.get(t).params; else { DashErrors.transDoesNotExist("getParams", t); return null; } } + public DashRef getSrc(String t) { + if (table.containsKey(t)) return table.get(t).src; + else { DashErrors.transDoesNotExist("getSrc", t); return null; } + } + public DashRef getDest(String t) { + if (table.containsKey(t)) return table.get(t).dest; + else { DashErrors.transDoesNotExist("getDest", t); return null; } + } + // might be better to make this getTransWithThisSrc + // but this is more efficient if it is only used for higherPriTrans + public List getTransWithTheseSrcs(List slist) { + List tlist = new ArrayList(); + for (String k:table.keySet()) { + if (slist.contains(table.get(k).src.getName())) tlist.add(k); + } + return tlist; + } + public List getHigherPriTrans(String t) { + // list returned could be empty + List tlist = new ArrayList(); + // have to look for transitions from sources earlier on the path of this transitions src + if (table.containsKey(t)) { tlist.addAll(getTransWithTheseSrcs(DashFQN.allPrefixes(table.get(t).src.getName()))); } + else { DashErrors.transDoesNotExist("getParams", t); } + return tlist; + } + + + + /* + public List getNotOrthogonalTransAbove(String t) { + List notOrthogonal = new ArrayList(); + String tScope = getScope(table.get(t).src, table.get(t).dest); + // get scope of this trans + for (to: table.getKeys()) { + if (!t.equals(to)) { + String toScope = getScope(table.get(to).src, table.get(to).dest); + if (!isBelow(toScope, tScope)) { + // will be caught by !takeni's below this trans + ; + } else if (isBelow(tScope, toScope)) { + notOrthogonal.add(to); + } else { + + } + + } + } + get scope of to + get lca of + } + */ public void resolveAll() { System.out.println("Resolving trans table"); if (getTransNames().isEmpty()) DashErrors.noTrans(); - // check all source and dest exist in state table isResolved = true; } + public boolean[] transAtThisParamDepth(int max) { + boolean[] depthsInUse = new boolean[max+1]; // 0..max + for (int i=0; i <= max; i++) depthsInUse[i] = false; + for (String k:table.keySet()) + if (table.get(k).params == null) depthsInUse[0] = true; + else depthsInUse[table.get(k).params.size()] = true; + return depthsInUse; + } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh index 7a83547fe..903238718 100755 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/install-alloy-files.sh @@ -42,6 +42,7 @@ sed -i -e 's/CompModule /DashModule /g' CompUtil.java # one place CompModule is used other than in types sed -it -e 's/return new CompModule(null, "", "");/return new DashModule(null, "", "");/' CompUtil.java + sed -i -e 's/CompUtil/DashUtil/g' CompUtil.java sed -i -e 's/CompParser/DashParser/g' CompUtil.java diff --git a/org.alloytools.alloy.dist/bnd.bnd b/org.alloytools.alloy.dist/bnd.bnd index 3e2419198..7886f63e7 100644 --- a/org.alloytools.alloy.dist/bnd.bnd +++ b/org.alloytools.alloy.dist/bnd.bnd @@ -35,6 +35,7 @@ JPM-Command: alloy @${repo;com.google.gson}, \ @${repo;org.eclipse.equinox.common}, \ @${repo;org.apache.commons.io}, \ + @${repo;com.io7m.jpplib.io7m-jpplib-core}, \ LICENSES -dependson: * From a32e9680ba7958d0d36af7050d1756ca615879bc Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 14 Apr 2023 09:46:25 -0400 Subject: [PATCH 027/129] working on entered/exited --- .../watform/dash4whole/DashMainTest.java | 17 + .../watform/alloyasthelper/ExprHelper.java | 11 +- .../ca/uwaterloo/watform/ast/DashRef.java | 2 + .../ca/uwaterloo/watform/ast/DashState.java | 10 +- .../ca/uwaterloo/watform/core/DashErrors.java | 12 +- .../ca/uwaterloo/watform/core/DashFQN.java | 18 +- .../uwaterloo/watform/core/DashUtilFcns.java | 7 +- .../watform/dashtoalloy/DashToAlloy.java | 4 +- .../uwaterloo/watform/parser/DashModule.java | 42 ++- .../uwaterloo/watform/parser/StateTable.java | 110 ++++-- .../uwaterloo/watform/parser/TransTable.java | 7 +- .../alloy/dash/DashCoreFQNTests.java | 63 +++- .../alloytools/alloy/dash/DashStateTests.java | 354 +++++++++++++++++- .../src/test/resources/pass/getEntered10.dsh | 24 ++ .../src/test/resources/pass/getEntered11.dsh | 16 + .../src/test/resources/pass/getEntered5.dsh | 10 + .../src/test/resources/pass/getEntered6.dsh | 13 + .../src/test/resources/pass/getEntered7.dsh | 13 + .../src/test/resources/pass/getEntered8.dsh | 16 + .../src/test/resources/pass/getEntered9.dsh | 18 + .../resources/pass/getEnteredInContext2.dsh | 13 + .../resources/pass/getEnteredInContext3.dsh | 14 + .../src/test/resources/pass/overall1.dsh | 12 + .../src/test/resources/pass/overall2.dsh | 12 + .../src/test/resources/pass/overall3.dsh | 14 + .../src/test/resources/pass/overall4.dsh | 12 + 26 files changed, 787 insertions(+), 57 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEntered10.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEntered11.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEntered5.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEntered6.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEntered7.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEntered8.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEntered9.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext3.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall4.dsh diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java index b53a68fca..0d7a0d8f6 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java @@ -24,6 +24,7 @@ import edu.mit.csail.sdg.translator.TranslateAlloyToKodkod; import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashFQN; import ca.uwaterloo.watform.parser.DashUtil; import ca.uwaterloo.watform.parser.DashModule; import ca.uwaterloo.watform.mainfunctions.MainFunctions; @@ -40,9 +41,25 @@ public static void main(String args[]) { System.out.println("Starting DashMainTest"); A4Reporter rep = new A4Reporter(); + if(args.length != 0) { + // first arg is filename + String fname = args[0]; + DashModule d = + MainFunctions.parseAndResolveDashFile(fname,rep); + if (args.length == 2) { + // transition name + d.debug(args[1]); + } + } + /* DashModule d = MainFunctions.parseAndResolveDashFile( "/Users/nday/UW/github/org.alloytools.alloy/org.alloytools.alloy.dash/src/test/resources/wfffail/noTrans1.dsh",rep); + */ + //List p = DashFQN.allPrefixes("A/B/C"); + //List k = (new String[]{"A", "A/B", "A/B/C"} ; + //System.out.println("all prefixes: " + p); + //assert(p.equals()); System.out.println("Finish DashMainTest"); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 073704dce..05474fde0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -101,12 +101,12 @@ public static Expr createJoinList(List elist) { } return ret; } - public static Expr createPlusList(List elist) { + public static Expr createUnionList(List elist) { Expr ret = null; assert(elist!=null); ret = elist.get(0); for (Expr el: elist.subList(1,elist.size())) { - ret = createPlus(ret,el); + ret = createUnion(ret,el); } return ret; } @@ -132,9 +132,14 @@ public static ExprList createOr(List args) { public static ExprBinary createArrow(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.ARROW.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static ExprBinary createPlus(Expr left,Expr right) { + // set union + public static ExprBinary createUnion(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.PLUS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } + // set diff + public static ExprBinary createDiff(Expr left,Expr right) { + return (ExprBinary) ExprBinary.Op.MINUS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } public static ExprBinary createIn(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.IN.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java index 634ee50a9..03442476e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java @@ -25,6 +25,8 @@ public DashRef(String n, List eList) { this.pos = Pos.UNKNOWN; this.name = n; this.paramValues = eList; + //System.out.println(n); + //System.out.println(eList); } public String getName() { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index b5f1c1e93..ce6e33d7c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -40,7 +40,8 @@ public DashState(Pos p, String n, String prm, DashStrings.StateKind k, DashStrin this.kind = k; this.def = d; this.items = i; - //System.out.println("here1 creating "+this.name+" "+ this.kind); + //System.out.println("here1 creating "+this.name); + //System.out.println("here1 " + (this.param == null)); } /* @@ -179,7 +180,7 @@ public void resolveAllStates(StateTable st, List params, List an .filter(i -> (i.kind == DashStrings.StateKind.AND)) .collect(Collectors.toList()); if (andList.equals(substatesList) && defaultsList.size() == 0) { - // all AND-states and non designated as defaults so all are defaults + // all AND-states are not designated as defaults so all are defaults for (String ch: childFQNs) st.setAsDefault(ch); } else if (defaultsList.size() == 0) DashErrors.noDefaultState(sfqn); @@ -191,8 +192,9 @@ public void resolveAllStates(StateTable st, List params, List an // o/w one OR state is default } else { // if defaults list is all c's, all c children should be included - - if (defaultsList != andList) DashErrors.allAndDefaults(sfqn); + //System.out.println("defaultsList: "+defaultsList); + //System.out.println("andList: "+andList); + if (!(defaultsList.equals(andList))) DashErrors.allAndDefaults(sfqn); } } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 552c17cc0..405db2508 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -95,6 +95,13 @@ public static void andCrossTransition(String tfqn) throws Err { // parts of the code that should be unreachable ------------- + public static String ancesNotPrefixMsg = " must be a prefix of "; + public static void ancesNotPrefix(String a, String d) throws Err { + throw new ErrorFatal(a + ancesNotPrefixMsg + d); + } + + + // not tested below this line public static void toAlloyNoDash() throws Err { throw new ErrorFatal("Translating to Alloy when no Dash part"); } @@ -122,7 +129,8 @@ public static void missingExpr(String s) throws Err { public static void tooHighParamDepth() throws Err { throw new ErrorFatal("paramsDepthInUse called with too high a number"); } - public static void ancesNotPrefix(String a, String d) throws Err { - throw new ErrorFatal(a + " must be prefix of " + d); + public static String paramNumberProblemMsg = "wrong number of param values: "; + public static void paramNumberProblem(String s) throws Err { + throw new ErrorFatal(paramNumberProblemMsg + s); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java index a45aea5eb..3d5dd415f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java @@ -77,11 +77,11 @@ public static String longestCommonFQN(String a, String b) { while (i < minLength && aSplit.get(i).equals(bSplit.get(i))) i++; return fqn(aSplit.subList(0,i)); } + // include this fqn public static List allPrefixes(String fqn) { List prefixes = new ArrayList(); - // not including state itself List splitfqn = splitFQN(fqn); - for (int i=0;i < splitfqn.size()-1; i++) { + for (int i=0;i < splitfqn.size(); i++) { StringJoiner sj = new StringJoiner(inputQualChar); for (int j=0;j<=i;j++) { sj.add(splitfqn.get(j)); @@ -92,9 +92,17 @@ public static List allPrefixes(String fqn) { } /* ances: A/B/C dest: A/B/C/D/E returns A/B/C/D */ public static String getChildOfContextAncesOfDest(String ances, String dest) { - if (dest.startsWith(ances)) - // by going to ances, we are adding +1 - return fqn(splitFQN(dest).subList(0,splitFQN(ances).size())); + /* + System.out.println(ances); + System.out.println(dest); + System.out.println(splitFQN(dest)); + System.out.println(splitFQN(dest).subList(0,splitFQN(ances).size())); + System.out.println(fqn(splitFQN(dest).subList(0,splitFQN(ances).size()))); + */ + if (dest.equals(ances)) return dest; + else if (dest.startsWith(ances)) + // dest must be longer than ances + return fqn(splitFQN(dest).subList(0,splitFQN(ances).size()+1)); else { DashErrors.ancesNotPrefix(ances,dest); return null; } } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java index 33fc09747..e0addd181 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java @@ -64,5 +64,10 @@ public static void handleException(Exception e) { e.printStackTrace(System.err); System.exit(1); } - + public static T lastElement(List ll) { + return ll.get(ll.size()-1); + } + public static List allButLast(List ll) { + return ll.subList(0,ll.size()-1); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 037ef5a2f..2b7eb9154 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -309,10 +309,10 @@ private void createTransSemantics(String t) { if (DashOptions.isElectrum) takens.add(createEquals( taken(i), - createPlus(taken(i),paramsToXArrow(prs,tfqn)))); + createUnion(taken(i),paramsToXArrow(prs,tfqn)))); else takens.add(createEquals( nextTaken(i), - createPlus(curTaken(i),paramsToXArrow(prs,tfqn)))); + createUnion(curTaken(i),paramsToXArrow(prs,tfqn)))); else if (DashOptions.isElectrum) takens.add(createEquals(taken(i), curTaken(i))); else takens.add(createEquals(nextTaken(i), curTaken(i))); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index d117ad75e..3453b65f3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -266,7 +266,7 @@ public List getLeafStatesEntered(DashRef s) { return stateTable.getLeafStatesEntered(s); } public List getLeafStatesEnteredWithContext(DashRef context, DashRef s) { - return stateTable.getLeafStatesEnteredWithContext(context, s); + return null; //stateTable.getLeafStatesEnteredWithContext(context, s); } public List getAllAnces(String sfqn) { return stateTable.getAllAnces(sfqn); @@ -355,9 +355,37 @@ public List exited(String tfqn) { DashRef scope = getScope(tfqn); return stateTable.getLeafStatesExited(scope); } + // for debugging + public List allPrefixDashRefs(DashRef x) { + return stateTable.allPrefixDashRefs(x); + } + public List entered(String tfqn) { + return stateTable.getLeafStatesEnteredInContext( + getScope(tfqn), + getTransDest(tfqn)); + } // processes --------------------------------------- + public void debug(String tfqn) { + System.out.println(stateTable.toString()); + System.out.println(transTable.toString()); + for (String x: getTransNames()) { + // System.out.println(tfqn +" scope :" + getScope(x)); + } + if (tfqn != null) { + System.out.println("src " + getTransSrc(tfqn)); + System.out.println("dest " + getTransDest(tfqn)); + System.out.println("getScope " + getScope(tfqn)); + System.out.println("getClosestConcAnces: "+getClosestConcAnces(getTransSrc(tfqn).getName())); + System.out.println("getAllNonConcDesc: " +getAllNonConcDesc(getClosestConcAnces(getTransSrc(tfqn).getName()))); + System.out.println("getRegion:"+"Root/S1/S2: "+getRegion(getTransSrc(tfqn).getName())); + System.out.println("exited: " + exited(tfqn)); + System.out.println("entered" + getLeafStatesEntered(getTransDest(tfqn))); + System.out.println("enteredInContext" + entered(tfqn)); + System.out.println("allPrefixDashRefs of scope: "+ allPrefixDashRefs(getScope(tfqn))); + } + } // should we use the rep arg here? public void resolveAllDash(A4Reporter rep) { @@ -374,16 +402,6 @@ public void resolveAllDash(A4Reporter rep) { // have to do states first so siblings of trans parent state // are in place to search for src/dest root.resolveAllTrans(stateTable,transTable); - System.out.println(stateTable.toString()); - System.out.println(transTable.toString()); - for (String tfqn: getTransNames()) { - System.out.println(tfqn +" scope :" + getScope(tfqn)); - } - //System.out.println("getClosestConcAnces: "+getClosestConcAnces("Root/S1/S2")); - //System.out.println("getAllNonConcDesc: " +getAllNonConcDesc("Root")); - //System.out.println("getRegion of "+"Root/S1/S2: "+getRegion("Root/S1/S2")); - //System.out.println("exited" + getLeafStatesExitedTrans("Root/S1/t1")); - //System.out.println("entered" + getLeafStatesEntered(getTransDest("Root/S1/t1"))); // if root has no substates? // if no transitions? stateTable.resolveAll(getRootName()); @@ -391,6 +409,8 @@ public void resolveAllDash(A4Reporter rep) { maxDepthParams = stateTable.getMaxDepthParams(); //transAtThisParamDepth = new boolean[maxDepthParams+1]; transAtThisParamDepth = transTable.transAtThisParamDepth(maxDepthParams); + // + //debug("Root/S1/t1"); } status = Status.RESOLVED_DASH; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 17fd14505..518c20774 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -225,6 +225,12 @@ public String getParam(String s) { return table.get(s).param; else { DashErrors.stateDoesNotExist("getParam", s); return null; } } + + public boolean hasParam(String s) { + if (table.containsKey(s)) + return table.get(s).param != null; + else { DashErrors.stateDoesNotExist("hasParam", s); return false; } + } public List getParams(String s) { if (table.containsKey(s)) return table.get(s).params; @@ -306,6 +312,7 @@ public List getAllNonConcDesc(String s) { return desc; } else { DashErrors.stateDoesNotExist("getAllNonConcDesc", s); return null; } } + // region is the area within which the src name does not need to be FQN public List getRegion(String sfqn) { return getAllNonConcDesc(getClosestConcAnces(sfqn)); } @@ -341,7 +348,7 @@ public void resolveAll(String root) { public List getLeafStatesExited(DashRef s) { List r = new ArrayList(); - System.out.println("exiting" + s.toString()); + //System.out.println("exiting" + s.toString()); if (isLeaf(s.getName())) { r.add(s); return r; @@ -350,7 +357,7 @@ public List getLeafStatesExited(DashRef s) { for (String ch:getImmChildren(s.getName())) { // exit all copies of the params List newParamValues = new ArrayList(s.getParamValues()); - newParamValues.add(ExprHelper.createVar(getParam(ch))); + if (hasParam(ch)) newParamValues.add(ExprHelper.createVar(getParam(ch))); r.addAll(getLeafStatesExited(new DashRef(ch, newParamValues))); } return r; @@ -378,43 +385,104 @@ public List getLeafStatesEntered(DashRef s) { List defaults = getDefaults(s.getName()); assert(defaults != null); for (String ch:defaults) { + //System.out.println(ch); // enter all copies of the param if a parameterized state List newParamValues = new ArrayList(s.getParamValues()); - newParamValues.add(ExprHelper.createVar(getParam(ch))); + if (hasParam(ch)) + newParamValues.add(ExprHelper.createVar(getParam(ch))); r.addAll(getLeafStatesEntered(new DashRef(ch, newParamValues))); } } return r; } + public List allPrefixDashRefs(DashRef s) { + List allPrefixFQNs = DashFQN.allPrefixes(s.getName()); + List r = new ArrayList(); + int i = 0; + for (String x:allPrefixFQNs) { + if (isAnd(x) && hasParam(x)) { + r.add(new DashRef(x,s.getParamValues().subList(0,i+1))); + i++; + } else + r.add(new DashRef(x,s.getParamValues().subList(0,i))); + } + assert(i == s.getParamValues().size()); + return r; + } /* Assumption: context is an ancestor of dest + + The param values of context do not have to match dest (but they will be subsets of the same set). + + The param values of context (from the scope) could be a set of param values or they could match dest + (and therefore src of the trans as well). But they could be an ITE expression because of expressions + used in src/dest. + + The dest param values must be singleton sets. + Does not seem to be any room for syntactic simplifications in these expressions. */ - public List getLeafStatesEnteredWithContext(DashRef context, DashRef dest) { - List r = new ArrayList(); - if (context.getName().equals(dest.getName())) - r.addAll(getLeafStatesEntered(dest)); - else { - // context must have children - List children = getImmChildren(context.getName()); - String chOfContext = DashFQN.getChildOfContextAncesOfDest(context.getName(),dest.getName()); - r.addAll(getLeafStatesEnteredWithContext(new DashRef(chOfContext,context.getParamValues()), dest)); - if (!isOr(chOfContext)) { - // enter all sibling c/p's - // treating c/p's the same + + public List getLeafStatesEnteredInContext(DashRef context, DashRef dest) { + List cR = allPrefixDashRefs(context); + List dR = allPrefixDashRefs(dest); + System.out.println("cR: "+cR); + System.out.println("dR: "+dR); + // cR is a prefix of dR but possibly with different param values + List r = new ArrayList(); // result + int p = 0; // parameter value position + List nP; + for (int i=0; i< cR.size()-1; i++) { + DashRef c = cR.get(i); + if (isAnd(c.getName()) && hasParam(c.getName())) { + nP = new ArrayList(); + nP.addAll(DashUtilFcns.allButLast(c.getParamValues())); + nP.add(ExprHelper.createDiff( + DashUtilFcns.lastElement(c.getParamValues()), + dest.getParamValues().get(p))); + r.addAll(getLeafStatesEntered(new DashRef(c.getName(), nP))); + p++; + } + } + System.out.println("r: "+r); + for (int i=cR.size()-1;i<= dR.size()-1;i++) { + DashRef d = dR.get(i); + System.out.println("d: "+d); + if (isAnd(d.getName())) { + // sisters + String chOfContext = d.getName(); + if (hasParam(chOfContext)) { + // one on path to dest + nP = new ArrayList + (DashUtilFcns.allButLast(d.getParamValues())); + nP.add(ExprHelper.createDiff( + // all param values + ExprHelper.createVar(getParam(d.getName())), + DashUtilFcns.lastElement(d.getParamValues()))); + r.addAll(getLeafStatesEntered( + new DashRef(chOfContext,nP))); + } + //siblings + List children = getImmChildren(getParent(d.getName())); List andChildren = children.stream() .filter(c -> isAnd(c)) .collect(Collectors.toList()); andChildren.remove(chOfContext); - for (String ch:children) { - List newParamValues = new ArrayList(); - // if a c, won't be any additional params - newParamValues.addAll(dest.getParamValues().subList(0, getParams(ch).size()-1)); - r.addAll(getLeafStatesEntered(new DashRef(ch, newParamValues))); - } + // siblings + for (String ch:andChildren) { + nP = new ArrayList(d.getParamValues()); + if (hasParam(ch)) + // add the entire param set + nP.add(ExprHelper.createVar(getParam(ch))); + r.addAll(getLeafStatesEntered(new DashRef(ch,nP))); + } } + //c = d; } + System.out.println("r "+r); + r.addAll(getLeafStatesEntered(dest)); return r; } + /* seems like this goes in DashToAlloy public Expr createStateArrow(String s) { Expr e = createVar(s); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 7cea72628..3db9f05be 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -144,8 +144,11 @@ public List getHigherPriTrans(String t) { // list returned could be empty List tlist = new ArrayList(); // have to look for transitions from sources earlier on the path of this transitions src - if (table.containsKey(t)) { tlist.addAll(getTransWithTheseSrcs(DashFQN.allPrefixes(table.get(t).src.getName()))); } - else { DashErrors.transDoesNotExist("getParams", t); } + List allPrefixes = DashFQN.allPrefixes(table.get(t).src.getName()); + // remove the src state itself + allPrefixes.remove(allPrefixes.size()-1); + if (table.containsKey(t)) tlist.addAll(getTransWithTheseSrcs(allPrefixes)); + else DashErrors.transDoesNotExist("getParams", t); return tlist; } diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java index a9ff38c8c..6addd079a 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java @@ -4,11 +4,19 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import edu.mit.csail.sdg.alloy4.ErrorFatal; import ca.uwaterloo.watform.core.*; public class DashCoreFQNTests { + public List ll(String[] k) { + return Arrays.asList(k); + } + @Test public void testFQN1() { String k = DashFQN.longestCommonFQN("Root/A","Root/B"); @@ -27,5 +35,58 @@ public void testFQN3() { assertEquals(k,"Root/B/Bit"); } - + @Test + public void getChildOfContextAncesOfDest1() { + assertEquals( + DashFQN.getChildOfContextAncesOfDest ("A/B/C", "A/B/C/D/E"), + "A/B/C/D"); + } + @Test + public void getChildOfContextAncesOfDest2() { + assertEquals( + DashFQN.getChildOfContextAncesOfDest ("A/B/C", "A/B/C"), + "A/B/C"); + } + @Test + public void getChildOfContextAncesOfDest3() { + Exception exception = assertThrows(ErrorFatal.class, () -> { + DashFQN.getChildOfContextAncesOfDest ("A/D/C", "A/B/C"); + }); + String actualMessage = exception.getMessage(); + assertTrue(actualMessage.contains(DashErrors.ancesNotPrefixMsg)); + } + @Test + public void getChildOfContextAncesOfDest4() { + Exception exception = assertThrows(ErrorFatal.class, () -> { + DashFQN.getChildOfContextAncesOfDest ("A/B/C", "A/B"); + }); + String actualMessage = exception.getMessage(); + assertTrue(actualMessage.contains(DashErrors.ancesNotPrefixMsg)); + } + + @Test + public void allPrefixes1() { + assertTrue(DashFQN.allPrefixes("A").equals( + ll(new String[]{ + "A" + }))); + } + @Test + public void allPrefixes2() { + assertEquals(DashFQN.allPrefixes("A/B"), + ll(new String[]{ + "A", + "A/B" + })); + } + @Test + public void allPrefixes3() { + assertEquals(DashFQN.allPrefixes("A/B/C"), + ll(new String[]{ + "A", + "A/B", + "A/B/C" + })); + } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java index 938b154b9..1e14985ba 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java @@ -153,10 +153,60 @@ public void getRegion2() { .equals(ll(new String[]{"Root", "Root/S1", "Root/S1/S2","Root/S3","Root/S3/S4", "Root/S3/S4/S5"}))); } + // allPrefixDashRefs ---------------------- + + public List allPrefixDashRefs(DashModule d, String tfqn) { + return d.allPrefixDashRefs(d.getScope(tfqn)) + .stream() + .map (i -> i.toString()) + .collect(Collectors.toList()); + } + @Test + public void allPrefixDashRefs1() { + DashModule d = test("scopeParam1"); + assertTrue( + allPrefixDashRefs(d,"Root/A/S1/t1") + .equals(ll(new String[]{ + "Root[]", + "Root/A[(pAPID = x => pAPID else APID)]" + }))); + } + @Test + public void allPrefixDashRefs2() { + DashModule d = test("scopeParam2"); + assertTrue( + allPrefixDashRefs(d, "Root/A/B/S1/t1") + .equals(ll(new String[]{ + "Root[]", + "Root/A[(pAPID = x => pAPID else APID)]", + "Root/A/B[(pAPID = x => pAPID else APID), (AND[pAPID = x, pBPID = y] => pBPID else BPID)]" + }))); + } + @Test + public void allPrefixDashRefs3() { + DashModule d = test("scopeParam3"); + assertTrue( + allPrefixDashRefs(d, "Root/A/B/S1/t1") + .equals(ll(new String[]{ + "Root[]", + "Root/A[pAPID]", + "Root/A/B[pAPID, pBPID]" + }))); + } + @Test + public void allPrefixDashRefs4() { + DashModule d = test("getEntered5"); + assertTrue( + allPrefixDashRefs(d, "Root/S1/t1") + .equals(ll(new String[]{ + "Root[]", + }))); + } + // getLeafStatesExited -------------------- public List exited(DashModule d, String tfqn) { - return d.getLeafStatesExited(d.getTransSrc(tfqn)) + return d.exited(tfqn) .stream() .map (i -> i.toString()) .collect(Collectors.toList()); @@ -168,7 +218,8 @@ public void getLeafStatesExited1() { assertTrue( exited(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S1[]" + "Root/S1[]", + "Root/S2[]" }))); } @Test @@ -177,7 +228,8 @@ public void getLeafStatesExited2() { assertTrue( exited(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S1[]" + "Root/S1[]", + "Root/S2/S3/S4[]" }))); } @Test @@ -204,7 +256,8 @@ public void getLeafStatesExited5() { assertTrue( exited(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S1[]" + "Root/S1[]", + "Root/S2/S3/S4[]" }))); assertTrue( exited(d,"Root/S2/t2") @@ -227,7 +280,8 @@ public void getLeafStatesExited7() { assertTrue( exited(d,"Root/A/t1") .equals(ll(new String[]{ - "Root/B/S1[x]" + "Root/A[APID]", + "Root/B/S1[BPID]" }))); } @@ -280,4 +334,294 @@ public void getLeafStatesEntered2() { "Root/S2/S3/S4[]" }))); } + @Test + public void getLeafStatesEntered3() { + DashModule d = test("scopeParam1"); + assertTrue( + entered(d,"Root/A/S1/t1") + .equals(ll(new String[]{ + "Root/A/S2[x]" + }))); + } + @Test + public void getLeafStatesEntered4() { + DashModule d = test("scopeParam2"); + assertTrue( + entered(d,"Root/A/B/S1/t1") + .equals(ll(new String[]{ + "Root/A/B/S2[x, y]" + }))); + } + @Test + public void getLeafStatesEntered5() { + DashModule d = test("getEntered5"); + assertTrue( + entered(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A[]" + }))); + } + @Test + public void getLeafStatesEntered6() { + DashModule d = test("getEntered6"); + assertTrue( + entered(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/S3[]" + }))); + } + @Test + public void getLeafStatesEntered7() { + DashModule d = test("getEntered7"); + assertTrue( + entered(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/S3[AID]" + }))); + } + @Test + public void getLeafStatesEntered8() { + DashModule d = test("getEntered8"); + assertTrue( + entered(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/B/S3[AID, BID]", + "Root/S2/A/C[AID, CID]" + }))); + } + @Test + public void getLeafStatesEntered9() { + DashModule d = test("getEntered9"); + assertTrue( + entered(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/B/S3[AID, BID]", + "Root/S2/A/C/S5[AID, CID]", + }))); + } + @Test + public void getLeafStatesEntered10() { + DashModule d = test("getEntered10"); + assertTrue( + entered(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/B/S3[AID, BID]", + "Root/S2/A/C/D/S5[AID, CID, DID]", + "Root/S2/A/C/E/S7[AID, CID, EID]" + }))); + } + @Test + public void getLeafStatesEntered11() { + DashModule d = test("getEntered11"); + assertTrue( + entered(d,"Root/A/S1/t1") + .equals(ll(new String[]{ + "Root/B/S2/C/S3[x, CID]" + }))); + } + + // getLeafStatesEnteredInContext ----------------- + + public List enteredInContext(DashModule d, String tfqn) { + return d.entered(tfqn) + .stream() + .map (i -> i.toString()) + .collect(Collectors.toList()); + } + + @Test + public void getLeafStatesEnteredInContext1() { + DashModule d = test("noSrc1"); + assertTrue( + enteredInContext(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2[]" + }))); + } + @Test + public void getLeafStatesEnteredInContext2() { + DashModule d = test("getEnteredInContext2"); + assertTrue( + enteredInContext(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/B/S3[]", + "Root/A/S2[]", + }))); + } + @Test + public void getLeafStatesEnteredInContext3() { + DashModule d = test("getEntered5"); + assertTrue( + enteredInContext(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A[]" + }))); + } + @Test + public void getLeafStatesEnteredInContext4() { + DashModule d = test("getEntered6"); + assertTrue( + enteredInContext(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/S3[]" + }))); + } + @Test + public void getLeafStatesEnteredInContext5() { + DashModule d = test("getEntered7"); + assertTrue( + enteredInContext(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/S3[AID]" + }))); + } + @Test + public void getLeafStatesEnteredInContext6() { + DashModule d = test("getEntered8"); + assertTrue( + enteredInContext(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/B/S3[AID, BID]", + "Root/S2/A/C[AID, CID]" + }))); + } + @Test + public void getLeafStatesEnteredInContext7() { + DashModule d = test("getEntered9"); + assertTrue( + enteredInContext(d,"Root/S1/t1") + .equals(ll(new String[]{ + "Root/S2/A/B/S3[AID, BID]", + "Root/S2/A/C/S5[AID, CID]", + }))); + } + + // connected tests on one model + @Test + public void getEnteredinContext3Tests() { + DashModule d = test("getEnteredInContext3"); + String tfqn = "Root/t1"; + assertTrue( + src(d, tfqn).equals("Root/A/B/S1[a1, b1]")); + assertTrue( + dest(d, tfqn).equals("Root/C/S2[c1]")); + assertTrue( + d.getScope(tfqn).toString().equals("Root[]")); + + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[AID, BID]", + "Root/C/S2[CID]" + }))); + assertTrue( + enteredInContext(d,tfqn) + .equals(ll(new String[]{ + "Root/C/S2[CID - c1]", + "Root/A/B/S1[c1, AID, BID]", + "Root/C/S2[c1]" + }))); + + } + @Test + public void overall1() { + DashModule d = test("overall1"); + String tfqn = "Root/A/B/S1/t1"; + assertTrue( + src(d, tfqn).equals("Root/A/B/S1[pAID, pBID]")); + assertTrue( + dest(d, tfqn).equals("Root/A/S1[a2]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/A[(pAID = a2 => pAID else AID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[(pAID = a2 => pAID else AID), BID]", + "Root/A/S1[(pAID = a2 => pAID else AID)]" + }))); + assertTrue( + enteredInContext(d,tfqn) + .equals(ll(new String[]{ + "Root/A/S1[AID - a2]", + "Root/A/S1[a2]", + }))); + } + + @Test + public void overall2() { + DashModule d = test("overall2"); + String tfqn = "Root/A/S2/t1"; + assertTrue( + src(d, tfqn).equals("Root/A/S2[pAID]")); + assertTrue( + dest(d, tfqn).equals("Root/A/B/S1[a1, b1]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/A[(pAID = a1 => pAID else AID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[(pAID = a1 => pAID else AID), BID]", + "Root/A/S2[(pAID = a1 => pAID else AID)]" + }))); + assertTrue( + enteredInContext(d,tfqn) + .equals(ll(new String[]{ + "Root/A/S2[AID - a1]", + "Root/A/B/S1[a1, BID - b1]", + "Root/A/B/S1[a1, b1]" + }))); + } + + @Test + public void overall3() { + DashModule d = test("overall3"); + String tfqn = "Root/A/B/S1/t1"; + assertTrue( + src(d, tfqn).equals("Root/A/B/S1[a1, b1]")); + assertTrue( + dest(d, tfqn).equals("Root/A/S1[a2]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/A[(a1 = a2 => a1 else AID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[(a1 = a2 => a1 else AID), BID]", + "Root/A/S1[(a1 = a2 => a1 else AID)]" + }))); + assertTrue( + enteredInContext(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[AID - a2, BID]", + "Root/A/S1[a2]" + }))); + } + /* + @Test + public void overall4() { + DashModule d = test("overall4"); + String tfqn = "Root/A/B/S1/t1"; + assertTrue( + src(d, tfqn).equals("Root/A/B/S1[a1, b1]")); + assertTrue( + dest(d, tfqn).equals("Root/A[a2]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/A[(a1 = a2 => a1 else AID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[(a1 = a2 => a1 else AID), BID]", + }))); + assertTrue( + enteredInContext(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[AID - a2, BID]", + "Root/A/B/S1[a2, BID - b1]" + "Root/A/B/S1[a2, b1]" + }))); + } + */ } diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEntered10.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered10.dsh new file mode 100644 index 000000000..2a3ea3285 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered10.dsh @@ -0,0 +1,24 @@ +state Root { + default state S1 { + trans t1 { + goto S2 + } + } + state S2 { + conc A [AID] { + conc B [BID] { + default state S3 {} + state S4 {} + } + conc C [CID] { + conc D [DID] { + default state S5 {} + state S6 {} + } + conc E [EID] { + state S7 {} + } + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEntered11.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered11.dsh new file mode 100644 index 000000000..c21323b1f --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered11.dsh @@ -0,0 +1,16 @@ +state Root { + conc A [AID] { + state S1 { + trans t1 { + goto Root/B[x] + } + } + } + conc B [BID] { + state S2 { + conc C [CID] { + state S3 {} + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEntered5.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered5.dsh new file mode 100644 index 000000000..6829b5357 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered5.dsh @@ -0,0 +1,10 @@ +state Root { + default state S1 { + trans t1 { + goto S2 + } + } + state S2 { + conc A {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEntered6.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered6.dsh new file mode 100644 index 000000000..5f3d2260e --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered6.dsh @@ -0,0 +1,13 @@ +state Root { + default state S1 { + trans t1 { + goto S2 + } + } + state S2 { + conc A { + default state S3 {} + state S4 {} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEntered7.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered7.dsh new file mode 100644 index 000000000..0343c3924 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered7.dsh @@ -0,0 +1,13 @@ +state Root { + default state S1 { + trans t1 { + goto S2 + } + } + state S2 { + conc A [AID] { + default state S3 {} + state S4 {} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEntered8.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered8.dsh new file mode 100644 index 000000000..51aaa564f --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered8.dsh @@ -0,0 +1,16 @@ +state Root { + default state S1 { + trans t1 { + goto S2 + } + } + state S2 { + conc A [AID] { + conc B [BID] { + default state S3 {} + state S4 {} + } + conc C [CID] {} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEntered9.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered9.dsh new file mode 100644 index 000000000..74873ef2b --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEntered9.dsh @@ -0,0 +1,18 @@ +state Root { + default state S1 { + trans t1 { + goto S2 + } + } + state S2 { + conc A [AID] { + conc B [BID] { + default state S3 {} + state S4 {} + } + conc C [CID] { + state S5 {} + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext2.dsh new file mode 100644 index 000000000..9db8415e2 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext2.dsh @@ -0,0 +1,13 @@ +state Root { + default state S1 { + trans t1 { + goto Root/A/S2 + } + } + conc A { + state S2 {} + } + conc B { + state S3 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext3.dsh new file mode 100644 index 000000000..db988387f --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext3.dsh @@ -0,0 +1,14 @@ +state Root { + conc A [AID] { + conc B [BID] { + state S1 {} + } + } + conc C [CID] { + state S2 {} + } + trans t1 { + from Root/A/B/S1[a1,b1] + goto Root/C/S2[c1] + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh new file mode 100644 index 000000000..be361b9ed --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh @@ -0,0 +1,12 @@ +state Root { + conc A [AID] { + conc B [BID] { + state S1 { + trans t1 { + goto Root/A/S1[a2] + } + } + } + default state S1 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall2.dsh new file mode 100644 index 000000000..e06607e00 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall2.dsh @@ -0,0 +1,12 @@ +state Root { + conc A [AID] { + conc B [BID] { + state S1 {} + } + default state S2 { + trans t1 { + goto Root/A/B/S1[a1,b1] + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh new file mode 100644 index 000000000..c5f2fcc26 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh @@ -0,0 +1,14 @@ +state Root { + conc A [AID] { + default conc B [BID] { + state S1 { + trans t1 { + from Root/A/B/S1[a1,b1] + goto Root/A/S1[a2] + } + } + } + state S1 {} + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall4.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall4.dsh new file mode 100644 index 000000000..75b111966 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall4.dsh @@ -0,0 +1,12 @@ +state Root { + conc A [AID] { + conc B [BID] { + state S1 { + trans t1 { + from Root/A/B/S1[a1, b1] + goto Root/A[a2] + } + } + } + } +} \ No newline at end of file From f4ab7e1deeb70782be890fadb80448a106cf7f15 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 21 Apr 2023 12:00:49 -0400 Subject: [PATCH 028/129] src/dest/scope/orthogonality --- .../watform/alloyasthelper/ExprHelper.java | 33 +- .../ca/uwaterloo/watform/ast/DashFrom.java | 1 + .../ca/uwaterloo/watform/ast/DashGoto.java | 2 +- .../ca/uwaterloo/watform/ast/DashState.java | 2 + .../ca/uwaterloo/watform/core/DashFQN.java | 2 +- .../watform/{ast => core}/DashRef.java | 13 +- .../uwaterloo/watform/core/DashStrings.java | 2 +- .../uwaterloo/watform/core/DashUtilFcns.java | 14 +- .../watform/dashtoalloy/DashToAlloy.java | 180 +++++---- .../uwaterloo/watform/parser/DashModule.java | 69 +++- .../uwaterloo/watform/parser/StateTable.java | 69 ++-- .../alloytools/alloy/dash/DashStateTests.java | 371 +++++++++++++++--- .../resources/pass/getEnteredInContext3.dsh | 14 - ...dInContext2.dsh => getEnteredInScope2.dsh} | 0 .../test/resources/pass/overall1-traces.als | 60 +++ .../src/test/resources/pass/overall1.dsh | 14 +- .../src/test/resources/pass/overall2.dsh | 10 +- .../src/test/resources/pass/overall3.dsh | 16 +- .../test/resources/pass/overall4-traces.als | 66 ++++ .../src/test/resources/pass/overall4.dsh | 8 +- .../src/test/resources/pass/overall5.dsh | 20 + .../src/test/resources/pass/overall6.dsh | 16 + .../test/resources/pass/overall7-traces.als | 114 ++++++ .../src/test/resources/pass/overall7.dsh | 20 + .../src/test/resources/pass/overall8.dsh | 18 + .../test/resources/pass/overall9-traces.als | 71 ++++ .../src/test/resources/pass/overall9.dsh | 20 + 27 files changed, 1011 insertions(+), 214 deletions(-) rename org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/{ast => core}/DashRef.java (72%) delete mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext3.dsh rename org.alloytools.alloy.dash/src/test/resources/pass/{getEnteredInContext2.dsh => getEnteredInScope2.dsh} (100%) create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall1-traces.als create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall4-traces.als create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall5.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall6.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall7-traces.als create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall7.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall8.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall9-traces.als create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall9.dsh diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 05474fde0..887d258b2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -110,8 +110,18 @@ public static Expr createUnionList(List elist) { } return ret; } - public static ExprBinary createEquals(Expr left, Expr right) { - return (ExprBinary) ExprBinary.Op.EQUALS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + public static Expr createDiffList(List elist) { + Expr ret = null; + assert(elist!=null); + ret = elist.get(0); + for (Expr el: elist.subList(1,elist.size())) { + ret = createDiff(ret,el); + } + return ret; + } + public static Expr createEquals(Expr left, Expr right) { + if (sEquals(left,right)) return (Expr) createTrue(); + else return (Expr) ExprBinary.Op.EQUALS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } public static ExprBinary createNotEquals(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.NOT_EQUALS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); @@ -145,19 +155,28 @@ public static ExprBinary createIn(Expr left,Expr right) { } // {x,y,z} // returns x -> (y -> z) - public static Expr createArrowList(List eList) { + public static Expr createArrowStringList(List eList) { assert(eList != null); Collections.reverse(eList); Expr o = createVar(eList.get(0)); - for (String e: eList.subList(1,eList.size()-1)) { + for (String e: eList.subList(1,eList.size())) { o = createArrow(createVar(e), o); } return o; } + public static Expr createArrowExprList(List eList) { + assert(eList != null); + Collections.reverse(eList); + Expr o = eList.get(0); + for (Expr e: eList.subList(1,eList.size())) { + o = createArrow(e, o); + } + return o; + } - - public static ExprITE createITE(Expr cond, Expr impliesExpr, Expr elseExpr) { - return (ExprITE) ExprITE.make(Pos.UNKNOWN, cond, impliesExpr, elseExpr); + public static Expr createITE(Expr cond, Expr impliesExpr, Expr elseExpr) { + if (sEquals(cond, createTrue())) return (Expr) impliesExpr; + else return (Expr) ExprITE.make(Pos.UNKNOWN, cond, impliesExpr, elseExpr); } public static ExprQt createAll(List decls, Expr expr) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java index 14afa0aa9..5fc23cb22 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java @@ -6,6 +6,7 @@ import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashRef; public class DashFrom extends Dash { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java index 8945fad45..171a3761f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java @@ -7,7 +7,7 @@ import ca.uwaterloo.watform.core.DashUtilFcns.*; import ca.uwaterloo.watform.core.DashStrings; - +import ca.uwaterloo.watform.core.DashRef; public class DashGoto extends Dash { public DashRef dest; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index ce6e33d7c..b567fd5b7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -340,6 +340,8 @@ public DashRef setSrcDest(String xType, List ll, StateTable st, String //System.out.println("Looking for: " + x); if (DashFQN.alreadyFQN(x.getName())) { // number of params provided must match number of params needed + //System.out.println(x.getParamValues().size()); + //System.out.println(st.getParams(x.getName()).size()); if (x.getParamValues().size() != st.getParams(x.getName()).size()) { DashErrors.fqnSrcDestMustHaveRightNumberParams(xType,tfqn); return null; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java index 3d5dd415f..38c2f7bac 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java @@ -64,7 +64,7 @@ public static List splitFQN(String fqn) { } public static String chopNameFromFQN(String fqn) { // this is from an output FQN - return DashUtilFcns.last(splitFQN(fqn)); + return DashUtilFcns.lastElement(splitFQN(fqn)); } // can't just take longest prefix because states may have similar names // such as Bit1 and Bit2 diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java similarity index 72% rename from org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java rename to org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index 03442476e..0cbbad402 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -1,14 +1,17 @@ -package ca.uwaterloo.watform.ast; +package ca.uwaterloo.watform.core; import java.util.List; import java.util.ArrayList; +import java.util.Collections; import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Expr; +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; import ca.uwaterloo.watform.core.DashUtilFcns; -public class DashRef extends Dash { +public class DashRef{ + private Pos pos; private String name; private List paramValues; @@ -43,4 +46,10 @@ public String toString() { public static List emptyParamValuesList() { return new ArrayList(); } + public Expr toAlloy() { + List ll = new ArrayList(paramValues); + Collections.reverse(ll); + ll.add(ExprHelper.createVar(name)); + return ExprHelper.createArrowExprList(ll); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index a86bf439f..34f2abe73 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -60,7 +60,7 @@ public class DashStrings { // sig names public static String snapshotName = "Snapshot"; public static String confName = "conf"; - public static String takenName = "taken"; + public static String scopesUsedName = "scopesUsed"; public static String stateLabelName = "StateLabel"; public static String systemStateName = "SystemState"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java index e0addd181..6584ccc6d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java @@ -16,12 +16,6 @@ public class DashUtilFcns { - - - public static String last(List ll) { - return ll.get(ll.size() - 1 ); - } - /* copied from https://stackoverflow.com/questions/7414667/identify-duplicates-in-a-list */ public static Set findDuplicates(Collection collection) { @@ -64,9 +58,11 @@ public static void handleException(Exception e) { e.printStackTrace(System.err); System.exit(1); } - public static T lastElement(List ll) { - return ll.get(ll.size()-1); - } + + public static T lastElement(List ll) { + return ll.get(ll.size() - 1 ); + } + public static List allButLast(List ll) { return ll.subList(0,ll.size()-1); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 2b7eb9154..606916351 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -9,6 +9,7 @@ package ca.uwaterloo.watform.dashtoalloy; import java.util.Collections; +import java.util.stream.Collectors; import java.util.List; import java.util.ArrayList; import java.util.Arrays; @@ -20,6 +21,7 @@ import ca.uwaterloo.watform.core.DashOptions; import ca.uwaterloo.watform.core.DashStrings; import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashRef; // shortens the code to import these statically import static ca.uwaterloo.watform.core.DashFQN.*; @@ -67,19 +69,19 @@ private void createSpaceSignatures() { d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); // Root //if (d.hasConcurrency() || d.getImmChildren(d.getRootName()).isEmpty()) - //d.alloyString += d.addExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + d.alloyString += d.addExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); //else - d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + //d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); recurseCreateStateSpaceSigs(d.getRootName()); d.alloyString += "\n"; // abstract sig TransLabel {} - d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); + // d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); // add all transitions as one sig extensions of TransLabel - for (String t : d.getTransNames()) { - d.alloyString += d.addOneExtendsSigSimple(fqn(t), DashStrings.transitionLabelName); - } - d.alloyString += "\n"; + //for (String t : d.getTransNames()) { + //d.alloyString += d.addOneExtendsSigSimple(fqn(t), DashStrings.transitionLabelName); + //} + //d.alloyString += "\n"; // abstract sig Identifiers {} if this model has parameterized components if (d.getMaxDepthParams() != 0) { @@ -116,34 +118,34 @@ private void createSpaceSignatures() { */ } private void recurseCreateStateSpaceSigs(String parent) { - for (String child: d.getImmChildren(parent)) - if (d.isLeaf(child)) d.alloyString += d.addOneExtendsSigSimple(fqn(child),fqn(parent)); - else { + for (String child: d.getImmChildren(parent)) { + if (d.isLeaf(child) || d.isAnd(child)) d.alloyString += d.addOneExtendsSigSimple(fqn(child),fqn(parent)); + else //if (d.isAnd(parent)) //d.alloyString += d.addExtendsSigSimple(fqn(child), fqn(parent)); //else - d.alloyString += d.addAbstractExtendsSigSimple(fqn(child), fqn(parent)); - recurseCreateStateSpaceSigs(child); - } + d.alloyString += d.addAbstractExtendsSigSimple(fqn(child), fqn(parent)); + if (!d.isLeaf(child)) recurseCreateStateSpaceSigs(child); + } } private void createSnapshotSig(){ if (DashOptions.isElectrum) { // if Electrum add var sigs - // taken0, conf0, event0 + // scopesUsed0, conf0, event0 - if (d.transAtThisParamDepth(0)) - d.alloyString += d.addVarSigSimple(DashStrings.takenName+"0", createVar(DashStrings.transitionLabelName)); + //if (d.transAtThisParamDepth(0)) + d.alloyString += d.addVarSigSimple(DashStrings.scopesUsedName+"0", createVar(DashStrings.stateLabelName)); d.alloyString += d.addVarSigSimple(DashStrings.confName+"0", createVar(DashStrings.stateLabelName)); if (d.hasEvents()) d.alloyString += d.addVarSigSimple(DashStrings.eventName+"0", createVar(DashStrings.eventLabelName)); List cop; for (int i = 1; i <= d.getMaxDepthParams(); i++) { cop = new ArrayList (Collections.nCopies(i+1,createVar(DashStrings.identifierName))); - if (d.transAtThisParamDepth(i)) - // taken 1, etc. + //if (d.transAtThisParamDepth(i)) + // scopesUsed 1, etc. d.alloyString += d.addVarSigSimple( - DashStrings.takenName+Integer.toString(i), - DashUtilFcns.newListWith(cop, createVar(DashStrings.transitionLabelName))); + DashStrings.scopesUsedName+Integer.toString(i), + DashUtilFcns.newListWith(cop, createVar(DashStrings.stateLabelName))); // conf 1, etc. d.alloyString += d.addVarSigSimple( DashStrings.confName+Integer.toString(i), @@ -172,29 +174,29 @@ private void createSnapshotSig(){ // if traces/tcmc sig Snapshot {} with fields List decls = new ArrayList(); - // taken0, conf0, event0 - if (d.transAtThisParamDepth(0)) - decls.add(DeclExt.newSetDeclExt(DashStrings.takenName+"0", DashStrings.transitionLabelName)); + // scopesUsed0, conf0, event0 + //if (d.transAtThisParamDepth(0)) + decls.add(DeclExt.newSetDeclExt(DashStrings.scopesUsedName+"0", DashStrings.stateLabelName)); decls.add(DeclExt.newSetDeclExt(DashStrings.confName+"0", DashStrings.stateLabelName)); if (d.hasEvents()) decls.add(DeclExt.newSetDeclExt(DashStrings.eventName+"0", DashStrings.eventLabelName)); List cop; for (int i = 1; i <= d.getMaxDepthParams(); i++) { cop = Collections.nCopies(i+1,DashStrings.identifierName); - // taken 1, etc. - if (d.transAtThisParamDepth(i)) + // scopesUsed 1, etc. + //if (d.transAtThisParamDepth(i)) decls.add(DeclExt.newSetDeclExt( - DashStrings.takenName+Integer.toString(i), - createArrowList(DashUtilFcns.newListWith(cop, DashStrings.transitionLabelName)))); + DashStrings.scopesUsedName+Integer.toString(i), + createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName)))); // conf 1, etc. decls.add(DeclExt.newSetDeclExt( DashStrings.confName+Integer.toString(i), - createArrowList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName)))); + createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName)))); // event 1, etc. if (d.hasEvents()) decls.add(new DeclExt( DashStrings.eventName+Integer.toString(i), - createArrowList(DashUtilFcns.newListWith(cop, DashStrings.eventLabelName)))); + createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.eventLabelName)))); } // stable: one boolean; if (d.hasConcurrency()) { @@ -238,9 +240,17 @@ private void createTransPre(String t) { // p3 -> p2 -> p1 -> src in s.confVar(i) // src does not have to be a basic state - /* - body.add(createIn(paramsToXArrow(prs,convertFQN(d.getTransSrc(t))),curConf(prs.size()))); - */ + + body.add(createIn(d.getTransSrc(t).toAlloy(),curConf(prs.size()))); + List nonO = d.nonOrthogonalScopesOf(t); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List u = hasNumParams(nonO,i).stream().map(x -> x.toAlloy()).collect(Collectors.toList()); + // scopesUsedi' = scopesUsedi - exitedi + enteredi + Expr e = curConf(i); + for (Expr x: u) body.add(createNot(createIn(x,scopesUsed(i)))); + } + // orthogonality + // nonOrthogonalScopes not in scopesUsed /* // guard_cond_t1 [s] o.add(d.getTransGuard(t).convertToAlloy(d.symbolTable, curVar(), nextVar())); @@ -267,21 +277,51 @@ private void createTransPre(String t) { d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.preName, curParamsDecls(prs), body); d.alloyString += "\n"; } + private List hasNumParams(List dr, int i) { + // filter to ones that have this number of params + //System.out.println(i); + //System.out.println(dr); + List o = dr.stream() + .filter(x -> x.getParamValues().size() == i) + .collect(Collectors.toList()); + //System.out.println(o); + return o; + } private void createTransPost(String t) { List prs = d.getTransParams(t); - // tmp List body = new ArrayList(); + + // confi' = confi - exitedi + enteredi + List entered = d.entered(t); + List exited = d.exited(t); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List ent = hasNumParams(entered,i).stream().map(x -> x.toAlloy()).collect(Collectors.toList()); + List exi = hasNumParams(exited,i).stream().map(x -> x.toAlloy()).collect(Collectors.toList()); + Expr e = curConf(i); + if (!exi.isEmpty()) e = createDiff(e,createDiffList(exi)); + if (!ent.isEmpty()) e = createUnion(e,createUnionList(ent)); + body.add(createEquals(nextConf(i),e)); + } + // scopesUsedi' = scopesUsedi + scopesUsed + List sU = d.scopesUsed(t); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List u = hasNumParams(sU,i).stream().map(x -> x.toAlloy()).collect(Collectors.toList()); + Expr e = curConf(i); + if (!u.isEmpty()) e = createUnion(e,createUnionList(u)); + body.add(createEquals(nextConf(i),e)); + } + d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.postName,curNextParamsDecls(prs),body); } // ----------------------------------------------------------------------------- /* pred t1_semantics[s:Snapshot,s':Snapshot, pParam0: Param0, ... ] { (s.stable = True) => { - s'.taken = t1 + s'.scopesUsed = t1 } else { - s'.taken = s.taken + t1 - no t1.notOrthogonal & (s.taken0 + taken0 |> TransitionLabel + s.taken1 |> TransitionLabel + ...) + s'.scopesUsed = s.scopesUsed + t1 + no t1.notOrthogonal & (s.scopesUsed0 + scopesUsed0 |> TransitionLabel + s.scopesUsed1 |> TransitionLabel + ...) } for all t in t1.higherPri // all have same param values (or prefixes) because these trans are from srcs @@ -298,27 +338,27 @@ private void createTransSemantics(String t) { String tfqn = convertFQN(t); // output FQN - // s'.taken = s.taken + t1 + // s'.scopesUsed = s.scopesUsed + t1 // or - // s'.taken2 = s.taken2 + p2 -> p1 -> tfqn - // and other takens stay the same - List takens = new ArrayList(); + // s'.scopesUsed2 = s.scopesUsed2 + p2 -> p1 -> tfqn + // and other scopesUseds stay the same + List scopesUseds = new ArrayList(); for (int i=0;i <= d.getMaxDepthParams(); i++) if (d.transAtThisParamDepth(i)) if (i == prs.size()) if (DashOptions.isElectrum) - takens.add(createEquals( - taken(i), - createUnion(taken(i),paramsToXArrow(prs,tfqn)))); - else takens.add(createEquals( + scopesUseds.add(createEquals( + scopesUsed(i), + createUnion(scopesUsed(i),paramsToXArrow(prs,tfqn)))); + else scopesUseds.add(createEquals( nextTaken(i), createUnion(curTaken(i),paramsToXArrow(prs,tfqn)))); else - if (DashOptions.isElectrum) takens.add(createEquals(taken(i), curTaken(i))); - else takens.add(createEquals(nextTaken(i), curTaken(i))); - Expr elseExpr = createAnd(takens); + if (DashOptions.isElectrum) scopesUseds.add(createEquals(scopesUsed(i), curTaken(i))); + else scopesUseds.add(createEquals(nextTaken(i), curTaken(i))); + Expr elseExpr = createAnd(scopesUseds); - // no trans "below" the scope of this trans with the same params can be taken + // no trans "below" the scope of this trans with the same params can be scopesUsed // (other params are for other parts of state hierarchy at this depth) // for the rest of the non-orthogonal trans, param values don't matter @@ -328,38 +368,38 @@ private void createTransSemantics(String t) { elseExpr = createAnd( elseExpr, - // no t1.notOrthogonal & (s.taken + s.taken1 |> TransitionLabel + taken2 |> TransitionLabel + ...) + // no t1.notOrthogonal & (s.scopesUsed + s.scopesUsed1 |> TransitionLabel + scopesUsed2 |> TransitionLabel + ...) createNo( createAnd( createNonOrthogonalExpr(t), - createChoppedGroup(prs.size(),DashStrings.takenName,DashStrings.transitionLabelName)))); + createChoppedGroup(prs.size(),DashStrings.scopesUsedName,DashStrings.transitionLabelName)))); } */ - takens = new ArrayList(); + scopesUseds = new ArrayList(); for (int i=0;i <= d.getMaxDepthParams(); i++) if (d.transAtThisParamDepth(i)) if (i == prs.size()) if (DashOptions.isElectrum) - takens.add(createEquals( - taken(i), + scopesUseds.add(createEquals( + scopesUsed(i), paramsToXArrow(prs,tfqn))); - else takens.add(createEquals( + else scopesUseds.add(createEquals( nextTaken(i), paramsToXArrow(prs,tfqn))); else - if (DashOptions.isElectrum) takens.add(createEquals(taken(i), createNone())); - else takens.add(createEquals(nextTaken(i), createNone())); - Expr firsttaken = createAnd(takens); + if (DashOptions.isElectrum) scopesUseds.add(createEquals(scopesUsed(i), createNone())); + else scopesUseds.add(createEquals(nextTaken(i), createNone())); + Expr firstscopesUsed = createAnd(scopesUseds); if (d.hasConcurrency()) body.add( createITE(curStableTrue(), - // s'.taken = t1 - firsttaken, + // s'.scopesUsed = t1 + firstscopesUsed, elseExpr) ); else - // will only have taken0 in it - body.add(firsttaken); + // will only have scopesUsed0 in it + body.add(firstscopesUsed); // priority // depends on the src of this transition @@ -395,7 +435,7 @@ private void createTransSemantics(String t) { (if trig_ev_t1 is internal, line below is false) trig_ev_t1 in (chop0(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) ... + ge) else { - no t1.notOrthogonal & (t + s.taken0 + s.taken1.TransLabel + s.taken2.TransLabel + s.taken3.TransLabel ...) + no t1.notOrthogonal & (t + s.scopesUsed0 + s.scopesUsed1.TransLabel + s.scopesUsed2.TransLabel + s.scopesUsed3.TransLabel ...) for all of t1's triggering events and forall n trig_ev_t1 in (s.event0.EventLabel + s.event1.EventLabel + s.event2.EventLabel ... + ge) } @@ -421,11 +461,11 @@ private void createTransIsEnabledAfterStep(String t) { o.add(dash.getTransGuard(t).convertToAlloy(dash.symbolTable, nextVar(), null, prs)); - // no t1.notOrthogonal & (t + s.taken + s.taken1 |> TransitionLabel + taken2 |> TransitionLabel + ...) + // no t1.notOrthogonal & (t + s.scopesUsed + s.scopesUsed1 |> TransitionLabel + scopesUsed2 |> TransitionLabel + ...) Expr elseExpr = createNo( createAnd( createNonOrthogonalExpr(t),createPlus(createVar(t), - createChoppedGroup(prs.size(),DashStrings.takenName,DashStrings.transitionLabelName)))); + createChoppedGroup(prs.size(),DashStrings.scopesUsedName,DashStrings.transitionLabelName)))); elseExpr = createAnd( elseExpr, createIn( @@ -586,8 +626,8 @@ private List curNextParamVars(List params) { return o; } - private Expr taken(int size) { - return createVar(DashStrings.takenName + size); + private Expr scopesUsed(int size) { + return createVar(DashStrings.scopesUsedName + size); } private Expr conf(int size) { return createVar(DashStrings.confName + size); @@ -595,13 +635,13 @@ private Expr conf(int size) { private Expr stable() { return createVar(DashStrings.stableName); } - // s.taken5 + // s.scopesUsed5 private Expr curTaken(int size) { - return curJoinExpr(taken(size)); + return curJoinExpr(scopesUsed(size)); } - // s'.taken5 + // s'.scopesUsed5 private Expr nextTaken(int size) { - return nextJoinExpr(taken(size)); + return nextJoinExpr(scopesUsed(size)); } // s.conf4 private Expr curConf(int size) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 3453b65f3..7ba115c64 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -9,6 +9,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Set; +import java.util.Collections; +import java.util.stream.Collectors; import edu.mit.csail.sdg.alloy4.Pair; import edu.mit.csail.sdg.alloy4.A4Reporter; @@ -16,8 +18,9 @@ import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.*; +import static ca.uwaterloo.watform.core.DashUtilFcns.*; import ca.uwaterloo.watform.ast.*; -import ca.uwaterloo.watform.alloyasthelper.ExprHelper; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; import ca.uwaterloo.watform.parser.CompModuleHelper; import ca.uwaterloo.watform.dashtoalloy.DashToAlloy; @@ -265,8 +268,8 @@ public List getLeafStatesExited(DashRef s) { public List getLeafStatesEntered(DashRef s) { return stateTable.getLeafStatesEntered(s); } - public List getLeafStatesEnteredWithContext(DashRef context, DashRef s) { - return null; //stateTable.getLeafStatesEnteredWithContext(context, s); + public List getLeafStatesEnteredWithScope(DashRef context, DashRef s) { + return null; //stateTable.getLeafStatesEnteredWithScope(context, s); } public List getAllAnces(String sfqn) { return stateTable.getAllAnces(sfqn); @@ -319,29 +322,29 @@ public DashRef getScope(String tfqn) { for (int i=0;i allPrefixDashRefs(DashRef x) { return stateTable.allPrefixDashRefs(x); } public List entered(String tfqn) { - return stateTable.getLeafStatesEnteredInContext( + return stateTable.getLeafStatesEnteredInScope( getScope(tfqn), getTransDest(tfqn)); } + public List onlyConc(List dr) { + return dr.stream() + .filter(x -> isAnd(x.getName())) + .collect(Collectors.toList()); + } + public List scopesUsed(String tfqn) { + DashRef scope = getScope(tfqn); + List aP = onlyConc(allPrefixDashRefs(scope)); + List r = new ArrayList(); + List prms; + Expr e; + Expr p; + for (DashRef s: allButLast(aP)) { + // if a prefix scope includes all param values, it really + // is the scope + if (isAnd(s.getName()) && stateTable.hasParam(s.getName())) { + prms = new ArrayList(allButLast(s.getParamValues())); + e = lastElement(s.getParamValues()); + p = createITE(createEquals(e,createVar(stateTable.getParam(s.getName()))), + createVar(stateTable.getParam(s.getName())), + createNone()); + prms.add(p); + r.add(new DashRef(s.getName(), prms)); + } + } + r.add(lastElement(aP)); + return r; + } + public List nonOrthogonalScopesOf(String tfqn) { + DashRef scope = getScope(tfqn); + System.out.println(allPrefixDashRefs(scope)); + List aP = allPrefixDashRefs(scope); + // always needs to include Root + List r = new ArrayList(); + r.add(aP.get(0)); + r.addAll(onlyConc(aP)); + return r; + } // processes --------------------------------------- public void debug(String tfqn) { @@ -382,8 +423,10 @@ public void debug(String tfqn) { System.out.println("getRegion:"+"Root/S1/S2: "+getRegion(getTransSrc(tfqn).getName())); System.out.println("exited: " + exited(tfqn)); System.out.println("entered" + getLeafStatesEntered(getTransDest(tfqn))); - System.out.println("enteredInContext" + entered(tfqn)); + System.out.println("enteredInScope" + entered(tfqn)); System.out.println("allPrefixDashRefs of scope: "+ allPrefixDashRefs(getScope(tfqn))); + System.out.println("scopesUsed: "+ scopesUsed(tfqn)); + System.out.println("nonOrthogonalScopes: " + nonOrthogonalScopesOf(tfqn)); } } // should we use the rep arg here? diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 518c20774..3f4556ed6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -24,7 +24,7 @@ import static ca.uwaterloo.watform.core.DashFQN.*; import ca.uwaterloo.watform.alloyasthelper.ExprHelper; -import ca.uwaterloo.watform.ast.DashRef; +import ca.uwaterloo.watform.core.DashRef; public class StateTable { private HashMap table; @@ -422,51 +422,62 @@ The param values of context (from the scope) could be a set of param values or t Does not seem to be any room for syntactic simplifications in these expressions. */ - public List getLeafStatesEnteredInContext(DashRef context, DashRef dest) { + public List getLeafStatesEnteredInScope(DashRef context, DashRef dest) { List cR = allPrefixDashRefs(context); List dR = allPrefixDashRefs(dest); System.out.println("cR: "+cR); System.out.println("dR: "+dR); // cR is a prefix of dR but possibly with different param values + // enter all the possible side concurrent regions of the scope(context) List r = new ArrayList(); // result int p = 0; // parameter value position - List nP; - for (int i=0; i< cR.size()-1; i++) { + List xP = new ArrayList(); // parameters carrying forward + List nP; // parameters for each addition + Expr e1; + Expr e2; + for (int i=0; i< cR.size(); i++) { DashRef c = cR.get(i); if (isAnd(c.getName()) && hasParam(c.getName())) { - nP = new ArrayList(); - nP.addAll(DashUtilFcns.allButLast(c.getParamValues())); - nP.add(ExprHelper.createDiff( - DashUtilFcns.lastElement(c.getParamValues()), - dest.getParamValues().get(p))); - r.addAll(getLeafStatesEntered(new DashRef(c.getName(), nP))); + nP = new ArrayList(xP); + e1 = DashUtilFcns.lastElement(c.getParamValues()); + e2 = dest.getParamValues().get(p); + if (!ExprHelper.sEquals(e1, e2)) { + nP.add(ExprHelper.createDiff(e1,e2)); + r.addAll(getLeafStatesEntered(new DashRef(c.getName(), nP))); + } // if equal this is empty so don't include it + xP.add(e2); // just e2 for next one p++; } } - System.out.println("r: "+r); - for (int i=cR.size()-1;i<= dR.size()-1;i++) { - DashRef d = dR.get(i); - System.out.println("d: "+d); - if (isAnd(d.getName())) { - // sisters - String chOfContext = d.getName(); - if (hasParam(chOfContext)) { - // one on path to dest + //System.out.println("r: "+r); + // we've dealt with all the side paths in cR of dR (including the last one in CR) + // now deal with the rest of dR by looking at the side paths of the children + // might be nothing in this loop if cR and dR are the same length + for (int i=cR.size()-1;i< dR.size()-1;i++) { + DashRef d = dR.get(i); // first one will be match the last of cR + DashRef chOfDest = dR.get(i+1); + //System.out.println("d: "+d); + if (isAnd(chOfDest.getName())) { + // has sisters + if (hasParam(chOfDest.getName())) { + // ones not on path to dest nP = new ArrayList - (DashUtilFcns.allButLast(d.getParamValues())); - nP.add(ExprHelper.createDiff( - // all param values - ExprHelper.createVar(getParam(d.getName())), - DashUtilFcns.lastElement(d.getParamValues()))); - r.addAll(getLeafStatesEntered( - new DashRef(chOfContext,nP))); + (DashUtilFcns.allButLast(chOfDest.getParamValues())); + // all param values + e1 = ExprHelper.createVar(getParam(chOfDest.getName())); + e2 = DashUtilFcns.lastElement(chOfDest.getParamValues()); + if (!ExprHelper.sEquals(e1, e2)) { + nP.add(ExprHelper.createDiff(e1, e2)); + r.addAll(getLeafStatesEntered( + new DashRef(chOfDest.getName(),nP))); + } // if equal this is empty so don't include it } //siblings - List children = getImmChildren(getParent(d.getName())); + List children = getImmChildren(d.getName()); List andChildren = children.stream() .filter(c -> isAnd(c)) .collect(Collectors.toList()); - andChildren.remove(chOfContext); + andChildren.remove(chOfDest.getName()); // siblings for (String ch:andChildren) { nP = new ArrayList(d.getParamValues()); @@ -476,7 +487,7 @@ public List getLeafStatesEnteredInContext(DashRef context, DashRef dest r.addAll(getLeafStatesEntered(new DashRef(ch,nP))); } } - //c = d; + // if its an OR state, just go on to the next one } System.out.println("r "+r); r.addAll(getLeafStatesEntered(dest)); diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java index 1e14985ba..e3e86847b 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java @@ -420,9 +420,9 @@ public void getLeafStatesEntered11() { }))); } - // getLeafStatesEnteredInContext ----------------- + // getLeafStatesEnteredInScope ----------------- - public List enteredInContext(DashModule d, String tfqn) { + public List enteredInScope(DashModule d, String tfqn) { return d.entered(tfqn) .stream() .map (i -> i.toString()) @@ -430,66 +430,66 @@ public List enteredInContext(DashModule d, String tfqn) { } @Test - public void getLeafStatesEnteredInContext1() { + public void getLeafStatesEnteredInScope1() { DashModule d = test("noSrc1"); assertTrue( - enteredInContext(d,"Root/S1/t1") + enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ "Root/S2[]" }))); } @Test - public void getLeafStatesEnteredInContext2() { - DashModule d = test("getEnteredInContext2"); + public void getLeafStatesEnteredInScope2() { + DashModule d = test("getEnteredInScope2"); assertTrue( - enteredInContext(d,"Root/S1/t1") + enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ "Root/B/S3[]", "Root/A/S2[]", }))); } @Test - public void getLeafStatesEnteredInContext3() { + public void getLeafStatesEnteredInScope3() { DashModule d = test("getEntered5"); assertTrue( - enteredInContext(d,"Root/S1/t1") + enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ "Root/S2/A[]" }))); } @Test - public void getLeafStatesEnteredInContext4() { + public void getLeafStatesEnteredInScope4() { DashModule d = test("getEntered6"); assertTrue( - enteredInContext(d,"Root/S1/t1") + enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ "Root/S2/A/S3[]" }))); } @Test - public void getLeafStatesEnteredInContext5() { + public void getLeafStatesEnteredInScope5() { DashModule d = test("getEntered7"); assertTrue( - enteredInContext(d,"Root/S1/t1") + enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ "Root/S2/A/S3[AID]" }))); } @Test - public void getLeafStatesEnteredInContext6() { + public void getLeafStatesEnteredInScope6() { DashModule d = test("getEntered8"); assertTrue( - enteredInContext(d,"Root/S1/t1") + enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ "Root/S2/A/B/S3[AID, BID]", "Root/S2/A/C[AID, CID]" }))); } @Test - public void getLeafStatesEnteredInContext7() { + public void getLeafStatesEnteredInScope7() { DashModule d = test("getEntered9"); assertTrue( - enteredInContext(d,"Root/S1/t1") + enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ "Root/S2/A/B/S3[AID, BID]", "Root/S2/A/C/S5[AID, CID]", @@ -498,8 +498,8 @@ public void getLeafStatesEnteredInContext7() { // connected tests on one model @Test - public void getEnteredinContext3Tests() { - DashModule d = test("getEnteredInContext3"); + public void overall1() { + DashModule d = test("overall1"); String tfqn = "Root/t1"; assertTrue( src(d, tfqn).equals("Root/A/B/S1[a1, b1]")); @@ -515,22 +515,22 @@ public void getEnteredinContext3Tests() { "Root/C/S2[CID]" }))); assertTrue( - enteredInContext(d,tfqn) + enteredInScope(d,tfqn) .equals(ll(new String[]{ "Root/C/S2[CID - c1]", - "Root/A/B/S1[c1, AID, BID]", + "Root/A/B/S1[AID, BID]", "Root/C/S2[c1]" }))); } @Test - public void overall1() { - DashModule d = test("overall1"); + public void overall2() { + DashModule d = test("overall2"); String tfqn = "Root/A/B/S1/t1"; assertTrue( src(d, tfqn).equals("Root/A/B/S1[pAID, pBID]")); assertTrue( - dest(d, tfqn).equals("Root/A/S1[a2]")); + dest(d, tfqn).equals("Root/A/S2[a2]")); assertTrue( d.getScope(tfqn).toString() .equals("Root/A[(pAID = a2 => pAID else AID)]")); @@ -538,19 +538,19 @@ public void overall1() { exited(d,tfqn) .equals(ll(new String[]{ "Root/A/B/S1[(pAID = a2 => pAID else AID), BID]", - "Root/A/S1[(pAID = a2 => pAID else AID)]" + "Root/A/S2[(pAID = a2 => pAID else AID)]" }))); assertTrue( - enteredInContext(d,tfqn) + enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A/S1[AID - a2]", - "Root/A/S1[a2]", + "Root/A/S2[(pAID = a2 => pAID else AID) - a2]", + "Root/A/S2[a2]", }))); } @Test - public void overall2() { - DashModule d = test("overall2"); + public void overall3() { + DashModule d = test("overall3"); String tfqn = "Root/A/S2/t1"; assertTrue( src(d, tfqn).equals("Root/A/S2[pAID]")); @@ -566,22 +566,62 @@ public void overall2() { "Root/A/S2[(pAID = a1 => pAID else AID)]" }))); assertTrue( - enteredInContext(d,tfqn) + enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A/S2[AID - a1]", + "Root/A/S2[(pAID = a1 => pAID else AID) - a1]", "Root/A/B/S1[a1, BID - b1]", "Root/A/B/S1[a1, b1]" }))); + + tfqn = "Root/A/B/S1/t2"; + assertTrue( + src(d, tfqn).equals("Root/A/B/S1[pAID, pBID]")); + assertTrue( + dest(d, tfqn).equals("Root/A/B/S1[pAID, pBID]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/A/B/S1[pAID, pBID]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[pAID, pBID]" + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[pAID, pBID]" + }))); + + tfqn = "Root/A/B/S1/t3"; + assertTrue( + src(d, tfqn).equals("Root/A/B/S1[pAID, b1]")); + assertTrue( + dest(d, tfqn).equals("Root/A/B/S1[pAID, b2]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/A/B/S1[pAID, (b1 = b2 => b1 else BID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[pAID, (b1 = b2 => b1 else BID)]" + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[pAID, (b1 = b2 => b1 else BID) - b2]", + "Root/A/B/S1[pAID, b2]" + }))); + } @Test - public void overall3() { - DashModule d = test("overall3"); + public void overall4() { + DashModule d = test("overall4"); String tfqn = "Root/A/B/S1/t1"; assertTrue( src(d, tfqn).equals("Root/A/B/S1[a1, b1]")); assertTrue( - dest(d, tfqn).equals("Root/A/S1[a2]")); + dest(d, tfqn).equals("Root/A/S2[a2]")); assertTrue( d.getScope(tfqn).toString() .equals("Root/A[(a1 = a2 => a1 else AID)]")); @@ -589,19 +629,19 @@ public void overall3() { exited(d,tfqn) .equals(ll(new String[]{ "Root/A/B/S1[(a1 = a2 => a1 else AID), BID]", - "Root/A/S1[(a1 = a2 => a1 else AID)]" + "Root/A/S2[(a1 = a2 => a1 else AID)]" }))); assertTrue( - enteredInContext(d,tfqn) + enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A/B/S1[AID - a2, BID]", - "Root/A/S1[a2]" + "Root/A/B/S1[(a1 = a2 => a1 else AID) - a2, BID]", + "Root/A/S2[a2]" }))); } - /* + @Test - public void overall4() { - DashModule d = test("overall4"); + public void overall5() { + DashModule d = test("overall5"); String tfqn = "Root/A/B/S1/t1"; assertTrue( src(d, tfqn).equals("Root/A/B/S1[a1, b1]")); @@ -616,12 +656,249 @@ public void overall4() { "Root/A/B/S1[(a1 = a2 => a1 else AID), BID]", }))); assertTrue( - enteredInContext(d,tfqn) + enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A/B/S1[AID - a2, BID]", - "Root/A/B/S1[a2, BID - b1]" - "Root/A/B/S1[a2, b1]" + "Root/A/B/S1[(a1 = a2 => a1 else AID) - a2, BID]", + "Root/A/B/S1[a2, BID]", }))); + + tfqn = "Root/t2"; + assertTrue( + src(d, tfqn).equals("Root/A/B/S1[a3, b3]")); + assertTrue( + dest(d, tfqn).equals("Root/A/B/S1[a4, b4]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/A/B/S1[(a3 = a4 => a3 else AID), (AND[a3 = a4, b3 = b4] => b3 else BID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[(a3 = a4 => a3 else AID), (AND[a3 = a4, b3 = b4] => b3 else BID)]", + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[(a3 = a4 => a3 else AID) - a4, BID]", + "Root/A/B/S1[a4, (AND[a3 = a4, b3 = b4] => b3 else BID) - b4]", + "Root/A/B/S1[a4, b4]" + }))); + + tfqn = "Root/t3"; + assertTrue( + src(d, tfqn).equals("Root/A/B/S1[a5, b5]")); + assertTrue( + dest(d, tfqn).equals("Root/A/B[a6, b6]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/A/B[(a5 = a6 => a5 else AID), (AND[a5 = a6, b5 = b6] => b5 else BID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[(a5 = a6 => a5 else AID), (AND[a5 = a6, b5 = b6] => b5 else BID)]", + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/A/B/S1[(a5 = a6 => a5 else AID) - a6, BID]", + "Root/A/B/S1[a6, (AND[a5 = a6, b5 = b6] => b5 else BID) - b6]", + "Root/A/B/S1[a6, b6]" + }))); } - */ + + @Test + public void overall6() { + DashModule d = test("overall6"); + String tfqn = "Root/B/S1/t1"; + assertTrue( + src(d, tfqn).equals("Root/B/S1[pBID]")); + assertTrue( + dest(d, tfqn).equals("Root/B[pBID]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/B[pBID]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/B/S1[pBID]", + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/B/S1[pBID]", + }))); + + tfqn = "Root/B/S1/t2"; + assertTrue( + src(d, tfqn).equals("Root/B/S1[pBID]")); + assertTrue( + dest(d, tfqn).equals("Root/B[b1]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/B[(pBID = b1 => pBID else BID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/B/S1[(pBID = b1 => pBID else BID)]", + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/B/S1[(pBID = b1 => pBID else BID) - b1]", + "Root/B/S1[b1]" + }))); + + tfqn = "Root/B/S1/t3"; + assertTrue( + src(d, tfqn).equals("Root/B/S1[pBID]")); + assertTrue( + dest(d, tfqn).equals("Root/C[]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root[]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/C[]", + "Root/B/S1[BID]" + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/C[]" + }))); + + } + + @Test + public void overall7() { + DashModule d = test("overall7"); + String tfqn = "Root/S1/t1"; + assertTrue( + src(d, tfqn).equals("Root/S1[]")); + assertTrue( + dest(d, tfqn).equals("Root/S1[]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/S1[]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/S1[]", + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/S1[]", + }))); + + tfqn = "Root/S1/t2"; + assertTrue( + src(d, tfqn).equals("Root/S1[]")); + assertTrue( + dest(d, tfqn).equals("Root/B[]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root[]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A[]", + "Root/B[]", + "Root/C[CID]", + "Root/S1[]", + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/A[]", + "Root/C[CID]", + "Root/B[]", + }))); + + tfqn = "Root/S1/t3"; + assertTrue( + src(d, tfqn).equals("Root/S1[]")); + assertTrue( + dest(d, tfqn).equals("Root/C[c1]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root[]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A[]", + "Root/B[]", + "Root/C[CID]", + "Root/S1[]", + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/C[CID - c1]", + "Root/A[]", + "Root/B[]", + "Root/C[c1]" + }))); + + } + @Test + public void overall8() { + DashModule d = test("overall8"); + String tfqn = "Root/t1"; + assertTrue( + src(d, tfqn).equals("Root/S3[]")); + assertTrue( + dest(d, tfqn).equals("Root/B/E/S2[e1]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root[]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/A/S1[AID]", + "Root/B/C[]", + "Root/B/D[]", + "Root/B/E/S2[EID]", + "Root/B/E/S4[EID]", + "Root/S3[]" + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/A/S1[AID]", + "Root/B/E/S4[EID - e1]", + "Root/B/C[]", + "Root/B/D[]", + "Root/B/E/S2[e1]" + }))); + } + + @Test + public void overall9() { + DashModule d = test("overall9"); + String tfqn = "Root/t1"; + assertTrue( + src(d, tfqn).equals("Root/B/E/F[e1, f1]")); + assertTrue( + dest(d, tfqn).equals("Root/B/E/G[e2]")); + assertTrue( + d.getScope(tfqn).toString() + .equals("Root/B/E[(e1 = e2 => e1 else EID)]")); + assertTrue( + exited(d,tfqn) + .equals(ll(new String[]{ + "Root/B/E/S2[(e1 = e2 => e1 else EID)]", + "Root/B/E/S4[(e1 = e2 => e1 else EID)]", + "Root/B/E/F[(e1 = e2 => e1 else EID), FID]", + "Root/B/E/G[(e1 = e2 => e1 else EID)]" + }))); + assertTrue( + enteredInScope(d,tfqn) + .equals(ll(new String[]{ + "Root/B/E/S4[(e1 = e2 => e1 else EID) - e2]", + "Root/B/E/F[e2, FID]", + "Root/B/E/G[e2]" + }))); + } + } diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext3.dsh deleted file mode 100644 index db988387f..000000000 --- a/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext3.dsh +++ /dev/null @@ -1,14 +0,0 @@ -state Root { - conc A [AID] { - conc B [BID] { - state S1 {} - } - } - conc C [CID] { - state S2 {} - } - trans t1 { - from Root/A/B/S1[a1,b1] - goto Root/C/S2[c1] - } -} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInScope2.dsh similarity index 100% rename from org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInContext2.dsh rename to org.alloytools.alloy.dash/src/test/resources/pass/getEnteredInScope2.dsh diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall1-traces.als b/org.alloytools.alloy.dash/src/test/resources/pass/overall1-traces.als new file mode 100644 index 000000000..3eaf29073 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall1-traces.als @@ -0,0 +1,60 @@ +open util/ordering[Snapshot] as Snapshot +abstract sig StateLabel {} +abstract sig Root extends StateLabel {} +abstract sig Root_A extends Root {} +abstract sig Root_A_B extends Root_A {} +one sig Root_A_B_S1 extends Root_A_B {} +abstract sig Root_C extends Root {} +one sig Root_C_S2 extends Root_C {} + +abstract sig TransitionLabel {} +one sig Root_t1 extends TransitionLabel {} + +abstract sig Identifiers {} +sig AID extends Identifiers {} +sig BID extends Identifiers {} +sig CID extends Identifiers {} + +sig Snapshot { + taken0 : set TransitionLabel, + conf0 : set StateLabel, + conf1 : Identifiers -> StateLabel, + conf2 : Identifiers -> Identifiers -> StateLabel, + stable : one boolean/Bool +} + +pred Root_t1_pre[s : one Snapshot] { + +} + + +pred Root_t1_post[s : one Snapshot, sNext : one Snapshot] { + sNext. (conf0) = s. (conf0) + sNext. (conf1) = { { s. (conf1) - Root/C/S2 } + Root/C/S2 + Root/C/S2 } + sNext. (conf2) = { { s. (conf2) - { AID -> Root/A/B/S1 } } + { AID -> Root/A/B/S1 } } +} + +pred Root_t1_semantics[s : one Snapshot, sNext : one Snapshot] { + (stable = boolean/True => + sNext. (taken0) = Root_t1 + else { + sNext. (taken0) = { s. (taken0) + Root_t1 } } +) +} + + +pred Root_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { + +} + + +pred Root_t1[s : one Snapshot, sNext : one Snapshot] { + s. (Root_t1_pre) + sNext. (s. (Root_t1_post)) + sNext. (s. (Root_t1_semantics)) +} + +pred small_step[s : one Snapshot, sNext : one Snapshot] { + (some pAID: one AID,pBID: one BID,pCID: one CID | { sNext. (s. (Root_t1)) }) +} + diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh index be361b9ed..db988387f 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh @@ -1,12 +1,14 @@ state Root { conc A [AID] { conc B [BID] { - state S1 { - trans t1 { - goto Root/A/S1[a2] - } - } + state S1 {} } - default state S1 {} + } + conc C [CID] { + state S2 {} + } + trans t1 { + from Root/A/B/S1[a1,b1] + goto Root/C/S2[c1] } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall2.dsh index e06607e00..0e7679a62 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall2.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall2.dsh @@ -1,12 +1,12 @@ state Root { conc A [AID] { conc B [BID] { - state S1 {} - } - default state S2 { - trans t1 { - goto Root/A/B/S1[a1,b1] + state S1 { + trans t1 { + goto Root/A/S2[a2] + } } } + default state S2 {} } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh index c5f2fcc26..63f0cd76b 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh @@ -1,14 +1,18 @@ state Root { conc A [AID] { - default conc B [BID] { + conc B [BID] { state S1 { - trans t1 { - from Root/A/B/S1[a1,b1] - goto Root/A/S1[a2] + trans t2 {} + trans t3 { + from Root/A/B/S1[pAID, b1] + goto Root/A/B/S1[pAID, b2] } } } - state S1 {} + default state S2 { + trans t1 { + goto Root/A/B/S1[a1,b1] + } + } } - } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall4-traces.als b/org.alloytools.alloy.dash/src/test/resources/pass/overall4-traces.als new file mode 100644 index 000000000..a37d4bb76 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall4-traces.als @@ -0,0 +1,66 @@ +open util/ordering[Snapshot] as Snapshot +abstract sig StateLabel {} +sig Root extends StateLabel {} +one sig Root_A extends Root {} +one sig Root_A_B extends Root_A {} +one sig Root_A_B_S1 extends Root_A_B {} +one sig Root_A_S2 extends Root_A {} + +abstract sig Identifiers {} +sig AID extends Identifiers {} +sig BID extends Identifiers {} + +sig Snapshot { + scopesUsed0 : set StateLabel, + conf0 : set StateLabel, + scopesUsed1 : Identifiers -> Identifiers -> StateLabel, + conf1 : Identifiers -> Identifiers -> StateLabel, + scopesUsed2 : Identifiers -> Identifiers -> Identifiers -> StateLabel, + conf2 : Identifiers -> Identifiers -> Identifiers -> StateLabel, + stable : one boolean/Bool +} + +pred Root_A_B_S1_t1_pre[s : one Snapshot, pAID : one AID, pBID : one BID] { + { b1 -> a1 -> Root/A/B/S1 } in s. (conf2) + ! {Root in scopesUsed0} + ! {{ (a1 = a2 => a1 else { AID } ) -> Root/A } in scopesUsed1} +} + + +pred Root_A_B_S1_t1_post[s : one Snapshot, sNext : one Snapshot, pAID : one AID, pBID : one BID] { + sNext. (conf0) = s. (conf0) + sNext. (conf1) = { { s. (conf1) - { (a1 = a2 => a1 else { AID } ) -> Root/A/S2 } } + { a2 -> Root/A/S2 } } + sNext. (conf2) = { { s. (conf2) - { BID -> (a1 = a2 => a1 else { AID } ) -> Root/A/B/S1 } } + { BID -> { (a1 = a2 => + a1 + else { + AID } +) - a2 } -> Root/A/B/S1 } } + sNext. (conf0) = s. (conf0) + sNext. (conf1) = { s. (conf1) + { (a1 = a2 => a1 else { AID } ) -> Root/A } } + sNext. (conf2) = s. (conf2) +} + +pred Root_A_B_S1_t1_semantics[s : one Snapshot, sNext : one Snapshot, pAID : one AID, pBID : one BID] { + (stable = boolean/True => + sNext. (scopesUsed2) = { BID -> AID -> Root_A_B_S1_t1 } + else { + sNext. (scopesUsed2) = { s. (scopesUsed2) + { AID -> BID -> Root_A_B_S1_t1 } } } +) +} + + +pred Root_A_B_S1_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, pAID : one AID, pBID : one BID, t : one TransitionLabel] { + +} + + +pred Root_A_B_S1_t1[s : one Snapshot, sNext : one Snapshot, pAID : one AID, pBID : one BID] { + pBID. (pAID. (s. (Root_A_B_S1_t1_pre))) + pBID. (pAID. (sNext. (s. (Root_A_B_S1_t1_post)))) + pBID. (pAID. (sNext. (s. (Root_A_B_S1_t1_semantics)))) +} + +pred small_step[s : one Snapshot, sNext : one Snapshot] { + (some pAID: one AID,pBID: one BID | { pBID. (pAID. (sNext. (s. (Root_A_B_S1_t1)))) }) +} + diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall4.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall4.dsh index 75b111966..4807a6004 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall4.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall4.dsh @@ -1,12 +1,14 @@ state Root { conc A [AID] { - conc B [BID] { + default conc B [BID] { state S1 { trans t1 { - from Root/A/B/S1[a1, b1] - goto Root/A[a2] + from Root/A/B/S1[a1,b1] + goto Root/A/S2[a2] } } } + state S2 {} } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall5.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall5.dsh new file mode 100644 index 000000000..36c19df76 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall5.dsh @@ -0,0 +1,20 @@ +state Root { + conc A [AID] { + conc B [BID] { + state S1 { + trans t1 { + from Root/A/B/S1[a1, b1] + goto Root/A[a2] + } + } + } + } + trans t2 { + from Root/A/B/S1[a3,b3] + goto Root/A/B/S1[a4,b4] + } + trans t3 { + from Root/A/B/S1[a5,b5] + goto Root/A/B[a6,b6] + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall6.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall6.dsh new file mode 100644 index 000000000..5e37d585f --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall6.dsh @@ -0,0 +1,16 @@ +state Root { + default state C {} + conc B [BID] { + state S1 { + trans t1 { + goto Root/B[pBID] + } + trans t2 { + goto Root/B[b1] + } + trans t3 { + goto Root/C + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall7-traces.als b/org.alloytools.alloy.dash/src/test/resources/pass/overall7-traces.als new file mode 100644 index 000000000..472e3e809 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall7-traces.als @@ -0,0 +1,114 @@ +open util/ordering[Snapshot] as Snapshot +abstract sig StateLabel {} +abstract sig Root extends StateLabel {} +one sig Root_A extends Root {} +one sig Root_B extends Root {} +one sig Root_C extends Root {} +one sig Root_S1 extends Root {} + +abstract sig Identifiers {} +sig CID extends Identifiers {} + +sig Snapshot { + scopesUsed0 : set TransitionLabel, + conf0 : set StateLabel, + conf1 : Identifiers -> Identifiers -> StateLabel, + stable : one boolean/Bool +} + +pred Root_S1_t1_pre[s : one Snapshot] { + +} + + +pred Root_S1_t1_post[s : one Snapshot, sNext : one Snapshot] { + sNext. (conf0) = { { s. (conf0) - Root/S1 } + Root/S1 } + sNext. (conf1) = s. (conf1) +} + +pred Root_S1_t1_semantics[s : one Snapshot, sNext : one Snapshot] { + (stable = boolean/True => + sNext. (scopesUsed0) = Root_S1_t1 + else { + sNext. (scopesUsed0) = { s. (scopesUsed0) + Root_S1_t1 } } +) +} + + +pred Root_S1_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { + +} + + +pred Root_S1_t1[s : one Snapshot, sNext : one Snapshot] { + s. (Root_S1_t1_pre) + sNext. (s. (Root_S1_t1_post)) + sNext. (s. (Root_S1_t1_semantics)) +} + +pred Root_S1_t2_pre[s : one Snapshot] { + +} + + +pred Root_S1_t2_post[s : one Snapshot, sNext : one Snapshot] { + sNext. (conf0) = { { s. (conf0) - Root/A - Root/B - Root/S1 } + Root/A + Root/B } + sNext. (conf1) = { { s. (conf1) - { CID -> Root/C } } + { CID -> Root/C } } +} + +pred Root_S1_t2_semantics[s : one Snapshot, sNext : one Snapshot] { + (stable = boolean/True => + sNext. (scopesUsed0) = Root_S1_t2 + else { + sNext. (scopesUsed0) = { s. (scopesUsed0) + Root_S1_t2 } } +) +} + + +pred Root_S1_t2_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { + +} + + +pred Root_S1_t2[s : one Snapshot, sNext : one Snapshot] { + s. (Root_S1_t2_pre) + sNext. (s. (Root_S1_t2_post)) + sNext. (s. (Root_S1_t2_semantics)) +} + +pred Root_S1_t3_pre[s : one Snapshot] { + +} + + +pred Root_S1_t3_post[s : one Snapshot, sNext : one Snapshot] { + sNext. (conf0) = { { s. (conf0) - Root/A - Root/B - Root/S1 } + Root/A + Root/B } + sNext. (conf1) = { { s. (conf1) - { CID -> Root/C } } + { { CID - c1 } -> Root/C } + { c1 -> Root/C } } +} + +pred Root_S1_t3_semantics[s : one Snapshot, sNext : one Snapshot] { + (stable = boolean/True => + sNext. (scopesUsed0) = Root_S1_t3 + else { + sNext. (scopesUsed0) = { s. (scopesUsed0) + Root_S1_t3 } } +) +} + + +pred Root_S1_t3_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { + +} + + +pred Root_S1_t3[s : one Snapshot, sNext : one Snapshot] { + s. (Root_S1_t3_pre) + sNext. (s. (Root_S1_t3_post)) + sNext. (s. (Root_S1_t3_semantics)) +} + +pred small_step[s : one Snapshot, sNext : one Snapshot] { + (some pCID: one CID | { sNext. (s. (Root_S1_t1)) or + sNext. (s. (Root_S1_t2)) or + sNext. (s. (Root_S1_t3)) }) +} + diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall7.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall7.dsh new file mode 100644 index 000000000..e951638ff --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall7.dsh @@ -0,0 +1,20 @@ +state Root { + default conc A { + + } + default conc B { + + } + default conc C [CID] { + + } + state S1 { + trans t1 {} + trans t2 { + goto Root/B + } + trans t3 { + goto Root/C[c1] + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall8.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall8.dsh new file mode 100644 index 000000000..e8fdb22a1 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall8.dsh @@ -0,0 +1,18 @@ +state Root { + default conc A [AID] { + state S1 {} + } + default conc B { + conc C {} + conc D {} + conc E [EID]{ + state S2 {} + default state S4 {} + } + } + state S3 {} + trans t1 { + from Root/S3 + goto Root/B/E/S2[e1] + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall9-traces.als b/org.alloytools.alloy.dash/src/test/resources/pass/overall9-traces.als new file mode 100644 index 000000000..fe2942631 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall9-traces.als @@ -0,0 +1,71 @@ +open util/ordering[Snapshot] as Snapshot +abstract sig StateLabel {} +abstract sig Root extends StateLabel {} +abstract sig Root_A extends Root {} +one sig Root_A_S1 extends Root_A {} +abstract sig Root_B extends Root {} +one sig Root_B_C extends Root_B {} +one sig Root_B_D extends Root_B {} +abstract sig Root_B_E extends Root_B {} +one sig Root_B_E_S2 extends Root_B_E {} +one sig Root_B_E_S4 extends Root_B_E {} +one sig Root_B_E_F extends Root_B_E {} +one sig Root_B_E_G extends Root_B_E {} +one sig Root_S3 extends Root {} + +abstract sig Identifiers {} +sig FID extends Identifiers {} +sig EID extends Identifiers {} +sig AID extends Identifiers {} + +sig Snapshot { + scopesUsed0 : set TransitionLabel, + conf0 : set StateLabel, + conf1 : Identifiers -> Identifiers -> StateLabel, + conf2 : Identifiers -> Identifiers -> Identifiers -> StateLabel, + stable : one boolean/Bool +} + +pred Root_t1_pre[s : one Snapshot] { + +} + + +pred Root_t1_post[s : one Snapshot, sNext : one Snapshot] { + sNext. (conf0) = s. (conf0) + sNext. (conf1) = { { s. (conf1) - { (e1 = e2 => e1 else { EID } ) -> Root/B/E/S2 } - { (e1 = e2 => + e1 + else { + EID } +) -> Root/B/E/S4 } - { (e1 = e2 => e1 else { EID } ) -> Root/B/E/G } } + { { (e1 = e2 => + e1 + else { + EID } +) - e2 } -> Root/B/E/S4 } + { e2 -> Root/B/E/G } } + sNext. (conf2) = { { s. (conf2) - { FID -> (e1 = e2 => e1 else { EID } ) -> Root/B/E/F } } + { FID -> e2 -> Root/B/E/F } } +} + +pred Root_t1_semantics[s : one Snapshot, sNext : one Snapshot] { + (stable = boolean/True => + sNext. (scopesUsed0) = Root_t1 + else { + sNext. (scopesUsed0) = { s. (scopesUsed0) + Root_t1 } } +) +} + + +pred Root_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { + +} + + +pred Root_t1[s : one Snapshot, sNext : one Snapshot] { + s. (Root_t1_pre) + sNext. (s. (Root_t1_post)) + sNext. (s. (Root_t1_semantics)) +} + +pred small_step[s : one Snapshot, sNext : one Snapshot] { + (some pFID: one FID,pEID: one EID,pAID: one AID | { sNext. (s. (Root_t1)) }) +} + diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall9.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall9.dsh new file mode 100644 index 000000000..95708acfd --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall9.dsh @@ -0,0 +1,20 @@ +state Root { + default conc A [AID] { + state S1 {} + } + default conc B { + conc C {} + conc D {} + conc E [EID]{ + state S2 {} + default state S4 {} + conc F [FID] {} + conc G {} + } + } + state S3 {} + trans t1 { + from Root/B/E/F[e1,f1] + goto Root/B/E/G[e2] + } +} \ No newline at end of file From 44d0311c1a58fa27bc428906dd93040803b31af5 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 25 Apr 2023 12:48:54 -0400 Subject: [PATCH 029/129] adding event/var/buffer decls --- .../watform/dash4whole/DashMainTest.java | 2 +- .../watform/ast/DashBufferDecls.java | 9 +++ .../uwaterloo/watform/ast/DashEventDecls.java | 6 ++ .../ca/uwaterloo/watform/ast/DashState.java | 72 +++++++++++++++++-- .../ca/uwaterloo/watform/ast/DashTrans.java | 2 +- .../uwaterloo/watform/ast/DashVarDecls.java | 10 ++- .../ca/uwaterloo/watform/core/DashErrors.java | 24 +++++++ .../uwaterloo/watform/core/DashUtilFcns.java | 3 +- .../uwaterloo/watform/parser/BufferTable.java | 64 +++++++++++++++++ .../uwaterloo/watform/parser/DashModule.java | 56 ++++++++++----- .../uwaterloo/watform/parser/EventTable.java | 57 +++++++++++++++ .../uwaterloo/watform/parser/StateTable.java | 12 ++-- .../uwaterloo/watform/parser/TransTable.java | 4 +- .../ca/uwaterloo/watform/parser/VarTable.java | 64 +++++++++++++++++ 14 files changed, 349 insertions(+), 36 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/BufferTable.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java index 0d7a0d8f6..57d235bf4 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/DashMainTest.java @@ -49,7 +49,7 @@ public static void main(String args[]) { if (args.length == 2) { // transition name d.debug(args[1]); - } + } else d.debug(); } /* DashModule d = diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java index 45cb8ff1a..f0f12940c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java @@ -37,4 +37,13 @@ public String toString() { s += sj.toString() + ":" + DashStrings.bufName + "[" + element + "]\n"; return s; } + public List getNames() { + return names; + } + public String getElement() { + return element; + } + public DashStrings.IntEnvKind getKind() { + return kind; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java index 132a3cdf6..bfd8ac1b7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEventDecls.java @@ -31,4 +31,10 @@ public String toString() { s += DashStrings.eventName + " " + sj.toString() +"{ }\n"; return s; } + public List getNames() { + return names; + } + public DashStrings.IntEnvKind getKind() { + return kind; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index b567fd5b7..24f9ebedd 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -17,6 +17,9 @@ import ca.uwaterloo.watform.alloyasthelper.ExprHelper; import ca.uwaterloo.watform.parser.StateTable; import ca.uwaterloo.watform.parser.TransTable; +import ca.uwaterloo.watform.parser.EventTable; +import ca.uwaterloo.watform.parser.VarTable; +import ca.uwaterloo.watform.parser.BufferTable; public class DashState extends Dash { @@ -120,10 +123,10 @@ public static List noSubstates() { * and put all states in the state table * also set this state's fqn here */ - public void resolveAllStates(StateTable st, List params, List ances) { + public void resolveAllStates(StateTable st, EventTable et, VarTable vt, BufferTable bt, List params, List ances) { if (DashFQN.alreadyFQN(name)) DashErrors.stateNameCantBeFQN(pos, name); sfqn = DashFQN.fqn(ances,name); - System.out.println("Resolving state "+sfqn); + //System.out.println("Resolving state "+sfqn); // process the children // have to make a copy so that recursion does not just @@ -159,7 +162,7 @@ public void resolveAllStates(StateTable st, List params, List an st.add(sfqn,kind, param, newParams,def, DashFQN.fqn(ances), childFQNs); // add all substates to the table - for (DashState s: substatesList) s.resolveAllStates(st, newParams, newAnces); + for (DashState s: substatesList) s.resolveAllStates(st, et, vt, bt, newParams, newAnces); // make sure defaults are correct // if there's only one child it is automatically the default @@ -200,6 +203,63 @@ public void resolveAllStates(StateTable st, List params, List an } } + // add declared events + List eventDeclsList = new ArrayList(); + if (items != null) + eventDeclsList = + items.stream() + .filter(i -> i instanceof DashEventDecls) + .map(p -> (DashEventDecls) p) + .collect(Collectors.toList()); + // put in event table with FQN + for (DashEventDecls e:eventDeclsList) { + DashStrings.IntEnvKind k = e.getKind(); + for (String x: e.getNames()) { + if (DashFQN.alreadyFQN(x)) DashErrors.eventNameCantBeFQN(e.getPos(), x); + String xfqn = DashFQN.fqn(sfqn,x); + if (!et.add(xfqn,k, newParams)) DashErrors.duplicateEventName(e.getPos(),x); + } + } + + // add declared variables + List varDeclsList = new ArrayList(); + if (items != null) + varDeclsList = + items.stream() + .filter(i -> i instanceof DashVarDecls) + .map(p -> (DashVarDecls) p) + .collect(Collectors.toList()); + // put in var table with FQN + for (DashVarDecls v:varDeclsList) { + DashStrings.IntEnvKind k = v.getKind(); + Expr t = v.getTyp(); + for (String x: v.getNames()) { + if (DashFQN.alreadyFQN(x)) DashErrors.varNameCantBeFQN(v.getPos(), x); + String xfqn = DashFQN.fqn(sfqn,x); + if (!vt.add(xfqn,k, newParams, t)) DashErrors.duplicateVarName(v.getPos(),x); + } + } + + // add declared buffers + List bufferDeclsList = new ArrayList(); + if (items != null) + bufferDeclsList = + items.stream() + .filter(i -> i instanceof DashBufferDecls) + .map(p -> (DashBufferDecls) p) + .collect(Collectors.toList()); + // put in var table with FQN + for (DashBufferDecls b:bufferDeclsList) { + DashStrings.IntEnvKind k = b.getKind(); + String el = b.getElement(); + for (String x: b.getNames()) { + if (DashFQN.alreadyFQN(x)) DashErrors.bufferNameCantBeFQN(b.getPos(), x); + String xfqn = DashFQN.fqn(sfqn,x); + if (!bt.add(xfqn,k, newParams, el)) DashErrors.duplicateBufferName(b.getPos(),x); + } + } + + /* // set the pathtohere and params of variables @@ -266,7 +326,7 @@ public void resolveAllTrans(StateTable st, TransTable tt) { .filter(i -> i instanceof DashFrom) .map(p -> ((DashFrom) p).src) .collect(Collectors.toList()); - System.out.println(fromList); + //System.out.println(fromList); DashRef src = setSrcDest("from", fromList, st, sfqn, tfqn); assert(src != null); st.add(src.getName()); @@ -276,7 +336,7 @@ public void resolveAllTrans(StateTable st, TransTable tt) { .filter(i -> i instanceof DashGoto) .map(p -> ((DashGoto) p).dest) .collect(Collectors.toList()); - System.out.println(gotoList); + //System.out.println(gotoList); DashRef dest = setSrcDest("goto", gotoList, st, sfqn, tfqn); assert(dest != null); st.add(dest.getName()); @@ -364,7 +424,7 @@ public DashRef setSrcDest(String xType, List ll, StateTable st, String for (String s:st.getRegion(parentFQN)) { if (x.getName().equals(DashFQN.chopNameFromFQN(s))) matches.add(s); } - System.out.println("matches: " + matches); + //System.out.println("matches: " + matches); if (matches.size() > 1) { DashErrors.ambiguousSrcDest(xType, tfqn); return null; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java index 51032325d..60b1d1260 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java @@ -37,7 +37,7 @@ public String toString() { } public void resolveAll(StateTable st, TransTable tt, List params, List ances) { String tfqn = DashFQN.fqn(ances,name); - System.out.println("Resolving trans "+tfqn); + //System.out.println("Resolving trans "+tfqn); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java index f392de941..9c960ee7b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashVarDecls.java @@ -24,7 +24,6 @@ public DashVarDecls (Pos pos, List n, Expr e, DashStrings.IntEnvKind k) this.kind = k; } - public String toString() { String s = new String(""); if (kind == DashStrings.IntEnvKind.ENV) { @@ -34,4 +33,13 @@ public String toString() { names.forEach(n -> sj.add(n)); return s + sj.toString() + ":" + typ.toString() + "\n"; } + public List getNames() { + return names; + } + public Expr getTyp() { + return typ; + } + public DashStrings.IntEnvKind getKind() { + return kind; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 405db2508..ef7a8afa5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -71,6 +71,30 @@ public static void ambiguousSrcDest(String x, String tfqn) throws Err { } // below this have not been tested + public static String eventNameCantBeFQNMsg = "Event name cannot be fully qualified at declaration: "; + public static void eventNameCantBeFQN(Pos o, String s) { + throw new ErrorSyntax(o, eventNameCantBeFQNMsg + s); + } + public static String duplicateEventNameMsg = "Event name already in use: "; + public static void duplicateEventName(Pos o, String s) { + throw new ErrorSyntax(o, duplicateEventNameMsg + s); + } + public static String varNameCantBeFQNMsg = "Var name cannot be fully qualified at declaration: "; + public static void varNameCantBeFQN(Pos o, String s) { + throw new ErrorSyntax(o, varNameCantBeFQNMsg + s); + } + public static String duplicateVarNameMsg = "Var name already in use: "; + public static void duplicateVarName(Pos o, String s) { + throw new ErrorSyntax(o, duplicateVarNameMsg + s); + } + public static String bufferNameCantBeFQNMsg = "Buffer name cannot be fully qualified at declaration: "; + public static void bufferNameCantBeFQN(Pos o, String s) { + throw new ErrorSyntax(o, bufferNameCantBeFQNMsg + s); + } + public static String duplicateBufferNameMsg = "Buffer name already in use: "; + public static void duplicateBufferName(Pos o, String s) { + throw new ErrorSyntax(o, duplicateBufferNameMsg + s); + } public static void siblingsSameKind(String fqn) throws Err { throw new ErrorSyntax("Children of "+fqn+" must all be of concurrent or not concurrent"); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java index 6584ccc6d..b28c2098b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java @@ -64,6 +64,7 @@ public static T lastElement(List ll) { } public static List allButLast(List ll) { - return ll.subList(0,ll.size()-1); + if (ll.isEmpty()) return ll; + else return ll.subList(0,ll.size()-1); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/BufferTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/BufferTable.java new file mode 100644 index 000000000..181c3d08b --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/BufferTable.java @@ -0,0 +1,64 @@ +package ca.uwaterloo.watform.parser; + +import java.util.List; +import java.util.ArrayList; +import java.util.HashMap; + +import edu.mit.csail.sdg.ast.Expr; + + +import static ca.uwaterloo.watform.core.DashUtilFcns.*; +import static ca.uwaterloo.watform.core.DashStrings.*; + +public class BufferTable { + + // stores Buffer Decls in a HashMap based on the buffer FQN + + private HashMap table; + + + public class BufferElement { + private IntEnvKind kind; + private List params; + private String element; + + public BufferElement( + IntEnvKind k, + List prms, + String e) { + assert(prms != null); + this.kind = k; + this.params = prms; + this.element = e; + } + public String toString() { + String s = new String(); + s += "kind: "+kind+"\n"; + s += "params: "+ NoneStringIfNeeded(params) +"\n"; + s += "element: "+element.toString() + "\n"; + return s; + } + } + + public BufferTable() { + this.table = new HashMap(); + + } + public String toString() { + String s = new String("BUFFER TABLE\n"); + for (String k:table.keySet()) { + s += " ----- \n"; + s += k + "\n"; + s += table.get(k).toString(); + } + return s; + } + public Boolean add(String vfqn, IntEnvKind k, List prms, String el) { + assert(prms!=null); + if (table.containsKey(vfqn)) return false; + else { table.put(vfqn, new BufferElement(k,prms, el)); return true; } + } + public void resolveAllBufferTable() { + // TODO + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 7ba115c64..d7307a089 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -44,6 +44,9 @@ public class DashModule extends CompModuleHelper { private SymbolTable symbolTable; private StateTable stateTable = new StateTable(); private TransTable transTable = new TransTable(); + private EventTable eventTable = new EventTable(); + private VarTable varTable = new VarTable(); + private BufferTable bufferTable = new BufferTable(); // once created and parsed, the following are // the phases of a DashModule @@ -195,7 +198,7 @@ public String toStringAlloy() { // needed during parsing ------------------------- public void importModules(List bufElements, List bufNames) { - System.out.println("Adding open stmts"); + //System.out.println("Adding open stmts"); String noAlias = null; booleanOpen = this.addOpenSimple(DashStrings.utilBooleanName, null, noAlias); if (DashOptions.isTcmc) @@ -375,30 +378,38 @@ public List onlyConc(List dr) { } public List scopesUsed(String tfqn) { DashRef scope = getScope(tfqn); - List aP = onlyConc(allPrefixDashRefs(scope)); + List aP = allPrefixDashRefs(scope); + List aPc = onlyConc(aP); List r = new ArrayList(); List prms; Expr e; Expr p; - for (DashRef s: allButLast(aP)) { - // if a prefix scope includes all param values, it really - // is the scope - if (isAnd(s.getName()) && stateTable.hasParam(s.getName())) { - prms = new ArrayList(allButLast(s.getParamValues())); - e = lastElement(s.getParamValues()); - p = createITE(createEquals(e,createVar(stateTable.getParam(s.getName()))), - createVar(stateTable.getParam(s.getName())), - createNone()); - prms.add(p); - r.add(new DashRef(s.getName(), prms)); + if (aPc.isEmpty()) { + // no concurrent states in scope prefix + // so just add root + r.add(aP.get(0)); + } else { + for (DashRef s: allButLast(aPc)) { + // if a prefix scope includes all param values, it really + // is the scope + if (isAnd(s.getName()) && stateTable.hasParam(s.getName())) { + prms = new ArrayList(allButLast(s.getParamValues())); + e = lastElement(s.getParamValues()); + p = createITE(createEquals(e,createVar(stateTable.getParam(s.getName()))), + createVar(stateTable.getParam(s.getName())), + createNone()); + prms.add(p); + r.add(new DashRef(s.getName(), prms)); + } } + // if it has a parameter it will be included + r.add(lastElement(aPc)); } - r.add(lastElement(aP)); return r; } public List nonOrthogonalScopesOf(String tfqn) { DashRef scope = getScope(tfqn); - System.out.println(allPrefixDashRefs(scope)); + //System.out.println(allPrefixDashRefs(scope)); List aP = allPrefixDashRefs(scope); // always needs to include Root List r = new ArrayList(); @@ -408,9 +419,17 @@ public List nonOrthogonalScopesOf(String tfqn) { } // processes --------------------------------------- + public void debug() { + System.out.println(stateTable.toString()); + System.out.println(transTable.toString()); + System.out.println(eventTable.toString()); + System.out.println(varTable.toString()); + } public void debug(String tfqn) { System.out.println(stateTable.toString()); System.out.println(transTable.toString()); + System.out.println(eventTable.toString()); + System.out.println(varTable.toString()); for (String x: getTransNames()) { // System.out.println(tfqn +" scope :" + getScope(x)); } @@ -432,7 +451,7 @@ public void debug(String tfqn) { // should we use the rep arg here? public void resolveAllDash(A4Reporter rep) { - System.out.println("Resolving Dash"); + //System.out.println("Resolving Dash"); if (roots.isEmpty()) { DashErrors.noStates(); } else if (roots.size() > 1) { @@ -441,13 +460,14 @@ public void resolveAllDash(A4Reporter rep) { root = roots.get(0); // passed with empty set of params, empty set of ancestors stateTable.setRoot(root.name); - root.resolveAllStates(stateTable,new ArrayList(),new ArrayList()); + root.resolveAllStates(stateTable,eventTable, varTable, bufferTable, new ArrayList(),new ArrayList()); // have to do states first so siblings of trans parent state // are in place to search for src/dest root.resolveAllTrans(stateTable,transTable); // if root has no substates? // if no transitions? stateTable.resolveAll(getRootName()); + // TODO will need eventTable transTable.resolveAll(); maxDepthParams = stateTable.getMaxDepthParams(); //transAtThisParamDepth = new boolean[maxDepthParams+1]; @@ -477,7 +497,7 @@ public void resolveAllAlloy(A4Reporter rep) { // so here we cast DashModule to CompModule and ignore the // output CompModule //assert(status == Status.TRANSLATED_TO_ALLOY); - System.out.println("Resolving Alloy"); + //System.out.println("Resolving Alloy"); // this quits if it throws an error //resolveAll(rep == null ? A4Reporter.NOP : rep, this); // if no errors diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java new file mode 100644 index 000000000..043df1565 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -0,0 +1,57 @@ +package ca.uwaterloo.watform.parser; + +import java.util.List; +import java.util.ArrayList; +import java.util.HashMap; + +import static ca.uwaterloo.watform.core.DashUtilFcns.*; +import static ca.uwaterloo.watform.core.DashStrings.*; + +public class EventTable { + + // stores Event Decls in a HashMap based on the event FQN + + private HashMap table; + + + public class EventElement { + private IntEnvKind kind; + private List params; + + public EventElement( + IntEnvKind k, + List prms) { + assert(prms != null); + this.kind = k; + this.params = prms; + } + public String toString() { + String s = new String(); + s += "kind: "+kind+"\n"; + s += "params: "+ NoneStringIfNeeded(params) +"\n"; + return s; + } + } + + public EventTable() { + this.table = new HashMap(); + + } + public String toString() { + String s = new String("EVENT TABLE\n"); + for (String k:table.keySet()) { + s += " ----- \n"; + s += k + "\n"; + s += table.get(k).toString(); + } + return s; + } + public Boolean add(String efqn, IntEnvKind k, List prms) { + assert(prms!=null); + if (table.containsKey(efqn)) return false; + else { table.put(efqn, new EventElement(k,prms)); return true; } + } + public void resolveAllEventTable() { + // TODO + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 3f4556ed6..e69a1b032 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -164,7 +164,7 @@ public void add(String fqn) { assert(!fqn.isEmpty()); if (!table.containsKey(fqn)) table.put(fqn,null); - System.out.println("adding State table: "+fqn); + //System.out.println("adding State table: "+fqn); } public void add( String fqn, @@ -186,7 +186,7 @@ else if (!se.attributesSame(k,prm,prms,d,p,iChildren)) } else table.put(fqn, new StateElement(k,prm, prms,d,p,iChildren)); - System.out.println("adding to State table: "+fqn+space+prm + space + prms+space+d+space+p+iChildren); + //System.out.println("adding to State table: "+fqn+space+prm + space + prms+space+d+space+p+iChildren); } public boolean containsKey(String s) { @@ -338,7 +338,7 @@ public List getAllParams() { return DashUtilFcns.setToList(allParams); } public void resolveAll(String root) { - System.out.println("Resolving state table"); + //System.out.println("Resolving state table"); for (String k: table.keySet()) if (table.get(k) == null) DashErrors.transUsesNonExistentState(k); // walk down parent to children and pass back info @@ -425,8 +425,8 @@ The param values of context (from the scope) could be a set of param values or t public List getLeafStatesEnteredInScope(DashRef context, DashRef dest) { List cR = allPrefixDashRefs(context); List dR = allPrefixDashRefs(dest); - System.out.println("cR: "+cR); - System.out.println("dR: "+dR); + //System.out.println("cR: "+cR); + //System.out.println("dR: "+dR); // cR is a prefix of dR but possibly with different param values // enter all the possible side concurrent regions of the scope(context) List r = new ArrayList(); // result @@ -489,7 +489,7 @@ public List getLeafStatesEnteredInScope(DashRef context, DashRef dest) } // if its an OR state, just go on to the next one } - System.out.println("r "+r); + //System.out.println("r "+r); r.addAll(getLeafStatesEntered(dest)); return r; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 3db9f05be..12fbc5846 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -98,7 +98,7 @@ public void add( List se) { */ { - System.out.println("Adding "+fqn); + //System.out.println("Adding "+fqn); assert(!fqn.isEmpty()); assert(params != null ); assert(s != null); @@ -178,7 +178,7 @@ public List getNotOrthogonalTransAbove(String t) { } */ public void resolveAll() { - System.out.println("Resolving trans table"); + //System.out.println("Resolving trans table"); if (getTransNames().isEmpty()) DashErrors.noTrans(); isResolved = true; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java new file mode 100644 index 000000000..89c641d14 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -0,0 +1,64 @@ +package ca.uwaterloo.watform.parser; + +import java.util.List; +import java.util.ArrayList; +import java.util.HashMap; + +import edu.mit.csail.sdg.ast.Expr; + + +import static ca.uwaterloo.watform.core.DashUtilFcns.*; +import static ca.uwaterloo.watform.core.DashStrings.*; + +public class VarTable { + + // stores Var Decls in a HashMap based on the event FQN + + private HashMap table; + + + public class VarElement { + private IntEnvKind kind; + private List params; + private Expr typ; + + public VarElement( + IntEnvKind k, + List prms, + Expr t) { + assert(prms != null); + this.kind = k; + this.params = prms; + this.typ = t; + } + public String toString() { + String s = new String(); + s += "kind: "+kind+"\n"; + s += "params: "+ NoneStringIfNeeded(params) +"\n"; + s += "typ: "+typ.toString() + "\n"; + return s; + } + } + + public VarTable() { + this.table = new HashMap(); + + } + public String toString() { + String s = new String("VAR TABLE\n"); + for (String k:table.keySet()) { + s += " ----- \n"; + s += k + "\n"; + s += table.get(k).toString(); + } + return s; + } + public Boolean add(String vfqn, IntEnvKind k, List prms, Expr t) { + assert(prms!=null); + if (table.containsKey(vfqn)) return false; + else { table.put(vfqn, new VarElement(k,prms, t)); return true; } + } + public void resolveAllVarTable() { + // TODO + } +} \ No newline at end of file From 0d9ad96ff57e3ee609b13213850abfbf990c78b2 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 2 May 2023 10:56:50 -0400 Subject: [PATCH 030/129] working on Alloy translation --- .../parser/Dash-cup-grammar.txt | 46 +- .../parser/Dash-cup-imports.txt | 4 +- org.alloytools.alloy.dash/parser/Dash.cup | 50 +- .../watform/alloyasthelper/ExprHelper.java | 121 ++- .../watform/alloyasthelper/ExprToString.java | 57 +- .../java/ca/uwaterloo/watform/ast/DashOn.java | 27 +- .../ca/uwaterloo/watform/ast/DashSend.java | 28 +- .../ca/uwaterloo/watform/ast/DashState.java | 363 ++------- .../ca/uwaterloo/watform/ast/DashTrans.java | 58 +- .../ca/uwaterloo/watform/core/DashErrors.java | 76 +- .../ca/uwaterloo/watform/core/DashFQN.java | 94 ++- .../ca/uwaterloo/watform/core/DashRef.java | 173 ++++- .../uwaterloo/watform/core/DashStrings.java | 14 +- .../watform/dashtoalloy/AddSmallStep.java | 57 ++ .../dashtoalloy/AddSnapshotSignature.java | 118 +++ .../dashtoalloy/AddSpaceSignatures.java | 103 +++ .../dashtoalloy/AddTestIfNextStable.java | 56 ++ .../watform/dashtoalloy/AddTrans.java | 63 ++ .../AddTransIsEnabledAfterStep.java | 139 ++++ .../watform/dashtoalloy/AddTransPost.java | 223 ++++++ .../watform/dashtoalloy/AddTransPre.java | 101 +++ .../uwaterloo/watform/dashtoalloy/Common.java | 220 ++++++ .../watform/dashtoalloy/DashToAlloy.java | 706 +----------------- .../watform/parser/CompModuleHelper.java | 8 +- .../uwaterloo/watform/parser/DashModule.java | 71 +- .../uwaterloo/watform/parser/EventTable.java | 49 ++ .../uwaterloo/watform/parser/StateTable.java | 88 ++- .../uwaterloo/watform/parser/TransTable.java | 339 +++++++-- .../alloy/dash/DashCoreFQNTests.java | 25 + .../alloytools/alloy/dash/DashEventTests.java | 74 ++ .../alloytools/alloy/dash/DashStateTests.java | 78 +- .../alloy/dash/DashWffFailTests.java | 11 +- .../src/test/resources/pass/event1.dsh | 7 + .../src/test/resources/pass/event2.dsh | 5 + .../src/test/resources/pass/event3.dsh | 6 + .../src/test/resources/pass/overall1.dsh | 2 + .../overall10.dsh} | 1 - .../overall11.dsh} | 2 +- .../overall12.dsh} | 1 - .../src/test/resources/wfffail/test11.dsh | 17 + .../resources/{pass => wfffail}/test2.dsh | 2 +- .../src/test/resources/wfffail/test3.dsh | 7 +- 42 files changed, 2437 insertions(+), 1253 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTrans.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java create mode 100644 org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashEventTests.java create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/event1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/event2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/event3.dsh rename org.alloytools.alloy.dash/src/test/resources/{wfffail/unknownSrcDest1.dsh => pass/overall10.dsh} (51%) rename org.alloytools.alloy.dash/src/test/resources/{wfffail/unknownSrcDest2.dsh => pass/overall11.dsh} (55%) rename org.alloytools.alloy.dash/src/test/resources/{wfffail/unknownSrcDest3.dsh => pass/overall12.dsh} (72%) create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/test11.dsh rename org.alloytools.alloy.dash/src/test/resources/{pass => wfffail}/test2.dsh (84%) diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt index b733dc9a5..4d050f61b 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -271,7 +271,7 @@ TransItemList ::= TransItemList:c TransItem:x {: c.add(x); RESULT = c; :}; //Exprp is non-empty list of comma-separated Expr - +//Exprs could be empty ist of comma-separated Expr TransItem ::= FROM:o Name:n {: RESULT = new DashFrom(o, new DashRef(o, n.label,DashRef.emptyParamValuesList())); :}; @@ -286,8 +286,15 @@ TransItem ::= GOTO:o Name:n LBRACKET Exprp:e RBRACKET RESULT = new DashGoto(o, new DashRef(o, n.label,e)); :}; -TransItem ::= ON:o Expr:e - {: RESULT = new DashOn(o, e); :}; +// this allows "on x.ev1", "on A/ev1[x]" and "on n" in parsing but will have to sort out later to see if correct +TransItem ::= ON:o Expr:v + {: RESULT = new DashOn(o, v); :}; + +//TransItem ::= ON:o Name:n +// {: //RESULT = new DashOn(o, new DashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; + +//TransItem ::= ON:o Name:n LBRACKET Expr:b RBRACKET +// {: //RESULT = new DashOn(o, new DashRef(o,n.label,e) ); :}; TransItem ::= WHEN:o Expr:v {: RESULT = new DashWhen(o, v); :}; @@ -295,28 +302,35 @@ TransItem ::= WHEN:o Expr:v TransItem ::= DO:o Expr:v {: RESULT = new DashDo(o, v); :}; - - - // this allows Send x.ev1 and "Send n" in parsing but will have to sort out later to see if correct TransItem ::= SEND:o Expr:v {: RESULT = new DashSend(o, v); :}; - -// DASH PLUS PROCESS VARIABLE REFERENCE -// ParamConcState[Param]/Variable -// result Param.ParamConcState/Variable -// not sure why a BadJoin is used here; but Alloy parsing rules use ExprBadJoins, not ExprJoins + +//TransItem ::= SEND:o Name:n +// {: RESULT = new DashSend(o, new DashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; + +//TransItem ::= SEND:o Name:n LBRACKET Exprp:e RBRACKET +// {: RESULT = new DashSend(o, new DashRef(o,n.label,e) ); :}; + +// DASH PLUS PROCESS REFERENCE +// in Alloy can't have a "/Variable" in the following so we need more syntax +// A/B/C[ParamValue1, ParamValue2]/Variable +// result ParamValue2.ParamValue1.A/B/C/Variable (using BadJoins) // note PRIME is a special token in grammar and we want to support v' + BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e {: - if (b.size() > 1) DashErrors.crossRefMoreThanOneArg(o,e.label); - RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label)); + Expr r = ExprVar.make(o, a.toString() + '/' + e.label); + Collections.reverse(b); + for (Expr x:b) r = ExprBinary.Op.JOIN.make(o,null, x, r); + RESULT= ExprBinary.Op.JOIN.make(o, null, DashRef.processRef(), r); :}; BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e PRIME {: - if (b.size() > 1) DashErrors.crossRefMoreThanOneArg(o,e.label); - // probably have to fix PRIME here later when turning to Alloy - RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label + "'")); + Expr r = ExprVar.make(o, a.toString() + '/' + e.label + "'"); + Collections.reverse(b); + for (Expr x:b) r = ExprBinary.Op.JOIN.make(o,null, x, r); + RESULT= ExprBinary.Op.JOIN.make(o, null, DashRef.processRef(),r); :}; //DASH end grammar --------------------------------------------------------------------- diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt b/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt index 72defeb8f..c0ed41169 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt @@ -1,6 +1,8 @@ import java.util.Arrays; import edu.mit.csail.sdg.alloy4.Pair; - +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; import edu.mit.csail.sdg.parser.CompModule; import edu.mit.csail.sdg.parser.MarkdownHandler; diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index 619bd7e96..0e7b3693e 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -67,7 +67,9 @@ import edu.mit.csail.sdg.ast.Sig; import edu.mit.csail.sdg.ast.Sig.PrimSig; import java.util.Arrays; import edu.mit.csail.sdg.alloy4.Pair; - +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; import edu.mit.csail.sdg.parser.CompModule; import edu.mit.csail.sdg.parser.MarkdownHandler; @@ -1523,7 +1525,7 @@ TransItemList ::= TransItemList:c TransItem:x {: c.add(x); RESULT = c; :}; //Exprp is non-empty list of comma-separated Expr - +//Exprs could be empty ist of comma-separated Expr TransItem ::= FROM:o Name:n {: RESULT = new DashFrom(o, new DashRef(o, n.label,DashRef.emptyParamValuesList())); :}; @@ -1538,8 +1540,15 @@ TransItem ::= GOTO:o Name:n LBRACKET Exprp:e RBRACKET RESULT = new DashGoto(o, new DashRef(o, n.label,e)); :}; -TransItem ::= ON:o Expr:e - {: RESULT = new DashOn(o, e); :}; +// this allows "on x.ev1", "on A/ev1[x]" and "on n" in parsing but will have to sort out later to see if correct +TransItem ::= ON:o Expr:v + {: RESULT = new DashOn(o, v); :}; + +//TransItem ::= ON:o Name:n +// {: //RESULT = new DashOn(o, new DashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; + +//TransItem ::= ON:o Name:n LBRACKET Expr:b RBRACKET +// {: //RESULT = new DashOn(o, new DashRef(o,n.label,e) ); :}; TransItem ::= WHEN:o Expr:v {: RESULT = new DashWhen(o, v); :}; @@ -1547,28 +1556,35 @@ TransItem ::= WHEN:o Expr:v TransItem ::= DO:o Expr:v {: RESULT = new DashDo(o, v); :}; - - - // this allows Send x.ev1 and "Send n" in parsing but will have to sort out later to see if correct TransItem ::= SEND:o Expr:v {: RESULT = new DashSend(o, v); :}; - -// DASH PLUS PROCESS VARIABLE REFERENCE -// ParamConcState[Param]/Variable -// result Param.ParamConcState/Variable -// not sure why a BadJoin is used here; but Alloy parsing rules use ExprBadJoins, not ExprJoins + +//TransItem ::= SEND:o Name:n +// {: RESULT = new DashSend(o, new DashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; + +//TransItem ::= SEND:o Name:n LBRACKET Exprp:e RBRACKET +// {: RESULT = new DashSend(o, new DashRef(o,n.label,e) ); :}; + +// DASH PLUS PROCESS REFERENCE +// in Alloy can't have a "/Variable" in the following so we need more syntax +// A/B/C[ParamValue1, ParamValue2]/Variable +// result ParamValue2.ParamValue1.A/B/C/Variable (using BadJoins) // note PRIME is a special token in grammar and we want to support v' + BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e {: - if (b.size() > 1) DashErrors.crossRefMoreThanOneArg(o,e.label); - RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label)); + Expr r = ExprVar.make(o, a.toString() + '/' + e.label); + Collections.reverse(b); + for (Expr x:b) r = ExprBinary.Op.JOIN.make(o,null, x, r); + RESULT= ExprBinary.Op.JOIN.make(o, null, DashRef.processRef(), r); :}; BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e PRIME {: - if (b.size() > 1) DashErrors.crossRefMoreThanOneArg(o,e.label); - // probably have to fix PRIME here later when turning to Alloy - RESULT= ExprBadJoin.make(o, null, b.get(0), ExprVar.make(o, a.toString() + '/' + e.label + "'")); + Expr r = ExprVar.make(o, a.toString() + '/' + e.label + "'"); + Collections.reverse(b); + for (Expr x:b) r = ExprBinary.Op.JOIN.make(o,null, x, r); + RESULT= ExprBinary.Op.JOIN.make(o, null, DashRef.processRef(),r); :}; //DASH end grammar --------------------------------------------------------------------- diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 887d258b2..aeb2f616d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -18,8 +18,10 @@ import edu.mit.csail.sdg.ast.ExprHasName; import edu.mit.csail.sdg.ast.ExprBinary; - import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashErrors; + +import ca.uwaterloo.watform.alloyasthelper.ExprToString; // these are all static // don't want to make them an extension @@ -28,6 +30,52 @@ public class ExprHelper { + // tests ------------------------------------ + public static boolean isExprBinary(Expr e) { + return (e instanceof ExprBinary); + } + public static boolean isExprJoin(Expr e) { + return ((e instanceof ExprBinary) && ((ExprBinary) e).op.equals(ExprBinary.Op.JOIN)); + } + public static boolean isExprArrow(Expr e) { + return ((e instanceof ExprBinary) && ((ExprBinary) e).op.equals(ExprBinary.Op.ARROW)); + } + public static boolean isExprBadJoin(Expr e) { + return (e instanceof ExprBadJoin); + } + public static boolean isExprVar(Expr e) { + return (e instanceof ExprVar); + } + + // simple equality: two var names are equal + public static boolean sEquals(Expr e1, Expr e2) { + return ( (e1 == e2) || + (isExprVar(e1) && isExprVar(e2) && + getVarName((ExprVar) e1).equals(getVarName((ExprVar) e2)))) ; + } + + // destructors ------------------------------- + public static String getVarName(ExprVar e) { + return e.label; + } + + public static Expr getRight(Expr e) { + if (isExprBinary(e) ) + return ((ExprBinary) e).right; + else if (isExprBadJoin(e) ) + return ((ExprBadJoin) e).right; + else { DashErrors.getRightNotBinaryOrJoin(); return null; } + } + public static Expr getLeft(Expr e) { + if (isExprBinary(e)) + return ((ExprBinary) e).left; + else if (isExprBadJoin(e)) + return ((ExprBadJoin) e).left; + else { DashErrors.getLeftNotBinaryOrJoin(); return null; } + } + + // constructors ----------------------------------- + // useful in development public static Expr createNullExpr() { return createEquals(createTrue(),createTrue()); @@ -35,34 +83,46 @@ public static Expr createNullExpr() { public static ExprVar createTrue() { return ExprVar.make(Pos.UNKNOWN, DashStrings.trueName); } + public static ExprVar createFalse() { + return ExprVar.make(Pos.UNKNOWN, DashStrings.falseName); + } public static ExprVar createNone() { return ExprVar.make(Pos.UNKNOWN, DashStrings.noneName); } public static ExprVar createVar(String v) { return ExprVar.make(Pos.UNKNOWN, v); } - public static List createVarList(List vList) { - List retList = new ArrayList(); + public static List createVarList(List vList) { + List retList = new ArrayList(); for (String v: vList) { retList.add(createVar(v)); } return retList; } - public static List createVarList(String prefix, List vList) { - List retList = new ArrayList(); + public static List createVarList(String prefix, List vList) { + List retList = new ArrayList(); for (String v: vList) { retList.add(createVar(prefix+v)); } return retList; } + // to avoid the need to cast every ExprVar to an Expr - public static List createVarExprList(String prefix, List vList) { - List retList = new ArrayList(); + public static List createExprVarList(List vList) { + List retList = new ArrayList(); + for (String v: vList) { + retList.add((ExprVar) createVar(v)); + } + return retList; + } + public static List createExprVarList(String prefix, List vList) { + List retList = new ArrayList(); for (String v: vList) { - retList.add((Expr) createVar(prefix+v)); + retList.add((ExprVar) createVar(prefix + v)); } return retList; } + /* generic ones */ public static Expr createBinaryExpr(Expr left, ExprBinary.Op op, Expr right) { return (ExprBinary) op.make(Pos.UNKNOWN, Pos.UNKNOWN,left,right); @@ -130,15 +190,31 @@ public static ExprBinary createNotEquals(Expr left, Expr right) { public static ExprList createAnd(Expr left, Expr right) { return (ExprList) ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static ExprList createAnd(List args) { - return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); + //public static ExprList createAndList(List args) { + // return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); + //} + public static Expr createAndFromList(List elist) { + if (elist.isEmpty()) return createTrue(); + Expr ret = elist.get(0); + for (Expr el: elist.subList(1,elist.size())) { + ret = createAnd(ret,el); + } + return ret; } public static ExprList createOr(Expr left, Expr right) { return (ExprList) ExprBinary.Op.OR.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - public static ExprList createOr(List args) { - return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); + public static Expr createOrFromList(List elist) { + if (elist.isEmpty()) return createTrue(); + Expr ret = elist.get(0); + for (Expr el: elist.subList(1,elist.size())) { + ret = createOr(ret,el); + } + return ret; } + //public static ExprList createOr(List args) { + // return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); + //} public static ExprBinary createArrow(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.ARROW.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } @@ -146,6 +222,17 @@ public static ExprBinary createArrow(Expr left,Expr right) { public static ExprBinary createUnion(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.PLUS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } + public static Expr createUnionFromList(List elist) { + if (elist.isEmpty()) return createNone(); + Expr ret = elist.get(0); + for (Expr el: elist.subList(1,elist.size())) { + ret = createUnion(ret,el); + } + return ret; + } + public static ExprBinary createIntersect(Expr left,Expr right) { + return (ExprBinary) ExprBinary.Op.INTERSECT.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } // set diff public static ExprBinary createDiff(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.MINUS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); @@ -203,12 +290,10 @@ public static Expr createPredCall(String name, List elist) { return o; } - // simple equality: two var names are equal - public static boolean sEquals(Expr e1, Expr e2) { - return ( (e1 == e2) || - (e1 instanceof ExprVar && - e2 instanceof ExprVar && - ((ExprVar) e1).label.equals(((ExprVar) e2).label))) ; + public static String myExprToString(Expr e) { + ExprToString eToString = new ExprToString(false); + return eToString.toString(e); } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index 7290c0268..c3d8c39bb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -5,6 +5,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.StringJoiner; +import java.util.List; +import java.util.Collections; import de.uka.ilkd.pp.DataLayouter; import de.uka.ilkd.pp.NoExceptions; @@ -17,7 +19,11 @@ import edu.mit.csail.sdg.ast.Sig.Field; import edu.mit.csail.sdg.ast.Sig.PrimSig; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; +import ca.uwaterloo.watform.core.DashFQN; +import ca.uwaterloo.watform.core.DashRef; import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashUtilFcns; public class ExprToString { @@ -39,16 +45,17 @@ public String toString(Expr e) { return back.getString(); } private void ExprToOut(Expr expr) { + /* if (expr instanceof ExprBad){ ExprBadToOut((ExprBad)expr); + } else if (expr instanceof ExprBadCall){ ExprBadCallToOut((ExprBadCall)expr); - } else if (expr instanceof ExprBadJoin){ - ExprBadJoinToOut((ExprBadJoin)expr); - } else */ - if (expr instanceof ExprBinary){ + if (expr instanceof ExprBadJoin){ + ExprBadJoinToOut((ExprBadJoin)expr); + } else if (expr instanceof ExprBinary) { ExprBinaryToOut((ExprBinary)expr); } else if (expr instanceof ExprCall){ ExprCallToOut((ExprCall)expr); @@ -72,7 +79,7 @@ private void ExprToOut(Expr expr) { SigToOut((Sig)expr); } else if (expr instanceof Field){ FieldToOut((Field)expr); - } else DashErrors.missingExpr("ExprToOut "); + } else DashErrors.missingExpr("ExprToOut :" +expr.getClass().getName()); } /* private void ExprBad(ExprBad expr) { @@ -90,18 +97,33 @@ private void ExprBadCall(ExprBadCall expr) { } out.end().print(']'); } - - private void ExprBadJoin(ExprBadJoin expr) { - Expr(expr.left); - out.print('.'); - Expr(expr.right); - } */ + + private Boolean isBinary(Expr e) { return (e instanceof ExprBinary); } private void ExprBinaryToOut(ExprBinary expr) { - if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { + if (DashRef.isDashRefProcessRef(expr)) { + // Root/A/B[exp1, exp2]/v1 + String v = DashRef.nameOfDashRefExpr(expr); + String n = DashFQN.chopNameFromFQN(v); + String prefix = DashFQN.chopPrefixFromFQN(v); + String s = prefix; + s += "["; + List el = new ArrayList(); + Expr e1 = getLeft(expr); + el.add(e1.toString()); + while (isExprJoin(e1)) { + el.add(e1.toString()); + e1 = getLeft(e1); + } + Collections.reverse(el); + s += DashUtilFcns.strCommaList(el); + s += "]/" + v; + out.print(s); + } + else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { out.print("seq "); ExprToOut(expr.right); } @@ -138,6 +160,17 @@ else if ( isBinary(expr.right) || isBinary(expr.left) ) { } } + private void ExprBadJoinToOut(ExprBadJoin expr) { + out.print("("); + ExprToOut(expr.left); + out.print(")"); + out.print('.'); + out.print("("); + ExprToOut(expr.right); + out.print(")"); + } + + private void ExprBinaryJoinToOut(ExprBinary expr) { // The Alloy resolve dot joins (this) to a variable reference in a variable. We should not bring the ("this") // We also do not print (Snapshot <: ...) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java index eb34eed2d..3345361c5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashOn.java @@ -4,15 +4,32 @@ import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashRef; public class DashOn extends Dash { - public Expr ev; - public DashOn(Pos pos,Expr e) { - assert(e != null); + //public DashRef ref; + public Expr exp; + /* + public DashOn(Pos pos,DashRef r) { + assert(r != null); this.pos = pos; - this.ev = e; + this.ref = r; + this.exp = null; + } + */ + public DashOn(Pos pos, Expr e) { + assert (e != null); + this.pos = pos; + this.exp = e; + //this.ref = null; } public String toString() { - return DashStrings.onName + " " + ev + "\n"; + //if (ref != null) + // return DashStrings.onName + " " + ref.toString() + "\n"; + //else + return DashStrings.onName + " " + exp.toString() + "\n"; + } + public Expr getExp() { + return exp; } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java index 2d7ae59e1..b1ea33efd 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashSend.java @@ -10,6 +10,7 @@ import java.util.StringJoiner; import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashRef; import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Expr; @@ -20,14 +21,31 @@ public class DashSend extends Dash { - public Expr eventExpr; - public DashSend(Pos pos,Expr ev) { - assert(ev != null); + //public DashRef ref; + public Expr exp; + + /* + public DashSend(Pos pos,DashRef r) { + assert(r != null); + this.pos = pos; + this.ref = r; + this.exp = null; + } + */ + public DashSend(Pos pos,Expr e) { + assert(e != null); this.pos = pos; - this.eventExpr = ev; + this.exp = e; + //this.ref = null; } public String toString() { - return DashStrings.sendName + " " + eventExpr.toString() + "\n"; + //if (ref != null) + // return DashStrings.sendName + " " + ref.toString() + "\n"; + //else + return DashStrings.sendName + " " + exp.toString() + "\n"; + } + public Expr getExp() { + return exp; } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index 24f9ebedd..3bf96d1c4 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -25,7 +25,7 @@ public class DashState extends Dash { // stuff from parsing public String name; - private String sfqn; // set during resolveAllState + //private String sfqn; // set during resolveAllState private String param; private DashStrings.StateKind kind; // basic state = OR with no subStates private DashStrings.DefKind def; @@ -114,20 +114,63 @@ public static String noParam() { public static List noSubstates() { return new ArrayList(); } - // env events cannot be generated - // env vars cannot be primed anywhere - // must have at least one transition (could be looping on Root ...) /* * check for errors in the state hierarchy * and put all states in the state table - * also set this state's fqn here */ - public void resolveAllStates(StateTable st, EventTable et, VarTable vt, BufferTable bt, List params, List ances) { - if (DashFQN.alreadyFQN(name)) DashErrors.stateNameCantBeFQN(pos, name); - sfqn = DashFQN.fqn(ances,name); + public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, BufferTable bt, List params, List ances) { + if (DashFQN.isFQN(name)) DashErrors.stateNameCantBeFQN(pos, name); + String sfqn = DashFQN.fqn(ances,name); //System.out.println("Resolving state "+sfqn); - + + // make a copy of the items list so we can + // subtract from it for error checking + // but keep the original items for printing, etc. + List xItems = new ArrayList(items); + + + // invariants --------------------- + List invList = new ArrayList(); + if (items != null) + invList = + items.stream() + .filter(i -> i instanceof DashInv) + .map(p -> (DashInv) p) + .collect(Collectors.toList()); + xItems.removeAll(invList); + + // inits --------------------- + List initList = new ArrayList(); + if (items != null) + initList = + items.stream() + .filter(i -> i instanceof DashInit) + .map(p -> (DashInit) p) + .collect(Collectors.toList()); + xItems.removeAll(initList); + + // actions --------------------- + List actionList = new ArrayList(); + if (items != null) + actionList = + items.stream() + .filter(i -> i instanceof DashAction) + .map(p -> (DashAction) p) + .collect(Collectors.toList()); + xItems.removeAll(actionList); + + // conditions --------------------- + List conditionList = new ArrayList(); + if (items != null) + conditionList = + items.stream() + .filter(i -> i instanceof DashCondition) + .map(p -> (DashCondition) p) + .collect(Collectors.toList()); + xItems.removeAll(conditionList); + + // --------------------- // process the children // have to make a copy so that recursion does not just // continue to add to list everywhere @@ -139,14 +182,16 @@ public void resolveAllStates(StateTable st, EventTable et, VarTable vt, BufferTa List substatesList = new ArrayList(); if (items != null) substatesList = - items.stream() + xItems.stream() .filter(i -> i instanceof DashState) .map(p -> (DashState) p) .collect(Collectors.toList()); - if (substatesList.isEmpty() ) { - st.add(sfqn, kind, param, newParams, def, DashFQN.fqn(ances), null); + + if (substatesList.isEmpty() ) { + if (!st.add(sfqn, kind, param, newParams, def, DashFQN.fqn(ances), new ArrayList(), + invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; } else { @@ -159,10 +204,11 @@ public void resolveAllStates(StateTable st, EventTable et, VarTable vt, BufferTa DashErrors.dupSiblingNames(DashUtilFcns.strCommaList(dups.stream().collect(Collectors.toList()))); // add this state to the table - st.add(sfqn,kind, param, newParams,def, DashFQN.fqn(ances), childFQNs); + if (!st.add(sfqn,kind, param, newParams,def, DashFQN.fqn(ances), childFQNs, + invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; // add all substates to the table - for (DashState s: substatesList) s.resolveAllStates(st, et, vt, bt, newParams, newAnces); + for (DashState s: substatesList) s.resolve(st, tt, et, vt, bt, newParams, newAnces); // make sure defaults are correct // if there's only one child it is automatically the default @@ -202,12 +248,13 @@ public void resolveAllStates(StateTable st, EventTable et, VarTable vt, BufferTa } } } - - // add declared events + xItems.removeAll(substatesList); + + // add declared events --------------------- List eventDeclsList = new ArrayList(); if (items != null) eventDeclsList = - items.stream() + xItems.stream() .filter(i -> i instanceof DashEventDecls) .map(p -> (DashEventDecls) p) .collect(Collectors.toList()); @@ -215,13 +262,14 @@ public void resolveAllStates(StateTable st, EventTable et, VarTable vt, BufferTa for (DashEventDecls e:eventDeclsList) { DashStrings.IntEnvKind k = e.getKind(); for (String x: e.getNames()) { - if (DashFQN.alreadyFQN(x)) DashErrors.eventNameCantBeFQN(e.getPos(), x); + if (DashFQN.isFQN(x)) DashErrors.eventNameCantBeFQN(e.getPos(), x); String xfqn = DashFQN.fqn(sfqn,x); if (!et.add(xfqn,k, newParams)) DashErrors.duplicateEventName(e.getPos(),x); } } + xItems.removeAll(eventDeclsList); - // add declared variables + // add declared variables ------------------------ List varDeclsList = new ArrayList(); if (items != null) varDeclsList = @@ -234,13 +282,14 @@ public void resolveAllStates(StateTable st, EventTable et, VarTable vt, BufferTa DashStrings.IntEnvKind k = v.getKind(); Expr t = v.getTyp(); for (String x: v.getNames()) { - if (DashFQN.alreadyFQN(x)) DashErrors.varNameCantBeFQN(v.getPos(), x); + if (DashFQN.isFQN(x)) DashErrors.varNameCantBeFQN(v.getPos(), x); String xfqn = DashFQN.fqn(sfqn,x); if (!vt.add(xfqn,k, newParams, t)) DashErrors.duplicateVarName(v.getPos(),x); } } + xItems.removeAll(varDeclsList); - // add declared buffers + // add declared buffers --------------------------- List bufferDeclsList = new ArrayList(); if (items != null) bufferDeclsList = @@ -253,276 +302,30 @@ public void resolveAllStates(StateTable st, EventTable et, VarTable vt, BufferTa DashStrings.IntEnvKind k = b.getKind(); String el = b.getElement(); for (String x: b.getNames()) { - if (DashFQN.alreadyFQN(x)) DashErrors.bufferNameCantBeFQN(b.getPos(), x); + if (DashFQN.isFQN(x)) DashErrors.bufferNameCantBeFQN(b.getPos(), x); String xfqn = DashFQN.fqn(sfqn,x); if (!bt.add(xfqn,k, newParams, el)) DashErrors.duplicateBufferName(b.getPos(),x); } } + xItems.removeAll(bufferDeclsList); - - /* - - // set the pathtohere and params of variables - // set the FQNs of src and dest of transitions - resolveVars(pth,prs); - resolveEvents(pth); - resolveTrans(pth,prs); - String defName = null; - for (s:substates) { - s.resolveAll(pathToHere, params); - // collect all the stuff from below - // set trans src/dest FQNs - allTransitions.addAll(s.getAllTransitions()); - symbolTable.addAll(s.getSymbolTable()); - allEvents.addAll(s.getAllEvents()); - allParams.addAll(s.getAllParams()); - // calculate all basic states entered/exited and pass up? - // or do that in StateTableResolve all?? - if (s.kind == StateKind.OR) { - if (defName == null) { - defName = s.getFullyQualName(); - } else { - // error multiple default states - } - } else { - defN - } - stateTable.merge(s.getStateTable()); - // what about parameters of states??? - } - stateTable.add(s,) - */ - } - - /* - * check for errors and put all the trans that are at this level - * in the trans table - * must be done after resolveAllState - * this fcn does not modify anything in this object - */ - public void resolveAllTrans(StateTable st, TransTable tt) { - - if (items == null ) return; - List transList = - items.stream() - .filter(i -> i instanceof DashTrans) - .map(p -> (DashTrans) p) - .collect(Collectors.toList()); - // all trans must have different names - ArrayList transFQNs = new ArrayList(); - transList.forEach(i -> transFQNs.add(DashFQN.fqn(sfqn, i.name))); - Set dups = DashUtilFcns.findDuplicates(transFQNs); - if (!dups.isEmpty()) - DashErrors.dupTransNames(DashUtilFcns.strCommaList(dups.stream().collect(Collectors.toList()))); - - for (DashTrans t: transList) { - String tfqn = DashFQN.fqn(sfqn,t.name); - - // transition src/dest have to be resolved here rather than in DashTrans because - // this src and dest are contextual - - List fromList = - t.items.stream() - .filter(i -> i instanceof DashFrom) - .map(p -> ((DashFrom) p).src) - .collect(Collectors.toList()); - //System.out.println(fromList); - DashRef src = setSrcDest("from", fromList, st, sfqn, tfqn); - assert(src != null); - st.add(src.getName()); - - List gotoList = - t.items.stream() - .filter(i -> i instanceof DashGoto) - .map(p -> ((DashGoto) p).dest) - .collect(Collectors.toList()); - //System.out.println(gotoList); - DashRef dest = setSrcDest("goto", gotoList, st, sfqn, tfqn); - assert(dest != null); - st.add(dest.getName()); - - /* - // AND-cross transitions are now allowed - // check if it is an AND-cross transition - List srcAnces = st.getAllAnces(src); - // System.out.println("src="+src+" srcAnces= "+srcAnces); - List destAnces = st.getAllAnces(dest); - // System.out.println("dest="+dest+" destAnces= "+destAnces); - int i = 0; - // find closest common ances - while (i< srcAnces.size() && i < destAnces.size() && srcAnces.get(i).equals(destAnces.get(i))) i++; - // are there any conc states between src/dest and the closest common ances? - for (int j=i; j < srcAnces.size();j++) - if (st.isAnd(srcAnces.get(i))) - DashErrors.andCrossTransition(tfqn); - for (int j=i; j < destAnces.size(); j++) - if (st.isAnd(st.getKind(destAnces.get(i)))) - DashErrors.andCrossTransition(tfqn); - */ - - tt.add(tfqn,st.getParams(sfqn),src,dest); - } - if (items != null ) { - List substatesList = + // add transitions ---------------------- + List transList = new ArrayList(); + if (items != null) + transList = items.stream() - .filter(i -> i instanceof DashState) - .map(p -> (DashState) p) + .filter(i -> i instanceof DashTrans) + .map(p -> (DashTrans) p) .collect(Collectors.toList()); - for (DashState s: substatesList) s.resolveAllTrans(st, tt); - } - - - - } - - /* - * this fcn figures out the src/dest of a transition - * from its context - * if it has no src/dest, the parent state is used - * if it is already FQN, it is returned directly - * Otherwise, it looks at all uniquely named states up to an ancestor conc state - * Requires state table to have been built already - */ - - public DashRef setSrcDest(String xType, List ll, StateTable st, String parentFQN, String tfqn) { - - //System.out.println("Here"); - //System.out.println(ll); - if (ll.size() > 1) { - DashErrors.moreThanOneSrcDest(xType, tfqn); - return null; - } else if (ll.isEmpty()) - // can be a loop on root - return new DashRef(parentFQN, ExprHelper.createVarExprList(DashStrings.pName,st.getParams(parentFQN))); - else { - // if has slashes, turn to "-" - DashRef x = ll.get(0); - //System.out.println("Looking for: " + x); - if (DashFQN.alreadyFQN(x.getName())) { - // number of params provided must match number of params needed - //System.out.println(x.getParamValues().size()); - //System.out.println(st.getParams(x.getName()).size()); - if (x.getParamValues().size() != st.getParams(x.getName()).size()) { - DashErrors.fqnSrcDestMustHaveRightNumberParams(xType,tfqn); - return null; - } - return x; - } else { - // not fully qualified - // shouldn't have params in DashRef - // Root could be here but won't have params - if (!x.getParamValues().isEmpty()) { - DashErrors.srcDestCantHaveParam(xType,tfqn); - return null; - } - // Root ends up here - List matches = new ArrayList(); - //String a = st.getClosestConcAnces(parentFQN); - //System.out.println("getClosestConcAnces: "+a); - //List b = st.getAllNonConcStatesWithinThisState(a); - //System.out.println("getAllNonConcStatesWithinThisState "+b); - for (String s:st.getRegion(parentFQN)) { - if (x.getName().equals(DashFQN.chopNameFromFQN(s))) matches.add(s); - } - //System.out.println("matches: " + matches); - if (matches.size() > 1) { - DashErrors.ambiguousSrcDest(xType, tfqn); - return null; - } else if (matches.isEmpty()) { - //DashUtilFcns.myprint(st.toString()); - DashErrors.unknownSrcDest(x.getName(),xType,tfqn); - return null; - } else { - String m = matches.get(0); - //System.out.println(m); - // must have same param values as trans b/c in same conc region - return new DashRef(m, paramVars(st.getParams(m))); - } - } + for (DashTrans t:transList) { + //System.out.println("newAnces: " +newAnces); + t.resolve(tt, newParams, newAnces); } - } - - // [n1,n2,...] - private List paramVars(List names) { - List o = new ArrayList(); - for (String n: names) o.add(ExprHelper.createVar(DashStrings.pName+n)); - return o; - } - + xItems.removeAll(transList); - /* - public String getParam() { - return params(1) - } - public String getParams() { - return params; - } - - - public getAllTransitions() { - returns allTransitions; - } - - public getAllEvents() { - return allEvents; - } - public getAllParams() { - return allParams; + if (!xItems.isEmpty()) DashErrors.nonEmptyStateItems(); } - // correctness checks - public boolean allSubStatesSameKind() { - if (subStates != null) { - StateKind k = substates(1).getKind(); - for (s:subStates) { - if (k != s.getKind()) { - error - } - } - return true; - } else { - return false; - } - } - - public getDefaultBasicStates() { - switch (kind): - case StateKind.BASIC: - return getFullyQualifiedName() - case StateKind.OR: - return getDefaultState - - - } else if (kind == StateKind.OR) { - - } else { - // error - } - } - } - public void resolveVars(String pth, List prs) { - for (d:dynvars) { - d.setPathToHere(pth); - d.setParams(params) - } - } - - public void resolveEvents(String pth) { - for (e:events) { - e.setPathToHere(pth); - } - } - public void resolveTrans(String pth, List prs) { - for (t:transitions) { - t.setPathToHere(pth); - t.setParems(params); - // calculate scope to put in table - // reject transition as crossing from one concurrent component to another if children of scope are concurrent !! - } - // what if no transitions - } - - */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java index 60b1d1260..c1bfe8cdd 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java @@ -1,6 +1,7 @@ package ca.uwaterloo.watform.ast; import java.util.List; +import java.util.ArrayList; import java.util.StringJoiner; import java.util.Collections; import java.util.stream.Collectors; @@ -25,19 +26,68 @@ public DashTrans(Pos p,String n, List i) { public String toString() { String s = new String(""); - if (items == null) { + if (items.isEmpty()) { s += DashStrings.transName + " " + name + " { }\n"; } else { - s += DashStrings.transName + " " + name + "{\n"; + s += DashStrings.transName + " " + name + " {\n"; StringJoiner j = new StringJoiner(""); items.forEach(i -> j.add(i.toString())); s += j.toString() + "}\n"; } return s; } - public void resolveAll(StateTable st, TransTable tt, List params, List ances) { + public void resolve(TransTable tt, List params, List ances) { + + if (DashFQN.isFQN(name)) DashErrors.transNameCantBeFQN(pos, name); String tfqn = DashFQN.fqn(ances,name); - //System.out.println("Resolving trans "+tfqn); + //System.out.println("HERE3 "+items.toString()); + List xItems = new ArrayList(items); + //System.out.println("HERE3 "+xItems.toString()); + List fromList = + xItems.stream() + .filter(i -> i instanceof DashFrom) + .map(i -> (DashFrom) i) + .collect(Collectors.toList()); + xItems.removeAll(fromList); + + List onList = + xItems.stream() + .filter(i -> i instanceof DashOn) + .map(i -> (DashOn) i) + .collect(Collectors.toList()); + + xItems.removeAll(onList); + + List whenList = + xItems.stream() + .filter(i -> i instanceof DashWhen) + .map(i -> (DashWhen) i) + .collect(Collectors.toList()); + xItems.removeAll(whenList); + + List gotoList = + xItems.stream() + .filter(i -> i instanceof DashGoto) + .map(i -> (DashGoto) i) + .collect(Collectors.toList()); + xItems.removeAll(gotoList); + + List sendList = + xItems.stream() + .filter(i -> i instanceof DashSend) + .map(i -> (DashSend) i) + .collect(Collectors.toList()); + xItems.removeAll(sendList); + + List doList = + xItems.stream() + .filter(i -> i instanceof DashDo) + .map(i -> (DashDo) i) + .collect(Collectors.toList()); + xItems.removeAll(doList); + if (!tt.add(tfqn,params, fromList, onList, whenList, gotoList, sendList, doList)) DashErrors.dupTransNames(pos,name); + //System.out.println(xItems); + if (!xItems.isEmpty()) DashErrors.nonEmptyTransItems(); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index ef7a8afa5..b3eef9432 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -46,8 +46,8 @@ public static void dupSiblingNames(String dups) throws Err { throw new ErrorSyntax(dupSiblingNamesMsg + dups); } public static String dupTransNameMsg = "Duplicate transition names: "; - public static void dupTransNames(String dups) throws Err { - throw new ErrorSyntax(dupTransNameMsg + dups); + public static void dupTransNames(Pos o, String dups) throws Err { + throw new ErrorSyntax(o, dupTransNameMsg + dups); } public static String moreThanOneSrcDestMsg = "Transition has more than one src or dest: "; public static void moreThanOneSrcDest(String x, String n) throws Err { @@ -71,6 +71,11 @@ public static void ambiguousSrcDest(String x, String tfqn) throws Err { } // below this have not been tested + public static String transNameCantBeFQNMsg = "Trans name cannot be fully qualified at declaration: "; + public static void transNameCantBeFQN(Pos o, String s) { + throw new ErrorSyntax(o, transNameCantBeFQNMsg + s); + } + public static String eventNameCantBeFQNMsg = "Event name cannot be fully qualified at declaration: "; public static void eventNameCantBeFQN(Pos o, String s) { throw new ErrorSyntax(o, eventNameCantBeFQNMsg + s); @@ -96,23 +101,39 @@ public static void duplicateBufferName(Pos o, String s) { throw new ErrorSyntax(o, duplicateBufferNameMsg + s); } - public static void siblingsSameKind(String fqn) throws Err { - throw new ErrorSyntax("Children of "+fqn+" must all be of concurrent or not concurrent"); + // event errors + public static String tooManyEventsMsg = "Multiple "; + public static void tooManyEvents(String xType, String tfqn) { + throw new ErrorSyntax(tooManyEventsMsg + xType + " in " + tfqn); + } + public static String unknownEventMsg = "Event does not exist: "; + public static void unknownEvent(String xType, String v, String tfqn) { + throw new ErrorSyntax(unknownEventMsg +v+" in "+ tfqn +" "+ xType); + } + public static String ambiguousEventMsg = "Event name not unique within this conc/Root region: "; + public static void ambiguousEvent(String xType, String v, String tfqn) { + throw new ErrorSyntax(ambiguousEventMsg +v+" in "+ tfqn + " "+xType); + } + public static String fqnEventMissingParametersMsg = "Fully qualified event name missing paramaters: "; + public static void fqnEventMissingParameters(String xType, String v, String tfqn) { + throw new ErrorSyntax(fqnEventMissingParametersMsg + v + " in "+tfqn + " " + xType); } - public static void crossRefMoreThanOneArg(Pos o, String n) throws Err { - throw new ErrorSyntax(o,"Two many args to reference to "+n+" in sibling state"); + public static String expNotEventMsg = "Not an event for: "; + public static void expNotEvent(String xType, String tfqn) { + throw new ErrorSyntax(expNotEventMsg + tfqn + " " + xType); } + //public static void siblingsSameKind(String fqn) throws Err { + // throw new ErrorSyntax("Children of "+fqn+" must all be of concurrent or not concurrent"); + //} + //public static void crossRefMoreThanOneArg(Pos o, String n) throws Err { + // throw new ErrorSyntax(o,"Two many args to reference to "+n+" in sibling state"); + //} + - public static void transUsesNonExistentState(String n) throws Err { - throw new ErrorSyntax("Some transition has from/goto to state "+n+" which doesn't exist"); - } - public static void andCrossTransition(String tfqn) throws Err { - throw new ErrorSyntax("Trans "+tfqn+" goes between concurrent states"); - } @@ -157,4 +178,35 @@ public static void tooHighParamDepth() throws Err { public static void paramNumberProblem(String s) throws Err { throw new ErrorFatal(paramNumberProblemMsg + s); } + public static String chopPrefixFromFQNwithNoPrefixMsg = "chopPrefixFromFQNwithNoPrefix: "; + public static void chopPrefixFromFQNwithNoPrefix(String s) throws Err { + throw new ErrorFatal(chopPrefixFromFQNwithNoPrefixMsg + s); + } + public static void nonEmptyStateItems() throws Err { + throw new ErrorFatal("Non-empty state items at end of state resolve"); + } + public static void nonEmptyTransItems() throws Err { + throw new ErrorFatal("Non-empty trans items at end of trans resolve"); + } + public static void getRightNotBinaryOrJoin() throws Err { + throw new ErrorFatal("getRightNotBinaryOrJoin"); + } + public static void getLeftNotBinaryOrJoin() throws Err { + throw new ErrorFatal("getLeftNotBinaryOrJoin"); + } + public static void replaceDashRefExprVarError() throws Err { + throw new ErrorFatal("replaceDashRefExprVarError"); + } + public static void nonDashRefExpr() throws Err { + throw new ErrorFatal("nonDashRefExpr"); + } + public static void eventTableGetParams() { + throw new ErrorFatal("eventTableGetParams"); + } + public static void regionMatchesWrongParamNumber() { + throw new ErrorFatal("regionMatchesWrongParamNumber"); + } + public static void createTestIfNextStableCallMultipleScopesAtSameLevel() { + throw new ErrorFatal("createTestIfNextStableCallMultipleScopesAtSameLevel"); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java index 38c2f7bac..f1bbdc4a3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java @@ -11,61 +11,80 @@ import java.util.stream.Collectors; + public class DashFQN { // used for translation to Alloy //NAD TODO this should match the qualChar used in parsing for vars and state names private static String inputQualChar = "/"; + private static String internalQualChar = inputQualChar; private static String outputQualChar = "_"; - public static String convertFQN(String n) { - return n.replace(inputQualChar, outputQualChar); + // to create Alloy output + public static String translateFQN(String n) { + return n.replace(internalQualChar, outputQualChar); } - public static Boolean alreadyFQN(String n) { + + // testing inputs from parsing + public static Boolean isFQN(String n) { return n.contains(inputQualChar); } - public static String fqn(List pth) { - if (pth.isEmpty()) return null; // for root - StringJoiner sj = new StringJoiner(inputQualChar); - pth.forEach(n -> sj.add(n)); - return sj.toString(); - } + + // creating FQNs from inputs -------------------------- + public static String fqn(String s1,String s2) { String q = new String(s1); - q += inputQualChar; + q += internalQualChar; q += s2; return q; } + public static String fqn(String n) { + return n.replace(inputQualChar, internalQualChar); + } + public static String fqn(List pth) { + if (pth.isEmpty()) return null; // for root + StringJoiner sj = new StringJoiner(internalQualChar); + pth.forEach(n -> sj.add(fqn(n))); + return sj.toString(); + } + public static String fqn(List pth, String name) { - if (alreadyFQN(name)) - //return name.replace(inputQualChar,outputQualChar); - return name; + if (isFQN(name)) + return fqn(name); else { - StringJoiner sj = new StringJoiner(inputQualChar); - pth.forEach(n -> sj.add(n)); - sj.add(name); + StringJoiner sj = new StringJoiner(internalQualChar); + pth.forEach(n -> sj.add(fqn(n))); + sj.add(fqn(name)); return sj.toString(); } } public static String fqn(List pth, String parent, String child) { - if (alreadyFQN(child)) + if (isFQN(child)) //return child.replace(inputQualChar,outputQualChar); - return child; + return fqn(child); else { - StringJoiner sj = new StringJoiner(inputQualChar); - pth.forEach(n -> sj.add(n)); - sj.add(parent); - sj.add(child); + StringJoiner sj = new StringJoiner(internalQualChar); + pth.forEach(n -> sj.add(fqn(n))); + sj.add(fqn(parent)); + sj.add(fqn(child)); return sj.toString(); } } + + // operations on FQNs public static List splitFQN(String fqn) { - return Arrays.asList(fqn.split(inputQualChar)); + return Arrays.asList(fqn.split(internalQualChar)); } public static String chopNameFromFQN(String fqn) { // this is from an output FQN return DashUtilFcns.lastElement(splitFQN(fqn)); } + // useful for getting parent state of a trans/event decl, etc. + public static String chopPrefixFromFQN(String fqn) { + List s = splitFQN(fqn); + if (s.size() < 2) { DashErrors.chopPrefixFromFQNwithNoPrefix(fqn); return null; } + else return fqn(DashUtilFcns.allButLast(splitFQN(fqn))); + } // can't just take longest prefix because states may have similar names // such as Bit1 and Bit2 public static String longestCommonFQN(String a, String b) { @@ -82,7 +101,7 @@ public static List allPrefixes(String fqn) { List prefixes = new ArrayList(); List splitfqn = splitFQN(fqn); for (int i=0;i < splitfqn.size(); i++) { - StringJoiner sj = new StringJoiner(inputQualChar); + StringJoiner sj = new StringJoiner(internalQualChar); for (int j=0;j<=i;j++) { sj.add(splitfqn.get(j)); } @@ -90,15 +109,28 @@ public static List allPrefixes(String fqn) { } return prefixes; } + /* + suffix("A/B/C/x", "C/x") is true + suffix("A/B/C/x", "x") is true + suffix("x","x") is true + suffix("A/B/xyz", "yz") is false + */ + public static boolean suffix(String a, String b) { + //System.out.println(a); + //System.out.println(b); + if (a.endsWith(b)) { + int x = a.lastIndexOf(b); + //System.out.println(x); + if (x != -1) { + if (x == 0) return true; + //System.out.println(a.charAt(x-1)); + if (a.charAt(x-1) == internalQualChar.charAt(0)) return true; + } + } + return false; + } /* ances: A/B/C dest: A/B/C/D/E returns A/B/C/D */ public static String getChildOfContextAncesOfDest(String ances, String dest) { - /* - System.out.println(ances); - System.out.println(dest); - System.out.println(splitFQN(dest)); - System.out.println(splitFQN(dest).subList(0,splitFQN(ances).size())); - System.out.println(fqn(splitFQN(dest).subList(0,splitFQN(ances).size()))); - */ if (dest.equals(ances)) return dest; else if (dest.startsWith(ances)) // dest must be longer than ances diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index 0cbbad402..da6343a08 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -3,12 +3,16 @@ import java.util.List; import java.util.ArrayList; import java.util.Collections; +import java.util.stream.Collectors; import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprBinary; +import edu.mit.csail.sdg.ast.ExprVar; -import ca.uwaterloo.watform.alloyasthelper.ExprHelper; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; public class DashRef{ private Pos pos; @@ -49,7 +53,170 @@ public static List emptyParamValuesList() { public Expr toAlloy() { List ll = new ArrayList(paramValues); Collections.reverse(ll); - ll.add(ExprHelper.createVar(name)); - return ExprHelper.createArrowExprList(ll); + ll.add(createVar(name)); + return createArrowExprList(ll); } + + + // the following operations are about Alloy expressions that + // represent joins from a DashRefs + + // These are: + // exp2. exp1. Root/A/B/v1 (from Root/A/B[exp1,exp2]/v1 with Joins for events and vars in exp) + // exp2. exp1. Root/A/B/v1 (with regular Joins for vars) + // exp2 -> exp1 -> Root/A/B/v1 (from events) + // We think it is a DashRef is there is a slash in the "name" + // slashes aren't regularly allowed in Alloy + + // stuck in the formula the parser produces + // from Root/A/B[exp1,exp2]/v1 + public static Expr processRef() { + return createVar(DashStrings.processRef); + } + + /* + could be used in an action or in an event expr + was built by new Expr rule in parser + Root/A/B[exp1,exp2]/v1 is recorded in the AST as + $$PROCESSREF$$ . exp2 . exp1 . Root/A/B/v1 + */ + public static boolean isDashRefProcessRef(Expr e) { + if (isExprJoin(e)) + if (isExprVar(getLeft(e))) + return sEquals(getLeft(e), processRef()); + return false; + } + /* + can only be used in an action + exp2. exp1. Root/A/B/v1 or + exp2. exp1. Root/A/B/v1' + */ + public static boolean isDashRefJoin(Expr e) { + if (isExprJoin(e)) { + Expr e2 = e; + while (isExprJoin(e2)) e2 = getRight(e2); + if (isExprVar(e2)) return true; + //String v = getVarName((ExprVar)e2); + //if (DashFQN.isFQN(v)) return true; + //} + } + return false; + } + // results from pred calls Tk[xx] + public static boolean isDashRefBadJoin(Expr e) { + //System.out.println(e); + //System.out.println(e.getClass().getName()); + if (isExprBadJoin(e)) { + Expr e2 = e; + while (isExprBadJoin(e2)) { + e2 = getRight(e2); + } + if (isExprVar(e2)) return true; //{ + //String v = getVarName((ExprVar)e2); + //if (DashFQN.isFQN(v)) return true; + //} + } + return false; + } + + /* + can only be used in an event + exp2 -> exp1 -> Root/A/B/ev1 + */ + public static boolean isDashRefArrow(Expr e) { + if (isExprArrow(e)) { + Expr e2 = e; + while (isExprArrow(e2)) e2 = getRight(e2); + if (isExprVar(e2)) return true; //{ + //String v = getVarName((ExprVar)e2); + //if (DashFQN.isFQN(v)) return true; + //} + } + return false; + } + + /* + from exp2. exp2. Root/A/B/v1' return Root/A/B/v1' + */ + public static String nameOfDashRefExpr(Expr e) { + assert(isDashRefProcessRef(e) || isDashRefJoin(e) || isDashRefArrow(e) || isDashRefBadJoin(e)); + Expr e2 = getRight(e); + while (isExprBadJoin(e2) || isExprJoin(e2)) { + e2 = getRight(e2); + } + assert(isExprVar(e2)); + String v = getVarName((ExprVar) e2); + //assert(DashFQN.isFQN(v)); + return v; + } + public static List paramValuesOfDashRefExpr(Expr e) { + List r = new ArrayList(); + Expr e1 = e; + if (isDashRefProcessRef(e1)) { + e1 = getRight(e1); // ignore $$PROCESSREF$$ + while (isExprJoin(e1)) { + r.add(getLeft(e1)); + e1 = getRight(e1); + } + } else if (isExprJoin(e1)) { + while (isExprJoin(e1)) { + r.add(getLeft(e1)); + e1 = getRight(e1); + } + } else if (isExprBadJoin(e1)) { + while (isExprBadJoin(e1)) { + r.add(getLeft(e1)); + e1 = getRight(e1); + } + } else if (isExprArrow(e1)) { + while (isExprArrow(e1)) { + r.add(getLeft(e1)); + e1 = getRight(e1); + } + } else { + DashErrors.nonDashRefExpr(); + return null; + } + return r; + } + /* + replaceDashRefExprVar(exp2. exp1. Root/A/B/v1', sNext.Root/A/B/v1 ) + returns exp2.exp1.sNext.Root/A/B/v1 + */ + + public static Expr subForDashRefArrow(Expr e, Expr r) { + if (isExprVar(e)) return r; + else return createArrow(getLeft(e), subForDashRefArrow(getRight(e),r)); + } + // works for Join or BadJoin + public static Expr subForDashRefJoin(Expr e, Expr r) { + if (isExprVar(e)) return r; + else return createJoin(getLeft(e), subForDashRefJoin(getRight(e),r)); + } + public static Expr convertDashRefProcessRefToArrow(Expr e) { + // removes $$PROCESSREF$$ and replaces joins with arrows + Expr e1 = getRight(e); + return convertDashRefProcessRefToArrowAux(e1); + } + public static Expr convertDashRefProcessRefToArrowAux(Expr e) { + if (isExprVar(e)) return fqnVar(e); + else return createArrow(getLeft(e), convertDashRefProcessRefToArrowAux(getRight(e))); + } + public static ExprVar fqnVar(Expr e) { + assert(isExprVar(e)); + return createVar(DashFQN.fqn(getVarName((ExprVar) e))); + } + // referencing a for loop variable in a filter does not work + // so do this as a loop + public static List hasNumParams(List dr, int i) { + // filter to ones that have this number of params + //System.out.println(i); + //System.out.println(dr); + List o = dr.stream() + .filter(x -> x.getParamValues().size() == i) + .collect(Collectors.toList()); + //System.out.println(o); + return o; + } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 34f2abe73..0ba204495 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -15,6 +15,7 @@ public class DashStrings { public static String asName = "as"; public static String boolName = "boolean/Bool"; public static String trueName = "boolean/True"; + public static String falseName = "boolean/False"; public static String noneName = "none"; public static String intName = "int"; public static String utilBooleanName = "util/boolean"; @@ -64,21 +65,21 @@ public class DashStrings { public static String stateLabelName = "StateLabel"; public static String systemStateName = "SystemState"; - public static String transitionLabelName = "TransitionLabel"; + //public static String transitionLabelName = "TransitionLabel"; public static String identifierName = "Identifiers"; // how to name parameter variables public static String pName = "p"; public static String eventsName = "events"; - public static String eventLabelName = "EventLabel"; - public static String envEventLabelName = "EnvironmentalEvent"; - public static String intEventLabelName = "InternalEvent"; + public static String allEventsName = "AllEvents"; + public static String allEnvironmentalEventsName = "AllEnvironmentalEvents"; + public static String allInternalEventsName = "AllInternalEvent"; public static String preName = "_pre"; public static String postName = "_post"; public static String semanticsName = "_semantics"; public static String testIfNextStableName = "testIfNextStable"; - public static String isEnabledAfterStepName = "_isEnabledAfterStep"; + public static String enabledAfterStepName = "_enabledAfterStep"; public static String tName = "t"; public static String geName = "ge"; @@ -113,4 +114,7 @@ public static enum DefKind { DEFAULT, NOTDEFAULT } + + public static String processRef = "$$PROCESSREF$$"; + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java new file mode 100644 index 000000000..81ad1f1f7 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java @@ -0,0 +1,57 @@ +package ca.uwaterloo.watform.dashtoalloy; + +//import java.util.Collections; +//import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +//import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +//import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +//import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddSmallStep { + /* + pred small_step [s:Snapshot, s': Snapshot] { + some pparam0 : Param0 , pparam1 : Param1 ... | + { // for all t’s at level i with params Param5, Param6, ... + (or t[s, s_next, pparam5, pparam6 ]) + // loop? big-step issue? + } + */ + public static void addSmallStep(DashModule d) { + + ArrayList e = new ArrayList(); + for (String tfqn: d.getAllTransNames()) { + String tout = translateFQN(tfqn); + // p3.p2.p1.t for parameters of this transition + if (DashOptions.isElectrum) e.add(createPredCall(tout,paramVars(d.getTransParams(tfqn)))); + // p3.p2.p1.s'.s.t for parameters of this transition + else e.add(createPredCall(tout,curNextParamVars(d.getTransParams(tfqn)))); + } + List body = new ArrayList(); + if (d.getAllParams().isEmpty()) body.add(createOrFromList(e)); + else body.add(createSome(paramDecls(d.getAllParams()),createOrFromList(e))); + + //TODO add loop if all notenabled + + d.alloyString += d.addPredSimple(DashStrings.smallStepName,curNextDecls(),body); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java new file mode 100644 index 000000000..0e9b1fc37 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -0,0 +1,118 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import static ca.uwaterloo.watform.core.DashStrings.*; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.alloyasthelper.DeclExt; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddSnapshotSignature { + + public static void addSnapshotSignature(DashModule d){ + if (DashOptions.isElectrum) { + // if Electrum add var sigs + // scopesUsed0, conf0, event0 + + d.alloyString += d.addVarSigSimple(scopesUsedName+"0", createVar(stateLabelName)); + d.alloyString += d.addVarSigSimple(confName+"0", createVar(stateLabelName)); + if (d.hasEvents()) + d.alloyString += d.addVarSigSimple(eventsName+"0", createVar(allEventsName)); + List cop; + for (int i = 1; i <= d.getMaxDepthParams(); i++) { + cop = new ArrayList (Collections.nCopies(i+1,createVar(identifierName))); + // scopesUsed 1, etc. + d.alloyString += d.addVarSigSimple( + scopesUsedName+Integer.toString(i), + DashUtilFcns.newListWith(cop, createVar(stateLabelName))); + // conf 1, etc. + d.alloyString += d.addVarSigSimple( + confName+Integer.toString(i), + DashUtilFcns.newListWith(cop, createVar(stateLabelName))); + // event 1, etc. + if (d.hasEvents() & d.hasEventsAti(i)) + d.alloyString += d.addVarSigSimple( + eventsName+Integer.toString(i), + DashUtilFcns.newListWith(cop, createVar(allEventsName))); + } + + // stable: one boolean; + if (d.hasConcurrency()) { + d.alloyString += d.addVarSigSimple(stableName, createVar(boolName)); + } + // add dynamic symbols (vars and buffers) + /* + for (DashDynSymbols v: getDynSymbols()) { + List prms = Collections.nCopies(IdentifiersName, v.getParams().size()); + addVarSigSimple( + v.getFullyQualName(), + createArrowList(prms+v.createAlloyTyp())); + } + */ + } else { + // if traces/tcmc sig Snapshot {} with fields + List decls = new ArrayList(); + + // scopesUsed0, conf0, event0 + //if (d.transAtThisParamDepth(0)) + decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", stateLabelName)); + decls.add(DeclExt.newSetDeclExt(confName+"0", stateLabelName)); + if (d.hasEvents()) + decls.add(DeclExt.newSetDeclExt(eventsName+"0", allEventsName)); + List cop; + for (int i = 1; i <= d.getMaxDepthParams(); i++) { + cop = Collections.nCopies(i+1,identifierName); + // scopesUsed 1, etc. + //if (d.transAtThisParamDepth(i)) + decls.add(DeclExt.newSetDeclExt( + scopesUsedName+Integer.toString(i), + createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); + // conf 1, etc. + decls.add(DeclExt.newSetDeclExt( + confName+Integer.toString(i), + createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); + // event 1, etc. + if (d.hasEvents() && d.hasEventsAti(i)) + decls.add(new DeclExt( + eventsName+Integer.toString(i), + createArrowStringList(DashUtilFcns.newListWith(cop, allEventsName)))); + } + // stable: one boolean; + if (d.hasConcurrency()) { + decls.add(new DeclExt(stableName, createOne(createVar(boolName)))); + } + // add dynamic symbols (vars and buffers) + /* + for (DashDynSymbols v: getDynSymbols()) { + List prms = Collections.nCopies(IdentifiersName, v.getParams().size()); + decls.add(createDecl( + v.getFullyQualName(), + createArrowList(prms+v.createAlloyTyp()))); + } + */ + + d.alloyString += d.addSigWithDeclsSimple( snapshotName, decls); + } + d.alloyString += "\n"; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java new file mode 100644 index 000000000..1dc9d0ad2 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -0,0 +1,103 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.alloyasthelper.DeclExt; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddSpaceSignatures { + + + // same for Electrum and other + + public static void addSpaceSignatures(DashModule d) { + // abstract sig Statelabel {} + d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); + // Root + //if (d.hasConcurrency() || d.getImmChildren(d.getRootName()).isEmpty()) + d.alloyString += d.addExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + //else + //d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + //System.out.println(d.getRootName()); + recurseCreateStateSpaceSigs(d, d.getRootName()); + d.alloyString += "\n"; + + // we don't need transition names anymore (rather we use scopes) + // abstract sig TransLabel {} + // d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); + // add all transitions as one sig extensions of TransLabel + //for (String t : d.getTransNames()) { + //d.alloyString += d.addOneExtendsSigSimple(translateFQN(t), DashStrings.transitionLabelName); + //} + //d.alloyString += "\n"; + + // abstract sig Identifiers {} if this model has parametrized components + if (d.getMaxDepthParams() != 0) { + d.alloyString += d.addAbstractSigSimple(DashStrings.identifierName); + for (String s: d.getAllParams()) + d.alloyString += d.addExtendsSigSimple(s, DashStrings.identifierName); + d.alloyString += "\n"; + } + + // events ---------------------- + if (d.hasEvents()) { + d.alloyString += d.addAbstractSigSimple(DashStrings.allEventsName); + if (d.hasInternalEvents()) { + d.alloyString += d.addAbstractExtendsSigSimple(DashStrings.allInternalEventsName, DashStrings.allEventsName); + for (String e: d.getAllInternalEventNames()) { + d.alloyString += d.addOneExtendsSigSimple(translateFQN(e),DashStrings.allInternalEventsName); + } + } + if (d.hasEnvironmentalEvents()){ + d.alloyString += d.addAbstractExtendsSigSimple( DashStrings.allEnvironmentalEventsName, DashStrings.allEventsName); + for (String e: d.getAllEnvironmentalEventNames()) { + d.alloyString += d.addOneExtendsSigSimple(translateFQN(e),DashStrings.allEnvironmentalEventsName); + } + } + d.alloyString += "\n"; + } + + + /* + if (d.hasBuffers()) { + for (String i: d.getBufferIndices()) { + addSigSimple( i); + } + } + */ + } + private static void recurseCreateStateSpaceSigs(DashModule d, String parent) { + for (String child: d.getImmChildren(parent)) { + //System.out.println(translateFQN(child)+" "+translateFQN(parent)); + if (d.isLeaf(child) || d.isAnd(child)) d.alloyString += d.addOneExtendsSigSimple(translateFQN(child),translateFQN(parent)); + else + //if (d.isAnd(parent)) + //d.alloyString += d.addExtendsSigSimple(translateFQN(child), translateFQN(parent)); + //else + d.alloyString += d.addAbstractExtendsSigSimple(translateFQN(child), translateFQN(parent)); + if (!d.isLeaf(child)) recurseCreateStateSpaceSigs(d,child); + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java new file mode 100644 index 000000000..f80f6801e --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java @@ -0,0 +1,56 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.alloyasthelper.DeclExt; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddTestIfNextStable { + + // only one per module + public static void addTestIfNextStable(DashModule d) { + List decls = new ArrayList(); + List args = new ArrayList(); + List body = new ArrayList(); + if (!DashOptions.isElectrum) { + decls.addAll(curNextDecls()); + args.addAll(curNextVars()); + } + for (int i=0; i<= d.getMaxDepthParams(); i++) { + decls.add(scopesUsedDecl(i)); + args.add(scopesUsedVar(i)); + if (d.hasEventsAti(i)) { + decls.add(eventsDecl(i)); + args.add(eventsVar(i)); + } + } + for (String tfqn: d.getAllTransNames()) { + String tout = translateFQN(tfqn); + body.add(createNot( + createPredCall(tout + DashStrings.enabledAfterStepName, args))); + } + d.alloyString += d.addPredSimple(DashStrings.testIfNextStableName,decls,body); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTrans.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTrans.java new file mode 100644 index 000000000..db79c20ff --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTrans.java @@ -0,0 +1,63 @@ + package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +//import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import static ca.uwaterloo.watform.core.DashStrings.*; +//import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddTrans { + + // -------------------------------------------------------------------------------------- + /* + pred t1[s:Snapshot,s':Snapshot,pparam0:param0,pparam1:param1,pparam2:param2,...] = + pparam2.pparam1.pparam0.s.pre_1 and + pparam2.pparam1.pparam0.s'.s.post_1 and + pparam2.pparam1.pparam0.s'.s'.semantics_t1 + */ + public static void addTrans(DashModule d, String tfqn) { + + // e.g. [ClientId,ServerId.,,,] + List prs = d.getTransParams(tfqn); + List body = new ArrayList(); + String tout = translateFQN(tfqn); // output FQN + + if (DashOptions.isElectrum) { + // pre_transName[ p0, p1, p2] -> p2.p1.p0.pre_transName + body.add(createPredCall(tout+ preName, paramVars(prs))); + // p2.p1.p0.post_transName + body.add(createPredCall(tout + postName, paramVars(prs))); + // p2.p1.p0.semantics_transName + //body.add(createPredCall(tout + semanticsName, paramVars(prs))); + } else { + // pre_transName[s, p0, p1, p2] -> p2.p1.p0.s.pre_transName + body.add(createPredCall(tout + preName, curParamVars(prs))); + // p2.p1.p0.s'.s.post_transName + body.add(createPredCall(tout + postName, curNextParamVars(prs))); + // p2.p1.p0.s'.s.semantics_transName + //body.add(createPredCall(tout + semanticsName, curNextParamVars(prs))); + } + d.alloyString += d.addPredSimple(tout, curNextParamsDecls(prs), body); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java new file mode 100644 index 000000000..8a1ead39d --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -0,0 +1,139 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.alloyasthelper.DeclExt; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddTransIsEnabledAfterStep { + // --------------------------------------------------- + /* + // this is considering all instances of t1s (thus, the existential quantification) + pred t1_enabledAfterStep[ + s:Snapshot,s':Snapshot, + pParam0: Param0, ... + t:TransitionLabel, // parameters don't matter for orthogonality + ge:EventLabel ] + { // b/c below is exists params, the params don't matter + src_state_t1 in s'.confi // where i is depth of src_state, + guard_cond_t1[s'] // may depend on params + (s.stable = True) => + no t1.notOrthogonal & t + for all of t1's triggering events and forall n + (if trig_ev_t1 is internal, line below is false) + trig_ev_t1 in (chop0(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) ... + ge) + else { + no t1.notOrthogonal & (t + s.scopesUsed0 + s.scopesUsed1.TransLabel + s.scopesUsed2.TransLabel + s.scopesUsed3.TransLabel ...) + for all of t1's triggering events and forall n + trig_ev_t1 in (s.event0.EventLabel + s.event1.EventLabel + s.event2.EventLabel ... + ge) + } + } + */ + public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { + + //TODO fix this one + + String tout = translateFQN(tfqn); + List prs = d.getTransParams(tfqn); + List decls = new ArrayList(); + List body = new ArrayList(); + + if (!DashOptions.isElectrum) { + decls.addAll(curNextDecls()); + } + for (int i=0; i<= d.getMaxDepthParams(); i++) { + decls.add(scopesUsedDecl(i)); + if (d.hasEventsAti(i)) { + decls.add(eventsDecl(i)); + } + } + + + // p3 -> p2 -> p1 -> src in s'.confVar(i) + // src does not have to be a basic state + body.add(createIn(d.getTransSrc(tfqn).toAlloy(),nextConf(prs.size()))); + + // guard condition is true is ' + // TOD + d.alloyString += d.addPredSimple(tout+DashStrings.enabledAfterStepName,decls,body); + /* + ArrayList o = new ArrayList(); + + + // src does not have to be a basic state + Expr src = createVar(dash.getTransSrc(t)); + ArrayList psList = createVars(prs); + List trig_ev = dash.transTable.get(t).getWhen(); + List int_trig_ev = trig_ev.stream().filter(ev -> ev.isInternal()).collect(Collectors.toList()); + + // p3 -> p2 -> p1 -> src in s'.confVar(i) + o.add(createIn(createArrowList(createVars(prs).add(src)),nextConf(prs.size()))); + + // guard_cond_t1 [s'] + // final parameter (usually s') should not be used in precondition + o.add(dash.getTransGuard(t).convertToAlloy(dash.symbolTable, nextVar(), null, prs)); + + + // no t1.notOrthogonal & (t + s.scopesUsed + s.scopesUsed1 |> TransitionLabel + scopesUsed2 |> TransitionLabel + ...) + Expr elseExpr = createNo( + createAnd( + createNonOrthogonalExpr(t),createPlus(createVar(t), + createChoppedGroup(prs.size(),DashStrings.scopesUsedName,DashStrings.transitionLabelName)))); + elseExpr = createAnd( + elseExpr, + createIn( + createPlusList(createVarList(trig_ev)), + createPlus( + // chop(s.event0,EventLabel + chop(s.event1,EventLabel) + chop(s.event2,EventLabel) + createChoppedGroup(prs.size(),DashStrings.eventName,DashStrings.eventLabelName), + ge))); + + if (int_trig_ev == null) { + // no t1.notOrthogonal & t + Expr ifExpr = createNo(createAnd(createNonOrthogonalExpr(t),createVar(t))); + ifExpr = createAnd( + ifExpr, + createIn( + createPlusList(createVarList(trig_ev)), + // chop(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) + createPlus(createChoppedGroup(prs.size(),DashStrings.eventName,DashStrings.environmentEventName),ge))) + body.add(createITE(sStableTrue(),ifExpr,elseExpr)); + } else { + body.add(createITE(sStableTrue(),createFalse(),elseExpr)); + } + */ + /* + List decls = curNextParamsDecls(prs); + decls.add((Decl) new DeclExt(DashStrings.tName, DashStrings.transitionLabelName)); + if (d.hasEvents()) + decls.add((Decl) DeclExt.newSetDeclExt(DashStrings.geName, DashStrings.eventLabelName)); + // tmp + + d.alloyString += "\n"; + */ + } + + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java new file mode 100644 index 000000000..e87575a99 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -0,0 +1,223 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import static ca.uwaterloo.watform.core.DashStrings.*; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashRef; +import ca.uwaterloo.watform.core.DashErrors; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.alloyasthelper.DeclExt; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddTransPost { + + /* + pred post_t1[s,s':Snapshot] { + forall i: confi' = confi - exitedi + enteredi + forall i : scopesUsedi' = scopesUsedi + scopesUsed + action_t1[s,s'] + testIfNextStable[s,s',t1,t1_send_ev] => { + s'.stable = True + s.stable = True => { + // case 1 + // big step = one small step + // only internal events are those generated by t1 + // allow env events to change + forall i: eventsi' & InternalEvents = t1_send_ev (if i) + } else { + // case 2 + // last small step of the big step + // add t1's gen events to the internal events + // allow env events to change + forall i: eventsi' & InternalEvent = + t1_send_ev (if i) + (InternalEvent & eventsi) + } + } else { + stable' = False + env_vars_unchanged[s,s'] + s.table = True => { + // case 3 + // first small step of the big step + // only internal events are those generated by t1 + forall i: eventsi' & InternalEvent = t1_send_ev (if i) + // env events stay the same + eventsi' & EnvironmentlEvent = eventsi & EnvironmentalEvent + } else { + // case 4 + // intermediate small step + // add t1's gen event to the events + // env events don't change + forall i: eventsi' = events + t1_send_ev (if i) + } + } + } + */ + + public static void addTransPost(DashModule d, String tfqn) { + String tout = translateFQN(tfqn); + + List prs = d.getTransParams(tfqn); + + List body = new ArrayList(); + + // confi' = confi - exitedi + enteredi + List entered = d.entered(tfqn); + List exited = d.exited(tfqn); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List ent = DashRef.hasNumParams(entered,i).stream() + .map(x -> x.toAlloy()) + .collect(Collectors.toList()); + List exi = DashRef.hasNumParams(exited,i).stream() + .map(x -> x.toAlloy()) + .collect(Collectors.toList()); + Expr e = curConf(i); + if (!exi.isEmpty()) e = createDiff(e,createDiffList(exi)); + if (!ent.isEmpty()) e = createUnion(e,createUnionList(ent)); + body.add(createEquals(nextConf(i),e)); + } + // scopesUsedi' = scopesUsedi + scopesUsed + List sU = d.scopesUsed(tfqn); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List u = DashRef.hasNumParams(sU,i).stream() + .map(x -> x.toAlloy()) + .collect(Collectors.toList()); + Expr e = curConf(i); + if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); + e = createEquals(nextConf(i),e); + } + + DashRef ev = d.getTransSend(tfqn); + Expr rhs, rhs1, q; + + // case 1 + // forall i. eventsi' & AllInternalEvents = t1_send (if i) + // eventsi' & AllIntermalEvents = none (if not i) + List case1 = new ArrayList(); + Expr c1; + for (int i=0;i <= d.getMaxDepthParams(); i++) { + if (d.hasEventsAti(i)) { + if (ev != null && ev.getParamValues().size() == i) rhs = ev.toAlloy(); + else rhs = createNone(); + case1.add(createEquals( + createIntersect(nextEvents(i),allInternalEventsVar()), + rhs)); + } + } + if (case1.isEmpty()) c1 = createTrue(); + else c1 = createAndFromList(case1); + + // case 2 + // forall i: eventsi' & InternalEvent = t1_send_ev (if i) + (InternalEvent & eventsi) + List case2 = new ArrayList(); + Expr c2; + for (int i=0;i <= d.getMaxDepthParams(); i++) { + if (d.hasEventsAti(i)) { + q = createIntersect(allInternalEventsVar(), curEvents(i)); + if (ev != null && ev.getParamValues().size() == i) rhs = createUnion(ev.toAlloy(), q); + else rhs = q; + case2.add(createEquals( + createIntersect(nextEvents(i),allInternalEventsVar()), + rhs)); + } + } + if (case2.isEmpty()) c2 = createTrue(); + else c2 = createAndFromList(case2); + + // case 3 + // forall i: (eventsi' & InternalEvent = t1_send_ev (if i)) + // (eventsi' & InternalEvent = none) (if not i) + // and (eventsi' & EnvironmentalEvent = eventsi & EnvironmentalEvent) + List case3 = new ArrayList(); + Expr c3; + for (int i=0;i <= d.getMaxDepthParams(); i++) { + if (d.hasEventsAti(i)) { + if (ev != null && ev.getParamValues().size() == i) rhs1 = ev.toAlloy(); + else rhs1 = createNone(); + case3.add(createAnd( + createEquals( + createIntersect(nextEvents(i),allInternalEventsVar()), + rhs1), + createEquals( + createIntersect(nextEvents(i),allEnvironmentalEventsVar()), + createIntersect(curEvents(i),allEnvironmentalEventsVar()) ))); + } + } + if (case3.isEmpty()) c3 = createTrue(); + else c3 = createAndFromList(case3); + + // case 4 + // forall i. eventsi' = eventsi + t1_send (if i) + // eventsi' = eventsi (if not i) + List case4 = new ArrayList(); + Expr c4; + for (int i=0;i <= d.getMaxDepthParams(); i++) { + if (d.hasEventsAti(i)) { + if (ev != null && ev.getParamValues().size() == i) + case4.add(createEquals(nextEvents(i),createUnion(curEvents(i), ev.toAlloy()))); + } + } + if (case4.isEmpty()) c4 = createTrue(); + else c4 = createAndFromList(case4); + + body.add( + createITE(createTestIfNextStableCall(d, tfqn), + createAnd( + nextStableTrue(), + createITE (curStableTrue(), + c1, + c2)), + createAnd( + nextStableFalse(), + createITE(curStableTrue(), + c3, + c4)))); + + d.alloyString += d.addPredSimple(tout+postName,curNextParamsDecls(prs),body); + } + + // pred call: testIfNextStable[s,s',scope1, scope2, ... , send1, send2, ...] + // where scopei, evi is "none" if this transition's scope and send event + private static Expr createTestIfNextStableCall(DashModule d, String tfqn) { + List args = new ArrayList(); + if (!DashOptions.isElectrum) { + args.add(curVar()); + args.add(nextVar()); + } + List sU = d.scopesUsed(tfqn); + DashRef ev = d.getTransSend(tfqn); + for (int i=0; i <= d.getMaxDepthParams(); i++) { + //TODO could only have scopesUsedi for i that has scopesUsed + List u = DashRef.hasNumParams(sU,i).stream() + .map(x -> x.toAlloy()) + .collect(Collectors.toList()); + if (u.size() == 1) args.add(u.get(0)); + else if (u.size() ==0 ) args.add(createNone()); + else { DashErrors.createTestIfNextStableCallMultipleScopesAtSameLevel(); return null; } + if (d.hasEventsAti(i)) { + if (ev != null && ev.getParamValues().size() == i) args.add(ev.toAlloy()); + else args.add(createNone()); + } + } + return createPredCall(testIfNextStableName,args); + } + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java new file mode 100644 index 000000000..1f1c087b4 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -0,0 +1,101 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.alloyasthelper.DeclExt; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddTransPre { + // -------------------------------------------------------------------------------------- + /* + pred pre_t1[s:Snapshot,pparam0:Param0, ...] { + src_state_t1 in .s.conf + orthogonal to any scopes uses + guard_cond_t1 [s] + s.stable = True => + { // beginning of a big step + // transition can be triggered only by environmental events + .trig_events_t1 in (s.events & ExternalEvent ) + } else { + // intermediate snapshot + // transition can be triggered by any type of event + .trig_events_t1 in s.events + } + } + Assumption: prs for src state and trig events are a subset of prs for trans + */ + public static void addTransPre(DashModule d, String tfqn) { + List prs = d.getTransParams(tfqn); + List body = new ArrayList(); + String tout = translateFQN(tfqn); + + // p3 -> p2 -> p1 -> src in s.confVar(i) + // src does not have to be a basic state + body.add(createIn(d.getTransSrc(tfqn).toAlloy(),curConf(prs.size()))); + + // has a scope that is orthogonal to any scopes used + List nonO = d.nonOrthogonalScopesOf(tfqn); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List u = DashRef.hasNumParams(nonO,i).stream() + .map(x -> x.toAlloy()) + .collect(Collectors.toList()); + // scopesUsedi' = scopesUsedi - exitedi + enteredi + Expr e = curConf(i); + for (Expr x: u) body.add(createNot(createIn(x,scopesUsedVar(i)))); + } + + // event trigger + // only one triggering event + if (d.hasConcurrency() && d.getTransOn(tfqn) != null && d.hasEnvironmentalEvents()) { + // trig_events_t1 + DashRef ev = d.getTransOn(tfqn); + int sz = ev.getParamValues().size(); + Expr ifBranch = createIn(ev.toAlloy(), + createIntersect( + curEvents(sz), + allEnvironmentalEventsVar())); + Expr elseBranch = createIn(ev.toAlloy(), curEvents(sz)); + body.add(createITE( + curStableTrue(), + ifBranch, + elseBranch + )); + } else if (d.getTransOn(tfqn) != null) { + DashRef ev = d.getTransOn(tfqn); + int sz = ev.getParamValues().size(); + body.add(createIn(ev.toAlloy(),curEvents(sz))); + } + + /* + // TODO + // guard_cond_t1 [s] + o.add(d.getTransGuard(t).convertToAlloy(d.symbolTable, curVar(), nextVar())); + */ + + // not a higher priority transition enabled + d.alloyString += d.addPredSimple(tout+DashStrings.preName, curParamsDecls(prs), body); + d.alloyString += "\n"; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java new file mode 100644 index 000000000..16b250da8 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -0,0 +1,220 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.alloyasthelper.DeclExt; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +public class Common { + + // common decls + public static Decl curDecl() { + return (Decl) new DeclExt(DashStrings.curName, DashStrings.snapshotName); + } + public static Decl nextDecl() { + return (Decl) new DeclExt(DashStrings.nextName, DashStrings.snapshotName); + } + public static Decl paramDecl(String n) { + return (Decl) new DeclExt(DashStrings.pName+n, n); + } + public static List curNextDecls() { + List o = new ArrayList(); + if (!DashOptions.isElectrum) { + o.add(curDecl()); + o.add(nextDecl()); + } + return o; + } + public static List paramDecls(List prs) { + List o = new ArrayList(); + for (String n: prs) o.add(paramDecl(n)); + return o; + } + public static List curParamsDecls(List prs) { + List o = new ArrayList(); + if (!DashOptions.isElectrum) o.add(curDecl()); + o.addAll(paramDecls(prs)); + return o; + } + public static List curNextParamsDecls(List prs) { + List o = new ArrayList(); + if (!DashOptions.isElectrum) { o.add(curDecl()); o.add(nextDecl()); } + o.addAll(paramDecls(prs)); + return o; + } + public static Decl eventsDecl(int i) { + return (Decl) new DeclExt(DashStrings.eventsName + i, DashStrings.allEventsName); + } + public static Decl scopesUsedDecl(int i) { + return (Decl) new DeclExt(DashStrings.scopesUsedName + i, DashStrings.stateLabelName); + } + + // common vars + // s + public static ExprVar curVar() { + return createVar(DashStrings.curName); + } + // s' + public static ExprVar nextVar() { + return createVar(DashStrings.nextName); + } + public static List curNextVars() { + List o = new ArrayList(); + o.add(curVar()); + o.add(nextVar()); + return o; + } + // [n1,n2,...] + public static List paramVars(List names) { + List o = new ArrayList(); + for (String n: names) o.add(createVar(DashStrings.pName+n)); + return o; + } + public static List curParamVars(List params) { + List o = new ArrayList(); + o.add(curVar()); + o.addAll(paramVars(params)); + return o; + } + public static List curNextParamVars(List params) { + List o = new ArrayList(curNextVars()); + o.addAll(paramVars(params)); + return o; + } + + public static Expr stable() { + return createVar(DashStrings.stableName); + } + + public static Expr allInternalEventsVar() { + return createVar(DashStrings.allInternalEventsName); + } + public static Expr allEnvironmentalEventsVar() { + return createVar(DashStrings.allEnvironmentalEventsName); + } + + public static Expr scopesUsedVar(int size) { + return createVar(DashStrings.scopesUsedName + size); + } + public static Expr confVar(int size) { + return createVar(DashStrings.confName + size); + } + public static Expr eventsVar(int size) { + return createVar(DashStrings.eventsName + size); + } + + public static Expr curScopesUsed(int size) { + return curJoinExpr(scopesUsedVar(size)); + } + // s'.scopesUsed5 + public static Expr nextScopesUsed(int size) { + return nextJoinExpr(scopesUsedVar(size)); + } + // s.conf4 + public static Expr curConf(int size) { + return curJoinExpr(confVar(size)); + } + // s'.conf3 + public static Expr nextConf(int size) { + return nextJoinExpr(confVar(size)); + } + // s.event4 + public static Expr curEvents(int size) { + return curJoinExpr(eventsVar(size)); + } + // s'.event3 + public static Expr nextEvents(int size) { + return nextJoinExpr(eventsVar(size)); + } + + // s.stable == boolean/True + public static Expr curStableTrue() { + return createEquals(curJoinExpr(stable()),createTrue()); + } + // s.stable == boolean/False + public static Expr curStableFalse() { + return createEquals(curJoinExpr(stable()),createFalse()); + } + // s'.stable == boolean/True + public static Expr nextStableTrue() { + return createEquals(nextJoinExpr(stable()),createTrue()); + } + // s'.stable == boolean/False + public static Expr nextStableFalse() { + return createEquals(nextJoinExpr(stable()),createFalse()); + } + + // s.name + public static Expr curJoinExpr(Expr e) { + return createJoin(curVar(), e); + } + //s'.name + public static Expr nextJoinExpr(Expr e) { + if (DashOptions.isElectrum) { + //TODO -- prime all variables?? + return createTrue(); + } else { + return createJoin(nextVar(), e); + } + } + // p3 -> p2 -> p1 -> x + public static Expr paramsToXArrow(List prs, String x) { + Collections.reverse(prs); + Expr e = createVar(x); + for (String p: prs) { + e = createArrow(createVar(p),e); + } + return e; + } + + + + + /* + public static Expr predJoinCurParams(String name, List prs) { + //p2.p1.p0.s.name + Expr e = createVar(name); + List prsVarList = convertParamsToVars(prs); + if (!DashOptions.isElectrum) e = createJoin(curVar(),e); + if (prs!= null) { + Collections.reverse(prsVarList); + prsVarList.add(e); + System.out.println("predJoinCurParams: " +prsVarList); + Expr x = createJoinList(prsVarList); + System.out.println("Join of prsVarList: " + x); + return createJoinList(prsVarList) ; + } else return e; + } + public static Expr predJoinCurNextParams(String name, List prs) { + //p2.p1.p0.s'.s.pre_transName + Expr e = createVar(name); + List prsVarList = convertParamsToVars(prs); + if (!DashOptions.isElectrum) e = createJoin(nextVar(),createJoin(curVar(),e)); + if (prs!=null) { + Collections.reverse(prsVarList); + prsVarList.add(e); + return createJoinList(prsVarList) ; + } else return e; + } + */ +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 606916351..2657a71a9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -1,705 +1,27 @@ /* - * Functions for translating Dash to Alloy - * The translation is done in place so the Dash - * module contains the original "state" and its - * translation to Alloy but there - * is too much code to put this all in one file + * The translation is done in place on the Dash module. + * This is the same for Electrum and other. */ package ca.uwaterloo.watform.dashtoalloy; -import java.util.Collections; -import java.util.stream.Collectors; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; - -import edu.mit.csail.sdg.ast.Decl; -import edu.mit.csail.sdg.ast.ExprVar; -import edu.mit.csail.sdg.ast.Expr; - -import ca.uwaterloo.watform.core.DashOptions; -import ca.uwaterloo.watform.core.DashStrings; -import ca.uwaterloo.watform.core.DashUtilFcns; -import ca.uwaterloo.watform.core.DashRef; - -// shortens the code to import these statically -import static ca.uwaterloo.watform.core.DashFQN.*; -import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; - -import ca.uwaterloo.watform.alloyasthelper.DeclExt; -import ca.uwaterloo.watform.alloyasthelper.ExprToString; - import ca.uwaterloo.watform.parser.DashModule; -import ca.uwaterloo.watform.parser.CompModuleHelper; public class DashToAlloy { - private DashModule d; - - public DashToAlloy(DashModule dash) { - this.d = dash; - } - - public void translate() { - assert(d.hasRoot()); - // translation is done in place - createSpaceSignatures(); // state, transition, parameter, buffer space - createSnapshotSig(); - for (String t: d.getTransNames()) { - createTransPre(t); - createTransPost(t); - createTransSemantics(t); - createTransIsEnabledAfterStep(t); - createTrans(t); - } - createSmallStep(); - } - - // make it shorter internally - private String fqn(String s) { - // internally we use "/" to separate FQN parts - // because Alloy names might use "_" - // but we can't output "/" in Alloy identifiers - // so before outputting we convert "/" to "_" - // for everything - return convertFQN(s); - } - private void createSpaceSignatures() { - // abstract sig Statelabel {} - d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); - // Root - //if (d.hasConcurrency() || d.getImmChildren(d.getRootName()).isEmpty()) - d.alloyString += d.addExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); - //else - //d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); - recurseCreateStateSpaceSigs(d.getRootName()); - d.alloyString += "\n"; - - // abstract sig TransLabel {} - // d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); - // add all transitions as one sig extensions of TransLabel - //for (String t : d.getTransNames()) { - //d.alloyString += d.addOneExtendsSigSimple(fqn(t), DashStrings.transitionLabelName); - //} - //d.alloyString += "\n"; - - // abstract sig Identifiers {} if this model has parameterized components - if (d.getMaxDepthParams() != 0) { - d.alloyString += d.addAbstractSigSimple(DashStrings.identifierName); - for (String s: d.getAllParams()) - d.alloyString += d.addExtendsSigSimple(s, DashStrings.identifierName); - d.alloyString += "\n"; - } - - /* - if (d.hasEvents()) { - addAbstractSigSimple(eventLabelName); - if (d.hasInternalEvents()) { - addAbstractExtendsSigSimple( environmentEventName, eventLabelName); - for (e: d.getInternalEventNames()) { - addOneExtendsSigSimple(e,internalEventName) - } - } - if (d.hasExternalEvents()){ - addAbstractExtendsSigSimple( internalEventName, eventLabelName); - for (e: d.getExternalEventNames()) { - addOneExtendsSigSimple(e,internalEventName) - } - } - } - - - - if (d.hasBuffers()) { - for (String i: d.getBufferIndices()) { - addSigSimple( i); - } - } - */ - } - private void recurseCreateStateSpaceSigs(String parent) { - for (String child: d.getImmChildren(parent)) { - if (d.isLeaf(child) || d.isAnd(child)) d.alloyString += d.addOneExtendsSigSimple(fqn(child),fqn(parent)); - else - //if (d.isAnd(parent)) - //d.alloyString += d.addExtendsSigSimple(fqn(child), fqn(parent)); - //else - d.alloyString += d.addAbstractExtendsSigSimple(fqn(child), fqn(parent)); - if (!d.isLeaf(child)) recurseCreateStateSpaceSigs(child); - } - } - private void createSnapshotSig(){ - if (DashOptions.isElectrum) { - // if Electrum add var sigs - // scopesUsed0, conf0, event0 - - //if (d.transAtThisParamDepth(0)) - d.alloyString += d.addVarSigSimple(DashStrings.scopesUsedName+"0", createVar(DashStrings.stateLabelName)); - d.alloyString += d.addVarSigSimple(DashStrings.confName+"0", createVar(DashStrings.stateLabelName)); - if (d.hasEvents()) - d.alloyString += d.addVarSigSimple(DashStrings.eventName+"0", createVar(DashStrings.eventLabelName)); - List cop; - for (int i = 1; i <= d.getMaxDepthParams(); i++) { - cop = new ArrayList (Collections.nCopies(i+1,createVar(DashStrings.identifierName))); - //if (d.transAtThisParamDepth(i)) - // scopesUsed 1, etc. - d.alloyString += d.addVarSigSimple( - DashStrings.scopesUsedName+Integer.toString(i), - DashUtilFcns.newListWith(cop, createVar(DashStrings.stateLabelName))); - // conf 1, etc. - d.alloyString += d.addVarSigSimple( - DashStrings.confName+Integer.toString(i), - DashUtilFcns.newListWith(cop, createVar(DashStrings.stateLabelName))); - // event 1, etc. - if (d.hasEvents()) - d.alloyString += d.addVarSigSimple( - DashStrings.eventName+Integer.toString(i), - DashUtilFcns.newListWith(cop, createVar(DashStrings.eventLabelName))); - } - - // stable: one boolean; - if (d.hasConcurrency()) { - d.alloyString += d.addVarSigSimple(DashStrings.stableName, createVar(DashStrings.boolName)); - } - // add dynamic symbols (vars and buffers) - /* - for (DashDynSymbols v: getDynSymbols()) { - List prms = Collections.nCopies(DashStrings.IdentifiersName, v.getParams().size()); - addVarSigSimple( - v.getFullyQualName(), - createArrowList(prms+v.createAlloyTyp())); - } - */ - } else { - // if traces/tcmc sig Snapshot {} with fields - List decls = new ArrayList(); - - // scopesUsed0, conf0, event0 - //if (d.transAtThisParamDepth(0)) - decls.add(DeclExt.newSetDeclExt(DashStrings.scopesUsedName+"0", DashStrings.stateLabelName)); - decls.add(DeclExt.newSetDeclExt(DashStrings.confName+"0", DashStrings.stateLabelName)); - if (d.hasEvents()) - decls.add(DeclExt.newSetDeclExt(DashStrings.eventName+"0", DashStrings.eventLabelName)); - List cop; - for (int i = 1; i <= d.getMaxDepthParams(); i++) { - cop = Collections.nCopies(i+1,DashStrings.identifierName); - // scopesUsed 1, etc. - //if (d.transAtThisParamDepth(i)) - decls.add(DeclExt.newSetDeclExt( - DashStrings.scopesUsedName+Integer.toString(i), - createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName)))); - // conf 1, etc. - decls.add(DeclExt.newSetDeclExt( - DashStrings.confName+Integer.toString(i), - createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName)))); - // event 1, etc. - if (d.hasEvents()) - decls.add(new DeclExt( - DashStrings.eventName+Integer.toString(i), - createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.eventLabelName)))); - } - // stable: one boolean; - if (d.hasConcurrency()) { - decls.add(new DeclExt(DashStrings.stableName, createOne(createVar(DashStrings.boolName)))); - } - // add dynamic symbols (vars and buffers) - /* - for (DashDynSymbols v: getDynSymbols()) { - List prms = Collections.nCopies(DashStrings.IdentifiersName, v.getParams().size()); - decls.add(createDecl( - v.getFullyQualName(), - createArrowList(prms+v.createAlloyTyp()))); - } - */ - - d.alloyString += d.addSigWithDeclsSimple( DashStrings.snapshotName, decls); - } - d.alloyString += "\n"; - } - // -------------------------------------------------------------------------------------- - /* - pred pre_t1[s:Snapshot,pparam0:Param0, ...] { - src_state_t1 in .s.conf - guard_cond_t1 [s] - s.stable = True => - { // beginning of a big step - // transition can be triggered only by environmental events - .trig_events_t1 in (s.events & EnvironmentalEvent ) - } else { - // intermediate snapshot - // transition can be triggered by any type of event - .trig_events_t1 in s.events - } - } - Assumption: prs for src state and trig events are a subset of prs for trans - */ - private void createTransPre(String t) { - List prs = d.getTransParams(t); - List body = new ArrayList(); - - - // p3 -> p2 -> p1 -> src in s.confVar(i) - // src does not have to be a basic state - - body.add(createIn(d.getTransSrc(t).toAlloy(),curConf(prs.size()))); - List nonO = d.nonOrthogonalScopesOf(t); - for (int i=0;i <= d.getMaxDepthParams(); i++) { - List u = hasNumParams(nonO,i).stream().map(x -> x.toAlloy()).collect(Collectors.toList()); - // scopesUsedi' = scopesUsedi - exitedi + enteredi - Expr e = curConf(i); - for (Expr x: u) body.add(createNot(createIn(x,scopesUsed(i)))); - } - // orthogonality - // nonOrthogonalScopes not in scopesUsed - /* - // guard_cond_t1 [s] - o.add(d.getTransGuard(t).convertToAlloy(d.symbolTable, curVar(), nextVar())); - - // events - if (d.hasConcurrency() && d.getTransTrigger(t) != null && d.hasEnvironmentalEvents()) { - // trig_events_t1 - ArrayList trigEvents = new ArrayList(); - for (e:d.getTransTriggerEvents(t)) { - // p3 -> p2 -> p1 -> event - trigEvents.add(createArrowList(createVars(d.getEventParams(e)).add(createVar(e)))); - } - Expr te = createPlus(trigEvents); - o.add(createITE( - createEquals(curStable(),createTrue()) - // have to look at different levels!! - createIn(te, createAnd(curEvents(),createVar(DashStrings.environmentEventName))), - createIn(te, curEvents())) - ); - } - Expr body = createAnd(o); - */ - - d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.preName, curParamsDecls(prs), body); - d.alloyString += "\n"; - } - private List hasNumParams(List dr, int i) { - // filter to ones that have this number of params - //System.out.println(i); - //System.out.println(dr); - List o = dr.stream() - .filter(x -> x.getParamValues().size() == i) - .collect(Collectors.toList()); - //System.out.println(o); - return o; - } - private void createTransPost(String t) { - List prs = d.getTransParams(t); - - List body = new ArrayList(); - - // confi' = confi - exitedi + enteredi - List entered = d.entered(t); - List exited = d.exited(t); - for (int i=0;i <= d.getMaxDepthParams(); i++) { - List ent = hasNumParams(entered,i).stream().map(x -> x.toAlloy()).collect(Collectors.toList()); - List exi = hasNumParams(exited,i).stream().map(x -> x.toAlloy()).collect(Collectors.toList()); - Expr e = curConf(i); - if (!exi.isEmpty()) e = createDiff(e,createDiffList(exi)); - if (!ent.isEmpty()) e = createUnion(e,createUnionList(ent)); - body.add(createEquals(nextConf(i),e)); - } - // scopesUsedi' = scopesUsedi + scopesUsed - List sU = d.scopesUsed(t); - for (int i=0;i <= d.getMaxDepthParams(); i++) { - List u = hasNumParams(sU,i).stream().map(x -> x.toAlloy()).collect(Collectors.toList()); - Expr e = curConf(i); - if (!u.isEmpty()) e = createUnion(e,createUnionList(u)); - body.add(createEquals(nextConf(i),e)); - } - - d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.postName,curNextParamsDecls(prs),body); - } - // ----------------------------------------------------------------------------- - /* - pred t1_semantics[s:Snapshot,s':Snapshot, pParam0: Param0, ... ] { - (s.stable = True) => { - s'.scopesUsed = t1 - } else { - s'.scopesUsed = s.scopesUsed + t1 - no t1.notOrthogonal & (s.scopesUsed0 + scopesUsed0 |> TransitionLabel + s.scopesUsed1 |> TransitionLabel + ...) - } - for all t in t1.higherPri - // all have same param values (or prefixes) because these trans are from srcs - // that are ances of the src of this transition - !pre_higherpri_trans[s,pParam0,pParam1] - !pre_higherpri_trans[s,pParam0] - // it depends on the params of the src state not on t1's params! ACK!!! - // maybe it is okay because pre_ of the trans has the correct parameters (might be trans params or something user has provided) - } - */ - private void createTransSemantics(String t) { - List body = new ArrayList(); - List prs = d.getTransParams(t); - String tfqn = convertFQN(t); // output FQN - - - // s'.scopesUsed = s.scopesUsed + t1 - // or - // s'.scopesUsed2 = s.scopesUsed2 + p2 -> p1 -> tfqn - // and other scopesUseds stay the same - List scopesUseds = new ArrayList(); - for (int i=0;i <= d.getMaxDepthParams(); i++) - if (d.transAtThisParamDepth(i)) - if (i == prs.size()) - if (DashOptions.isElectrum) - scopesUseds.add(createEquals( - scopesUsed(i), - createUnion(scopesUsed(i),paramsToXArrow(prs,tfqn)))); - else scopesUseds.add(createEquals( - nextTaken(i), - createUnion(curTaken(i),paramsToXArrow(prs,tfqn)))); - else - if (DashOptions.isElectrum) scopesUseds.add(createEquals(scopesUsed(i), curTaken(i))); - else scopesUseds.add(createEquals(nextTaken(i), curTaken(i))); - Expr elseExpr = createAnd(scopesUseds); - - // no trans "below" the scope of this trans with the same params can be scopesUsed - // (other params are for other parts of state hierarchy at this depth) - - // for the rest of the non-orthogonal trans, param values don't matter - - /* - if (notOrthogonal != null) { - elseExpr = - createAnd( - elseExpr, - // no t1.notOrthogonal & (s.scopesUsed + s.scopesUsed1 |> TransitionLabel + scopesUsed2 |> TransitionLabel + ...) - createNo( - createAnd( - createNonOrthogonalExpr(t), - createChoppedGroup(prs.size(),DashStrings.scopesUsedName,DashStrings.transitionLabelName)))); - } - */ - scopesUseds = new ArrayList(); - for (int i=0;i <= d.getMaxDepthParams(); i++) - if (d.transAtThisParamDepth(i)) - if (i == prs.size()) - if (DashOptions.isElectrum) - scopesUseds.add(createEquals( - scopesUsed(i), - paramsToXArrow(prs,tfqn))); - else scopesUseds.add(createEquals( - nextTaken(i), - paramsToXArrow(prs,tfqn))); - else - if (DashOptions.isElectrum) scopesUseds.add(createEquals(scopesUsed(i), createNone())); - else scopesUseds.add(createEquals(nextTaken(i), createNone())); - Expr firstscopesUsed = createAnd(scopesUseds); - if (d.hasConcurrency()) - body.add( - createITE(curStableTrue(), - // s'.scopesUsed = t1 - firstscopesUsed, - elseExpr) - ); - else - // will only have scopesUsed0 in it - body.add(firstscopesUsed); - - // priority - // depends on the src of this transition - for (String h: d.getHigherPriTrans(t)) { - List hprs = d.getTransParams(h); - // !pre_higherpri_trans[s,p0,p1] - // Note: all the parameter values will be the same - // only lower priority transitions could have more parameters - if (DashOptions.isElectrum) - body.add(createNot(createPredCall(convertFQN(h+DashStrings.preName),paramVars(hprs)))); - else - body.add(createNot(createPredCall(convertFQN(h+DashStrings.preName),curParamVars(hprs)))); - } - - - d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.semanticsName,curNextParamsDecls(prs),body); - d.alloyString += "\n"; - } - // --------------------------------------------------- - /* - // this is considering all instances of t1s (thus, the existential quantification) - pred t1_enabledAfterStep[ - s:Snapshot,s':Snapshot, - pParam0: Param0, ... - t:TransitionLabel, // parameters don't matter for orthogonality - ge:EventLabel ] - { // b/c below is exists params, the params don't matter - src_state_t1 in s'.confi // where i is depth of src_state, - guard_cond_t1[s'] // may depend on params - (s.stable = True) => - no t1.notOrthogonal & t - for all of t1's triggering events and forall n - (if trig_ev_t1 is internal, line below is false) - trig_ev_t1 in (chop0(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) ... + ge) - else { - no t1.notOrthogonal & (t + s.scopesUsed0 + s.scopesUsed1.TransLabel + s.scopesUsed2.TransLabel + s.scopesUsed3.TransLabel ...) - for all of t1's triggering events and forall n - trig_ev_t1 in (s.event0.EventLabel + s.event1.EventLabel + s.event2.EventLabel ... + ge) - } - } - */ - private void createTransIsEnabledAfterStep(String t) { - List prs = d.getTransParams(t); - /* - ArrayList o = new ArrayList(); - - - // src does not have to be a basic state - Expr src = createVar(dash.getTransSrc(t)); - ArrayList psList = createVars(prs); - List trig_ev = dash.transTable.get(t).getWhen(); - List int_trig_ev = trig_ev.stream().filter(ev -> ev.isInternal()).collect(Collectors.toList()); - - // p3 -> p2 -> p1 -> src in s'.confVar(i) - o.add(createIn(createArrowList(createVars(prs).add(src)),nextConf(prs.size()))); - - // guard_cond_t1 [s'] - // final parameter (usually s') should not be used in precondition - o.add(dash.getTransGuard(t).convertToAlloy(dash.symbolTable, nextVar(), null, prs)); - - - // no t1.notOrthogonal & (t + s.scopesUsed + s.scopesUsed1 |> TransitionLabel + scopesUsed2 |> TransitionLabel + ...) - Expr elseExpr = createNo( - createAnd( - createNonOrthogonalExpr(t),createPlus(createVar(t), - createChoppedGroup(prs.size(),DashStrings.scopesUsedName,DashStrings.transitionLabelName)))); - elseExpr = createAnd( - elseExpr, - createIn( - createPlusList(createVarList(trig_ev)), - createPlus( - // chop(s.event0,EventLabel + chop(s.event1,EventLabel) + chop(s.event2,EventLabel) - createChoppedGroup(prs.size(),DashStrings.eventName,DashStrings.eventLabelName), - ge))); - - if (int_trig_ev == null) { - // no t1.notOrthogonal & t - Expr ifExpr = createNo(createAnd(createNonOrthogonalExpr(t),createVar(t))); - ifExpr = createAnd( - ifExpr, - createIn( - createPlusList(createVarList(trig_ev)), - // chop(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) - createPlus(createChoppedGroup(prs.size(),DashStrings.eventName,DashStrings.environmentEventName),ge))) - body.add(createITE(sStableTrue(),ifExpr,elseExpr)); - } else { - body.add(createITE(sStableTrue(),createFalse(),elseExpr)); - } - */ - List decls = curNextParamsDecls(prs); - decls.add((Decl) new DeclExt(DashStrings.tName, DashStrings.transitionLabelName)); - if (d.hasEvents()) - decls.add((Decl) DeclExt.newSetDeclExt(DashStrings.geName, DashStrings.eventLabelName)); - // tmp - List body = new ArrayList(); - d.alloyString += d.addPredSimple(convertFQN(t)+DashStrings.isEnabledAfterStepName,decls,body); - d.alloyString += "\n"; - } - - // -------------------------------------------------------------------------------------- - /* - pred t1[s:Snapshot,s':Snapshot,pparam0:param0,pparam1:param1,pparam2:param2,...] = - pparam2.pparam1.pparam0.s.pre_1 and - pparam2.pparam1.pparam0.s'.s.post_1 and - pparam2.pparam1.pparam0.s'.s'.semantics_t1 - */ - private void createTrans(String t) { - // t is FQN - // e.g. [ClientId,ServerId.,,,] - List prs = d.getTransParams(t); - List body = new ArrayList(); - String tfqn = convertFQN(t); // output FQN - - if (DashOptions.isElectrum) { - // pre_transName[ p0, p1, p2] -> p2.p1.p0.pre_transName - body.add(createPredCall(tfqn + DashStrings.preName, paramVars(prs))); - // p2.p1.p0.post_transName - body.add(createPredCall(tfqn + DashStrings.postName, paramVars(prs))); - // p2.p1.p0.semantics_transName - body.add(createPredCall(tfqn + DashStrings.semanticsName, paramVars(prs))); - } else { - // pre_transName[s, p0, p1, p2] -> p2.p1.p0.s.pre_transName - body.add(createPredCall(tfqn + DashStrings.preName, curParamVars(prs))); - // p2.p1.p0.s'.s.post_transName - body.add(createPredCall(tfqn + DashStrings.postName, curNextParamVars(prs))); - // p2.p1.p0.s'.s.semantics_transName - body.add(createPredCall(tfqn + DashStrings.semanticsName, curNextParamVars(prs))); - } - d.alloyString += d.addPredSimple(tfqn, curNextParamsDecls(prs), body); - } - - // -------------------------------------------------------------------------------------- - /* - pred small_step [s:Snapshot, s': Snapshot] { - some pparam0 : Param0 , pparam1 : Param1 ... | - { // for all t’s at level i with params Param5, Param6, ... - (or t[s, s_next, pparam5, pparam6 ]) - // loop? big-step issue? - } - */ - private void createSmallStep() { - - // list of FQN of transitions - // does not have to be done in order of number of parameters b/c all disjuncted - ArrayList e = new ArrayList(); - for (String t: d.getTransNames()) { - String tfqn = convertFQN(t); // output FQN - // p3.p2.p1.s'.s.t for parameters of this transition - if (DashOptions.isElectrum) e.add(createPredCall(tfqn,paramVars(d.getTransParams(t)))); - else e.add(createPredCall(tfqn,curNextParamVars(d.getTransParams(t)))); - } - List body = new ArrayList(); - if (d.getAllParams().isEmpty()) body.add(createOr(e)); - else body.add(createSome(paramDecls(d.getAllParams()),createOr(e))); - - //TODO add loop if all notenabled - d.alloyString += d.addPredSimple(DashStrings.smallStepName,curNextDecls(),body); - } - - - - // common decls - private Decl curDecl() { - return (Decl) new DeclExt(DashStrings.curName, DashStrings.snapshotName); - } - private Decl nextDecl() { - return (Decl) new DeclExt(DashStrings.nextName, DashStrings.snapshotName); - } - private Decl paramDecl(String n) { - return (Decl) new DeclExt(DashStrings.pName+n, n); - } - private List curNextDecls() { - List o = new ArrayList(); - if (!DashOptions.isElectrum) { - o.add(curDecl()); - o.add(nextDecl()); - } - return o; - } - private List paramDecls(List prs) { - List o = new ArrayList(); - for (String n: prs) o.add(paramDecl(n)); - return o; - } - private List curParamsDecls(List prs) { - List o = new ArrayList(); - if (!DashOptions.isElectrum) o.add(curDecl()); - o.addAll(paramDecls(prs)); - return o; - } - private List curNextParamsDecls(List prs) { - List o = new ArrayList(); - if (!DashOptions.isElectrum) { o.add(curDecl()); o.add(nextDecl()); } - o.addAll(paramDecls(prs)); - return o; - } - - // common vars - // s - private ExprVar curVar() { - return createVar(DashStrings.curName); - } - // s' - private ExprVar nextVar() { - return createVar(DashStrings.nextName); - } - // [n1,n2,...] - private List paramVars(List names) { - List o = new ArrayList(); - for (String n: names) o.add(createVar(DashStrings.pName+n)); - return o; - } - private List curParamVars(List params) { - List o = new ArrayList(); - o.add(curVar()); - o.addAll(paramVars(params)); - return o; - } - private List curNextParamVars(List params) { - List o = new ArrayList(); - o.add(curVar()); - o.add(nextVar()); - o.addAll(paramVars(params)); - return o; - } - private Expr scopesUsed(int size) { - return createVar(DashStrings.scopesUsedName + size); - } - private Expr conf(int size) { - return createVar(DashStrings.confName + size); - } - private Expr stable() { - return createVar(DashStrings.stableName); - } - // s.scopesUsed5 - private Expr curTaken(int size) { - return curJoinExpr(scopesUsed(size)); - } - // s'.scopesUsed5 - private Expr nextTaken(int size) { - return nextJoinExpr(scopesUsed(size)); - } - // s.conf4 - private Expr curConf(int size) { - return curJoinExpr(conf(size)); - } - // s'.conf3 - private Expr nextConf(int size) { - return nextJoinExpr(conf(size)); - } - // s.stable == boolean/True - private Expr curStableTrue() { - return createEquals(stable(),createTrue()); - } - // s.name - private Expr curJoinExpr(Expr e) { - return createJoin(curVar(), e); - } - //s'.name - private Expr nextJoinExpr(Expr e) { - return createJoin(nextVar(), e); - } - // p3 -> p2 -> p1 -> x - private Expr paramsToXArrow(List prs, String x) { - Collections.reverse(prs); - Expr e = createVar(x); - for (String p: prs) { - e = createArrow(createVar(p),e); + public static void translate(DashModule d) { + assert(d.hasRoot()); // there is a Dash component in this module + AddSpaceSignatures.addSpaceSignatures(d); // state, transition, parameter, buffer space + AddSnapshotSignature.addSnapshotSignature(d); + for (String tfqn: d.getAllTransNames()) { + AddTransPre.addTransPre(d,tfqn); + AddTransPost.addTransPost(d,tfqn); + //createTransSemantics(t); + AddTransIsEnabledAfterStep.addTransIsEnabledAfterStep(d,tfqn); + AddTrans.addTrans(d,tfqn); } - return e; - } - /* - private Expr predJoinCurParams(String name, List prs) { - //p2.p1.p0.s.name - Expr e = createVar(name); - List prsVarList = convertParamsToVars(prs); - if (!DashOptions.isElectrum) e = createJoin(curVar(),e); - if (prs!= null) { - Collections.reverse(prsVarList); - prsVarList.add(e); - System.out.println("predJoinCurParams: " +prsVarList); - Expr x = createJoinList(prsVarList); - System.out.println("Join of prsVarList: " + x); - return createJoinList(prsVarList) ; - } else return e; + AddTestIfNextStable.addTestIfNextStable(d); + AddSmallStep.addSmallStep(d); } - private Expr predJoinCurNextParams(String name, List prs) { - //p2.p1.p0.s'.s.pre_transName - Expr e = createVar(name); - List prsVarList = convertParamsToVars(prs); - if (!DashOptions.isElectrum) e = createJoin(nextVar(),createJoin(curVar(),e)); - if (prs!=null) { - Collections.reverse(prsVarList); - prsVarList.add(e); - return createJoinList(prsVarList) ; - } else return e; - } - */ - - } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index add4d6160..007055c6a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -112,7 +112,7 @@ public String addAbstractExtendsSigSimple(String extension, String extended) { Pos.UNKNOWN, extension, ExprHelper.createVar(DashStrings.extendsName), - ExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), + ExprHelper.createExprVarList(new ArrayList(Arrays.asList(extended))), new ArrayList(), null, AttrType.ABSTRACT.makenull(Pos.UNKNOWN), @@ -134,7 +134,7 @@ public String addExtendsSigSimple(String extension, String extended) { Pos.UNKNOWN, extension, ExprHelper.createVar(DashStrings.extendsName), - ExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), + ExprHelper.createExprVarList(new ArrayList(Arrays.asList(extended))), new ArrayList(), null, null, @@ -156,7 +156,7 @@ public String addOneExtendsSigSimple(String extension, String extended) { Pos.UNKNOWN, extension, ExprHelper.createVar(DashStrings.extendsName), - ExprHelper.createVarList(new ArrayList(Arrays.asList(extended))), + ExprHelper.createExprVarList(new ArrayList(Arrays.asList(extended))), new ArrayList(), null, null, @@ -249,7 +249,7 @@ public String addVarSigSimple(String name, List typ) { * t is return type; null if predicate */ public String addPredSimple(String name, List decls, List eList) { - Expr body = ExprHelper.createAnd(eList); + Expr body = ExprHelper.createAndFromList(eList); addFunc(Pos.UNKNOWN, Pos.UNKNOWN, ExprHelper.createVar(name), null, decls, null, body); String s = new String(); s += DashStrings.predName + " " + name + "["; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index d7307a089..48bda211e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -233,13 +233,16 @@ public int getNumBuffers() { return numBuffers; } public boolean hasInternalEvents() { - return false; // (eventTable.hasInternalEvents()); + return eventTable.hasInternalEvents(); } public boolean hasEnvironmentalEvents() { - return false; //(eventTable.hasExternalEvents()); + return eventTable.hasEnvironmentalEvents(); } public boolean hasEvents() { - return false; //(hasInternalEvents() || hasEnvironmentalEvents()) + return eventTable.hasEvents(); + } + public boolean hasEventsAti(int i) { + return eventTable.hasEventsAti(i); } public boolean hasConcurrency() { return stateTable.hasConcurrency(root.name); @@ -277,19 +280,23 @@ public List getLeafStatesEnteredWithScope(DashRef context, DashRef s) { public List getAllAnces(String sfqn) { return stateTable.getAllAnces(sfqn); } - public String getClosestConcAnces(String sfqn) { - return stateTable.getClosestConcAnces(sfqn); + public String getClosestParamAnces(String sfqn) { + return stateTable.getClosestParamAnces(sfqn); } - public List getAllNonConcDesc(String sfqn) { - return stateTable.getAllNonConcDesc(sfqn); + public List getAllNonParamDesc(String sfqn) { + return stateTable.getAllNonParamDesc(sfqn); } public List getRegion(String sfqn) { return stateTable.getRegion(sfqn); } // stuff about transitions - public Set getTransNames() { - return transTable.getTransNames(); + public Set getAllTransNames() { + return transTable.getAllTransNames(); + } + + public List getParams(String tfqn) { + return transTable.getParams(tfqn); } public DashRef getTransSrc(String tfqn) { return transTable.getSrc(tfqn); @@ -297,6 +304,12 @@ public DashRef getTransSrc(String tfqn) { public DashRef getTransDest(String tfqn) { return transTable.getDest(tfqn); } + public DashRef getTransOn(String tfqn) { + return transTable.getOn(tfqn); + } + public DashRef getTransSend(String tfqn) { + return transTable.getSend(tfqn); + } public List getHigherPriTrans(String tfqn) { return transTable.getHigherPriTrans(tfqn); } @@ -361,6 +374,7 @@ public List exited(String tfqn) { DashRef scope = getScope(tfqn); return stateTable.getLeafStatesExited(scope); } + // for debugging public List allPrefixDashRefs(DashRef x) { return stateTable.allPrefixDashRefs(x); @@ -430,15 +444,15 @@ public void debug(String tfqn) { System.out.println(transTable.toString()); System.out.println(eventTable.toString()); System.out.println(varTable.toString()); - for (String x: getTransNames()) { + for (String x: getAllTransNames()) { // System.out.println(tfqn +" scope :" + getScope(x)); } if (tfqn != null) { System.out.println("src " + getTransSrc(tfqn)); System.out.println("dest " + getTransDest(tfqn)); System.out.println("getScope " + getScope(tfqn)); - System.out.println("getClosestConcAnces: "+getClosestConcAnces(getTransSrc(tfqn).getName())); - System.out.println("getAllNonConcDesc: " +getAllNonConcDesc(getClosestConcAnces(getTransSrc(tfqn).getName()))); + System.out.println("getClosestParamAnces: "+getClosestParamAnces(getTransSrc(tfqn).getName())); + //System.out.println("getAllNonParamDesc: " +getAllNonParamDesc(getClosestConcAnces(getTransSrc(tfqn).getName()))); System.out.println("getRegion:"+"Root/S1/S2: "+getRegion(getTransSrc(tfqn).getName())); System.out.println("exited: " + exited(tfqn)); System.out.println("entered" + getLeafStatesEntered(getTransDest(tfqn))); @@ -460,15 +474,15 @@ public void resolveAllDash(A4Reporter rep) { root = roots.get(0); // passed with empty set of params, empty set of ancestors stateTable.setRoot(root.name); - root.resolveAllStates(stateTable,eventTable, varTable, bufferTable, new ArrayList(),new ArrayList()); + root.resolve(stateTable,transTable, eventTable, varTable, bufferTable, new ArrayList(),new ArrayList()); // have to do states first so siblings of trans parent state // are in place to search for src/dest - root.resolveAllTrans(stateTable,transTable); + // root.resolveTransTable(stateTable,transTable); // if root has no substates? // if no transitions? - stateTable.resolveAll(getRootName()); + stateTable.resolve(getRootName()); // TODO will need eventTable - transTable.resolveAll(); + transTable.resolve(stateTable, eventTable); maxDepthParams = stateTable.getMaxDepthParams(); //transAtThisParamDepth = new boolean[maxDepthParams+1]; transAtThisParamDepth = transTable.transAtThisParamDepth(maxDepthParams); @@ -483,9 +497,8 @@ public void translate() { System.out.println("Translating to Alloy"); // this is so we can partition the translation // code into a different file - DashToAlloy d = new DashToAlloy(this); // translation is done in place - d.translate(); + DashToAlloy.translate(this); // if no errors status = Status.TRANSLATED_TO_ALLOY; } @@ -515,18 +528,18 @@ public List getDefaults(String s) { public String getRoot() { return root.name(); // as root it is already FQN } - + */ public List getAllInternalEventNames() { - assert(r.hasAllInternalEvents()); - return eventTable.getInternalEvent(); + //assert(hasInternalEvents()); + return eventTable.getAllInternalEvents(); } public List getAllEnvironmentalEventNames() { - assert(r.hasAllExternalEvents()); - return eventTable.getEnvironmentalEvents(); - } - public List getTransitionNames() { - return transTable.getNames(); + //assert(hasExternalEvents()); + return eventTable.getAllEnvironmentalEvents(); } + + + /* public List getTransTriggerEvents(String t){ return transTable.get(t).trigger(); } @@ -561,9 +574,9 @@ public List getTransitionsAtLevel(int i) { ArrayList o = transTable.keys().stream().filter(t -> transTable.get(t).params.size() == i).collect(Collectors.toList()); return o; } - public List getTransParams(String t) { - return transTable.get(t).getParams(); - } + */ + + /* public ArrayList getBasicStatesEnteredAtLevel(i){ ArrayList bs = stateTable.get(root).basicStatesEntered; ArrayList o = bs.stream().filter(s -> s.params.size() == i).collect(Collectors.toList()); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index 043df1565..e171eb6f8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -3,9 +3,13 @@ import java.util.List; import java.util.ArrayList; import java.util.HashMap; +import java.util.Collections; +import java.util.stream.Collectors; import static ca.uwaterloo.watform.core.DashUtilFcns.*; import static ca.uwaterloo.watform.core.DashStrings.*; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashFQN; public class EventTable { @@ -54,4 +58,49 @@ public Boolean add(String efqn, IntEnvKind k, List prms) { public void resolveAllEventTable() { // TODO } + public boolean hasEvents() { + return (!table.keySet().isEmpty() ); + } + public boolean hasEvent(String e) { + return table.containsKey(e); + } + public boolean hasEventsAti(int i) { + for (String e: table.keySet()) { + if (table.get(e).params.size() == i) return true; + } + return false; + } + public boolean hasInternalEvents() { + for (String e: table.keySet()) { + if (table.get(e).kind == IntEnvKind.INT) return true; + } + return false; + } + public boolean hasEnvironmentalEvents() { + for (String e: table.keySet()) { + if (table.get(e).kind == IntEnvKind.ENV) return true; + } + return false; + } + public List getAllInternalEvents() { + return table.keySet().stream() + .filter(i -> table.get(i).kind == IntEnvKind.INT) + .collect(Collectors.toList()); + } + public List getAllEnvironmentalEvents() { + return table.keySet().stream() + .filter(i -> table.get(i).kind == IntEnvKind.ENV) + .collect(Collectors.toList()); + } + public List getParams(String ev) { + if (table.containsKey(ev)) return table.get(ev).params; + else { DashErrors.eventTableGetParams(); return null; } + } + public List allEventsOfState(String sfqn) { + // return all events declared in this state + // will have the sfqn as a prefix + return table.keySet().stream() + .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) + .collect(Collectors.toList()); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index e69a1b032..dafde283f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -19,6 +19,7 @@ import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.*; +import ca.uwaterloo.watform.ast.*; import static ca.uwaterloo.watform.core.DashUtilFcns.*; import static ca.uwaterloo.watform.core.DashStrings.*; import static ca.uwaterloo.watform.core.DashFQN.*; @@ -46,6 +47,11 @@ public class StateElement { // this could be a set b/c there are no dups and order // doesn't matter, but lists are easier to work with private List immChildren; // empty if none + private List invariants; + private List inits; + private List actions; + private List conditions; + /* private ArrayList transWithThisSrc; private ArrayList transWithThisScope; @@ -61,20 +67,31 @@ public StateElement( List prms, DashStrings.DefKind d, String p, - List iChildren) { + List iChildren, + List invL, + List initL, + List actL, + List condL) { assert(k != null); assert(prm == null || !prm.isEmpty()); assert(prms != null); assert(p == null || !p.isEmpty()); assert(iChildren != null); // could be empty - + assert(invL != null); + assert(initL != null); + assert(actL != null); + assert(condL != null); this.kind = k; this.param = prm; this.params = prms; this.def = d; this.parent = p; this.immChildren = iChildren; + this.invariants = invL; + this.inits = initL; + this.actions = actL; + this.conditions = condL; } public String toString() { @@ -166,26 +183,31 @@ public void add(String fqn) { table.put(fqn,null); //System.out.println("adding State table: "+fqn); } - public void add( + public boolean add( String fqn, DashStrings.StateKind k, String prm, List prms, DashStrings.DefKind d, String p, - List iChildren) { + List iChildren, + List invL, + List initL, + List actL, + List condL) { // if its null, make it empty to not throw exceptions - if (iChildren == null) iChildren = new ArrayList(); - if (table.containsKey(fqn)) { - StateElement se = table.get(fqn); - if (se == null) - table.replace(fqn, new StateElement(k,prm, prms,d, p,iChildren)); - else if (!se.attributesSame(k,prm,prms,d,p,iChildren)) + //if (iChildren == null) iChildren = new ArrayList(); + //if (table.containsKey(fqn)) { + // StateElement se = table.get(fqn); + // if (se == null) + // table.replace(fqn, new StateElement(k,prm, prms,d, p,iChildren, invL, initL, actL, condL)); + // else if (!se.attributesSame(k,prm,prms,d,p,iChildren)) // hopefully not possible - DashErrors.addStateToStateTableDup(fqn); - } - else - table.put(fqn, new StateElement(k,prm, prms,d,p,iChildren)); + //DashErrors.addStateToStateTableDup(fqn); + //} + //else + if (table.containsKey(fqn)) return false; + else { table.put(fqn, new StateElement(k,prm, prms,d,p,iChildren, invL, initL, actL, condL)); return true; } //System.out.println("adding to State table: "+fqn+space+prm + space + prms+space+d+space+p+iChildren); } @@ -267,7 +289,14 @@ public List getAllAnces(String fqn) { // contains at least Root state return x; } - public String getClosestConcAnces(String s) { + + public List getAllPrefixParamAnces(String sfqn) { + return getAllAnces(sfqn).stream() + .filter(i -> (isAnd(i) && hasParam(i)) || isRoot(i)) + .collect(Collectors.toList()); + } + // might not be used anymore + public String getClosestParamAnces(String s) { // getAllAnces returns list from Root, ..., parentFQN on path // could also just walk back through parents List allAnces = getAllAnces(s); @@ -277,7 +306,7 @@ public String getClosestConcAnces(String s) { String concAnces = null; // allAnces cannot be empty b/c must have Root in it for (String a:allAnces) { - if (isAnd(a) || isRoot(a)) { + if (hasParam(a) || isRoot(a)) { concAnces = a; break; } @@ -285,6 +314,7 @@ public String getClosestConcAnces(String s) { //System.out.println("getClosestConcAnces: "+concAnces); return concAnces; // might be null } + /* public List getAllNonConcStatesWithinThisState(String concAnces) { if (concAnces!=null) return getAllNonConcDesc(concAnces); @@ -296,25 +326,28 @@ public List getAllNonConcStatesWithinThisState(String concAnces) { } } */ - public List getAllNonConcDesc(String s) { - // get all the descendants not WITHIN concurrent states + public List getAllNonParamDesc(String s) { + // get all the descendants not WITHIN parameterized states // s is included // have to be careful to avoid duplicates - // System.out.println("getAllNonConcDesc "+s); List desc = new ArrayList(); desc.add(s); // could be Root or a conc state - //System.out.println("in getAllNonConcDesc: "+desc); + if (table.containsKey(s)) { for (String c: table.get(s).immChildren) { - //System.out.println("in getAllNonConcDesc: "+c); - if (isOr(c)) desc.addAll(getAllNonConcDesc(c)); + //System.out.println("in getAllNonParamDesc: "+c); + if (isOr(c) || !hasParam(c)) desc.addAll(getAllNonParamDesc(c)); } return desc; - } else { DashErrors.stateDoesNotExist("getAllNonConcDesc", s); return null; } + } else { DashErrors.stateDoesNotExist("getAllNonParamDesc", s); return null; } } // region is the area within which the src name does not need to be FQN public List getRegion(String sfqn) { - return getAllNonConcDesc(getClosestConcAnces(sfqn)); + List r = new ArrayList(); + for (String s: getAllPrefixParamAnces(sfqn)) { + r.addAll(getAllNonParamDesc(s)); + } + return r; } public int getMaxDepthParams() { return getMaxDepthParams(root); @@ -337,11 +370,12 @@ public List getAllParams() { } return DashUtilFcns.setToList(allParams); } - public void resolveAll(String root) { + public void resolve(String root) { //System.out.println("Resolving state table"); - for (String k: table.keySet()) - if (table.get(k) == null) DashErrors.transUsesNonExistentState(k); + //for (String k: table.keySet()) + //if (table.get(k) == null) DashErrors.transUsesNonExistentState(k); // walk down parent to children and pass back info + //TODO: nothing to do here now? isResolved = true; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 12fbc5846..eb2a3a576 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -12,14 +12,21 @@ import java.util.HashMap; import java.util.List; import java.util.ArrayList; +import java.util.Collections; +import java.util.stream.Collectors; import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprVar; import ca.uwaterloo.watform.core.*; import static ca.uwaterloo.watform.core.DashUtilFcns.*; import ca.uwaterloo.watform.alloyasthelper.ExprHelper; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; import ca.uwaterloo.watform.ast.*; + // env events cannot be generated + // env vars cannot be primed anywhere + public class TransTable { private HashMap table; @@ -27,26 +34,34 @@ public class TransTable { public class TransElement { public List params; // null if no params + public List fromList; + public List onList; + public List whenList; + public List gotoList; + public List sendList; + public List doList; + + + + // calculated when resolved public DashRef src; public DashRef dest; public Expr when; // just one? - public Expr on; + public DashRef on; public List action; - public List send; + public DashRef send; /* public List changedDynSymbols; // includes buffers - - // don't need scope - it is calculated from FQNs - public Set higherPriority; - public Set orthogonal; // keep both lists just in case - public Set notOrthogonal; - public Set changedDynSymbols; */ public TransElement( List prms, - DashRef s, - DashRef d + List fl, + List ol, + List wl, + List gl, + List sl, + List dl ) /* DashEvent w, @@ -57,54 +72,64 @@ public TransElement( */ { this.params = prms; - this.src = s; - this.dest = d; - /* - this.when = w; - this.on = o; - this.action = a; - this.send = s; - this.changedDynSymbols = null; // not yet known; consists of FQN list - this.higherPriorityTrans = null; // not yet known; FQNs - this.notOrthogonal = null; // not yet known; FQNs - this.orthogonal = null; - this.basicStatesEntered = null; - this.basicStatesExited = null; - */ + this.fromList = fl; + this.onList = ol; + this.whenList = wl; + this.gotoList = gl; + this.sendList = sl; + this.doList = dl; } public String toString() { String s = new String(); - s += "params: " + params +"\n"; - s += "src: " + src.toString() + "\n"; - s += "dest: " + dest.toString() + "\n"; + s += "params: " + NoneStringIfNeeded(params) +"\n"; + s += "src: " + NoneStringIfNeeded(src) + "\n"; + s += "dest: " + NoneStringIfNeeded(dest) + "\n"; + s += "on: " + NoneStringIfNeeded(on) + "\n"; + s += "send: " + NoneStringIfNeeded(send) + "\n"; // add more return s; } + public void setSrc(DashRef s) { + src = s; + } + public void setDest(DashRef d) { + dest = d; + } + public void setOn(DashRef e) { + on = e; + } + public void setSend(DashRef e) { + send = e; + } } public TransTable() { table = new HashMap(); isResolved = false; } - public void add( - String fqn, + public boolean add( + String tfqn, List params, - DashRef s, - DashRef d) - /* - DashEvent w, - DashExpr o, - List a, - List se) { - */ + List fromList, + List onList, + List whenList, + List gotoList, + List sendList, + List doList + ) { - //System.out.println("Adding "+fqn); - assert(!fqn.isEmpty()); + //System.out.println("Adding "+tfqn); + //System.out.println("onList: " + NoneStringIfNeeded(onList)); + assert(!tfqn.isEmpty()); assert(params != null ); - assert(s != null); - assert(d != null); - if (table.containsKey(fqn)) DashErrors.transTableDup(fqn); - else table.put(fqn, new TransElement(params,s,d)); + assert(fromList != null); + assert(onList != null); + assert(whenList != null); + assert(gotoList != null); + assert(sendList != null); + assert(doList != null); + if (table.containsKey(tfqn)) return false; + else { table.put(tfqn, new TransElement(params,fromList,onList,whenList,gotoList,sendList,doList)); return true; } } public String toString() { String s = new String(); @@ -116,7 +141,8 @@ public String toString() { } return s; } - public Set getTransNames() { + + public Set getAllTransNames() { return table.keySet(); } public List getParams(String t) { @@ -131,6 +157,16 @@ public DashRef getDest(String t) { if (table.containsKey(t)) return table.get(t).dest; else { DashErrors.transDoesNotExist("getDest", t); return null; } } + public DashRef getOn(String t) { + if (table.containsKey(t)) return table.get(t).on; + else { DashErrors.transDoesNotExist("getOn", t); return null; } + } + public DashRef getSend(String t) { + if (table.containsKey(t)) return table.get(t).send; + else { DashErrors.transDoesNotExist("getSend", t); return null; } + } + + // might be better to make this getTransWithThisSrc // but this is more efficient if it is only used for higherPriTrans public List getTransWithTheseSrcs(List slist) { @@ -152,36 +188,209 @@ public List getHigherPriTrans(String t) { return tlist; } + /* + * check for errors and put all the trans that are at this level + * in the trans table + * must be done after resolveAllState + * this fcn does not modify anything in this object + */ + public void resolve(StateTable st, EventTable et) { + + //System.out.println(st); + //System.out.println(toString()); + //System.out.println("Resolving trans table"); + if (getAllTransNames().isEmpty()) DashErrors.noTrans(); + for (String tfqn: table.keySet()) { + //String tfqn = DashFQN.fqn(sfqn,t.name); + + // determining the src state + List fList = + table.get(tfqn).fromList.stream() + .map(p -> (p.src)) + .collect(Collectors.toList()); + table.get(tfqn).setSrc(determineSrcDest("from", fList, st, tfqn)); + + // determining the dest state + List gList = + table.get(tfqn).gotoList.stream() + .map(p -> (p.dest)) + .collect(Collectors.toList()); + table.get(tfqn).setDest(determineSrcDest("goto", gList, st, tfqn)); + + // determining the when + + // determining the on + List onExpList = + table.get(tfqn).onList.stream() + .map(p -> (p.getExp())) + .collect(Collectors.toList()); + table.get(tfqn).setOn(determineEvent("on", onExpList,st, et, tfqn)); + + // determining the send + List sendExpList = + table.get(tfqn).sendList.stream() + .map(p -> (p.getExp())) + .collect(Collectors.toList()); + table.get(tfqn).setSend(determineEvent("send", sendExpList,st, et, tfqn)); + + // determining the do + + } + isResolved = true; + } + /* - public List getNotOrthogonalTransAbove(String t) { - List notOrthogonal = new ArrayList(); - String tScope = getScope(table.get(t).src, table.get(t).dest); - // get scope of this trans - for (to: table.getKeys()) { - if (!t.equals(to)) { - String toScope = getScope(table.get(to).src, table.get(to).dest); - if (!isBelow(toScope, tScope)) { - // will be caught by !takeni's below this trans - ; - } else if (isBelow(tScope, toScope)) { - notOrthogonal.add(to); + * this fcn figures out the src/dest of a transition + * from its context + * if it has no src/dest, the parent state is used + * if it is already FQN, it is returned directly + * Otherwise, it looks at all uniquely named states up to an ancestor conc state + * Requires state table to have been built already + */ + + public DashRef determineSrcDest(String xType, List ll, StateTable st, String tfqn) { + + // parent state of this transition + String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); + if (ll.size() > 1) { + DashErrors.moreThanOneSrcDest(xType, tfqn); + return null; + } else if (ll.isEmpty()) + // can be a loop on root + return new DashRef(parentFQN, ExprHelper.createVarList(DashStrings.pName,st.getParams(parentFQN))); + else { + // if has slashes, turn to "-" + DashRef x = ll.get(0); + //System.out.println("Looking for: " + x); + String n = DashFQN.fqn(x.getName()); + if (DashFQN.isFQN(n)) { + // number of params provided must match number of params needed + //System.out.println(x.getParamValues().size()); + //System.out.println(st.getParams(x.getName()).size()); + if (x.getParamValues().size() != st.getParams(n).size()) { + DashErrors.fqnSrcDestMustHaveRightNumberParams(xType,tfqn); + return null; + } + if (!st.containsKey(n)) DashErrors.unknownSrcDest(x.getName(),xType,tfqn); + return x; + } else { + // not fully qualified + // shouldn't have params in DashRef + // Root could be here but won't have params + if (!x.getParamValues().isEmpty()) { + DashErrors.srcDestCantHaveParam(xType,tfqn); + return null; + } + // Root ends up here + List matches = new ArrayList(); + //String a = st.getClosestConcAnces(parentFQN); + //System.out.println("getClosestConcAnces: "+a); + //List b = st.getAllNonConcStatesWithinThisState(a); + //System.out.println("getAllNonConcStatesWithinThisState "+b); + for (String s:st.getRegion(parentFQN)) { + //System.out.println(s + " " + n); + if (DashFQN.suffix(s,n)) matches.add(s); + } + //System.out.println("matches: " + matches); + if (matches.size() > 1) { + DashErrors.ambiguousSrcDest(xType, tfqn); + return null; + } else if (matches.isEmpty()) { + //DashUtilFcns.myprint(st.toString()); + DashErrors.unknownSrcDest(x.getName(),xType,tfqn); + return null; } else { - + String m = matches.get(0); + //System.out.println(m); + // must have same param values as trans b/c in same conc region + return new DashRef(m, ExprHelper.createVarList(DashStrings.pName, st.getParams(m))); } - } } - get scope of to - get lca of } - */ - public void resolveAll() { - //System.out.println("Resolving trans table"); - if (getTransNames().isEmpty()) DashErrors.noTrans(); - isResolved = true; + + // [n1,n2,...] + /*private List paramVars(List names) { + List o = new ArrayList(); + for (String n: names) o.add(ExprHelper.createVar(DashStrings.pName+n)); + return o; + }*/ + + private DashRef determineEvent(String xType, List expList, StateTable st, EventTable et, String tfqn) { + if (expList.isEmpty()) return null; + else if (expList.size() > 1) { + DashErrors.tooManyEvents(xType, tfqn); + return null; + } else { + Expr exp = expList.get(0); + // don't include isDashRefJoin here because that is only possible for actions not events + // which are tuples + // but a DashRefProcessRef could be either a value for an action + // or a tuple for an event + // Arrow: b1 -> a1 -> ev + // ProcessRef: A/B/C[a1,b1]/ev which became $$PROCESSREF$$. b1.a1.A/B/C/ev in parsing + // BadJoin: ev[a1,b1] which became b1.a1.ev in parsing + if (ExprHelper.isExprVar(exp) || + DashRef.isDashRefArrow(exp) || + DashRef.isDashRefProcessRef(exp) || + DashRef.isDashRefBadJoin(exp)) { + String e; + List paramValues; + if (ExprHelper.isExprVar(exp)) { + e = ExprHelper.getVarName((ExprVar) exp); + paramValues = new ArrayList(); + } else { + e = DashFQN.fqn(DashRef.nameOfDashRefExpr(exp)); + paramValues = DashRef.paramValuesOfDashRefExpr(exp); + } + String efqn = DashFQN.fqn(e); + String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); + //System.out.println(efqn); + List matches = new ArrayList(); + for (String s:st.getRegion(parentFQN)) + for (String x:et.allEventsOfState(s)) { + //System.out.println(x); + if (DashFQN.suffix(x,efqn)) matches.add(x); + } + if (matches.size() > 1) { + DashErrors.ambiguousEvent(xType, e, tfqn); + return null; + } else if (matches.isEmpty()) { + DashErrors.unknownEvent(xType, e,tfqn); + return null; + } else { + String m = matches.get(0); + if (paramValues.isEmpty()) { + // must have same param values as trans b/c in same conc region + if (et.getParams(m).size() > getParams(tfqn).size()) { + // getRegion did not return things that all + // have the same parameter values + DashErrors.regionMatchesWrongParamNumber(); + return null; + } else { + // but could be a subset of transition param values + List prmValues = + ExprHelper.createVarList(DashStrings.pName, + getParams(tfqn).subList(0, et.getParams(m).size() )); + return new DashRef(m, prmValues); + } + } else if (et.getParams(m).size() != paramValues.size()) { + // came with parameters so must be right number + DashErrors.fqnEventMissingParameters(xType, e, tfqn); + return null; + } else { + return new DashRef(efqn, paramValues); + } + } + } else { + DashErrors.expNotEvent(xType, tfqn); + return null; + } + } } + public boolean[] transAtThisParamDepth(int max) { boolean[] depthsInUse = new boolean[max+1]; // 0..max for (int i=0; i <= max; i++) depthsInUse[i] = false; diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java index 6addd079a..5082ce738 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashCoreFQNTests.java @@ -17,6 +17,24 @@ public List ll(String[] k) { return Arrays.asList(k); } + @Test + public void test1() { + String k = DashFQN.fqn("Root"); + assertEquals(k, "Root"); + } + + @Test + public void test2() { + String k = DashFQN.fqn("Root/A/B"); + assertEquals(k, "Root/A/B"); + } + + @Test + public void test3() { + String k = DashFQN.fqn("Root/A/B"); + assertEquals(k, "Root/A/B"); + } + @Test public void testFQN1() { String k = DashFQN.longestCommonFQN("Root/A","Root/B"); @@ -89,4 +107,11 @@ public void allPrefixes3() { })); } + @Test + public void suffix() { + assert(DashFQN.suffix("A/B/C/x", "C/x")); + assert(DashFQN.suffix("A/B/C/x", "x")); + assert(DashFQN.suffix("x","x")); + assert(!DashFQN.suffix("A/B/xyz", "yz")); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashEventTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashEventTests.java new file mode 100644 index 000000000..4599129c2 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashEventTests.java @@ -0,0 +1,74 @@ +package org.alloytools.alloy.dash; + +import java.util.*; +import java.io.File; +import java.util.Collections; +import java.util.stream.Collectors; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; + +import edu.mit.csail.sdg.alloy4.A4Reporter; + +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.mainfunctions.MainFunctions; + +public class DashEventTests { + + private static String resourcePath = "src/test/resources/pass"; + + public static DashModule test(String fileName) { + File dir = new File(resourcePath); + String absolutePath = new File(resourcePath).getAbsolutePath(); + A4Reporter rep = new A4Reporter(); + return MainFunctions.parseAndResolveDashFile(absolutePath+"/"+fileName+".dsh", rep); + } + public List ll(String[] k) { + return Arrays.asList(k); + } + + public static String on(DashModule d, String s) { + return DashUtilFcns.NoneStringIfNeeded(d.getTransOn(s)); + } + + public static String send(DashModule d, String s) { + return DashUtilFcns.NoneStringIfNeeded(d.getTransSend(s)); + } + + @Test + public void event1() { + DashModule d = test("event1"); + String tfqn = "Root/t1"; + assertTrue( + on(d, tfqn).equals("Root/ev1[]")); + assertTrue( + send(d, tfqn).equals("Root/ev1[]")); + } + + @Test + public void event2() { + DashModule d = test("event2"); + String tfqn = "Root/t1"; + assertTrue( + on(d, tfqn).equals("none")); + assertTrue( + send(d, tfqn).equals("none")); + } + + @Test + public void event3() { + DashModule d = test("event3"); + String tfqn = "Root/t1"; + assertTrue( + on(d, tfqn).equals("Root/ev1[]")); + assertTrue( + send(d, tfqn).equals("none")); + } + + //TODO add many more tests + +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java index e3e86847b..bb7cfdf09 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java @@ -115,42 +115,58 @@ public void getAllAnces1() { assertTrue(d.getAllAnces("Root/S1").equals(ll(new String[]{"Root", "Root/S1"}))); } - // getClosestConcAnces ---------------- + // getClosestParamAnces ---------------- @Test - public void getClosestConcAnces1() { + public void getClosestParamAnces1() { DashModule d = test("noSrc1"); - assertTrue(d.getClosestConcAnces("Root/S1").equals("Root")); - assertTrue(d.getClosestConcAnces("Root/S2").equals("Root")); + assertTrue(d.getClosestParamAnces("Root/S1").equals("Root")); + assertTrue(d.getClosestParamAnces("Root/S2").equals("Root")); } @Test - public void getClosestConcAnces2() { + public void getClosestParamAnces2() { DashModule d = test("scopeParam2"); - assertTrue(d.getClosestConcAnces("Root/A/B/S1").equals("Root/A/B")); - assertTrue(d.getClosestConcAnces("Root/A/B").equals("Root/A/B")); + assertTrue(d.getClosestParamAnces("Root/A/B/S1").equals("Root/A/B")); + assertTrue(d.getClosestParamAnces("Root/A/B").equals("Root/A/B")); } - // getAllNonConcDesc -------------- - @Test - public void getAllNonConcDesc1() { - DashModule d = test("getAllNonConcDesc1"); - assertTrue(d.getAllNonConcDesc("Root") - .equals(ll(new String[]{"Root", "Root/S1", "Root/S1/S2","Root/S3","Root/S3/S4", "Root/S3/S4/S5"}))); - } // getRegion ---------------------- @Test public void getRegion1() { DashModule d = test("getRegion1"); assertTrue(d.getRegion("Root/S1/S2") - .equals(ll(new String[]{"Root", "Root/S1", "Root/S1/S2","Root/S3","Root/S3/S4", "Root/S3/S4/S5"}))); + .equals(ll(new String[]{ + "Root", + "Root/S1", + "Root/S1/S2", + "Root/S3", + "Root/S3/S4", + "Root/S3/S4/S5", + "Root/S3/A", + "Root/S3/A/S7", + "Root/S3/A/S7/S8", + "Root/S3/B", + "Root/S3/B/S7" + }))); } @Test public void getRegion2() { DashModule d = test("getAllNonConcDesc1"); assertTrue(d.getRegion("Root/S1/S2") - .equals(ll(new String[]{"Root", "Root/S1", "Root/S1/S2","Root/S3","Root/S3/S4", "Root/S3/S4/S5"}))); + .equals(ll(new String[]{ + "Root", + "Root/S1", + "Root/S1/S2", + "Root/S3", + "Root/S3/S4", + "Root/S3/S4/S5", + "Root/S3/A", + "Root/S3/A/S7", + "Root/S3/B", + "Root/S3/B/S7" + }))); } // allPrefixDashRefs ---------------------- @@ -901,4 +917,34 @@ public void overall9() { }))); } + @Test + public void overall10() { + DashModule d = test("overall10"); + String tfqn = "Root/S1/t1"; + assertTrue( + src(d, tfqn).equals("Root/S1[]")); + assertTrue( + dest(d, tfqn).equals("Root/S2[]")); + } + + @Test + public void overall11() { + DashModule d = test("overall11"); + String tfqn = "Root/S1/t1"; + assertTrue( + src(d, tfqn).equals("Root/S1[]")); + assertTrue( + dest(d, tfqn).equals("Root/S2[]")); + } + + @Test + public void overall12() { + DashModule d = test("overall12"); + String tfqn = "Root/S1/t1"; + assertTrue( + src(d, tfqn).equals("Root/S1[]")); + assertTrue( + dest(d, tfqn).equals("Root/S1/S7[]")); + } + } diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java index ceb5bec79..399eeaa9d 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java @@ -79,13 +79,14 @@ public static Collection fileNameMsg() { {"moreThanOneSrcDest1", moreThanOneSrcDestMsg}, {"moreThanOneSrcDest2", moreThanOneSrcDestMsg}, // 19 {"moreThanOneSrcDest3", moreThanOneSrcDestMsg}, - {"unknownSrcDest1", unknownSrcDestMsg}, - {"unknownSrcDest2", unknownSrcDestMsg}, - {"unknownSrcDest3", unknownSrcDestMsg}, + //{"unknownSrcDest1", unknownSrcDestMsg}, //21 + //{"unknownSrcDest2", unknownSrcDestMsg}, + //{"unknownSrcDest3", unknownSrcDestMsg}, {"unknownSrcDest4", unknownSrcDestMsg}, - {"fqnSrcDestMustHaveRightNumberParams1", fqnSrcDestMustHaveRightNumberParamsMsg}, + {"fqnSrcDestMustHaveRightNumberParams1", fqnSrcDestMustHaveRightNumberParamsMsg}, {"srcDestCantHaveParam1", srcDestCantHaveParamMsg}, - {"ambiguousSrcDest1", ambiguousSrcDestMsg} + {"ambiguousSrcDest1", ambiguousSrcDestMsg}, + {"test11",ambiguousSrcDestMsg} }); } diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/event1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/event1.dsh new file mode 100644 index 000000000..76eae2f33 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/event1.dsh @@ -0,0 +1,7 @@ +state Root { + event ev1 {} + trans t1 { + on ev1 + send ev1 + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/event2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/event2.dsh new file mode 100644 index 000000000..6c1ba2cfe --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/event2.dsh @@ -0,0 +1,5 @@ +state Root { + event ev1 {} + trans t1 { + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/event3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/event3.dsh new file mode 100644 index 000000000..f495a9e8a --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/event3.dsh @@ -0,0 +1,6 @@ +state Root { + event ev1 {} + trans t1 { + on ev1 + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh index db988387f..f2a9120b3 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall1.dsh @@ -1,4 +1,5 @@ state Root { + event ev1 {} conc A [AID] { conc B [BID] { state S1 {} @@ -10,5 +11,6 @@ state Root { trans t1 { from Root/A/B/S1[a1,b1] goto Root/C/S2[c1] + on ev1 } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall10.dsh similarity index 51% rename from org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest1.dsh rename to org.alloytools.alloy.dash/src/test/resources/pass/overall10.dsh index bb9c5d6e9..da881495e 100644 --- a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest1.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall10.dsh @@ -1,4 +1,3 @@ -// S2 is unknown b/c it is not within the same conc name space state Root { conc S1 { trans t1 { diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall11.dsh similarity index 55% rename from org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest2.dsh rename to org.alloytools.alloy.dash/src/test/resources/pass/overall11.dsh index fafff521a..a11815988 100644 --- a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest2.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall11.dsh @@ -1,4 +1,4 @@ -// S2 is unknown b/c it is not within the same conc name space + state Root { conc S1 { trans t1 { diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall12.dsh similarity index 72% rename from org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest3.dsh rename to org.alloytools.alloy.dash/src/test/resources/pass/overall12.dsh index d3c24c724..e79a4994c 100644 --- a/org.alloytools.alloy.dash/src/test/resources/wfffail/unknownSrcDest3.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall12.dsh @@ -1,4 +1,3 @@ -// S2 is unknown b/c it is not within the same conc name space state Root { conc S1 { state S7 {} diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test11.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test11.dsh new file mode 100644 index 000000000..c9db1d5e1 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test11.dsh @@ -0,0 +1,17 @@ +state Root { + conc S1 { + state S7 {} + trans t1 { + goto S7 + } + } + default state S2 { + state S3{ + state S7{ + trans t2 { + goto S7 + } + } + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/test2.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test2.dsh similarity index 84% rename from org.alloytools.alloy.dash/src/test/resources/pass/test2.dsh rename to org.alloytools.alloy.dash/src/test/resources/wfffail/test2.dsh index 2cff40987..fd6b14205 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/test2.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test2.dsh @@ -3,6 +3,6 @@ state A { // these are all allowed send ev1 send P[x]/ev1 - send x.y.ev1 + on P[x]/ev1 } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/wfffail/test3.dsh b/org.alloytools.alloy.dash/src/test/resources/wfffail/test3.dsh index a0a26286e..55a97b6c3 100644 --- a/org.alloytools.alloy.dash/src/test/resources/wfffail/test3.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/wfffail/test3.dsh @@ -1,6 +1,9 @@ state A { trans t1 { - // should fail on x,y as a list - send P[x,y]/ev1 + // these are all allowed + send ev1 + send P[x]/ev1 + send x.y.ev1 + on x.y.ev1 } } \ No newline at end of file From bf89f69ab1fc26c8b96473e3140527369f7ae9d1 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 2 May 2023 16:38:21 -0400 Subject: [PATCH 031/129] added in events, testIfNextStable, enabledAfterStep --- .../watform/alloyasthelper/ExprHelper.java | 16 +- .../ca/uwaterloo/watform/core/DashErrors.java | 4 +- .../uwaterloo/watform/core/DashStrings.java | 6 +- .../dashtoalloy/AddTestIfNextStable.java | 9 +- .../AddTransIsEnabledAfterStep.java | 180 ++++++++++-------- .../watform/dashtoalloy/AddTransPost.java | 34 ++-- .../watform/dashtoalloy/AddTransPre.java | 4 +- .../uwaterloo/watform/dashtoalloy/Common.java | 36 +++- .../watform/dashtoalloy/DashToAlloy.java | 5 +- .../uwaterloo/watform/parser/DashModule.java | 3 + .../uwaterloo/watform/parser/EventTable.java | 10 +- 11 files changed, 188 insertions(+), 119 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index aeb2f616d..da2f10b76 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -187,8 +187,12 @@ public static ExprBinary createNotEquals(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.NOT_EQUALS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } // returns an ExprList - public static ExprList createAnd(Expr left, Expr right) { - return (ExprList) ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + public static Expr createAnd(Expr left, Expr right) { + if (sEquals(left, createFalse())) return createFalse(); + if (sEquals(right, createFalse())) return createFalse(); + if (sEquals(left, createTrue())) return right; + if (sEquals(right, createTrue())) return left; + return (Expr) ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } //public static ExprList createAndList(List args) { // return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); @@ -201,8 +205,12 @@ public static Expr createAndFromList(List elist) { } return ret; } - public static ExprList createOr(Expr left, Expr right) { - return (ExprList) ExprBinary.Op.OR.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + public static Expr createOr(Expr left, Expr right) { + if (sEquals(left, createTrue())) return createTrue(); + if (sEquals(right, createTrue())) return createTrue(); + if (sEquals(left, createFalse())) return right; + if (sEquals(right, createFalse())) return left; + return (Expr) ExprBinary.Op.OR.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } public static Expr createOrFromList(List elist) { if (elist.isEmpty()) return createTrue(); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index b3eef9432..a392757a1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -200,8 +200,8 @@ public static void replaceDashRefExprVarError() throws Err { public static void nonDashRefExpr() throws Err { throw new ErrorFatal("nonDashRefExpr"); } - public static void eventTableGetParams() { - throw new ErrorFatal("eventTableGetParams"); + public static void eventTableEventNotFound(String m, String efqn) { + throw new ErrorFatal("eventTableEventNotFound: "+m+" "+efqn); } public static void regionMatchesWrongParamNumber() { throw new ErrorFatal("regionMatchesWrongParamNumber"); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 0ba204495..8d3584c15 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -58,7 +58,7 @@ public class DashStrings { public static String equalsName = "equals"; public static String isEnabled = "isEnabled"; - // sig names + // sig/field names public static String snapshotName = "Snapshot"; public static String confName = "conf"; public static String scopesUsedName = "scopesUsed"; @@ -81,8 +81,8 @@ public class DashStrings { public static String testIfNextStableName = "testIfNextStable"; public static String enabledAfterStepName = "_enabledAfterStep"; public static String tName = "t"; - public static String geName = "ge"; - + public static String genEventName = "genEvents"; + public static String scopeName = "scope"; public static String bufferName = "buffer"; public static String bufferIndexName = "bufIdx"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java index f80f6801e..e6adeddc4 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java @@ -39,11 +39,11 @@ public static void addTestIfNextStable(DashModule d) { args.addAll(curNextVars()); } for (int i=0; i<= d.getMaxDepthParams(); i++) { - decls.add(scopesUsedDecl(i)); - args.add(scopesUsedVar(i)); + decls.add(scopeDecl(i)); + args.add(scopeVar(i)); if (d.hasEventsAti(i)) { - decls.add(eventsDecl(i)); - args.add(eventsVar(i)); + decls.add(genEventDecl(i)); + args.add(genEventVar(i)); } } for (String tfqn: d.getAllTransNames()) { @@ -51,6 +51,7 @@ public static void addTestIfNextStable(DashModule d) { body.add(createNot( createPredCall(tout + DashStrings.enabledAfterStepName, args))); } + d.alloyString += d.addPredSimple(DashStrings.testIfNextStableName,decls,body); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java index 8a1ead39d..4ae8533dd 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -33,107 +33,135 @@ public class AddTransIsEnabledAfterStep { // this is considering all instances of t1s (thus, the existential quantification) pred t1_enabledAfterStep[ s:Snapshot,s':Snapshot, - pParam0: Param0, ... - t:TransitionLabel, // parameters don't matter for orthogonality - ge:EventLabel ] - { // b/c below is exists params, the params don't matter + pParam0: Param0, + ... + scopes0: StateLabel, + scopes1: Identifiers -> StateLabel, + ... + genEvents0:EventLabel, + genEvents1: Identifiers -> EventLabel, + ... ] + { + // many of these may depend on param values src_state_t1 in s'.confi // where i is depth of src_state, - guard_cond_t1[s'] // may depend on params + guard_cond_t1[s'] (s.stable = True) => - no t1.notOrthogonal & t - for all of t1's triggering events and forall n - (if trig_ev_t1 is internal, line below is false) - trig_ev_t1 in (chop0(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) ... + ge) + o1: forall i. not(t1_nonOrthScopei in scopesi) + ev1: t1_on in (s.eventsi & EnvEvents) + genEventsi // if t1_on is internal this is false else { - no t1.notOrthogonal & (t + s.scopesUsed0 + s.scopesUsed1.TransLabel + s.scopesUsed2.TransLabel + s.scopesUsed3.TransLabel ...) - for all of t1's triggering events and forall n - trig_ev_t1 in (s.event0.EventLabel + s.event1.EventLabel + s.event2.EventLabel ... + ge) + o2: forall i. not(t1_nonOrthScopei in scopesi + s'.scopesUsedi) + ev2: t1_on in s.eventsi + genEventsi } } */ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { - //TODO fix this one - String tout = translateFQN(tfqn); List prs = d.getTransParams(tfqn); List decls = new ArrayList(); List body = new ArrayList(); - if (!DashOptions.isElectrum) { - decls.addAll(curNextDecls()); - } + if (DashOptions.isElectrum) { + decls.addAll(paramDecls(prs)); + } else { + decls.addAll(curNextParamsDecls(prs)); + } for (int i=0; i<= d.getMaxDepthParams(); i++) { - decls.add(scopesUsedDecl(i)); + decls.add(scopeDecl(i)); if (d.hasEventsAti(i)) { - decls.add(eventsDecl(i)); + decls.add(genEventsDecl(i)); } } - // p3 -> p2 -> p1 -> src in s'.confVar(i) // src does not have to be a basic state body.add(createIn(d.getTransSrc(tfqn).toAlloy(),nextConf(prs.size()))); - // guard condition is true is ' - // TOD - d.alloyString += d.addPredSimple(tout+DashStrings.enabledAfterStepName,decls,body); - /* - ArrayList o = new ArrayList(); - - - // src does not have to be a basic state - Expr src = createVar(dash.getTransSrc(t)); - ArrayList psList = createVars(prs); - List trig_ev = dash.transTable.get(t).getWhen(); - List int_trig_ev = trig_ev.stream().filter(ev -> ev.isInternal()).collect(Collectors.toList()); - - // p3 -> p2 -> p1 -> src in s'.confVar(i) - o.add(createIn(createArrowList(createVars(prs).add(src)),nextConf(prs.size()))); - - // guard_cond_t1 [s'] - // final parameter (usually s') should not be used in precondition - o.add(dash.getTransGuard(t).convertToAlloy(dash.symbolTable, nextVar(), null, prs)); - - - // no t1.notOrthogonal & (t + s.scopesUsed + s.scopesUsed1 |> TransitionLabel + scopesUsed2 |> TransitionLabel + ...) - Expr elseExpr = createNo( - createAnd( - createNonOrthogonalExpr(t),createPlus(createVar(t), - createChoppedGroup(prs.size(),DashStrings.scopesUsedName,DashStrings.transitionLabelName)))); - elseExpr = createAnd( - elseExpr, - createIn( - createPlusList(createVarList(trig_ev)), - createPlus( - // chop(s.event0,EventLabel + chop(s.event1,EventLabel) + chop(s.event2,EventLabel) - createChoppedGroup(prs.size(),DashStrings.eventName,DashStrings.eventLabelName), - ge))); - - if (int_trig_ev == null) { - // no t1.notOrthogonal & t - Expr ifExpr = createNo(createAnd(createNonOrthogonalExpr(t),createVar(t))); - ifExpr = createAnd( - ifExpr, - createIn( - createPlusList(createVarList(trig_ev)), - // chop(s.event0,EnvEvents) + chop1(s.event1,EnvEvents) + chop2(s.event2,EnvEvents) - createPlus(createChoppedGroup(prs.size(),DashStrings.eventName,DashStrings.environmentEventName),ge))) - body.add(createITE(sStableTrue(),ifExpr,elseExpr)); + // primed guard condition is true + // TODO + + // orthogonality ------------------ + + // if first step of the big step + // tfqn's non-orthogonal scope are not in any scopes used in the parameters + List orth1 = new ArrayList(); + List nonO = d.nonOrthogonalScopesOf(tfqn); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List u = DashRef.hasNumParams(nonO,i).stream() + .map(x -> x.toAlloy()) + .collect(Collectors.toList()); + // o1: forall i. not(t1_nonOrthScopei in scopesi) + for (Expr x: u) orth1.add(createNot(createIn(x,scopeVar(i)))); + } + Expr o1 = createAndFromList(orth1); + + + // if not the first of the big step + // tfqn's non-orthogonal scope are not in any scopes used in the parameters + the cur scopes used + List orth2 = new ArrayList(); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List u = DashRef.hasNumParams(nonO,i).stream() + .map(x -> x.toAlloy()) + .collect(Collectors.toList()); + // o2: forall i. not(t1_nonOrthScopei in scopesi + s'.scopesUsedi) + for (Expr x: u) orth1.add(createNot(createIn(x,createUnion(curScopesUsed(i), scopeVar(i))))); + } + Expr o2 = createAndFromList(orth2); + + // events ---------------------------- + + DashRef ev = d.getTransOn(tfqn); + Expr ev1, ev2; + if (ev != null) { + //ev1: t1_on in (s.eventsi & EnvEvents) + genEventsi // if t1_on is internal this is false + if (d.isEnvironmentalEvent(ev.getName())) { + ev1 = createFalse(); + } else { + ev1 = createIn( + ev.toAlloy(), + createUnion( + createIntersect( + curEvents(ev.getParamValues().size()), + allEnvironmentalEventsVar()), + genEventVar(ev.getParamValues().size()))); + } + // ev2: t1_on in s.eventsi + genEventsi + ev2 = createIn( + ev.toAlloy(), + createUnion( + curEvents(ev.getParamValues().size()), + genEventVar(ev.getParamValues().size()))); } else { - body.add(createITE(sStableTrue(),createFalse(),elseExpr)); + ev1 = createTrue(); + ev2 = createTrue(); } - */ - /* - List decls = curNextParamsDecls(prs); - decls.add((Decl) new DeclExt(DashStrings.tName, DashStrings.transitionLabelName)); - if (d.hasEvents()) - decls.add((Decl) DeclExt.newSetDeclExt(DashStrings.geName, DashStrings.eventLabelName)); - // tmp - - d.alloyString += "\n"; - */ + + if (d.hasConcurrency()) + body.add( + createITE(curStableTrue(), + createAnd( + o1, + ev1), + createAnd( + o2, + ev2))); + else + body.add(createAnd(o1,ev1)); + + d.alloyString += d.addPredSimple(tout+DashStrings.enabledAfterStepName,decls,body); } + public static Decl genEventsDecl(int i) { + return (Decl) new DeclExt(DashStrings.genEventName + i, DashStrings.allEventsName); + } + public static Decl scopeDecl(int i) { + return (Decl) new DeclExt(DashStrings.scopeName + i, DashStrings.stateLabelName); + } + public static Expr genEventsVar(int i) { + return createVar(DashStrings.genEventName + i); + } + public static Expr scopeVar(int i) { + return createVar(DashStrings.scopeName + i); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index e87575a99..732fcbb9d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -74,9 +74,7 @@ public class AddTransPost { public static void addTransPost(DashModule d, String tfqn) { String tout = translateFQN(tfqn); - List prs = d.getTransParams(tfqn); - List body = new ArrayList(); // confi' = confi - exitedi + enteredi @@ -100,9 +98,9 @@ public static void addTransPost(DashModule d, String tfqn) { List u = DashRef.hasNumParams(sU,i).stream() .map(x -> x.toAlloy()) .collect(Collectors.toList()); - Expr e = curConf(i); + Expr e = curScopesUsed(i); if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); - e = createEquals(nextConf(i),e); + e = createEquals(nextScopesUsed(i),e); } DashRef ev = d.getTransSend(tfqn); @@ -178,18 +176,22 @@ public static void addTransPost(DashModule d, String tfqn) { if (case4.isEmpty()) c4 = createTrue(); else c4 = createAndFromList(case4); - body.add( - createITE(createTestIfNextStableCall(d, tfqn), - createAnd( - nextStableTrue(), - createITE (curStableTrue(), - c1, - c2)), - createAnd( - nextStableFalse(), - createITE(curStableTrue(), - c3, - c4)))); + if (d.hasConcurrency()) + body.add( + createITE(createTestIfNextStableCall(d, tfqn), + createAnd( + nextStableTrue(), + createITE (curStableTrue(), + c1, + c2)), + createAnd( + nextStableFalse(), + createITE(curStableTrue(), + c3, + c4)))); + else + body.add( + createAnd(nextStableTrue(), c1)); d.alloyString += d.addPredSimple(tout+postName,curNextParamsDecls(prs),body); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 1f1c087b4..6e521993a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -61,9 +61,7 @@ public static void addTransPre(DashModule d, String tfqn) { List u = DashRef.hasNumParams(nonO,i).stream() .map(x -> x.toAlloy()) .collect(Collectors.toList()); - // scopesUsedi' = scopesUsedi - exitedi + enteredi - Expr e = curConf(i); - for (Expr x: u) body.add(createNot(createIn(x,scopesUsedVar(i)))); + for (Expr x: u) body.add(createNot(createIn(x,curScopesUsed(i)))); } // event trigger diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index 16b250da8..793067fd5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -27,16 +27,23 @@ public class Common { - // common decls + // s:Snapshot public static Decl curDecl() { return (Decl) new DeclExt(DashStrings.curName, DashStrings.snapshotName); } + + + // s':Snapshot public static Decl nextDecl() { return (Decl) new DeclExt(DashStrings.nextName, DashStrings.snapshotName); } + + // p0:P0 public static Decl paramDecl(String n) { return (Decl) new DeclExt(DashStrings.pName+n, n); } + + // [s:Snapshot, s':Snapshot] public static List curNextDecls() { List o = new ArrayList(); if (!DashOptions.isElectrum) { @@ -45,28 +52,35 @@ public static List curNextDecls() { } return o; } + + // [p0:P0, p1:P1, ...] public static List paramDecls(List prs) { List o = new ArrayList(); for (String n: prs) o.add(paramDecl(n)); return o; } + + // s:Snapshot, p0:P0, p1:P1, ...] public static List curParamsDecls(List prs) { List o = new ArrayList(); if (!DashOptions.isElectrum) o.add(curDecl()); o.addAll(paramDecls(prs)); return o; } + // s:Snapshot, s':Snapshot, p0:P0, p1:P1, ...] public static List curNextParamsDecls(List prs) { List o = new ArrayList(); if (!DashOptions.isElectrum) { o.add(curDecl()); o.add(nextDecl()); } o.addAll(paramDecls(prs)); return o; } - public static Decl eventsDecl(int i) { - return (Decl) new DeclExt(DashStrings.eventsName + i, DashStrings.allEventsName); + + public static Decl genEventDecl(int i) { + return (Decl) new DeclExt(DashStrings.genEventName + i, DashStrings.allEventsName); } - public static Decl scopesUsedDecl(int i) { - return (Decl) new DeclExt(DashStrings.scopesUsedName + i, DashStrings.stateLabelName); + + public static Decl scopeDecl(int i) { + return (Decl) new DeclExt(DashStrings.scopeName + i, DashStrings.allEventsName); } // common vars @@ -78,30 +92,34 @@ public static ExprVar curVar() { public static ExprVar nextVar() { return createVar(DashStrings.nextName); } + //[s,s'] public static List curNextVars() { List o = new ArrayList(); o.add(curVar()); o.add(nextVar()); return o; } - // [n1,n2,...] + // [p1,p2,...] public static List paramVars(List names) { List o = new ArrayList(); for (String n: names) o.add(createVar(DashStrings.pName+n)); return o; } + // [s, p1,p2,...] public static List curParamVars(List params) { List o = new ArrayList(); o.add(curVar()); o.addAll(paramVars(params)); return o; } + // [s,s', p1,p2,...] public static List curNextParamVars(List params) { List o = new ArrayList(curNextVars()); o.addAll(paramVars(params)); return o; } + // stable public static Expr stable() { return createVar(DashStrings.stableName); } @@ -116,6 +134,12 @@ public static Expr allEnvironmentalEventsVar() { public static Expr scopesUsedVar(int size) { return createVar(DashStrings.scopesUsedName + size); } + public static Expr scopeVar(int size) { + return createVar(DashStrings.scopeName + size); + } + public static Expr genEventVar(int size) { + return createVar(DashStrings.genEventName + size); + } public static Expr confVar(int size) { return createVar(DashStrings.confName + size); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 2657a71a9..e8619ff80 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -17,10 +17,11 @@ public static void translate(DashModule d) { AddTransPre.addTransPre(d,tfqn); AddTransPost.addTransPost(d,tfqn); //createTransSemantics(t); - AddTransIsEnabledAfterStep.addTransIsEnabledAfterStep(d,tfqn); + if (d.hasConcurrency()) AddTransIsEnabledAfterStep.addTransIsEnabledAfterStep(d,tfqn); AddTrans.addTrans(d,tfqn); } - AddTestIfNextStable.addTestIfNextStable(d); + if (d.hasConcurrency()) + AddTestIfNextStable.addTestIfNextStable(d); AddSmallStep.addSmallStep(d); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 48bda211e..94ce4db26 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -314,6 +314,9 @@ public List getHigherPriTrans(String tfqn) { return transTable.getHigherPriTrans(tfqn); } + public boolean isEnvironmentalEvent(String efqn) { + return eventTable.isEnvironmentalEvent(efqn); + } public Boolean transAtThisParamDepth(int i) { if (i > maxDepthParams) { DashErrors.tooHighParamDepth(); return null; } else diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index e171eb6f8..f7bf2a342 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -92,9 +92,13 @@ public List getAllEnvironmentalEvents() { .filter(i -> table.get(i).kind == IntEnvKind.ENV) .collect(Collectors.toList()); } - public List getParams(String ev) { - if (table.containsKey(ev)) return table.get(ev).params; - else { DashErrors.eventTableGetParams(); return null; } + public List getParams(String efqn) { + if (table.containsKey(efqn)) return table.get(efqn).params; + else { DashErrors.eventTableEventNotFound("getParams", efqn); return null; } + } + public boolean isEnvironmentalEvent(String efqn) { + if (table.containsKey(efqn)) return (table.get(efqn).kind == IntEnvKind.ENV); + else { DashErrors.eventTableEventNotFound("isEnvironmentalEvent", efqn); return false; } } public List allEventsOfState(String sfqn) { // return all events declared in this state From e640d36e36c8806aa157ac7a20d41bb3b0004831 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 4 May 2023 20:29:09 -0400 Subject: [PATCH 032/129] adding in expr translation --- .../watform/alloyasthelper/DeclExt.java | 49 ++-- .../watform/alloyasthelper/ExprHelper.java | 48 ++-- .../java/ca/uwaterloo/watform/ast/DashDo.java | 3 + .../ca/uwaterloo/watform/ast/DashInit.java | 3 + .../ca/uwaterloo/watform/ast/DashInv.java | 3 + .../ca/uwaterloo/watform/ast/DashWhen.java | 3 + .../ca/uwaterloo/watform/core/DashErrors.java | 42 +++- .../ca/uwaterloo/watform/core/DashRef.java | 27 ++- .../uwaterloo/watform/core/DashStrings.java | 7 +- .../dashtoalloy/AddSnapshotSignature.java | 103 ++++++-- .../watform/parser/CompModuleHelper.java | 22 +- .../uwaterloo/watform/parser/DashModule.java | 22 +- .../uwaterloo/watform/parser/EventTable.java | 1 + .../uwaterloo/watform/parser/StateTable.java | 51 +++- .../uwaterloo/watform/parser/TransTable.java | 68 ++++-- .../ca/uwaterloo/watform/parser/VarTable.java | 228 +++++++++++++++++- .../alloy/dash/DashWffFailTests.java | 6 +- 17 files changed, 577 insertions(+), 109 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java index 880e6a352..8faf9e19b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.StringJoiner; +import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Decl; import edu.mit.csail.sdg.ast.Expr; import edu.mit.csail.sdg.ast.ExprVar; @@ -15,8 +16,26 @@ public class DeclExt extends Decl { - public DeclExt(ExprVar v, Expr e) { - super(null, null, null, null, new ArrayList<>(Arrays.asList(v)) , e); + public DeclExt(ExprVar v, Expr e, boolean isVar) { + super(null, null, null, + isVar ? Pos.UNKNOWN:null, + new ArrayList<>(Arrays.asList(v)) , + e); + } + public DeclExt(String v, Expr e) { + // not sure if mult is needed on last arg + super(null, null, null, null, new ArrayList<>(Arrays.asList(ExprHelper.createVar(v))) , e); + } + // default is "one" + public DeclExt(String v, String typ) { + super(null, null, null, null, new ArrayList<>(Arrays.asList(ExprHelper.createVar(v))), ExprHelper.createOne(ExprHelper.createVar(typ))); + } + public DeclExt(String v, Expr e, boolean isVar) { + // not sure if mult is needed on last arg + super(null, null, null, + isVar ? Pos.UNKNOWN:null, + new ArrayList<>(Arrays.asList(ExprHelper.createVar(v))), + e); } public String toString() { // Decl does not have a toString() @@ -29,24 +48,24 @@ public String toString() { return x; } - public DeclExt(String v, Expr e) { - // not sure if mult is needed on last arg - super(null, null, null, null, new ArrayList<>(Arrays.asList(ExprHelper.createVar(v))) , e); - } - // default is "one" - public DeclExt(String v, String typ) { - super(null, null, null, null, new ArrayList<>(Arrays.asList(ExprHelper.createVar(v))), ExprHelper.createOne(ExprHelper.createVar(typ))); - } + public static DeclExt newOneDeclExt(String v, String typ) { return new DeclExt(v, ExprHelper.createOne(ExprHelper.createVar(typ))); } - public static DeclExt newOneDeclExt(String v, Expr typ) { - return new DeclExt(v, typ); - } + //public static DeclExt newOneDeclExt(String v, Expr typ) { + // return new DeclExt(v, typ); + //} public static DeclExt newSetDeclExt(String v, String typ) { return new DeclExt(v, ExprHelper.createSet(ExprHelper.createVar(typ))); } - public static DeclExt newSetDeclExt(String v, Expr typ) { - return new DeclExt(v, typ); + //public static DeclExt newSetDeclExt(String v, Expr typ) { + // return new DeclExt(v, typ); + //} + + // using Pos.UNKNOWN here as the 4th arg + // makes it seem like there is a pos for "var" + // making it a "var" decl + public static DeclExt newVarDeclExt(String v, Expr typ) { + return new DeclExt(v , typ, true); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index da2f10b76..adf4b22bf 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -47,7 +47,7 @@ public static boolean isExprVar(Expr e) { return (e instanceof ExprVar); } - // simple equality: two var names are equal + // simple equality: two var names are equal ----------------------- public static boolean sEquals(Expr e1, Expr e2) { return ( (e1 == e2) || (isExprVar(e1) && isExprVar(e2) && @@ -60,18 +60,31 @@ public static String getVarName(ExprVar e) { } public static Expr getRight(Expr e) { - if (isExprBinary(e) ) + if (isExprBinary(e)) return ((ExprBinary) e).right; else if (isExprBadJoin(e) ) return ((ExprBadJoin) e).right; - else { DashErrors.getRightNotBinaryOrJoin(); return null; } + else if (e instanceof ExprITE) + return ((ExprITE) e).right; + else { DashErrors.getRightNotBinaryOrJoin(e.getClass().getName()); return null; } } public static Expr getLeft(Expr e) { if (isExprBinary(e)) return ((ExprBinary) e).left; else if (isExprBadJoin(e)) return ((ExprBadJoin) e).left; - else { DashErrors.getLeftNotBinaryOrJoin(); return null; } + else if (e instanceof ExprITE) + return ((ExprITE) e).left; + else { DashErrors.getLeftNotBinaryOrJoin(e.getClass().getName()); return null; } + } + + public static ExprBinary.Op getOp(Expr e) { + assert(e instanceof ExprBinary); + return ((ExprBinary) e).op; + } + public static Expr getCond(Expr e) { + assert(e instanceof ExprITE); + return ((ExprITE) e).cond; } // constructors ----------------------------------- @@ -130,9 +143,10 @@ public static Expr createBinaryExpr(Expr left, ExprBinary.Op op, Expr right) { public static Expr createUnaryExpr(ExprUnary.Op op, Expr sub) { return (ExprUnary) op.make(Pos.UNKNOWN, sub); } - // dunno why this one is different in Alloy code + + public static Expr createExprList(ExprList.Op op, List args) { - return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, op, args); + return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, op, args); } public static Expr createExprQt(ExprQt.Op op, List decls, Expr expr) { return op.make(Pos.UNKNOWN, Pos.UNKNOWN, decls,expr); @@ -186,7 +200,7 @@ public static Expr createEquals(Expr left, Expr right) { public static ExprBinary createNotEquals(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.NOT_EQUALS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - // returns an ExprList + public static Expr createAnd(Expr left, Expr right) { if (sEquals(left, createFalse())) return createFalse(); if (sEquals(right, createFalse())) return createFalse(); @@ -194,10 +208,13 @@ public static Expr createAnd(Expr left, Expr right) { if (sEquals(right, createTrue())) return left; return (Expr) ExprBinary.Op.AND.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } - //public static ExprList createAndList(List args) { - // return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); - //} + public static Expr createAndList(List args) { + //TODO put simplifications in here + return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.AND, args); + } + public static Expr createAndFromList(List elist) { + // does simplifications if (elist.isEmpty()) return createTrue(); Expr ret = elist.get(0); for (Expr el: elist.subList(1,elist.size())) { @@ -220,9 +237,10 @@ public static Expr createOrFromList(List elist) { } return ret; } - //public static ExprList createOr(List args) { - // return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); - //} + public static ExprList createOrList(List args) { + // put simplifications in here so can replace createOrFromList + return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); + } public static ExprBinary createArrow(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.ARROW.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } @@ -231,6 +249,7 @@ public static ExprBinary createUnion(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.PLUS.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } public static Expr createUnionFromList(List elist) { + //TODO make an ExprList if (elist.isEmpty()) return createNone(); Expr ret = elist.get(0); for (Expr el: elist.subList(1,elist.size())) { @@ -273,7 +292,8 @@ public static Expr createITE(Expr cond, Expr impliesExpr, Expr elseExpr) { if (sEquals(cond, createTrue())) return (Expr) impliesExpr; else return (Expr) ExprITE.make(Pos.UNKNOWN, cond, impliesExpr, elseExpr); } - + + public static ExprQt createAll(List decls, Expr expr) { return (ExprQt) ExprQt.Op.ALL.make(Pos.UNKNOWN, Pos.UNKNOWN, decls, expr); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java index 8a6e43a40..1c3acbe58 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashDo.java @@ -24,4 +24,7 @@ public String toString() { s += "}\n"; return s; } + public Expr getDo() { + return action; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java index 3c6309d19..b0b0e166c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java @@ -27,4 +27,7 @@ public String toString() { s += init.toString() + "\n"; return s + "}\n"; } + public Expr getInit() { + return init; + } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java index ccaf59721..a2796ae52 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java @@ -30,4 +30,7 @@ public String toString() { s += inv.toString() + "\n"; return s + "}\n"; } + public Expr getInv() { + return inv; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java index bded691c0..5c11e6348 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashWhen.java @@ -15,4 +15,7 @@ public DashWhen(Pos pos,Expr w) { public String toString() { return DashStrings.whenName + " " + when.toString() + "\n"; } + public Expr getWhen() { + return when; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index a392757a1..8e95bc20c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -49,10 +49,12 @@ public static void dupSiblingNames(String dups) throws Err { public static void dupTransNames(Pos o, String dups) throws Err { throw new ErrorSyntax(o, dupTransNameMsg + dups); } + /* public static String moreThanOneSrcDestMsg = "Transition has more than one src or dest: "; public static void moreThanOneSrcDest(String x, String n) throws Err { throw new ErrorSyntax(moreThanOneSrcDestMsg + x); } + */ public static String unknownSrcDestMsg = "Src/Dest of trans is unknown: "; public static void unknownSrcDest(String x, String t, String tfqn) throws Err { throw new ErrorSyntax(unknownSrcDestMsg + "trans "+tfqn+" "+t+" "+x); @@ -71,6 +73,10 @@ public static void ambiguousSrcDest(String x, String tfqn) throws Err { } // below this have not been tested + public static String nameShouldNotBePrimedMsg = "Declared state/trans/event/var cannot have a primed name: "; + public static void nameShouldNotBePrimed(String n) { + throw new ErrorSyntax(nameShouldNotBePrimedMsg+n); + } public static String transNameCantBeFQNMsg = "Trans name cannot be fully qualified at declaration: "; public static void transNameCantBeFQN(Pos o, String s) { throw new ErrorSyntax(o, transNameCantBeFQNMsg + s); @@ -102,9 +108,9 @@ public static void duplicateBufferName(Pos o, String s) { } // event errors - public static String tooManyEventsMsg = "Multiple "; - public static void tooManyEvents(String xType, String tfqn) { - throw new ErrorSyntax(tooManyEventsMsg + xType + " in " + tfqn); + public static String tooManyMsg = "Multiple "; + public static void tooMany(String xType, String tfqn) { + throw new ErrorSyntax(tooManyMsg + xType + " in " + tfqn); } public static String unknownEventMsg = "Event does not exist: "; public static void unknownEvent(String xType, String v, String tfqn) { @@ -128,10 +134,18 @@ public static void expNotEvent(String xType, String tfqn) { //public static void crossRefMoreThanOneArg(Pos o, String n) throws Err { // throw new ErrorSyntax(o,"Two many args to reference to "+n+" in sibling state"); //} - - - - + public static String noPrimedVarsInMsg = "Primed variables are not allowed in: "; + public static void noPrimedVarsIn(String s1, String s2, String s3) { + throw new ErrorSyntax(noPrimedVarsInMsg + s1 + " " + s2 + " "+s3); + } + public static String ambiguousVarMsg = "Var name not unique within this conc/Root region: "; + public static void ambiguousVar(String xType, String v, String tfqn) { + throw new ErrorSyntax(ambiguousVarMsg +v+" in "+ tfqn + " "+xType); + } + public static String fqnVarWrongNumberParametersMsg = "Wrong number of parameter values for: "; + public static String fqnVarWrongNumberParameters(String s1, String s2, String s3) { + throw new ErrorSyntax(fqnVarWrongNumberParametersMsg + s1 + " "+s2 +" "+s3); + } @@ -168,6 +182,9 @@ public static void stateDoesNotExist(String s1, String n) throws Err { public static void transDoesNotExist(String s1, String n) throws Err { throw new ErrorFatal("for function "+s1+", trans "+n+ " does not exist in trans table"); } + public static void varDoesNotExist(String s1, String n) throws Err { + throw new ErrorFatal("for function "+s1+", var "+n+ " does not exist in var table"); + } public static void missingExpr(String s) throws Err { throw new ErrorFatal("Missing expr type in "+s); } @@ -188,11 +205,11 @@ public static void nonEmptyStateItems() throws Err { public static void nonEmptyTransItems() throws Err { throw new ErrorFatal("Non-empty trans items at end of trans resolve"); } - public static void getRightNotBinaryOrJoin() throws Err { - throw new ErrorFatal("getRightNotBinaryOrJoin"); + public static void getRightNotBinaryOrJoin(String s) throws Err { + throw new ErrorFatal("getRightNotBinaryOrJoin: "+s); } - public static void getLeftNotBinaryOrJoin() throws Err { - throw new ErrorFatal("getLeftNotBinaryOrJoin"); + public static void getLeftNotBinaryOrJoin(String s) throws Err { + throw new ErrorFatal("getLeftNotBinaryOrJoin: "+s); } public static void replaceDashRefExprVarError() throws Err { throw new ErrorFatal("replaceDashRefExprVarError"); @@ -209,4 +226,7 @@ public static void regionMatchesWrongParamNumber() { public static void createTestIfNextStableCallMultipleScopesAtSameLevel() { throw new ErrorFatal("createTestIfNextStableCallMultipleScopesAtSameLevel"); } + public static String UnsupportedExpr(String s1, String s2) { + throw new ErrorFatal("unsupported expression type in: "+ s1 + " "+s2); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index da6343a08..fe6f21481 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -13,6 +13,7 @@ import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; import ca.uwaterloo.watform.core.DashUtilFcns; import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; public class DashRef{ private Pos pos; @@ -36,6 +37,16 @@ public DashRef(String n, List eList) { //System.out.println(eList); } + // within expressions we can't have DashRefs + // so we'll fake it + public static Expr DashRefExpr(String n, List eList) { + // a lot like toAlloy + List ll = new ArrayList(eList); + Collections.reverse(ll); + ll.add(createVar(n)); + return createArrow(processRef(), createArrowExprList(ll)); + } + public String getName() { return name; } @@ -91,6 +102,7 @@ public static boolean isDashRefProcessRef(Expr e) { exp2. exp1. Root/A/B/v1 or exp2. exp1. Root/A/B/v1' */ + /* public static boolean isDashRefJoin(Expr e) { if (isExprJoin(e)) { Expr e2 = e; @@ -102,7 +114,9 @@ public static boolean isDashRefJoin(Expr e) { } return false; } + */ // results from pred calls Tk[xx] + /* public static boolean isDashRefBadJoin(Expr e) { //System.out.println(e); //System.out.println(e.getClass().getName()); @@ -118,11 +132,12 @@ public static boolean isDashRefBadJoin(Expr e) { } return false; } - + */ /* can only be used in an event exp2 -> exp1 -> Root/A/B/ev1 */ + /* public static boolean isDashRefArrow(Expr e) { if (isExprArrow(e)) { Expr e2 = e; @@ -134,14 +149,14 @@ public static boolean isDashRefArrow(Expr e) { } return false; } - + */ /* from exp2. exp2. Root/A/B/v1' return Root/A/B/v1' */ public static String nameOfDashRefExpr(Expr e) { - assert(isDashRefProcessRef(e) || isDashRefJoin(e) || isDashRefArrow(e) || isDashRefBadJoin(e)); + //assert(isDashRefProcessRef(e) || isDashRefJoin(e) || isDashRefArrow(e) || isDashRefBadJoin(e)); Expr e2 = getRight(e); - while (isExprBadJoin(e2) || isExprJoin(e2)) { + while (/*isExprBadJoin(e2) ||*/ isExprJoin(e2)) { e2 = getRight(e2); } assert(isExprVar(e2)); @@ -158,7 +173,7 @@ public static List paramValuesOfDashRefExpr(Expr e) { r.add(getLeft(e1)); e1 = getRight(e1); } - } else if (isExprJoin(e1)) { + } /* else if (isExprJoin(e1)) { while (isExprJoin(e1)) { r.add(getLeft(e1)); e1 = getRight(e1); @@ -173,7 +188,7 @@ public static List paramValuesOfDashRefExpr(Expr e) { r.add(getLeft(e1)); e1 = getRight(e1); } - } else { + } */ else { DashErrors.nonDashRefExpr(); return null; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 8d3584c15..486ed0090 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -48,7 +48,7 @@ public class DashStrings { public static String gotoName = "goto"; public static String sendName = "send"; public static String SLASH = "/"; - + public static String PRIME = "'"; // predicate names @@ -73,7 +73,7 @@ public class DashStrings { public static String allEventsName = "AllEvents"; public static String allEnvironmentalEventsName = "AllEnvironmentalEvents"; public static String allInternalEventsName = "AllInternalEvent"; - + public static String variablesName = "Variables"; public static String preName = "_pre"; public static String postName = "_post"; @@ -117,4 +117,7 @@ public static enum DefKind { public static String processRef = "$$PROCESSREF$$"; + public static boolean hasPrime(String s) { + return (s.substring(s.length()-1, s.length()).equals(PRIME)); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 0e9b1fc37..39a45c0e6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -14,6 +14,7 @@ import static ca.uwaterloo.watform.core.DashStrings.*; import ca.uwaterloo.watform.core.DashUtilFcns; import ca.uwaterloo.watform.core.DashRef; +import ca.uwaterloo.watform.core.DashStrings; // shortens the code to import these statically import static ca.uwaterloo.watform.core.DashFQN.*; @@ -60,22 +61,73 @@ public static void addSnapshotSignature(DashModule d){ if (d.hasConcurrency()) { d.alloyString += d.addVarSigSimple(stableName, createVar(boolName)); } - // add dynamic symbols (vars and buffers) - /* - for (DashDynSymbols v: getDynSymbols()) { - List prms = Collections.nCopies(IdentifiersName, v.getParams().size()); - addVarSigSimple( - v.getFullyQualName(), - createArrowList(prms+v.createAlloyTyp())); - } - */ + // add vars and parameter sets -------------------------------------- + + List decls; + List allvfqns = d.getAllVarNames(); + + // vfqns with no params and simple type + // becomes var sig vfqn in var {} + List allvfqnsNoParamsSimpleTyp = allvfqns.stream() + .filter(i -> d.getVarParams(i).size() == 0 && isExprVar(d.getVarType(i))) + .collect(Collectors.toList()); + for (String v: allvfqnsNoParamsSimpleTyp) + d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar) d.getVarType(v)) ); + + // vfqns with no params and arrow type (A -> B) + // becomes sig A { var vfqn: B } + // but A has already been declared somewhere by the user + // and we can't easily add a field to an existing signature in + // Alloy module, so instead add one atom to model + // one sig Variables { + // v1: typ1 + // } + // and have to deal with this case in translation to Alloy + List allvfqnsNoParamsArrowTyp = allvfqns.stream() + .filter(i -> d.getVarParams(i).size() == 0 && isExprArrow(d.getVarType(i))) + .collect(Collectors.toList()); + if (!allvfqnsNoParamsArrowTyp.isEmpty()) { + decls = new ArrayList(); + for (String v: allvfqnsNoParamsArrowTyp) + decls.add(DeclExt.newVarDeclExt(translateFQN(v), d.getVarType(v))); + d.alloyString += d.addOneSigWithDeclsSimple(DashStrings.variablesName, decls); + } + + // vfqns with parameters P1, P2, P3 + // sig P1 { + // var v1: P2 -> P3 -> typ1 + // } + // it is enough to look at state parameters to get all parameters + List allvfqnsWithThisFirstParam; + + for (String prm: d.getAllParams()) { + allvfqnsWithThisFirstParam = allvfqns.stream() + // must be at least one parameter + .filter(i -> d.getVarParams(i).size() != 0 && d.getVarParams(i).get(0).equals(prm)) + .collect(Collectors.toList()); + // construct decls -- might be none but still have to + // create sig for this parameter + decls = new ArrayList(); + for (String v: allvfqnsWithThisFirstParam) { + if (d.getVarParams(v).size() == 1) { + decls.add(new DeclExt(v, d.getVarType(v))); + } else { + List plist = createVarList(d.getVarParams(v).subList(1, d.getVarParams(v).size()-1)); + plist.add(d.getVarType(v)); + decls.add(DeclExt.newVarDeclExt(translateFQN(v),createArrowExprList(plist))); + } + } + d.alloyString += d.addSigWithDeclsSimple(prm, decls); + } + + // add buffers } else { // if traces/tcmc sig Snapshot {} with fields List decls = new ArrayList(); // scopesUsed0, conf0, event0 //if (d.transAtThisParamDepth(0)) - decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", stateLabelName)); + decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", stateLabelName)); decls.add(DeclExt.newSetDeclExt(confName+"0", stateLabelName)); if (d.hasEvents()) decls.add(DeclExt.newSetDeclExt(eventsName+"0", allEventsName)); @@ -84,16 +136,16 @@ public static void addSnapshotSignature(DashModule d){ cop = Collections.nCopies(i+1,identifierName); // scopesUsed 1, etc. //if (d.transAtThisParamDepth(i)) - decls.add(DeclExt.newSetDeclExt( + decls.add((Decl) new DeclExt( scopesUsedName+Integer.toString(i), createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); // conf 1, etc. - decls.add(DeclExt.newSetDeclExt( + decls.add((Decl) new DeclExt( confName+Integer.toString(i), createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); // event 1, etc. if (d.hasEvents() && d.hasEventsAti(i)) - decls.add(new DeclExt( + decls.add((Decl) new DeclExt( eventsName+Integer.toString(i), createArrowStringList(DashUtilFcns.newListWith(cop, allEventsName)))); } @@ -101,16 +153,21 @@ public static void addSnapshotSignature(DashModule d){ if (d.hasConcurrency()) { decls.add(new DeclExt(stableName, createOne(createVar(boolName)))); } - // add dynamic symbols (vars and buffers) - /* - for (DashDynSymbols v: getDynSymbols()) { - List prms = Collections.nCopies(IdentifiersName, v.getParams().size()); - decls.add(createDecl( - v.getFullyQualName(), - createArrowList(prms+v.createAlloyTyp()))); - } - */ - + // add vars + List typlist; + for (String vfqn: d.getAllVarNames()) { + typlist = createVarList(d.getVarParams(vfqn)); // could be empty + typlist.add(d.getVarType(vfqn)); + if (typlist.size() > 1 ) + decls.add((Decl) new DeclExt( + translateFQN(vfqn), + createArrowExprList(typlist))); + else + decls.add((Decl) new DeclExt( + translateFQN(vfqn), + typlist.get(0))); + } + // add buffers d.alloyString += d.addSigWithDeclsSimple( snapshotName, decls); } d.alloyString += "\n"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 007055c6a..4901a08d0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -192,7 +192,27 @@ public String addSigWithDeclsSimple(String name, List decls) { s += j.toString() + "\n}\n"; return s; } - + public String addOneSigWithDeclsSimple(String name, List decls) { + // sig name { decls } + addSig( + Pos.UNKNOWN, + name, + null, + null, + decls, + null, + null, + null, + AttrType.ONE.makenull(Pos.UNKNOWN), + null, + null, + null); + String s = DashStrings.sigName + space + name + space + "{\n"; + StringJoiner j = new StringJoiner(",\n"); + decls.forEach(i -> j.add(tab + i.toString())); + s += j.toString() + "\n}\n"; + return s; + } public String addVarSigSimple(String name, ExprVar typ) { // var sig s in typ {}; addSig( diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 94ce4db26..6d9668eed 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -291,7 +291,7 @@ public List getRegion(String sfqn) { } // stuff about transitions - public Set getAllTransNames() { + public List getAllTransNames() { return transTable.getAllTransNames(); } @@ -316,6 +316,15 @@ public List getHigherPriTrans(String tfqn) { public boolean isEnvironmentalEvent(String efqn) { return eventTable.isEnvironmentalEvent(efqn); + } + public List getAllVarNames() { + return varTable.getAllVarNames(); + } + public List getVarParams(String vfqn) { + return varTable.getParams(vfqn); + } + public Expr getVarType(String vfqn) { + return varTable.getType(vfqn); } public Boolean transAtThisParamDepth(int i) { if (i > maxDepthParams) { DashErrors.tooHighParamDepth(); return null; } @@ -483,11 +492,14 @@ public void resolveAllDash(A4Reporter rep) { // root.resolveTransTable(stateTable,transTable); // if root has no substates? // if no transitions? - stateTable.resolve(getRootName()); - // TODO will need eventTable - transTable.resolve(stateTable, eventTable); + + // resolves inits, invariants + stateTable.resolve(getRootName(), varTable); + + transTable.resolve(stateTable, eventTable, varTable); + maxDepthParams = stateTable.getMaxDepthParams(); - //transAtThisParamDepth = new boolean[maxDepthParams+1]; + transAtThisParamDepth = transTable.transAtThisParamDepth(maxDepthParams); // //debug("Root/S1/t1"); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index f7bf2a342..8cdba9d83 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -53,6 +53,7 @@ public String toString() { public Boolean add(String efqn, IntEnvKind k, List prms) { assert(prms!=null); if (table.containsKey(efqn)) return false; + else if (hasPrime(efqn)) { DashErrors.nameShouldNotBePrimed(efqn); return false; } else { table.put(efqn, new EventElement(k,prms)); return true; } } public void resolveAllEventTable() { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index dafde283f..5aa837756 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -19,13 +19,15 @@ import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.*; -import ca.uwaterloo.watform.ast.*; +import ca.uwaterloo.watform.core.DashRef; import static ca.uwaterloo.watform.core.DashUtilFcns.*; import static ca.uwaterloo.watform.core.DashStrings.*; import static ca.uwaterloo.watform.core.DashFQN.*; import ca.uwaterloo.watform.alloyasthelper.ExprHelper; -import ca.uwaterloo.watform.core.DashRef; +import ca.uwaterloo.watform.ast.*; + +import ca.uwaterloo.watform.parser.VarTable; public class StateTable { private HashMap table; @@ -47,11 +49,13 @@ public class StateElement { // this could be a set b/c there are no dups and order // doesn't matter, but lists are easier to work with private List immChildren; // empty if none - private List invariants; - private List inits; + private List origInvariants; + private List origInits; private List actions; private List conditions; - + // after resolve + private List invs; + private List inits; /* private ArrayList transWithThisSrc; private ArrayList transWithThisScope; @@ -88,8 +92,8 @@ public StateElement( this.def = d; this.parent = p; this.immChildren = iChildren; - this.invariants = invL; - this.inits = initL; + this.origInvariants = invL; + this.origInits = initL; this.actions = actL; this.conditions = condL; @@ -141,6 +145,7 @@ public Boolean allAttributesEmpty() { immChildren.isEmpty() ) ; } */ + /* public Boolean attributesSame(DashStrings.StateKind k, String prm, List prms, DashStrings.DefKind d, String p, List iChildren) { return (kind == k && param.equals(prm) && @@ -149,6 +154,13 @@ public Boolean attributesSame(DashStrings.StateKind k, String prm, List parent.equals(p) && immChildren.equals(iChildren)); } + */ + public void setInits(List elist) { + inits = elist; + } + public void setInvs(List elist) { + invs = elist; + } } @@ -207,6 +219,7 @@ public boolean add( //} //else if (table.containsKey(fqn)) return false; + else if (DashStrings.hasPrime(fqn)) { DashErrors.nameShouldNotBePrimed(fqn); return false; } else { table.put(fqn, new StateElement(k,prm, prms,d,p,iChildren, invL, initL, actL, condL)); return true; } //System.out.println("adding to State table: "+fqn+space+prm + space + prms+space+d+space+p+iChildren); } @@ -370,12 +383,24 @@ public List getAllParams() { } return DashUtilFcns.setToList(allParams); } - public void resolve(String root) { - //System.out.println("Resolving state table"); - //for (String k: table.keySet()) - //if (table.get(k) == null) DashErrors.transUsesNonExistentState(k); - // walk down parent to children and pass back info - //TODO: nothing to do here now? + public void resolve(String root, VarTable vt) { + // resolve inits and invariants + for (String sfqn: table.keySet()) { + table.get(sfqn) + .setInits(table.get(sfqn).origInits.stream() + .map(i -> vt.resolveExpr("init", i.getInit(), + getRegion(sfqn), + sfqn, + getParams(sfqn))) + .collect(Collectors.toList())); + table.get(sfqn) + .setInvs(table.get(sfqn).origInvariants.stream() + .map(i -> vt.resolveExpr("inv", i.getInv(), + getRegion(sfqn), + sfqn, + getParams(sfqn))) + .collect(Collectors.toList())); + } isResolved = true; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index eb2a3a576..acb4353c7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -8,7 +8,7 @@ import java.io.*; -import java.util.Set; + import java.util.HashMap; import java.util.List; import java.util.ArrayList; @@ -48,7 +48,7 @@ public class TransElement { public DashRef dest; public Expr when; // just one? public DashRef on; - public List action; + public Expr act; public DashRef send; /* @@ -86,6 +86,8 @@ public String toString() { s += "dest: " + NoneStringIfNeeded(dest) + "\n"; s += "on: " + NoneStringIfNeeded(on) + "\n"; s += "send: " + NoneStringIfNeeded(send) + "\n"; + s += "when: " + NoneStringIfNeeded(when) + "\n"; + s += "do: " + NoneStringIfNeeded(act) + "\n"; // add more return s; } @@ -101,6 +103,12 @@ public void setOn(DashRef e) { public void setSend(DashRef e) { send = e; } + public void setWhen(Expr e) { + when = e; + } + public void setDo(Expr e) { + act = e; + } } public TransTable() { @@ -129,6 +137,7 @@ public boolean add( assert(sendList != null); assert(doList != null); if (table.containsKey(tfqn)) return false; + else if (DashStrings.hasPrime(tfqn)) { DashErrors.nameShouldNotBePrimed(tfqn); return false; } else { table.put(tfqn, new TransElement(params,fromList,onList,whenList,gotoList,sendList,doList)); return true; } } public String toString() { @@ -142,8 +151,8 @@ public String toString() { return s; } - public Set getAllTransNames() { - return table.keySet(); + public List getAllTransNames() { + return new ArrayList(table.keySet()); } public List getParams(String t) { if (table.containsKey(t)) return table.get(t).params; @@ -165,7 +174,14 @@ public DashRef getSend(String t) { if (table.containsKey(t)) return table.get(t).send; else { DashErrors.transDoesNotExist("getSend", t); return null; } } - + public Expr getDo(String t) { + if (table.containsKey(t)) return table.get(t).act; + else { DashErrors.transDoesNotExist("getDo", t); return null; } + } + public Expr getWhen(String t) { + if (table.containsKey(t)) return table.get(t).when; + else { DashErrors.transDoesNotExist("getWhen", t); return null; } + } // might be better to make this getTransWithThisSrc // but this is more efficient if it is only used for higherPriTrans @@ -194,7 +210,7 @@ public List getHigherPriTrans(String t) { * must be done after resolveAllState * this fcn does not modify anything in this object */ - public void resolve(StateTable st, EventTable et) { + public void resolve(StateTable st, EventTable et, VarTable vt) { //System.out.println(st); //System.out.println(toString()); @@ -218,7 +234,16 @@ public void resolve(StateTable st, EventTable et) { table.get(tfqn).setDest(determineSrcDest("goto", gList, st, tfqn)); // determining the when - + List whenExpList = + table.get(tfqn).whenList.stream() + .map(p -> (p.getWhen())) + .collect(Collectors.toList()); + table.get(tfqn) + .setDo( + vt.resolveExprList("when", whenExpList, + st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), + tfqn, + getParams(tfqn))); // determining the on @@ -236,7 +261,17 @@ public void resolve(StateTable st, EventTable et) { table.get(tfqn).setSend(determineEvent("send", sendExpList,st, et, tfqn)); // determining the do - + List doExpList = + table.get(tfqn).doList.stream() + .map(p -> (p.getDo())) + .collect(Collectors.toList()); + table.get(tfqn) + .setDo( + vt.resolveExprList("do", doExpList, + st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), + tfqn, + getParams(tfqn))); + } isResolved = true; } @@ -250,12 +285,14 @@ public void resolve(StateTable st, EventTable et) { * Requires state table to have been built already */ + // tfqn is needed for error messages + public DashRef determineSrcDest(String xType, List ll, StateTable st, String tfqn) { // parent state of this transition String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); if (ll.size() > 1) { - DashErrors.moreThanOneSrcDest(xType, tfqn); + DashErrors.tooMany(xType, tfqn); return null; } else if (ll.isEmpty()) // can be a loop on root @@ -321,7 +358,7 @@ public DashRef determineSrcDest(String xType, List ll, StateTable st, private DashRef determineEvent(String xType, List expList, StateTable st, EventTable et, String tfqn) { if (expList.isEmpty()) return null; else if (expList.size() > 1) { - DashErrors.tooManyEvents(xType, tfqn); + DashErrors.tooMany(xType, tfqn); return null; } else { Expr exp = expList.get(0); @@ -333,16 +370,17 @@ else if (expList.size() > 1) { // ProcessRef: A/B/C[a1,b1]/ev which became $$PROCESSREF$$. b1.a1.A/B/C/ev in parsing // BadJoin: ev[a1,b1] which became b1.a1.ev in parsing if (ExprHelper.isExprVar(exp) || - DashRef.isDashRefArrow(exp) || - DashRef.isDashRefProcessRef(exp) || - DashRef.isDashRefBadJoin(exp)) { + //DashRef.isDashRefArrow(exp) || + DashRef.isDashRefProcessRef(exp))// || + //DashRef.isDashRefBadJoin(exp)) + { String e; List paramValues; if (ExprHelper.isExprVar(exp)) { e = ExprHelper.getVarName((ExprVar) exp); paramValues = new ArrayList(); } else { - e = DashFQN.fqn(DashRef.nameOfDashRefExpr(exp)); + e = DashRef.nameOfDashRefExpr(exp); paramValues = DashRef.paramValuesOfDashRefExpr(exp); } String efqn = DashFQN.fqn(e); @@ -391,6 +429,8 @@ else if (expList.size() > 1) { } } + + public boolean[] transAtThisParamDepth(int max) { boolean[] depthsInUse = new boolean[max+1]; // 0..max for (int i=0; i <= max; i++) depthsInUse[i] = false; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index 89c641d14..22bc1a152 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -1,14 +1,22 @@ package ca.uwaterloo.watform.parser; +import java.util.Set; import java.util.List; import java.util.ArrayList; import java.util.HashMap; +import java.util.Collections; +import java.util.stream.Collectors; -import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.*; +import edu.mit.csail.sdg.alloy4.ConstList; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.core.*; import static ca.uwaterloo.watform.core.DashUtilFcns.*; import static ca.uwaterloo.watform.core.DashStrings.*; +import ca.uwaterloo.watform.core.DashRef; public class VarTable { @@ -42,7 +50,6 @@ public String toString() { public VarTable() { this.table = new HashMap(); - } public String toString() { String s = new String("VAR TABLE\n"); @@ -56,9 +63,226 @@ public String toString() { public Boolean add(String vfqn, IntEnvKind k, List prms, Expr t) { assert(prms!=null); if (table.containsKey(vfqn)) return false; + if (hasPrime(vfqn)) { DashErrors.nameShouldNotBePrimed(vfqn); return false; } else { table.put(vfqn, new VarElement(k,prms, t)); return true; } } public void resolveAllVarTable() { // TODO } + public List getAllVarNames() { + return new ArrayList(table.keySet()); + } + public List getParams(String vfqn) { + if (table.containsKey(vfqn)) return table.get(vfqn).params; + else { DashErrors.varDoesNotExist("getParams", vfqn); return null; } + } + public Expr getType(String vfqn) { + if (table.containsKey(vfqn)) return table.get(vfqn).typ; + else { DashErrors.varDoesNotExist("getType", vfqn); return null; } + } + + public List allVarsOfState(String sfqn) { + // return all events declared in this state + // will have the sfqn as a prefix + return table.keySet().stream() + // prefix of vfqn are state names + .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) + .collect(Collectors.toList()); + } + + /* + results in an Expr for the action that has all references to variables as DashRefExpr's + fqn is a parameter to determine transition parameters and for error messages + used for when and do parts of a transitions + + TODO: buffers, this + */ + public Expr resolveExprList(String xType, List expList, List region, String fqn, List params) { + if (expList.isEmpty()) return null; + else if (expList.size() > 1) { + DashErrors.tooMany(xType, fqn); + return null; + } else { + Expr exp = expList.get(0); + + + return resolveExpr(xType, exp, region, fqn, params); + } + } + + //TODO should probably be a visitor using accept methods of Expr + // have to recurse through exp types, replace dynamic vars with DashRef and rebuild exp + // don't use ExprHelper much here because we want to + // as much about the expression as possible + public Expr resolveExpr(String xType, Expr exp, List region, String fqn, List params) { + if (isExprVar(exp) || + //DashRef.isDashRefJoin(exp) || + DashRef.isDashRefProcessRef(exp)) // || + //DashRef.isDashRefBadJoin(exp)) + { + return dashRefVar(xType, exp, region, fqn, params); + + } else if (isExprBinary(exp)) { + return ((ExprBinary) exp).op.make( + exp.pos, + exp.closingBracket, + resolveExpr(xType, getLeft(exp), region, fqn, params), + resolveExpr(xType, getRight(exp), region, fqn, params)); + + } else if (isExprBadJoin(exp)) { + return ExprBadJoin.make( + exp.pos, + exp.closingBracket, + resolveExpr(xType, getLeft(exp), region, fqn, params), + resolveExpr(xType, getRight(exp), region, fqn, params)); + + } else if (exp instanceof ExprCall) { + return ExprCall.make( + exp.pos, + exp.closingBracket, + ((ExprCall) exp).fun, + ((ExprCall) exp).args.stream() + .map(i -> resolveExpr(xType, i, region, fqn, params)) + .collect(Collectors.toList()), + ((ExprCall) exp).extraWeight); + + } else if (exp instanceof ExprChoice){ + //TODO: check into this cast + // not sure why is it necessary + ConstList x = (ConstList) ((ExprChoice) exp).choices.stream() + .map(i -> resolveExpr(xType, i, region, fqn, params)) + .collect(Collectors.toList()); + return ExprChoice.make( + false, + exp.pos, + x, + ((ExprChoice) exp).reasons); + + } else if (exp instanceof ExprITE){ + return ExprITE.make( + exp.pos, + resolveExpr(xType, getCond(exp), region, fqn, params), + resolveExpr(xType, getLeft(exp), region, fqn, params), + resolveExpr(xType, getRight(exp), region, fqn, params)); + + } else if (exp instanceof ExprList){ + return ExprList.make( + exp.pos, + exp.closingBracket, + ((ExprList) exp).op, + ((ExprList) exp).args.stream() + .map(i -> resolveExpr(xType, i, region, fqn, params)) + .collect(Collectors.toList()) + ); + + } else if (exp instanceof ExprUnary){ + return ((ExprUnary) exp).op.make( + exp.pos, + resolveExpr(xType, ((ExprUnary) exp).sub, region, fqn, params)); + + } else if (exp instanceof ExprLet){ + //TODO rule out var name + return ExprLet.make( + exp.pos, + ((ExprLet) exp).var, + resolveExpr(xType, ((ExprLet) exp).expr, region, fqn, params), + resolveExpr(xType, ((ExprLet) exp).sub, region, fqn, params)); + + } else if (exp instanceof ExprQt){ + //TODO rule out var names + return ((ExprQt) exp).op.make( + exp.pos, + exp.closingBracket, + ((ExprQt) exp).decls, + resolveExpr(xType, ((ExprQt) exp).sub, region, fqn, params)); + + } else if (exp instanceof ExprConstant){ + return exp; + + } else { + DashErrors.UnsupportedExpr(xType, fqn); + return null; + } + } + + // fqn could be trans or state + private Expr dashRefVar(String xType, Expr exp, List region, String fqn, List params) { + + // Join: b1.a1.var + + // DashRefProcessRef: A/B/C[a1,b1]/var which became $$PROCESSREF$$. b1.a1.A/B/C/var in parsing + // a DashRefProcessRef could be either a value for an exp + // or a tuple for an event + + // BadJoin: var[a1,b1] which became b1.a1.var in parsing + + // don't include isDashRefArrow here because that is only possible for + // events (which are tuples) not actions + + + String v; + List paramValues; + if (isExprVar(exp)) { + v = getVarName((ExprVar) exp); + paramValues = new ArrayList(); + } else { + v = DashRef.nameOfDashRefExpr(exp); + paramValues = DashRef.paramValuesOfDashRefExpr(exp); + } + String vfqn = DashFQN.fqn(v); + Boolean isPrimed = false; + if (hasPrime(v)) { + isPrimed = true; + vfqn = vfqn.substring(0,vfqn.length()-1); + } + + + if (!xType.equals("do") && isPrimed) { + DashErrors.noPrimedVarsIn(xType, v, fqn); + return null; + } + List matches = new ArrayList(); + for (String s:region) + for (String x:allVarsOfState(s)) { + if (DashFQN.suffix(x,vfqn)) matches.add(x); + } + if (matches.size() > 1) { + DashErrors.ambiguousVar(xType, v, fqn); + return null; + } else if (matches.isEmpty()) { + // its some var other than a dynamic variable + return exp; + } else { + String m = matches.get(0); + if (paramValues.isEmpty()) { + // must have same param values as trans b/c in same conc region + if (getParams(m).size() > params.size()) { + // getRegion did not return things that all + // have the same parameter values + DashErrors.regionMatchesWrongParamNumber(); + return null; + } else { + // could be a subset of transition param values + List prmValues = + createVarList( + DashStrings.pName, + params.subList(0, getParams(m).size())); + if (isPrimed) m = m + PRIME; + return DashRef.DashRefExpr(m, prmValues); + } + } else if (getParams(m).size() != paramValues.size()) { + // came with parameters so must be right number + DashErrors.fqnVarWrongNumberParameters(xType, v, fqn); + return null; + } else { + if (isPrimed) m = m+PRIME; + return DashRef.DashRefExpr( + m, + // have to recursive through expressions in parameters + paramValues.stream() + .map(i -> resolveExpr(xType, i, region, fqn, params)) + .collect(Collectors.toList())); + } + } + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java index 399eeaa9d..cd9b7ca49 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java @@ -76,9 +76,9 @@ public static Collection fileNameMsg() { {"dupSiblingNames2", dupSiblingNamesMsg}, {"dupTransName1", dupTransNameMsg}, {"dupTransName2", dupTransNameMsg}, // 17 - {"moreThanOneSrcDest1", moreThanOneSrcDestMsg}, - {"moreThanOneSrcDest2", moreThanOneSrcDestMsg}, // 19 - {"moreThanOneSrcDest3", moreThanOneSrcDestMsg}, + {"moreThanOneSrcDest1", tooManyMsg}, + {"moreThanOneSrcDest2", tooManyMsg}, // 19 + {"moreThanOneSrcDest3", tooManyMsg}, //{"unknownSrcDest1", unknownSrcDestMsg}, //21 //{"unknownSrcDest2", unknownSrcDestMsg}, //{"unknownSrcDest3", unknownSrcDestMsg}, From 56c1804db63b65f5a402fa011cda8e28d1d60e47 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sun, 7 May 2023 14:17:40 -0400 Subject: [PATCH 033/129] adding expression translation --- .../watform/alloyasthelper/ExprHelper.java | 18 ++- .../watform/alloyasthelper/ExprToString.java | 50 +++--- .../ca/uwaterloo/watform/ast/DashInv.java | 2 +- .../ca/uwaterloo/watform/core/DashErrors.java | 7 + .../ca/uwaterloo/watform/core/DashFQN.java | 2 + .../ca/uwaterloo/watform/core/DashRef.java | 30 +++- .../uwaterloo/watform/core/DashStrings.java | 12 +- .../watform/dashtoalloy/AddInit.java | 65 ++++++++ .../uwaterloo/watform/dashtoalloy/AddInv.java | 69 ++++++++ .../dashtoalloy/AddSnapshotSignature.java | 2 +- .../AddTransIsEnabledAfterStep.java | 10 +- .../watform/dashtoalloy/AddTransPost.java | 21 +-- .../watform/dashtoalloy/AddTransPre.java | 13 +- .../uwaterloo/watform/dashtoalloy/Common.java | 150 +++++++++++++++++- .../watform/dashtoalloy/DashToAlloy.java | 2 + .../watform/parser/CompModuleHelper.java | 22 ++- .../uwaterloo/watform/parser/DashModule.java | 16 +- .../uwaterloo/watform/parser/StateTable.java | 37 +++-- .../uwaterloo/watform/parser/TransTable.java | 2 + .../ca/uwaterloo/watform/parser/VarTable.java | 93 +++++++---- 20 files changed, 522 insertions(+), 101 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index adf4b22bf..b7e97eaa8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -34,6 +34,9 @@ public class ExprHelper { public static boolean isExprBinary(Expr e) { return (e instanceof ExprBinary); } + public static boolean isExprUnary(Expr e) { + return (e instanceof ExprUnary); + } public static boolean isExprJoin(Expr e) { return ((e instanceof ExprBinary) && ((ExprBinary) e).op.equals(ExprBinary.Op.JOIN)); } @@ -47,6 +50,12 @@ public static boolean isExprVar(Expr e) { return (e instanceof ExprVar); } + public static boolean isPrimedVar(Expr e) { + return (e instanceof ExprUnary && + ((ExprUnary) e).sub instanceof ExprVar && + ((ExprUnary) e).op == ExprUnary.Op.PRIME); + } + // simple equality: two var names are equal ----------------------- public static boolean sEquals(Expr e1, Expr e2) { return ( (e1 == e2) || @@ -78,6 +87,13 @@ else if (e instanceof ExprITE) else { DashErrors.getLeftNotBinaryOrJoin(e.getClass().getName()); return null; } } + public static Expr getSub(Expr e) { + if (isExprUnary(e)) { + return ((ExprUnary) e).sub; + } else { + DashErrors.getSubNotUnary(e.getClass().getName()); return null; + } + } public static ExprBinary.Op getOp(Expr e) { assert(e instanceof ExprBinary); return ((ExprBinary) e).op; @@ -171,7 +187,7 @@ public static Expr createJoinList(List elist) { Collections.reverse(elist); ret = elist.get(0); for (Expr el: elist.subList(1,elist.size())) { - ret = createJoin(ret,el); + ret = createJoin(el,ret); } return ret; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index c3d8c39bb..005a884b6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -291,63 +291,75 @@ private void ExprQtToOut(ExprQt expr) { } private void ExprUnaryToOut(ExprUnary expr) { + switch (expr.op) { + /* case SOMEOF : - out.print("some "); - break; + out.print("some ("); + ExprToOut(expr.sub); + out.print(")"); case LONEOF : - out.print("lone "); - break; + out.print("lone ("); + out.print(")"); case ONEOF : - out.print("one "); - break; + out.print("one ("); + out.print(")"); case SETOF : - out.print("set "); - break; + out.print("set ("); + out.print(")"); case EXACTLYOF : - out.print("exactly "); - break; + out.print("exactly ("); + out.print(")"); case CAST2INT : out.print("int["); ExprToOut(expr.sub); out.print(']'); - return; + case CAST2SIGINT : out.print("Int["); ExprToOut(expr.sub); out.print(']'); - return; + case PRIME : + //TODO: perhaps this one should not exist? + //TODO: other temporal formulas that should not exist? out.print('('); ExprToOut(expr.sub); out.print(")'"); - return; + case RCLOSURE : out.print("* ("); ExprToOut(expr.sub); out.print(")"); - return; + case TRANSPOSE : out.print("~ ("); ExprToOut(expr.sub); out.print(")"); - return; + case CLOSURE : out.print("^ ("); ExprToOut(expr.sub); out.print(")"); - return; + case NOT : out.print("! {"); ExprToOut(expr.sub); out.print("}"); - return; + */ case NOOP : + ExprToOut(expr.sub); break; default : - out.print(expr.op).print(' '); + // this puts in more brackets that usual + // but since we can have + // #var become #(s.var) + // the brackets might be necessary + out.print(expr.op).print('('); + ExprToOut(expr.sub); + out.print(")"); } - ExprToOut(expr.sub); + } private void ExprVarToOut(ExprVar expr) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java index a2796ae52..6330b2f42 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java @@ -24,7 +24,7 @@ public DashInv(Pos p, String n, Expr i) { } public String toString() { String s = new String(); - s += DashStrings.invariantName +" "; + s += DashStrings.invName +" "; if (name != null) s += name; s += " {\n"; s += inv.toString() + "\n"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 8e95bc20c..254a13831 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -8,6 +8,7 @@ import edu.mit.csail.sdg.alloy4.Err; import edu.mit.csail.sdg.alloy4.ErrorSyntax; import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.ast.Expr; public class DashErrors { @@ -211,6 +212,9 @@ public static void getRightNotBinaryOrJoin(String s) throws Err { public static void getLeftNotBinaryOrJoin(String s) throws Err { throw new ErrorFatal("getLeftNotBinaryOrJoin: "+s); } + public static void getSubNotUnary(String s) throws Err { + throw new ErrorFatal("getSubNotUnary: "+s); + } public static void replaceDashRefExprVarError() throws Err { throw new ErrorFatal("replaceDashRefExprVarError"); } @@ -229,4 +233,7 @@ public static void createTestIfNextStableCallMultipleScopesAtSameLevel() { public static String UnsupportedExpr(String s1, String s2) { throw new ErrorFatal("unsupported expression type in: "+ s1 + " "+s2); } + public static String UnsupportedExpr(String s1, Expr e) { + throw new ErrorFatal("unsupported expression type in: "+ s1+ " " + e.toString()); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java index f1bbdc4a3..9117cf093 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java @@ -38,6 +38,8 @@ public static String fqn(String s1,String s2) { q += s2; return q; } + // not really needed unless we change it so that + // inputQualChar != internal QualChar public static String fqn(String n) { return n.replace(inputQualChar, internalQualChar); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index fe6f21481..8a91edfe4 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -44,7 +44,9 @@ public static Expr DashRefExpr(String n, List eList) { List ll = new ArrayList(eList); Collections.reverse(ll); ll.add(createVar(n)); - return createArrow(processRef(), createArrowExprList(ll)); + //System.out.println(ll); + //System.out.println(createJoin(processRef(), createJoinList(ll))); + return createJoin(processRef(), createJoinList(ll)); } public String getName() { @@ -61,12 +63,7 @@ public String toString() { public static List emptyParamValuesList() { return new ArrayList(); } - public Expr toAlloy() { - List ll = new ArrayList(paramValues); - Collections.reverse(ll); - ll.add(createVar(name)); - return createArrowExprList(ll); - } + // the following operations are about Alloy expressions that @@ -92,11 +89,30 @@ public static Expr processRef() { $$PROCESSREF$$ . exp2 . exp1 . Root/A/B/v1 */ public static boolean isDashRefProcessRef(Expr e) { + //System.out.println("in isDashRefProcessRef"+ e.toString()); if (isExprJoin(e)) if (isExprVar(getLeft(e))) return sEquals(getLeft(e), processRef()); return false; } + public static Expr getDashRefProcessRefVar(Expr e) { + assert(isDashRefProcessRef(e)); + while (isExprJoin(e)) e = getRight(e); + // might be a $$PROCESSREF$$.a.b.PRIME(e) + return e; + } + public static List getDashRefProcessRefParamValues(Expr e) { + assert(isDashRefProcessRef(e)); + List plist = new ArrayList(); + // strip off $$PROCESSREF$$ + Expr f = getRight(e); + while (isExprJoin(f)) { + //System.out.println(f.toString()); + plist.add(getLeft(f)); + f = getRight(f); + } + return plist; + } /* can only be used in an action exp2. exp1. Root/A/B/v1 or diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 486ed0090..027916768 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -24,7 +24,9 @@ public class DashStrings { public static String utilBufferName = "util/buffer"; public static String sigName = "sig"; public static String predName = "pred"; + public static String factName = "fact"; + // used for printing: parts of Dash syntax // must be in sync with Dash-cup-symbols.txt public static String stateName = "state"; @@ -35,8 +37,10 @@ public class DashStrings { public static String envName = "env"; public static String bufName = "buf"; - public static String initName = "init"; - public static String invariantName = "inv"; + // init is a reserved word in Electrum + public static String initName = "initial"; + public static String electrumInitName = "init"; + public static String invName = "inv"; public static String actionName = "action"; public static String conditionName = "condition"; @@ -120,4 +124,8 @@ public static enum DefKind { public static boolean hasPrime(String s) { return (s.substring(s.length()-1, s.length()).equals(PRIME)); } + public static String removePrime(String s) { + if (hasPrime(s)) return s.substring(0, s.length()-1); + else return s; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java new file mode 100644 index 000000000..1d0e64f40 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -0,0 +1,65 @@ + package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +//import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddInit { + + // -------------------------------------------------------------------------------------- + /* + TODO add here + */ + public static void addInit(DashModule d) { + + List prs = d.getAllParams(); + List body = new ArrayList(); + + // even if these are empty we need this predicate to exist + for (Expr i: d.getInits()) + // these may have the use of parameters in them + body.add(translateExpr(i,d)); + + // it was really tricky to get these types/lists right + // so don't try to combine these steps + + Expr e; + if (!prs.isEmpty()) + e = createAll( + // might need to add "p" to the front of these + paramDecls(prs), + createAndFromList(body)); + else e = createAndFromList(body); + body = new ArrayList(); + body.add(e); + // init is a reserved word in Electrum + if (DashOptions.isElectrum) { + d.alloyString += d.addPredSimple(DashStrings.electrumInitName, new ArrayList(), body); + } else { + d.alloyString += d.addPredSimple(DashStrings.initName, curNextParamsDecls(prs),body); + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java new file mode 100644 index 000000000..3a9279aa1 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java @@ -0,0 +1,69 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; + + + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +//import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +//import static ca.uwaterloo.watform.core.DashFQN.*; + + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddInv { + + // -------------------------------------------------------------------------------------- + /* + TODO add here + */ + public static void addInv(DashModule d) { + + List prs = d.getAllParams(); + List body = new ArrayList(); + + // since this is a fact, we don't need it if there are no invariants + if (!d.getInvs().isEmpty()) { + for (Expr i: d.getInvs()) + // these may have the use of parameters in them + body.add(translateExpr(i,d)); + + // it was really tricky to get these types/lists right + // so don't try to combine these steps + + Expr e; + if (!prs.isEmpty()) + e = createAll( + // might need to add "p" to the front of these + paramDecls(prs), + createAndFromList(body)); + else e = createAndFromList(body); + List decls = new ArrayList(); + decls.add(curDecl()); + if (!DashOptions.isElectrum) { + body = new ArrayList(); + body.add(createAll(decls,e)); + } + d.alloyString += d.addFactSimple(DashStrings.invName, body); + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 39a45c0e6..390d05ab2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -84,7 +84,7 @@ public static void addSnapshotSignature(DashModule d){ // } // and have to deal with this case in translation to Alloy List allvfqnsNoParamsArrowTyp = allvfqns.stream() - .filter(i -> d.getVarParams(i).size() == 0 && isExprArrow(d.getVarType(i))) + .filter(i -> Common.isWeirdOne(i,d)) .collect(Collectors.toList()); if (!allvfqnsNoParamsArrowTyp.isEmpty()) { decls = new ArrayList(); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java index 4ae8533dd..68753998d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -75,7 +75,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { // p3 -> p2 -> p1 -> src in s'.confVar(i) // src does not have to be a basic state - body.add(createIn(d.getTransSrc(tfqn).toAlloy(),nextConf(prs.size()))); + body.add(createIn(translateDashRef(d.getTransSrc(tfqn)),nextConf(prs.size()))); // primed guard condition is true // TODO @@ -88,7 +88,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { List nonO = d.nonOrthogonalScopesOf(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(nonO,i).stream() - .map(x -> x.toAlloy()) + .map(x -> translateDashRef(x)) .collect(Collectors.toList()); // o1: forall i. not(t1_nonOrthScopei in scopesi) for (Expr x: u) orth1.add(createNot(createIn(x,scopeVar(i)))); @@ -101,7 +101,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { List orth2 = new ArrayList(); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(nonO,i).stream() - .map(x -> x.toAlloy()) + .map(x -> translateDashRef(x)) .collect(Collectors.toList()); // o2: forall i. not(t1_nonOrthScopei in scopesi + s'.scopesUsedi) for (Expr x: u) orth1.add(createNot(createIn(x,createUnion(curScopesUsed(i), scopeVar(i))))); @@ -118,7 +118,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { ev1 = createFalse(); } else { ev1 = createIn( - ev.toAlloy(), + translateDashRef(ev), createUnion( createIntersect( curEvents(ev.getParamValues().size()), @@ -127,7 +127,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { } // ev2: t1_on in s.eventsi + genEventsi ev2 = createIn( - ev.toAlloy(), + translateDashRef(ev), createUnion( curEvents(ev.getParamValues().size()), genEventVar(ev.getParamValues().size()))); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 732fcbb9d..44ccbed92 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -82,10 +82,10 @@ public static void addTransPost(DashModule d, String tfqn) { List exited = d.exited(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List ent = DashRef.hasNumParams(entered,i).stream() - .map(x -> x.toAlloy()) + .map(x -> translateDashRef(x)) .collect(Collectors.toList()); List exi = DashRef.hasNumParams(exited,i).stream() - .map(x -> x.toAlloy()) + .map(x -> translateDashRef(x)) .collect(Collectors.toList()); Expr e = curConf(i); if (!exi.isEmpty()) e = createDiff(e,createDiffList(exi)); @@ -96,13 +96,16 @@ public static void addTransPost(DashModule d, String tfqn) { List sU = d.scopesUsed(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(sU,i).stream() - .map(x -> x.toAlloy()) + .map(x -> translateDashRef(x)) .collect(Collectors.toList()); Expr e = curScopesUsed(i); if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); e = createEquals(nextScopesUsed(i),e); } + if (d.getTransDo(tfqn) != null) + body.add(translateExpr(d.getTransDo(tfqn),d)); + DashRef ev = d.getTransSend(tfqn); Expr rhs, rhs1, q; @@ -113,7 +116,7 @@ public static void addTransPost(DashModule d, String tfqn) { Expr c1; for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { - if (ev != null && ev.getParamValues().size() == i) rhs = ev.toAlloy(); + if (ev != null && ev.getParamValues().size() == i) rhs = translateDashRef(ev); else rhs = createNone(); case1.add(createEquals( createIntersect(nextEvents(i),allInternalEventsVar()), @@ -130,7 +133,7 @@ public static void addTransPost(DashModule d, String tfqn) { for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { q = createIntersect(allInternalEventsVar(), curEvents(i)); - if (ev != null && ev.getParamValues().size() == i) rhs = createUnion(ev.toAlloy(), q); + if (ev != null && ev.getParamValues().size() == i) rhs = createUnion(translateDashRef(ev), q); else rhs = q; case2.add(createEquals( createIntersect(nextEvents(i),allInternalEventsVar()), @@ -148,7 +151,7 @@ public static void addTransPost(DashModule d, String tfqn) { Expr c3; for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { - if (ev != null && ev.getParamValues().size() == i) rhs1 = ev.toAlloy(); + if (ev != null && ev.getParamValues().size() == i) rhs1 = translateDashRef(ev); else rhs1 = createNone(); case3.add(createAnd( createEquals( @@ -170,7 +173,7 @@ public static void addTransPost(DashModule d, String tfqn) { for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) - case4.add(createEquals(nextEvents(i),createUnion(curEvents(i), ev.toAlloy()))); + case4.add(createEquals(nextEvents(i),createUnion(curEvents(i), translateDashRef(ev)))); } } if (case4.isEmpty()) c4 = createTrue(); @@ -209,13 +212,13 @@ private static Expr createTestIfNextStableCall(DashModule d, String tfqn) { for (int i=0; i <= d.getMaxDepthParams(); i++) { //TODO could only have scopesUsedi for i that has scopesUsed List u = DashRef.hasNumParams(sU,i).stream() - .map(x -> x.toAlloy()) + .map(x -> translateDashRef(x)) .collect(Collectors.toList()); if (u.size() == 1) args.add(u.get(0)); else if (u.size() ==0 ) args.add(createNone()); else { DashErrors.createTestIfNextStableCallMultipleScopesAtSameLevel(); return null; } if (d.hasEventsAti(i)) { - if (ev != null && ev.getParamValues().size() == i) args.add(ev.toAlloy()); + if (ev != null && ev.getParamValues().size() == i) args.add(translateDashRef(ev)); else args.add(createNone()); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 6e521993a..9aa3a421e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -53,13 +53,16 @@ public static void addTransPre(DashModule d, String tfqn) { // p3 -> p2 -> p1 -> src in s.confVar(i) // src does not have to be a basic state - body.add(createIn(d.getTransSrc(tfqn).toAlloy(),curConf(prs.size()))); + body.add(createIn(translateDashRef(d.getTransSrc(tfqn)),curConf(prs.size()))); + + if (d.getTransWhen(tfqn) != null) + body.add(translateExpr(d.getTransWhen(tfqn),d)); // has a scope that is orthogonal to any scopes used List nonO = d.nonOrthogonalScopesOf(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(nonO,i).stream() - .map(x -> x.toAlloy()) + .map(x -> translateDashRef(x)) .collect(Collectors.toList()); for (Expr x: u) body.add(createNot(createIn(x,curScopesUsed(i)))); } @@ -70,11 +73,11 @@ public static void addTransPre(DashModule d, String tfqn) { // trig_events_t1 DashRef ev = d.getTransOn(tfqn); int sz = ev.getParamValues().size(); - Expr ifBranch = createIn(ev.toAlloy(), + Expr ifBranch = createIn(translateDashRef(ev), createIntersect( curEvents(sz), allEnvironmentalEventsVar())); - Expr elseBranch = createIn(ev.toAlloy(), curEvents(sz)); + Expr elseBranch = createIn(translateDashRef(ev), curEvents(sz)); body.add(createITE( curStableTrue(), ifBranch, @@ -83,7 +86,7 @@ public static void addTransPre(DashModule d, String tfqn) { } else if (d.getTransOn(tfqn) != null) { DashRef ev = d.getTransOn(tfqn); int sz = ev.getParamValues().size(); - body.add(createIn(ev.toAlloy(),curEvents(sz))); + body.add(createIn(translateDashRef(ev),curEvents(sz))); } /* diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index 793067fd5..dce203d51 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -6,14 +6,16 @@ import java.util.ArrayList; import java.util.Arrays; -import edu.mit.csail.sdg.ast.Decl; -import edu.mit.csail.sdg.ast.ExprVar; -import edu.mit.csail.sdg.ast.Expr; +//import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.*; +import edu.mit.csail.sdg.alloy4.ConstList; import ca.uwaterloo.watform.core.DashOptions; import ca.uwaterloo.watform.core.DashStrings; import ca.uwaterloo.watform.core.DashUtilFcns; import ca.uwaterloo.watform.core.DashRef; +import ca.uwaterloo.watform.core.DashErrors; // shortens the code to import these statically import static ca.uwaterloo.watform.core.DashFQN.*; @@ -211,7 +213,149 @@ public static Expr paramsToXArrow(List prs, String x) { return e; } + public static Expr translateDashRef(DashRef e) { + List ll = new ArrayList(e.getParamValues()); + Collections.reverse(ll); + ll.add(createVar(translateFQN(e.getName()))); + return createArrowExprList(ll); + } + + //TODO better name! + public static boolean isWeirdOne(String vfqn, DashModule d) { + return d.getVarParams(vfqn).size() == 0 && isExprArrow(d.getVarType(vfqn)); + } + public static Expr translateExpr(Expr exp, DashModule d) { + // special case for Variables.v1 if v1 has no params and has an + // arrow type and isElectrum + //System.out.println(exp); + if (DashRef.isDashRefProcessRef(exp)) { + // these remove $$PROCESSID$$ + Expr var = DashRef.getDashRefProcessRefVar(exp); + // have to translate paramvalues + // may be empty + List paramValuesList = + DashRef.getDashRefProcessRefParamValues(exp).stream() + .map(i -> translateExpr(i,d)) + .collect(Collectors.toList()); + + //common subexpressions + Boolean hasPrime = DashStrings.hasPrime(getVarName((ExprVar) var)); + Boolean isWeirdOne = isWeirdOne(DashStrings.removePrime(getVarName((ExprVar) var)),d); + Expr voutNotPrime = createVar(translateFQN(DashStrings.removePrime(getVarName((ExprVar) var)))); + Expr voutMayHavePrime; + if (!hasPrime) voutMayHavePrime = voutNotPrime; + else voutMayHavePrime = + createVar(translateFQN(DashStrings.removePrime(getVarName((ExprVar) var)))+DashStrings.PRIME); + + //System.out.println(paramValuesList); + if (DashOptions.isElectrum) { + // already has prime or not + if (isWeirdOne) + return createJoin(createVar(DashStrings.variablesName), voutMayHavePrime); + else { + paramValuesList.add(voutMayHavePrime); + return createJoinList(paramValuesList); + } + } else { + if (hasPrime) paramValuesList.add(nextJoinExpr(voutNotPrime)); + else paramValuesList.add(curJoinExpr(voutNotPrime)); + return createJoinList(paramValuesList); + } + + } else if (isExprVar(exp)) { + return exp; + + } else if (isExprBinary(exp)) { + return ((ExprBinary) exp).op.make( + exp.pos, + exp.closingBracket, + translateExpr(getLeft(exp),d), + translateExpr(getRight(exp),d)); + + } else if (isExprBadJoin(exp)) { + return ExprBadJoin.make( + exp.pos, + exp.closingBracket, + translateExpr(getLeft(exp),d), + translateExpr(getRight(exp),d)); + + } else if (exp instanceof ExprCall) { + return ExprCall.make( + exp.pos, + exp.closingBracket, + ((ExprCall) exp).fun, + ((ExprCall) exp).args.stream() + .map(i -> translateExpr(i,d)) + .collect(Collectors.toList()), + ((ExprCall) exp).extraWeight); + + } else if (exp instanceof ExprChoice){ + //TODO: check into this cast + // not sure why is it necessary + ConstList x = (ConstList) ((ExprChoice) exp).choices.stream() + .map(i -> translateExpr(i,d)) + .collect(Collectors.toList()); + return ExprChoice.make( + false, + exp.pos, + x, + ((ExprChoice) exp).reasons); + + } else if (exp instanceof ExprITE){ + return ExprITE.make( + exp.pos, + translateExpr(getCond(exp),d), + translateExpr(getLeft(exp),d), + translateExpr(getRight(exp),d)); + } else if (exp instanceof ExprList){ + return ExprList.make( + exp.pos, + exp.closingBracket, + ((ExprList) exp).op, + ((ExprList) exp).args.stream() + .map(i -> translateExpr(i,d)) + .collect(Collectors.toList())); + + } else if (exp instanceof ExprUnary){ + return ((ExprUnary) exp).op.make( + exp.pos, + translateExpr(((ExprUnary) exp).sub,d)); + + } else if (exp instanceof ExprLet){ + //TODO rule out var name + return ExprLet.make( + exp.pos, + ((ExprLet) exp).var, + translateExpr(((ExprLet) exp).expr,d), + translateExpr(((ExprLet) exp).sub,d)); + + } else if (exp instanceof ExprQt){ + + // have to translate the expressions in the decls too + List decls = ((ExprQt) exp).decls.stream() + .map(i -> new Decl( + i.isPrivate, + i.disjoint, + i.disjoint2, + i.isVar, + i.names, + translateExpr(i.expr, d))) + .collect(Collectors.toList()); + return ((ExprQt) exp).op.make( + exp.pos, + exp.closingBracket, + decls, + translateExpr(((ExprQt) exp).sub,d)); + + } else if (exp instanceof ExprConstant){ + return exp; + + } else { + DashErrors.UnsupportedExpr("translateExpr", exp); + return null; + } + } /* diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index e8619ff80..0e92ba04f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -13,6 +13,8 @@ public static void translate(DashModule d) { assert(d.hasRoot()); // there is a Dash component in this module AddSpaceSignatures.addSpaceSignatures(d); // state, transition, parameter, buffer space AddSnapshotSignature.addSnapshotSignature(d); + AddInit.addInit(d); + AddInv.addInv(d); for (String tfqn: d.getAllTransNames()) { AddTransPre.addTransPre(d,tfqn); AddTransPost.addTransPost(d,tfqn); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 4901a08d0..34338973b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -300,12 +300,24 @@ public String addPredSimple(String name, List decls, List eList) { * * Alloy: void addFact(Pos pos, String name, Expr value) */ - /* - public void addFactSimple(String name, List eList) { - Expr body = createAnd(eList); - alloy.addFact(Pos.UNKNOWN,name,body); + + public String addFactSimple(String name, List eList) { + Expr body = ExprHelper.createAndFromList(eList); + addFact(Pos.UNKNOWN,name,body); + String s = new String(); + s += DashStrings.factName + " " + name + "{"; + StringJoiner j = new StringJoiner(", "); + s += tab; + StringJoiner sj = new StringJoiner("\n" + tab); + for (Expr e: eList) { + ExprToString eToString = new ExprToString(false); + sj.add(eToString.toString(e)); + } + s += sj.toString() + "\n"; + s+= "}\n\n"; + return s; } - */ + // Helper method to change "{path/label}" to "label" private String cleanLabel(String label) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 6d9668eed..e376130fa 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -178,10 +178,12 @@ public String toStringAlloy() { // skip Dash stuff for (int i = 0; i <= rootEndLine - rootStartLine+1; i++) br.readLine(); + // print the translated Dash + s += alloyString; // add the rest of the lines String rr; while ((rr = br.readLine()) != null) s += rr + "\n"; - s += alloyString; + } else { // just put all the lines in the string because there is no Dash part BufferedReader br = new BufferedReader(new FileReader(getFilePath())); @@ -307,6 +309,12 @@ public DashRef getTransDest(String tfqn) { public DashRef getTransOn(String tfqn) { return transTable.getOn(tfqn); } + public Expr getTransDo(String tfqn) { + return transTable.getDo(tfqn); + } + public Expr getTransWhen(String tfqn) { + return transTable.getWhen(tfqn); + } public DashRef getTransSend(String tfqn) { return transTable.getSend(tfqn); } @@ -335,6 +343,12 @@ public List getTransParams(String t) { return transTable.getParams(t); } + public List getInits() { + return stateTable.getInits(); + } + public List getInvs() { + return stateTable.getInvs(); + } // stuff about both states and trans public DashRef getScope(String tfqn) { DashRef src = getTransSrc(tfqn); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 5aa837756..73d45e4b9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -33,6 +33,8 @@ public class StateTable { private HashMap table; private boolean isResolved; private String root; + private List inits = new ArrayList(); + private List invs = new ArrayList(); private String space = " "; @@ -155,12 +157,7 @@ public Boolean attributesSame(DashStrings.StateKind k, String prm, List immChildren.equals(iChildren)); } */ - public void setInits(List elist) { - inits = elist; - } - public void setInvs(List elist) { - invs = elist; - } + } @@ -223,7 +220,12 @@ public boolean add( else { table.put(fqn, new StateElement(k,prm, prms,d,p,iChildren, invL, initL, actL, condL)); return true; } //System.out.println("adding to State table: "+fqn+space+prm + space + prms+space+d+space+p+iChildren); } - + public void addInit(Expr exp) { + inits.add(exp); + } + public void addInv(Expr exp) { + invs.add(exp); + } public boolean containsKey(String s) { return table.containsKey(s); } @@ -254,7 +256,9 @@ public boolean isDefault(String s) { return (table.get(s).def == DefKind.DEFAULT); else { DashErrors.stateDoesNotExist("isDefault",s); return false; } } - + public List getAllStateNames() { + return new ArrayList(table.keySet()); + } public String getParam(String s) { if (table.containsKey(s)) return table.get(s).param; @@ -386,17 +390,19 @@ public List getAllParams() { public void resolve(String root, VarTable vt) { // resolve inits and invariants for (String sfqn: table.keySet()) { - table.get(sfqn) - .setInits(table.get(sfqn).origInits.stream() + inits.addAll( + table.get(sfqn).origInits.stream() .map(i -> vt.resolveExpr("init", i.getInit(), getRegion(sfqn), + getAllStateNames(), sfqn, getParams(sfqn))) .collect(Collectors.toList())); - table.get(sfqn) - .setInvs(table.get(sfqn).origInvariants.stream() + invs.addAll( + table.get(sfqn).origInvariants.stream() .map(i -> vt.resolveExpr("inv", i.getInv(), getRegion(sfqn), + getAllStateNames(), sfqn, getParams(sfqn))) .collect(Collectors.toList())); @@ -404,7 +410,12 @@ public void resolve(String root, VarTable vt) { isResolved = true; } - + public List getInits() { + return inits; + } + public List getInvs() { + return invs; + } public List getLeafStatesExited(DashRef s) { List r = new ArrayList(); //System.out.println("exiting" + s.toString()); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index acb4353c7..5bb528b25 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -242,6 +242,7 @@ public void resolve(StateTable st, EventTable et, VarTable vt) { .setDo( vt.resolveExprList("when", whenExpList, st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), + st.getAllStateNames(), tfqn, getParams(tfqn))); @@ -269,6 +270,7 @@ public void resolve(StateTable st, EventTable et, VarTable vt) { .setDo( vt.resolveExprList("do", doExpList, st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), + st.getAllStateNames(), tfqn, getParams(tfqn))); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index 22bc1a152..fedee704c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -73,6 +73,7 @@ public List getAllVarNames() { return new ArrayList(table.keySet()); } public List getParams(String vfqn) { + //System.out.println(table); if (table.containsKey(vfqn)) return table.get(vfqn).params; else { DashErrors.varDoesNotExist("getParams", vfqn); return null; } } @@ -97,44 +98,46 @@ public List allVarsOfState(String sfqn) { TODO: buffers, this */ - public Expr resolveExprList(String xType, List expList, List region, String fqn, List params) { + public Expr resolveExprList(String xType, List expList, List region, List allStateNames, String fqn, List params) { if (expList.isEmpty()) return null; else if (expList.size() > 1) { DashErrors.tooMany(xType, fqn); return null; } else { Expr exp = expList.get(0); - - - return resolveExpr(xType, exp, region, fqn, params); + return resolveExpr(xType, exp, region, allStateNames, fqn, params); } } + + //TODO should probably be a visitor using accept methods of Expr // have to recurse through exp types, replace dynamic vars with DashRef and rebuild exp // don't use ExprHelper much here because we want to // as much about the expression as possible - public Expr resolveExpr(String xType, Expr exp, List region, String fqn, List params) { + public Expr resolveExpr(String xType, Expr exp, List region, List allStateNames, String fqn, List params) { + //System.out.println(exp); if (isExprVar(exp) || + isPrimedVar(exp) || //DashRef.isDashRefJoin(exp) || DashRef.isDashRefProcessRef(exp)) // || //DashRef.isDashRefBadJoin(exp)) { - return dashRefVar(xType, exp, region, fqn, params); + return dashRefVar(xType, exp, region, allStateNames, fqn, params); } else if (isExprBinary(exp)) { return ((ExprBinary) exp).op.make( exp.pos, exp.closingBracket, - resolveExpr(xType, getLeft(exp), region, fqn, params), - resolveExpr(xType, getRight(exp), region, fqn, params)); + resolveExpr(xType, getLeft(exp), region, allStateNames,fqn, params), + resolveExpr(xType, getRight(exp), region, allStateNames,fqn, params)); } else if (isExprBadJoin(exp)) { return ExprBadJoin.make( exp.pos, exp.closingBracket, - resolveExpr(xType, getLeft(exp), region, fqn, params), - resolveExpr(xType, getRight(exp), region, fqn, params)); + resolveExpr(xType, getLeft(exp), region, allStateNames,fqn, params), + resolveExpr(xType, getRight(exp), region, allStateNames,fqn, params)); } else if (exp instanceof ExprCall) { return ExprCall.make( @@ -142,7 +145,7 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn, exp.closingBracket, ((ExprCall) exp).fun, ((ExprCall) exp).args.stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, allStateNames,fqn, params)) .collect(Collectors.toList()), ((ExprCall) exp).extraWeight); @@ -150,7 +153,7 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn, //TODO: check into this cast // not sure why is it necessary ConstList x = (ConstList) ((ExprChoice) exp).choices.stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, allStateNames,fqn, params)) .collect(Collectors.toList()); return ExprChoice.make( false, @@ -161,9 +164,9 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn, } else if (exp instanceof ExprITE){ return ExprITE.make( exp.pos, - resolveExpr(xType, getCond(exp), region, fqn, params), - resolveExpr(xType, getLeft(exp), region, fqn, params), - resolveExpr(xType, getRight(exp), region, fqn, params)); + resolveExpr(xType, getCond(exp), region, allStateNames,fqn, params), + resolveExpr(xType, getLeft(exp), region, allStateNames,fqn, params), + resolveExpr(xType, getRight(exp), region, allStateNames,fqn, params)); } else if (exp instanceof ExprList){ return ExprList.make( @@ -171,30 +174,42 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn, exp.closingBracket, ((ExprList) exp).op, ((ExprList) exp).args.stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, allStateNames,fqn, params)) .collect(Collectors.toList()) ); } else if (exp instanceof ExprUnary){ return ((ExprUnary) exp).op.make( exp.pos, - resolveExpr(xType, ((ExprUnary) exp).sub, region, fqn, params)); + resolveExpr(xType, ((ExprUnary) exp).sub, region, allStateNames,fqn, params)); } else if (exp instanceof ExprLet){ //TODO rule out var name return ExprLet.make( exp.pos, ((ExprLet) exp).var, - resolveExpr(xType, ((ExprLet) exp).expr, region, fqn, params), - resolveExpr(xType, ((ExprLet) exp).sub, region, fqn, params)); + resolveExpr(xType, ((ExprLet) exp).expr, region, allStateNames,fqn, params), + resolveExpr(xType, ((ExprLet) exp).sub, region, allStateNames,fqn, params)); } else if (exp instanceof ExprQt){ - //TODO rule out var names + //TODO rule out var names in delcs as dynamic vars later + + // have to convert the expressions in the decls too + List decls = ((ExprQt) exp).decls.stream() + .map(i -> new Decl( + i.isPrivate, + i.disjoint, + i.disjoint2, + i.isVar, + i.names, + resolveExpr(xType, i.expr, region, allStateNames,fqn, params))) + .collect(Collectors.toList()); + return ((ExprQt) exp).op.make( exp.pos, exp.closingBracket, - ((ExprQt) exp).decls, - resolveExpr(xType, ((ExprQt) exp).sub, region, fqn, params)); + decls, + resolveExpr(xType, ((ExprQt) exp).sub, region, allStateNames,fqn, params)); } else if (exp instanceof ExprConstant){ return exp; @@ -206,7 +221,7 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn, } // fqn could be trans or state - private Expr dashRefVar(String xType, Expr exp, List region, String fqn, List params) { + private Expr dashRefVar(String xType, Expr exp, List region, List allStateNames, String fqn, List params) { // Join: b1.a1.var @@ -219,13 +234,18 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, // don't include isDashRefArrow here because that is only possible for // events (which are tuples) not actions + // turns PRIME(v) into v' String v; List paramValues; if (isExprVar(exp)) { v = getVarName((ExprVar) exp); paramValues = new ArrayList(); + } else if (isPrimedVar(exp)) { + v = getVarName((ExprVar) getSub(exp))+PRIME; + paramValues = new ArrayList(); } else { + // name might not be fully resolved v = DashRef.nameOfDashRefExpr(exp); paramValues = DashRef.paramValuesOfDashRefExpr(exp); } @@ -236,16 +256,29 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, vfqn = vfqn.substring(0,vfqn.length()-1); } - + // only place primes can be is in "do" expressions if (!xType.equals("do") && isPrimed) { DashErrors.noPrimedVarsIn(xType, v, fqn); return null; } List matches = new ArrayList(); - for (String s:region) - for (String x:allVarsOfState(s)) { - if (DashFQN.suffix(x,vfqn)) matches.add(x); - } + if (paramValues.isEmpty()) { + // if no param values must be within the region of the same params (could be prefix of params) + for (String s:region) + for (String x:allVarsOfState(s)) { + if (DashFQN.suffix(x,vfqn)) matches.add(x); + } + } else { + // if it has params values, could be suffix of any state + // and later we check it has the right number of params + for (String s:allStateNames) + for (String x:allVarsOfState(s)) { + if (DashFQN.suffix(x,vfqn)) matches.add(x); + } + } + //System.out.println("vfqn: " + vfqn); + //System.out.println("matches: "+ matches); + //System.out.println("region: " + region); if (matches.size() > 1) { DashErrors.ambiguousVar(xType, v, fqn); return null; @@ -268,6 +301,7 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, DashStrings.pName, params.subList(0, getParams(m).size())); if (isPrimed) m = m + PRIME; + //System.out.println("here1" + m); return DashRef.DashRefExpr(m, prmValues); } } else if (getParams(m).size() != paramValues.size()) { @@ -276,11 +310,12 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, return null; } else { if (isPrimed) m = m+PRIME; + //System.out.println("here2" + m); return DashRef.DashRefExpr( m, // have to recursive through expressions in parameters paramValues.stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, allStateNames, fqn, params)) .collect(Collectors.toList())); } } From 44e3d40ad125c2d8bcc89787b8b38fdbcba9a7e6 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sun, 7 May 2023 16:43:51 -0400 Subject: [PATCH 034/129] refactored resolve src/dest/on/send --- .../watform/alloyasthelper/DeclExt.java | 1 + .../ca/uwaterloo/watform/core/DashErrors.java | 2 +- .../uwaterloo/watform/parser/EventTable.java | 93 +++++++ .../uwaterloo/watform/parser/StateTable.java | 67 ++++- .../uwaterloo/watform/parser/TransTable.java | 257 ++++++------------ .../ca/uwaterloo/watform/parser/VarTable.java | 75 +++-- .../alloy/dash/DashWffFailTests.java | 8 +- 7 files changed, 280 insertions(+), 223 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java index 8faf9e19b..23d50fc0d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java @@ -68,4 +68,5 @@ public static DeclExt newSetDeclExt(String v, String typ) { public static DeclExt newVarDeclExt(String v, Expr typ) { return new DeclExt(v , typ, true); } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 254a13831..025e8bd84 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -60,7 +60,7 @@ public static void moreThanOneSrcDest(String x, String n) throws Err { public static void unknownSrcDest(String x, String t, String tfqn) throws Err { throw new ErrorSyntax(unknownSrcDestMsg + "trans "+tfqn+" "+t+" "+x); } - public static String fqnSrcDestMustHaveRightNumberParamsMsg = "A fully qualified state name must have the right number of parameters: "; + public static String fqnSrcDestMustHaveRightNumberParamsMsg = "Incorrect number of parameters: "; public static void fqnSrcDestMustHaveRightNumberParams(String xType, String tfqn) throws Err { throw new ErrorSyntax(fqnSrcDestMustHaveRightNumberParamsMsg + xType + " of transition "+ tfqn ); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index 8cdba9d83..b6b5ef65d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -6,10 +6,16 @@ import java.util.Collections; import java.util.stream.Collectors; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprVar; + import static ca.uwaterloo.watform.core.DashUtilFcns.*; import static ca.uwaterloo.watform.core.DashStrings.*; import ca.uwaterloo.watform.core.DashErrors; import ca.uwaterloo.watform.core.DashFQN; +import ca.uwaterloo.watform.core.DashRef; + +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; public class EventTable { @@ -93,6 +99,9 @@ public List getAllEnvironmentalEvents() { .filter(i -> table.get(i).kind == IntEnvKind.ENV) .collect(Collectors.toList()); } + public List getAllEventNames() { + return new ArrayList(table.keySet()); + } public List getParams(String efqn) { if (table.containsKey(efqn)) return table.get(efqn).params; else { DashErrors.eventTableEventNotFound("getParams", efqn); return null; } @@ -108,4 +117,88 @@ public List allEventsOfState(String sfqn) { .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) .collect(Collectors.toList()); } + + public DashRef resolveEvent(String xType, Expr exp, List region, String tfqn, List tparams, VarTable vt) { + + + // don't include isDashRefJoin here because that is only possible for actions not events + // which are tuples + // but a DashRefProcessRef could be either a value for an action + // or a tuple for an event + // Arrow: b1 -> a1 -> ev + // ProcessRef: A/B/C[a1,b1]/ev which became $$PROCESSREF$$. b1.a1.A/B/C/ev in parsing + // BadJoin: ev[a1,b1] which became b1.a1.ev in parsing + if (ExprHelper.isExprVar(exp) || + //DashRef.isDashRefArrow(exp) || + DashRef.isDashRefProcessRef(exp))// || + //DashRef.isDashRefBadJoin(exp)) + { + String e; + List paramValues; + if (ExprHelper.isExprVar(exp)) { + e = ExprHelper.getVarName((ExprVar) exp); + paramValues = new ArrayList(); + } else { + e = DashRef.nameOfDashRefExpr(exp); + paramValues = + // have to recursive through expressions in parameters + DashRef.paramValuesOfDashRefExpr(exp).stream() + .map(i -> vt.resolveExpr(xType, i, region, tfqn, tparams)) + .collect(Collectors.toList()); + } + String efqn = DashFQN.fqn(e); + + //System.out.println(efqn); + List matches = new ArrayList(); + if (paramValues.isEmpty()) { + // if no param values must be within the region of the same params (could be prefix of params) + for (String s:region) + for (String x:allEventsOfState(s)) { + if (DashFQN.suffix(x,efqn)) matches.add(x); + } + } else { + // if it has params values, could be suffix of any event + // and later we check it has the right number of params + for (String x:getAllEventNames()) { + if (DashFQN.suffix(x,efqn)) matches.add(x); + } + } + + if (matches.size() > 1) { + DashErrors.ambiguousEvent(xType, e, tfqn); + return null; + } else if (matches.isEmpty()) { + DashErrors.unknownEvent(xType, e,tfqn); + return null; + } else { + String m = matches.get(0); + if (paramValues.isEmpty()) { + // must have same param values as trans b/c in same conc region + if (getParams(m).size() > tparams.size()) { + // getRegion did not return things that all + // have the same parameter values + DashErrors.regionMatchesWrongParamNumber(); + return null; + } else { + // but could be a subset of transition param values + List prmValues = + ExprHelper.createVarList(pName, + tparams.subList(0, getParams(m).size() )); + return new DashRef(m, prmValues); + } + } else if (getParams(m).size() != paramValues.size()) { + // came with parameters so must be right number + DashErrors.fqnEventMissingParameters(xType, e, tfqn); + return null; + } else { + return new DashRef(m,paramValues); + } + } + } else { + DashErrors.expNotEvent(xType, tfqn); + return null; + } + + } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 73d45e4b9..5278c8d8c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -394,7 +394,6 @@ public void resolve(String root, VarTable vt) { table.get(sfqn).origInits.stream() .map(i -> vt.resolveExpr("init", i.getInit(), getRegion(sfqn), - getAllStateNames(), sfqn, getParams(sfqn))) .collect(Collectors.toList())); @@ -402,7 +401,6 @@ public void resolve(String root, VarTable vt) { table.get(sfqn).origInvariants.stream() .map(i -> vt.resolveExpr("inv", i.getInv(), getRegion(sfqn), - getAllStateNames(), sfqn, getParams(sfqn))) .collect(Collectors.toList())); @@ -410,6 +408,71 @@ public void resolve(String root, VarTable vt) { isResolved = true; } + /* + * this fcn figures out the src/dest of a transition + * from its context + * if it has no src/dest, the parent state is used + * if it is already FQN, it is returned directly + * Otherwise, it looks at all uniquely named states up to an ancestor conc state + * Requires state table to have been built already + */ + + // tfqn is needed for error messages + + public DashRef resolveSrcDest(String xType, DashRef x, String tfqn, List tparams, VarTable vt) { + + //System.out.println("Looking for: " + x); + String sfqn = DashFQN.fqn(x.getName()); + String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); + // param values might be empty + List paramValues = x.getParamValues().stream() + .map(i -> vt.resolveExpr("from", i, getRegion(parentFQN), tfqn, tparams)) + .collect(Collectors.toList()); + + List matches = new ArrayList(); + if (paramValues.isEmpty()) { + // if no param values must be within the region of the same params (could be prefix of params) + for (String s:getRegion(parentFQN)) + if (DashFQN.suffix(s,sfqn)) matches.add(s); + } else { + // if it has params values, could be suffix of any event + // and later we check it has the right number of params + for (String s:getAllStateNames()) + if (DashFQN.suffix(s,sfqn)) matches.add(s); + } + + if (matches.size() > 1) { + DashErrors.ambiguousSrcDest(xType, tfqn); + return null; + } else if (matches.isEmpty()) { + DashErrors.unknownSrcDest(x.getName(),xType,tfqn); + return null; + } else { + String m = matches.get(0); + if (paramValues.isEmpty()) { + // must have same param values as trans b/c in same conc region + if (getParams(m).size() > tparams.size()) { + // getRegion did not return things that all + // have the same parameter values + DashErrors.regionMatchesWrongParamNumber(); + return null; + } else { + // but could be a subset of transition param values + List prmValues = + ExprHelper.createVarList(pName, + tparams.subList(0, getParams(m).size() )); + return new DashRef(m, prmValues); + } + } else if (getParams(m).size() != paramValues.size()) { + // came with parameters so must be right number + DashErrors.fqnSrcDestMustHaveRightNumberParams(xType, tfqn); + return null; + } else { + return new DashRef(m,paramValues); + } + } + } + public List getInits() { return inits; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 5bb528b25..0b4d159e7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -46,8 +46,8 @@ public class TransElement { // calculated when resolved public DashRef src; public DashRef dest; - public Expr when; // just one? - public DashRef on; + public Expr when; // expr + public DashRef on; // event public Expr act; public DashRef send; @@ -218,137 +218,119 @@ public void resolve(StateTable st, EventTable et, VarTable vt) { if (getAllTransNames().isEmpty()) DashErrors.noTrans(); for (String tfqn: table.keySet()) { //String tfqn = DashFQN.fqn(sfqn,t.name); - + String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); // determining the src state List fList = table.get(tfqn).fromList.stream() .map(p -> (p.src)) .collect(Collectors.toList()); - table.get(tfqn).setSrc(determineSrcDest("from", fList, st, tfqn)); + + if (fList.size() > 1) DashErrors.tooMany("from", tfqn); + else if (fList.isEmpty()) + // can be a loop on root + table.get(tfqn) + .setSrc(new DashRef(parentFQN, ExprHelper.createVarList(DashStrings.pName,getParams(tfqn)))); + else + table.get(tfqn) + .setSrc( + st.resolveSrcDest("from", + fList.get(0), + tfqn, + getParams(tfqn), + vt)); // determining the dest state List gList = table.get(tfqn).gotoList.stream() .map(p -> (p.dest)) .collect(Collectors.toList()); - table.get(tfqn).setDest(determineSrcDest("goto", gList, st, tfqn)); - - // determining the when - List whenExpList = - table.get(tfqn).whenList.stream() - .map(p -> (p.getWhen())) - .collect(Collectors.toList()); - table.get(tfqn) - .setDo( - vt.resolveExprList("when", whenExpList, - st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), - st.getAllStateNames(), - tfqn, - getParams(tfqn))); - - // determining the on + if (gList.size() > 1) DashErrors.tooMany("goto", tfqn); + else if (gList.isEmpty()) + // can be a loop on root + table.get(tfqn) + .setDest(new DashRef(parentFQN, ExprHelper.createVarList(DashStrings.pName,getParams(tfqn)))); + else + table.get(tfqn) + .setDest( + st.resolveSrcDest("goto", + gList.get(0), + tfqn, + getParams(tfqn), + vt)); + + // determining the on (event) List onExpList = table.get(tfqn).onList.stream() .map(p -> (p.getExp())) .collect(Collectors.toList()); - table.get(tfqn).setOn(determineEvent("on", onExpList,st, et, tfqn)); + if (onExpList.size() > 1) DashErrors.tooMany("on", tfqn); + else if (!onExpList.isEmpty()) { + table.get(tfqn) + .setOn( + et.resolveEvent("on", + onExpList.get(0), + st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), + tfqn, + getParams(tfqn), + vt)); + } // determining the send List sendExpList = table.get(tfqn).sendList.stream() .map(p -> (p.getExp())) .collect(Collectors.toList()); - table.get(tfqn).setSend(determineEvent("send", sendExpList,st, et, tfqn)); + if (sendExpList.size() > 1) DashErrors.tooMany("send", tfqn); + else if (!sendExpList.isEmpty()) { + table.get(tfqn) + .setSend( + et.resolveEvent("send", + sendExpList.get(0), + st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), + tfqn, + getParams(tfqn), + vt)); + } + + // determining the when (expr) + List whenExpList = + table.get(tfqn).whenList.stream() + .map(p -> (p.getWhen())) + .collect(Collectors.toList()); + if (whenExpList.size() > 1) DashErrors.tooMany("when", tfqn); + else if (!whenExpList.isEmpty()) { + table.get(tfqn) + .setWhen( + vt.resolveExpr("when", + whenExpList.get(0), + st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), + tfqn, + getParams(tfqn))); + } // determining the do List doExpList = table.get(tfqn).doList.stream() .map(p -> (p.getDo())) .collect(Collectors.toList()); - table.get(tfqn) - .setDo( - vt.resolveExprList("do", doExpList, - st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), - st.getAllStateNames(), - tfqn, - getParams(tfqn))); - + if (doExpList.size() > 1) DashErrors.tooMany("on", tfqn); + else if (!doExpList.isEmpty()) { + table.get(tfqn) + .setDo( + vt.resolveExpr("do", doExpList.get(0), + st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), + tfqn, + getParams(tfqn))); + } + } isResolved = true; } - /* - * this fcn figures out the src/dest of a transition - * from its context - * if it has no src/dest, the parent state is used - * if it is already FQN, it is returned directly - * Otherwise, it looks at all uniquely named states up to an ancestor conc state - * Requires state table to have been built already - */ - - // tfqn is needed for error messages - - public DashRef determineSrcDest(String xType, List ll, StateTable st, String tfqn) { - - // parent state of this transition - String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); - if (ll.size() > 1) { - DashErrors.tooMany(xType, tfqn); - return null; - } else if (ll.isEmpty()) - // can be a loop on root - return new DashRef(parentFQN, ExprHelper.createVarList(DashStrings.pName,st.getParams(parentFQN))); - else { - // if has slashes, turn to "-" - DashRef x = ll.get(0); - //System.out.println("Looking for: " + x); - String n = DashFQN.fqn(x.getName()); - if (DashFQN.isFQN(n)) { - // number of params provided must match number of params needed - //System.out.println(x.getParamValues().size()); - //System.out.println(st.getParams(x.getName()).size()); - if (x.getParamValues().size() != st.getParams(n).size()) { - DashErrors.fqnSrcDestMustHaveRightNumberParams(xType,tfqn); - return null; - } - if (!st.containsKey(n)) DashErrors.unknownSrcDest(x.getName(),xType,tfqn); - return x; - } else { - // not fully qualified - // shouldn't have params in DashRef - // Root could be here but won't have params - if (!x.getParamValues().isEmpty()) { - DashErrors.srcDestCantHaveParam(xType,tfqn); - return null; - } - // Root ends up here - List matches = new ArrayList(); - //String a = st.getClosestConcAnces(parentFQN); - //System.out.println("getClosestConcAnces: "+a); - //List b = st.getAllNonConcStatesWithinThisState(a); - //System.out.println("getAllNonConcStatesWithinThisState "+b); - for (String s:st.getRegion(parentFQN)) { - //System.out.println(s + " " + n); - if (DashFQN.suffix(s,n)) matches.add(s); - } - //System.out.println("matches: " + matches); - if (matches.size() > 1) { - DashErrors.ambiguousSrcDest(xType, tfqn); - return null; - } else if (matches.isEmpty()) { - //DashUtilFcns.myprint(st.toString()); - DashErrors.unknownSrcDest(x.getName(),xType,tfqn); - return null; - } else { - String m = matches.get(0); - //System.out.println(m); - // must have same param values as trans b/c in same conc region - return new DashRef(m, ExprHelper.createVarList(DashStrings.pName, st.getParams(m))); - } - } - } - } + + + // [n1,n2,...] /*private List paramVars(List names) { @@ -357,79 +339,6 @@ public DashRef determineSrcDest(String xType, List ll, StateTable st, return o; }*/ - private DashRef determineEvent(String xType, List expList, StateTable st, EventTable et, String tfqn) { - if (expList.isEmpty()) return null; - else if (expList.size() > 1) { - DashErrors.tooMany(xType, tfqn); - return null; - } else { - Expr exp = expList.get(0); - // don't include isDashRefJoin here because that is only possible for actions not events - // which are tuples - // but a DashRefProcessRef could be either a value for an action - // or a tuple for an event - // Arrow: b1 -> a1 -> ev - // ProcessRef: A/B/C[a1,b1]/ev which became $$PROCESSREF$$. b1.a1.A/B/C/ev in parsing - // BadJoin: ev[a1,b1] which became b1.a1.ev in parsing - if (ExprHelper.isExprVar(exp) || - //DashRef.isDashRefArrow(exp) || - DashRef.isDashRefProcessRef(exp))// || - //DashRef.isDashRefBadJoin(exp)) - { - String e; - List paramValues; - if (ExprHelper.isExprVar(exp)) { - e = ExprHelper.getVarName((ExprVar) exp); - paramValues = new ArrayList(); - } else { - e = DashRef.nameOfDashRefExpr(exp); - paramValues = DashRef.paramValuesOfDashRefExpr(exp); - } - String efqn = DashFQN.fqn(e); - String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); - //System.out.println(efqn); - List matches = new ArrayList(); - for (String s:st.getRegion(parentFQN)) - for (String x:et.allEventsOfState(s)) { - //System.out.println(x); - if (DashFQN.suffix(x,efqn)) matches.add(x); - } - if (matches.size() > 1) { - DashErrors.ambiguousEvent(xType, e, tfqn); - return null; - } else if (matches.isEmpty()) { - DashErrors.unknownEvent(xType, e,tfqn); - return null; - } else { - String m = matches.get(0); - if (paramValues.isEmpty()) { - // must have same param values as trans b/c in same conc region - if (et.getParams(m).size() > getParams(tfqn).size()) { - // getRegion did not return things that all - // have the same parameter values - DashErrors.regionMatchesWrongParamNumber(); - return null; - } else { - // but could be a subset of transition param values - List prmValues = - ExprHelper.createVarList(DashStrings.pName, - getParams(tfqn).subList(0, et.getParams(m).size() )); - return new DashRef(m, prmValues); - } - } else if (et.getParams(m).size() != paramValues.size()) { - // came with parameters so must be right number - DashErrors.fqnEventMissingParameters(xType, e, tfqn); - return null; - } else { - return new DashRef(efqn, paramValues); - } - } - } else { - DashErrors.expNotEvent(xType, tfqn); - return null; - } - } - } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index fedee704c..1fc103878 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -72,6 +72,14 @@ public void resolveAllVarTable() { public List getAllVarNames() { return new ArrayList(table.keySet()); } + public List allVarsOfState(String sfqn) { + // return all events declared in this state + // will have the sfqn as a prefix + return table.keySet().stream() + // prefix of vfqn are state names + .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) + .collect(Collectors.toList()); + } public List getParams(String vfqn) { //System.out.println(table); if (table.containsKey(vfqn)) return table.get(vfqn).params; @@ -82,14 +90,7 @@ public Expr getType(String vfqn) { else { DashErrors.varDoesNotExist("getType", vfqn); return null; } } - public List allVarsOfState(String sfqn) { - // return all events declared in this state - // will have the sfqn as a prefix - return table.keySet().stream() - // prefix of vfqn are state names - .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) - .collect(Collectors.toList()); - } + /* results in an Expr for the action that has all references to variables as DashRefExpr's @@ -98,16 +99,6 @@ public List allVarsOfState(String sfqn) { TODO: buffers, this */ - public Expr resolveExprList(String xType, List expList, List region, List allStateNames, String fqn, List params) { - if (expList.isEmpty()) return null; - else if (expList.size() > 1) { - DashErrors.tooMany(xType, fqn); - return null; - } else { - Expr exp = expList.get(0); - return resolveExpr(xType, exp, region, allStateNames, fqn, params); - } - } @@ -115,7 +106,7 @@ else if (expList.size() > 1) { // have to recurse through exp types, replace dynamic vars with DashRef and rebuild exp // don't use ExprHelper much here because we want to // as much about the expression as possible - public Expr resolveExpr(String xType, Expr exp, List region, List allStateNames, String fqn, List params) { + public Expr resolveExpr(String xType, Expr exp, List region, String fqn, List params) { //System.out.println(exp); if (isExprVar(exp) || isPrimedVar(exp) || @@ -123,21 +114,21 @@ public Expr resolveExpr(String xType, Expr exp, List region, List region, List resolveExpr(xType, i, region, allStateNames,fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, params)) .collect(Collectors.toList()), ((ExprCall) exp).extraWeight); @@ -153,7 +144,7 @@ public Expr resolveExpr(String xType, Expr exp, List region, List x = (ConstList) ((ExprChoice) exp).choices.stream() - .map(i -> resolveExpr(xType, i, region, allStateNames,fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, params)) .collect(Collectors.toList()); return ExprChoice.make( false, @@ -164,9 +155,9 @@ public Expr resolveExpr(String xType, Expr exp, List region, List region, List resolveExpr(xType, i, region, allStateNames,fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, params)) .collect(Collectors.toList()) ); } else if (exp instanceof ExprUnary){ return ((ExprUnary) exp).op.make( exp.pos, - resolveExpr(xType, ((ExprUnary) exp).sub, region, allStateNames,fqn, params)); + resolveExpr(xType, ((ExprUnary) exp).sub, region, fqn, params)); } else if (exp instanceof ExprLet){ //TODO rule out var name return ExprLet.make( exp.pos, ((ExprLet) exp).var, - resolveExpr(xType, ((ExprLet) exp).expr, region, allStateNames,fqn, params), - resolveExpr(xType, ((ExprLet) exp).sub, region, allStateNames,fqn, params)); + resolveExpr(xType, ((ExprLet) exp).expr, region, fqn, params), + resolveExpr(xType, ((ExprLet) exp).sub, region, fqn, params)); } else if (exp instanceof ExprQt){ //TODO rule out var names in delcs as dynamic vars later @@ -202,14 +193,14 @@ public Expr resolveExpr(String xType, Expr exp, List region, List region, List region, List allStateNames, String fqn, List params) { + private Expr dashRefVar(String xType, Expr exp, List region, String fqn, List params) { // Join: b1.a1.var @@ -269,16 +260,16 @@ private Expr dashRefVar(String xType, Expr exp, List region, List 1) { DashErrors.ambiguousVar(xType, v, fqn); return null; @@ -315,7 +306,7 @@ private Expr dashRefVar(String xType, Expr exp, List region, List resolveExpr(xType, i, region, allStateNames, fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, params)) .collect(Collectors.toList())); } } diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java index cd9b7ca49..748ba57d5 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java @@ -69,7 +69,7 @@ public static Collection fileNameMsg() { {"tooManyDefaultStates1", tooManyDefaultStatesMsg}, {"tooManyDefaultStates2", tooManyDefaultStatesMsg}, {"allConcDefaultStates1",allConcDefaultStatesMsg}, - {"allConcDefaultStates2",allConcDefaultStatesMsg}, + {"allConcDefaultStates2",allConcDefaultStatesMsg}, //11 {"stateNameCantBeFQN1", stateNameCantBeFQNMsg}, {"stateNameCantBeFQN2", stateNameCantBeFQNMsg}, {"dupSiblingNames1", dupSiblingNamesMsg}, @@ -79,12 +79,12 @@ public static Collection fileNameMsg() { {"moreThanOneSrcDest1", tooManyMsg}, {"moreThanOneSrcDest2", tooManyMsg}, // 19 {"moreThanOneSrcDest3", tooManyMsg}, - //{"unknownSrcDest1", unknownSrcDestMsg}, //21 + //{"unknownSrcDest1", unknownSrcDestMsg}, //{"unknownSrcDest2", unknownSrcDestMsg}, //{"unknownSrcDest3", unknownSrcDestMsg}, - {"unknownSrcDest4", unknownSrcDestMsg}, + {"unknownSrcDest4", unknownSrcDestMsg}, //21 {"fqnSrcDestMustHaveRightNumberParams1", fqnSrcDestMustHaveRightNumberParamsMsg}, - {"srcDestCantHaveParam1", srcDestCantHaveParamMsg}, + {"srcDestCantHaveParam1", fqnSrcDestMustHaveRightNumberParamsMsg}, //23 {"ambiguousSrcDest1", ambiguousSrcDestMsg}, {"test11",ambiguousSrcDestMsg} }); From e03cb12cf83473c7415ac367cee54159cdeb5fae Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Mon, 8 May 2023 20:06:03 -0400 Subject: [PATCH 035/129] added support for buffers, thisAID keyword, traces/electrum/tcmc facts --- .../models/util/{ctl.als => tcmc.als} | 2 +- .../util/{ctl_path.als => tcmc_path.als} | 2 +- .../{ctl_subgraph.als => tcmc_subgraph.als} | 2 +- .../util/{ctlfc_path.als => tcmcfc_path.als} | 2 +- ...ctlfc_subgraph.als => tcmcfc_subgraph.als} | 2 +- .../models/util/{ctlfc.als => tmcfc.als} | 2 +- .../parser/Dash-cup-grammar.txt | 24 +- org.alloytools.alloy.dash/parser/Dash.cup | 24 +- .../watform/alloyasthelper/ExprHelper.java | 3 + .../watform/alloyasthelper/ExprToString.java | 6 +- .../watform/ast/DashBufferDecls.java | 13 +- .../ca/uwaterloo/watform/ast/DashState.java | 13 +- .../ca/uwaterloo/watform/core/DashErrors.java | 15 +- .../uwaterloo/watform/core/DashSituation.java | 5 +- .../uwaterloo/watform/core/DashStrings.java | 22 +- .../watform/dashtoalloy/AddElectrumFact.java | 56 +++++ .../watform/dashtoalloy/AddInit.java | 6 +- .../dashtoalloy/AddSnapshotSignature.java | 125 +++++++--- .../dashtoalloy/AddSpaceSignatures.java | 30 ++- .../watform/dashtoalloy/AddTcmcFact.java | 78 +++++++ .../watform/dashtoalloy/AddTracesFact.java | 69 ++++++ .../watform/dashtoalloy/AddTransPost.java | 24 +- .../uwaterloo/watform/dashtoalloy/Common.java | 13 +- .../watform/dashtoalloy/DashToAlloy.java | 8 + .../uwaterloo/watform/parser/BufferTable.java | 64 ------ .../watform/parser/CompModuleHelper.java | 53 ++++- .../uwaterloo/watform/parser/DashModule.java | 31 ++- .../ca/uwaterloo/watform/parser/VarTable.java | 217 ++++++++++++++++-- 28 files changed, 732 insertions(+), 179 deletions(-) rename org.alloytools.alloy.core/src/main/resources/models/util/{ctl.als => tcmc.als} (99%) rename org.alloytools.alloy.core/src/main/resources/models/util/{ctl_path.als => tcmc_path.als} (99%) rename org.alloytools.alloy.core/src/main/resources/models/util/{ctl_subgraph.als => tcmc_subgraph.als} (99%) rename org.alloytools.alloy.core/src/main/resources/models/util/{ctlfc_path.als => tcmcfc_path.als} (99%) rename org.alloytools.alloy.core/src/main/resources/models/util/{ctlfc_subgraph.als => tcmcfc_subgraph.als} (99%) rename org.alloytools.alloy.core/src/main/resources/models/util/{ctlfc.als => tmcfc.als} (99%) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddElectrumFact.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTracesFact.java delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/BufferTable.java diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctl.als b/org.alloytools.alloy.core/src/main/resources/models/util/tcmc.als similarity index 99% rename from org.alloytools.alloy.core/src/main/resources/models/util/ctl.als rename to org.alloytools.alloy.core/src/main/resources/models/util/tcmc.als index 204f642e5..a71feb674 100644 --- a/org.alloytools.alloy.core/src/main/resources/models/util/ctl.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/tcmc.als @@ -27,7 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -module util/ctl[S] +module util/tcmc[S] //********************KRIPKE STRUCTURE DEF*************************// diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctl_path.als b/org.alloytools.alloy.core/src/main/resources/models/util/tcmc_path.als similarity index 99% rename from org.alloytools.alloy.core/src/main/resources/models/util/ctl_path.als rename to org.alloytools.alloy.core/src/main/resources/models/util/tcmc_path.als index dd25ecc2c..025e55491 100755 --- a/org.alloytools.alloy.core/src/main/resources/models/util/ctl_path.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/tcmc_path.als @@ -8,7 +8,7 @@ * https://opensource.org/licenses/BSD-2-Clause. */ -module ctl_path[S] +module tcmc_path[S] // ********** Kripke structure ************************************************* diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctl_subgraph.als b/org.alloytools.alloy.core/src/main/resources/models/util/tcmc_subgraph.als similarity index 99% rename from org.alloytools.alloy.core/src/main/resources/models/util/ctl_subgraph.als rename to org.alloytools.alloy.core/src/main/resources/models/util/tcmc_subgraph.als index 451e4a880..511e7b924 100755 --- a/org.alloytools.alloy.core/src/main/resources/models/util/ctl_subgraph.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/tcmc_subgraph.als @@ -8,7 +8,7 @@ * https://opensource.org/licenses/BSD-2-Clause. */ -module ctl_subgraph[S] +module tcmc_subgraph[S] // ********** Kripke structure ************************************************* diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_path.als b/org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc_path.als similarity index 99% rename from org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_path.als rename to org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc_path.als index 68bcb80d7..70b0dcdf9 100755 --- a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_path.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc_path.als @@ -8,7 +8,7 @@ * https://opensource.org/licenses/BSD-2-Clause. */ -module ctlfc_path[S] +module tcmcfc_path[S] // ********** Kripke structure ************************************************* diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_subgraph.als b/org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc_subgraph.als similarity index 99% rename from org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_subgraph.als rename to org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc_subgraph.als index a26d50f31..c8f03647f 100755 --- a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc_subgraph.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc_subgraph.als @@ -8,7 +8,7 @@ * https://opensource.org/licenses/BSD-2-Clause. */ -module ctlfc_subgraph[S] +module tcmcfc_subgraph[S] // ********** Kripke structure ************************************************* diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc.als b/org.alloytools.alloy.core/src/main/resources/models/util/tmcfc.als similarity index 99% rename from org.alloytools.alloy.core/src/main/resources/models/util/ctlfc.als rename to org.alloytools.alloy.core/src/main/resources/models/util/tmcfc.als index 59967619d..cf9cb250d 100755 --- a/org.alloytools.alloy.core/src/main/resources/models/util/ctlfc.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/tmcfc.als @@ -8,7 +8,7 @@ * https://opensource.org/licenses/BSD-2-Clause. */ -module ctlfc[S] +module tcmcfc[S] // ********** Kripke structure ************************************************* diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt index 4d050f61b..cfd849122 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -196,46 +196,62 @@ StateItem ::= ENV:o Names:n COLON Expr:b StateItem ::= Names:n COLON:o BUF LBRACKET Name:m RBRACKET {: ArrayList ll = new ArrayList(); + Integer startIndex = DashSituation.bufferIndex; for (ExprVar x: n) { ll.add(x.label); // it will do this the same way both passes through parsing DashSituation.bufferElements.add(m.label); DashSituation.bufferNames.add(x.label); + DashSituation.bufferIndex++; } - RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.INT); + // endIndex is inclusive + Integer endIndex = DashSituation.bufferIndex - 1; + RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.INT, startIndex, endIndex); :}; StateItem ::= Names:n COLON:o BUF LBRACKET SIGINT RBRACKET {: ArrayList ll = new ArrayList(); + Integer startIndex = DashSituation.bufferIndex; for (ExprVar x: n) { ll.add(x.label); // it will do this the same way both passes through parsing DashSituation.bufferElements.add(DashStrings.intName); DashSituation.bufferNames.add(x.label); + DashSituation.bufferIndex++; } - RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT); + // endIndex is inclusive + Integer endIndex = DashSituation.bufferIndex - 1; + RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT, startIndex, endIndex); :}; StateItem ::= ENV:o Names:n COLON BUF LBRACKET Name:m RBRACKET {: ArrayList ll = new ArrayList(); + Integer startIndex = DashSituation.bufferIndex; for (ExprVar x: n) { ll.add(x.label); // it will do this the same way both passes through parsing DashSituation.bufferElements.add(m.label); DashSituation.bufferNames.add(x.label); + DashSituation.bufferIndex++; } - RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV); + // endIndex is inclusive + Integer endIndex = DashSituation.bufferIndex - 1; + RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV, startIndex, endIndex); :}; StateItem ::= ENV:o Names:n COLON BUF LBRACKET SIGINT RBRACKET {: ArrayList ll = new ArrayList(); + Integer startIndex = DashSituation.bufferIndex; for (ExprVar x: n) { ll.add(x.label); // it will do this the same way both passes through parsing DashSituation.bufferElements.add(DashStrings.intName); DashSituation.bufferNames.add(x.label); + DashSituation.bufferIndex++; } - RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV); + // endIndex is inclusive + Integer endIndex = DashSituation.bufferIndex - 1; + RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV, startIndex, endIndex); :}; // init diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index 0e7b3693e..2a0e0e09f 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -1450,46 +1450,62 @@ StateItem ::= ENV:o Names:n COLON Expr:b StateItem ::= Names:n COLON:o BUF LBRACKET Name:m RBRACKET {: ArrayList ll = new ArrayList(); + Integer startIndex = DashSituation.bufferIndex; for (ExprVar x: n) { ll.add(x.label); // it will do this the same way both passes through parsing DashSituation.bufferElements.add(m.label); DashSituation.bufferNames.add(x.label); + DashSituation.bufferIndex++; } - RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.INT); + // endIndex is inclusive + Integer endIndex = DashSituation.bufferIndex - 1; + RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.INT, startIndex, endIndex); :}; StateItem ::= Names:n COLON:o BUF LBRACKET SIGINT RBRACKET {: ArrayList ll = new ArrayList(); + Integer startIndex = DashSituation.bufferIndex; for (ExprVar x: n) { ll.add(x.label); // it will do this the same way both passes through parsing DashSituation.bufferElements.add(DashStrings.intName); DashSituation.bufferNames.add(x.label); + DashSituation.bufferIndex++; } - RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT); + // endIndex is inclusive + Integer endIndex = DashSituation.bufferIndex - 1; + RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT, startIndex, endIndex); :}; StateItem ::= ENV:o Names:n COLON BUF LBRACKET Name:m RBRACKET {: ArrayList ll = new ArrayList(); + Integer startIndex = DashSituation.bufferIndex; for (ExprVar x: n) { ll.add(x.label); // it will do this the same way both passes through parsing DashSituation.bufferElements.add(m.label); DashSituation.bufferNames.add(x.label); + DashSituation.bufferIndex++; } - RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV); + // endIndex is inclusive + Integer endIndex = DashSituation.bufferIndex - 1; + RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV, startIndex, endIndex); :}; StateItem ::= ENV:o Names:n COLON BUF LBRACKET SIGINT RBRACKET {: ArrayList ll = new ArrayList(); + Integer startIndex = DashSituation.bufferIndex; for (ExprVar x: n) { ll.add(x.label); // it will do this the same way both passes through parsing DashSituation.bufferElements.add(DashStrings.intName); DashSituation.bufferNames.add(x.label); + DashSituation.bufferIndex++; } - RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV); + // endIndex is inclusive + Integer endIndex = DashSituation.bufferIndex - 1; + RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV, startIndex, endIndex); :}; // init diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index b7e97eaa8..5ca78dd24 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -257,6 +257,9 @@ public static ExprList createOrList(List args) { // put simplifications in here so can replace createOrFromList return (ExprList) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, ExprList.Op.OR, args); } + public static Expr createIff(Expr left, Expr right) { + return (Expr) ExprBinary.Op.IFF.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } public static ExprBinary createArrow(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.ARROW.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index 005a884b6..e65c3e7c5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -127,9 +127,11 @@ else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { out.print("seq "); ExprToOut(expr.right); } - else if (expr.op == ExprBinary.Op.JOIN) + else if (expr.op == ExprBinary.Op.JOIN) { + out.print("("); ExprBinaryJoinToOut(expr); - else if (expr.op == ExprBinary.Op.IMPLIES) { + out.print(")"); + } else if (expr.op == ExprBinary.Op.IMPLIES) { ExprToOut(expr.left); out.print(" => ").print("{ "); ExprToOut(expr.right); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java index f0f12940c..7a2698631 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashBufferDecls.java @@ -17,17 +17,22 @@ public class DashBufferDecls extends Dash { private List names; private String element; private DashStrings.IntEnvKind kind; + private Integer startIndex; + private Integer endIndex; - public DashBufferDecls(Pos pos, List n, String element, DashStrings.IntEnvKind k) { + public DashBufferDecls(Pos pos, List n, String element, DashStrings.IntEnvKind k, int startIndex, int endIndex) { assert (n != null && element != null); this.pos = pos; this.names = n; this.element = element; this.kind = k; + this.startIndex = startIndex; + this.endIndex = endIndex; } public String toString() { + // indices are hidden String s = new String(""); if (kind == DashStrings.IntEnvKind.ENV) { s += DashStrings.envName + " "; @@ -46,4 +51,10 @@ public String getElement() { public DashStrings.IntEnvKind getKind() { return kind; } + public int getStartIndex() { + return startIndex; + } + public int getEndIndex() { + return endIndex; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index 3bf96d1c4..b2bf70275 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -19,7 +19,7 @@ import ca.uwaterloo.watform.parser.TransTable; import ca.uwaterloo.watform.parser.EventTable; import ca.uwaterloo.watform.parser.VarTable; -import ca.uwaterloo.watform.parser.BufferTable; +//import ca.uwaterloo.watform.parser.BufferTable; public class DashState extends Dash { @@ -119,7 +119,7 @@ public static List noSubstates() { * check for errors in the state hierarchy * and put all states in the state table */ - public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, BufferTable bt, List params, List ances) { + public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, List params, List ances) { if (DashFQN.isFQN(name)) DashErrors.stateNameCantBeFQN(pos, name); String sfqn = DashFQN.fqn(ances,name); //System.out.println("Resolving state "+sfqn); @@ -208,7 +208,7 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Bu invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; // add all substates to the table - for (DashState s: substatesList) s.resolve(st, tt, et, vt, bt, newParams, newAnces); + for (DashState s: substatesList) s.resolve(st, tt, et, vt, newParams, newAnces); // make sure defaults are correct // if there's only one child it is automatically the default @@ -284,7 +284,7 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Bu for (String x: v.getNames()) { if (DashFQN.isFQN(x)) DashErrors.varNameCantBeFQN(v.getPos(), x); String xfqn = DashFQN.fqn(sfqn,x); - if (!vt.add(xfqn,k, newParams, t)) DashErrors.duplicateVarName(v.getPos(),x); + if (!vt.addVar(xfqn,k, newParams, t)) DashErrors.duplicateVarName(v.getPos(),x); } } xItems.removeAll(varDeclsList); @@ -301,11 +301,14 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Bu for (DashBufferDecls b:bufferDeclsList) { DashStrings.IntEnvKind k = b.getKind(); String el = b.getElement(); + Integer idx = b.getStartIndex(); for (String x: b.getNames()) { if (DashFQN.isFQN(x)) DashErrors.bufferNameCantBeFQN(b.getPos(), x); String xfqn = DashFQN.fqn(sfqn,x); - if (!bt.add(xfqn,k, newParams, el)) DashErrors.duplicateBufferName(b.getPos(),x); + if (!vt.addBuffer(xfqn,k, newParams, el, idx)) DashErrors.duplicateBufferName(b.getPos(),x); + idx++; } + if (idx != b.getEndIndex()+1) DashErrors.bufferIndexDoesNotMatchBufferNumber(); } xItems.removeAll(bufferDeclsList); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 025e8bd84..c6ed195f2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -148,8 +148,10 @@ public static String fqnVarWrongNumberParameters(String s1, String s2, String s3 throw new ErrorSyntax(fqnVarWrongNumberParametersMsg + s1 + " "+s2 +" "+s3); } - - + public static String cantPrimeAnExternalMsg = "Internal var/buffer cannot be primed: "; + public static String cantPrimeAnExternal(String s1, String s2) { + throw new ErrorSyntax(cantPrimeAnExternalMsg + s1 + " in " + s2); + } @@ -186,6 +188,12 @@ public static void transDoesNotExist(String s1, String n) throws Err { public static void varDoesNotExist(String s1, String n) throws Err { throw new ErrorFatal("for function "+s1+", var "+n+ " does not exist in var table"); } + public static void bufferDoesNotExist(String s1, String n) throws Err { + throw new ErrorFatal("for function "+s1+", buffer "+n+ " does not exist in buffer table"); + } + public static void varBufferDoesNotExist(String s1, String n) throws Err { + throw new ErrorFatal("for function "+s1+", buffer/var "+n+ " does not exist in buffer table"); + } public static void missingExpr(String s) throws Err { throw new ErrorFatal("Missing expr type in "+s); } @@ -236,4 +244,7 @@ public static String UnsupportedExpr(String s1, String s2) { public static String UnsupportedExpr(String s1, Expr e) { throw new ErrorFatal("unsupported expression type in: "+ s1+ " " + e.toString()); } + public static void bufferIndexDoesNotMatchBufferNumber() { + throw new ErrorFatal("bufferIndexDoesNotMatchBufferNumber"); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java index d0cd0fecc..baa5f8a9b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashSituation.java @@ -6,7 +6,7 @@ // everything must be static public class DashSituation { - // we need a little bit of knowledge of the state of the process + // we need a little bit of knowledge of the state of the process because // open statements have to be done before anything else in an // Alloy file, but we don't know how many buffers we have // so we have to run parsing once to count buffers @@ -21,9 +21,10 @@ public class DashSituation { // its a pain to make a pair in Alloy (Pair class is difficult) // or Java where javafx.util.Pair does not seem to be available // for this version of Alloy - // so just keep two lists insync + // so just keep two lists in sync public static List bufferNames = new ArrayList(); public static List bufferElements = new ArrayList(); + public static int bufferIndex = 0; // we will need more here to know the names of the elements // of the buffers for the open statements } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 027916768..0a3a8b4bb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -19,13 +19,17 @@ public class DashStrings { public static String noneName = "none"; public static String intName = "int"; public static String utilBooleanName = "util/boolean"; - public static String utilCTLpathName = "util/ctl_path"; + public static String utilTcmcPathName = "util/tcmc_path"; public static String utilOrderingName = "util/ordering"; public static String utilBufferName = "util/buffer"; public static String sigName = "sig"; public static String predName = "pred"; public static String factName = "fact"; - + public static String orderingFirstName = "first"; + public static String orderingNextName = "next"; + public static String orderingLastName = "last"; + + // used for printing: parts of Dash syntax // must be in sync with Dash-cup-symbols.txt @@ -37,12 +41,13 @@ public class DashStrings { public static String envName = "env"; public static String bufName = "buf"; - // init is a reserved word in Electrum - public static String initName = "initial"; + // init is a reserved word in Dash + public static String initFactName = "initial"; public static String electrumInitName = "init"; public static String invName = "inv"; public static String actionName = "action"; public static String conditionName = "condition"; + public static String initName = "init"; public static String transName = "trans"; public static String fromName = "from"; @@ -61,7 +66,12 @@ public class DashStrings { public static String stableName = "stable"; public static String equalsName = "equals"; public static String isEnabled = "isEnabled"; - + public static String tracesFactName = "traces_fact"; + public static String electrumFactName = "electrum_fact"; + public static String tcmcFactName = "tcmc_fact"; + public static String ksSigmaName = "tcmc/ks_sigma"; + public static String ksS0Name = "tcmc/ks_s0"; + // sig/field names public static String snapshotName = "Snapshot"; public static String confName = "conf"; @@ -90,7 +100,7 @@ public class DashStrings { public static String bufferName = "buffer"; public static String bufferIndexName = "bufIdx"; - + public static String thisName = "this"; public static String tracesName = "traces"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddElectrumFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddElectrumFact.java new file mode 100644 index 000000000..66cbd28b3 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddElectrumFact.java @@ -0,0 +1,56 @@ +/* + Add fact for Electrum +*/ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import static ca.uwaterloo.watform.core.DashStrings.*; +//import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +//import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; +import ca.uwaterloo.watform.alloyasthelper.DeclExt; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddElectrumFact { + + public static void addElectrumFact(DashModule d) { + + /* + fact electrum { + init and always small_step + } + */ + + assert(DashOptions.isElectrum); + List body = new ArrayList(); + + body.add(createVar(initFactName)); + body.add(createAlways(createVar(smallStepName))); + d.alloyString += d.addFactSimple(initFactName, body); + + } +} + + + diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 1d0e64f40..2110e8397 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -1,4 +1,4 @@ - package ca.uwaterloo.watform.dashtoalloy; +package ca.uwaterloo.watform.dashtoalloy; import java.util.Collections; import java.util.stream.Collectors; @@ -57,9 +57,9 @@ public static void addInit(DashModule d) { body.add(e); // init is a reserved word in Electrum if (DashOptions.isElectrum) { - d.alloyString += d.addPredSimple(DashStrings.electrumInitName, new ArrayList(), body); + d.alloyString += d.addPredSimple(DashStrings.initFactName, new ArrayList(), body); } else { - d.alloyString += d.addPredSimple(DashStrings.initName, curNextParamsDecls(prs),body); + d.alloyString += d.addPredSimple(DashStrings.initFactName, curNextParamsDecls(prs),body); } } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 390d05ab2..9a45aeb08 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -34,27 +34,44 @@ public static void addSnapshotSignature(DashModule d){ if (DashOptions.isElectrum) { // if Electrum add var sigs // scopesUsed0, conf0, event0 - + List decls; + d.alloyString += d.addVarSigSimple(scopesUsedName+"0", createVar(stateLabelName)); d.alloyString += d.addVarSigSimple(confName+"0", createVar(stateLabelName)); if (d.hasEvents()) d.alloyString += d.addVarSigSimple(eventsName+"0", createVar(allEventsName)); - List cop; - for (int i = 1; i <= d.getMaxDepthParams(); i++) { - cop = new ArrayList (Collections.nCopies(i+1,createVar(identifierName))); - // scopesUsed 1, etc. - d.alloyString += d.addVarSigSimple( - scopesUsedName+Integer.toString(i), - DashUtilFcns.newListWith(cop, createVar(stateLabelName))); - // conf 1, etc. - d.alloyString += d.addVarSigSimple( - confName+Integer.toString(i), - DashUtilFcns.newListWith(cop, createVar(stateLabelName))); - // event 1, etc. - if (d.hasEvents() & d.hasEventsAti(i)) - d.alloyString += d.addVarSigSimple( - eventsName+Integer.toString(i), - DashUtilFcns.newListWith(cop, createVar(allEventsName))); + + // sig Identifiers { + // conf1: StateLabel, + // scopesUsed1: StateLabel, + // events1: AllEvent, + // conf2: Identifiers -> StateLabel, + // scopesUsed2: Identifers -> StateLabel, + // etc + // } + if (d.getMaxDepthParams() != 0) { + List cop; + decls = new ArrayList(); + for (int i = 1; i <= d.getMaxDepthParams(); i++) { + cop = new ArrayList (Collections.nCopies(i-1,createVar(identifierName))); + // conf 1, etc. + decls.add( + DeclExt.newVarDeclExt( + confName+Integer.toString(i), + createArrowExprList(DashUtilFcns.newListWith(cop, createVar(stateLabelName))))); + // scopesUsed 1, etc. + decls.add( + DeclExt.newVarDeclExt( + scopesUsedName+Integer.toString(i), + createArrowExprList(DashUtilFcns.newListWith(cop, createVar(stateLabelName))))); + if (d.hasEvents() & d.hasEventsAti(i)) + // events 1, etc. + decls.add( + DeclExt.newVarDeclExt( + eventsName+Integer.toString(i), + createArrowExprList(DashUtilFcns.newListWith(cop, createVar(allEventsName))))); + } + d.alloyString += d.addSigWithDeclsSimple(identifierName, decls); } // stable: one boolean; @@ -63,13 +80,15 @@ public static void addSnapshotSignature(DashModule d){ } // add vars and parameter sets -------------------------------------- - List decls; + List allvfqns = d.getAllVarNames(); + List allbfqns = d.getAllBufferNames(); // vfqns with no params and simple type // becomes var sig vfqn in var {} + // no buffers in this case List allvfqnsNoParamsSimpleTyp = allvfqns.stream() - .filter(i -> d.getVarParams(i).size() == 0 && isExprVar(d.getVarType(i))) + .filter(i -> d.getVarBufferParams(i).size() == 0 && isExprVar(d.getVarType(i))) .collect(Collectors.toList()); for (String v: allvfqnsNoParamsSimpleTyp) d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar) d.getVarType(v)) ); @@ -83,6 +102,7 @@ public static void addSnapshotSignature(DashModule d){ // v1: typ1 // } // and have to deal with this case in translation to Alloy + // no buffers in this case because they can be grouped with index List allvfqnsNoParamsArrowTyp = allvfqns.stream() .filter(i -> Common.isWeirdOne(i,d)) .collect(Collectors.toList()); @@ -96,31 +116,69 @@ public static void addSnapshotSignature(DashModule d){ // vfqns with parameters P1, P2, P3 // sig P1 { // var v1: P2 -> P3 -> typ1 + // var buf: P2 -> P3 -> bufindex -> eltype // } // it is enough to look at state parameters to get all parameters List allvfqnsWithThisFirstParam; - + List allbfqnsWithThisFirstParam; + List plist; + for (String prm: d.getAllParams()) { + + // variables with parameters grouped with parameter allvfqnsWithThisFirstParam = allvfqns.stream() // must be at least one parameter - .filter(i -> d.getVarParams(i).size() != 0 && d.getVarParams(i).get(0).equals(prm)) + .filter(i -> d.getVarBufferParams(i).size() != 0 && d.getVarBufferParams(i).get(0).equals(prm)) .collect(Collectors.toList()); // construct decls -- might be none but still have to // create sig for this parameter decls = new ArrayList(); for (String v: allvfqnsWithThisFirstParam) { - if (d.getVarParams(v).size() == 1) { - decls.add(new DeclExt(v, d.getVarType(v))); + if (d.getVarBufferParams(v).size() == 1) { + decls.add(DeclExt.newVarDeclExt(v, d.getVarType(v))); } else { - List plist = createVarList(d.getVarParams(v).subList(1, d.getVarParams(v).size()-1)); + plist = createVarList(d.getVarBufferParams(v).subList(1, d.getVarBufferParams(v).size()-1)); plist.add(d.getVarType(v)); decls.add(DeclExt.newVarDeclExt(translateFQN(v),createArrowExprList(plist))); } } - d.alloyString += d.addSigWithDeclsSimple(prm, decls); + // buffers with parameters grouped with parameter + allbfqnsWithThisFirstParam = allbfqns.stream() + // must be at least one parameter + .filter(i -> d.getVarBufferParams(i).size() != 0 && d.getVarBufferParams(i).get(0).equals(prm)) + .collect(Collectors.toList()); + // construct decls -- might be none but still have to + // create sig for this parameter + for (String b: allbfqnsWithThisFirstParam) { + if (d.getVarBufferParams(b).size() != 1) + plist = createVarList(d.getVarBufferParams(b).subList(1, d.getVarBufferParams(b).size()-1)); + else + plist = new ArrayList(); + plist.add(bufferIndexVar(d.getBufferIndex(b))); + plist.add(createVar(d.getBufferElement(b))); + decls.add(DeclExt.newVarDeclExt(translateFQN(b),createArrowExprList(plist))); + } + d.alloyString += d.addSigExtendsWithDeclsSimple(prm, identifierName, decls); } + + // buffers with no parameters + // grouped in buffer index introduction + // every buffer has a different index + // so just one decl per sig + List allbfqnsWithNoParams = allbfqns.stream() + // must be at least one parameter + .filter(i -> d.getVarBufferParams(i).size() == 0 ) + .collect(Collectors.toList()); + for (String b: allbfqnsWithNoParams) { + decls = new ArrayList(); + decls.add(DeclExt.newVarDeclExt( + translateFQN(b), + createVar(d.getBufferElement(b)))); + d.alloyString += d.addSigWithDeclsSimple( + bufferIndexName + d.getBufferIndex(b), + decls); + } - // add buffers } else { // if traces/tcmc sig Snapshot {} with fields List decls = new ArrayList(); @@ -156,7 +214,7 @@ public static void addSnapshotSignature(DashModule d){ // add vars List typlist; for (String vfqn: d.getAllVarNames()) { - typlist = createVarList(d.getVarParams(vfqn)); // could be empty + typlist = createVarList(d.getVarBufferParams(vfqn)); // could be empty typlist.add(d.getVarType(vfqn)); if (typlist.size() > 1 ) decls.add((Decl) new DeclExt( @@ -168,6 +226,19 @@ public static void addSnapshotSignature(DashModule d){ typlist.get(0))); } // add buffers + for (String bfqn: d.getAllBufferNames()) { + typlist = createVarList(d.getVarBufferParams(bfqn)); // could be empty + typlist.add(bufferIndexVar(d.getBufferIndex(bfqn))); + typlist.add(createVar(d.getBufferElement(bfqn))); + if (typlist.size() > 1 ) + decls.add((Decl) new DeclExt( + translateFQN(bfqn), + createArrowExprList(typlist))); + else + decls.add((Decl) new DeclExt( + translateFQN(bfqn), + typlist.get(0))); + } d.alloyString += d.addSigWithDeclsSimple( snapshotName, decls); } d.alloyString += "\n"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index 1dc9d0ad2..3baba637d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -54,12 +54,16 @@ public static void addSpaceSignatures(DashModule d) { //d.alloyString += "\n"; // abstract sig Identifiers {} if this model has parametrized components - if (d.getMaxDepthParams() != 0) { - d.alloyString += d.addAbstractSigSimple(DashStrings.identifierName); - for (String s: d.getAllParams()) - d.alloyString += d.addExtendsSigSimple(s, DashStrings.identifierName); - d.alloyString += "\n"; - } + // if not Electrum + // o/w conf1, etc have to be fields in sig Identifiers + // and this functionality is within AddSnapshotSignatures + if (!DashOptions.isElectrum) + if (d.getMaxDepthParams() != 0) { + d.alloyString += d.addAbstractSigSimple(DashStrings.identifierName); + for (String s: d.getAllParams()) + d.alloyString += d.addExtendsSigSimple(s, DashStrings.identifierName); + d.alloyString += "\n"; + } // events ---------------------- if (d.hasEvents()) { @@ -79,14 +83,16 @@ public static void addSpaceSignatures(DashModule d) { d.alloyString += "\n"; } - - /* - if (d.hasBuffers()) { - for (String i: d.getBufferIndices()) { - addSigSimple( i); + // abstract sig BufIdx {} if this model has buffers + // if not Electrum + // o/w buffers have to be fields in sig BufIdx + // and this functionality is within AddSnapshotSignatures + if (!DashOptions.isElectrum && d.hasBuffers()) { + for (int i: d.getBufferIndices()) { + d.alloyString += d.addSigSimple(DashStrings.bufferIndexName + i); } } - */ + } private static void recurseCreateStateSpaceSigs(DashModule d, String parent) { for (String child: d.getImmChildren(parent)) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java new file mode 100644 index 000000000..7228a8027 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java @@ -0,0 +1,78 @@ +/* + Add fact for tcmc +*/ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import static ca.uwaterloo.watform.core.DashStrings.*; +//import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +//import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; +import ca.uwaterloo.watform.alloyasthelper.DeclExt; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddTcmcFact { + + public static void addTcmcFact(DashModule d) { + + /* + open util/tcmc[Snapshot] as snapshot + + fact tcmc { + // ksS0 satisfies init (initial) constraints + (all s: one Snapshot | { s in tcmc/ks_s0 } <=> init[s]) + // ksSigma satisfies small_step predicate + (all s,s_next: one Snapshot | ({ s -> s_next } in tcmc/ks_sigma) <=> small_step[s, s_next ]) + } + + */ + + assert(DashOptions.isTcmc); + List body = new ArrayList(); + + List decls = new ArrayList(); + decls.add(curDecl()); + + List args = new ArrayList(); + args.add(curVar()); + body.add( + createAll( + decls, + createIff( + createIn(curVar(), createVar(ksS0Name)), + createPredCall(initFactName,args)))); + + body.add( + createAll( + curNextDecls(), + createIff( + createIn( + createArrow(curVar(), nextVar()), + createVar(ksSigmaName)), + createPredCall(smallStepName, curNextVars())))); + + d.alloyString += d.addFactSimple(tcmcFactName, body); + + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTracesFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTracesFact.java new file mode 100644 index 000000000..c5378de68 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTracesFact.java @@ -0,0 +1,69 @@ +/* + Add fact for traces +*/ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import static ca.uwaterloo.watform.core.DashStrings.*; +//import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +//import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; +import ca.uwaterloo.watform.alloyasthelper.DeclExt; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddTracesFact { + + public static void addTracesFact(DashModule d) { + + /* + open util/traces[Snapshot] as snapshot + + fact traces { + init[snapshot/first] and + (all s: one (Snapshot - snapshot/last) | small_step[s, s. (snapshot/next)] ) + } + */ + + assert(DashOptions.isTraces); + List body = new ArrayList(); + + Expr snapShotFirst = createVar(snapshotName + "/" + orderingFirstName); + Expr snapShotLast = createVar(snapshotName + "/" + orderingLastName); + Expr snapShotNext = createVar(snapshotName + "/" + orderingNextName); + + List args = new ArrayList(); + args.add(snapShotFirst); + body.add(createPredCall(initFactName,args)); + + args = new ArrayList(); + args.add(curVar()); + args.add(curJoinExpr(snapShotNext)); + List decls = new ArrayList(); + decls.add((Decl) new DeclExt(curName, createOne(createDiff(createVar(snapshotName), snapShotLast)))); + body.add(createAll(decls,createPredCall(smallStepName,args))); + + d.alloyString += d.addFactSimple(tracesFactName, body); + + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 44ccbed92..f052959f7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -72,6 +72,7 @@ public class AddTransPost { } */ + // TODO for Electrum! public static void addTransPost(DashModule d, String tfqn) { String tout = translateFQN(tfqn); List prs = d.getTransParams(tfqn); @@ -103,6 +104,7 @@ public static void addTransPost(DashModule d, String tfqn) { e = createEquals(nextScopesUsed(i),e); } + // action_t1[s,s'] if (d.getTransDo(tfqn) != null) body.add(translateExpr(d.getTransDo(tfqn),d)); @@ -179,6 +181,18 @@ public static void addTransPost(DashModule d, String tfqn) { if (case4.isEmpty()) c4 = createTrue(); else c4 = createAndFromList(case4); + // env_vars_unchanged[s,s'] + + List allVarBuffers = d.getAllVarNames(); + allVarBuffers.addAll(d.getAllBufferNames()); + // might just return true if allVarBuffers is empty + Expr envNoChange = createAndFromList(allVarBuffers.stream() + .filter(i -> !d.isInternal(i)) + .map(i -> createVarDoesNotChange(d, i)) + .collect(Collectors.toList())); + Expr stableFalseAndEnvNoChange = createAnd(nextStableFalse(), envNoChange); + + if (d.hasConcurrency()) body.add( createITE(createTestIfNextStableCall(d, tfqn), @@ -188,7 +202,7 @@ public static void addTransPost(DashModule d, String tfqn) { c1, c2)), createAnd( - nextStableFalse(), + stableFalseAndEnvNoChange, createITE(curStableTrue(), c3, c4)))); @@ -199,6 +213,14 @@ public static void addTransPost(DashModule d, String tfqn) { d.alloyString += d.addPredSimple(tout+postName,curNextParamsDecls(prs),body); } + public static Expr createVarDoesNotChange(DashModule d, String x) { + return createAll( + paramDecls(d.getVarBufferParams(x)), + createEquals( + createJoinList(DashUtilFcns.newListWith(curParamVars(d.getVarBufferParams(x)),createVar(x))), + createJoinList(DashUtilFcns.newListWith(nextParamVars(d.getVarBufferParams(x)),createVar(x))))); + } + // pred call: testIfNextStable[s,s',scope1, scope2, ... , send1, send2, ...] // where scopei, evi is "none" if this transition's scope and send event private static Expr createTestIfNextStableCall(DashModule d, String tfqn) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index dce203d51..f4e47fe82 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -114,6 +114,13 @@ public static List curParamVars(List params) { o.addAll(paramVars(params)); return o; } + // [s', p1,p2,...] + public static List nextParamVars(List params) { + List o = new ArrayList(); + o.add(nextVar()); + o.addAll(paramVars(params)); + return o; + } // [s,s', p1,p2,...] public static List curNextParamVars(List params) { List o = new ArrayList(curNextVars()); @@ -222,7 +229,7 @@ public static Expr translateDashRef(DashRef e) { //TODO better name! public static boolean isWeirdOne(String vfqn, DashModule d) { - return d.getVarParams(vfqn).size() == 0 && isExprArrow(d.getVarType(vfqn)); + return d.getVarBufferParams(vfqn).size() == 0 && isExprArrow(d.getVarType(vfqn)); } public static Expr translateExpr(Expr exp, DashModule d) { // special case for Variables.v1 if v1 has no params and has an @@ -357,7 +364,9 @@ public static Expr translateExpr(Expr exp, DashModule d) { } } - + public static Expr bufferIndexVar(int i) { + return createVar(DashStrings.bufferIndexName + i); + } /* public static Expr predJoinCurParams(String name, List prs) { //p2.p1.p0.s.name diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 0e92ba04f..7c1fad848 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -6,6 +6,7 @@ package ca.uwaterloo.watform.dashtoalloy; import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.core.DashOptions; public class DashToAlloy { @@ -25,6 +26,13 @@ public static void translate(DashModule d) { if (d.hasConcurrency()) AddTestIfNextStable.addTestIfNextStable(d); AddSmallStep.addSmallStep(d); + + if (DashOptions.isTraces) + AddTracesFact.addTracesFact(d); + else if (DashOptions.isTcmc) + AddTcmcFact.addTcmcFact(d); + else if (DashOptions.isElectrum) + AddElectrumFact.addElectrumFact(d); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/BufferTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/BufferTable.java deleted file mode 100644 index 181c3d08b..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/BufferTable.java +++ /dev/null @@ -1,64 +0,0 @@ -package ca.uwaterloo.watform.parser; - -import java.util.List; -import java.util.ArrayList; -import java.util.HashMap; - -import edu.mit.csail.sdg.ast.Expr; - - -import static ca.uwaterloo.watform.core.DashUtilFcns.*; -import static ca.uwaterloo.watform.core.DashStrings.*; - -public class BufferTable { - - // stores Buffer Decls in a HashMap based on the buffer FQN - - private HashMap table; - - - public class BufferElement { - private IntEnvKind kind; - private List params; - private String element; - - public BufferElement( - IntEnvKind k, - List prms, - String e) { - assert(prms != null); - this.kind = k; - this.params = prms; - this.element = e; - } - public String toString() { - String s = new String(); - s += "kind: "+kind+"\n"; - s += "params: "+ NoneStringIfNeeded(params) +"\n"; - s += "element: "+element.toString() + "\n"; - return s; - } - } - - public BufferTable() { - this.table = new HashMap(); - - } - public String toString() { - String s = new String("BUFFER TABLE\n"); - for (String k:table.keySet()) { - s += " ----- \n"; - s += k + "\n"; - s += table.get(k).toString(); - } - return s; - } - public Boolean add(String vfqn, IntEnvKind k, List prms, String el) { - assert(prms!=null); - if (table.containsKey(vfqn)) return false; - else { table.put(vfqn, new BufferElement(k,prms, el)); return true; } - } - public void resolveAllBufferTable() { - // TODO - } -} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 34338973b..60795115b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -82,6 +82,7 @@ public String addSigSimple(String name) { null); String s = new String(); s += DashStrings.sigName + space + name + " {}\n"; + //System.out.println(s); return s; } @@ -103,6 +104,7 @@ public String addAbstractSigSimple(String name) { String s = new String(); s += DashStrings.abstractName + space + DashStrings.sigName + space; s += name + " {}\n"; + //System.out.println(s); return s; } @@ -125,6 +127,7 @@ public String addAbstractExtendsSigSimple(String extension, String extended) { s += extension + space + DashStrings.extendsName + space; s += extended; s += " {} \n"; + //System.out.println(s); return s; } @@ -147,6 +150,7 @@ public String addExtendsSigSimple(String extension, String extended) { s += extension + space + DashStrings.extendsName + space; s += extended; s += " {} \n"; + //System.out.println(s); return s; } @@ -169,6 +173,7 @@ public String addOneExtendsSigSimple(String extension, String extended) { s += extension + space + DashStrings.extendsName + space; s += extended; s += " {} \n"; + //System.out.println(s); return s; } public String addSigWithDeclsSimple(String name, List decls) { @@ -176,8 +181,31 @@ public String addSigWithDeclsSimple(String name, List decls) { addSig( Pos.UNKNOWN, name, + null, + null, + decls, + null, null, null, + null, + null, + null, + null); + String s = DashStrings.sigName + space + name; + s += " {\n"; + StringJoiner j = new StringJoiner(",\n"); + decls.forEach(i -> j.add(tab + i.toString())); + s += j.toString() + "\n}\n"; + //System.out.println(s); + return s; + } + public String addSigExtendsWithDeclsSimple(String extension, String extended, List decls) { + // sig name { decls } + addSig( + Pos.UNKNOWN, + extension, + ExprHelper.createVar(DashStrings.extendsName), + ExprHelper.createExprVarList(new ArrayList(Arrays.asList(extended))), decls, null, null, @@ -186,10 +214,14 @@ public String addSigWithDeclsSimple(String name, List decls) { null, null, null); - String s = DashStrings.sigName + space + name + space + "{\n"; + String s = DashStrings.sigName + space; + s += extension + space + DashStrings.extendsName + space; + s += extended; + s += " {\n"; StringJoiner j = new StringJoiner(",\n"); decls.forEach(i -> j.add(tab + i.toString())); s += j.toString() + "\n}\n"; + //System.out.println(s); return s; } public String addOneSigWithDeclsSimple(String name, List decls) { @@ -211,6 +243,7 @@ public String addOneSigWithDeclsSimple(String name, List decls) { StringJoiner j = new StringJoiner(",\n"); decls.forEach(i -> j.add(tab + i.toString())); s += j.toString() + "\n}\n"; + //System.out.println(s); return s; } public String addVarSigSimple(String name, ExprVar typ) { @@ -233,6 +266,7 @@ public String addVarSigSimple(String name, ExprVar typ) { s += name + space + DashStrings.inName + space; s += typ.toString(); s += " { }\n"; + //System.out.println(s); return s; } @@ -256,6 +290,7 @@ public String addVarSigSimple(String name, List typ) { s += name + space + DashStrings.inName + space; s += typ.toString(); s += " { }\n"; + //System.out.println(s); return s; } @@ -272,10 +307,13 @@ public String addPredSimple(String name, List decls, List eList) { Expr body = ExprHelper.createAndFromList(eList); addFunc(Pos.UNKNOWN, Pos.UNKNOWN, ExprHelper.createVar(name), null, decls, null, body); String s = new String(); - s += DashStrings.predName + " " + name + "["; - StringJoiner j = new StringJoiner(", "); - decls.forEach(i -> j.add(i.toString())); - s += j.toString() + "] {\n"; + s += DashStrings.predName + " " + name; + if (!decls.isEmpty()) { + s += " ["; + StringJoiner j = new StringJoiner(", "); + decls.forEach(i -> j.add(i.toString())); + s += j.toString() + "]"; + } // we have to use our own printer // rather than expr.toString() // because that fcn does not include brackets @@ -284,7 +322,8 @@ public String addPredSimple(String name, List decls, List eList) { // later we could do something nicer for pred calls // but remember the predicate call to testIfNextStable is nested // inside an ITE - s += tab; + + s += " {\n "+tab; StringJoiner sj = new StringJoiner("\n" + tab); for (Expr e: eList) { ExprToString eToString = new ExprToString(false); @@ -305,7 +344,7 @@ public String addFactSimple(String name, List eList) { Expr body = ExprHelper.createAndFromList(eList); addFact(Pos.UNKNOWN,name,body); String s = new String(); - s += DashStrings.factName + " " + name + "{"; + s += DashStrings.factName + " " + name + " {"; StringJoiner j = new StringJoiner(", "); s += tab; StringJoiner sj = new StringJoiner("\n" + tab); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index e376130fa..467c0d79a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -38,7 +38,6 @@ public class DashModule extends CompModuleHelper { public Integer rootEndLine = null; // derived during resolveAllDash phase - private int numBuffers = 0; private int maxDepthParams = 0; private boolean[] transAtThisParamDepth; private SymbolTable symbolTable; @@ -46,7 +45,6 @@ public class DashModule extends CompModuleHelper { private TransTable transTable = new TransTable(); private EventTable eventTable = new EventTable(); private VarTable varTable = new VarTable(); - private BufferTable bufferTable = new BufferTable(); // once created and parsed, the following are // the phases of a DashModule @@ -98,6 +96,7 @@ private void initializeDashModule() { // including recursively for open stmts // make sure we only do import on second parsing pass DashSituation.haveCountedBuffers = false; + DashSituation.bufferIndex = 0; } } @@ -204,7 +203,7 @@ public void importModules(List bufElements, List bufNames) { String noAlias = null; booleanOpen = this.addOpenSimple(DashStrings.utilBooleanName, null, noAlias); if (DashOptions.isTcmc) - opens += this.addOpenSimple(DashStrings.utilCTLpathName, Arrays.asList(DashStrings.snapshotName), noAlias); + opens += this.addOpenSimple(DashStrings.utilTcmcPathName, Arrays.asList(DashStrings.snapshotName), noAlias); else if (DashOptions.isTraces) opens += this.addOpenSimple(DashStrings.utilOrderingName, Arrays.asList(DashStrings.snapshotName),DashStrings.snapshotName); // add the open statements for the buffers @@ -231,8 +230,11 @@ public String getRootName() { if (root != null) return root.name; else { DashErrors.toAlloyNoDash(); return null; } } - public int getNumBuffers() { - return numBuffers; + public List getBufferIndices() { + return varTable.getBufferIndices(); + } + public boolean hasBuffers() { + return (!getBufferIndices().isEmpty()); } public boolean hasInternalEvents() { return eventTable.hasInternalEvents(); @@ -328,11 +330,11 @@ public boolean isEnvironmentalEvent(String efqn) { public List getAllVarNames() { return varTable.getAllVarNames(); } - public List getVarParams(String vfqn) { + public List getVarBufferParams(String vfqn) { return varTable.getParams(vfqn); } public Expr getVarType(String vfqn) { - return varTable.getType(vfqn); + return varTable.getVarType(vfqn); } public Boolean transAtThisParamDepth(int i) { if (i > maxDepthParams) { DashErrors.tooHighParamDepth(); return null; } @@ -349,6 +351,19 @@ public List getInits() { public List getInvs() { return stateTable.getInvs(); } + public List getAllBufferNames() { + return varTable.getAllBufferNames(); + } + public int getBufferIndex(String bfqn) { + return varTable.getBufferIndex(bfqn); + } + public String getBufferElement(String bfqn) { + return varTable.getBufferElement(bfqn); + } + public boolean isInternal(String vfqn) { + // works for buffers also + return varTable.isInternal(vfqn); + } // stuff about both states and trans public DashRef getScope(String tfqn) { DashRef src = getTransSrc(tfqn); @@ -500,7 +515,7 @@ public void resolveAllDash(A4Reporter rep) { root = roots.get(0); // passed with empty set of params, empty set of ancestors stateTable.setRoot(root.name); - root.resolve(stateTable,transTable, eventTable, varTable, bufferTable, new ArrayList(),new ArrayList()); + root.resolve(stateTable,transTable, eventTable, varTable, new ArrayList(),new ArrayList()); // have to do states first so siblings of trans parent state // are in place to search for src/dest // root.resolveTransTable(stateTable,transTable); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index 1fc103878..44a1bbd5c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -20,10 +20,15 @@ public class VarTable { - // stores Var Decls in a HashMap based on the event FQN + // stores Var, Buffer Decls in a HashMap based on the event FQN - private HashMap table; + private HashMap varTable; + private HashMap bufferTable; + public VarTable() { + this.varTable = new HashMap(); + this.bufferTable = new HashMap(); + } public class VarElement { private IntEnvKind kind; @@ -48,48 +53,127 @@ public String toString() { } } - public VarTable() { - this.table = new HashMap(); - } public String toString() { String s = new String("VAR TABLE\n"); - for (String k:table.keySet()) { + for (String k:varTable.keySet()) { s += " ----- \n"; s += k + "\n"; - s += table.get(k).toString(); + s += varTable.get(k).toString(); + } + s += "\nBUFFER TABLE\n"; + for (String k:bufferTable.keySet()) { + s += " ----- \n"; + s += k + "\n"; + s += bufferTable.get(k).toString(); } return s; } - public Boolean add(String vfqn, IntEnvKind k, List prms, Expr t) { + public Boolean addVar(String vfqn, IntEnvKind k, List prms, Expr t) { assert(prms!=null); - if (table.containsKey(vfqn)) return false; + if (varTable.containsKey(vfqn)) return false; if (hasPrime(vfqn)) { DashErrors.nameShouldNotBePrimed(vfqn); return false; } - else { table.put(vfqn, new VarElement(k,prms, t)); return true; } + else { varTable.put(vfqn, new VarElement(k,prms, t)); return true; } } public void resolveAllVarTable() { // TODO } public List getAllVarNames() { - return new ArrayList(table.keySet()); + return new ArrayList(varTable.keySet()); } - public List allVarsOfState(String sfqn) { + public List getAllNames() { + // vars plus buffers + List x = getAllVarNames(); + x.addAll(getAllBufferNames()); + return x; + } + public List getVarsOfState(String sfqn) { // return all events declared in this state // will have the sfqn as a prefix - return table.keySet().stream() + return varTable.keySet().stream() // prefix of vfqn are state names .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) .collect(Collectors.toList()); } - public List getParams(String vfqn) { - //System.out.println(table); - if (table.containsKey(vfqn)) return table.get(vfqn).params; - else { DashErrors.varDoesNotExist("getParams", vfqn); return null; } + public List getBuffersOfState(String sfqn) { + // return all events declared in this state + // will have the sfqn as a prefix + return bufferTable.keySet().stream() + // prefix of vfqn are state names + .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) + .collect(Collectors.toList()); } - public Expr getType(String vfqn) { - if (table.containsKey(vfqn)) return table.get(vfqn).typ; + public List getNamesOfState(String sfqn) { + List x = getVarsOfState(sfqn); + x.addAll(getBuffersOfState(sfqn)); + return x; + } + // same function for buffers and variables + public List getParams(String fqn) { + if (bufferTable.containsKey(fqn)) return bufferTable.get(fqn).params; + if (varTable.containsKey(fqn)) return varTable.get(fqn).params; + else { DashErrors.varBufferDoesNotExist("getParams", fqn); return null; } + } + public Expr getVarType(String vfqn) { + if (varTable.containsKey(vfqn)) return varTable.get(vfqn).typ; else { DashErrors.varDoesNotExist("getType", vfqn); return null; } } + // same function for buffers and variables + public boolean isInternal(String fqn) { + if (bufferTable.containsKey(fqn)) return (bufferTable.get(fqn).kind == IntEnvKind.INT); + if (varTable.containsKey(fqn)) return (varTable.get(fqn).kind == IntEnvKind.INT); + else { DashErrors.varBufferDoesNotExist("isInternal", fqn); return false; } + } + + public class BufferElement { + private IntEnvKind kind; + private List params; + private String element; + private Integer index; + public BufferElement( + IntEnvKind k, + List prms, + String e, + Integer idx) { + assert(prms != null); + this.kind = k; + this.params = prms; + this.element = e; + this.index = idx; + } + public String toString() { + String s = new String(); + s += "kind: "+kind+"\n"; + s += "params: "+ NoneStringIfNeeded(params) +"\n"; + s += "element: "+element.toString() + "\n"; + s += "index:" + index; + return s; + } + } + + public List getAllBufferNames() { + return new ArrayList(bufferTable.keySet()); + } + public List getBufferIndices() { + List k = new ArrayList(); + for (int i=0; i< getAllBufferNames().size();i++) k.add(i); + return k; + } + + public int getBufferIndex(String bfqn) { + if (bufferTable.containsKey(bfqn)) return bufferTable.get(bfqn).index; + else { DashErrors.bufferDoesNotExist("getIndex", bfqn); return -1; } + } + public String getBufferElement(String bfqn) { + if (bufferTable.containsKey(bfqn)) return bufferTable.get(bfqn).element; + else { DashErrors.bufferDoesNotExist("getElement", bfqn); return null; } + } + + public Boolean addBuffer(String vfqn, IntEnvKind k, List prms, String el, Integer idx) { + assert(prms!=null); + if (bufferTable.containsKey(vfqn)) return false; + else { bufferTable.put(vfqn, new BufferElement(k,prms, el, idx)); return true; } + } /* @@ -97,7 +181,6 @@ public Expr getType(String vfqn) { fqn is a parameter to determine transition parameters and for error messages used for when and do parts of a transitions - TODO: buffers, this */ @@ -231,6 +314,17 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, List paramValues; if (isExprVar(exp)) { v = getVarName((ExprVar) exp); + if (v.startsWith(thisName)) { + // thisAID gets replaced with pAID as a normal variable + // not a processref + String suffix = v.substring(thisName.length(),v.length()); + String match = ""; + for (String x:params) + if (x.equals(suffix)) + match = x; + if (!match.isEmpty()) + return createVar(pName+match); + } paramValues = new ArrayList(); } else if (isPrimedVar(exp)) { v = getVarName((ExprVar) getSub(exp))+PRIME; @@ -244,7 +338,8 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, Boolean isPrimed = false; if (hasPrime(v)) { isPrimed = true; - vfqn = vfqn.substring(0,vfqn.length()-1); + vfqn = removePrime(vfqn); // vfqn.substring(0,vfqn.length()-1); + } // only place primes can be is in "do" expressions @@ -256,13 +351,15 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, if (paramValues.isEmpty()) { // if no param values must be within the region of the same params (could be prefix of params) for (String s:region) - for (String x:allVarsOfState(s)) { + // buffers and vars + for (String x:getNamesOfState(s)) { if (DashFQN.suffix(x,vfqn)) matches.add(x); } } else { // if it has params values, could be suffix of any var // and later we check it has the right number of params - for (String x:getAllVarNames()) { + // vars and buffers + for (String x:getAllNames()) { if (DashFQN.suffix(x,vfqn)) matches.add(x); } } @@ -300,6 +397,10 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, DashErrors.fqnVarWrongNumberParameters(xType, v, fqn); return null; } else { + if (isPrimed && !isInternal(m)) { + DashErrors.cantPrimeAnExternal(v, fqn); + return null; + } if (isPrimed) m = m+PRIME; //System.out.println("here2" + m); return DashRef.DashRefExpr( @@ -311,4 +412,74 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, } } } + + // must be done after resolve + // might be primed or unprimed + public List collectDashRefs(Expr exp) { + if (DashRef.isDashRefProcessRef(exp)) { + List x = new ArrayList(); + x.add(exp); + return x; + } else if (isExprBinary(exp)) { + List x = new ArrayList(collectDashRefs(getLeft(exp))); + x.addAll(collectDashRefs(getRight(exp))); + return x; + } else if (isExprBadJoin(exp)) { + List x = new ArrayList(collectDashRefs(getLeft(exp))); + x.addAll(collectDashRefs(getRight(exp))); + return x; + } else if (exp instanceof ExprCall) { + List x = new ArrayList(); + for (Expr e: ((ExprCall) exp).args) x.addAll(collectDashRefs(e)); + return x; + } else if (exp instanceof ExprChoice){ + List x = new ArrayList(); + for (Expr e: ((ExprChoice) exp).choices) x.addAll(collectDashRefs(e)); + return x; + } else if (exp instanceof ExprITE){ + List x = new ArrayList(collectDashRefs(getCond(exp))); + x.addAll(collectDashRefs(getLeft(exp))); + x.addAll(collectDashRefs(getRight(exp))); + return x; + } else if (exp instanceof ExprList){ + List x = new ArrayList(); + for (Expr e: ((ExprCall) exp).args) x.addAll(collectDashRefs(e)); + return x; + } else if (exp instanceof ExprUnary){ + return collectDashRefs(((ExprUnary) exp).sub); + } else if (exp instanceof ExprLet){ + List x = new ArrayList(collectDashRefs(((ExprLet) exp).expr)); + x.addAll(collectDashRefs(((ExprLet) exp).sub)); + return x; + } else if (exp instanceof ExprQt){ + List x = new ArrayList(); + List ll = ((ExprQt) exp).decls.stream() + .map(i -> i.expr) + .collect(Collectors.toList()); + for (Expr e: ll) x.addAll(collectDashRefs(e)); + x.addAll(collectDashRefs(((ExprQt) exp).sub)); + return x; + } else if (exp instanceof ExprConstant){ + return new ArrayList(); + } else { + DashErrors.UnsupportedExpr("collectDashRefs", ""); + return null; + } + } + + // returns the primed variables in an exp (but w/o the primes) + public List primedDashRefs(Expr exp) { + List drs = collectDashRefs(exp); + List o = new ArrayList(); + String v; + List paramValues; + for (Expr e: drs) { + v = DashRef.nameOfDashRefExpr(e); + paramValues = DashRef.paramValuesOfDashRefExpr(e); + if (hasPrime(v)) { + o.add(DashRef.DashRefExpr(removePrime(v), paramValues)); + } + } + return o; + } } \ No newline at end of file From 6109c2112402ba1948ceb2565014764cbbcc6053 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Mon, 8 May 2023 20:26:07 -0400 Subject: [PATCH 036/129] fixed printing of declarations to use our ExprToString --- .../watform/alloyasthelper/DeclExt.java | 4 ++- .../watform/alloyasthelper/ExprToString.java | 29 +++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java index 23d50fc0d..f8ba40f21 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java @@ -13,6 +13,7 @@ import ca.uwaterloo.watform.core.DashErrors; import ca.uwaterloo.watform.alloyasthelper.ExprHelper; +import ca.uwaterloo.watform.alloyasthelper.ExprToString; public class DeclExt extends Decl { @@ -44,7 +45,8 @@ public String toString() { names.forEach(n -> sj.add(n.toString())); x += sj.toString(); x += " : "; - x += expr.toString(); + ExprToString eToString = new ExprToString(false); + x += eToString.toString(expr); return x; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index e65c3e7c5..631924eab 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -124,8 +124,9 @@ private void ExprBinaryToOut(ExprBinary expr) { out.print(s); } else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { - out.print("seq "); + out.print("(seq "); ExprToOut(expr.right); + out.print(")"); } else if (expr.op == ExprBinary.Op.JOIN) { out.print("("); @@ -295,60 +296,70 @@ private void ExprQtToOut(ExprQt expr) { private void ExprUnaryToOut(ExprUnary expr) { switch (expr.op) { - /* + // this ops don't print properly with toString + // e.g. set X becomes set of X case SOMEOF : out.print("some ("); ExprToOut(expr.sub); out.print(")"); + break; case LONEOF : out.print("lone ("); + ExprToOut(expr.sub); out.print(")"); + break; case ONEOF : out.print("one ("); + ExprToOut(expr.sub); out.print(")"); + break; case SETOF : out.print("set ("); + ExprToOut(expr.sub); out.print(")"); + break; case EXACTLYOF : out.print("exactly ("); + ExprToOut(expr.sub); out.print(")"); + break; case CAST2INT : out.print("int["); ExprToOut(expr.sub); out.print(']'); - + break; case CAST2SIGINT : out.print("Int["); ExprToOut(expr.sub); out.print(']'); - + break; case PRIME : //TODO: perhaps this one should not exist? //TODO: other temporal formulas that should not exist? out.print('('); ExprToOut(expr.sub); out.print(")'"); - + break; case RCLOSURE : out.print("* ("); ExprToOut(expr.sub); out.print(")"); - + break; case TRANSPOSE : out.print("~ ("); ExprToOut(expr.sub); out.print(")"); - + break; case CLOSURE : out.print("^ ("); ExprToOut(expr.sub); out.print(")"); - + break; case NOT : out.print("! {"); ExprToOut(expr.sub); out.print("}"); - */ + break; case NOOP : ExprToOut(expr.sub); break; From 08e9d1198c6b7b2dd0af916d27574875e95d1eb2 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 11 May 2023 21:38:44 -0400 Subject: [PATCH 037/129] bug fixes wrt pretty printing --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 3 + .../watform/alloyasthelper/DeclExt.java | 4 +- .../watform/alloyasthelper/ExprHelper.java | 10 +- .../watform/alloyasthelper/ExprToString.java | 240 ++++++++++++------ .../uwaterloo/watform/core/DashStrings.java | 5 + .../dashtoalloy/AddSnapshotSignature.java | 2 +- .../AddTransIsEnabledAfterStep.java | 17 +- .../watform/dashtoalloy/AddTransPost.java | 18 +- .../watform/dashtoalloy/AddTransPre.java | 10 +- .../uwaterloo/watform/dashtoalloy/Common.java | 11 +- .../watform/parser/CompModuleHelper.java | 77 +++--- .../uwaterloo/watform/parser/DashModule.java | 32 ++- 12 files changed, 279 insertions(+), 150 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index ca3dd3998..492abcb09 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -10,6 +10,8 @@ import java.io.File; import java.io.FileWriter; +import edu.mit.csail.sdg.alloy4.Version; + import edu.mit.csail.sdg.alloy4.A4Reporter; import edu.mit.csail.sdg.alloy4viz.VizGUI; import edu.mit.csail.sdg.ast.Command; @@ -85,6 +87,7 @@ public static void main(String args[]) throws Exception { } } + System.out.println("Alloy/Dash Analyzer: " + Version.getShortversion() + " built " + Version.buildDate()); DashOptions.isTraces = (method.equals("traces")); DashOptions.isTcmc = (method.equals("tcmc")); DashOptions.isElectrum = (method.equals("electrum")); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java index f8ba40f21..6a23e8fda 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java @@ -45,8 +45,8 @@ public String toString() { names.forEach(n -> sj.add(n.toString())); x += sj.toString(); x += " : "; - ExprToString eToString = new ExprToString(false); - x += eToString.toString(expr); + //ExprToString eToString = new ExprToString(false); + x += ExprHelper.ppExpr(expr); return x; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 5ca78dd24..725eb6aeb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -337,10 +337,14 @@ public static Expr createPredCall(String name, List elist) { return o; } - public static String myExprToString(Expr e) { + /* these wrap the object creation and call to the pretty printer */ + public static String ppExpr(Expr e) { ExprToString eToString = new ExprToString(false); - return eToString.toString(e); + return eToString.exprToString(e); } - + public static String ppDecl(Decl d) { + ExprToString eToString = new ExprToString(false); + return eToString.declToString(d); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index 631924eab..2894248b4 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -24,11 +24,25 @@ import ca.uwaterloo.watform.core.DashRef; import ca.uwaterloo.watform.core.DashErrors; import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashStrings; +/* + Notes on the pretty printer primitives + .begin(boolean consistent, int spaces) - start block + .beginC(x) = .begin(true,x) + .end() - end block + .print(string text) + .brk(int spacesifnotbroken, int spacestoaddorsubtractfromindentifbroken) + .brk(x) = .brk(x,0) + .brk() = .brk(1,0) + + consistent block means if break required then all have breaks + inconsistent block means put as much as possible on a line +*/ public class ExprToString { - int indent = 4; - int lineWidth = 80; + int indent = DashStrings.tab.length(); + int lineWidth = 60; StringBackend back = new StringBackend(lineWidth); DataLayouter out = new DataLayouter(back, indent);; Boolean isAfterAlloyResolveAll; @@ -38,12 +52,20 @@ public ExprToString(boolean isAfterAlloyResolveAll) { this.isAfterAlloyResolveAll = isAfterAlloyResolveAll; } - public String toString(Expr e) { + public String exprToString(Expr e) { out.beginC(0); ExprToOut(e); - out.end().close(); + out.end(); + out.close(); return back.getString(); } + public String declToString(Decl d) { + out.beginC(0); + DeclToOut(d); + out.end(); + out.close(); + return back.getString(); + } private void ExprToOut(Expr expr) { /* @@ -74,12 +96,14 @@ private void ExprToOut(Expr expr) { } else if (expr instanceof ExprUnary){ ExprUnaryToOut((ExprUnary)expr); } else if (expr instanceof ExprVar){ - ExprVarToOut((ExprVar)expr); + out.print(cleanLabel(((ExprVar) expr).label)); } else if (expr instanceof Sig){ - SigToOut((Sig)expr); + out.print(cleanLabel(((Sig) expr).label)); } else if (expr instanceof Field){ - FieldToOut((Field)expr); - } else DashErrors.missingExpr("ExprToOut :" +expr.getClass().getName()); + out.print("(").print(cleanLabel(((Field) expr).label)).print(")"); + } else { + DashErrors.missingExpr("ExprToOut :" +expr.getClass().getName()); + } } /* private void ExprBad(ExprBad expr) { @@ -99,16 +123,18 @@ private void ExprBadCall(ExprBadCall expr) { } */ - + /* private Boolean isBinary(Expr e) { return (e instanceof ExprBinary); } + */ private void ExprBinaryToOut(ExprBinary expr) { if (DashRef.isDashRefProcessRef(expr)) { // Root/A/B[exp1, exp2]/v1 String v = DashRef.nameOfDashRefExpr(expr); String n = DashFQN.chopNameFromFQN(v); String prefix = DashFQN.chopPrefixFromFQN(v); + //TODO: should do proper pretty printing for these! String s = prefix; s += "["; List el = new ArrayList(); @@ -125,9 +151,20 @@ private void ExprBinaryToOut(ExprBinary expr) { } else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { out.print("(seq "); + out.beginC(2); ExprToOut(expr.right); + out.end(); out.print(")"); + } else { + out.beginI(2); + addBracketsIfNeeded(getLeft(expr)); + out.brk(1,0); + out.print(expr.op); + out.brk(1,0); + addBracketsIfNeeded(getRight(expr)); + out.end(); } + /* else if (expr.op == ExprBinary.Op.JOIN) { out.print("("); ExprBinaryJoinToOut(expr); @@ -148,7 +185,7 @@ else if ( isBinary(expr.right) || isBinary(expr.left) ) { ExprToOut(expr.left); out.print(' ').print(expr.op).print(' '); } - if (isBinary(expr.right) && !(exprOp(expr.right) == exprOp(expr)) && !(exprOp(expr.right) == ExprBinary.Op.JOIN)){ + if (isBinary(expr.right) && !({exprOp}(expr.right) == exprOp(expr)) && !(exprOp(expr.right) == ExprBinary.Op.JOIN)){ out.print('{').print(' '); ExprToOut(expr.right); out.print(' ').print("}"); @@ -161,19 +198,27 @@ else if ( isBinary(expr.right) || isBinary(expr.left) ) { out.print(' ').print(expr.op).print(' '); ExprToOut(expr.right); } + */ } - + + private void addBracketsIfNeeded(Expr expr) { + if (!isExprVar(expr)) { + out.beginC(2); + out.print("("); + } + ExprToOut(expr); + if (!isExprVar(expr)) { + out.print(")"); + out.end(); + } + } private void ExprBadJoinToOut(ExprBadJoin expr) { - out.print("("); - ExprToOut(expr.left); - out.print(")"); + addBracketsIfNeeded(expr.left); out.print('.'); - out.print("("); - ExprToOut(expr.right); - out.print(")"); + addBracketsIfNeeded(expr.right); } - + /* private void ExprBinaryJoinToOut(ExprBinary expr) { // The Alloy resolve dot joins (this) to a variable reference in a variable. We should not bring the ("this") // We also do not print (Snapshot <: ...) @@ -197,18 +242,21 @@ private void ExprBinaryJoinToOut(ExprBinary expr) { } } } + */ private void ExprCallToOut(ExprCall expr) { out.print(cleanLabel(expr.fun.label)); if (expr.args.size() == 0) return; - out.print('[').beginCInd(); + out.print('['); + out.beginC(2); for (int i = 0; i < expr.args.size(); i++) { - if (i > 0) - out.print(", "); + if (i > 0) out.print(", "); ExprToOut(expr.args.get(i)); } - out.print(']').end(); + out.end(); + out.print(']'); + } private void ExprChoiceToOut(ExprChoice expr) { @@ -230,49 +278,69 @@ else if (expr.op == ExprConstant.Op.STRING) } private void ExprITEToOut(ExprITE expr) { - out.print('(').beginCInd(); - ExprToOut(expr.cond); - out.print(" => ").brk(1,0); - ExprToOut(expr.left); - out.brk(1,-indent).print(" else ").print("{").brk(1,0); - ExprToOut(expr.right); - out.print(" }"); - out.brk(1,-indent).end().print(')'); + out.beginC(2); + addBracketsIfNeeded(expr.cond); + out.print("=>"); + out.brk(1,indent); + addBracketsIfNeeded(expr.left); + out.brk(1,0); + out.print("else"); + //{") + out.brk(1,indent); + addBracketsIfNeeded(expr.right); + //out.print(" }"); + out.brk(1,-indent); + out.end(); + //out.print(')'); } private void ExprLetToOut(ExprLet expr) { out.print("(let ").print(cleanLabel(expr.var.label)).print("= ").print(expr.toString()).print(" | "); + out.beginC(2); ExprToOut(expr.sub); + out.end(); out.print(')'); } private void ExprListToOut(ExprList expr) { if (expr.op == ExprList.Op.AND ) { String op = " and"; + out.beginC(2); for (int i = 0; i < expr.args.size(); i++) { if (i > 0) out.print(op).brk(1,0); ExprToOut(expr.args.get(i)); } + out.end(); } else if (expr.op == ExprList.Op.OR) { String op = " or"; out.print("{ "); + out.beginC(2); for (int i = 0; i < expr.args.size(); i++) { - if (i > 0) - out.print(op).brk(1,0); + if (i > 0) { + out.print(op); + out.brk(1,0); + } ExprToOut(expr.args.get(i)); } + out.end(); out.print(" }"); } else { - out.print(expr.op).print("[").beginCInd().brk(1,0); + out.print(expr.op); + out.print("["); + out.beginCInd(); + out.brk(1,0); + out.beginC(2); for (int i = 0; i < expr.args.size(); i++) { if (i > 0) out.print(",").brk(1,0); ExprToOut(expr.args.get(i)); } - out.brk(1,-indent).end().print(']'); + out.brk(1,-indent); + out.end(); + out.print(']'); } } @@ -296,32 +364,37 @@ private void ExprQtToOut(ExprQt expr) { private void ExprUnaryToOut(ExprUnary expr) { switch (expr.op) { - // this ops don't print properly with toString + // special cases for the + // ones that the Alloy op.toString() + // does not seem to print in a way that matches + // how the symbol is input // e.g. set X becomes set of X case SOMEOF : - out.print("some ("); - ExprToOut(expr.sub); - out.print(")"); + out.print("some"); + out.brk(1); + addBracketsIfNeeded(expr.sub); break; case LONEOF : - out.print("lone ("); - ExprToOut(expr.sub); - out.print(")"); + out.print("lone"); + out.brk(1); + addBracketsIfNeeded(expr.sub); break; case ONEOF : - out.print("one ("); - ExprToOut(expr.sub); - out.print(")"); - break; - case SETOF : - out.print("set ("); - ExprToOut(expr.sub); - out.print(")"); + out.print("one"); + + out.brk(1); + addBracketsIfNeeded(expr.sub); break; + case EXACTLYOF : - out.print("exactly ("); - ExprToOut(expr.sub); - out.print(")"); + out.print("exactly"); + out.brk(1); + addBracketsIfNeeded(expr.sub); + break; + case SETOF : + out.print("set"); + out.brk(1); + addBracketsIfNeeded(expr.sub); break; case CAST2INT : out.print("int["); @@ -336,45 +409,43 @@ private void ExprUnaryToOut(ExprUnary expr) { case PRIME : //TODO: perhaps this one should not exist? //TODO: other temporal formulas that should not exist? - out.print('('); - ExprToOut(expr.sub); - out.print(")'"); + addBracketsIfNeeded(expr.sub); + out.print("'"); break; case RCLOSURE : - out.print("* ("); - ExprToOut(expr.sub); - out.print(")"); + out.print("*"); + out.brk(1,0); + addBracketsIfNeeded(expr.sub); break; case TRANSPOSE : - out.print("~ ("); - ExprToOut(expr.sub); - out.print(")"); + out.print("~"); + out.brk(1,0); + addBracketsIfNeeded(expr.sub); break; case CLOSURE : - out.print("^ ("); - ExprToOut(expr.sub); - out.print(")"); + out.print("^"); + out.brk(1); + addBracketsIfNeeded(expr.sub); break; case NOT : - out.print("! {"); - ExprToOut(expr.sub); - out.print("}"); + out.print("!"); + out.brk(1,0); + addBracketsIfNeeded(expr.sub); break; case NOOP : ExprToOut(expr.sub); break; default : - // this puts in more brackets that usual - // but since we can have - // #var become #(s.var) - // the brackets might be necessary - out.print(expr.op).print('('); - ExprToOut(expr.sub); - out.print(")"); + // many operators print okay + // e.g., one, + out.print(expr.op); + out.brk(1); + addBracketsIfNeeded(expr.sub); } } + /* private void ExprVarToOut(ExprVar expr) { out.print(cleanLabel(expr.label)); } @@ -386,9 +457,11 @@ private void SigToOut(Sig sig) { private void FieldToOut(Field field) { out.print("(").print(cleanLabel(field.label)).print(")"); } + */ // Helper method to print a list of declarations - private void DeclsToOut(ConstList decls) { + private void DeclsToOut(List decls) { + //TODO add appropriate breaks here boolean first = true; for (Decl decl : decls) { StringJoiner namesJoiner = new StringJoiner(","); @@ -406,6 +479,20 @@ private void DeclsToOut(ConstList decls) { } } + private void DeclToOut(Decl decl) { + if (decl.disjoint != null) { + out.print("disj").print(" "); + } + //StringJoiner namesJoiner = new StringJoiner(","); + //decl.names.forEach(name -> namesJoiner.add(cleanLabel(name.label))); + //if (!first) { + // out.print(","); + //} + //first = false; + out.print(DashUtilFcns.strCommaList(decl.names)); + out.print(": "); + ExprToOut(decl.expr); + } // Helper method to change "{path/label}" to "label" private String cleanLabel(String label) { if (!label.contains("this/")) { @@ -421,11 +508,12 @@ private String cleanLabel(String label) { return label; } - + /* private ExprBinary.Op exprOp (Expr expr) { if (expr instanceof ExprBinary) return ((ExprBinary) expr).op; return null; } + */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 0a3a8b4bb..af4c5ef65 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -4,6 +4,9 @@ public class DashStrings { + // pretty printing anywhere + public static String tab = " "; + /* alloy keywords */ public static String moduleName = "module"; public static String extendsName = "extends"; @@ -138,4 +141,6 @@ public static String removePrime(String s) { if (hasPrime(s)) return s.substring(0, s.length()-1); else return s; } + + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 9a45aeb08..47ca795c8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -191,7 +191,7 @@ public static void addSnapshotSignature(DashModule d){ decls.add(DeclExt.newSetDeclExt(eventsName+"0", allEventsName)); List cop; for (int i = 1; i <= d.getMaxDepthParams(); i++) { - cop = Collections.nCopies(i+1,identifierName); + cop = Collections.nCopies(i,identifierName); // scopesUsed 1, etc. //if (d.transAtThisParamDepth(i)) decls.add((Decl) new DeclExt( diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java index 68753998d..814179817 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -75,7 +75,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { // p3 -> p2 -> p1 -> src in s'.confVar(i) // src does not have to be a basic state - body.add(createIn(translateDashRef(d.getTransSrc(tfqn)),nextConf(prs.size()))); + body.add(createIn(translateDashRefToArrow(d.getTransSrc(tfqn)),nextConf(prs.size()))); // primed guard condition is true // TODO @@ -88,7 +88,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { List nonO = d.nonOrthogonalScopesOf(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(nonO,i).stream() - .map(x -> translateDashRef(x)) + .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); // o1: forall i. not(t1_nonOrthScopei in scopesi) for (Expr x: u) orth1.add(createNot(createIn(x,scopeVar(i)))); @@ -101,7 +101,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { List orth2 = new ArrayList(); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(nonO,i).stream() - .map(x -> translateDashRef(x)) + .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); // o2: forall i. not(t1_nonOrthScopei in scopesi + s'.scopesUsedi) for (Expr x: u) orth1.add(createNot(createIn(x,createUnion(curScopesUsed(i), scopeVar(i))))); @@ -118,7 +118,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { ev1 = createFalse(); } else { ev1 = createIn( - translateDashRef(ev), + translateDashRefToArrow(ev), createUnion( createIntersect( curEvents(ev.getParamValues().size()), @@ -127,7 +127,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { } // ev2: t1_on in s.eventsi + genEventsi ev2 = createIn( - translateDashRef(ev), + translateDashRefToArrow(ev), createUnion( curEvents(ev.getParamValues().size()), genEventVar(ev.getParamValues().size()))); @@ -154,14 +154,9 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { public static Decl genEventsDecl(int i) { return (Decl) new DeclExt(DashStrings.genEventName + i, DashStrings.allEventsName); } - public static Decl scopeDecl(int i) { - return (Decl) new DeclExt(DashStrings.scopeName + i, DashStrings.stateLabelName); - } public static Expr genEventsVar(int i) { return createVar(DashStrings.genEventName + i); } - public static Expr scopeVar(int i) { - return createVar(DashStrings.scopeName + i); - } + } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index f052959f7..207758e12 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -83,10 +83,10 @@ public static void addTransPost(DashModule d, String tfqn) { List exited = d.exited(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List ent = DashRef.hasNumParams(entered,i).stream() - .map(x -> translateDashRef(x)) + .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); List exi = DashRef.hasNumParams(exited,i).stream() - .map(x -> translateDashRef(x)) + .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); Expr e = curConf(i); if (!exi.isEmpty()) e = createDiff(e,createDiffList(exi)); @@ -97,7 +97,7 @@ public static void addTransPost(DashModule d, String tfqn) { List sU = d.scopesUsed(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(sU,i).stream() - .map(x -> translateDashRef(x)) + .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); Expr e = curScopesUsed(i); if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); @@ -118,7 +118,7 @@ public static void addTransPost(DashModule d, String tfqn) { Expr c1; for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { - if (ev != null && ev.getParamValues().size() == i) rhs = translateDashRef(ev); + if (ev != null && ev.getParamValues().size() == i) rhs = translateDashRefToArrow(ev); else rhs = createNone(); case1.add(createEquals( createIntersect(nextEvents(i),allInternalEventsVar()), @@ -135,7 +135,7 @@ public static void addTransPost(DashModule d, String tfqn) { for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { q = createIntersect(allInternalEventsVar(), curEvents(i)); - if (ev != null && ev.getParamValues().size() == i) rhs = createUnion(translateDashRef(ev), q); + if (ev != null && ev.getParamValues().size() == i) rhs = createUnion(translateDashRefToArrow(ev), q); else rhs = q; case2.add(createEquals( createIntersect(nextEvents(i),allInternalEventsVar()), @@ -153,7 +153,7 @@ public static void addTransPost(DashModule d, String tfqn) { Expr c3; for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { - if (ev != null && ev.getParamValues().size() == i) rhs1 = translateDashRef(ev); + if (ev != null && ev.getParamValues().size() == i) rhs1 = translateDashRefToArrow(ev); else rhs1 = createNone(); case3.add(createAnd( createEquals( @@ -175,7 +175,7 @@ public static void addTransPost(DashModule d, String tfqn) { for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) - case4.add(createEquals(nextEvents(i),createUnion(curEvents(i), translateDashRef(ev)))); + case4.add(createEquals(nextEvents(i),createUnion(curEvents(i), translateDashRefToArrow(ev)))); } } if (case4.isEmpty()) c4 = createTrue(); @@ -234,13 +234,13 @@ private static Expr createTestIfNextStableCall(DashModule d, String tfqn) { for (int i=0; i <= d.getMaxDepthParams(); i++) { //TODO could only have scopesUsedi for i that has scopesUsed List u = DashRef.hasNumParams(sU,i).stream() - .map(x -> translateDashRef(x)) + .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); if (u.size() == 1) args.add(u.get(0)); else if (u.size() ==0 ) args.add(createNone()); else { DashErrors.createTestIfNextStableCallMultipleScopesAtSameLevel(); return null; } if (d.hasEventsAti(i)) { - if (ev != null && ev.getParamValues().size() == i) args.add(translateDashRef(ev)); + if (ev != null && ev.getParamValues().size() == i) args.add(translateDashRefToArrow(ev)); else args.add(createNone()); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 9aa3a421e..0e8f357d3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -53,7 +53,7 @@ public static void addTransPre(DashModule d, String tfqn) { // p3 -> p2 -> p1 -> src in s.confVar(i) // src does not have to be a basic state - body.add(createIn(translateDashRef(d.getTransSrc(tfqn)),curConf(prs.size()))); + body.add(createIn(translateDashRefToArrow(d.getTransSrc(tfqn)),curConf(prs.size()))); if (d.getTransWhen(tfqn) != null) body.add(translateExpr(d.getTransWhen(tfqn),d)); @@ -62,7 +62,7 @@ public static void addTransPre(DashModule d, String tfqn) { List nonO = d.nonOrthogonalScopesOf(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(nonO,i).stream() - .map(x -> translateDashRef(x)) + .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); for (Expr x: u) body.add(createNot(createIn(x,curScopesUsed(i)))); } @@ -73,11 +73,11 @@ public static void addTransPre(DashModule d, String tfqn) { // trig_events_t1 DashRef ev = d.getTransOn(tfqn); int sz = ev.getParamValues().size(); - Expr ifBranch = createIn(translateDashRef(ev), + Expr ifBranch = createIn(translateDashRefToArrow(ev), createIntersect( curEvents(sz), allEnvironmentalEventsVar())); - Expr elseBranch = createIn(translateDashRef(ev), curEvents(sz)); + Expr elseBranch = createIn(translateDashRefToArrow(ev), curEvents(sz)); body.add(createITE( curStableTrue(), ifBranch, @@ -86,7 +86,7 @@ public static void addTransPre(DashModule d, String tfqn) { } else if (d.getTransOn(tfqn) != null) { DashRef ev = d.getTransOn(tfqn); int sz = ev.getParamValues().size(); - body.add(createIn(translateDashRef(ev),curEvents(sz))); + body.add(createIn(translateDashRefToArrow(ev),curEvents(sz))); } /* diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index f4e47fe82..ce8f7e11e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -82,7 +82,7 @@ public static Decl genEventDecl(int i) { } public static Decl scopeDecl(int i) { - return (Decl) new DeclExt(DashStrings.scopeName + i, DashStrings.allEventsName); + return (Decl) new DeclExt(DashStrings.scopeName + i, DashStrings.stateLabelName); } // common vars @@ -220,13 +220,20 @@ public static Expr paramsToXArrow(List prs, String x) { return e; } - public static Expr translateDashRef(DashRef e) { + public static Expr translateDashRefToArrow(DashRef e) { List ll = new ArrayList(e.getParamValues()); Collections.reverse(ll); ll.add(createVar(translateFQN(e.getName()))); return createArrowExprList(ll); } + public static Expr translateDashRefToJoin(DashRef e) { + List ll = new ArrayList(e.getParamValues()); + Collections.reverse(ll); + ll.add(createVar(translateFQN(e.getName()))); + return createJoinList(ll); + } + //TODO better name! public static boolean isWeirdOne(String vfqn, DashModule d) { return d.getVarBufferParams(vfqn).size() == 0 && isExprArrow(d.getVarType(vfqn)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 60795115b..f75af84c9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -25,13 +25,13 @@ import edu.mit.csail.sdg.parser.CompModule; import ca.uwaterloo.watform.core.DashStrings; -import ca.uwaterloo.watform.alloyasthelper.ExprHelper; -import ca.uwaterloo.watform.alloyasthelper.ExprToString; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; +//import static ca.uwaterloo.watform.alloyasthelper.ExprToString.*; public class CompModuleHelper extends CompModule { private String space = " "; - private String tab = " "; + private String tab = DashStrings.tab; // this class is never instantiated public CompModuleHelper(CompModule world, String filename, String path) { @@ -39,11 +39,11 @@ public CompModuleHelper(CompModule world, String filename, String path) { } public String addOpenSimple(String name, List args, String aliasName) { - ExprVar alias = (aliasName == null) ? null : ExprHelper.createVar(aliasName); + ExprVar alias = (aliasName == null) ? null : createVar(aliasName); List argsExprList = new ArrayList(); if (args != null) - for (String a: args) argsExprList.add(ExprHelper.createVar(a)); - addOpen(null, null, ExprHelper.createVar(name), argsExprList, alias); + for (String a: args) argsExprList.add(createVar(a)); + addOpen(null, null, createVar(name), argsExprList, alias); // build the string that is this open String s = DashStrings.openName + " "+name; if (args != null) { @@ -113,8 +113,8 @@ public String addAbstractExtendsSigSimple(String extension, String extended) { addSig( Pos.UNKNOWN, extension, - ExprHelper.createVar(DashStrings.extendsName), - ExprHelper.createExprVarList(new ArrayList(Arrays.asList(extended))), + createVar(DashStrings.extendsName), + createExprVarList(new ArrayList(Arrays.asList(extended))), new ArrayList(), null, AttrType.ABSTRACT.makenull(Pos.UNKNOWN), @@ -136,8 +136,8 @@ public String addExtendsSigSimple(String extension, String extended) { addSig( Pos.UNKNOWN, extension, - ExprHelper.createVar(DashStrings.extendsName), - ExprHelper.createExprVarList(new ArrayList(Arrays.asList(extended))), + createVar(DashStrings.extendsName), + createExprVarList(new ArrayList(Arrays.asList(extended))), new ArrayList(), null, null, @@ -159,8 +159,8 @@ public String addOneExtendsSigSimple(String extension, String extended) { addSig( Pos.UNKNOWN, extension, - ExprHelper.createVar(DashStrings.extendsName), - ExprHelper.createExprVarList(new ArrayList(Arrays.asList(extended))), + createVar(DashStrings.extendsName), + createExprVarList(new ArrayList(Arrays.asList(extended))), new ArrayList(), null, null, @@ -192,9 +192,9 @@ public String addSigWithDeclsSimple(String name, List decls) { null, null); String s = DashStrings.sigName + space + name; - s += " {\n"; - StringJoiner j = new StringJoiner(",\n"); - decls.forEach(i -> j.add(tab + i.toString())); + s += " {\n"+tab; + StringJoiner j = new StringJoiner(",\n"+tab); + decls.forEach(i -> j.add(ppDecl(i))); s += j.toString() + "\n}\n"; //System.out.println(s); return s; @@ -204,8 +204,8 @@ public String addSigExtendsWithDeclsSimple(String extension, String extended, Li addSig( Pos.UNKNOWN, extension, - ExprHelper.createVar(DashStrings.extendsName), - ExprHelper.createExprVarList(new ArrayList(Arrays.asList(extended))), + createVar(DashStrings.extendsName), + createExprVarList(new ArrayList(Arrays.asList(extended))), decls, null, null, @@ -218,8 +218,9 @@ public String addSigExtendsWithDeclsSimple(String extension, String extended, Li s += extension + space + DashStrings.extendsName + space; s += extended; s += " {\n"; - StringJoiner j = new StringJoiner(",\n"); - decls.forEach(i -> j.add(tab + i.toString())); + //s += ppDecls(decls); + StringJoiner j = new StringJoiner(",\n"+tab); + decls.forEach(i -> j.add(ppDecl(i))); s += j.toString() + "\n}\n"; //System.out.println(s); return s; @@ -240,8 +241,9 @@ public String addOneSigWithDeclsSimple(String name, List decls) { null, null); String s = DashStrings.sigName + space + name + space + "{\n"; + //s += ppDecls(decls); StringJoiner j = new StringJoiner(",\n"); - decls.forEach(i -> j.add(tab + i.toString())); + decls.forEach(i -> j.add(ppDecl(i))); s += j.toString() + "\n}\n"; //System.out.println(s); return s; @@ -251,7 +253,7 @@ public String addVarSigSimple(String name, ExprVar typ) { addSig( Pos.UNKNOWN, name, - ExprHelper.createVar(DashStrings.inName), + createVar(DashStrings.inName), Arrays.asList(typ), new ArrayList(), null, @@ -264,7 +266,7 @@ public String addVarSigSimple(String name, ExprVar typ) { ); String s = DashStrings.varName + space + DashStrings.sigName + space; s += name + space + DashStrings.inName + space; - s += typ.toString(); + s += ppExpr(typ); s += " { }\n"; //System.out.println(s); return s; @@ -275,7 +277,7 @@ public String addVarSigSimple(String name, List typ) { addSig( Pos.UNKNOWN, name, - ExprHelper.createVar(DashStrings.inName), + createVar(DashStrings.inName), typ, new ArrayList(), null, @@ -288,7 +290,7 @@ public String addVarSigSimple(String name, List typ) { ); String s = DashStrings.varName + space + DashStrings.sigName + space; s += name + space + DashStrings.inName + space; - s += typ.toString(); + s += ppExpr(((Expr) typ)); s += " { }\n"; //System.out.println(s); return s; @@ -304,14 +306,15 @@ public String addVarSigSimple(String name, List typ) { * t is return type; null if predicate */ public String addPredSimple(String name, List decls, List eList) { - Expr body = ExprHelper.createAndFromList(eList); - addFunc(Pos.UNKNOWN, Pos.UNKNOWN, ExprHelper.createVar(name), null, decls, null, body); + Expr body = createAndFromList(eList); + addFunc(Pos.UNKNOWN, Pos.UNKNOWN, createVar(name), null, decls, null, body); String s = new String(); s += DashStrings.predName + " " + name; if (!decls.isEmpty()) { s += " ["; + //s += ppDecls(decls); StringJoiner j = new StringJoiner(", "); - decls.forEach(i -> j.add(i.toString())); + decls.forEach(i -> j.add(ppDecl(i))); s += j.toString() + "]"; } // we have to use our own printer @@ -323,14 +326,14 @@ public String addPredSimple(String name, List decls, List eList) { // but remember the predicate call to testIfNextStable is nested // inside an ITE - s += " {\n "+tab; + s += " {\n"+tab; StringJoiner sj = new StringJoiner("\n" + tab); for (Expr e: eList) { - ExprToString eToString = new ExprToString(false); - sj.add(eToString.toString(e)); + //ExprToString eToString = new ExprToString(false); + sj.add(ppExpr(e)); } - s += sj.toString() + "\n"; - s+= "}\n\n"; + s += sj.toString(); + s += "\n}\n\n"; return s; } @@ -341,7 +344,7 @@ public String addPredSimple(String name, List decls, List eList) { */ public String addFactSimple(String name, List eList) { - Expr body = ExprHelper.createAndFromList(eList); + Expr body = createAndFromList(eList); addFact(Pos.UNKNOWN,name,body); String s = new String(); s += DashStrings.factName + " " + name + " {"; @@ -349,8 +352,8 @@ public String addFactSimple(String name, List eList) { s += tab; StringJoiner sj = new StringJoiner("\n" + tab); for (Expr e: eList) { - ExprToString eToString = new ExprToString(false); - sj.add(eToString.toString(e)); + //ExprToString eToString = new ExprToString(false); + sj.add(ppExpr(e)); } s += sj.toString() + "\n"; s+= "}\n\n"; @@ -380,6 +383,7 @@ public String getFilePath() { } // this seems incomplete -> DROP IT EVENTUALLY // also need to print facts + /* public String sigsToString() { StringBuilder sb = new StringBuilder(""); for(Sig sig: sigs.values()) { @@ -424,4 +428,7 @@ public String sigsToString() { } return sb.toString(); } + */ + + } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 467c0d79a..b31416393 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -87,7 +87,7 @@ public DashModule(CompModule world, String filename, String path) { initializeDashModule(); } private void initializeDashModule() { - assert (!DashOptions.isElectrum && (DashOptions.isTcmc || DashOptions.isTraces)); + //assert (!DashOptions.isElectrum && (DashOptions.isTcmc || DashOptions.isTraces)); // do the open stmts for Dash after we know how many buffers // b/c the opens are parsed during parsing if (DashSituation.haveCountedBuffers) { @@ -150,30 +150,47 @@ public String toStringAlloy() { String r; Integer k = 0; Boolean writeBooleanOpen = true; - if (rootStartLine == 1) s += opens; - else { + Boolean wroteOpens = false; + //System.out.println(opens); + //if (rootStartLine == 1) { + // assume there were no opens in the file + // s += booleanOpen; + // s += opens; + //} else { + + //System.out.println(rootStartLine); + + // lines in file start counting at 1 + k = 0; for (int j= 0; j < rootStartLine-1; j++) { k = j; + //System.out.println(j); r = br.readLine(); + // empty line if (!(r.replaceAll("\\s+","").equals(""))) { if (r.contains(DashStrings.moduleName) || r.contains(DashStrings.openName)) { + //make sure we don't open boolean twice if (r.contains(DashStrings.openName) && r.contains(DashStrings.utilBooleanName)) writeBooleanOpen = false; s += r +"\n"; } else { + // we've reached the end of the opens in the file + // now add our own opens and quit this loop if (writeBooleanOpen) s += booleanOpen; s += opens + "\n"; // have to write the line after module/opens + // that we just read s += r +"\n"; + wroteOpens = true; break; } } else s += "\n"; } - // there was nothing before "state" - if (k == rootStartLine-1) s += opens; + if (!wroteOpens) { s += booleanOpen; s += opens; } + // add all the lines after the opens and before 'state' if (k+1 < rootStartLine-1) { for (int i = k+1; i < rootStartLine -1 ; i++) s += br.readLine() + "\n"; } - } + //} // skip Dash stuff for (int i = 0; i <= rootEndLine - rootStartLine+1; i++) br.readLine(); @@ -201,6 +218,9 @@ public String toStringAlloy() { public void importModules(List bufElements, List bufNames) { //System.out.println("Adding open stmts"); String noAlias = null; + // module might already include it + // safe to reopen it internally? + // but don't want it printed twice? booleanOpen = this.addOpenSimple(DashStrings.utilBooleanName, null, noAlias); if (DashOptions.isTcmc) opens += this.addOpenSimple(DashStrings.utilTcmcPathName, Arrays.asList(DashStrings.snapshotName), noAlias); From 7ec8d61e0acafc9710fd8716b8b5a6836a13fe45 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Mon, 15 May 2023 10:52:17 -0400 Subject: [PATCH 038/129] small bug fixes --- .../watform/alloyasthelper/ExprHelper.java | 11 ++++ .../uwaterloo/watform/core/DashStrings.java | 20 +++--- .../watform/dashtoalloy/AddInit.java | 20 +++--- .../AddTransIsEnabledAfterStep.java | 2 +- .../watform/dashtoalloy/AddTransPost.java | 62 +++++++++++-------- .../uwaterloo/watform/dashtoalloy/Common.java | 10 ++- .../uwaterloo/watform/parser/DashModule.java | 3 + .../uwaterloo/watform/parser/EventTable.java | 4 ++ .../ca/uwaterloo/watform/parser/VarTable.java | 5 +- 9 files changed, 89 insertions(+), 48 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 725eb6aeb..2cd4e67e9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -191,6 +191,9 @@ public static Expr createJoinList(List elist) { } return ret; } + public static ExprBinary createRangeRes(Expr left, Expr right) { + return (ExprBinary) ExprBinary.Op.RANGE.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } public static Expr createUnionList(List elist) { Expr ret = null; assert(elist!=null); @@ -307,8 +310,16 @@ public static Expr createArrowExprList(List eList) { return o; } + // Alloy won't use boolean/True or boolean/False as formulas + // but it can be convenient in our code to use them + // so let's just simplify them out in formulas public static Expr createITE(Expr cond, Expr impliesExpr, Expr elseExpr) { if (sEquals(cond, createTrue())) return (Expr) impliesExpr; + if (sEquals(cond,createFalse())) return (Expr) elseExpr; + if (sEquals(impliesExpr,createTrue())) return createOr(cond, createAnd(createNot(cond),elseExpr)); + if (sEquals(impliesExpr,createFalse())) return createAnd(createNot(cond),elseExpr); + if (sEquals(elseExpr,createTrue())) return createOr(createAnd(cond,impliesExpr), createNot(cond)); + if (sEquals(elseExpr,createFalse())) return createAnd(cond,impliesExpr); else return (Expr) ExprITE.make(Pos.UNKNOWN, cond, impliesExpr, elseExpr); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index af4c5ef65..100852044 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -80,17 +80,17 @@ public class DashStrings { public static String confName = "conf"; public static String scopesUsedName = "scopesUsed"; - public static String stateLabelName = "StateLabel"; - public static String systemStateName = "SystemState"; + public static String stateLabelName = "States"; + //public static String systemStateName = "SystemState"; //public static String transitionLabelName = "TransitionLabel"; - public static String identifierName = "Identifiers"; + public static String identifierName = "Ids"; // how to name parameter variables public static String pName = "p"; public static String eventsName = "events"; - public static String allEventsName = "AllEvents"; - public static String allEnvironmentalEventsName = "AllEnvironmentalEvents"; - public static String allInternalEventsName = "AllInternalEvent"; - public static String variablesName = "Variables"; + public static String allEventsName = "Events"; + public static String allEnvironmentalEventsName = "EnvEvents"; + public static String allInternalEventsName = "IntEvent"; + public static String variablesName = "Vars"; public static String preName = "_pre"; public static String postName = "_post"; @@ -98,8 +98,8 @@ public class DashStrings { public static String testIfNextStableName = "testIfNextStable"; public static String enabledAfterStepName = "_enabledAfterStep"; public static String tName = "t"; - public static String genEventName = "genEvents"; - public static String scopeName = "scope"; + public static String genEventName = "genEvs"; + public static String scopeName = "scp"; public static String bufferName = "buffer"; public static String bufferIndexName = "bufIdx"; @@ -108,7 +108,7 @@ public class DashStrings { public static String tracesName = "traces"; public static String curName = "s"; - public static String nextName = "sNext"; + public static String nextName = "sn"; public static String prime(String a) { return a+"'"; }; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 2110e8397..6156ccf52 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -47,19 +47,21 @@ public static void addInit(DashModule d) { // so don't try to combine these steps Expr e; - if (!prs.isEmpty()) - e = createAll( - // might need to add "p" to the front of these - paramDecls(prs), - createAndFromList(body)); - else e = createAndFromList(body); - body = new ArrayList(); - body.add(e); + if (!body.isEmpty()) { + if (!prs.isEmpty()) + e = createAll( + // might need to add "p" to the front of these + paramDecls(prs), + createAndFromList(body)); + else e = createAndFromList(body); + body = new ArrayList(); + body.add(e); + } // init is a reserved word in Electrum if (DashOptions.isElectrum) { d.alloyString += d.addPredSimple(DashStrings.initFactName, new ArrayList(), body); } else { - d.alloyString += d.addPredSimple(DashStrings.initFactName, curNextParamsDecls(prs),body); + d.alloyString += d.addPredSimple(DashStrings.initFactName, curParamsDecls(prs),body); } } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java index 814179817..3eca0a077 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -114,7 +114,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { Expr ev1, ev2; if (ev != null) { //ev1: t1_on in (s.eventsi & EnvEvents) + genEventsi // if t1_on is internal this is false - if (d.isEnvironmentalEvent(ev.getName())) { + if (d.isInternalEvent(ev.getName())) { ev1 = createFalse(); } else { ev1 = createIn( diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 207758e12..967b1473c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -89,7 +89,12 @@ public static void addTransPost(DashModule d, String tfqn) { .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); Expr e = curConf(i); - if (!exi.isEmpty()) e = createDiff(e,createDiffList(exi)); + for (Expr x:ent) { + // can't diff ((ent1 - ent2) - ent3) + // but have to diff from whole set + e = createDiff(e,x); + } + //if (!exi.isEmpty()) e = createDiff(e,createDiffList(exi)); if (!ent.isEmpty()) e = createUnion(e,createUnionList(ent)); body.add(createEquals(nextConf(i),e)); } @@ -112,8 +117,8 @@ public static void addTransPost(DashModule d, String tfqn) { Expr rhs, rhs1, q; // case 1 - // forall i. eventsi' & AllInternalEvents = t1_send (if i) - // eventsi' & AllIntermalEvents = none (if not i) + // forall i. eventsi' :> InternalEvents = t1_send (if i) + // eventsi' :> InternalEvents = none (if not i) List case1 = new ArrayList(); Expr c1; for (int i=0;i <= d.getMaxDepthParams(); i++) { @@ -121,15 +126,16 @@ public static void addTransPost(DashModule d, String tfqn) { if (ev != null && ev.getParamValues().size() == i) rhs = translateDashRefToArrow(ev); else rhs = createNone(); case1.add(createEquals( - createIntersect(nextEvents(i),allInternalEventsVar()), + createRangeRes(nextEvents(i),allInternalEventsVar()), rhs)); } } - if (case1.isEmpty()) c1 = createTrue(); - else c1 = createAndFromList(case1); + //if (case1.isEmpty()) c1 = createTrue(); + c1 = createAndFromList(case1); // case 2 - // forall i: eventsi' & InternalEvent = t1_send_ev (if i) + (InternalEvent & eventsi) + // forall i. eventsi' :> InternalEvents = t1_send_ev (if i) + eventsi + // eventsi' :> InternalEvents = eventsi (if not i) List case2 = new ArrayList(); Expr c2; for (int i=0;i <= d.getMaxDepthParams(); i++) { @@ -138,34 +144,39 @@ public static void addTransPost(DashModule d, String tfqn) { if (ev != null && ev.getParamValues().size() == i) rhs = createUnion(translateDashRefToArrow(ev), q); else rhs = q; case2.add(createEquals( - createIntersect(nextEvents(i),allInternalEventsVar()), + createRangeRes(nextEvents(i),allInternalEventsVar()), rhs)); } } - if (case2.isEmpty()) c2 = createTrue(); - else c2 = createAndFromList(case2); + //if (case2.isEmpty()) c2 = createTrue(); + c2 = createAndFromList(case2); // case 3 - // forall i: (eventsi' & InternalEvent = t1_send_ev (if i)) - // (eventsi' & InternalEvent = none) (if not i) - // and (eventsi' & EnvironmentalEvent = eventsi & EnvironmentalEvent) + // forall i: (eventsi' :> InternalEvent = t1_send_ev (if i)) + // (eventsi' :> InternalEvent = none) (if not i) + // and (eventsi' :> EnvironmentalEvent = eventsi :> EnvironmentalEvent) List case3 = new ArrayList(); Expr c3; for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) rhs1 = translateDashRefToArrow(ev); else rhs1 = createNone(); - case3.add(createAnd( - createEquals( - createIntersect(nextEvents(i),allInternalEventsVar()), - rhs1), - createEquals( - createIntersect(nextEvents(i),allEnvironmentalEventsVar()), - createIntersect(curEvents(i),allEnvironmentalEventsVar()) ))); + if (d.hasEnvironmentalEvents()) + case3.add(createAnd( + createEquals( + createRangeRes(nextEvents(i),allInternalEventsVar()), + rhs1), + createEquals( + createRangeRes(nextEvents(i),allEnvironmentalEventsVar()), + createRangeRes(curEvents(i),allEnvironmentalEventsVar()) ))); + else + case3.add(createEquals( + createRangeRes(nextEvents(i),allInternalEventsVar()), + rhs1)); } } - if (case3.isEmpty()) c3 = createTrue(); - else c3 = createAndFromList(case3); + //if (case3.isEmpty()) c3 = createTrue(); + c3 = createAndFromList(case3); // case 4 // forall i. eventsi' = eventsi + t1_send (if i) @@ -178,8 +189,8 @@ public static void addTransPost(DashModule d, String tfqn) { case4.add(createEquals(nextEvents(i),createUnion(curEvents(i), translateDashRefToArrow(ev)))); } } - if (case4.isEmpty()) c4 = createTrue(); - else c4 = createAndFromList(case4); + //if (case4.isEmpty()) c4 = createTrue(); + c4 = createAndFromList(case4); // env_vars_unchanged[s,s'] @@ -192,7 +203,8 @@ public static void addTransPost(DashModule d, String tfqn) { .collect(Collectors.toList())); Expr stableFalseAndEnvNoChange = createAnd(nextStableFalse(), envNoChange); - + // big ITE is simplified for boolean/True, boolean/False + // b/c Alloy does not allow those as "formulas" if (d.hasConcurrency()) body.add( createITE(createTestIfNextStableCall(d, tfqn), diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index ce8f7e11e..56745a19a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -78,11 +78,17 @@ public static List curNextParamsDecls(List prs) { } public static Decl genEventDecl(int i) { - return (Decl) new DeclExt(DashStrings.genEventName + i, DashStrings.allEventsName); + Listcop = Collections.nCopies(i,DashStrings.identifierName); + return (Decl) new DeclExt( + DashStrings.genEventName + i, + createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.allEventsName))); } public static Decl scopeDecl(int i) { - return (Decl) new DeclExt(DashStrings.scopeName + i, DashStrings.stateLabelName); + Listcop = Collections.nCopies(i,DashStrings.identifierName); + return (Decl) new DeclExt( + DashStrings.scopeName + i, + createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.stateLabelName))); } // common vars diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index b31416393..5e78078ee 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -347,6 +347,9 @@ public List getHigherPriTrans(String tfqn) { public boolean isEnvironmentalEvent(String efqn) { return eventTable.isEnvironmentalEvent(efqn); } + public boolean isInternalEvent(String efqn) { + return eventTable.isInternalEvent(efqn); + } public List getAllVarNames() { return varTable.getAllVarNames(); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index b6b5ef65d..f24b1b39d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -110,6 +110,10 @@ public boolean isEnvironmentalEvent(String efqn) { if (table.containsKey(efqn)) return (table.get(efqn).kind == IntEnvKind.ENV); else { DashErrors.eventTableEventNotFound("isEnvironmentalEvent", efqn); return false; } } + public boolean isInternalEvent(String efqn) { + if (table.containsKey(efqn)) return (table.get(efqn).kind == IntEnvKind.INT); + else { DashErrors.eventTableEventNotFound("isInternalEvent", efqn); return false; } + } public List allEventsOfState(String sfqn) { // return all events declared in this state // will have the sfqn as a prefix diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index 44a1bbd5c..ff4f7ca25 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -332,7 +332,10 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, } else { // name might not be fully resolved v = DashRef.nameOfDashRefExpr(exp); - paramValues = DashRef.paramValuesOfDashRefExpr(exp); + // have to recurse through param values + paramValues = DashRef.paramValuesOfDashRefExpr(exp).stream() + .map(i -> resolveExpr(xType, i, region, fqn, params)) + .collect(Collectors.toList()); } String vfqn = DashFQN.fqn(v); Boolean isPrimed = false; From c02f0462b0122aa0afbf14742610f6ffc3aea9dd Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 16 May 2023 19:31:37 -0400 Subject: [PATCH 039/129] adding something in org.alloytools.alloy.dash/src/main.resources --- .../watform/alloyasthelper/ExprHelper.java | 18 ++++++++++++----- .../ca/uwaterloo/watform/core/DashErrors.java | 6 +++--- .../uwaterloo/watform/core/DashUtilFcns.java | 11 ++++++++++ .../dashtoalloy/AddSpaceSignatures.java | 16 +++++++-------- .../watform/dashtoalloy/AddTransPost.java | 4 ++-- .../watform/dashtoalloy/AddTransPre.java | 13 ++++++++---- .../uwaterloo/watform/dashtoalloy/Common.java | 10 ++++++++++ .../uwaterloo/watform/parser/DashModule.java | 20 +++++++++++++++++-- .../src/main/resources/nothing.txt | 1 + 9 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/resources/nothing.txt diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 2cd4e67e9..d7b7a3941 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -20,7 +20,7 @@ import ca.uwaterloo.watform.core.DashStrings; import ca.uwaterloo.watform.core.DashErrors; - +import ca.uwaterloo.watform.core.DashUtilFcns; import ca.uwaterloo.watform.alloyasthelper.ExprToString; // these are all static @@ -175,6 +175,9 @@ public static Expr createNot(Expr sub) { public static Expr createOne(Expr sub) { return (ExprUnary) ExprUnary.Op.ONE.make(Pos.UNKNOWN, sub); } + public static Expr createSomeOf(Expr sub) { + return (ExprUnary) ExprUnary.Op.SOMEOF.make(Pos.UNKNOWN, sub); + } public static Expr createSet(Expr sub) { return (ExprUnary) ExprUnary.Op.SETOF.make(Pos.UNKNOWN, sub); } @@ -302,10 +305,15 @@ public static Expr createArrowStringList(List eList) { } public static Expr createArrowExprList(List eList) { assert(eList != null); - Collections.reverse(eList); - Expr o = eList.get(0); - for (Expr e: eList.subList(1,eList.size())) { - o = createArrow(e, o); + System.out.println("input " + eList); + List xList = DashUtilFcns.reverse(eList); + System.out.println("reversed: " +xList); + Expr o = xList.get(0); + if (xList.size() == 1) return o; + else { + for (Expr x: xList.subList(1,xList.size())) { + o = createArrow(x, o); + } } return o; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index c6ed195f2..7371bc129 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -14,15 +14,15 @@ public class DashErrors { // syntax errors -------------------------------------------- - public static String onlyOneStateMsg = "Model can only have one 'state' section"; + public static String onlyOneStateMsg = "Dash model can only have one 'state' section"; public static void onlyOneState(Pos o) throws Err { throw new ErrorSyntax(o,onlyOneStateMsg); } - public static String noTransMsg = "Model does not contain any transitions."; + public static String noTransMsg = "Dash Model does not contain any transitions."; public static void noTrans() throws Err { throw new ErrorSyntax(noTransMsg); } - public static String noStatesMsg = "Model must have at least one state."; + public static String noStatesMsg = "Dash model must have at least one state."; public static void noStates() throws Err { throw new ErrorSyntax(noStatesMsg); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java index b28c2098b..fef942a84 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java @@ -67,4 +67,15 @@ public static List allButLast(List ll) { if (ll.isEmpty()) return ll; else return ll.subList(0,ll.size()-1); } + // java's Collection.reverse doesn't work sometimes + public static List reverse(List ll) { + assert(!ll.isEmpty()); + //System.out.println(ll); + List x = new ArrayList(); + for (int i=ll.size();i==0;i--) { + x.add(ll.get(i-1)); + System.out.println("here"); + } + return x; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index 3baba637d..e6a0179bd 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -35,12 +35,7 @@ public class AddSpaceSignatures { public static void addSpaceSignatures(DashModule d) { // abstract sig Statelabel {} d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); - // Root - //if (d.hasConcurrency() || d.getImmChildren(d.getRootName()).isEmpty()) - d.alloyString += d.addExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); - //else - //d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); - //System.out.println(d.getRootName()); + d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); recurseCreateStateSpaceSigs(d, d.getRootName()); d.alloyString += "\n"; @@ -97,12 +92,15 @@ public static void addSpaceSignatures(DashModule d) { private static void recurseCreateStateSpaceSigs(DashModule d, String parent) { for (String child: d.getImmChildren(parent)) { //System.out.println(translateFQN(child)+" "+translateFQN(parent)); - if (d.isLeaf(child) || d.isAnd(child)) d.alloyString += d.addOneExtendsSigSimple(translateFQN(child),translateFQN(parent)); - else + if (d.isLeaf(child)) d.alloyString += d.addOneExtendsSigSimple(translateFQN(child),translateFQN(parent)); + else { //if (d.isAnd(parent)) //d.alloyString += d.addExtendsSigSimple(translateFQN(child), translateFQN(parent)); //else - d.alloyString += d.addAbstractExtendsSigSimple(translateFQN(child), translateFQN(parent)); + String x = d.addAbstractExtendsSigSimple(translateFQN(child), translateFQN(parent)); + d.alloyString += x; + //System.out.println("HERE" + x); + } if (!d.isLeaf(child)) recurseCreateStateSpaceSigs(d,child); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 967b1473c..dfa1f2cd3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -140,7 +140,7 @@ public static void addTransPost(DashModule d, String tfqn) { Expr c2; for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { - q = createIntersect(allInternalEventsVar(), curEvents(i)); + q = createRangeRes(curEvents(i), allInternalEventsVar()); if (ev != null && ev.getParamValues().size() == i) rhs = createUnion(translateDashRefToArrow(ev), q); else rhs = q; case2.add(createEquals( @@ -253,7 +253,7 @@ private static Expr createTestIfNextStableCall(DashModule d, String tfqn) { else { DashErrors.createTestIfNextStableCallMultipleScopesAtSameLevel(); return null; } if (d.hasEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) args.add(translateDashRefToArrow(ev)); - else args.add(createNone()); + else args.add(createNoneArrow(i)); } } return createPredCall(testIfNextStableName,args); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 0e8f357d3..f1f284a67 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -31,7 +31,8 @@ public class AddTransPre { // -------------------------------------------------------------------------------------- /* pred pre_t1[s:Snapshot,pparam0:Param0, ...] { - src_state_t1 in .s.conf + src_state_t1 in .s.conf is not correct!!! + src_staet_t1 & .s.conf != none orthogonal to any scopes uses guard_cond_t1 [s] s.stable = True => @@ -51,9 +52,13 @@ public static void addTransPre(DashModule d, String tfqn) { List body = new ArrayList(); String tout = translateFQN(tfqn); - // p3 -> p2 -> p1 -> src in s.confVar(i) + // p3 -> p2 -> p1 -> src & s.confVar(i) != none // src does not have to be a basic state - body.add(createIn(translateDashRefToArrow(d.getTransSrc(tfqn)),curConf(prs.size()))); + body.add( + createSomeOf( + createIntersect( + translateDashRefToArrow(d.getTransSrc(tfqn)), + curConf(prs.size())))); if (d.getTransWhen(tfqn) != null) body.add(translateExpr(d.getTransWhen(tfqn),d)); @@ -74,7 +79,7 @@ public static void addTransPre(DashModule d, String tfqn) { DashRef ev = d.getTransOn(tfqn); int sz = ev.getParamValues().size(); Expr ifBranch = createIn(translateDashRefToArrow(ev), - createIntersect( + createRangeRes( curEvents(sz), allEnvironmentalEventsVar())); Expr elseBranch = createIn(translateDashRefToArrow(ev), curEvents(sz)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index 56745a19a..58eef8578 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -17,6 +17,7 @@ import ca.uwaterloo.watform.core.DashRef; import ca.uwaterloo.watform.core.DashErrors; + // shortens the code to import these statically import static ca.uwaterloo.watform.core.DashFQN.*; import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; @@ -380,6 +381,15 @@ public static Expr translateExpr(Expr exp, DashModule d) { public static Expr bufferIndexVar(int i) { return createVar(DashStrings.bufferIndexName + i); } + // none -> none -> none + public static Expr createNoneArrow(int i) { + if (i==0) return createNone(); + else { + //System.out.println(i); + //System.out.println(Collections.nCopies(i+1,createNone())); + return createArrowExprList(Collections.nCopies(i+1,createNone())); + } + } /* public static Expr predJoinCurParams(String name, List prs) { //p2.p1.p0.s.name diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 5e78078ee..a5cb10d38 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -11,6 +11,12 @@ import java.util.Set; import java.util.Collections; import java.util.stream.Collectors; +import java.time.format.DateTimeFormatter; +import java.time.LocalDateTime; + + + + import edu.mit.csail.sdg.alloy4.Pair; import edu.mit.csail.sdg.alloy4.A4Reporter; @@ -61,8 +67,18 @@ public static enum Status { } private Status status = Status.CREATED; - // strings for statements resulting from the translation + + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + + // strings for statements resulting from the translation public String alloyString = new String(); + public String commentString = new String( + "/*\n" + + " Automatically created via translation of a Dash model to Alloy\n" + + " on "+dtf.format(now) + "\n" + + "*/\n\n" + ); // the open statements added for Dash translation to Alloy // go at the beginning of the model so these are separate from the others private String opens = new String(); @@ -134,7 +150,7 @@ public String toStringRegular() { return s; } public String toStringAlloy() { - String s = ""; + String s = new String(commentString); /* if (rootStartLine != null) { s += "Path " + getFilePath() +"\n"; diff --git a/org.alloytools.alloy.dash/src/main/resources/nothing.txt b/org.alloytools.alloy.dash/src/main/resources/nothing.txt new file mode 100644 index 000000000..230ef40ea --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/resources/nothing.txt @@ -0,0 +1 @@ +Something here so org.alloytools.alloy.dash/src/main/resources is not empty. \ No newline at end of file From 5dada10c8bc8ace1d02a73044f6cf419daceb3e0 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 17 May 2023 10:55:57 -0400 Subject: [PATCH 040/129] minor bug fixes --- .../watform/alloyasthelper/ExprHelper.java | 7 +- .../uwaterloo/watform/core/DashStrings.java | 120 ++++++++++-------- .../uwaterloo/watform/core/DashUtilFcns.java | 7 +- .../watform/dashtoalloy/AddTcmcFact.java | 4 +- .../watform/dashtoalloy/AddTracesFact.java | 6 +- .../AddTransIsEnabledAfterStep.java | 8 +- .../watform/dashtoalloy/AddTransPre.java | 3 +- .../uwaterloo/watform/parser/DashModule.java | 2 +- xt.sh | 3 + 9 files changed, 88 insertions(+), 72 deletions(-) create mode 100755 xt.sh diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index d7b7a3941..52e6648a8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -304,10 +304,11 @@ public static Expr createArrowStringList(List eList) { return o; } public static Expr createArrowExprList(List eList) { - assert(eList != null); - System.out.println("input " + eList); + assert(!eList.isEmpty()); + //System.out.println("input " + eList); List xList = DashUtilFcns.reverse(eList); - System.out.println("reversed: " +xList); + //assert(!xList.isEmpty()); + //System.out.println("reversed: " +xList); Expr o = xList.get(0); if (xList.size() == 1) return o; else { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 100852044..60aaedf5e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -21,37 +21,37 @@ public class DashStrings { public static String falseName = "boolean/False"; public static String noneName = "none"; public static String intName = "int"; - public static String utilBooleanName = "util/boolean"; - public static String utilTcmcPathName = "util/tcmc_path"; - public static String utilOrderingName = "util/ordering"; - public static String utilBufferName = "util/buffer"; public static String sigName = "sig"; public static String predName = "pred"; public static String factName = "fact"; - public static String orderingFirstName = "first"; - public static String orderingNextName = "next"; - public static String orderingLastName = "last"; + public static String thisName = "this"; + + + // standard modules + public static String utilBooleanName = "util/boolean"; + + //public static String utilOrderingName = "util/ordering"; + public static String utilTracesName = "util/traces"; + public static String tracesFirstName = "first"; + public static String tracesNextName = "next"; + public static String tracesLastName = "last"; + + public static String utilBufferName = "util/buffer"; + public static String utilTcmcPathName = "util/tcmc_path"; + public static String tcmcKsSigmaName = "tcmc/ks_sigma"; + public static String tcmcKsS0Name = "tcmc/ks_s0"; + // Dash input keywords // used for printing: parts of Dash syntax // must be in sync with Dash-cup-symbols.txt public static String stateName = "state"; public static String concName = "conc"; public static String defaultName = "default"; - public static String eventName = "event"; public static String envName = "env"; public static String bufName = "buf"; - - // init is a reserved word in Dash - public static String initFactName = "initial"; - public static String electrumInitName = "init"; - public static String invName = "inv"; - public static String actionName = "action"; - public static String conditionName = "condition"; - public static String initName = "init"; - public static String transName = "trans"; public static String fromName = "from"; public static String onName = "on"; @@ -59,56 +59,67 @@ public class DashStrings { public static String doName = "do"; public static String gotoName = "goto"; public static String sendName = "send"; - public static String SLASH = "/"; - public static String PRIME = "'"; - + public static String invName = "inv"; + public static String actionName = "action"; + public static String conditionName = "condition"; + public static String initName = "init"; + // user must be aware of this name + public static String bufferIndexName = "bufIdx"; + + // init is a reserved word in Dash + public static String initFactName = "dsh_initial"; + public static String electrumInitName = "dsh_init"; // predicate names - public static String smallStepName = "small_step"; - public static String stableName = "stable"; - public static String equalsName = "equals"; - public static String isEnabled = "isEnabled"; - public static String tracesFactName = "traces_fact"; - public static String electrumFactName = "electrum_fact"; - public static String tcmcFactName = "tcmc_fact"; - public static String ksSigmaName = "tcmc/ks_sigma"; - public static String ksS0Name = "tcmc/ks_s0"; - - // sig/field names - public static String snapshotName = "Snapshot"; - public static String confName = "conf"; - public static String scopesUsedName = "scopesUsed"; - - public static String stateLabelName = "States"; + public static String smallStepName = "dsh_small_step"; + public static String stableName = "dsh_stable"; + //public static String equalsName = "equals"; + public static String isEnabled = "dsh_isEnabled"; + public static String tracesFactName = "dsh_traces_fact"; + public static String electrumFactName = "dsh_electrum_fact"; + public static String tcmcFactName = "dsh_tcmc_fact"; + + + /* names used in Dash translation */ + // sig names + public static String snapshotName = "DshSnapshot"; + public static String allEventsName = "DshEvents"; + public static String allEnvironmentalEventsName = "DshEnvEvents"; + public static String allInternalEventsName = "DshIntEvents"; + public static String variablesName = "DshVars"; + public static String stateLabelName = "DshStates"; //public static String systemStateName = "SystemState"; //public static String transitionLabelName = "TransitionLabel"; - public static String identifierName = "Ids"; - // how to name parameter variables - public static String pName = "p"; - public static String eventsName = "events"; - public static String allEventsName = "Events"; - public static String allEnvironmentalEventsName = "EnvEvents"; - public static String allInternalEventsName = "IntEvent"; - public static String variablesName = "Vars"; + public static String identifierName = "DshIds"; + public static String bufferName = "DshBuffer"; + // field names + public static String confName = "dsh_conf"; + public static String scopesUsedName = "dsh_sc_used"; + public static String eventsName = "dsh_events"; + + // predicate names + public static String tName = "dsh_t"; public static String preName = "_pre"; public static String postName = "_post"; public static String semanticsName = "_semantics"; - public static String testIfNextStableName = "testIfNextStable"; + public static String testIfNextStableName = "dsh_testIfNextStable"; public static String enabledAfterStepName = "_enabledAfterStep"; - public static String tName = "t"; - public static String genEventName = "genEvs"; - public static String scopeName = "scp"; - public static String bufferName = "buffer"; - public static String bufferIndexName = "bufIdx"; - - public static String thisName = "this"; - - public static String tracesName = "traces"; + // variable/parameter names + // how to name parameter variables public static String curName = "s"; public static String nextName = "sn"; + public static String pName = "p"; + public static String genEventName = "dsh_genEvs"; + public static String scopeName = "dsh_scp"; + + // strings used internally + public static String processRef = "$$PROCESSREF$$"; + public static String SLASH = "/"; + public static String PRIME = "'"; + public static String prime(String a) { return a+"'"; }; @@ -132,7 +143,6 @@ public static enum DefKind { NOTDEFAULT } - public static String processRef = "$$PROCESSREF$$"; public static boolean hasPrime(String s) { return (s.substring(s.length()-1, s.length()).equals(PRIME)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java index fef942a84..8a27e9259 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java @@ -70,12 +70,11 @@ public static List allButLast(List ll) { // java's Collection.reverse doesn't work sometimes public static List reverse(List ll) { assert(!ll.isEmpty()); - //System.out.println(ll); List x = new ArrayList(); - for (int i=ll.size();i==0;i--) { - x.add(ll.get(i-1)); - System.out.println("here"); + for (int i=ll.size()-1;i>=0;i--) { + x.add(ll.get(i)); } + assert(x.size() == ll.size()); return x; } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java index 7228a8027..8cfbb892e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java @@ -60,7 +60,7 @@ public static void addTcmcFact(DashModule d) { createAll( decls, createIff( - createIn(curVar(), createVar(ksS0Name)), + createIn(curVar(), createVar(tcmcKsS0Name)), createPredCall(initFactName,args)))); body.add( @@ -69,7 +69,7 @@ public static void addTcmcFact(DashModule d) { createIff( createIn( createArrow(curVar(), nextVar()), - createVar(ksSigmaName)), + createVar(tcmcKsSigmaName)), createPredCall(smallStepName, curNextVars())))); d.alloyString += d.addFactSimple(tcmcFactName, body); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTracesFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTracesFact.java index c5378de68..07d7119f7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTracesFact.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTracesFact.java @@ -48,9 +48,9 @@ public static void addTracesFact(DashModule d) { assert(DashOptions.isTraces); List body = new ArrayList(); - Expr snapShotFirst = createVar(snapshotName + "/" + orderingFirstName); - Expr snapShotLast = createVar(snapshotName + "/" + orderingLastName); - Expr snapShotNext = createVar(snapshotName + "/" + orderingNextName); + Expr snapShotFirst = createVar(snapshotName + "/" + tracesFirstName); + Expr snapShotLast = createVar(snapshotName + "/" + tracesLastName); + Expr snapShotNext = createVar(snapshotName + "/" + tracesNextName); List args = new ArrayList(); args.add(snapShotFirst); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java index 3eca0a077..8f11836f3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -43,7 +43,7 @@ public class AddTransIsEnabledAfterStep { ... ] { // many of these may depend on param values - src_state_t1 in s'.confi // where i is depth of src_state, + some (src_state_t1 & s'.confi) // where i is depth of src_state, guard_cond_t1[s'] (s.stable = True) => o1: forall i. not(t1_nonOrthScopei in scopesi) @@ -75,7 +75,11 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { // p3 -> p2 -> p1 -> src in s'.confVar(i) // src does not have to be a basic state - body.add(createIn(translateDashRefToArrow(d.getTransSrc(tfqn)),nextConf(prs.size()))); + body.add( + createSomeOf( + createIntersect( + translateDashRefToArrow(d.getTransSrc(tfqn)), + nextConf(prs.size())))); // primed guard condition is true // TODO diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index f1f284a67..4995f1041 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -31,8 +31,7 @@ public class AddTransPre { // -------------------------------------------------------------------------------------- /* pred pre_t1[s:Snapshot,pparam0:Param0, ...] { - src_state_t1 in .s.conf is not correct!!! - src_staet_t1 & .s.conf != none + some (src_staet_t1 & .s.conf) orthogonal to any scopes uses guard_cond_t1 [s] s.stable = True => diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index a5cb10d38..fa7bdeb22 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -241,7 +241,7 @@ public void importModules(List bufElements, List bufNames) { if (DashOptions.isTcmc) opens += this.addOpenSimple(DashStrings.utilTcmcPathName, Arrays.asList(DashStrings.snapshotName), noAlias); else if (DashOptions.isTraces) - opens += this.addOpenSimple(DashStrings.utilOrderingName, Arrays.asList(DashStrings.snapshotName),DashStrings.snapshotName); + opens += this.addOpenSimple(DashStrings.utilTracesName, Arrays.asList(DashStrings.snapshotName),DashStrings.snapshotName); // add the open statements for the buffers if (bufElements != null ) for (int i = 0; i < bufElements.size(); i++) diff --git a/xt.sh b/xt.sh new file mode 100755 index 000000000..67424d702 --- /dev/null +++ b/xt.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./gradlew build -x test \ No newline at end of file From 4507e855c8185f827af03c2ff290716ce75a54cf Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 19 May 2023 11:11:30 -0400 Subject: [PATCH 041/129] small bug fixes; removed action/condition syntax --- .../parser/Dash-cup-grammar.txt | 8 +- .../parser/Dash-cup-symbols.txt | 4 +- org.alloytools.alloy.dash/parser/Dash.cup | 12 +- .../watform/alloyasthelper/ExprHelper.java | 4 + .../watform/alloyasthelper/ExprToString.java | 8 +- .../ca/uwaterloo/watform/ast/DashAction.java | 2 + .../uwaterloo/watform/ast/DashCondition.java | 2 + .../ca/uwaterloo/watform/core/DashErrors.java | 3 + .../uwaterloo/watform/core/DashStrings.java | 6 +- .../dashtoalloy/AddSnapshotSignature.java | 10 +- .../AddTransIsEnabledAfterStep.java | 6 +- .../watform/dashtoalloy/AddTransPost.java | 8 +- .../uwaterloo/watform/dashtoalloy/Common.java | 9 +- .../uwaterloo/watform/parser/DashModule.java | 4 +- .../uwaterloo/watform/parser/StateTable.java | 11 ++ .../uwaterloo/watform/parser/SymbolTable.java | 109 ------------------ .../ca/uwaterloo/watform/parser/VarTable.java | 11 +- 17 files changed, 71 insertions(+), 146 deletions(-) delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/SymbolTable.java diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt index cfd849122..d507563c9 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -267,12 +267,12 @@ StateItem ::= INVARIANT:o Name:n Super:v {: RESULT = new DashInv(o, n.label, v); :}; // action -StateItem ::= ACTION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE - {: RESULT = new DashAction(o, n.label, e); :}; +//StateItem ::= ACTION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE +// {: RESULT = new DashAction(o, n.label, e); :}; // condition -StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE - {: RESULT = new DashCondition(o, n.label, e); :}; +//StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE +// {: RESULT = new DashCondition(o, n.label, e); :}; // transition StateItem ::= TRANS:o Name:n LBRACE TransItemList:c RBRACE diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt b/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt index 531514f61..784ff979d 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt @@ -14,8 +14,8 @@ ch.put(DashSym.INIT, "init"); ch.put(DashSym.INVARIANT, "invariant"); - ch.put(DashSym.ACTION, "action"); - ch.put(DashSym.CONDITION, "condition"); + //ch.put(DashSym.ACTION, "action"); + //ch.put(DashSym.CONDITION, "condition"); ch.put(DashSym.TRANS, "trans"); diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index 2a0e0e09f..1a414894c 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -279,8 +279,8 @@ parser code {: ch.put(DashSym.INIT, "init"); ch.put(DashSym.INVARIANT, "invariant"); - ch.put(DashSym.ACTION, "action"); - ch.put(DashSym.CONDITION, "condition"); + //ch.put(DashSym.ACTION, "action"); + //ch.put(DashSym.CONDITION, "condition"); ch.put(DashSym.TRANS, "trans"); @@ -1521,12 +1521,12 @@ StateItem ::= INVARIANT:o Name:n Super:v {: RESULT = new DashInv(o, n.label, v); :}; // action -StateItem ::= ACTION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE - {: RESULT = new DashAction(o, n.label, e); :}; +//StateItem ::= ACTION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE +// {: RESULT = new DashAction(o, n.label, e); :}; // condition -StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE - {: RESULT = new DashCondition(o, n.label, e); :}; +//StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE +// {: RESULT = new DashCondition(o, n.label, e); :}; // transition StateItem ::= TRANS:o Name:n LBRACE TransItemList:c RBRACE diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 52e6648a8..112ee04a3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -37,6 +37,10 @@ public static boolean isExprBinary(Expr e) { public static boolean isExprUnary(Expr e) { return (e instanceof ExprUnary); } + public static boolean isExprCard(Expr e) { + return ((e instanceof ExprUnary) && ((ExprUnary) e).op.equals(ExprUnary.Op.CARDINALITY)); + } + public static boolean isExprJoin(Expr e) { return ((e instanceof ExprBinary) && ((ExprBinary) e).op.equals(ExprBinary.Op.JOIN)); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index 2894248b4..e9ab6efd1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -150,11 +150,11 @@ private void ExprBinaryToOut(ExprBinary expr) { out.print(s); } else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { - out.print("(seq "); + out.print("seq "); out.beginC(2); ExprToOut(expr.right); out.end(); - out.print(")"); + //out.print(")"); } else { out.beginI(2); addBracketsIfNeeded(getLeft(expr)); @@ -202,12 +202,12 @@ else if ( isBinary(expr.right) || isBinary(expr.left) ) { } private void addBracketsIfNeeded(Expr expr) { - if (!isExprVar(expr)) { + if (!(isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr) ))) { out.beginC(2); out.print("("); } ExprToOut(expr); - if (!isExprVar(expr)) { + if (!(isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr) ) )) { out.print(")"); out.end(); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java index e1d8a5eee..288bcb32e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java @@ -3,6 +3,8 @@ we do not know what order items within a state will be parsed in. */ +// Not currently used + package ca.uwaterloo.watform.ast; import ca.uwaterloo.watform.core.DashStrings; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java index 837eb0d1e..34f094f12 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java @@ -3,6 +3,8 @@ we do not know what order items within a state will be parsed in. */ +// Not used now + package ca.uwaterloo.watform.ast; import ca.uwaterloo.watform.core.DashStrings; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 7371bc129..4782a6351 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -247,4 +247,7 @@ public static String UnsupportedExpr(String s1, Expr e) { public static void bufferIndexDoesNotMatchBufferNumber() { throw new ErrorFatal("bufferIndexDoesNotMatchBufferNumber"); } + public static void doesNotExist(String fcnName, String m) { + throw new ErrorFatal("fcn "+fcnName+" arg "+m+"not in table"); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 60aaedf5e..111a31d49 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -100,11 +100,11 @@ public class DashStrings { public static String eventsName = "dsh_events"; // predicate names - public static String tName = "dsh_t"; + //public static String tName = "dsh_t"; public static String preName = "_pre"; public static String postName = "_post"; - public static String semanticsName = "_semantics"; - public static String testIfNextStableName = "dsh_testIfNextStable"; + //public static String semanticsName = "_semantics"; + public static String testIfNextStableName = "_testIfNextStable"; public static String enabledAfterStepName = "_enabledAfterStep"; // variable/parameter names diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 47ca795c8..b08ab14eb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -91,7 +91,7 @@ public static void addSnapshotSignature(DashModule d){ .filter(i -> d.getVarBufferParams(i).size() == 0 && isExprVar(d.getVarType(i))) .collect(Collectors.toList()); for (String v: allvfqnsNoParamsSimpleTyp) - d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar) d.getVarType(v)) ); + d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar) translateExpr(d.getVarType(v),d)) ); // vfqns with no params and arrow type (A -> B) // becomes sig A { var vfqn: B } @@ -109,7 +109,7 @@ public static void addSnapshotSignature(DashModule d){ if (!allvfqnsNoParamsArrowTyp.isEmpty()) { decls = new ArrayList(); for (String v: allvfqnsNoParamsArrowTyp) - decls.add(DeclExt.newVarDeclExt(translateFQN(v), d.getVarType(v))); + decls.add(DeclExt.newVarDeclExt(translateFQN(v), translateExpr(d.getVarType(v),d))); d.alloyString += d.addOneSigWithDeclsSimple(DashStrings.variablesName, decls); } @@ -135,10 +135,10 @@ public static void addSnapshotSignature(DashModule d){ decls = new ArrayList(); for (String v: allvfqnsWithThisFirstParam) { if (d.getVarBufferParams(v).size() == 1) { - decls.add(DeclExt.newVarDeclExt(v, d.getVarType(v))); + decls.add(DeclExt.newVarDeclExt(v, translateExpr(d.getVarType(v),d))); } else { plist = createVarList(d.getVarBufferParams(v).subList(1, d.getVarBufferParams(v).size()-1)); - plist.add(d.getVarType(v)); + plist.add(translateExpr(d.getVarType(v),d)); decls.add(DeclExt.newVarDeclExt(translateFQN(v),createArrowExprList(plist))); } } @@ -215,7 +215,7 @@ public static void addSnapshotSignature(DashModule d){ List typlist; for (String vfqn: d.getAllVarNames()) { typlist = createVarList(d.getVarBufferParams(vfqn)); // could be empty - typlist.add(d.getVarType(vfqn)); + typlist.add(translateExpr(d.getVarType(vfqn),d)); if (typlist.size() > 1 ) decls.add((Decl) new DeclExt( translateFQN(vfqn), diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java index 8f11836f3..b6ca9f74c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -69,7 +69,7 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { for (int i=0; i<= d.getMaxDepthParams(); i++) { decls.add(scopeDecl(i)); if (d.hasEventsAti(i)) { - decls.add(genEventsDecl(i)); + decls.add(genEventDecl(i)); } } @@ -155,12 +155,14 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { d.alloyString += d.addPredSimple(tout+DashStrings.enabledAfterStepName,decls,body); } + /* public static Decl genEventsDecl(int i) { return (Decl) new DeclExt(DashStrings.genEventName + i, DashStrings.allEventsName); } + public static Expr genEventsVar(int i) { return createVar(DashStrings.genEventName + i); } - + */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index dfa1f2cd3..25186e66a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -124,7 +124,7 @@ public static void addTransPost(DashModule d, String tfqn) { for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) rhs = translateDashRefToArrow(ev); - else rhs = createNone(); + else rhs = createNoneArrow(i); case1.add(createEquals( createRangeRes(nextEvents(i),allInternalEventsVar()), rhs)); @@ -160,7 +160,7 @@ public static void addTransPost(DashModule d, String tfqn) { for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) rhs1 = translateDashRefToArrow(ev); - else rhs1 = createNone(); + else rhs1 = createNoneArrow(i); if (d.hasEnvironmentalEvents()) case3.add(createAnd( createEquals( @@ -218,9 +218,7 @@ public static void addTransPost(DashModule d, String tfqn) { createITE(curStableTrue(), c3, c4)))); - else - body.add( - createAnd(nextStableTrue(), c1)); + d.alloyString += d.addPredSimple(tout+postName,curNextParamsDecls(prs),body); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index 58eef8578..3e1e21b7c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -79,10 +79,15 @@ public static List curNextParamsDecls(List prs) { } public static Decl genEventDecl(int i) { - Listcop = Collections.nCopies(i,DashStrings.identifierName); - return (Decl) new DeclExt( + if (i==0) return (Decl) new DeclExt( + DashStrings.genEventName + i, + createVar(DashStrings.allEventsName)); + else { + Listcop = Collections.nCopies(i,DashStrings.identifierName); + return (Decl) new DeclExt( DashStrings.genEventName + i, createArrowStringList(DashUtilFcns.newListWith(cop, DashStrings.allEventsName))); + } } public static Decl scopeDecl(int i) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index fa7bdeb22..8f2a281e9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -46,7 +46,7 @@ public class DashModule extends CompModuleHelper { // derived during resolveAllDash phase private int maxDepthParams = 0; private boolean[] transAtThisParamDepth; - private SymbolTable symbolTable; + //private SymbolTable symbolTable; private StateTable stateTable = new StateTable(); private TransTable transTable = new TransTable(); private EventTable eventTable = new EventTable(); @@ -565,7 +565,7 @@ public void resolveAllDash(A4Reporter rep) { stateTable.resolve(getRootName(), varTable); transTable.resolve(stateTable, eventTable, varTable); - + varTable.resolve(); maxDepthParams = stateTable.getMaxDepthParams(); transAtThisParamDepth = transTable.transAtThisParamDepth(maxDepthParams); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 5278c8d8c..2badccdea 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -404,6 +404,17 @@ public void resolve(String root, VarTable vt) { sfqn, getParams(sfqn))) .collect(Collectors.toList())); + // have to resolve variables here because need + // other parameters to resolveExpr + for (String vfqn: vt.getVarsOfState(sfqn)) { + vt.setVarType(vfqn, + vt.resolveExpr( + "var", + vt.getVarType(vfqn), + getRegion(sfqn), + sfqn, + getParams(sfqn))); + } } isResolved = true; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/SymbolTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/SymbolTable.java deleted file mode 100644 index 8c5dafc43..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/SymbolTable.java +++ /dev/null @@ -1,109 +0,0 @@ -package ca.uwaterloo.watform.parser; - -import java.util.ArrayList; -import java.util.HashMap; - -import edu.mit.csail.sdg.ast.Expr; -import ca.uwaterloo.watform.core.DashStrings; - -public class SymbolTable { - - private HashMap table; - private int NOTBUFFER = -1; - - public class DynSymbol { - - private int index; // used for buffers - // tmp - private String typ; - // private DashExpr exp; // type expression - private DashStrings.IntEnvKind kind; - - // for variables - public DynSymbol(Expr e, DashStrings.IntEnvKind k) { - this.index = NOTBUFFER; - // tmp - this.typ = null; - this.kind = k; - - } - // for buffers - public DynSymbol(int idx, DashStrings.IntEnvKind k, String elements) { - this.index = idx; - // temporary - this.typ = elements; - // this.typ = DashExpr(createArrow(DashStrings.bufferIndexName+idx, elements)); - this.kind = k; - - } - } - public SymbolTable() { - this.table = new HashMap(); - } - /* - public void addDeclaredVar(String n, List prs, Expr e, EventVarKind k) { - if (!table.keys().contains(n)) { - table.put(n,DynVar(i,prs,e,k)) - } else { - if (table.get(n).declared) // err declared twice - else table.get(n) = DynVar(i,prs,e,k); - } - } - */ - public void addDeclaredBuffer(String n, int idx, DashStrings.IntEnvKind k, String elements) { - if (!table.keySet().contains(n)) { - table.put(n,new DynSymbol(idx,k,elements)); - } else { - if (table.get(n) != null) { ; } // err declared twice - else table.put(n, new DynSymbol(idx,k,elements)); - } - } - /* - public void addUsedVar(String n) { - if ( !(table.keys().contains(n))) table.put(n,null); - } - public void addUsedBuffer(String n) { - if ( !(table.keys().contains(n))) table.put(n,null); - } - public void resolveAll() { - // check for any vars used but not declared - for (e:table.keys()) { - if (table.get(e) == null) { - // err used but not declared - } - } - } - */ - /* - creates the fully qualified name - uses snapshot or not for Electrum - joins with params - */ - /* - public AlloyExpr createAlloyExprVar(boolean primed) { - String n = pathHere+"/"+name; - if (DashOptions.isElectrum() && primed) { - n = DashStrings.prime(n) ; - } - ExprVar e = createVar(n) - if (!DashOptions.isElectrum()) { - if (!primed) { - s = DashStrings.sCur; - e = AlloyExprHelper.createExprJoin(s,e) - } else { - s = DashStrings.sNext; - e = AlloyExprHelper.createExprJoin(s,e) - } - } - // turn all the params into vars - return AlloyExprHelper.createExprJoin (p0.p1.p2.e) - } - - // used for snapshot declarations - // probably will have to return exp and then convert - public Expr createAlloyTyp(symboltable) { - // does it have to convert anything?? - return typ.convertToAlloy(symboltable) - } - */ -} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index ff4f7ca25..9164a5881 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -51,8 +51,15 @@ public String toString() { s += "typ: "+typ.toString() + "\n"; return s; } + public void setType(Expr typ) { + this.typ = typ; + } } + public void setVarType(String vfqn, Expr typ) { + if (varTable.containsKey(vfqn)) varTable.get(vfqn).setType(typ); + else { DashErrors.doesNotExist("setVarType", vfqn); } + } public String toString() { String s = new String("VAR TABLE\n"); for (String k:varTable.keySet()) { @@ -74,8 +81,8 @@ public Boolean addVar(String vfqn, IntEnvKind k, List prms, Expr t) { if (hasPrime(vfqn)) { DashErrors.nameShouldNotBePrimed(vfqn); return false; } else { varTable.put(vfqn, new VarElement(k,prms, t)); return true; } } - public void resolveAllVarTable() { - // TODO + public void resolve() { + //anything? } public List getAllVarNames() { return new ArrayList(varTable.keySet()); From 84de1214d7c283c940bd6eb02a60376cbb60fb5f Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 25 May 2023 20:53:49 -0400 Subject: [PATCH 042/129] add more in init; indexed parameters in case nested states use same parameter set --- .../watform/alloyasthelper/ExprHelper.java | 2 + .../ca/uwaterloo/watform/ast/DashState.java | 23 +-- .../ca/uwaterloo/watform/ast/DashTrans.java | 4 +- .../ca/uwaterloo/watform/core/DashErrors.java | 3 + .../uwaterloo/watform/core/DashUtilFcns.java | 7 + .../watform/dashtoalloy/AddInit.java | 41 +++++- .../uwaterloo/watform/dashtoalloy/AddInv.java | 6 +- .../watform/dashtoalloy/AddSmallStep.java | 12 +- .../dashtoalloy/AddSnapshotSignature.java | 3 +- .../dashtoalloy/AddSpaceSignatures.java | 2 +- .../dashtoalloy/AddTestIfNextStable.java | 4 + .../watform/dashtoalloy/AddTrans.java | 10 +- .../AddTransIsEnabledAfterStep.java | 11 +- .../watform/dashtoalloy/AddTransPost.java | 64 +++++--- .../watform/dashtoalloy/AddTransPre.java | 6 +- .../uwaterloo/watform/dashtoalloy/Common.java | 58 +++++--- .../uwaterloo/watform/parser/DashModule.java | 23 ++- .../uwaterloo/watform/parser/EventTable.java | 26 +++- .../uwaterloo/watform/parser/StateTable.java | 49 +++++-- .../uwaterloo/watform/parser/TransTable.java | 32 +++- .../ca/uwaterloo/watform/parser/VarTable.java | 76 ++++++---- .../alloytools/alloy/dash/DashStateTests.java | 137 +++++++++++------- .../test/resources/pass/overall1-traces.als | 60 -------- .../src/test/resources/pass/overall13.dsh | 14 ++ .../src/test/resources/pass/overall3.dsh | 4 +- .../test/resources/pass/overall4-traces.als | 66 --------- .../src/test/resources/pass/overall6.dsh | 2 +- .../test/resources/pass/overall7-traces.als | 114 --------------- .../test/resources/pass/overall9-traces.als | 71 --------- 29 files changed, 420 insertions(+), 510 deletions(-) delete mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall1-traces.als create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall13.dsh delete mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall4-traces.als delete mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall7-traces.als delete mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/overall9-traces.als diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 112ee04a3..3b25529fb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -139,6 +139,8 @@ public static List createVarList(String prefix, List vList) { } return retList; } + + // to avoid the need to cast every ExprVar to an Expr public static List createExprVarList(List vList) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index b2bf70275..f4d9a3980 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -119,7 +119,7 @@ public static List noSubstates() { * check for errors in the state hierarchy * and put all states in the state table */ - public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, List params, List ances) { + public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, List params, List paramsIdx, List ances) { if (DashFQN.isFQN(name)) DashErrors.stateNameCantBeFQN(pos, name); String sfqn = DashFQN.fqn(ances,name); //System.out.println("Resolving state "+sfqn); @@ -177,7 +177,12 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li List newAnces = new ArrayList(ances); newAnces.add(name); List newParams = new ArrayList(params); - if (param != null) newParams.add(param); + List newParamsIdx = new ArrayList(paramsIdx); + if (param != null) { + newParams.add(param); + int idx = st.addToParamsList(param); + newParamsIdx.add(idx); + } List substatesList = new ArrayList(); if (items != null) @@ -190,7 +195,7 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li if (substatesList.isEmpty() ) { - if (!st.add(sfqn, kind, param, newParams, def, DashFQN.fqn(ances), new ArrayList(), + if (!st.add(sfqn, kind, param, newParams, newParamsIdx, def, DashFQN.fqn(ances), new ArrayList(), invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; } else { @@ -204,11 +209,11 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li DashErrors.dupSiblingNames(DashUtilFcns.strCommaList(dups.stream().collect(Collectors.toList()))); // add this state to the table - if (!st.add(sfqn,kind, param, newParams,def, DashFQN.fqn(ances), childFQNs, + if (!st.add(sfqn,kind, param, newParams,newParamsIdx, def, DashFQN.fqn(ances), childFQNs, invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; // add all substates to the table - for (DashState s: substatesList) s.resolve(st, tt, et, vt, newParams, newAnces); + for (DashState s: substatesList) s.resolve(st, tt, et, vt, newParams, newParamsIdx, newAnces); // make sure defaults are correct // if there's only one child it is automatically the default @@ -264,7 +269,7 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li for (String x: e.getNames()) { if (DashFQN.isFQN(x)) DashErrors.eventNameCantBeFQN(e.getPos(), x); String xfqn = DashFQN.fqn(sfqn,x); - if (!et.add(xfqn,k, newParams)) DashErrors.duplicateEventName(e.getPos(),x); + if (!et.add(xfqn,k, newParams, newParamsIdx)) DashErrors.duplicateEventName(e.getPos(),x); } } xItems.removeAll(eventDeclsList); @@ -284,7 +289,7 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li for (String x: v.getNames()) { if (DashFQN.isFQN(x)) DashErrors.varNameCantBeFQN(v.getPos(), x); String xfqn = DashFQN.fqn(sfqn,x); - if (!vt.addVar(xfqn,k, newParams, t)) DashErrors.duplicateVarName(v.getPos(),x); + if (!vt.addVar(xfqn,k, newParams, newParamsIdx, t)) DashErrors.duplicateVarName(v.getPos(),x); } } xItems.removeAll(varDeclsList); @@ -305,7 +310,7 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li for (String x: b.getNames()) { if (DashFQN.isFQN(x)) DashErrors.bufferNameCantBeFQN(b.getPos(), x); String xfqn = DashFQN.fqn(sfqn,x); - if (!vt.addBuffer(xfqn,k, newParams, el, idx)) DashErrors.duplicateBufferName(b.getPos(),x); + if (!vt.addBuffer(xfqn,k, newParams, newParamsIdx, el, idx)) DashErrors.duplicateBufferName(b.getPos(),x); idx++; } if (idx != b.getEndIndex()+1) DashErrors.bufferIndexDoesNotMatchBufferNumber(); @@ -322,7 +327,7 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li .collect(Collectors.toList()); for (DashTrans t:transList) { //System.out.println("newAnces: " +newAnces); - t.resolve(tt, newParams, newAnces); + t.resolve(tt, newParams, newParamsIdx, newAnces); } xItems.removeAll(transList); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java index c1bfe8cdd..cfa2e6e9e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java @@ -36,7 +36,7 @@ public String toString() { } return s; } - public void resolve(TransTable tt, List params, List ances) { + public void resolve(TransTable tt, List params, List paramsIdx, List ances) { if (DashFQN.isFQN(name)) DashErrors.transNameCantBeFQN(pos, name); String tfqn = DashFQN.fqn(ances,name); @@ -86,7 +86,7 @@ public void resolve(TransTable tt, List params, List ances) { .collect(Collectors.toList()); xItems.removeAll(doList); - if (!tt.add(tfqn,params, fromList, onList, whenList, gotoList, sendList, doList)) DashErrors.dupTransNames(pos,name); + if (!tt.add(tfqn,params, paramsIdx, fromList, onList, whenList, gotoList, sendList, doList)) DashErrors.dupTransNames(pos,name); //System.out.println(xItems); if (!xItems.isEmpty()) DashErrors.nonEmptyTransItems(); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 4782a6351..667525b7c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -250,4 +250,7 @@ public static void bufferIndexDoesNotMatchBufferNumber() { public static void doesNotExist(String fcnName, String m) { throw new ErrorFatal("fcn "+fcnName+" arg "+m+"not in table"); } + public static void noInitialEntered(){ + throw new ErrorFatal("there are no default initial states"); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java index 8a27e9259..242e6ad94 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashUtilFcns.java @@ -77,4 +77,11 @@ public static List reverse(List ll) { assert(x.size() == ll.size()); return x; } + + public static List listOfInt(int start, int stop) { + assert(start <= stop); + List x = new ArrayList(); + for (int i=start; i <= stop; i++) x.add(i); + return x; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 6156ccf52..a5bd0a028 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.ArrayList; import java.util.Arrays; +import java.util.stream.IntStream; import edu.mit.csail.sdg.ast.Decl; //import edu.mit.csail.sdg.ast.ExprVar; @@ -12,8 +13,9 @@ import ca.uwaterloo.watform.core.DashOptions; import ca.uwaterloo.watform.core.DashStrings; -//import ca.uwaterloo.watform.core.DashUtilFcns; -//import ca.uwaterloo.watform.core.DashRef; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; // shortens the code to import these statically import static ca.uwaterloo.watform.core.DashFQN.*; @@ -35,9 +37,32 @@ public class AddInit { */ public static void addInit(DashModule d) { - List prs = d.getAllParams(); + List prs = d.getAllParamsInOrder(); List body = new ArrayList(); + // forall i. confi = default entries + List entered = d.initialEntered(); + if (entered.isEmpty()) DashErrors.noInitialEntered(); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List ent = DashRef.hasNumParams(entered,i).stream() + .map(x -> translateDashRefToArrow(x)) + .collect(Collectors.toList()); + if (!ent.isEmpty()) body.add(createEquals(curConf(i),createUnionList(ent))); + else body.add(createEquals(curConf(i), createNone())); + } + for (int i = 1; i <= d.getMaxDepthParams(); i++) { + // scopesUsedi = none + body.add(createEquals( + curScopesUsed(i), + createNone())); + // no limits on initial set of events except that they must be environmental + body.add(createIn( + curEvents(i), + allEnvironmentalEventsVar())); + } + + + // even if these are empty we need this predicate to exist for (Expr i: d.getInits()) // these may have the use of parameters in them @@ -50,9 +75,8 @@ public static void addInit(DashModule d) { if (!body.isEmpty()) { if (!prs.isEmpty()) e = createAll( - // might need to add "p" to the front of these - paramDecls(prs), - createAndFromList(body)); + paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1), prs), + createAndFromList(body)); else e = createAndFromList(body); body = new ArrayList(); body.add(e); @@ -61,7 +85,10 @@ public static void addInit(DashModule d) { if (DashOptions.isElectrum) { d.alloyString += d.addPredSimple(DashStrings.initFactName, new ArrayList(), body); } else { - d.alloyString += d.addPredSimple(DashStrings.initFactName, curParamsDecls(prs),body); + d.alloyString += d.addPredSimple( + DashStrings.initFactName, + curParamsDecls(DashUtilFcns.listOfInt(0,prs.size()-1), prs), + body); } } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java index 3a9279aa1..b1bd66cb9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java @@ -14,7 +14,7 @@ import ca.uwaterloo.watform.core.DashOptions; import ca.uwaterloo.watform.core.DashStrings; -//import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashUtilFcns; //import ca.uwaterloo.watform.core.DashRef; // shortens the code to import these statically @@ -38,7 +38,7 @@ public class AddInv { */ public static void addInv(DashModule d) { - List prs = d.getAllParams(); + List prs = d.getAllParamsInOrder(); List body = new ArrayList(); // since this is a fact, we don't need it if there are no invariants @@ -54,7 +54,7 @@ public static void addInv(DashModule d) { if (!prs.isEmpty()) e = createAll( // might need to add "p" to the front of these - paramDecls(prs), + paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1), prs), createAndFromList(body)); else e = createAndFromList(body); List decls = new ArrayList(); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java index 81ad1f1f7..67bb1bbb9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java @@ -12,7 +12,7 @@ import ca.uwaterloo.watform.core.DashOptions; import ca.uwaterloo.watform.core.DashStrings; -//import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashUtilFcns; //import ca.uwaterloo.watform.core.DashRef; // shortens the code to import these statically @@ -39,16 +39,18 @@ public class AddSmallStep { public static void addSmallStep(DashModule d) { ArrayList e = new ArrayList(); + List prs = d.getAllParamsInOrder(); + for (String tfqn: d.getAllTransNames()) { String tout = translateFQN(tfqn); // p3.p2.p1.t for parameters of this transition - if (DashOptions.isElectrum) e.add(createPredCall(tout,paramVars(d.getTransParams(tfqn)))); + if (DashOptions.isElectrum) e.add(createPredCall(tout,paramVars(d.getTransParamsIdx(tfqn), d.getTransParams(tfqn)))); // p3.p2.p1.s'.s.t for parameters of this transition - else e.add(createPredCall(tout,curNextParamVars(d.getTransParams(tfqn)))); + else e.add(createPredCall(tout,curNextParamVars(d.getTransParamsIdx(tfqn),d.getTransParams(tfqn)))); } List body = new ArrayList(); - if (d.getAllParams().isEmpty()) body.add(createOrFromList(e)); - else body.add(createSome(paramDecls(d.getAllParams()),createOrFromList(e))); + if (d.getAllParamsInOrder().isEmpty()) body.add(createOrFromList(e)); + else body.add(createSome(paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1),prs),createOrFromList(e))); //TODO add loop if all notenabled diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index b08ab14eb..30ad1197f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -123,7 +123,7 @@ public static void addSnapshotSignature(DashModule d){ List allbfqnsWithThisFirstParam; List plist; - for (String prm: d.getAllParams()) { + for (String prm: DashUtilFcns.listToSet(d.getAllParamsInOrder())) { // variables with parameters grouped with parameter allvfqnsWithThisFirstParam = allvfqns.stream() @@ -185,6 +185,7 @@ public static void addSnapshotSignature(DashModule d){ // scopesUsed0, conf0, event0 //if (d.transAtThisParamDepth(0)) + //TODO: if no concurrency, don't need scopesUsed !! decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", stateLabelName)); decls.add(DeclExt.newSetDeclExt(confName+"0", stateLabelName)); if (d.hasEvents()) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index e6a0179bd..5ba51c7f9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -55,7 +55,7 @@ public static void addSpaceSignatures(DashModule d) { if (!DashOptions.isElectrum) if (d.getMaxDepthParams() != 0) { d.alloyString += d.addAbstractSigSimple(DashStrings.identifierName); - for (String s: d.getAllParams()) + for (String s: DashUtilFcns.listToSet(d.getAllParamsInOrder())) d.alloyString += d.addExtendsSigSimple(s, DashStrings.identifierName); d.alloyString += "\n"; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java index e6adeddc4..973fb6150 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java @@ -34,10 +34,14 @@ public static void addTestIfNextStable(DashModule d) { List decls = new ArrayList(); List args = new ArrayList(); List body = new ArrayList(); + List allParams = d.getAllParamsInOrder(); if (!DashOptions.isElectrum) { decls.addAll(curNextDecls()); args.addAll(curNextVars()); } + for (int i=0; i < allParams.size(); i++) { + decls.add(paramDecl(i,allParams.get(i))); + } for (int i=0; i<= d.getMaxDepthParams(); i++) { decls.add(scopeDecl(i)); args.add(scopeVar(i)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTrans.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTrans.java index db79c20ff..1725def44 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTrans.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTrans.java @@ -45,19 +45,19 @@ public static void addTrans(DashModule d, String tfqn) { if (DashOptions.isElectrum) { // pre_transName[ p0, p1, p2] -> p2.p1.p0.pre_transName - body.add(createPredCall(tout+ preName, paramVars(prs))); + body.add(createPredCall(tout+ preName, paramVars(d.getTransParamsIdx(tfqn), d.getTransParams(tfqn)))); // p2.p1.p0.post_transName - body.add(createPredCall(tout + postName, paramVars(prs))); + body.add(createPredCall(tout + postName, paramVars(d.getTransParamsIdx(tfqn), d.getTransParams(tfqn)))); // p2.p1.p0.semantics_transName //body.add(createPredCall(tout + semanticsName, paramVars(prs))); } else { // pre_transName[s, p0, p1, p2] -> p2.p1.p0.s.pre_transName - body.add(createPredCall(tout + preName, curParamVars(prs))); + body.add(createPredCall(tout + preName, curParamVars(d.getTransParamsIdx(tfqn), d.getTransParams(tfqn)))); // p2.p1.p0.s'.s.post_transName - body.add(createPredCall(tout + postName, curNextParamVars(prs))); + body.add(createPredCall(tout + postName, curNextParamVars(d.getTransParamsIdx(tfqn), d.getTransParams(tfqn)))); // p2.p1.p0.s'.s.semantics_transName //body.add(createPredCall(tout + semanticsName, curNextParamVars(prs))); } - d.alloyString += d.addPredSimple(tout, curNextParamsDecls(prs), body); + d.alloyString += d.addPredSimple(tout, curNextParamsDecls(d.getTransParamsIdx(tfqn),d.getTransParams(tfqn)), body); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java index b6ca9f74c..7449848d6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -57,14 +57,15 @@ public class AddTransIsEnabledAfterStep { public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { String tout = translateFQN(tfqn); - List prs = d.getTransParams(tfqn); + List prsIdx = d.getTransParamsIdx(tfqn); + List prs = d.getTransParams(tfqn); List decls = new ArrayList(); List body = new ArrayList(); if (DashOptions.isElectrum) { - decls.addAll(paramDecls(prs)); + decls.addAll(paramDecls(prsIdx,prs)); } else { - decls.addAll(curNextParamsDecls(prs)); + decls.addAll(curNextParamsDecls(prsIdx,prs)); } for (int i=0; i<= d.getMaxDepthParams(); i++) { decls.add(scopeDecl(i)); @@ -73,13 +74,13 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { } } - // p3 -> p2 -> p1 -> src in s'.confVar(i) + // some (p3 -> p2 -> p1 -> src & s'.confi) // src does not have to be a basic state body.add( createSomeOf( createIntersect( translateDashRefToArrow(d.getTransSrc(tfqn)), - nextConf(prs.size())))); + nextConf(prsIdx.size())))); // primed guard condition is true // TODO diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 25186e66a..580f71e7f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -37,6 +37,8 @@ public class AddTransPost { action_t1[s,s'] testIfNextStable[s,s',t1,t1_send_ev] => { s'.stable = True + // empty scopesUsed + forall i : scopesUsedi' = none s.stable = True => { // case 1 // big step = one small step @@ -54,19 +56,23 @@ public class AddTransPost { } else { stable' = False env_vars_unchanged[s,s'] - s.table = True => { + s.stable = True => { // case 3 // first small step of the big step // only internal events are those generated by t1 forall i: eventsi' & InternalEvent = t1_send_ev (if i) // env events stay the same eventsi' & EnvironmentlEvent = eventsi & EnvironmentalEvent + // empty previous scopes used and just add this one + forall i : scopesUsedi' = scopesUsed } else { // case 4 // intermediate small step // add t1's gen event to the events // env events don't change forall i: eventsi' = events + t1_send_ev (if i) + // just add to scopesUsed + forall i : scopesUsedi' = scopesUsedi + scopesUsed } } } @@ -75,7 +81,8 @@ public class AddTransPost { // TODO for Electrum! public static void addTransPost(DashModule d, String tfqn) { String tout = translateFQN(tfqn); - List prs = d.getTransParams(tfqn); + List prsIdx = d.getTransParamsIdx(tfqn); + List prs = d.getTransParams(tfqn); List body = new ArrayList(); // confi' = confi - exitedi + enteredi @@ -89,7 +96,7 @@ public static void addTransPost(DashModule d, String tfqn) { .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); Expr e = curConf(i); - for (Expr x:ent) { + for (Expr x:exi) { // can't diff ((ent1 - ent2) - ent3) // but have to diff from whole set e = createDiff(e,x); @@ -98,16 +105,6 @@ public static void addTransPost(DashModule d, String tfqn) { if (!ent.isEmpty()) e = createUnion(e,createUnionList(ent)); body.add(createEquals(nextConf(i),e)); } - // scopesUsedi' = scopesUsedi + scopesUsed - List sU = d.scopesUsed(tfqn); - for (int i=0;i <= d.getMaxDepthParams(); i++) { - List u = DashRef.hasNumParams(sU,i).stream() - .map(x -> translateDashRefToArrow(x)) - .collect(Collectors.toList()); - Expr e = curScopesUsed(i); - if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); - e = createEquals(nextScopesUsed(i),e); - } // action_t1[s,s'] if (d.getTransDo(tfqn) != null) @@ -151,6 +148,14 @@ public static void addTransPost(DashModule d, String tfqn) { //if (case2.isEmpty()) c2 = createTrue(); c2 = createAndFromList(case2); + List scopesUsedEmpty = new ArrayList(); + + for (int i=0;i <= d.getMaxDepthParams(); i++) { + scopesUsedEmpty.add(createEquals(nextScopesUsed(i),createNone())); + } + Expr stableTrueAndScopesUsedEmpty = + createAnd(nextStableTrue(), createAndFromList(scopesUsedEmpty)); + // case 3 // forall i: (eventsi' :> InternalEvent = t1_send_ev (if i)) // (eventsi' :> InternalEvent = none) (if not i) @@ -174,6 +179,7 @@ public static void addTransPost(DashModule d, String tfqn) { createRangeRes(nextEvents(i),allInternalEventsVar()), rhs1)); } + case3.add(createEquals(nextScopesUsed(i),createNone())); } //if (case3.isEmpty()) c3 = createTrue(); c3 = createAndFromList(case3); @@ -182,15 +188,25 @@ public static void addTransPost(DashModule d, String tfqn) { // forall i. eventsi' = eventsi + t1_send (if i) // eventsi' = eventsi (if not i) List case4 = new ArrayList(); - Expr c4; + List sU = d.scopesUsed(tfqn); + List u; + Expr e; for (int i=0;i <= d.getMaxDepthParams(); i++) { if (d.hasEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) case4.add(createEquals(nextEvents(i),createUnion(curEvents(i), translateDashRefToArrow(ev)))); } + // scopesUsedi' = scopesUsedi + scopesUsed + u = DashRef.hasNumParams(sU,i).stream() + .map(x -> translateDashRefToArrow(x)) + .collect(Collectors.toList()); + e = curScopesUsed(i); + if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); + case4.add(createEquals(nextScopesUsed(i),e)); } + //if (case4.isEmpty()) c4 = createTrue(); - c4 = createAndFromList(case4); + Expr c4 = createAndFromList(case4); // env_vars_unchanged[s,s'] @@ -209,7 +225,7 @@ public static void addTransPost(DashModule d, String tfqn) { body.add( createITE(createTestIfNextStableCall(d, tfqn), createAnd( - nextStableTrue(), + stableTrueAndScopesUsedEmpty, createITE (curStableTrue(), c1, c2)), @@ -220,15 +236,15 @@ public static void addTransPost(DashModule d, String tfqn) { c4)))); - d.alloyString += d.addPredSimple(tout+postName,curNextParamsDecls(prs),body); + d.alloyString += d.addPredSimple(tout+postName,curNextParamsDecls(prsIdx,prs),body); } public static Expr createVarDoesNotChange(DashModule d, String x) { return createAll( - paramDecls(d.getVarBufferParams(x)), + paramDecls(d.getVarBufferParamsIdx(x),d.getAllParamsInOrder()), createEquals( - createJoinList(DashUtilFcns.newListWith(curParamVars(d.getVarBufferParams(x)),createVar(x))), - createJoinList(DashUtilFcns.newListWith(nextParamVars(d.getVarBufferParams(x)),createVar(x))))); + createJoinList(DashUtilFcns.newListWith(curParamVars(d.getVarBufferParamsIdx(x), d.getVarBufferParams(x)),createVar(x))), + createJoinList(DashUtilFcns.newListWith(nextParamVars(d.getVarBufferParamsIdx(x), d.getVarBufferParams(x)),createVar(x))))); } // pred call: testIfNextStable[s,s',scope1, scope2, ... , send1, send2, ...] @@ -239,6 +255,14 @@ private static Expr createTestIfNextStableCall(DashModule d, String tfqn) { args.add(curVar()); args.add(nextVar()); } + // add args for parameters; has to be something or none for every possible parameter in the system + List paramsIdxUsed = d.getTransParamsIdx(tfqn); + for (int i=0;i sU = d.scopesUsed(tfqn); DashRef ev = d.getTransSend(tfqn); for (int i=0; i <= d.getMaxDepthParams(); i++) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 4995f1041..9e996147e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -47,7 +47,7 @@ .trig_events_t1 in (s.events & ExternalEvent ) Assumption: prs for src state and trig events are a subset of prs for trans */ public static void addTransPre(DashModule d, String tfqn) { - List prs = d.getTransParams(tfqn); + List prsIdx = d.getTransParamsIdx(tfqn); List body = new ArrayList(); String tout = translateFQN(tfqn); @@ -57,7 +57,7 @@ public static void addTransPre(DashModule d, String tfqn) { createSomeOf( createIntersect( translateDashRefToArrow(d.getTransSrc(tfqn)), - curConf(prs.size())))); + curConf(prsIdx.size())))); if (d.getTransWhen(tfqn) != null) body.add(translateExpr(d.getTransWhen(tfqn),d)); @@ -100,7 +100,7 @@ public static void addTransPre(DashModule d, String tfqn) { */ // not a higher priority transition enabled - d.alloyString += d.addPredSimple(tout+DashStrings.preName, curParamsDecls(prs), body); + d.alloyString += d.addPredSimple(tout+DashStrings.preName, curParamsDecls(prsIdx,d.getAllParamsInOrder()), body); d.alloyString += "\n"; } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index 3e1e21b7c..33998521d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -42,10 +42,15 @@ public static Decl nextDecl() { } // p0:P0 - public static Decl paramDecl(String n) { - return (Decl) new DeclExt(DashStrings.pName+n, n); + public static Decl paramDecl(Integer n, String name) { + return (Decl) new DeclExt(DashStrings.pName+n+"_"+name, name); } + //pi: Identfiers + //public static Decl posParamDecl(Integer i) { + // return (Decl) new DeclExt(DashStrings.pName+Integer.toString(i), DashStrings.identifierName); + //} + // [s:Snapshot, s':Snapshot] public static List curNextDecls() { List o = new ArrayList(); @@ -57,24 +62,24 @@ public static List curNextDecls() { } // [p0:P0, p1:P1, ...] - public static List paramDecls(List prs) { + public static List paramDecls(List prsIdx , List prs) { List o = new ArrayList(); - for (String n: prs) o.add(paramDecl(n)); + for (int i=0;i curParamsDecls(List prs) { + public static List curParamsDecls(List prsIdx, List prs) { List o = new ArrayList(); if (!DashOptions.isElectrum) o.add(curDecl()); - o.addAll(paramDecls(prs)); + o.addAll(paramDecls(prsIdx, prs)); return o; } // s:Snapshot, s':Snapshot, p0:P0, p1:P1, ...] - public static List curNextParamsDecls(List prs) { + public static List curNextParamsDecls(List prsIdx, List prs) { List o = new ArrayList(); if (!DashOptions.isElectrum) { o.add(curDecl()); o.add(nextDecl()); } - o.addAll(paramDecls(prs)); + o.addAll(paramDecls(prsIdx, prs)); return o; } @@ -113,30 +118,39 @@ public static List curNextVars() { o.add(nextVar()); return o; } - // [p1,p2,...] - public static List paramVars(List names) { + //pi: Identfiers + //public static Expr posParamVar(Integer i) { + // return createVar(DashStrings.pName+Integer.toString(i)); + //} + // p0_AID + public static Expr paramVar(Integer i, String n) { + return createVar(DashStrings.pName+Integer.toString(i)+"_"+n); + } + // [p0_AID,p1_AID,...] + public static List paramVars(List prsIdx, List prs) { + assert(prsIdx.size() == prs.size()); List o = new ArrayList(); - for (String n: names) o.add(createVar(DashStrings.pName+n)); + for (int i=0;i curParamVars(List params) { + public static List curParamVars(List prsIdx, List prs) { List o = new ArrayList(); o.add(curVar()); - o.addAll(paramVars(params)); + o.addAll(paramVars(prsIdx,prs)); return o; } // [s', p1,p2,...] - public static List nextParamVars(List params) { + public static List nextParamVars(List prsIdx, List prs) { List o = new ArrayList(); o.add(nextVar()); - o.addAll(paramVars(params)); + o.addAll(paramVars(prsIdx, prs)); return o; } // [s,s', p1,p2,...] - public static List curNextParamVars(List params) { + public static List curNextParamVars(List prsIdx, List prs) { List o = new ArrayList(curNextVars()); - o.addAll(paramVars(params)); + o.addAll(paramVars(prsIdx,prs)); return o; } @@ -222,15 +236,17 @@ public static Expr nextJoinExpr(Expr e) { return createJoin(nextVar(), e); } } + /* // p3 -> p2 -> p1 -> x - public static Expr paramsToXArrow(List prs, String x) { - Collections.reverse(prs); + public static Expr paramsToXArrow(List prsIdx, List prs, String x) { + Collections.reverse(prsIdx); Expr e = createVar(x); - for (String p: prs) { - e = createArrow(createVar(p),e); + for (int i=0;i ll = new ArrayList(e.getParamValues()); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 8f2a281e9..9f9fb20ba 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -30,6 +30,7 @@ import ca.uwaterloo.watform.parser.CompModuleHelper; import ca.uwaterloo.watform.dashtoalloy.DashToAlloy; +import ca.uwaterloo.watform.dashtoalloy.Common; public class DashModule extends CompModuleHelper { @@ -52,6 +53,8 @@ public class DashModule extends CompModuleHelper { private EventTable eventTable = new EventTable(); private VarTable varTable = new VarTable(); + + // once created and parsed, the following are // the phases of a DashModule // all operations happen in place @@ -291,10 +294,11 @@ public int getMaxDepthParams() { // could precalculate this return maxDepthParams; } - public List getAllParams() { - return stateTable.getAllParams(); + public List getAllParamsInOrder() { + return stateTable.getAllParamsInOrder(); } + //stuff about states (some of these are to expose the stateTable for testing) public boolean isLeaf(String s) { return (stateTable.isLeaf(s)); @@ -329,7 +333,9 @@ public List getAllNonParamDesc(String sfqn) { public List getRegion(String sfqn) { return stateTable.getRegion(sfqn); } - + public List getTransParamsIdx(String tfqn) { + return transTable.getParamsIdx(tfqn); + } // stuff about transitions public List getAllTransNames() { return transTable.getAllTransNames(); @@ -372,6 +378,9 @@ public List getAllVarNames() { public List getVarBufferParams(String vfqn) { return varTable.getParams(vfqn); } + public List getVarBufferParamsIdx(String vfqn) { + return varTable.getParamsIdx(vfqn); + } public Expr getVarType(String vfqn) { return varTable.getVarType(vfqn); } @@ -410,7 +419,7 @@ public DashRef getScope(String tfqn) { String sc = DashFQN.longestCommonFQN(src.getName(),dest.getName()); // maxCommonParams is max number of params that could have in common // but they don't necessarily have the same values - Integer maxCommonParams = stateTable.getParams(sc).size(); + Integer maxCommonParams = stateTable.getParamsIdx(sc).size(); List scopeParams = new ArrayList(); Expr equals = null; Expr s = null; @@ -464,7 +473,9 @@ public List entered(String tfqn) { getScope(tfqn), getTransDest(tfqn)); } - + public List initialEntered() { + return stateTable.getRootLeafStatesEntered(); + } public List onlyConc(List dr) { return dr.stream() .filter(x -> isAnd(x.getName())) @@ -554,7 +565,7 @@ public void resolveAllDash(A4Reporter rep) { root = roots.get(0); // passed with empty set of params, empty set of ancestors stateTable.setRoot(root.name); - root.resolve(stateTable,transTable, eventTable, varTable, new ArrayList(),new ArrayList()); + root.resolve(stateTable,transTable, eventTable, varTable, new ArrayList(),new ArrayList(), new ArrayList()); // have to do states first so siblings of trans parent state // are in place to search for src/dest // root.resolveTransTable(stateTable,transTable); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index f24b1b39d..d4aa223c9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -16,6 +16,7 @@ import ca.uwaterloo.watform.core.DashRef; import ca.uwaterloo.watform.alloyasthelper.ExprHelper; +import ca.uwaterloo.watform.dashtoalloy.Common; public class EventTable { @@ -27,18 +28,22 @@ public class EventTable { public class EventElement { private IntEnvKind kind; private List params; + private List paramsIdx; public EventElement( IntEnvKind k, - List prms) { + List prms, + List prmsIdx) { assert(prms != null); this.kind = k; this.params = prms; + this.paramsIdx = prmsIdx; } public String toString() { String s = new String(); s += "kind: "+kind+"\n"; s += "params: "+ NoneStringIfNeeded(params) +"\n"; + s += "paramsIdx: "+ NoneStringIfNeeded(paramsIdx) +"\n"; return s; } } @@ -56,11 +61,11 @@ public String toString() { } return s; } - public Boolean add(String efqn, IntEnvKind k, List prms) { + public Boolean add(String efqn, IntEnvKind k, List prms, List prmsIdx) { assert(prms!=null); if (table.containsKey(efqn)) return false; else if (hasPrime(efqn)) { DashErrors.nameShouldNotBePrimed(efqn); return false; } - else { table.put(efqn, new EventElement(k,prms)); return true; } + else { table.put(efqn, new EventElement(k,prms,prmsIdx)); return true; } } public void resolveAllEventTable() { // TODO @@ -106,6 +111,10 @@ public List getParams(String efqn) { if (table.containsKey(efqn)) return table.get(efqn).params; else { DashErrors.eventTableEventNotFound("getParams", efqn); return null; } } + public List getParamsIdx(String efqn) { + if (table.containsKey(efqn)) return table.get(efqn).paramsIdx; + else { DashErrors.eventTableEventNotFound("getParamsIdx", efqn); return null; } + } public boolean isEnvironmentalEvent(String efqn) { if (table.containsKey(efqn)) return (table.get(efqn).kind == IntEnvKind.ENV); else { DashErrors.eventTableEventNotFound("isEnvironmentalEvent", efqn); return false; } @@ -122,7 +131,7 @@ public List allEventsOfState(String sfqn) { .collect(Collectors.toList()); } - public DashRef resolveEvent(String xType, Expr exp, List region, String tfqn, List tparams, VarTable vt) { + public DashRef resolveEvent(String xType, Expr exp, List region, String tfqn, List tparamsIdx, List tparams, VarTable vt) { // don't include isDashRefJoin here because that is only possible for actions not events @@ -147,7 +156,7 @@ public DashRef resolveEvent(String xType, Expr exp, List region, String paramValues = // have to recursive through expressions in parameters DashRef.paramValuesOfDashRefExpr(exp).stream() - .map(i -> vt.resolveExpr(xType, i, region, tfqn, tparams)) + .map(i -> vt.resolveExpr(xType, i, region, tfqn, tparamsIdx, tparams)) .collect(Collectors.toList()); } String efqn = DashFQN.fqn(e); @@ -178,7 +187,7 @@ public DashRef resolveEvent(String xType, Expr exp, List region, String String m = matches.get(0); if (paramValues.isEmpty()) { // must have same param values as trans b/c in same conc region - if (getParams(m).size() > tparams.size()) { + if (getParams(m).size() > tparamsIdx.size()) { // getRegion did not return things that all // have the same parameter values DashErrors.regionMatchesWrongParamNumber(); @@ -186,8 +195,9 @@ public DashRef resolveEvent(String xType, Expr exp, List region, String } else { // but could be a subset of transition param values List prmValues = - ExprHelper.createVarList(pName, - tparams.subList(0, getParams(m).size() )); + Common.paramVars( + tparamsIdx.subList(0, getParamsIdx(m).size()), + tparams.subList(0,getParams(m).size()) ); return new DashRef(m, prmValues); } } else if (getParams(m).size() != paramValues.size()) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 2badccdea..46c9d306c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -28,6 +28,7 @@ import ca.uwaterloo.watform.ast.*; import ca.uwaterloo.watform.parser.VarTable; +import ca.uwaterloo.watform.dashtoalloy.Common; public class StateTable { private HashMap table; @@ -35,7 +36,12 @@ public class StateTable { private String root; private List inits = new ArrayList(); private List invs = new ArrayList(); + private List allParamsInOrder = new ArrayList(); + public Integer addToParamsList(String p) { + allParamsInOrder.add(p); + return allParamsInOrder.size()-1; + } private String space = " "; /* nested class for elementes in the state table */ @@ -44,6 +50,7 @@ public class StateElement { private DashStrings.StateKind kind; // must exist AND/OR private String param; // may be empty private List params; // null if none; param is last of params if it exists + private List paramsIdx; // their pos in the list of params (will be a sequence) private DashStrings.DefKind def; // these all use fullQual names to point to trans in TransTable // or states in this StateTable @@ -71,6 +78,7 @@ public StateElement( DashStrings.StateKind k, String prm, List prms, + List prmsIdx, DashStrings.DefKind d, String p, List iChildren, @@ -91,6 +99,7 @@ public StateElement( this.kind = k; this.param = prm; this.params = prms; + this.paramsIdx = prmsIdx; this.def = d; this.parent = p; this.immChildren = iChildren; @@ -197,6 +206,7 @@ public boolean add( DashStrings.StateKind k, String prm, List prms, + List prmsIdx, DashStrings.DefKind d, String p, List iChildren, @@ -217,7 +227,7 @@ public boolean add( //else if (table.containsKey(fqn)) return false; else if (DashStrings.hasPrime(fqn)) { DashErrors.nameShouldNotBePrimed(fqn); return false; } - else { table.put(fqn, new StateElement(k,prm, prms,d,p,iChildren, invL, initL, actL, condL)); return true; } + else { table.put(fqn, new StateElement(k,prm, prms,prmsIdx, d,p,iChildren, invL, initL, actL, condL)); return true; } //System.out.println("adding to State table: "+fqn+space+prm + space + prms+space+d+space+p+iChildren); } public void addInit(Expr exp) { @@ -275,6 +285,11 @@ public List getParams(String s) { return table.get(s).params; else { DashErrors.stateDoesNotExist("getParams", s); return null; } } + public List getParamsIdx(String s) { + if (table.containsKey(s)) + return table.get(s).paramsIdx; + else { DashErrors.stateDoesNotExist("getParamsIdx", s); return null; } + } public Boolean hasConcurrency(String s) { if (table.containsKey(s)) { if (table.get(s).kind == DashStrings.StateKind.AND) return true; @@ -379,13 +394,14 @@ public int getMaxDepthParams(String s) { } return max; } - public List getAllParams() { + public List getAllParamsInOrder() { // variety of ways of doing this operation - Set allParams = new HashSet(); - for (String k: table.keySet()) { - if (table.get(k).params != null) allParams.addAll(table.get(k).params); - } - return DashUtilFcns.setToList(allParams); + return allParamsInOrder; + //Set allParams = new HashSet(); + //for (String k: table.keySet()) { + // if (table.get(k).params != null) allParams.addAll(table.get(k).params); + //} + //return DashUtilFcns.setToList(allParams); } public void resolve(String root, VarTable vt) { // resolve inits and invariants @@ -395,6 +411,7 @@ public void resolve(String root, VarTable vt) { .map(i -> vt.resolveExpr("init", i.getInit(), getRegion(sfqn), sfqn, + getParamsIdx(sfqn), getParams(sfqn))) .collect(Collectors.toList())); invs.addAll( @@ -402,6 +419,7 @@ public void resolve(String root, VarTable vt) { .map(i -> vt.resolveExpr("inv", i.getInv(), getRegion(sfqn), sfqn, + getParamsIdx(sfqn), getParams(sfqn))) .collect(Collectors.toList())); // have to resolve variables here because need @@ -413,6 +431,7 @@ public void resolve(String root, VarTable vt) { vt.getVarType(vfqn), getRegion(sfqn), sfqn, + getParamsIdx(sfqn), getParams(sfqn))); } } @@ -430,14 +449,14 @@ public void resolve(String root, VarTable vt) { // tfqn is needed for error messages - public DashRef resolveSrcDest(String xType, DashRef x, String tfqn, List tparams, VarTable vt) { + public DashRef resolveSrcDest(String xType, DashRef x, String tfqn, List tparamsIdx, List tparams, VarTable vt) { //System.out.println("Looking for: " + x); String sfqn = DashFQN.fqn(x.getName()); String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); // param values might be empty List paramValues = x.getParamValues().stream() - .map(i -> vt.resolveExpr("from", i, getRegion(parentFQN), tfqn, tparams)) + .map(i -> vt.resolveExpr("from", i, getRegion(parentFQN), tfqn, tparamsIdx, tparams)) .collect(Collectors.toList()); List matches = new ArrayList(); @@ -462,7 +481,7 @@ public DashRef resolveSrcDest(String xType, DashRef x, String tfqn, List String m = matches.get(0); if (paramValues.isEmpty()) { // must have same param values as trans b/c in same conc region - if (getParams(m).size() > tparams.size()) { + if (getParams(m).size() > tparamsIdx.size()) { // getRegion did not return things that all // have the same parameter values DashErrors.regionMatchesWrongParamNumber(); @@ -470,8 +489,9 @@ public DashRef resolveSrcDest(String xType, DashRef x, String tfqn, List } else { // but could be a subset of transition param values List prmValues = - ExprHelper.createVarList(pName, - tparams.subList(0, getParams(m).size() )); + Common.paramVars( + tparamsIdx.subList(0, getParams(m).size()), + tparams.subList(0, getParams(m).size()) ); return new DashRef(m, prmValues); } } else if (getParams(m).size() != paramValues.size()) { @@ -539,6 +559,11 @@ public List getLeafStatesEntered(DashRef s) { } return r; } + public List getRootLeafStatesEntered() { + List x = new ArrayList(); + //System.out.println(getLeafStatesEntered(new DashRef(root,x))); + return getLeafStatesEntered(new DashRef(root,x)); + } public List allPrefixDashRefs(DashRef s) { List allPrefixFQNs = DashFQN.allPrefixes(s.getName()); List r = new ArrayList(); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 0b4d159e7..2dbeeeec8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -23,6 +23,7 @@ import ca.uwaterloo.watform.alloyasthelper.ExprHelper; //import ca.uwaterloo.watform.alloyasthelper.ExprToString; import ca.uwaterloo.watform.ast.*; +import ca.uwaterloo.watform.dashtoalloy.Common; // env events cannot be generated // env vars cannot be primed anywhere @@ -34,6 +35,7 @@ public class TransTable { public class TransElement { public List params; // null if no params + public List paramsIdx; public List fromList; public List onList; public List whenList; @@ -56,6 +58,7 @@ public class TransElement { */ public TransElement( List prms, + List prmsIdx, List fl, List ol, List wl, @@ -72,6 +75,7 @@ public TransElement( */ { this.params = prms; + this.paramsIdx = prmsIdx; this.fromList = fl; this.onList = ol; this.whenList = wl; @@ -82,6 +86,7 @@ public TransElement( public String toString() { String s = new String(); s += "params: " + NoneStringIfNeeded(params) +"\n"; + s += "paramsIdx: " + NoneStringIfNeeded(paramsIdx) +"\n"; s += "src: " + NoneStringIfNeeded(src) + "\n"; s += "dest: " + NoneStringIfNeeded(dest) + "\n"; s += "on: " + NoneStringIfNeeded(on) + "\n"; @@ -118,6 +123,7 @@ public TransTable() { public boolean add( String tfqn, List params, + List paramsIdx, List fromList, List onList, List whenList, @@ -130,6 +136,7 @@ public boolean add( //System.out.println("onList: " + NoneStringIfNeeded(onList)); assert(!tfqn.isEmpty()); assert(params != null ); + assert(paramsIdx != null); assert(fromList != null); assert(onList != null); assert(whenList != null); @@ -138,7 +145,7 @@ public boolean add( assert(doList != null); if (table.containsKey(tfqn)) return false; else if (DashStrings.hasPrime(tfqn)) { DashErrors.nameShouldNotBePrimed(tfqn); return false; } - else { table.put(tfqn, new TransElement(params,fromList,onList,whenList,gotoList,sendList,doList)); return true; } + else { table.put(tfqn, new TransElement(params,paramsIdx, fromList,onList,whenList,gotoList,sendList,doList)); return true; } } public String toString() { String s = new String(); @@ -158,6 +165,10 @@ public List getParams(String t) { if (table.containsKey(t)) return table.get(t).params; else { DashErrors.transDoesNotExist("getParams", t); return null; } } + public List getParamsIdx(String t) { + if (table.containsKey(t)) return table.get(t).paramsIdx; + else { DashErrors.transDoesNotExist("getParamsIdx", t); return null; } + } public DashRef getSrc(String t) { if (table.containsKey(t)) return table.get(t).src; else { DashErrors.transDoesNotExist("getSrc", t); return null; } @@ -229,14 +240,15 @@ public void resolve(StateTable st, EventTable et, VarTable vt) { else if (fList.isEmpty()) // can be a loop on root table.get(tfqn) - .setSrc(new DashRef(parentFQN, ExprHelper.createVarList(DashStrings.pName,getParams(tfqn)))); + .setSrc(new DashRef(parentFQN, Common.paramVars(getParamsIdx(tfqn), getParams(tfqn)))); else table.get(tfqn) .setSrc( st.resolveSrcDest("from", fList.get(0), tfqn, - getParams(tfqn), + getParamsIdx(tfqn), + getParams(tfqn), vt)); // determining the dest state @@ -249,14 +261,15 @@ else if (fList.isEmpty()) else if (gList.isEmpty()) // can be a loop on root table.get(tfqn) - .setDest(new DashRef(parentFQN, ExprHelper.createVarList(DashStrings.pName,getParams(tfqn)))); + .setDest(new DashRef(parentFQN, Common.paramVars(getParamsIdx(tfqn),getParams(tfqn)))); else table.get(tfqn) .setDest( st.resolveSrcDest("goto", gList.get(0), tfqn, - getParams(tfqn), + getParamsIdx(tfqn), + getParams(tfqn), vt)); // determining the on (event) @@ -272,6 +285,7 @@ else if (!onExpList.isEmpty()) { onExpList.get(0), st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), tfqn, + getParamsIdx(tfqn), getParams(tfqn), vt)); } @@ -289,7 +303,8 @@ else if (!sendExpList.isEmpty()) { sendExpList.get(0), st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), tfqn, - getParams(tfqn), + getParamsIdx(tfqn), + getParams(tfqn), vt)); } @@ -306,6 +321,7 @@ else if (!whenExpList.isEmpty()) { whenExpList.get(0), st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), tfqn, + getParamsIdx(tfqn), getParams(tfqn))); } @@ -321,6 +337,7 @@ else if (!doExpList.isEmpty()) { vt.resolveExpr("do", doExpList.get(0), st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), tfqn, + getParamsIdx(tfqn), getParams(tfqn))); } @@ -341,7 +358,7 @@ else if (!doExpList.isEmpty()) { - + public boolean[] transAtThisParamDepth(int max) { boolean[] depthsInUse = new boolean[max+1]; // 0..max for (int i=0; i <= max; i++) depthsInUse[i] = false; @@ -350,5 +367,6 @@ public boolean[] transAtThisParamDepth(int max) { else depthsInUse[table.get(k).params.size()] = true; return depthsInUse; } + } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index 9164a5881..d31dc5917 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -17,6 +17,7 @@ import static ca.uwaterloo.watform.core.DashUtilFcns.*; import static ca.uwaterloo.watform.core.DashStrings.*; import ca.uwaterloo.watform.core.DashRef; +import ca.uwaterloo.watform.dashtoalloy.Common; public class VarTable { @@ -33,21 +34,25 @@ public VarTable() { public class VarElement { private IntEnvKind kind; private List params; + private List paramsIdx; private Expr typ; public VarElement( IntEnvKind k, List prms, + List prmsIdx, Expr t) { assert(prms != null); this.kind = k; this.params = prms; + this.paramsIdx = prmsIdx; this.typ = t; } public String toString() { String s = new String(); s += "kind: "+kind+"\n"; s += "params: "+ NoneStringIfNeeded(params) +"\n"; + s += "paramsIdx: "+ NoneStringIfNeeded(paramsIdx) +"\n"; s += "typ: "+typ.toString() + "\n"; return s; } @@ -75,11 +80,11 @@ public String toString() { } return s; } - public Boolean addVar(String vfqn, IntEnvKind k, List prms, Expr t) { + public Boolean addVar(String vfqn, IntEnvKind k, List prms, List prmsIdx, Expr t) { assert(prms!=null); if (varTable.containsKey(vfqn)) return false; if (hasPrime(vfqn)) { DashErrors.nameShouldNotBePrimed(vfqn); return false; } - else { varTable.put(vfqn, new VarElement(k,prms, t)); return true; } + else { varTable.put(vfqn, new VarElement(k,prms, prmsIdx, t)); return true; } } public void resolve() { //anything? @@ -115,11 +120,17 @@ public List getNamesOfState(String sfqn) { return x; } // same function for buffers and variables + //TODO: what if var and buffer have the same name!!! public List getParams(String fqn) { if (bufferTable.containsKey(fqn)) return bufferTable.get(fqn).params; if (varTable.containsKey(fqn)) return varTable.get(fqn).params; else { DashErrors.varBufferDoesNotExist("getParams", fqn); return null; } } + public List getParamsIdx(String fqn) { + if (bufferTable.containsKey(fqn)) return bufferTable.get(fqn).paramsIdx; + if (varTable.containsKey(fqn)) return varTable.get(fqn).paramsIdx; + else { DashErrors.varBufferDoesNotExist("getParams", fqn); return null; } + } public Expr getVarType(String vfqn) { if (varTable.containsKey(vfqn)) return varTable.get(vfqn).typ; else { DashErrors.varDoesNotExist("getType", vfqn); return null; } @@ -134,17 +145,20 @@ public boolean isInternal(String fqn) { public class BufferElement { private IntEnvKind kind; private List params; + private List paramsIdx; private String element; private Integer index; public BufferElement( IntEnvKind k, List prms, + List prmsIdx, String e, Integer idx) { assert(prms != null); this.kind = k; this.params = prms; + this.paramsIdx = prmsIdx; this.element = e; this.index = idx; } @@ -152,6 +166,7 @@ public String toString() { String s = new String(); s += "kind: "+kind+"\n"; s += "params: "+ NoneStringIfNeeded(params) +"\n"; + s += "paramsIdx: "+ NoneStringIfNeeded(paramsIdx) +"\n"; s += "element: "+element.toString() + "\n"; s += "index:" + index; return s; @@ -176,10 +191,10 @@ public String getBufferElement(String bfqn) { else { DashErrors.bufferDoesNotExist("getElement", bfqn); return null; } } - public Boolean addBuffer(String vfqn, IntEnvKind k, List prms, String el, Integer idx) { + public Boolean addBuffer(String vfqn, IntEnvKind k, List prms, List prmsIdx, String el, Integer idx) { assert(prms!=null); if (bufferTable.containsKey(vfqn)) return false; - else { bufferTable.put(vfqn, new BufferElement(k,prms, el, idx)); return true; } + else { bufferTable.put(vfqn, new BufferElement(k,prms, prmsIdx, el, idx)); return true; } } @@ -196,7 +211,7 @@ public Boolean addBuffer(String vfqn, IntEnvKind k, List prms, String el // have to recurse through exp types, replace dynamic vars with DashRef and rebuild exp // don't use ExprHelper much here because we want to // as much about the expression as possible - public Expr resolveExpr(String xType, Expr exp, List region, String fqn, List params) { + public Expr resolveExpr(String xType, Expr exp, List region, String fqn, List paramsIdx, List params) { //System.out.println(exp); if (isExprVar(exp) || isPrimedVar(exp) || @@ -204,21 +219,21 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn DashRef.isDashRefProcessRef(exp)) // || //DashRef.isDashRefBadJoin(exp)) { - return dashRefVar(xType, exp, region, fqn, params); + return dashRefVar(xType, exp, region, fqn, paramsIdx, params); } else if (isExprBinary(exp)) { return ((ExprBinary) exp).op.make( exp.pos, exp.closingBracket, - resolveExpr(xType, getLeft(exp), region, fqn, params), - resolveExpr(xType, getRight(exp), region, fqn, params)); + resolveExpr(xType, getLeft(exp), region, fqn, paramsIdx, params), + resolveExpr(xType, getRight(exp), region, fqn, paramsIdx, params)); } else if (isExprBadJoin(exp)) { return ExprBadJoin.make( exp.pos, exp.closingBracket, - resolveExpr(xType, getLeft(exp), region, fqn, params), - resolveExpr(xType, getRight(exp), region, fqn, params)); + resolveExpr(xType, getLeft(exp), region, fqn, paramsIdx, params), + resolveExpr(xType, getRight(exp), region, fqn, paramsIdx, params)); } else if (exp instanceof ExprCall) { return ExprCall.make( @@ -226,7 +241,7 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn exp.closingBracket, ((ExprCall) exp).fun, ((ExprCall) exp).args.stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx, params)) .collect(Collectors.toList()), ((ExprCall) exp).extraWeight); @@ -234,7 +249,7 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn //TODO: check into this cast // not sure why is it necessary ConstList x = (ConstList) ((ExprChoice) exp).choices.stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx, params)) .collect(Collectors.toList()); return ExprChoice.make( false, @@ -245,9 +260,9 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn } else if (exp instanceof ExprITE){ return ExprITE.make( exp.pos, - resolveExpr(xType, getCond(exp), region, fqn, params), - resolveExpr(xType, getLeft(exp), region, fqn, params), - resolveExpr(xType, getRight(exp), region, fqn, params)); + resolveExpr(xType, getCond(exp), region, fqn, paramsIdx, params), + resolveExpr(xType, getLeft(exp), region, fqn, paramsIdx, params), + resolveExpr(xType, getRight(exp), region, fqn, paramsIdx, params)); } else if (exp instanceof ExprList){ return ExprList.make( @@ -255,22 +270,22 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn exp.closingBracket, ((ExprList) exp).op, ((ExprList) exp).args.stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx, params)) .collect(Collectors.toList()) ); } else if (exp instanceof ExprUnary){ return ((ExprUnary) exp).op.make( exp.pos, - resolveExpr(xType, ((ExprUnary) exp).sub, region, fqn, params)); + resolveExpr(xType, ((ExprUnary) exp).sub, region, fqn, paramsIdx, params)); } else if (exp instanceof ExprLet){ //TODO rule out var name return ExprLet.make( exp.pos, ((ExprLet) exp).var, - resolveExpr(xType, ((ExprLet) exp).expr, region, fqn, params), - resolveExpr(xType, ((ExprLet) exp).sub, region, fqn, params)); + resolveExpr(xType, ((ExprLet) exp).expr, region, fqn, paramsIdx, params), + resolveExpr(xType, ((ExprLet) exp).sub, region, fqn, paramsIdx, params)); } else if (exp instanceof ExprQt){ //TODO rule out var names in delcs as dynamic vars later @@ -283,14 +298,14 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn i.disjoint2, i.isVar, i.names, - resolveExpr(xType, i.expr, region, fqn, params))) + resolveExpr(xType, i.expr, region, fqn, paramsIdx, params))) .collect(Collectors.toList()); return ((ExprQt) exp).op.make( exp.pos, exp.closingBracket, decls, - resolveExpr(xType, ((ExprQt) exp).sub, region, fqn, params)); + resolveExpr(xType, ((ExprQt) exp).sub, region, fqn, paramsIdx, params)); } else if (exp instanceof ExprConstant){ return exp; @@ -302,7 +317,7 @@ public Expr resolveExpr(String xType, Expr exp, List region, String fqn } // fqn could be trans or state - private Expr dashRefVar(String xType, Expr exp, List region, String fqn, List params) { + private Expr dashRefVar(String xType, Expr exp, List region, String fqn, List paramsIdx, List params) { // Join: b1.a1.var @@ -321,7 +336,8 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, List paramValues; if (isExprVar(exp)) { v = getVarName((ExprVar) exp); - if (v.startsWith(thisName)) { + //TODO fix this!!! + /*if (v.startsWith(thisName)) { // thisAID gets replaced with pAID as a normal variable // not a processref String suffix = v.substring(thisName.length(),v.length()); @@ -331,7 +347,7 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, match = x; if (!match.isEmpty()) return createVar(pName+match); - } + }*/ paramValues = new ArrayList(); } else if (isPrimedVar(exp)) { v = getVarName((ExprVar) getSub(exp))+PRIME; @@ -341,7 +357,7 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, v = DashRef.nameOfDashRefExpr(exp); // have to recurse through param values paramValues = DashRef.paramValuesOfDashRefExpr(exp).stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx, params)) .collect(Collectors.toList()); } String vfqn = DashFQN.fqn(v); @@ -387,7 +403,7 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, String m = matches.get(0); if (paramValues.isEmpty()) { // must have same param values as trans b/c in same conc region - if (getParams(m).size() > params.size()) { + if (getParams(m).size() > paramsIdx.size()) { // getRegion did not return things that all // have the same parameter values DashErrors.regionMatchesWrongParamNumber(); @@ -395,9 +411,9 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, } else { // could be a subset of transition param values List prmValues = - createVarList( - DashStrings.pName, - params.subList(0, getParams(m).size())); + Common.paramVars( + paramsIdx.subList(0, getParams(m).size()), + params.subList(0,getParams(m).size())); if (isPrimed) m = m + PRIME; //System.out.println("here1" + m); return DashRef.DashRefExpr(m, prmValues); @@ -417,7 +433,7 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, m, // have to recursive through expressions in parameters paramValues.stream() - .map(i -> resolveExpr(xType, i, region, fqn, params)) + .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx,params)) .collect(Collectors.toList())); } } diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java index bb7cfdf09..c353bd34e 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java @@ -35,7 +35,7 @@ public List ll(String[] k) { return Arrays.asList(k); } - // src/dest ------------------ + // helper functions ------------------ public static String src(DashModule d, String s) { return d.getTransSrc(s).toString(); @@ -44,6 +44,14 @@ public static String dest(DashModule d, String s) { return d.getTransDest(s).toString(); } + public List allPrefixDashRefs(DashModule d, String tfqn) { + return d.allPrefixDashRefs(d.getScope(tfqn)) + .stream() + .map (i -> i.toString()) + .collect(Collectors.toList()); + } + + // src/dest ---------------- @Test public void noDefaultNeededTest1() { DashModule d = test("noDefaultNeeded1"); @@ -97,13 +105,13 @@ public void srcDestFQN1() { @Test public void paramSrcDest1() { DashModule d = test("paramSrcDest1"); - assertTrue(src(d,"Root/A/t1").equals("Root/A[pAPID]")); - assertTrue(dest(d,"Root/A/t1").equals("Root/A[pAPID]")); + assertTrue(src(d,"Root/A/t1").equals("Root/A[p0_APID]")); + assertTrue(dest(d,"Root/A/t1").equals("Root/A[p0_APID]")); } @Test public void paramSrcDest2() { DashModule d = test("paramSrcDest2"); - assertTrue(src(d,"Root/A/t1").equals("Root/A[pAPID]")); + assertTrue(src(d,"Root/A/t1").equals("Root/A[p0_APID]")); assertTrue(dest(d,"Root/A/t1").equals("Root/B/S1[x]")); } @@ -171,12 +179,8 @@ public void getRegion2() { // allPrefixDashRefs ---------------------- - public List allPrefixDashRefs(DashModule d, String tfqn) { - return d.allPrefixDashRefs(d.getScope(tfqn)) - .stream() - .map (i -> i.toString()) - .collect(Collectors.toList()); - } + + @Test public void allPrefixDashRefs1() { DashModule d = test("scopeParam1"); @@ -184,7 +188,7 @@ public void allPrefixDashRefs1() { allPrefixDashRefs(d,"Root/A/S1/t1") .equals(ll(new String[]{ "Root[]", - "Root/A[(pAPID = x => pAPID else APID)]" + "Root/A[(p0_APID = x => p0_APID else APID)]" }))); } @Test @@ -194,8 +198,8 @@ public void allPrefixDashRefs2() { allPrefixDashRefs(d, "Root/A/B/S1/t1") .equals(ll(new String[]{ "Root[]", - "Root/A[(pAPID = x => pAPID else APID)]", - "Root/A/B[(pAPID = x => pAPID else APID), (AND[pAPID = x, pBPID = y] => pBPID else BPID)]" + "Root/A[(p0_APID = x => p0_APID else APID)]", + "Root/A/B[(p0_APID = x => p0_APID else APID), (AND[p0_APID = x, p1_BPID = y] => p1_BPID else BPID)]" }))); } @Test @@ -205,8 +209,8 @@ public void allPrefixDashRefs3() { allPrefixDashRefs(d, "Root/A/B/S1/t1") .equals(ll(new String[]{ "Root[]", - "Root/A[pAPID]", - "Root/A/B[pAPID, pBPID]" + "Root/A[p0_APID]", + "Root/A/B[p0_APID, p1_BPID]" }))); } @Test @@ -287,7 +291,7 @@ public void getLeafStatesExited6() { assertTrue( exited(d,"Root/A/t1") .equals(ll(new String[]{ - "Root/A[pAPID]" + "Root/A[p0_APID]" }))); } @Test @@ -307,21 +311,21 @@ public void getScope1() { DashModule d = test("scopeParam1"); assertTrue( d.getScope("Root/A/S1/t1").toString() - .equals("Root/A[(pAPID = x => pAPID else APID)]")); + .equals("Root/A[(p0_APID = x => p0_APID else APID)]")); } @Test public void getScope2() { DashModule d = test("scopeParam2"); assertTrue( d.getScope("Root/A/B/S1/t1").toString() - .equals("Root/A/B[(pAPID = x => pAPID else APID), (AND[pAPID = x, pBPID = y] => pBPID else BPID)]")); + .equals("Root/A/B[(p0_APID = x => p0_APID else APID), (AND[p0_APID = x, p1_BPID = y] => p1_BPID else BPID)]")); } @Test public void getScope3() { DashModule d = test("scopeParam3"); assertTrue( d.getScope("Root/A/B/S1/t1").toString() - .equals("Root/A/B[pAPID, pBPID]")); + .equals("Root/A/B[p0_APID, p1_BPID]")); } // getLeafStatesEntered ----------------- @@ -537,31 +541,36 @@ public void overall1() { "Root/A/B/S1[AID, BID]", "Root/C/S2[c1]" }))); - + assertTrue( + d.getTransParamsIdx(tfqn) + .equals(Arrays.asList())); } @Test public void overall2() { DashModule d = test("overall2"); String tfqn = "Root/A/B/S1/t1"; assertTrue( - src(d, tfqn).equals("Root/A/B/S1[pAID, pBID]")); + src(d, tfqn).equals("Root/A/B/S1[p0_AID, p1_BID]")); assertTrue( dest(d, tfqn).equals("Root/A/S2[a2]")); assertTrue( d.getScope(tfqn).toString() - .equals("Root/A[(pAID = a2 => pAID else AID)]")); + .equals("Root/A[(p0_AID = a2 => p0_AID else AID)]")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/A/B/S1[(pAID = a2 => pAID else AID), BID]", - "Root/A/S2[(pAID = a2 => pAID else AID)]" + "Root/A/B/S1[(p0_AID = a2 => p0_AID else AID), BID]", + "Root/A/S2[(p0_AID = a2 => p0_AID else AID)]" }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A/S2[(pAID = a2 => pAID else AID) - a2]", + "Root/A/S2[(p0_AID = a2 => p0_AID else AID) - a2]", "Root/A/S2[a2]", }))); + assertTrue( + d.getTransParamsIdx(tfqn) + .equals(Arrays.asList(0,1))); } @Test @@ -569,63 +578,63 @@ public void overall3() { DashModule d = test("overall3"); String tfqn = "Root/A/S2/t1"; assertTrue( - src(d, tfqn).equals("Root/A/S2[pAID]")); + src(d, tfqn).equals("Root/A/S2[p0_AID]")); assertTrue( dest(d, tfqn).equals("Root/A/B/S1[a1, b1]")); assertTrue( d.getScope(tfqn).toString() - .equals("Root/A[(pAID = a1 => pAID else AID)]")); + .equals("Root/A[(p0_AID = a1 => p0_AID else AID)]")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/A/B/S1[(pAID = a1 => pAID else AID), BID]", - "Root/A/S2[(pAID = a1 => pAID else AID)]" + "Root/A/B/S1[(p0_AID = a1 => p0_AID else AID), BID]", + "Root/A/S2[(p0_AID = a1 => p0_AID else AID)]" }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A/S2[(pAID = a1 => pAID else AID) - a1]", + "Root/A/S2[(p0_AID = a1 => p0_AID else AID) - a1]", "Root/A/B/S1[a1, BID - b1]", "Root/A/B/S1[a1, b1]" }))); tfqn = "Root/A/B/S1/t2"; assertTrue( - src(d, tfqn).equals("Root/A/B/S1[pAID, pBID]")); + src(d, tfqn).equals("Root/A/B/S1[p0_AID, p1_BID]")); assertTrue( - dest(d, tfqn).equals("Root/A/B/S1[pAID, pBID]")); + dest(d, tfqn).equals("Root/A/B/S1[p0_AID, p1_BID]")); assertTrue( d.getScope(tfqn).toString() - .equals("Root/A/B/S1[pAID, pBID]")); + .equals("Root/A/B/S1[p0_AID, p1_BID]")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/A/B/S1[pAID, pBID]" + "Root/A/B/S1[p0_AID, p1_BID]" }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A/B/S1[pAID, pBID]" + "Root/A/B/S1[p0_AID, p1_BID]" }))); tfqn = "Root/A/B/S1/t3"; assertTrue( - src(d, tfqn).equals("Root/A/B/S1[pAID, b1]")); + src(d, tfqn).equals("Root/A/B/S1[p0_AID, b1]")); assertTrue( - dest(d, tfqn).equals("Root/A/B/S1[pAID, b2]")); + dest(d, tfqn).equals("Root/A/B/S1[p0_AID, b2]")); assertTrue( d.getScope(tfqn).toString() - .equals("Root/A/B/S1[pAID, (b1 = b2 => b1 else BID)]")); + .equals("Root/A/B/S1[p0_AID, (b1 = b2 => b1 else BID)]")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/A/B/S1[pAID, (b1 = b2 => b1 else BID)]" + "Root/A/B/S1[p0_AID, (b1 = b2 => b1 else BID)]" }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A/B/S1[pAID, (b1 = b2 => b1 else BID) - b2]", - "Root/A/B/S1[pAID, b2]" + "Root/A/B/S1[p0_AID, (b1 = b2 => b1 else BID) - b2]", + "Root/A/B/S1[p0_AID, b2]" }))); } @@ -726,46 +735,46 @@ public void overall6() { DashModule d = test("overall6"); String tfqn = "Root/B/S1/t1"; assertTrue( - src(d, tfqn).equals("Root/B/S1[pBID]")); + src(d, tfqn).equals("Root/B/S1[p0_BID]")); assertTrue( - dest(d, tfqn).equals("Root/B[pBID]")); + dest(d, tfqn).equals("Root/B[p0_BID]")); assertTrue( d.getScope(tfqn).toString() - .equals("Root/B[pBID]")); + .equals("Root/B[p0_BID]")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/B/S1[pBID]", + "Root/B/S1[p0_BID]", }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/B/S1[pBID]", + "Root/B/S1[p0_BID]", }))); tfqn = "Root/B/S1/t2"; assertTrue( - src(d, tfqn).equals("Root/B/S1[pBID]")); + src(d, tfqn).equals("Root/B/S1[p0_BID]")); assertTrue( dest(d, tfqn).equals("Root/B[b1]")); assertTrue( d.getScope(tfqn).toString() - .equals("Root/B[(pBID = b1 => pBID else BID)]")); + .equals("Root/B[(p0_BID = b1 => p0_BID else BID)]")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/B/S1[(pBID = b1 => pBID else BID)]", + "Root/B/S1[(p0_BID = b1 => p0_BID else BID)]", }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/B/S1[(pBID = b1 => pBID else BID) - b1]", + "Root/B/S1[(p0_BID = b1 => p0_BID else BID) - b1]", "Root/B/S1[b1]" }))); tfqn = "Root/B/S1/t3"; assertTrue( - src(d, tfqn).equals("Root/B/S1[pBID]")); + src(d, tfqn).equals("Root/B/S1[p0_BID]")); assertTrue( dest(d, tfqn).equals("Root/C[]")); assertTrue( @@ -783,6 +792,9 @@ public void overall6() { "Root/C[]" }))); + assertTrue( + d.getTransParamsIdx(tfqn) + .equals(Arrays.asList(0))); } @Test @@ -947,4 +959,27 @@ public void overall12() { dest(d, tfqn).equals("Root/S1/S7[]")); } + @Test + public void overall13() { + DashModule d = test("overall13"); + String tfqn = "Root/A/B/t1"; + assertTrue( + d.getTransParamsIdx(tfqn) + .equals(Arrays.asList(0,1))); + tfqn = "Root/A/t2"; + assertTrue( + d.getTransParamsIdx(tfqn) + .equals(Arrays.asList(0))); + tfqn = "Root/C/t3"; + assertTrue( + d.getTransParamsIdx(tfqn) + .equals(Arrays.asList(2))); + tfqn = "Root/C/D/t4"; + assertTrue( + d.getTransParamsIdx(tfqn) + .equals(Arrays.asList(2,3))); + assertTrue( + d.getAllParamsInOrder() + .equals(Arrays.asList("AID","BID","BID","AID"))); + } } diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall1-traces.als b/org.alloytools.alloy.dash/src/test/resources/pass/overall1-traces.als deleted file mode 100644 index 3eaf29073..000000000 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall1-traces.als +++ /dev/null @@ -1,60 +0,0 @@ -open util/ordering[Snapshot] as Snapshot -abstract sig StateLabel {} -abstract sig Root extends StateLabel {} -abstract sig Root_A extends Root {} -abstract sig Root_A_B extends Root_A {} -one sig Root_A_B_S1 extends Root_A_B {} -abstract sig Root_C extends Root {} -one sig Root_C_S2 extends Root_C {} - -abstract sig TransitionLabel {} -one sig Root_t1 extends TransitionLabel {} - -abstract sig Identifiers {} -sig AID extends Identifiers {} -sig BID extends Identifiers {} -sig CID extends Identifiers {} - -sig Snapshot { - taken0 : set TransitionLabel, - conf0 : set StateLabel, - conf1 : Identifiers -> StateLabel, - conf2 : Identifiers -> Identifiers -> StateLabel, - stable : one boolean/Bool -} - -pred Root_t1_pre[s : one Snapshot] { - -} - - -pred Root_t1_post[s : one Snapshot, sNext : one Snapshot] { - sNext. (conf0) = s. (conf0) - sNext. (conf1) = { { s. (conf1) - Root/C/S2 } + Root/C/S2 + Root/C/S2 } - sNext. (conf2) = { { s. (conf2) - { AID -> Root/A/B/S1 } } + { AID -> Root/A/B/S1 } } -} - -pred Root_t1_semantics[s : one Snapshot, sNext : one Snapshot] { - (stable = boolean/True => - sNext. (taken0) = Root_t1 - else { - sNext. (taken0) = { s. (taken0) + Root_t1 } } -) -} - - -pred Root_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { - -} - - -pred Root_t1[s : one Snapshot, sNext : one Snapshot] { - s. (Root_t1_pre) - sNext. (s. (Root_t1_post)) - sNext. (s. (Root_t1_semantics)) -} - -pred small_step[s : one Snapshot, sNext : one Snapshot] { - (some pAID: one AID,pBID: one BID,pCID: one CID | { sNext. (s. (Root_t1)) }) -} - diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall13.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall13.dsh new file mode 100644 index 000000000..07da21824 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall13.dsh @@ -0,0 +1,14 @@ +state Root { + conc A [AID] { + conc B [BID] { + trans t1 {} + } + trans t2 {} + } + conc C [BID] { + trans t3 {} + conc D [AID] { + trans t4 {} + } + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh index 63f0cd76b..394d4505b 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall3.dsh @@ -4,8 +4,8 @@ state Root { state S1 { trans t2 {} trans t3 { - from Root/A/B/S1[pAID, b1] - goto Root/A/B/S1[pAID, b2] + from Root/A/B/S1[p0_AID, b1] + goto Root/A/B/S1[p0_AID, b2] } } } diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall4-traces.als b/org.alloytools.alloy.dash/src/test/resources/pass/overall4-traces.als deleted file mode 100644 index a37d4bb76..000000000 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall4-traces.als +++ /dev/null @@ -1,66 +0,0 @@ -open util/ordering[Snapshot] as Snapshot -abstract sig StateLabel {} -sig Root extends StateLabel {} -one sig Root_A extends Root {} -one sig Root_A_B extends Root_A {} -one sig Root_A_B_S1 extends Root_A_B {} -one sig Root_A_S2 extends Root_A {} - -abstract sig Identifiers {} -sig AID extends Identifiers {} -sig BID extends Identifiers {} - -sig Snapshot { - scopesUsed0 : set StateLabel, - conf0 : set StateLabel, - scopesUsed1 : Identifiers -> Identifiers -> StateLabel, - conf1 : Identifiers -> Identifiers -> StateLabel, - scopesUsed2 : Identifiers -> Identifiers -> Identifiers -> StateLabel, - conf2 : Identifiers -> Identifiers -> Identifiers -> StateLabel, - stable : one boolean/Bool -} - -pred Root_A_B_S1_t1_pre[s : one Snapshot, pAID : one AID, pBID : one BID] { - { b1 -> a1 -> Root/A/B/S1 } in s. (conf2) - ! {Root in scopesUsed0} - ! {{ (a1 = a2 => a1 else { AID } ) -> Root/A } in scopesUsed1} -} - - -pred Root_A_B_S1_t1_post[s : one Snapshot, sNext : one Snapshot, pAID : one AID, pBID : one BID] { - sNext. (conf0) = s. (conf0) - sNext. (conf1) = { { s. (conf1) - { (a1 = a2 => a1 else { AID } ) -> Root/A/S2 } } + { a2 -> Root/A/S2 } } - sNext. (conf2) = { { s. (conf2) - { BID -> (a1 = a2 => a1 else { AID } ) -> Root/A/B/S1 } } + { BID -> { (a1 = a2 => - a1 - else { - AID } -) - a2 } -> Root/A/B/S1 } } - sNext. (conf0) = s. (conf0) - sNext. (conf1) = { s. (conf1) + { (a1 = a2 => a1 else { AID } ) -> Root/A } } - sNext. (conf2) = s. (conf2) -} - -pred Root_A_B_S1_t1_semantics[s : one Snapshot, sNext : one Snapshot, pAID : one AID, pBID : one BID] { - (stable = boolean/True => - sNext. (scopesUsed2) = { BID -> AID -> Root_A_B_S1_t1 } - else { - sNext. (scopesUsed2) = { s. (scopesUsed2) + { AID -> BID -> Root_A_B_S1_t1 } } } -) -} - - -pred Root_A_B_S1_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, pAID : one AID, pBID : one BID, t : one TransitionLabel] { - -} - - -pred Root_A_B_S1_t1[s : one Snapshot, sNext : one Snapshot, pAID : one AID, pBID : one BID] { - pBID. (pAID. (s. (Root_A_B_S1_t1_pre))) - pBID. (pAID. (sNext. (s. (Root_A_B_S1_t1_post)))) - pBID. (pAID. (sNext. (s. (Root_A_B_S1_t1_semantics)))) -} - -pred small_step[s : one Snapshot, sNext : one Snapshot] { - (some pAID: one AID,pBID: one BID | { pBID. (pAID. (sNext. (s. (Root_A_B_S1_t1)))) }) -} - diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall6.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/overall6.dsh index 5e37d585f..2c44239eb 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall6.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/overall6.dsh @@ -3,7 +3,7 @@ state Root { conc B [BID] { state S1 { trans t1 { - goto Root/B[pBID] + goto Root/B[p0_BID] } trans t2 { goto Root/B[b1] diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall7-traces.als b/org.alloytools.alloy.dash/src/test/resources/pass/overall7-traces.als deleted file mode 100644 index 472e3e809..000000000 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall7-traces.als +++ /dev/null @@ -1,114 +0,0 @@ -open util/ordering[Snapshot] as Snapshot -abstract sig StateLabel {} -abstract sig Root extends StateLabel {} -one sig Root_A extends Root {} -one sig Root_B extends Root {} -one sig Root_C extends Root {} -one sig Root_S1 extends Root {} - -abstract sig Identifiers {} -sig CID extends Identifiers {} - -sig Snapshot { - scopesUsed0 : set TransitionLabel, - conf0 : set StateLabel, - conf1 : Identifiers -> Identifiers -> StateLabel, - stable : one boolean/Bool -} - -pred Root_S1_t1_pre[s : one Snapshot] { - -} - - -pred Root_S1_t1_post[s : one Snapshot, sNext : one Snapshot] { - sNext. (conf0) = { { s. (conf0) - Root/S1 } + Root/S1 } - sNext. (conf1) = s. (conf1) -} - -pred Root_S1_t1_semantics[s : one Snapshot, sNext : one Snapshot] { - (stable = boolean/True => - sNext. (scopesUsed0) = Root_S1_t1 - else { - sNext. (scopesUsed0) = { s. (scopesUsed0) + Root_S1_t1 } } -) -} - - -pred Root_S1_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { - -} - - -pred Root_S1_t1[s : one Snapshot, sNext : one Snapshot] { - s. (Root_S1_t1_pre) - sNext. (s. (Root_S1_t1_post)) - sNext. (s. (Root_S1_t1_semantics)) -} - -pred Root_S1_t2_pre[s : one Snapshot] { - -} - - -pred Root_S1_t2_post[s : one Snapshot, sNext : one Snapshot] { - sNext. (conf0) = { { s. (conf0) - Root/A - Root/B - Root/S1 } + Root/A + Root/B } - sNext. (conf1) = { { s. (conf1) - { CID -> Root/C } } + { CID -> Root/C } } -} - -pred Root_S1_t2_semantics[s : one Snapshot, sNext : one Snapshot] { - (stable = boolean/True => - sNext. (scopesUsed0) = Root_S1_t2 - else { - sNext. (scopesUsed0) = { s. (scopesUsed0) + Root_S1_t2 } } -) -} - - -pred Root_S1_t2_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { - -} - - -pred Root_S1_t2[s : one Snapshot, sNext : one Snapshot] { - s. (Root_S1_t2_pre) - sNext. (s. (Root_S1_t2_post)) - sNext. (s. (Root_S1_t2_semantics)) -} - -pred Root_S1_t3_pre[s : one Snapshot] { - -} - - -pred Root_S1_t3_post[s : one Snapshot, sNext : one Snapshot] { - sNext. (conf0) = { { s. (conf0) - Root/A - Root/B - Root/S1 } + Root/A + Root/B } - sNext. (conf1) = { { s. (conf1) - { CID -> Root/C } } + { { CID - c1 } -> Root/C } + { c1 -> Root/C } } -} - -pred Root_S1_t3_semantics[s : one Snapshot, sNext : one Snapshot] { - (stable = boolean/True => - sNext. (scopesUsed0) = Root_S1_t3 - else { - sNext. (scopesUsed0) = { s. (scopesUsed0) + Root_S1_t3 } } -) -} - - -pred Root_S1_t3_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { - -} - - -pred Root_S1_t3[s : one Snapshot, sNext : one Snapshot] { - s. (Root_S1_t3_pre) - sNext. (s. (Root_S1_t3_post)) - sNext. (s. (Root_S1_t3_semantics)) -} - -pred small_step[s : one Snapshot, sNext : one Snapshot] { - (some pCID: one CID | { sNext. (s. (Root_S1_t1)) or - sNext. (s. (Root_S1_t2)) or - sNext. (s. (Root_S1_t3)) }) -} - diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/overall9-traces.als b/org.alloytools.alloy.dash/src/test/resources/pass/overall9-traces.als deleted file mode 100644 index fe2942631..000000000 --- a/org.alloytools.alloy.dash/src/test/resources/pass/overall9-traces.als +++ /dev/null @@ -1,71 +0,0 @@ -open util/ordering[Snapshot] as Snapshot -abstract sig StateLabel {} -abstract sig Root extends StateLabel {} -abstract sig Root_A extends Root {} -one sig Root_A_S1 extends Root_A {} -abstract sig Root_B extends Root {} -one sig Root_B_C extends Root_B {} -one sig Root_B_D extends Root_B {} -abstract sig Root_B_E extends Root_B {} -one sig Root_B_E_S2 extends Root_B_E {} -one sig Root_B_E_S4 extends Root_B_E {} -one sig Root_B_E_F extends Root_B_E {} -one sig Root_B_E_G extends Root_B_E {} -one sig Root_S3 extends Root {} - -abstract sig Identifiers {} -sig FID extends Identifiers {} -sig EID extends Identifiers {} -sig AID extends Identifiers {} - -sig Snapshot { - scopesUsed0 : set TransitionLabel, - conf0 : set StateLabel, - conf1 : Identifiers -> Identifiers -> StateLabel, - conf2 : Identifiers -> Identifiers -> Identifiers -> StateLabel, - stable : one boolean/Bool -} - -pred Root_t1_pre[s : one Snapshot] { - -} - - -pred Root_t1_post[s : one Snapshot, sNext : one Snapshot] { - sNext. (conf0) = s. (conf0) - sNext. (conf1) = { { s. (conf1) - { (e1 = e2 => e1 else { EID } ) -> Root/B/E/S2 } - { (e1 = e2 => - e1 - else { - EID } -) -> Root/B/E/S4 } - { (e1 = e2 => e1 else { EID } ) -> Root/B/E/G } } + { { (e1 = e2 => - e1 - else { - EID } -) - e2 } -> Root/B/E/S4 } + { e2 -> Root/B/E/G } } - sNext. (conf2) = { { s. (conf2) - { FID -> (e1 = e2 => e1 else { EID } ) -> Root/B/E/F } } + { FID -> e2 -> Root/B/E/F } } -} - -pred Root_t1_semantics[s : one Snapshot, sNext : one Snapshot] { - (stable = boolean/True => - sNext. (scopesUsed0) = Root_t1 - else { - sNext. (scopesUsed0) = { s. (scopesUsed0) + Root_t1 } } -) -} - - -pred Root_t1_isEnabledAfterStep[s : one Snapshot, sNext : one Snapshot, t : one TransitionLabel] { - -} - - -pred Root_t1[s : one Snapshot, sNext : one Snapshot] { - s. (Root_t1_pre) - sNext. (s. (Root_t1_post)) - sNext. (s. (Root_t1_semantics)) -} - -pred small_step[s : one Snapshot, sNext : one Snapshot] { - (some pFID: one FID,pEID: one EID,pAID: one AID | { sNext. (s. (Root_t1)) }) -} - From 5ddb4b83430a027f3a7869913bd8e995bc90e6ea Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 26 May 2023 11:09:30 -0400 Subject: [PATCH 043/129] adding stableTrue to init --- .../src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java | 1 + 1 file changed, 1 insertion(+) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index a5bd0a028..df325768e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -60,6 +60,7 @@ public static void addInit(DashModule d) { curEvents(i), allEnvironmentalEventsVar())); } + body.add(curStableTrue()); From 7fb7733ae9e44a0733d29b0ba224aa9eaed7c95a Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 26 May 2023 11:17:27 -0400 Subject: [PATCH 044/129] added stable to init --- .../src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java | 1 + 1 file changed, 1 insertion(+) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index df325768e..1aa22be40 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -60,6 +60,7 @@ public static void addInit(DashModule d) { curEvents(i), allEnvironmentalEventsVar())); } + //TODO could put this outside of quantifiers body.add(curStableTrue()); From 6612a63dd2b0dededccc9fbaa926f0da7d25b2a2 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 26 May 2023 12:22:20 -0400 Subject: [PATCH 045/129] moved init stable outside of quantifier --- .../main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 1aa22be40..29a278d22 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -34,6 +34,7 @@ public class AddInit { // -------------------------------------------------------------------------------------- /* TODO add here + TODO add Electrum */ public static void addInit(DashModule d) { @@ -60,8 +61,7 @@ public static void addInit(DashModule d) { curEvents(i), allEnvironmentalEventsVar())); } - //TODO could put this outside of quantifiers - body.add(curStableTrue()); + @@ -83,6 +83,8 @@ public static void addInit(DashModule d) { body = new ArrayList(); body.add(e); } + + body.add(curStableTrue()); // init is a reserved word in Electrum if (DashOptions.isElectrum) { d.alloyString += d.addPredSimple(DashStrings.initFactName, new ArrayList(), body); From 18a173a78cf50ebbc33a49e569ba668f10b48715 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 26 May 2023 13:57:51 -0400 Subject: [PATCH 046/129] stable in init only present for models with concurrency --- .../main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 29a278d22..9fd4341d4 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -83,8 +83,7 @@ public static void addInit(DashModule d) { body = new ArrayList(); body.add(e); } - - body.add(curStableTrue()); + if (d.hasConcurrency()) body.add(curStableTrue()); // init is a reserved word in Electrum if (DashOptions.isElectrum) { d.alloyString += d.addPredSimple(DashStrings.initFactName, new ArrayList(), body); From 52e57df77055be30b88e80cddb816f5fa10f14fa Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sat, 27 May 2023 15:37:10 -0400 Subject: [PATCH 047/129] redid dash cli to call resolveAlloy properly; added -r option --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 147 +++++++++--------- .../edu/mit/csail/sdg/parser/CompModule.java | 2 +- .../ca/uwaterloo/watform/core/DashErrors.java | 10 +- .../watform/mainfunctions/MainFunctions.java | 90 +++++++---- .../uwaterloo/watform/parser/DashModule.java | 9 +- 5 files changed, 153 insertions(+), 105 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index 492abcb09..fe4056240 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -21,6 +21,7 @@ import edu.mit.csail.sdg.translator.TranslateAlloyToKodkod; import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashErrors; // import ca.uwaterloo.watform.parser.DashUtil; import ca.uwaterloo.watform.core.DashUtilFcns; import ca.uwaterloo.watform.parser.DashModule; @@ -33,11 +34,41 @@ public class Dash { @SuppressWarnings("resource" ) + public static void executeCommands(CompModule c, Integer cmdnum, A4Reporter rep) { + // Choose some default options for how you want to execute the commands + A4Options options = new A4Options(); + + List commands = c.getAllCommands(); + // this is an annoying way to convert a list to an array + Integer i = 1; + for (Command cmd : commands) { + if (i == cmdnum | cmdnum == 0) { + System.out.println("Executing command: " + cmd); + A4Solution ans = null; + try { + ans = MainFunctions.executeCommand(cmd,c,rep, options); + } catch (Exception e) { + DashUtilFcns.handleException(e); + } + if (ans.satisfiable()) { + System.out.println("Result: SAT"); + } else { + System.out.println("Result: UNSAT"); + } + } + i++; + } + if (cmdnum >= i) { + System.err.println("Command number: " + cmdnum + " does not exist in file"); + } + } public static void main(String args[]) throws Exception { if(args.length == 0) { - System.out.println("Arguments: (-m traces|tcmc|electrum) (-c #) (-p) (-t) filename(s); -c is cmdnum; -t is translateOnly"); + System.out.println("Arguments: (-m traces|tcmc|electrum) (-c #) (-p) (-t) (-r) filename(s)"); + System.out.println(" -c is cmdnum; -t is translateOnly; -r is resolveOnly; -p is printDash"); + System.out.println("if given a .als files, it runs all its commands"); System.exit(0); } @@ -51,6 +82,7 @@ public static void main(String args[]) throws Exception { Integer cmdnum = 0; Boolean translateOnly = false; Boolean printOnly = false; + Boolean resolveOnly = false; for (int i=0; i commands = alloymodule.getAllCommands(); - // this is an annoying way to convert a list to an array - Integer i = 1; - for (Command cmd : commands) { - if (i == cmdnum | cmdnum == 0) { - System.out.println("Executing command: " + cmd); - A4Solution ans = null; - try { - ans = MainFunctions.executeCommand(cmd,alloymodule,rep, options); - } catch (Exception e) { - DashUtilFcns.handleException(e); - } - if (ans.satisfiable()) { - System.out.println("Result: SAT"); - } else { - System.out.println("Result: UNSAT"); + } else { + try { + DashModule d = MainFunctions.parseDashFile(filename, rep); + System.out.println("Parsed Dash file"); + if (d == null) DashErrors.emptyFile(filename); + if (printOnly) { + System.out.println(d.toStringAlloy()); + } else { + d = MainFunctions.resolveDash(d, rep); + System.out.println("Resolved Dash"); + CompModule c = MainFunctions.translate(d, rep); + System.out.println("Translated Dash to Alloy"); + // if problem exception would be raised + if (translateOnly) { + String outfilename = filename.substring(0,filename.length()-4) + "-" + method + ".als"; + File out = new File(outfilename); + if (!out.exists()) out.createNewFile(); + System.out.println("Creating: " + outfilename); + FileWriter fw = new FileWriter(out.getAbsoluteFile()); + BufferedWriter bw = new BufferedWriter(fw); + bw.write(d.toStringAlloy()); + bw.close(); + } else { + c = MainFunctions.resolveAlloy(c,rep); + System.out.println("Resolved Alloy"); + if (!resolveOnly) { + executeCommands(c,cmdnum,rep); } - } - i++; - } - if (cmdnum >= i) { - System.err.println("Command number: " + cmdnum + " does not exist in file"); + } } + } catch (Exception e) { + DashUtilFcns.handleException(e); } } } diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java index 1652f4b2d..adfea63e3 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/parser/CompModule.java @@ -2199,7 +2199,7 @@ else if (hasMetaField == false) * This method resolves the entire world; NOTE: if it throws an exception, it * may leave the world in an inconsistent state! */ - static CompModule resolveAll(final A4Reporter rep, final CompModule root) throws Err { + public static CompModule resolveAll(final A4Reporter rep, final CompModule root) throws Err { final List warns = new ArrayList(); for (CompModule m : root.getAllReachableModules()) root.allModules.add(m); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 667525b7c..0a5a3db8e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -152,8 +152,14 @@ public static String fqnVarWrongNumberParameters(String s1, String s2, String s3 public static String cantPrimeAnExternal(String s1, String s2) { throw new ErrorSyntax(cantPrimeAnExternalMsg + s1 + " in " + s2); } - - + public static String emptyModuleMsg = "Empty module"; + public static String emptyModule() { + throw new ErrorSyntax(emptyModuleMsg); + } + public static String emptyFileMsg = "Empty file: "; + public static String emptyFile(String fname) { + throw new ErrorSyntax(emptyFileMsg+fname); + } // parts of the code that should be unreachable ------------- diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index cdd7aea7b..9f7b27bc4 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -6,6 +6,7 @@ import edu.mit.csail.sdg.alloy4.A4Reporter; import edu.mit.csail.sdg.ast.Command; import edu.mit.csail.sdg.parser.CompModule; +import edu.mit.csail.sdg.parser.CompUtil; import edu.mit.csail.sdg.translator.A4Options; import edu.mit.csail.sdg.translator.A4Options.SatSolver; @@ -14,38 +15,81 @@ import ca.uwaterloo.watform.core.DashSituation; import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashErrors; import ca.uwaterloo.watform.parser.DashUtil; import ca.uwaterloo.watform.parser.DashModule; // no io in these! - +// A4 reporter is not used in Dash stuff public class MainFunctions { - // both these function expect DashOptions to be set + // all these function expect DashOptions to be set - public static DashModule parseAndResolveDashFile(String filename, A4Reporter rep) { - DashModule dash = null; + public static DashModule parseDashFile(String filename, A4Reporter rep) { + //DashOptions.isTraces = true; - DashOptions.isTraces = true; + // some necessary initialization for two passes of parsing DashSituation.haveCountedBuffers = false; DashSituation.bufferElements = new ArrayList(); DashSituation.bufferNames = new ArrayList(); - dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); - if (dash == null) { - System.err.println("Empty Alloy file"); + // first pass to collect buffers for open statements + DashModule d = DashUtil.parseEverything_fromFileDash(rep, null, filename); + if (d == null) { + DashErrors.emptyFile(filename); } else { DashSituation.haveCountedBuffers = true; - dash = DashUtil.parseEverything_fromFileDash(rep, null, filename); - //System.out.println(filename + " parsed successfully."); - // well-formedness checks - dash.resolveAllDash(rep); - //System.out.println(dash.toString()); + // second pass, which will put in appropriate open statements for buffers + d = DashUtil.parseEverything_fromFileDash(rep, null, filename); + } + return d; + } + public static DashModule resolveDash(DashModule d, A4Reporter rep) { + if (d == null) { + DashErrors.emptyModule(); + } else { + // done in place + d.resolveAllDash(rep); } - - return dash; + return d; } + public static DashModule translate(DashModule d, A4Reporter rep) { + if (d == null) { + DashErrors.emptyModule(); + } else { + // done in place + d.translate(); + } + return d; + } + + public static CompModule resolveAlloy(CompModule c, A4Reporter rep) { + CompModule o = null; + if (c == null) { + DashErrors.emptyModule(); + } else { + o = CompModule.resolveAll(rep,c); + } + return o; + } + + // make our CLI also work for .als files + public static CompModule parseAlloyFile(String filename, A4Reporter rep) { + CompModule c = CompUtil.parseEverything_fromFile(rep, null, filename); + if (c == null) { + DashErrors.emptyFile(filename); + } + return c; + } + + // for testing + public static DashModule parseAndResolveDashFile(String filename, A4Reporter rep) { + DashModule d = parseDashFile(filename,rep); + return resolveDash(d,rep); + } + + /* // only needed for testing public static void parseAndResolveAlloyFile(String filename, A4Reporter rep) { DashModule dash = null; @@ -67,16 +111,16 @@ public static void parseAndResolveAlloyFile(String filename, A4Reporter rep) { } } } - public static String dumpString(DashModule dash) { + + public static String alloyString(DashModule dash) { String s = null; - if (dash != null) { s = dash.toString(); } - return s; } - + */ + /* public static DashModule translate(DashModule dash, A4Reporter rep) { DashOptions.isTraces = true; @@ -91,17 +135,11 @@ public static DashModule translate(DashModule dash, A4Reporter rep) { return dash; } + */ public static A4Solution executeCommand(Command cmd, CompModule alloy, A4Reporter rep, A4Options options) { - - //TODO this should be an option also options.solver = A4Options.SatSolver.SAT4J; - A4Solution ans = TranslateAlloyToKodkod.execute_command(rep, alloy.getAllReachableSigs(), cmd, options); return ans; - } - - - } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 9f9fb20ba..65cd02543 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -588,7 +588,7 @@ public void resolveAllDash(A4Reporter rep) { public void translate() { assert(status == Status.RESOLVED_DASH); - System.out.println("Translating to Alloy"); + //System.out.println("Translating to Alloy"); // this is so we can partition the translation // code into a different file // translation is done in place @@ -596,6 +596,7 @@ public void translate() { // if no errors status = Status.TRANSLATED_TO_ALLOY; } + /* public void resolveAllAlloy(A4Reporter rep) { // this method in CompModule is static and takes a CompModule as // input and returns one as output even though it makes all the @@ -606,11 +607,11 @@ public void resolveAllAlloy(A4Reporter rep) { //assert(status == Status.TRANSLATED_TO_ALLOY); //System.out.println("Resolving Alloy"); // this quits if it throws an error - //resolveAll(rep == null ? A4Reporter.NOP : rep, this); + resolveAll(rep == null ? A4Reporter.NOP : rep, (CompModule) this); // if no errors - status = Status.RESOLVED_ALLOY; + //status = Status.RESOLVED_ALLOY; } - + */ // for testing public List getDefaults(String s) { return stateTable.getDefaults(s); From aaf2b92bd594f82e17bb3aa7f863ab1c8b433770 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sat, 27 May 2023 17:39:42 -0400 Subject: [PATCH 048/129] cleaned up printing --- .../watform/alloyasthelper/ExprToString.java | 43 ++++++++++++++----- .../watform/dashtoalloy/AddInit.java | 10 +++-- .../watform/parser/CompModuleHelper.java | 4 +- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index e9ab6efd1..6acba4eed 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -155,28 +155,35 @@ else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { ExprToOut(expr.right); out.end(); //out.print(")"); + } else if (expr.op == ExprBinary.Op.JOIN) { + // there are really long join expressions + //out.beginI(2); + addBracketsIfNeededNoBlocks(getLeft(expr)); + //out.brk(1,0); + out.print(expr.op); + //out.brk(1,0); + addBracketsIfNeededNoBlocks(getRight(expr)); + //out.end(); } else { out.beginI(2); addBracketsIfNeeded(getLeft(expr)); - out.brk(1,0); + //out.brk(1,0); + out.print(" "); out.print(expr.op); out.brk(1,0); addBracketsIfNeeded(getRight(expr)); out.end(); - } + /* - else if (expr.op == ExprBinary.Op.JOIN) { - out.print("("); - ExprBinaryJoinToOut(expr); - out.print(")"); } else if (expr.op == ExprBinary.Op.IMPLIES) { ExprToOut(expr.left); out.print(" => ").print("{ "); ExprToOut(expr.right); out.print(" } "); } + // This used to ensure that binary expressions have proper braces around them - else if ( isBinary(expr.right) || isBinary(expr.left) ) { + } else if ( isBinary(expr.right) || isBinary(expr.left) ) { if ( isBinary(expr.left) && !(exprOp(expr.left) == exprOp(expr)) && !(exprOp(expr.left) == ExprBinary.Op.JOIN)) { out.print('{').print(' '); ExprToOut(expr.left); @@ -197,10 +204,23 @@ else if ( isBinary(expr.right) || isBinary(expr.left) ) { ExprToOut(expr.left); out.print(' ').print(expr.op).print(' '); ExprToOut(expr.right); - } */ + } + } + private void addBracketsIfNeededNoBlocks(Expr expr) { + if (!(isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr) ))) { + //out.beginC(2); + out.print("("); + } + ExprToOut(expr); + if (!(isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr) ) )) { + out.print(")"); + //out.end(); + } + } + private void addBracketsIfNeeded(Expr expr) { if (!(isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr) ))) { out.beginC(2); @@ -211,13 +231,14 @@ private void addBracketsIfNeeded(Expr expr) { out.print(")"); out.end(); } - } + } + private void ExprBadJoinToOut(ExprBadJoin expr) { addBracketsIfNeeded(expr.left); out.print('.'); addBracketsIfNeeded(expr.right); } - + /* private void ExprBinaryJoinToOut(ExprBinary expr) { // The Alloy resolve dot joins (this) to a variable reference in a variable. We should not bring the ("this") @@ -429,7 +450,7 @@ private void ExprUnaryToOut(ExprUnary expr) { break; case NOT : out.print("!"); - out.brk(1,0); + //out.brk(1,0); addBracketsIfNeeded(expr.sub); break; case NOOP : diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 9fd4341d4..f020860cb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -55,11 +55,13 @@ public static void addInit(DashModule d) { // scopesUsedi = none body.add(createEquals( curScopesUsed(i), - createNone())); + createNoneArrow(i))); // no limits on initial set of events except that they must be environmental - body.add(createIn( - curEvents(i), - allEnvironmentalEventsVar())); + //s.events1 :> internalEvents = none -> none + if (d.hasEventsAti(i)) + body.add(createEquals( + createRangeRes(curEvents(i), allInternalEventsVar()), + createNoneArrow(i))); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index f75af84c9..13da71f72 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -311,9 +311,9 @@ public String addPredSimple(String name, List decls, List eList) { String s = new String(); s += DashStrings.predName + " " + name; if (!decls.isEmpty()) { - s += " ["; + s += " [\n\t"; //s += ppDecls(decls); - StringJoiner j = new StringJoiner(", "); + StringJoiner j = new StringJoiner(",\n\t"); decls.forEach(i -> j.add(ppDecl(i))); s += j.toString() + "]"; } From 9b4891a38525b20f523a0191966dcbc8cafe26ee Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 31 May 2023 21:14:37 -0400 Subject: [PATCH 049/129] rewrite of resolve functions to support thisA where A is a state --- .../main/java/edu/mit/csail/sdg/ast/Expr.java | 4 +- .../parser/Dash-cup-grammar.txt | 76 +-- .../parser/Dash-cup-imports.txt | 2 +- .../parser/Dash-cup-terminals.txt | 4 +- .../parser/Dash-lex-addition.txt | 4 +- org.alloytools.alloy.dash/parser/Dash.cup | 82 ++-- org.alloytools.alloy.dash/parser/Dash.lex | 4 +- .../watform/alloyasthelper/ExprHelper.java | 6 + .../watform/alloyasthelper/ExprToString.java | 23 +- .../ca/uwaterloo/watform/ast/DashFrom.java | 4 +- .../ca/uwaterloo/watform/ast/DashGoto.java | 4 +- .../ca/uwaterloo/watform/ast/DashState.java | 28 +- .../ca/uwaterloo/watform/ast/DashTrans.java | 2 +- .../ca/uwaterloo/watform/core/DashErrors.java | 62 ++- .../ca/uwaterloo/watform/core/DashRef.java | 456 +++++++++++++----- .../uwaterloo/watform/dashtoalloy/Common.java | 17 +- .../watform/mainfunctions/MainFunctions.java | 1 + .../watform/parser/CompModuleHelper.java | 1 + .../uwaterloo/watform/parser/DashModule.java | 10 +- .../uwaterloo/watform/parser/EventTable.java | 12 +- .../uwaterloo/watform/parser/ResolveExpr.java | 339 +++++++++++++ .../uwaterloo/watform/parser/StateTable.java | 45 +- .../uwaterloo/watform/parser/TransTable.java | 182 ++++++- .../ca/uwaterloo/watform/parser/VarTable.java | 200 +++----- .../alloytools/alloy/dash/DashEventTests.java | 6 +- .../alloytools/alloy/dash/DashStateTests.java | 148 +++--- .../alloy/dash/DashWffFailTests.java | 10 +- .../src/test/resources/pass/process-ref.dsh | 2 +- 28 files changed, 1217 insertions(+), 517 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java diff --git a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java index 9a4939175..2feb1531e 100644 --- a/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java +++ b/org.alloytools.alloy.core/src/main/java/edu/mit/csail/sdg/ast/Expr.java @@ -125,7 +125,7 @@ public final Type type() { * @param errors - the list of errors associated with this Expr node (can be * null if there are none) */ - Expr(Pos pos, Pos closingBracket, boolean ambiguous, Type type, int mult, long weight, JoinableList errors) { + public Expr(Pos pos, Pos closingBracket, boolean ambiguous, Type type, int mult, long weight, JoinableList errors) { this.pos = (pos == null ? Pos.UNKNOWN : pos); this.closingBracket = (closingBracket == null ? Pos.UNKNOWN : closingBracket); this.ambiguous = ambiguous; @@ -140,7 +140,7 @@ public final Type type() { } /** This must only be called by Sig's constructor. */ - Expr(Pos pos, Type type) { + public Expr(Pos pos, Type type) { this.closingBracket = Pos.UNKNOWN; this.ambiguous = false; this.errors = emptyListOfErrors; diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt index d507563c9..034797bfe 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -5,7 +5,7 @@ // besides creating a DashState; the parsing also has count buffers and create indexes // for those buffers in order to have the correct open statements -// no DashErrors here -- all are checked in wff checks +// a few Dash errors here // adding a case for the Spec Spec ::= Spec StateRoot:o ; @@ -288,65 +288,67 @@ TransItemList ::= TransItemList:c TransItem:x //Exprp is non-empty list of comma-separated Expr //Exprs could be empty ist of comma-separated Expr + +// src/dest --------------------- TransItem ::= FROM:o Name:n - {: RESULT = new DashFrom(o, new DashRef(o, n.label,DashRef.emptyParamValuesList())); :}; + {: RESULT = new DashFrom(o, DashRef.createStateDashRef(o, n.label,DashRef.emptyParamValuesList())); :}; -TransItem ::= FROM:o Name:n LBRACKET Exprp:e RBRACKET - {: RESULT = new DashFrom(o, new DashRef(o,n.label,e)); :}; +TransItem ::= FROM Name:n LBRACKET:o Exprp:e RBRACKET + {: RESULT = new DashFrom(o, DashRef.createStateDashRef(o,n.label,e)); :}; TransItem ::= GOTO:o Name:n - {: RESULT = new DashGoto(o, new DashRef(o,n.label,DashRef.emptyParamValuesList())); :}; + {: RESULT = new DashGoto(o, DashRef.createStateDashRef(o,n.label,DashRef.emptyParamValuesList())); :}; -TransItem ::= GOTO:o Name:n LBRACKET Exprp:e RBRACKET - {: - RESULT = new DashGoto(o, new DashRef(o, n.label,e)); - :}; +TransItem ::= GOTO Name:n LBRACKET:o Exprp:e RBRACKET + {: RESULT = new DashGoto(o, DashRef.createStateDashRef(o, n.label,e)); :}; + +// events A/B[a1]/ev1 --------------------------- + +TransItem ::= ON:o Name:n + {: RESULT = new DashOn(o, DashRef.createEventDashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; -// this allows "on x.ev1", "on A/ev1[x]" and "on n" in parsing but will have to sort out later to see if correct -TransItem ::= ON:o Expr:v - {: RESULT = new DashOn(o, v); :}; +TransItem ::= ON Name:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e + {: RESULT = new DashOn(o, DashRef.createEventDashRef(o, a.toString() + '/' + e.label, b)); :}; -//TransItem ::= ON:o Name:n -// {: //RESULT = new DashOn(o, new DashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; +TransItem ::= SEND:o Name:n + {: RESULT = new DashSend(o, DashRef.createEventDashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; -//TransItem ::= ON:o Name:n LBRACKET Expr:b RBRACKET -// {: //RESULT = new DashOn(o, new DashRef(o,n.label,e) ); :}; +TransItem ::= SEND Name:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e + {: RESULT = new DashSend(o, DashRef.createEventDashRef(o, a.toString() + '/' + e.label, DashRef.emptyParamValuesList()) ); :}; + +// actions/guards TransItem ::= WHEN:o Expr:v {: RESULT = new DashWhen(o, v); :}; TransItem ::= DO:o Expr:v {: RESULT = new DashDo(o, v); :}; -// this allows Send x.ev1 and "Send n" in parsing but will have to sort out later to see if correct -TransItem ::= SEND:o Expr:v - {: RESULT = new DashSend(o, v); :}; - -//TransItem ::= SEND:o Name:n -// {: RESULT = new DashSend(o, new DashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; - -//TransItem ::= SEND:o Name:n LBRACKET Exprp:e RBRACKET -// {: RESULT = new DashSend(o, new DashRef(o,n.label,e) ); :}; - -// DASH PLUS PROCESS REFERENCE -// in Alloy can't have a "/Variable" in the following so we need more syntax +// DASH PLUS REFERENCE +// in Alloy can't have a "/Variable" in the following as a regular +// expression so we need more syntax +// and this distinguishes it from other Alloy expressions // A/B/C[ParamValue1, ParamValue2]/Variable -// result ParamValue2.ParamValue1.A/B/C/Variable (using BadJoins) // note PRIME is a special token in grammar and we want to support v' BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e {: - Expr r = ExprVar.make(o, a.toString() + '/' + e.label); - Collections.reverse(b); - for (Expr x:b) r = ExprBinary.Op.JOIN.make(o,null, x, r); - RESULT= ExprBinary.Op.JOIN.make(o, null, DashRef.processRef(), r); + // have to find the error here + // because if put Name:a in rule above, get shift/reduce conflict + // and DashRef expects a String + if (!ExprHelper.isExprVar(a)) DashErrors.notVarBeforeDashRef(o,a.toString()); + else { + String r = a.toString() + '/' + e.label; + RESULT = DashRef.createVarDashRef(o, r, b); + } :}; BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e PRIME {: - Expr r = ExprVar.make(o, a.toString() + '/' + e.label + "'"); - Collections.reverse(b); - for (Expr x:b) r = ExprBinary.Op.JOIN.make(o,null, x, r); - RESULT= ExprBinary.Op.JOIN.make(o, null, DashRef.processRef(),r); + if (!ExprHelper.isExprVar(a)) DashErrors.notVarBeforeDashRef(o,a.toString()); + else { + String r = a.toString() + '/' + e.label + "'"; + RESULT = DashRef.createVarDashRef(o,r, b); + } :}; //DASH end grammar --------------------------------------------------------------------- diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt b/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt index c0ed41169..e87f115bf 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-imports.txt @@ -9,4 +9,4 @@ import edu.mit.csail.sdg.parser.MarkdownHandler; import ca.uwaterloo.watform.ast.*; import ca.uwaterloo.watform.core.*; - +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt b/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt index ffa42b34a..5f1e76a77 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt @@ -14,8 +14,8 @@ terminal Pos BUF; terminal Pos INIT; terminal Pos INVARIANT; -terminal Pos ACTION; -terminal Pos CONDITION; +//terminal Pos ACTION; +//terminal Pos CONDITION; terminal Pos TRANS; diff --git a/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt b/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt index e4ce2d2c5..fcf7e5092 100644 --- a/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt +++ b/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt @@ -10,8 +10,8 @@ "init" { return alloy_sym(yytext(), DashSym.INIT );} "invariant" { return alloy_sym(yytext(), DashSym.INVARIANT );} -"action" { return alloy_sym(yytext(), DashSym.ACTION );} -"condition" { return alloy_sym(yytext(), DashSym.CONDITION );} +//"action" { return alloy_sym(yytext(), DashSym.ACTION );} +//"condition" { return alloy_sym(yytext(), DashSym.CONDITION );} "trans" { return alloy_sym(yytext(), DashSym.TRANS );} diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index 1a414894c..19170a5ef 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -76,7 +76,7 @@ import edu.mit.csail.sdg.parser.MarkdownHandler; import ca.uwaterloo.watform.ast.*; import ca.uwaterloo.watform.core.*; - +import ca.uwaterloo.watform.alloyasthelper.ExprHelper; // @modified [electrum] added temporal operators to the AST (unary temporal operators // have the same precedence as other unary operators, binary ones have the @@ -591,8 +591,8 @@ terminal Pos BUF; terminal Pos INIT; terminal Pos INVARIANT; -terminal Pos ACTION; -terminal Pos CONDITION; +//terminal Pos ACTION; +//terminal Pos CONDITION; terminal Pos TRANS; @@ -1259,7 +1259,7 @@ BaseExpr ::= LBRACE:o Declz:a RBRACE:c {: RESULT = ExprQt.Op.COMPRE // besides creating a DashState; the parsing also has count buffers and create indexes // for those buffers in order to have the correct open statements -// no DashErrors here -- all are checked in wff checks +// a few Dash errors here // adding a case for the Spec Spec ::= Spec StateRoot:o ; @@ -1542,65 +1542,67 @@ TransItemList ::= TransItemList:c TransItem:x //Exprp is non-empty list of comma-separated Expr //Exprs could be empty ist of comma-separated Expr + +// src/dest --------------------- TransItem ::= FROM:o Name:n - {: RESULT = new DashFrom(o, new DashRef(o, n.label,DashRef.emptyParamValuesList())); :}; + {: RESULT = new DashFrom(o, DashRef.createStateDashRef(o, n.label,DashRef.emptyParamValuesList())); :}; -TransItem ::= FROM:o Name:n LBRACKET Exprp:e RBRACKET - {: RESULT = new DashFrom(o, new DashRef(o,n.label,e)); :}; +TransItem ::= FROM Name:n LBRACKET:o Exprp:e RBRACKET + {: RESULT = new DashFrom(o, DashRef.createStateDashRef(o,n.label,e)); :}; TransItem ::= GOTO:o Name:n - {: RESULT = new DashGoto(o, new DashRef(o,n.label,DashRef.emptyParamValuesList())); :}; + {: RESULT = new DashGoto(o, DashRef.createStateDashRef(o,n.label,DashRef.emptyParamValuesList())); :}; -TransItem ::= GOTO:o Name:n LBRACKET Exprp:e RBRACKET - {: - RESULT = new DashGoto(o, new DashRef(o, n.label,e)); - :}; +TransItem ::= GOTO Name:n LBRACKET:o Exprp:e RBRACKET + {: RESULT = new DashGoto(o, DashRef.createStateDashRef(o, n.label,e)); :}; + +// events A/B[a1]/ev1 --------------------------- + +TransItem ::= ON:o Name:n + {: RESULT = new DashOn(o, DashRef.createEventDashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; -// this allows "on x.ev1", "on A/ev1[x]" and "on n" in parsing but will have to sort out later to see if correct -TransItem ::= ON:o Expr:v - {: RESULT = new DashOn(o, v); :}; +TransItem ::= ON Name:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e + {: RESULT = new DashOn(o, DashRef.createEventDashRef(o, a.toString() + '/' + e.label, b)); :}; -//TransItem ::= ON:o Name:n -// {: //RESULT = new DashOn(o, new DashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; +TransItem ::= SEND:o Name:n + {: RESULT = new DashSend(o, DashRef.createEventDashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; -//TransItem ::= ON:o Name:n LBRACKET Expr:b RBRACKET -// {: //RESULT = new DashOn(o, new DashRef(o,n.label,e) ); :}; +TransItem ::= SEND Name:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e + {: RESULT = new DashSend(o, DashRef.createEventDashRef(o, a.toString() + '/' + e.label, DashRef.emptyParamValuesList()) ); :}; + +// actions/guards TransItem ::= WHEN:o Expr:v {: RESULT = new DashWhen(o, v); :}; TransItem ::= DO:o Expr:v {: RESULT = new DashDo(o, v); :}; -// this allows Send x.ev1 and "Send n" in parsing but will have to sort out later to see if correct -TransItem ::= SEND:o Expr:v - {: RESULT = new DashSend(o, v); :}; - -//TransItem ::= SEND:o Name:n -// {: RESULT = new DashSend(o, new DashRef(o, n.label,DashRef.emptyParamValuesList()) ); :}; - -//TransItem ::= SEND:o Name:n LBRACKET Exprp:e RBRACKET -// {: RESULT = new DashSend(o, new DashRef(o,n.label,e) ); :}; - -// DASH PLUS PROCESS REFERENCE -// in Alloy can't have a "/Variable" in the following so we need more syntax +// DASH PLUS REFERENCE +// in Alloy can't have a "/Variable" in the following as a regular +// expression so we need more syntax +// and this distinguishes it from other Alloy expressions // A/B/C[ParamValue1, ParamValue2]/Variable -// result ParamValue2.ParamValue1.A/B/C/Variable (using BadJoins) // note PRIME is a special token in grammar and we want to support v' BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e {: - Expr r = ExprVar.make(o, a.toString() + '/' + e.label); - Collections.reverse(b); - for (Expr x:b) r = ExprBinary.Op.JOIN.make(o,null, x, r); - RESULT= ExprBinary.Op.JOIN.make(o, null, DashRef.processRef(), r); + // have to find the error here + // because if put Name:a in rule above, get shift/reduce conflict + // and DashRef expects a String + if (!ExprHelper.isExprVar(a)) DashErrors.notVarBeforeDashRef(o,a.toString()); + else { + String r = a.toString() + '/' + e.label; + RESULT = DashRef.createVarDashRef(o, r, b); + } :}; BracketExprB ::= BracketExprB:a LBRACKET:o Exprs:b RBRACKET SLASH Name:e PRIME {: - Expr r = ExprVar.make(o, a.toString() + '/' + e.label + "'"); - Collections.reverse(b); - for (Expr x:b) r = ExprBinary.Op.JOIN.make(o,null, x, r); - RESULT= ExprBinary.Op.JOIN.make(o, null, DashRef.processRef(),r); + if (!ExprHelper.isExprVar(a)) DashErrors.notVarBeforeDashRef(o,a.toString()); + else { + String r = a.toString() + '/' + e.label + "'"; + RESULT = DashRef.createVarDashRef(o,r, b); + } :}; //DASH end grammar --------------------------------------------------------------------- diff --git a/org.alloytools.alloy.dash/parser/Dash.lex b/org.alloytools.alloy.dash/parser/Dash.lex index c241001b1..3f1bfdcda 100644 --- a/org.alloytools.alloy.dash/parser/Dash.lex +++ b/org.alloytools.alloy.dash/parser/Dash.lex @@ -253,8 +253,8 @@ import edu.mit.csail.sdg.parser.CompModule; "init" { return alloy_sym(yytext(), DashSym.INIT );} "invariant" { return alloy_sym(yytext(), DashSym.INVARIANT );} -"action" { return alloy_sym(yytext(), DashSym.ACTION );} -"condition" { return alloy_sym(yytext(), DashSym.CONDITION );} +//"action" { return alloy_sym(yytext(), DashSym.ACTION );} +//"condition" { return alloy_sym(yytext(), DashSym.CONDITION );} "trans" { return alloy_sym(yytext(), DashSym.TRANS );} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 3b25529fb..3dec1562c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -125,6 +125,9 @@ public static ExprVar createNone() { public static ExprVar createVar(String v) { return ExprVar.make(Pos.UNKNOWN, v); } + public static ExprVar createVar(Pos p, String v) { + return ExprVar.make(p, v); + } public static List createVarList(List vList) { List retList = new ArrayList(); for (String v: vList) { @@ -190,6 +193,9 @@ public static Expr createSet(Expr sub) { public static ExprBinary createJoin(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.JOIN.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } + public static ExprBinary createJoin(Pos p, Expr left, Expr right) { + return (ExprBinary) ExprBinary.Op.JOIN.make(p, p, left, right); + } public static Expr createJoinList(List elist) { Expr ret = null; assert(elist!=null); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index 6acba4eed..508b79e11 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -7,6 +7,7 @@ import java.util.StringJoiner; import java.util.List; import java.util.Collections; +import java.util.stream.Collectors; import de.uka.ilkd.pp.DataLayouter; import de.uka.ilkd.pp.NoExceptions; @@ -129,25 +130,25 @@ private Boolean isBinary(Expr e) { } */ private void ExprBinaryToOut(ExprBinary expr) { - if (DashRef.isDashRefProcessRef(expr)) { + if (DashRef.isDashRef(expr)) { // Root/A/B[exp1, exp2]/v1 - String v = DashRef.nameOfDashRefExpr(expr); + /* + String v = DashRef.getName(expr); String n = DashFQN.chopNameFromFQN(v); String prefix = DashFQN.chopPrefixFromFQN(v); //TODO: should do proper pretty printing for these! String s = prefix; s += "["; List el = new ArrayList(); - Expr e1 = getLeft(expr); - el.add(e1.toString()); - while (isExprJoin(e1)) { - el.add(e1.toString()); - e1 = getLeft(e1); - } - Collections.reverse(el); - s += DashUtilFcns.strCommaList(el); + List paramValues = + DashRef.getParamValues(expr).stream() + .map(i -> i.toString()) + .collect(Collectors.toList()); + Collections.reverse(paramValues); + s += DashUtilFcns.strCommaList(paramValues); s += "]/" + v; - out.print(s); + */ + out.print(expr.toString()); } else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { out.print("seq "); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java index 5fc23cb22..86dfce17e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java @@ -10,8 +10,8 @@ public class DashFrom extends Dash { - public DashRef src; - public DashFrom(Pos pos,DashRef d) { + public Expr src; + public DashFrom(Pos pos,Expr d) { assert(d != null); this.pos = pos; this.src = d; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java index 171a3761f..c5288c3c6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashGoto.java @@ -10,8 +10,8 @@ import ca.uwaterloo.watform.core.DashRef; public class DashGoto extends Dash { - public DashRef dest; - public DashGoto(Pos pos,DashRef d) { + public Expr dest; + public DashGoto(Pos pos,Expr d) { assert(d!=null); this.pos = pos; this.dest = d; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index f4d9a3980..604f741b6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -19,6 +19,9 @@ import ca.uwaterloo.watform.parser.TransTable; import ca.uwaterloo.watform.parser.EventTable; import ca.uwaterloo.watform.parser.VarTable; + +import static ca.uwaterloo.watform.parser.ResolveExpr.*; + //import ca.uwaterloo.watform.parser.BufferTable; public class DashState extends Dash { @@ -119,9 +122,14 @@ public static List noSubstates() { * check for errors in the state hierarchy * and put all states in the state table */ - public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, List params, List paramsIdx, List ances) { + public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, List ances) { + // this state is not yet in the st + // but its parent is in the st + if (DashFQN.isFQN(name)) DashErrors.stateNameCantBeFQN(pos, name); String sfqn = DashFQN.fqn(ances,name); + String parentfqn = DashFQN.fqn(ances); + //System.out.println("Resolving state "+sfqn); // make a copy of the items list so we can @@ -176,8 +184,12 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li // continue to add to list everywhere List newAnces = new ArrayList(ances); newAnces.add(name); - List newParams = new ArrayList(params); - List newParamsIdx = new ArrayList(paramsIdx); + List newParams = new ArrayList(); + List newParamsIdx = new ArrayList(); + if (parentfqn != null) { + newParams.addAll(st.getParams(parentfqn)); + newParamsIdx.addAll(st.getParamsIdx(parentfqn)); + } if (param != null) { newParams.add(param); int idx = st.addToParamsList(param); @@ -195,7 +207,7 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li if (substatesList.isEmpty() ) { - if (!st.add(sfqn, kind, param, newParams, newParamsIdx, def, DashFQN.fqn(ances), new ArrayList(), + if (!st.add(sfqn, kind, param, newParams, newParamsIdx, def,parentfqn, new ArrayList(), invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; } else { @@ -209,11 +221,11 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li DashErrors.dupSiblingNames(DashUtilFcns.strCommaList(dups.stream().collect(Collectors.toList()))); // add this state to the table - if (!st.add(sfqn,kind, param, newParams,newParamsIdx, def, DashFQN.fqn(ances), childFQNs, + if (!st.add(sfqn,kind, param, newParams,newParamsIdx, def, parentfqn, childFQNs, invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; // add all substates to the table - for (DashState s: substatesList) s.resolve(st, tt, et, vt, newParams, newParamsIdx, newAnces); + for (DashState s: substatesList) s.load(st, tt, et, vt, newAnces); // make sure defaults are correct // if there's only one child it is automatically the default @@ -325,10 +337,12 @@ public void resolve(StateTable st, TransTable tt, EventTable et, VarTable vt, Li .filter(i -> i instanceof DashTrans) .map(p -> (DashTrans) p) .collect(Collectors.toList()); + for (DashTrans t:transList) { //System.out.println("newAnces: " +newAnces); - t.resolve(tt, newParams, newParamsIdx, newAnces); + t.load(tt, newParams, newParamsIdx, newAnces); } + xItems.removeAll(transList); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java index cfa2e6e9e..fa3c81d72 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashTrans.java @@ -36,7 +36,7 @@ public String toString() { } return s; } - public void resolve(TransTable tt, List params, List paramsIdx, List ances) { + public void load(TransTable tt, List params, List paramsIdx, List ances) { if (DashFQN.isFQN(name)) DashErrors.transNameCantBeFQN(pos, name); String tfqn = DashFQN.fqn(ances,name); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 0a5a3db8e..216059bff 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -68,16 +68,26 @@ public static void fqnSrcDestMustHaveRightNumberParams(String xType, String tfqn public static void srcDestCantHaveParam(String xType, String tfqn) throws Err { throw new ErrorSyntax(srcDestCantHaveParamMsg + xType + " of transition "+ tfqn ); } - public static String ambiguousSrcDestMsg = "State name not unique within this conc/Root region: "; - public static void ambiguousSrcDest(String x, String tfqn) throws Err { - throw new ErrorSyntax(ambiguousSrcDestMsg + "trans "+tfqn+" "+x); + public static String ambiguousRefMsg = "Name not unique: "; + public static void ambiguousRef(Pos pos, String expString) throws Err { + throw new ErrorSyntax(pos + " " + ambiguousRefMsg + expString); } - // below this have not been tested + // below this have not been tested + public static String unknownStateMsg = "State does not exist: "; + public static void unknownState(Pos pos, String expString) { + throw new ErrorSyntax(pos + " " + unknownStateMsg + expString); + } + public static String unknownEventMsg = "Event does not exist: "; + public static void unknownEvent(Pos pos, String expString) { + throw new ErrorSyntax(pos + " " + unknownEventMsg + expString); + } + public static String nameShouldNotBePrimedMsg = "Declared state/trans/event/var cannot have a primed name: "; public static void nameShouldNotBePrimed(String n) { throw new ErrorSyntax(nameShouldNotBePrimedMsg+n); } + public static String transNameCantBeFQNMsg = "Trans name cannot be fully qualified at declaration: "; public static void transNameCantBeFQN(Pos o, String s) { throw new ErrorSyntax(o, transNameCantBeFQNMsg + s); @@ -113,14 +123,13 @@ public static void duplicateBufferName(Pos o, String s) { public static void tooMany(String xType, String tfqn) { throw new ErrorSyntax(tooManyMsg + xType + " in " + tfqn); } - public static String unknownEventMsg = "Event does not exist: "; - public static void unknownEvent(String xType, String v, String tfqn) { - throw new ErrorSyntax(unknownEventMsg +v+" in "+ tfqn +" "+ xType); - } + + /* public static String ambiguousEventMsg = "Event name not unique within this conc/Root region: "; public static void ambiguousEvent(String xType, String v, String tfqn) { throw new ErrorSyntax(ambiguousEventMsg +v+" in "+ tfqn + " "+xType); } + */ public static String fqnEventMissingParametersMsg = "Fully qualified event name missing paramaters: "; public static void fqnEventMissingParameters(String xType, String v, String tfqn) { throw new ErrorSyntax(fqnEventMissingParametersMsg + v + " in "+tfqn + " " + xType); @@ -135,9 +144,9 @@ public static void expNotEvent(String xType, String tfqn) { //public static void crossRefMoreThanOneArg(Pos o, String n) throws Err { // throw new ErrorSyntax(o,"Two many args to reference to "+n+" in sibling state"); //} - public static String noPrimedVarsInMsg = "Primed variables are not allowed in: "; - public static void noPrimedVarsIn(String s1, String s2, String s3) { - throw new ErrorSyntax(noPrimedVarsInMsg + s1 + " " + s2 + " "+s3); + public static String noPrimedVarsMsg = " Primed variables are not allowed in: "; + public static void noPrimedVars(Pos pos, String expString) { + throw new ErrorSyntax(pos + " " + noPrimedVarsMsg + expString); } public static String ambiguousVarMsg = "Var name not unique within this conc/Root region: "; public static void ambiguousVar(String xType, String v, String tfqn) { @@ -148,9 +157,9 @@ public static String fqnVarWrongNumberParameters(String s1, String s2, String s3 throw new ErrorSyntax(fqnVarWrongNumberParametersMsg + s1 + " "+s2 +" "+s3); } - public static String cantPrimeAnExternalMsg = "Internal var/buffer cannot be primed: "; - public static String cantPrimeAnExternal(String s1, String s2) { - throw new ErrorSyntax(cantPrimeAnExternalMsg + s1 + " in " + s2); + public static String cantPrimeAnExternalVarMsg = " Internal var/buffer cannot be primed: "; + public static String cantPrimeAnExternalVar(Pos pos, String expString) { + throw new ErrorSyntax(pos + " " + cantPrimeAnExternalVarMsg + expString); } public static String emptyModuleMsg = "Empty module"; public static String emptyModule() { @@ -160,6 +169,18 @@ public static String emptyModule() { public static String emptyFile(String fname) { throw new ErrorSyntax(emptyFileMsg+fname); } + public static String ambiguousUseOfThisMsg = " Ambiguous use of 'this' "; + public static String ambiguousUseOfThis(Pos pos, String expString) { + throw new ErrorSyntax(pos + ambiguousUseOfThisMsg + expString); + } + public static String nonParamUseOfThisMsg = " 'this' must refer to a parametrized state: "; + public static String nonParamUseOfThis(Pos pos, String expString) { + throw new ErrorSyntax(pos + nonParamUseOfThisMsg + expString); + } + public static String wrongNumberParamsMsg = " Incorrect number of parameters: "; + public static void wrongNumberParams(Pos pos, String expString) { + throw new ErrorSyntax(pos + " " + wrongNumberParamsMsg + expString); + } // parts of the code that should be unreachable ------------- @@ -167,9 +188,10 @@ public static String emptyFile(String fname) { public static void ancesNotPrefix(String a, String d) throws Err { throw new ErrorFatal(a + ancesNotPrefixMsg + d); } - - - // not tested below this line + public static String notVarBeforeDashRefMsg = "must be var: "; + public static void notVarBeforeDashRef (Pos o, String expString) { + throw new ErrorFatal(o + notVarBeforeDashRefMsg + expString); + } public static void toAlloyNoDash() throws Err { throw new ErrorFatal("Translating to Alloy when no Dash part"); } @@ -198,7 +220,7 @@ public static void bufferDoesNotExist(String s1, String n) throws Err { throw new ErrorFatal("for function "+s1+", buffer "+n+ " does not exist in buffer table"); } public static void varBufferDoesNotExist(String s1, String n) throws Err { - throw new ErrorFatal("for function "+s1+", buffer/var "+n+ " does not exist in buffer table"); + throw new ErrorFatal("for function "+s1+", "+n+ " does not exist in buffer or var table"); } public static void missingExpr(String s) throws Err { throw new ErrorFatal("Missing expr type in "+s); @@ -238,9 +260,7 @@ public static void nonDashRefExpr() throws Err { public static void eventTableEventNotFound(String m, String efqn) { throw new ErrorFatal("eventTableEventNotFound: "+m+" "+efqn); } - public static void regionMatchesWrongParamNumber() { - throw new ErrorFatal("regionMatchesWrongParamNumber"); - } + public static void createTestIfNextStableCallMultipleScopesAtSameLevel() { throw new ErrorFatal("createTestIfNextStableCallMultipleScopesAtSameLevel"); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index 8a91edfe4..53ba141e8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -1,21 +1,336 @@ +/* + These static methods let us treat an Expr as a reference to a Dash object + that has a name and a list of parameter values. + + From Root/A/B[exp1,exp2]/v1 in parsing + a DashRef is recorded in the AST as $$PROCESSREF$$ . exp2 . exp1 . Root/A/B/v1 + + After resolving, a DashRef with no params is $$PROCESSREF$$. var1 + + These references can be within Alloy Expr so we can't do a class extension. + + Even though we could do something different for states/events + (where they aren't referenced within Expr) + its best to use the same functions for all + + Note: we cannot allow any of + b1 -> a1 -> var1 + b1.a1.var1 + var1[a1,b1] + as a way to reference vars or events with parameter values b/c we cannot + tell the difference between the above and something like Chairs.occupied' + where "Chairs" is not a parameter value but a something to be joined with + occupied after it has all of its parameter values. +*/ + package ca.uwaterloo.watform.core; -import java.util.List; -import java.util.ArrayList; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.alloy4.ErrorType; +import edu.mit.csail.sdg.alloy4.ErrorWarning; +import edu.mit.csail.sdg.alloy4.JoinableList; +import edu.mit.csail.sdg.ast.Browsable; +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.mit.csail.sdg.ast.Type; +import edu.mit.csail.sdg.ast.VisitReturn; + + +import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +//import java.util.JoinableList; + import edu.mit.csail.sdg.alloy4.Pos; +//import edu.mit.csail.sdg.alloy4.ErrorWarning; +//import edu.mit.csail.sdg.alloy4.Err; +//import edu.mit.csail.sdg.ast.Type; +//import edu.mit.csail.sdg.ast.Browsable; +//import edu.mit.csail.sdg.ast.VisitReturn; import edu.mit.csail.sdg.ast.Expr; -import edu.mit.csail.sdg.ast.ExprBinary; -import edu.mit.csail.sdg.ast.ExprVar; +//import edu.mit.csail.sdg.ast.ExprBinary; +//import edu.mit.csail.sdg.ast.ExprVar; import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; import ca.uwaterloo.watform.core.DashUtilFcns; import ca.uwaterloo.watform.core.DashErrors; import ca.uwaterloo.watform.core.DashRef; -public class DashRef{ +public class DashRef extends Expr { + + //private Pos pos; + private DashRefKind kind; + private String name; + private List paramValues; + + // generally in the code we know the kind by context but + // for printing we need the kind here + // and this simplified some code for the DashRef to know its kind + private static enum DashRefKind { + STATE, + EVENT, + VAR + // BUFFER ???? + } + + // for internal uses + public DashRef(DashRefKind k, String n, List prmValues) { + super(Pos.UNKNOWN, Type.FORMULA); + this.kind = k; + this.name = n; + this.paramValues = prmValues; + //List ll = new ArrayList(eList); + //Collections.reverse(ll); + //ll.add(createVar(n)); + //return createJoin(processRef(), createJoinList(ll)); + } + + // for uses in parsing + public DashRef(Pos p, DashRefKind k, String n, List prmValues) { + super(p, Type.FORMULA); + this.kind = k; + this.name = n; + this.paramValues = prmValues; + //List ll = new ArrayList(eList); + //Collections.reverse(ll); + //ll.add(createVar(n)); + //return createJoin(processRef(), createJoinList(ll)); + } + + public static DashRef createStateDashRef(Pos p, String n, List prmValues) { + return new DashRef(p, DashRefKind.STATE,n, prmValues); + } + public static DashRef createEventDashRef(Pos p, String n, List prmValues) { + return new DashRef(p, DashRefKind.EVENT,n, prmValues); + + } + public static DashRef createVarDashRef(Pos p, String n, List prmValues) { + return new DashRef(p, DashRefKind.VAR,n, prmValues); + } + public static DashRef createStateDashRef(String n, List prmValues) { + return new DashRef(DashRefKind.STATE,n, prmValues); + } + public static DashRef createEventDashRef(String n, List prmValues) { + return new DashRef(DashRefKind.EVENT,n, prmValues); + + } + public static DashRef createVarDashRef(String n, List prmValues) { + return new DashRef(DashRefKind.VAR,n, prmValues); + } + + + /* + public static Expr createDashRef(Pos p, String n, List eList) { + List ll = new ArrayList(eList); + Collections.reverse(ll); + ll.add(createVar(p, n)); + return createJoin(p, processRef(), createJoinList(ll)); + } + */ + public static List emptyParamValuesList() { + return new ArrayList(); + } + + // we probably don't need this anymore + /* + private static Expr processRef() { + return createVar(DashStrings.processRef); + } + */ + + public static boolean isDashRef(Expr r) { + return (r instanceof DashRef); + /* + if (isExprJoin(e)) + if (isExprVar(getLeft(e))) + return sEquals(getLeft(e), processRef()); + return false; + */ + } + public String getName() { + return name; + } + public List getParamValues() { + return paramValues; + } + public boolean isState() { + return kind == DashRefKind.STATE; + } + public boolean isEvent() { + return kind == DashRefKind.EVENT; + } + public boolean isVar() { + return kind == DashRefKind.EVENT; + } + //public Pos getPos() { + // return pos; + //} + + public String toString() { + // STATE: Root/A/B[a1,b1] + // other: Root/A/B[a1,b1]/var1 + String s = ""; + if (kind == DashRefKind.STATE) { + s += getName(); + } else { + s += DashFQN.chopPrefixFromFQN(getName()); + } + + if (!paramValues.isEmpty()) { + s += "["; + List paramValues = + getParamValues().stream() + .map(i -> i.toString()) + .collect(Collectors.toList()); + //Collections.reverse(paramValues); + s += DashUtilFcns.strCommaList(paramValues); + s += "]"; + } + if (kind != DashRefKind.STATE) { + s += "/"; + s += DashFQN.chopNameFromFQN(getName()); + } + return s; + } + + /** {@inheritDoc} */ + @Override + public void toString(StringBuilder out, int indent) { + // STATE: Root/A/B[a1,b1] + // other: Root/A/B[a1,b1]/var1 + String s = ""; + if (kind == DashRefKind.STATE) { + out.append(getName()); + } else { + out.append(DashFQN.chopPrefixFromFQN(getName())); + } + if (!paramValues.isEmpty()) { + out.append("["); + List paramValues = + getParamValues().stream() + .map(i -> i.toString()) + .collect(Collectors.toList()); + //Collections.reverse(paramValues); + out.append(DashUtilFcns.strCommaList(paramValues)); + out.append("]"); + } + if (kind != DashRefKind.STATE) { + out.append("/"); + out.append(DashFQN.chopNameFromFQN(getName())); + } + } + + //TODO: fix below this line as these are methods + // that must be present to inherit from Expr + // but not sure what they should do + // or if it is okay to have them do nothing + // because DashRefs disappear in conversion to Alloy + /** {@inheritDoc} */ + @Override + public int getDepth() { + int max = 1; + for (Expr x : paramValues) { + int tmp = x.getDepth(); + if (max < tmp) + max = tmp; + } + return 1 + max; + } +/** {@inheritDoc} */ + @Override + public Expr resolve(Type p, Collection warns) { + // this is not needed because DashRef disappear before + // Alloy resolve + return createNone(); + } + /** {@inheritDoc} */ + @Override + public final T accept(VisitReturn visitor) throws Err { + return null; + } + /** {@inheritDoc} */ + @Override + public List< ? extends Browsable> getSubnodes() { + //Browsable a = make(var.pos, var.pos, "var " + var.label + " = ...", expr); + //Browsable b = make(sub.span(), sub.span(), "where...", sub); + return null; + } + /** {@inheritDoc} */ + @Override + public String getHTML() { + return ""; + } + /* + public static String getName(Expr e) { + assert(isDashRef(e) || isExprVar(e)); + if (isDashRef(e)) { + // might be a $$PROCESSREF$$.a.b.PRIME(e) + while (isExprJoin(e)) e = getRight(e); + assert(isExprVar(e)); + } + return getVarName((ExprVar) e); + } + public static List getParamValues(Expr e) { + assert(isDashRef(e) || isExprVar(e)); + List plist = new ArrayList(); + // strip off $$PROCESSREF$$ + if (isDashRef(e)) { + Expr f = getRight(e); + while (isExprJoin(f)) { + //System.out.println(f.toString()); + plist.add(getLeft(f)); + f = getRight(f); + } + } + return plist; + } + */ + /* + public static Expr subForDashRefArrow(Expr e, Expr r) { + if (isExprVar(e)) return r; + else return createArrow(getLeft(e), subForDashRefArrow(getRight(e),r)); + } + // works for Join or BadJoin + public static Expr subForDashRefJoin(Expr e, Expr r) { + if (isExprVar(e)) return r; + else return createJoin(getLeft(e), subForDashRefJoin(getRight(e),r)); + } + */ + /* + public Expr convertToJoin() { + List ll = new ArrayList(getParamValues()); + //Collections.reverse(ll); + ll.add(createVar(name)); + return createJoinList(ll); + } + public Expr convertToArrow() { + List ll = new ArrayList(getParamValues()); + //Collections.reverse(ll); + ll.add(createVar(name)); + return createArrowExprList(ll); + } + */ + /* + private static Expr convertDashRefToArrowAux(Expr e) { + //if (isExprVar(e)) return createVar(DashFQN.fqn(getVarName((ExprVar) e))); + //else return createArrow(getLeft(e), convertDashRefToArrowAux(getRight(e))); + } + */ + /* + public static Expr convertDashRefToArrow(Expr e) { + // removes $$PROCESSREF$$ and replaces joins with arrows + Expr e1 = getRight(e); + return convertDashRefToArrowAux(e1); + } + */ + + + /* private Pos pos; private String name; private List paramValues; @@ -36,19 +351,9 @@ public DashRef(String n, List eList) { //System.out.println(n); //System.out.println(eList); } + */ - // within expressions we can't have DashRefs - // so we'll fake it - public static Expr DashRefExpr(String n, List eList) { - // a lot like toAlloy - List ll = new ArrayList(eList); - Collections.reverse(ll); - ll.add(createVar(n)); - //System.out.println(ll); - //System.out.println(createJoin(processRef(), createJoinList(ll))); - return createJoin(processRef(), createJoinList(ll)); - } - + /* public String getName() { return name; } @@ -60,59 +365,10 @@ public String toString() { r += name + "[" + DashUtilFcns.strCommaList(paramValues) +"]"; return r; } - public static List emptyParamValuesList() { - return new ArrayList(); - } - - - - // the following operations are about Alloy expressions that - // represent joins from a DashRefs + */ - // These are: - // exp2. exp1. Root/A/B/v1 (from Root/A/B[exp1,exp2]/v1 with Joins for events and vars in exp) - // exp2. exp1. Root/A/B/v1 (with regular Joins for vars) - // exp2 -> exp1 -> Root/A/B/v1 (from events) - // We think it is a DashRef is there is a slash in the "name" - // slashes aren't regularly allowed in Alloy - // stuck in the formula the parser produces - // from Root/A/B[exp1,exp2]/v1 - public static Expr processRef() { - return createVar(DashStrings.processRef); - } - /* - could be used in an action or in an event expr - was built by new Expr rule in parser - Root/A/B[exp1,exp2]/v1 is recorded in the AST as - $$PROCESSREF$$ . exp2 . exp1 . Root/A/B/v1 - */ - public static boolean isDashRefProcessRef(Expr e) { - //System.out.println("in isDashRefProcessRef"+ e.toString()); - if (isExprJoin(e)) - if (isExprVar(getLeft(e))) - return sEquals(getLeft(e), processRef()); - return false; - } - public static Expr getDashRefProcessRefVar(Expr e) { - assert(isDashRefProcessRef(e)); - while (isExprJoin(e)) e = getRight(e); - // might be a $$PROCESSREF$$.a.b.PRIME(e) - return e; - } - public static List getDashRefProcessRefParamValues(Expr e) { - assert(isDashRefProcessRef(e)); - List plist = new ArrayList(); - // strip off $$PROCESSREF$$ - Expr f = getRight(e); - while (isExprJoin(f)) { - //System.out.println(f.toString()); - plist.add(getLeft(f)); - f = getRight(f); - } - return plist; - } /* can only be used in an action exp2. exp1. Root/A/B/v1 or @@ -169,74 +425,14 @@ public static boolean isDashRefArrow(Expr e) { /* from exp2. exp2. Root/A/B/v1' return Root/A/B/v1' */ - public static String nameOfDashRefExpr(Expr e) { - //assert(isDashRefProcessRef(e) || isDashRefJoin(e) || isDashRefArrow(e) || isDashRefBadJoin(e)); - Expr e2 = getRight(e); - while (/*isExprBadJoin(e2) ||*/ isExprJoin(e2)) { - e2 = getRight(e2); - } - assert(isExprVar(e2)); - String v = getVarName((ExprVar) e2); - //assert(DashFQN.isFQN(v)); - return v; - } - public static List paramValuesOfDashRefExpr(Expr e) { - List r = new ArrayList(); - Expr e1 = e; - if (isDashRefProcessRef(e1)) { - e1 = getRight(e1); // ignore $$PROCESSREF$$ - while (isExprJoin(e1)) { - r.add(getLeft(e1)); - e1 = getRight(e1); - } - } /* else if (isExprJoin(e1)) { - while (isExprJoin(e1)) { - r.add(getLeft(e1)); - e1 = getRight(e1); - } - } else if (isExprBadJoin(e1)) { - while (isExprBadJoin(e1)) { - r.add(getLeft(e1)); - e1 = getRight(e1); - } - } else if (isExprArrow(e1)) { - while (isExprArrow(e1)) { - r.add(getLeft(e1)); - e1 = getRight(e1); - } - } */ else { - DashErrors.nonDashRefExpr(); - return null; - } - return r; - } + /* replaceDashRefExprVar(exp2. exp1. Root/A/B/v1', sNext.Root/A/B/v1 ) returns exp2.exp1.sNext.Root/A/B/v1 */ - public static Expr subForDashRefArrow(Expr e, Expr r) { - if (isExprVar(e)) return r; - else return createArrow(getLeft(e), subForDashRefArrow(getRight(e),r)); - } - // works for Join or BadJoin - public static Expr subForDashRefJoin(Expr e, Expr r) { - if (isExprVar(e)) return r; - else return createJoin(getLeft(e), subForDashRefJoin(getRight(e),r)); - } - public static Expr convertDashRefProcessRefToArrow(Expr e) { - // removes $$PROCESSREF$$ and replaces joins with arrows - Expr e1 = getRight(e); - return convertDashRefProcessRefToArrowAux(e1); - } - public static Expr convertDashRefProcessRefToArrowAux(Expr e) { - if (isExprVar(e)) return fqnVar(e); - else return createArrow(getLeft(e), convertDashRefProcessRefToArrowAux(getRight(e))); - } - public static ExprVar fqnVar(Expr e) { - assert(isExprVar(e)); - return createVar(DashFQN.fqn(getVarName((ExprVar) e))); - } + + // referencing a for loop variable in a filter does not work // so do this as a loop public static List hasNumParams(List dr, int i) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index 33998521d..ea63fc037 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -41,6 +41,7 @@ public static Decl nextDecl() { return (Decl) new DeclExt(DashStrings.nextName, DashStrings.snapshotName); } + // p0:P0 public static Decl paramDecl(Integer n, String name) { return (Decl) new DeclExt(DashStrings.pName+n+"_"+name, name); @@ -264,30 +265,30 @@ public static Expr translateDashRefToJoin(DashRef e) { //TODO better name! public static boolean isWeirdOne(String vfqn, DashModule d) { + //System.out.println("Vqn: " + vfqn); return d.getVarBufferParams(vfqn).size() == 0 && isExprArrow(d.getVarType(vfqn)); } public static Expr translateExpr(Expr exp, DashModule d) { // special case for Variables.v1 if v1 has no params and has an // arrow type and isElectrum //System.out.println(exp); - if (DashRef.isDashRefProcessRef(exp)) { - // these remove $$PROCESSID$$ - Expr var = DashRef.getDashRefProcessRefVar(exp); + if (DashRef.isDashRef(exp)) { + String vName = ((DashRef) exp).getName(); // have to translate paramvalues // may be empty List paramValuesList = - DashRef.getDashRefProcessRefParamValues(exp).stream() + ((DashRef) exp).getParamValues().stream() .map(i -> translateExpr(i,d)) .collect(Collectors.toList()); //common subexpressions - Boolean hasPrime = DashStrings.hasPrime(getVarName((ExprVar) var)); - Boolean isWeirdOne = isWeirdOne(DashStrings.removePrime(getVarName((ExprVar) var)),d); - Expr voutNotPrime = createVar(translateFQN(DashStrings.removePrime(getVarName((ExprVar) var)))); + Boolean hasPrime = DashStrings.hasPrime(vName); + Boolean isWeirdOne = isWeirdOne(DashStrings.removePrime(vName),d); + Expr voutNotPrime = createVar(translateFQN(DashStrings.removePrime(vName))); Expr voutMayHavePrime; if (!hasPrime) voutMayHavePrime = voutNotPrime; else voutMayHavePrime = - createVar(translateFQN(DashStrings.removePrime(getVarName((ExprVar) var)))+DashStrings.PRIME); + createVar(translateFQN(DashStrings.removePrime(vName))+DashStrings.PRIME); //System.out.println(paramValuesList); if (DashOptions.isElectrum) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index 9f7b27bc4..fe436c379 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -52,6 +52,7 @@ public static DashModule resolveDash(DashModule d, A4Reporter rep) { // done in place d.resolveAllDash(rep); } + //d.debug(); return d; } public static DashModule translate(DashModule d, A4Reporter rep) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 13da71f72..951258094 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -39,6 +39,7 @@ public CompModuleHelper(CompModule world, String filename, String path) { } public String addOpenSimple(String name, List args, String aliasName) { + //System.out.println("adding open: "+name); ExprVar alias = (aliasName == null) ? null : createVar(aliasName); List argsExprList = new ArrayList(); if (args != null) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 65cd02543..592fce2a2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -455,7 +455,7 @@ public DashRef getScope(String tfqn) { break; } } - return new DashRef (sc,scopeParams); + return DashRef.createStateDashRef (sc,scopeParams); } // returns the list of states with params // that are exited when taking trans t @@ -504,7 +504,7 @@ public List scopesUsed(String tfqn) { createVar(stateTable.getParam(s.getName())), createNone()); prms.add(p); - r.add(new DashRef(s.getName(), prms)); + r.add(DashRef.createStateDashRef(s.getName(), prms)); } } // if it has a parameter it will be included @@ -565,7 +565,7 @@ public void resolveAllDash(A4Reporter rep) { root = roots.get(0); // passed with empty set of params, empty set of ancestors stateTable.setRoot(root.name); - root.resolve(stateTable,transTable, eventTable, varTable, new ArrayList(),new ArrayList(), new ArrayList()); + root.load(stateTable,transTable, eventTable, varTable, new ArrayList()); // have to do states first so siblings of trans parent state // are in place to search for src/dest // root.resolveTransTable(stateTable,transTable); @@ -573,10 +573,10 @@ public void resolveAllDash(A4Reporter rep) { // if no transitions? // resolves inits, invariants - stateTable.resolve(getRootName(), varTable); + stateTable.resolve(getRootName(), eventTable, varTable); transTable.resolve(stateTable, eventTable, varTable); - varTable.resolve(); + varTable.resolve(stateTable, eventTable); maxDepthParams = stateTable.getMaxDepthParams(); transAtThisParamDepth = transTable.transAtThisParamDepth(maxDepthParams); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index d4aa223c9..09f11c2fc 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -123,14 +123,14 @@ public boolean isInternalEvent(String efqn) { if (table.containsKey(efqn)) return (table.get(efqn).kind == IntEnvKind.INT); else { DashErrors.eventTableEventNotFound("isInternalEvent", efqn); return false; } } - public List allEventsOfState(String sfqn) { + public List getEventsOfState(String sfqn) { // return all events declared in this state // will have the sfqn as a prefix return table.keySet().stream() .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) .collect(Collectors.toList()); } - + /* public DashRef resolveEvent(String xType, Expr exp, List region, String tfqn, List tparamsIdx, List tparams, VarTable vt) { @@ -143,7 +143,7 @@ public DashRef resolveEvent(String xType, Expr exp, List region, String // BadJoin: ev[a1,b1] which became b1.a1.ev in parsing if (ExprHelper.isExprVar(exp) || //DashRef.isDashRefArrow(exp) || - DashRef.isDashRefProcessRef(exp))// || + DashRef.isDashRef(exp))// || //DashRef.isDashRefBadJoin(exp)) { String e; @@ -152,10 +152,10 @@ public DashRef resolveEvent(String xType, Expr exp, List region, String e = ExprHelper.getVarName((ExprVar) exp); paramValues = new ArrayList(); } else { - e = DashRef.nameOfDashRefExpr(exp); + e = exp.getName(); paramValues = // have to recursive through expressions in parameters - DashRef.paramValuesOfDashRefExpr(exp).stream() + exp.getParamValues().stream() .map(i -> vt.resolveExpr(xType, i, region, tfqn, tparamsIdx, tparams)) .collect(Collectors.toList()); } @@ -214,5 +214,5 @@ public DashRef resolveEvent(String xType, Expr exp, List region, String } } - + */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java new file mode 100644 index 000000000..47ac85387 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java @@ -0,0 +1,339 @@ +package ca.uwaterloo.watform.parser; + +import java.util.List; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Collections; +import java.util.stream.Collectors; + +import edu.mit.csail.sdg.alloy4.Pos; + +import edu.mit.csail.sdg.ast.Expr; +import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.ExprBinary; +import edu.mit.csail.sdg.ast.ExprUnary; +import edu.mit.csail.sdg.ast.ExprLet; +import edu.mit.csail.sdg.ast.ExprBadJoin; +import edu.mit.csail.sdg.ast.ExprCall; +import edu.mit.csail.sdg.ast.ExprChoice; +import edu.mit.csail.sdg.alloy4.ConstList; +import edu.mit.csail.sdg.ast.ExprITE; +import edu.mit.csail.sdg.ast.ExprList; +import edu.mit.csail.sdg.ast.ExprQt; +import edu.mit.csail.sdg.ast.ExprConstant; +import edu.mit.csail.sdg.ast.Decl; + +import static ca.uwaterloo.watform.core.DashUtilFcns.*; +import static ca.uwaterloo.watform.core.DashStrings.*; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashFQN; +import ca.uwaterloo.watform.core.DashRef; + +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; +import ca.uwaterloo.watform.dashtoalloy.Common; + + +public class ResolveExpr{ + + // returns an Expr (could be a DashRef) or raises an exception + // can be used for expr, event uses, state uses + // returned DashRef might have to be converted to a tuple for a state or an event in translation + + //TODO should probably be a visitor using accept methods of Expr + // have to recurse through exp types, replace dynamic vars with DashRef and rebuild exp + // don't use ExprHelper much here because we want to + // as much about the expression as possible + public static Expr resolveExpr( StateTable st, + EventTable et, + VarTable vt, + String kind, + boolean primeOk, + boolean primeOkInPrmValues, + boolean thisOk, + String sfqn, // could be parent of event or trans + Expr exp) { + + if (isExprVar(exp) || + isPrimedVar(exp) || + DashRef.isDashRef(exp)) + { + return resolveDashRef(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, exp); + + } else if (isExprBinary(exp)) { + return ((ExprBinary) exp).op.make( + exp.pos, + exp.closingBracket, + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); + + } else if (isExprBadJoin(exp)) { + return ExprBadJoin.make( + exp.pos, + exp.closingBracket, + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); + + } else if (exp instanceof ExprCall) { + return ExprCall.make( + exp.pos, + exp.closingBracket, + ((ExprCall) exp).fun, + ((ExprCall) exp).args.stream() + .map(i -> resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) + .collect(Collectors.toList()), + ((ExprCall) exp).extraWeight); + + } else if (exp instanceof ExprChoice){ + //TODO: check into this cast + // not sure why is it necessary + ConstList x = (ConstList) ((ExprChoice) exp).choices.stream() + .map(i -> resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) + .collect(Collectors.toList()); + return ExprChoice.make( + false, + exp.pos, + x, + ((ExprChoice) exp).reasons); + + } else if (exp instanceof ExprITE){ + return ExprITE.make( + exp.pos, + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getCond(exp)), + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); + + } else if (exp instanceof ExprList){ + return ExprList.make( + exp.pos, + exp.closingBracket, + ((ExprList) exp).op, + ((ExprList) exp).args.stream() + .map(i -> resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) + .collect(Collectors.toList()) + ); + + } else if (exp instanceof ExprUnary){ + return ((ExprUnary) exp).op.make( + exp.pos, + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprUnary) exp).sub)); + + } else if (exp instanceof ExprLet){ + //TODO rule out var name + return ExprLet.make( + exp.pos, + ((ExprLet) exp).var, + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprLet) exp).expr), + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprLet) exp).sub) ); + + } else if (exp instanceof ExprQt){ + //TODO rule out var names in delcs as dynamic vars later + + // have to convert the expressions in the decls too + List decls = ((ExprQt) exp).decls.stream() + .map(i -> new Decl( + i.isPrivate, + i.disjoint, + i.disjoint2, + i.isVar, + i.names, + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i.expr))) + .collect(Collectors.toList()); + + return ((ExprQt) exp).op.make( + exp.pos, + exp.closingBracket, + decls, + resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn,((ExprQt) exp).sub)); + + } else if (exp instanceof ExprConstant){ + return exp; + + } else { + DashErrors.UnsupportedExpr(exp.toString(), sfqn); + return null; + } + } + + static Expr resolveDashRef( StateTable st, + EventTable et, + VarTable vt, + String kind, + boolean primeOk, + boolean primeOkInPrmValues, + boolean thisOk, + String sfqn, // could be parent of event or trans + Expr exp) { + + // Join: b1.a1.var + + // DashRefProcessRef: A/B/C[a1,b1]/var which became $$PROCESSREF$$. b1.a1.A/B/C/var in parsing + // a DashRefProcessRef could be either a value for an exp + // or a tuple for an event + + // BadJoin: var[a1,b1] which became b1.a1.var in parsing + + // don't include isDashRefArrow here because that is only possible for + // events (which are tuples) not actions + + // turns PRIME(v) into v' + + assert(isExprVar(exp) || isPrimedVar(exp) || DashRef.isDashRef(exp)); + assert(kind.equals("state") || kind.equals("event") || kind.equals("var")); + String v; + List paramsIdx = st.getParamsIdx(sfqn); + List params = st.getParams(sfqn); + + List paramValues = new ArrayList(); + + Boolean isPrimed = false; + Pos pos = exp.pos(); + if (isExprVar(exp)) { + // no param values + v = getVarName((ExprVar) exp); + + if (thisOk && v.startsWith(thisName)) { + // thisSname gets replaced with p0_AID as a normal variable + // not a dashsref + String suffix = v.substring(thisName.length(),v.length()); + List matches = findMatchesInRegion(st,et,vt,"state",sfqn,suffix); + if (matches.size() == 1 && st.hasParam(matches.get(0))) + return Common.paramVar(st.getParamIdx(matches.get(0)), st.getParam(matches.get(0))); + else if (matches.size() == 1 && !st.hasParam(matches.get(0))) + DashErrors.nonParamUseOfThis(pos,exp.toString()); + else if (matches.size() > 1) { + DashErrors.ambiguousUseOfThis(pos,exp.toString()); + } + /* else we carry on with it as a regular var name with no params */ + } + } else if (isPrimedVar(exp)) { + // AlloyExpr is PrimeOp(name) + //System.out.println("isPrimedVar"); + isPrimed = true; + v = getVarName((ExprVar) getSub(exp)); + if (!primeOk) { DashErrors.noPrimedVars(pos, exp.toString()); return null; } + } else { + // name might not be fully resolved + // might have a prime on name + // due to the way DashRefs are parsed, + // they are not turned into PrimeOp(name) + v = ((DashRef) exp).getName(); + if (hasPrime(v)) { + isPrimed = true; + v = removePrime(v); + if (!primeOk) { DashErrors.noPrimedVars(pos, exp.toString()); return null; } + } + // have to recurse through param values as VARs + paramValues = ((DashRef) exp).getParamValues().stream() + .map(i -> resolveExpr(st, et, vt, "var", primeOkInPrmValues, primeOkInPrmValues, thisOk, sfqn, i)) + .collect(Collectors.toList()); + } + // now we have v as the name, paramValues as the possible empty set of resolved param values + // and isPrimed is set correctly + //System.out.println("looking for "+v); + List matches; + if (paramValues.isEmpty()) { + // if no param values must be within region + // that has same param values + matches = findMatchesInRegion(st,et,vt,kind,sfqn,v); + } else { + // if it has params values, could be suffix of any var + // and later we check it has the right number of params + matches = findMatches(st, et, vt, kind, v); + } + //System.out.println(matches); + if (matches.size() > 1) { + DashErrors.ambiguousRef(pos, exp.toString()); + return null; + } else if (matches.isEmpty()) { + if (kind.equals("state")) {DashErrors.unknownState(pos, exp.toString()); return null; } + else if (kind.equals("event")) { DashErrors.unknownEvent(pos, exp.toString()); return null; } + else { // it's some var other than a dynamic variable + //System.out.println("no match: "+exp.toString()); + return exp; + } + } else { + // one match + String m = matches.get(0); + List mParams; + if (kind.equals("state")) mParams = st.getParams(m); + else if (kind.equals("event")) mParams = et.getParams(m); + else mParams = vt.getParams(m); + + if (paramValues.isEmpty()) { + // must have same param values as sfqn b/c in same region + if (mParams.size() > paramsIdx.size()) { + // getRegion did not return things that all + // have the same parameter values + + DashErrors.wrongNumberParams(pos, exp.toString()); + return null; + } else { + // could be a subset of param values + paramValues = + Common.paramVars( + paramsIdx.subList(0, mParams.size()), + params.subList(0,mParams.size())); + } + } else if (mParams.size() != paramValues.size()) { + // came with parameters so must be right number + //TODO could paramValues b less than mParams???? + // and paramValues be a suffix of mParams??? + // since the name can be a suffix + DashErrors.wrongNumberParams(pos, exp.toString()); + return null; + } else + + if (isPrimed && kind.equals("var")) + if (!vt.isInternal(m)) { + DashErrors.cantPrimeAnExternalVar(pos, v); + return null; + } + if (isPrimed) m = m+PRIME; + if (kind.equals("state")) { return DashRef.createStateDashRef(pos, m, paramValues); } + else if (kind.equals("event")) { return DashRef.createEventDashRef(pos, m, paramValues); } + else { + //System.out.println(DashRef.createVarDashRef(pos, m, paramValues)); + return DashRef.createVarDashRef(pos, m, paramValues); + } + } + } + + private static List findMatchesInRegion(StateTable st, EventTable et, VarTable vt, String kind, String sfqn, String suffix) { + + List region = new ArrayList(); + if (kind.equals("state")) region = st.getRegion(sfqn); + else if (kind.equals("event")) { + for (String x: st.getRegion(sfqn)) region.addAll(et.getEventsOfState(x)); + } else if (kind.equals("var")) { + for (String x: st.getRegion(sfqn)) { + region.addAll(vt.getVarsOfState(x)); + region.addAll(vt.getBuffersOfState(x)); + } + } + return compareMatches(suffix,region); + } + private static List compareMatches(String suffix, List region) { + List matches = new ArrayList(); + for (String x:region) + // can't just end with the suffix b/c that might not be a complete name! + // e.g., Chairs can match xChairs and yChairs but those are actually different identifiers! + if (x.endsWith(suffix)) { + // matches to the very beginning + if (x.lastIndexOf(suffix) == 0) matches.add(x); + // matches starts with a "/" + else if (x.substring(x.lastIndexOf(suffix)-1,x.lastIndexOf(suffix)).equals("/")) matches.add(x); + } + return matches; + } + + private static List findMatches(StateTable st, EventTable et, VarTable vt, String kind, String suffix) { + List region = new ArrayList(); + if (kind.equals("state")) region.addAll(st.getAllStateNames()); + else if (kind.equals("event")) region.addAll(et.getAllEventNames()); + else if (kind.equals("var")) { + region.addAll(vt.getAllVarNames()); + region.addAll(vt.getAllBufferNames()); + } + return compareMatches(suffix,region); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 46c9d306c..5d6e59dec 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -274,7 +274,11 @@ public String getParam(String s) { return table.get(s).param; else { DashErrors.stateDoesNotExist("getParam", s); return null; } } - + public Integer getParamIdx(String s) { + if (table.containsKey(s) && hasParam(s)) + return lastElement(table.get(s).paramsIdx); + else { DashErrors.stateDoesNotExist("getParam", s); return null; } + } public boolean hasParam(String s) { if (table.containsKey(s)) return table.get(s).param != null; @@ -403,6 +407,22 @@ public List getAllParamsInOrder() { //} //return DashUtilFcns.setToList(allParams); } + public void resolve(String root, EventTable et, VarTable vt) { + // resolve inits and invariants + for (String sfqn: table.keySet()) { + inits.addAll( + table.get(sfqn).origInits.stream() + .map(i -> ResolveExpr.resolveExpr(this, et, vt, "var", false, false, true, sfqn, i.getInit())) + .collect(Collectors.toList())); + invs.addAll( + table.get(sfqn).origInvariants.stream() + .map(i -> ResolveExpr.resolveExpr(this, et, vt, "var", false, false, true, sfqn, i.getInv())) + .collect(Collectors.toList())); + + } + isResolved = true; + } + /* public void resolve(String root, VarTable vt) { // resolve inits and invariants for (String sfqn: table.keySet()) { @@ -422,6 +442,7 @@ public void resolve(String root, VarTable vt) { getParamsIdx(sfqn), getParams(sfqn))) .collect(Collectors.toList())); + // have to resolve variables here because need // other parameters to resolveExpr for (String vfqn: vt.getVarsOfState(sfqn)) { @@ -434,9 +455,11 @@ public void resolve(String root, VarTable vt) { getParamsIdx(sfqn), getParams(sfqn))); } + } isResolved = true; } + */ /* * this fcn figures out the src/dest of a transition @@ -448,7 +471,7 @@ public void resolve(String root, VarTable vt) { */ // tfqn is needed for error messages - + /* public DashRef resolveSrcDest(String xType, DashRef x, String tfqn, List tparamsIdx, List tparams, VarTable vt) { //System.out.println("Looking for: " + x); @@ -503,7 +526,7 @@ public DashRef resolveSrcDest(String xType, DashRef x, String tfqn, List getInits() { return inits; } @@ -522,7 +545,7 @@ public List getLeafStatesExited(DashRef s) { // exit all copies of the params List newParamValues = new ArrayList(s.getParamValues()); if (hasParam(ch)) newParamValues.add(ExprHelper.createVar(getParam(ch))); - r.addAll(getLeafStatesExited(new DashRef(ch, newParamValues))); + r.addAll(getLeafStatesExited(DashRef.createStateDashRef(ch, newParamValues))); } return r; } @@ -554,7 +577,7 @@ public List getLeafStatesEntered(DashRef s) { List newParamValues = new ArrayList(s.getParamValues()); if (hasParam(ch)) newParamValues.add(ExprHelper.createVar(getParam(ch))); - r.addAll(getLeafStatesEntered(new DashRef(ch, newParamValues))); + r.addAll(getLeafStatesEntered(DashRef.createStateDashRef(ch, newParamValues))); } } return r; @@ -562,7 +585,7 @@ public List getLeafStatesEntered(DashRef s) { public List getRootLeafStatesEntered() { List x = new ArrayList(); //System.out.println(getLeafStatesEntered(new DashRef(root,x))); - return getLeafStatesEntered(new DashRef(root,x)); + return getLeafStatesEntered(DashRef.createStateDashRef(root,x)); } public List allPrefixDashRefs(DashRef s) { List allPrefixFQNs = DashFQN.allPrefixes(s.getName()); @@ -570,10 +593,10 @@ public List allPrefixDashRefs(DashRef s) { int i = 0; for (String x:allPrefixFQNs) { if (isAnd(x) && hasParam(x)) { - r.add(new DashRef(x,s.getParamValues().subList(0,i+1))); + r.add(DashRef.createStateDashRef(x,s.getParamValues().subList(0,i+1))); i++; } else - r.add(new DashRef(x,s.getParamValues().subList(0,i))); + r.add(DashRef.createStateDashRef(x,s.getParamValues().subList(0,i))); } assert(i == s.getParamValues().size()); return r; @@ -612,7 +635,7 @@ public List getLeafStatesEnteredInScope(DashRef context, DashRef dest) e2 = dest.getParamValues().get(p); if (!ExprHelper.sEquals(e1, e2)) { nP.add(ExprHelper.createDiff(e1,e2)); - r.addAll(getLeafStatesEntered(new DashRef(c.getName(), nP))); + r.addAll(getLeafStatesEntered(DashRef.createStateDashRef(c.getName(), nP))); } // if equal this is empty so don't include it xP.add(e2); // just e2 for next one p++; @@ -638,7 +661,7 @@ public List getLeafStatesEnteredInScope(DashRef context, DashRef dest) if (!ExprHelper.sEquals(e1, e2)) { nP.add(ExprHelper.createDiff(e1, e2)); r.addAll(getLeafStatesEntered( - new DashRef(chOfDest.getName(),nP))); + DashRef.createStateDashRef(chOfDest.getName(),nP))); } // if equal this is empty so don't include it } //siblings @@ -653,7 +676,7 @@ public List getLeafStatesEnteredInScope(DashRef context, DashRef dest) if (hasParam(ch)) // add the entire param set nP.add(ExprHelper.createVar(getParam(ch))); - r.addAll(getLeafStatesEntered(new DashRef(ch,nP))); + r.addAll(getLeafStatesEntered(DashRef.createStateDashRef(ch,nP))); } } // if its an OR state, just go on to the next one diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 2dbeeeec8..24d9565de 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -24,6 +24,7 @@ //import ca.uwaterloo.watform.alloyasthelper.ExprToString; import ca.uwaterloo.watform.ast.*; import ca.uwaterloo.watform.dashtoalloy.Common; +import static ca.uwaterloo.watform.parser.ResolveExpr.*; // env events cannot be generated // env vars cannot be primed anywhere @@ -223,6 +224,185 @@ public List getHigherPriTrans(String t) { */ public void resolve(StateTable st, EventTable et, VarTable vt) { + //System.out.println(st); + //System.out.println(toString()); + //System.out.println("Resolving trans table"); + if (getAllTransNames().isEmpty()) DashErrors.noTrans(); + for (String tfqn: table.keySet()) { + //String tfqn = DashFQN.fqn(sfqn,t.name); + String sfqn = DashFQN.chopPrefixFromFQN(tfqn); + // determining the src state + List fList = + table.get(tfqn).fromList.stream() + .map(p -> (p.src)) + .collect(Collectors.toList()); + + if (fList.size() > 1) DashErrors.tooMany("from", tfqn); + else if (fList.isEmpty()) + // can be a loop on root + table.get(tfqn) + .setSrc(DashRef.createStateDashRef(sfqn, + Common.paramVars(getParamsIdx(tfqn), getParams(tfqn)))); + else + table.get(tfqn) + .setSrc((DashRef) resolveExpr(st, et, vt, "state", false, false, true, sfqn, fList.get(0))); + + // determining the dest state + List gList = + table.get(tfqn).gotoList.stream() + .map(p -> (p.dest)) + .collect(Collectors.toList()); + + if (gList.size() > 1) DashErrors.tooMany("goto", tfqn); + else if (gList.isEmpty()) + // can be a loop on root + table.get(tfqn) + .setDest(DashRef.createStateDashRef(sfqn, + Common.paramVars(getParamsIdx(tfqn),getParams(tfqn)))); + else + table.get(tfqn) + .setDest((DashRef) resolveExpr(st, et, vt, "state", false, true, true, sfqn, gList.get(0))); + + // determining the on (event) + List onExpList = + table.get(tfqn).onList.stream() + .map(p -> (p.getExp())) + .collect(Collectors.toList()); + if (onExpList.size() > 1) DashErrors.tooMany("on", tfqn); + else if (!onExpList.isEmpty()) { + table.get(tfqn) + .setOn((DashRef) resolveExpr(st, et, vt, "event", false, false, true, sfqn, onExpList.get(0))); + } + + // determining the send + List sendExpList = + table.get(tfqn).sendList.stream() + .map(p -> (p.getExp())) + .collect(Collectors.toList()); + if (sendExpList.size() > 1) DashErrors.tooMany("send", tfqn); + else if (!sendExpList.isEmpty()) { + table.get(tfqn) + .setSend((DashRef) resolveExpr(st, et, vt, "event", false, true, true, sfqn, sendExpList.get(0))); + } + + // determining the when (expr) + List whenExpList = + table.get(tfqn).whenList.stream() + .map(p -> (p.getWhen())) + .collect(Collectors.toList()); + if (whenExpList.size() > 1) DashErrors.tooMany("when", tfqn); + else if (!whenExpList.isEmpty()) { + table.get(tfqn) + .setWhen(resolveExpr(st, et, vt, "var", false, false, true, sfqn, whenExpList.get(0))); + } + + // determining the do + List doExpList = + table.get(tfqn).doList.stream() + .map(p -> (p.getDo())) + .collect(Collectors.toList()); + if (doExpList.size() > 1) DashErrors.tooMany("on", tfqn); + else if (!doExpList.isEmpty()) { + table.get(tfqn) + .setDo(resolveExpr(st, et, vt, "var", true, true, true, sfqn, doExpList.get(0))); + } + + } + isResolved = true; + } + + /* + public void resolve(StateTable st, EventTable et, VarTable vt) { + + //System.out.println(st); + //System.out.println(toString()); + //System.out.println("Resolving trans table"); + if (getAllTransNames().isEmpty()) DashErrors.noTrans(); + for (String tfqn: table.keySet()) { + //String tfqn = DashFQN.fqn(sfqn,t.name); + String sfqn = DashFQN.chopPrefixFromFQN(tfqn); + // determining the src state + List fList = + table.get(tfqn).fromList.stream() + .map(p -> (p.src)) + .collect(Collectors.toList()); + + if (fList.size() > 1) DashErrors.tooMany("from", tfqn); + else if (fList.isEmpty()) + // can be a loop on root + table.get(tfqn) + .setSrc(new DashRef(sfqn, Common.paramVars(getParamsIdx(tfqn), getParams(tfqn)))); + else + table.get(tfqn) + .setSrc(resolveExpr(st, et, vt, "state", false, false, true, sfqn, fList.get(0))); + + // determining the dest state + List gList = + table.get(tfqn).gotoList.stream() + .map(p -> (p.dest)) + .collect(Collectors.toList()); + + if (gList.size() > 1) DashErrors.tooMany("goto", tfqn); + else if (gList.isEmpty()) + // can be a loop on root + table.get(tfqn) + .setDest(new DashRef(sfqn, + Common.paramVars(getParamsIdx(tfqn),getParams(tfqn)))); + else + table.get(tfqn) + .setDest(resolveExpr(st, et, vt, "state", false, true, true, sfqn, gList.get(0))); + + // determining the on (event) + List onExpList = + table.get(tfqn).onList.stream() + .map(p -> (p.getExp())) + .collect(Collectors.toList()); + if (onExpList.size() > 1) DashErrors.tooMany("on", tfqn); + else if (!onExpList.isEmpty()) { + table.get(tfqn) + .setOn(resolveExpr(st, et, vt, "event", false, false, true, sfqn, onExpList.get(0))); + } + + // determining the send + List sendExpList = + table.get(tfqn).sendList.stream() + .map(p -> (p.getExp())) + .collect(Collectors.toList()); + if (sendExpList.size() > 1) DashErrors.tooMany("send", tfqn); + else if (!sendExpList.isEmpty()) { + table.get(tfqn) + .setSend(resolveExpr(st, et, vt, "event", false, true, true, sfqn, sendExpList.get(0))); + } + + // determining the when (expr) + List whenExpList = + table.get(tfqn).whenList.stream() + .map(p -> (p.getWhen())) + .collect(Collectors.toList()); + if (whenExpList.size() > 1) DashErrors.tooMany("when", tfqn); + else if (!whenExpList.isEmpty()) { + table.get(tfqn) + .setWhen(resolveExpr(st, et, vt, "var", false, false, true, sfqn, whenExpList.get(0))); + } + + // determining the do + List doExpList = + table.get(tfqn).doList.stream() + .map(p -> (p.getDo())) + .collect(Collectors.toList()); + if (doExpList.size() > 1) DashErrors.tooMany("on", tfqn); + else if (!doExpList.isEmpty()) { + table.get(tfqn) + .setDo(resolveExpr(st, et, vt, "var", true, true, true, sfqn, doExpList.get(0))); + } + + } + isResolved = true; + } + */ + /* + public void resolve(StateTable st, EventTable et, VarTable vt) { + //System.out.println(st); //System.out.println(toString()); //System.out.println("Resolving trans table"); @@ -344,7 +524,7 @@ else if (!doExpList.isEmpty()) { } isResolved = true; } - + */ diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index d31dc5917..e249fc991 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -19,6 +19,9 @@ import ca.uwaterloo.watform.core.DashRef; import ca.uwaterloo.watform.dashtoalloy.Common; +import ca.uwaterloo.watform.parser.StateTable; +import ca.uwaterloo.watform.parser.EventTable; + public class VarTable { // stores Var, Buffer Decls in a HashMap based on the event FQN @@ -86,9 +89,22 @@ public Boolean addVar(String vfqn, IntEnvKind k, List prms, List getAllVarNames() { return new ArrayList(varTable.keySet()); } @@ -122,6 +138,7 @@ public List getNamesOfState(String sfqn) { // same function for buffers and variables //TODO: what if var and buffer have the same name!!! public List getParams(String fqn) { + //System.out.println("getParams: " + fqn); if (bufferTable.containsKey(fqn)) return bufferTable.get(fqn).params; if (varTable.containsKey(fqn)) return varTable.get(fqn).params; else { DashErrors.varBufferDoesNotExist("getParams", fqn); return null; } @@ -207,117 +224,10 @@ public Boolean addBuffer(String vfqn, IntEnvKind k, List prms, List region, String fqn, List paramsIdx, List params) { - //System.out.println(exp); - if (isExprVar(exp) || - isPrimedVar(exp) || - //DashRef.isDashRefJoin(exp) || - DashRef.isDashRefProcessRef(exp)) // || - //DashRef.isDashRefBadJoin(exp)) - { - return dashRefVar(xType, exp, region, fqn, paramsIdx, params); - - } else if (isExprBinary(exp)) { - return ((ExprBinary) exp).op.make( - exp.pos, - exp.closingBracket, - resolveExpr(xType, getLeft(exp), region, fqn, paramsIdx, params), - resolveExpr(xType, getRight(exp), region, fqn, paramsIdx, params)); - - } else if (isExprBadJoin(exp)) { - return ExprBadJoin.make( - exp.pos, - exp.closingBracket, - resolveExpr(xType, getLeft(exp), region, fqn, paramsIdx, params), - resolveExpr(xType, getRight(exp), region, fqn, paramsIdx, params)); - - } else if (exp instanceof ExprCall) { - return ExprCall.make( - exp.pos, - exp.closingBracket, - ((ExprCall) exp).fun, - ((ExprCall) exp).args.stream() - .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx, params)) - .collect(Collectors.toList()), - ((ExprCall) exp).extraWeight); - - } else if (exp instanceof ExprChoice){ - //TODO: check into this cast - // not sure why is it necessary - ConstList x = (ConstList) ((ExprChoice) exp).choices.stream() - .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx, params)) - .collect(Collectors.toList()); - return ExprChoice.make( - false, - exp.pos, - x, - ((ExprChoice) exp).reasons); - - } else if (exp instanceof ExprITE){ - return ExprITE.make( - exp.pos, - resolveExpr(xType, getCond(exp), region, fqn, paramsIdx, params), - resolveExpr(xType, getLeft(exp), region, fqn, paramsIdx, params), - resolveExpr(xType, getRight(exp), region, fqn, paramsIdx, params)); - - } else if (exp instanceof ExprList){ - return ExprList.make( - exp.pos, - exp.closingBracket, - ((ExprList) exp).op, - ((ExprList) exp).args.stream() - .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx, params)) - .collect(Collectors.toList()) - ); - - } else if (exp instanceof ExprUnary){ - return ((ExprUnary) exp).op.make( - exp.pos, - resolveExpr(xType, ((ExprUnary) exp).sub, region, fqn, paramsIdx, params)); - - } else if (exp instanceof ExprLet){ - //TODO rule out var name - return ExprLet.make( - exp.pos, - ((ExprLet) exp).var, - resolveExpr(xType, ((ExprLet) exp).expr, region, fqn, paramsIdx, params), - resolveExpr(xType, ((ExprLet) exp).sub, region, fqn, paramsIdx, params)); - - } else if (exp instanceof ExprQt){ - //TODO rule out var names in delcs as dynamic vars later - - // have to convert the expressions in the decls too - List decls = ((ExprQt) exp).decls.stream() - .map(i -> new Decl( - i.isPrivate, - i.disjoint, - i.disjoint2, - i.isVar, - i.names, - resolveExpr(xType, i.expr, region, fqn, paramsIdx, params))) - .collect(Collectors.toList()); - - return ((ExprQt) exp).op.make( - exp.pos, - exp.closingBracket, - decls, - resolveExpr(xType, ((ExprQt) exp).sub, region, fqn, paramsIdx, params)); - - } else if (exp instanceof ExprConstant){ - return exp; - - } else { - DashErrors.UnsupportedExpr(xType, fqn); - return null; - } - } + /* // fqn could be trans or state - private Expr dashRefVar(String xType, Expr exp, List region, String fqn, List paramsIdx, List params) { + private Expr dashRefVar(StateTable st, TransTable tt, String xType, Expr exp, List region, String fqn, List paramsIdx, List params) { // Join: b1.a1.var @@ -333,21 +243,28 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, // turns PRIME(v) into v' String v; + List paramsIdx List paramValues; if (isExprVar(exp)) { v = getVarName((ExprVar) exp); - //TODO fix this!!! - /*if (v.startsWith(thisName)) { - // thisAID gets replaced with pAID as a normal variable + if (v.startsWith(thisName)) { + // thisSname gets replaced with p0_AID as a normal variable // not a processref String suffix = v.substring(thisName.length(),v.length()); - String match = ""; - for (String x:params) - if (x.equals(suffix)) - match = x; - if (!match.isEmpty()) - return createVar(pName+match); - }*/ + List match = new ArrayList(); + for (String x:region) + if (x.endsWith(suffix)) { + // x must exist because in region + Integer x = DashUtilFcns.lastElement(st.getParamsIdx(x)); + String p = DashUtilFcns.lastElement(st.getParams(x)); + match.add(Common.paramVar(x,p)); + } + if (match.size() == 1) + return match.get(0); + else if (match.size() > 1) + DashErrors.ambiguousUseOfThis(exp.toString()); + // else we carry on with it as a regular var name + } paramValues = new ArrayList(); } else if (isPrimedVar(exp)) { v = getVarName((ExprVar) getSub(exp))+PRIME; @@ -357,7 +274,7 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, v = DashRef.nameOfDashRefExpr(exp); // have to recurse through param values paramValues = DashRef.paramValuesOfDashRefExpr(exp).stream() - .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx, params)) + .map(i -> resolveExpr(st, xType, i, region, fqn, paramsIdx, params)) .collect(Collectors.toList()); } String vfqn = DashFQN.fqn(v); @@ -433,52 +350,49 @@ private Expr dashRefVar(String xType, Expr exp, List region, String fqn, m, // have to recursive through expressions in parameters paramValues.stream() - .map(i -> resolveExpr(xType, i, region, fqn, paramsIdx,params)) + .map(i -> resolveExpr(st, xType, i, region, fqn, paramsIdx,params)) .collect(Collectors.toList())); } } } + */ // must be done after resolve // might be primed or unprimed - public List collectDashRefs(Expr exp) { - if (DashRef.isDashRefProcessRef(exp)) { - List x = new ArrayList(); - x.add(exp); + public List collectDashRefs(Expr exp) { + List x = new ArrayList(); + if (DashRef.isDashRef(exp)) { + x.add((DashRef) exp); return x; } else if (isExprBinary(exp)) { - List x = new ArrayList(collectDashRefs(getLeft(exp))); + x.addAll(collectDashRefs(getLeft(exp))); x.addAll(collectDashRefs(getRight(exp))); return x; } else if (isExprBadJoin(exp)) { - List x = new ArrayList(collectDashRefs(getLeft(exp))); + x.addAll(collectDashRefs(getLeft(exp))); x.addAll(collectDashRefs(getRight(exp))); return x; } else if (exp instanceof ExprCall) { - List x = new ArrayList(); for (Expr e: ((ExprCall) exp).args) x.addAll(collectDashRefs(e)); return x; } else if (exp instanceof ExprChoice){ - List x = new ArrayList(); for (Expr e: ((ExprChoice) exp).choices) x.addAll(collectDashRefs(e)); return x; } else if (exp instanceof ExprITE){ - List x = new ArrayList(collectDashRefs(getCond(exp))); + x.addAll(collectDashRefs(getCond(exp))); x.addAll(collectDashRefs(getLeft(exp))); x.addAll(collectDashRefs(getRight(exp))); return x; } else if (exp instanceof ExprList){ - List x = new ArrayList(); for (Expr e: ((ExprCall) exp).args) x.addAll(collectDashRefs(e)); return x; } else if (exp instanceof ExprUnary){ return collectDashRefs(((ExprUnary) exp).sub); } else if (exp instanceof ExprLet){ - List x = new ArrayList(collectDashRefs(((ExprLet) exp).expr)); + x.addAll(collectDashRefs(((ExprLet) exp).expr)); x.addAll(collectDashRefs(((ExprLet) exp).sub)); return x; } else if (exp instanceof ExprQt){ - List x = new ArrayList(); List ll = ((ExprQt) exp).decls.stream() .map(i -> i.expr) .collect(Collectors.toList()); @@ -486,7 +400,7 @@ public List collectDashRefs(Expr exp) { x.addAll(collectDashRefs(((ExprQt) exp).sub)); return x; } else if (exp instanceof ExprConstant){ - return new ArrayList(); + return new ArrayList(); } else { DashErrors.UnsupportedExpr("collectDashRefs", ""); return null; @@ -494,16 +408,16 @@ public List collectDashRefs(Expr exp) { } // returns the primed variables in an exp (but w/o the primes) - public List primedDashRefs(Expr exp) { - List drs = collectDashRefs(exp); - List o = new ArrayList(); + public List primedDashRefs(Expr exp) { + List drs = collectDashRefs(exp); + List o = new ArrayList(); String v; List paramValues; - for (Expr e: drs) { - v = DashRef.nameOfDashRefExpr(e); - paramValues = DashRef.paramValuesOfDashRefExpr(e); + for (DashRef e: drs) { + v = e.getName(); + paramValues = e.getParamValues(); if (hasPrime(v)) { - o.add(DashRef.DashRefExpr(removePrime(v), paramValues)); + o.add(DashRef.createVarDashRef(removePrime(v), paramValues)); } } return o; diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashEventTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashEventTests.java index 4599129c2..8d1c9d5e3 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashEventTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashEventTests.java @@ -44,9 +44,9 @@ public void event1() { DashModule d = test("event1"); String tfqn = "Root/t1"; assertTrue( - on(d, tfqn).equals("Root/ev1[]")); + on(d, tfqn).equals("Root/ev1")); assertTrue( - send(d, tfqn).equals("Root/ev1[]")); + send(d, tfqn).equals("Root/ev1")); } @Test @@ -64,7 +64,7 @@ public void event3() { DashModule d = test("event3"); String tfqn = "Root/t1"; assertTrue( - on(d, tfqn).equals("Root/ev1[]")); + on(d, tfqn).equals("Root/ev1")); assertTrue( send(d, tfqn).equals("none")); } diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java index c353bd34e..f6f9c297a 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java @@ -68,38 +68,38 @@ public void noDefaultNeededTest2() { @Test public void noSrcDest1() { DashModule d = test("noSrcDest1"); - assertTrue(src(d,"Root/t1").equals("Root[]")); - assertTrue(dest(d,"Root/t1").equals("Root[]")); + assertTrue(src(d,"Root/t1").equals("Root")); + assertTrue(dest(d,"Root/t1").equals("Root")); } @Test public void noSrc1() { DashModule d = test("noSrc1"); - assertTrue(src(d,"Root/S1/t1").equals("Root/S1[]")); - assertTrue(dest(d,"Root/S1/t1").equals("Root/S2[]")); + assertTrue(src(d,"Root/S1/t1").equals("Root/S1")); + assertTrue(dest(d,"Root/S1/t1").equals("Root/S2")); } @Test public void noSrc2() { DashModule d = test("noSrc2"); - assertTrue(src(d,"Root/S1/t1").equals("Root/S1[]")); - assertTrue(dest(d,"Root/S1/t1").equals("Root/S2/S3/S4[]")); + assertTrue(src(d,"Root/S1/t1").equals("Root/S1")); + assertTrue(dest(d,"Root/S1/t1").equals("Root/S2/S3/S4")); } @Test public void otherSrcDest1() { DashModule d = test("otherSrcDest1"); - assertTrue(src(d,"Root/S1/t1").equals("Root/S1[]")); - assertTrue(dest(d,"Root/S1/t1").equals("Root/S2/S3/S4[]")); - assertTrue(src(d,"Root/S2/t2").equals("Root/S2/S3[]")); - assertTrue(dest(d,"Root/S2/t2").equals("Root/S2[]")); + assertTrue(src(d,"Root/S1/t1").equals("Root/S1")); + assertTrue(dest(d,"Root/S1/t1").equals("Root/S2/S3/S4")); + assertTrue(src(d,"Root/S2/t2").equals("Root/S2/S3")); + assertTrue(dest(d,"Root/S2/t2").equals("Root/S2")); } @Test public void srcDestFQN1() { DashModule d = test("srcDestFQN1"); - assertTrue(src(d,"Root/S1/t1").equals("Root/S1[]")); - assertTrue(dest(d,"Root/S1/t1").equals("Root/S1/S7[]")); - assertTrue(src(d,"Root/S2/S3/S4/t2").equals("Root/S2/S3/S4[]")); - assertTrue(dest(d,"Root/S2/S3/S4/t2").equals("Root/S1/S7[]")); + assertTrue(src(d,"Root/S1/t1").equals("Root/S1")); + assertTrue(dest(d,"Root/S1/t1").equals("Root/S1/S7")); + assertTrue(src(d,"Root/S2/S3/S4/t2").equals("Root/S2/S3/S4")); + assertTrue(dest(d,"Root/S2/S3/S4/t2").equals("Root/S1/S7")); } @Test @@ -187,7 +187,7 @@ public void allPrefixDashRefs1() { assertTrue( allPrefixDashRefs(d,"Root/A/S1/t1") .equals(ll(new String[]{ - "Root[]", + "Root", "Root/A[(p0_APID = x => p0_APID else APID)]" }))); } @@ -197,7 +197,7 @@ public void allPrefixDashRefs2() { assertTrue( allPrefixDashRefs(d, "Root/A/B/S1/t1") .equals(ll(new String[]{ - "Root[]", + "Root", "Root/A[(p0_APID = x => p0_APID else APID)]", "Root/A/B[(p0_APID = x => p0_APID else APID), (AND[p0_APID = x, p1_BPID = y] => p1_BPID else BPID)]" }))); @@ -208,7 +208,7 @@ public void allPrefixDashRefs3() { assertTrue( allPrefixDashRefs(d, "Root/A/B/S1/t1") .equals(ll(new String[]{ - "Root[]", + "Root", "Root/A[p0_APID]", "Root/A/B[p0_APID, p1_BPID]" }))); @@ -219,7 +219,7 @@ public void allPrefixDashRefs4() { assertTrue( allPrefixDashRefs(d, "Root/S1/t1") .equals(ll(new String[]{ - "Root[]", + "Root", }))); } @@ -238,8 +238,8 @@ public void getLeafStatesExited1() { assertTrue( exited(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S1[]", - "Root/S2[]" + "Root/S1", + "Root/S2" }))); } @Test @@ -248,8 +248,8 @@ public void getLeafStatesExited2() { assertTrue( exited(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S1[]", - "Root/S2/S3/S4[]" + "Root/S1", + "Root/S2/S3/S4" }))); } @Test @@ -258,7 +258,7 @@ public void getLeafStatesExited3() { assertTrue( exited(d,"Root/C/t1") .equals(ll(new String[]{ - "Root/C[]" + "Root/C" }))); } @Test @@ -267,7 +267,7 @@ public void getLeafStatesExited4() { assertTrue( exited(d,"Root/t1") .equals(ll(new String[]{ - "Root[]" + "Root" }))); } @Test @@ -276,13 +276,13 @@ public void getLeafStatesExited5() { assertTrue( exited(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S1[]", - "Root/S2/S3/S4[]" + "Root/S1", + "Root/S2/S3/S4" }))); assertTrue( exited(d,"Root/S2/t2") .equals(ll(new String[]{ - "Root/S2/S3/S4[]" + "Root/S2/S3/S4" }))); } @Test @@ -342,7 +342,7 @@ public void getLeafStatesEntered1() { assertTrue( entered(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S2[]" + "Root/S2" }))); } @Test @@ -351,7 +351,7 @@ public void getLeafStatesEntered2() { assertTrue( entered(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S2/S3/S4[]" + "Root/S2/S3/S4" }))); } @Test @@ -378,7 +378,7 @@ public void getLeafStatesEntered5() { assertTrue( entered(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S2/A[]" + "Root/S2/A" }))); } @Test @@ -387,7 +387,7 @@ public void getLeafStatesEntered6() { assertTrue( entered(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S2/A/S3[]" + "Root/S2/A/S3" }))); } @Test @@ -455,7 +455,7 @@ public void getLeafStatesEnteredInScope1() { assertTrue( enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S2[]" + "Root/S2" }))); } @Test @@ -464,8 +464,8 @@ public void getLeafStatesEnteredInScope2() { assertTrue( enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/B/S3[]", - "Root/A/S2[]", + "Root/B/S3", + "Root/A/S2", }))); } @Test @@ -474,7 +474,7 @@ public void getLeafStatesEnteredInScope3() { assertTrue( enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S2/A[]" + "Root/S2/A" }))); } @Test @@ -483,7 +483,7 @@ public void getLeafStatesEnteredInScope4() { assertTrue( enteredInScope(d,"Root/S1/t1") .equals(ll(new String[]{ - "Root/S2/A/S3[]" + "Root/S2/A/S3" }))); } @Test @@ -526,7 +526,7 @@ public void overall1() { assertTrue( dest(d, tfqn).equals("Root/C/S2[c1]")); assertTrue( - d.getScope(tfqn).toString().equals("Root[]")); + d.getScope(tfqn).toString().equals("Root")); assertTrue( exited(d,tfqn) @@ -776,20 +776,20 @@ public void overall6() { assertTrue( src(d, tfqn).equals("Root/B/S1[p0_BID]")); assertTrue( - dest(d, tfqn).equals("Root/C[]")); + dest(d, tfqn).equals("Root/C")); assertTrue( d.getScope(tfqn).toString() - .equals("Root[]")); + .equals("Root")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/C[]", + "Root/C", "Root/B/S1[BID]" }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/C[]" + "Root/C" }))); assertTrue( @@ -802,69 +802,69 @@ public void overall7() { DashModule d = test("overall7"); String tfqn = "Root/S1/t1"; assertTrue( - src(d, tfqn).equals("Root/S1[]")); + src(d, tfqn).equals("Root/S1")); assertTrue( - dest(d, tfqn).equals("Root/S1[]")); + dest(d, tfqn).equals("Root/S1")); assertTrue( d.getScope(tfqn).toString() - .equals("Root/S1[]")); + .equals("Root/S1")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/S1[]", + "Root/S1", }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/S1[]", + "Root/S1", }))); tfqn = "Root/S1/t2"; assertTrue( - src(d, tfqn).equals("Root/S1[]")); + src(d, tfqn).equals("Root/S1")); assertTrue( - dest(d, tfqn).equals("Root/B[]")); + dest(d, tfqn).equals("Root/B")); assertTrue( d.getScope(tfqn).toString() - .equals("Root[]")); + .equals("Root")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/A[]", - "Root/B[]", + "Root/A", + "Root/B", "Root/C[CID]", - "Root/S1[]", + "Root/S1", }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ - "Root/A[]", + "Root/A", "Root/C[CID]", - "Root/B[]", + "Root/B", }))); tfqn = "Root/S1/t3"; assertTrue( - src(d, tfqn).equals("Root/S1[]")); + src(d, tfqn).equals("Root/S1")); assertTrue( dest(d, tfqn).equals("Root/C[c1]")); assertTrue( d.getScope(tfqn).toString() - .equals("Root[]")); + .equals("Root")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ - "Root/A[]", - "Root/B[]", + "Root/A", + "Root/B", "Root/C[CID]", - "Root/S1[]", + "Root/S1", }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ "Root/C[CID - c1]", - "Root/A[]", - "Root/B[]", + "Root/A", + "Root/B", "Root/C[c1]" }))); @@ -874,29 +874,29 @@ public void overall8() { DashModule d = test("overall8"); String tfqn = "Root/t1"; assertTrue( - src(d, tfqn).equals("Root/S3[]")); + src(d, tfqn).equals("Root/S3")); assertTrue( dest(d, tfqn).equals("Root/B/E/S2[e1]")); assertTrue( d.getScope(tfqn).toString() - .equals("Root[]")); + .equals("Root")); assertTrue( exited(d,tfqn) .equals(ll(new String[]{ "Root/A/S1[AID]", - "Root/B/C[]", - "Root/B/D[]", + "Root/B/C", + "Root/B/D", "Root/B/E/S2[EID]", "Root/B/E/S4[EID]", - "Root/S3[]" + "Root/S3" }))); assertTrue( enteredInScope(d,tfqn) .equals(ll(new String[]{ "Root/A/S1[AID]", "Root/B/E/S4[EID - e1]", - "Root/B/C[]", - "Root/B/D[]", + "Root/B/C", + "Root/B/D", "Root/B/E/S2[e1]" }))); } @@ -934,9 +934,9 @@ public void overall10() { DashModule d = test("overall10"); String tfqn = "Root/S1/t1"; assertTrue( - src(d, tfqn).equals("Root/S1[]")); + src(d, tfqn).equals("Root/S1")); assertTrue( - dest(d, tfqn).equals("Root/S2[]")); + dest(d, tfqn).equals("Root/S2")); } @Test @@ -944,9 +944,9 @@ public void overall11() { DashModule d = test("overall11"); String tfqn = "Root/S1/t1"; assertTrue( - src(d, tfqn).equals("Root/S1[]")); + src(d, tfqn).equals("Root/S1")); assertTrue( - dest(d, tfqn).equals("Root/S2[]")); + dest(d, tfqn).equals("Root/S2")); } @Test @@ -954,9 +954,9 @@ public void overall12() { DashModule d = test("overall12"); String tfqn = "Root/S1/t1"; assertTrue( - src(d, tfqn).equals("Root/S1[]")); + src(d, tfqn).equals("Root/S1")); assertTrue( - dest(d, tfqn).equals("Root/S1/S7[]")); + dest(d, tfqn).equals("Root/S1/S7")); } @Test diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java index 748ba57d5..dc95aacd0 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashWffFailTests.java @@ -82,11 +82,11 @@ public static Collection fileNameMsg() { //{"unknownSrcDest1", unknownSrcDestMsg}, //{"unknownSrcDest2", unknownSrcDestMsg}, //{"unknownSrcDest3", unknownSrcDestMsg}, - {"unknownSrcDest4", unknownSrcDestMsg}, //21 - {"fqnSrcDestMustHaveRightNumberParams1", fqnSrcDestMustHaveRightNumberParamsMsg}, - {"srcDestCantHaveParam1", fqnSrcDestMustHaveRightNumberParamsMsg}, //23 - {"ambiguousSrcDest1", ambiguousSrcDestMsg}, - {"test11",ambiguousSrcDestMsg} + {"unknownSrcDest4", unknownStateMsg}, //21 + {"fqnSrcDestMustHaveRightNumberParams1", wrongNumberParamsMsg}, //22 + {"srcDestCantHaveParam1", wrongNumberParamsMsg}, //23 + {"ambiguousSrcDest1", ambiguousRefMsg}, + {"test11",ambiguousRefMsg} }); } diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/process-ref.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/process-ref.dsh index 85ca6f9f6..a6a981241 100644 --- a/org.alloytools.alloy.dash/src/test/resources/pass/process-ref.dsh +++ b/org.alloytools.alloy.dash/src/test/resources/pass/process-ref.dsh @@ -1,5 +1,5 @@ state Root { trans t1 { - on Elevator[e0]/direction = Up + on Elevator[e0]/direction } } \ No newline at end of file From e0a23119879e855838adc5c9925bed4f48689852 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 1 Jun 2023 22:06:33 -0400 Subject: [PATCH 050/129] various bug fixes; 1) VarTable, BufferTable must be LinkedHashMaps to keep same input order for Alloy declarations; 2) removing universal quantification of snapshots or parameters if not used in init & inv; 3) fixing parameters passed to enabledAfterStep from testIfNextStable --- .../src/main/resources/models/util/buffer.als | 2 +- .../watform/alloyasthelper/ExprHelper.java | 55 +++++++++++++++ .../ca/uwaterloo/watform/core/DashRef.java | 11 ++- .../uwaterloo/watform/core/DashStrings.java | 11 +-- .../watform/dashtoalloy/AddInit.java | 20 ++++-- .../uwaterloo/watform/dashtoalloy/AddInv.java | 26 ++++--- .../dashtoalloy/AddSnapshotSignature.java | 22 +++--- .../dashtoalloy/AddTestIfNextStable.java | 20 ++++-- .../AddTransIsEnabledAfterStep.java | 6 +- .../watform/dashtoalloy/AddTransPost.java | 18 ++--- .../watform/dashtoalloy/AddTransPre.java | 18 +++-- .../uwaterloo/watform/dashtoalloy/Common.java | 69 +++++++++++++------ .../uwaterloo/watform/parser/ResolveExpr.java | 2 +- .../ca/uwaterloo/watform/parser/VarTable.java | 11 +-- 14 files changed, 214 insertions(+), 77 deletions(-) diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/buffer.als b/org.alloytools.alloy.core/src/main/resources/models/util/buffer.als index 865c201be..b25c7a87c 100644 --- a/org.alloytools.alloy.core/src/main/resources/models/util/buffer.als +++ b/org.alloytools.alloy.core/src/main/resources/models/util/buffer.als @@ -1,4 +1,4 @@ -module util/buffer[elem, BufIdx] +module util/buffer[BufIdx, elem] open util/ordering[BufIdx] as ord diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 3dec1562c..a64555f22 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Collections; +import java.util.stream.Collectors; import edu.mit.csail.sdg.alloy4.Pos; @@ -12,11 +13,15 @@ import edu.mit.csail.sdg.ast.ExprBinary; import edu.mit.csail.sdg.ast.ExprITE; import edu.mit.csail.sdg.ast.ExprList; +import edu.mit.csail.sdg.ast.ExprLet; import edu.mit.csail.sdg.ast.ExprQt; import edu.mit.csail.sdg.ast.ExprUnary; import edu.mit.csail.sdg.ast.ExprVar; import edu.mit.csail.sdg.ast.ExprHasName; import edu.mit.csail.sdg.ast.ExprBinary; +import edu.mit.csail.sdg.ast.ExprCall; +import edu.mit.csail.sdg.ast.ExprChoice; +import edu.mit.csail.sdg.ast.ExprConstant; import ca.uwaterloo.watform.core.DashStrings; import ca.uwaterloo.watform.core.DashErrors; @@ -116,6 +121,16 @@ public static Expr createNullExpr() { public static ExprVar createTrue() { return ExprVar.make(Pos.UNKNOWN, DashStrings.trueName); } + public static Expr createIsTrue(Expr e) { + List elist = new ArrayList(); + elist.add(e); + return createPredCall(DashStrings.isTrue,elist); + } + public static Expr createIsFalse(Expr e) { + List elist = new ArrayList(); + elist.add(e); + return createPredCall(DashStrings.isFalse,elist); + } public static ExprVar createFalse() { return ExprVar.make(Pos.UNKNOWN, DashStrings.falseName); } @@ -379,4 +394,44 @@ public static String ppDecl(Decl d) { ExprToString eToString = new ExprToString(false); return eToString.declToString(d); } + + public static boolean usedIn(Expr v, Expr exp) { + + assert(isExprVar(v)); + if (isExprVar(exp)) { + return (getVarName((ExprVar) exp).equals(getVarName((ExprVar) v))); + } + else if (isExprBinary(exp) || isExprBadJoin(exp)) { + return (usedIn(v,getLeft(exp)) || usedIn(v,getRight(exp))); + } else if (exp instanceof ExprCall) { + for (Expr e: ((ExprCall) exp).args) + if (usedIn(v,e)) return true; + return false; + } else if (exp instanceof ExprChoice){ + for (Expr e: ((ExprChoice) exp).choices) + if (usedIn(v,e)) return true; + return false; + } else if (exp instanceof ExprITE){ + return (usedIn(v,getCond(exp)) || usedIn(v,getLeft(exp)) || usedIn(v, getRight(exp))); + } else if (exp instanceof ExprList){ + for (Expr e: ((ExprList) exp).args) + if (usedIn(v,e)) return true; + return false; + } else if (exp instanceof ExprUnary){ + return usedIn(v,((ExprUnary) exp).sub); + } else if (exp instanceof ExprLet){ + return usedIn(v,(((ExprLet) exp).expr)) || usedIn(v,((ExprLet) exp).sub); + } else if (exp instanceof ExprQt){ + List ll = ((ExprQt) exp).decls.stream() + .map(i -> i.expr) + .collect(Collectors.toList()); + for (Expr e: ll) if (usedIn(v,e)) return true; + return false; + } else if (exp instanceof ExprConstant){ + return false; + } else { + DashErrors.UnsupportedExpr("usedIn", ""); + return false; + } + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index 53ba141e8..7b9843763 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -178,7 +178,11 @@ public String toString() { if (kind == DashRefKind.STATE) { s += getName(); } else { - s += DashFQN.chopPrefixFromFQN(getName()); + // might not yet have a prefix + if (DashFQN.isFQN(getName())) + s += DashFQN.chopPrefixFromFQN(getName()); + else + s += "NoPrefixYet"; } if (!paramValues.isEmpty()) { @@ -207,7 +211,10 @@ public void toString(StringBuilder out, int indent) { if (kind == DashRefKind.STATE) { out.append(getName()); } else { - out.append(DashFQN.chopPrefixFromFQN(getName())); + if (DashFQN.isFQN(getName())) + out.append(DashFQN.chopPrefixFromFQN(getName())); + else + out.append("NoPrefixYet"); } if (!paramValues.isEmpty()) { out.append("["); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 111a31d49..b826786b6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -16,9 +16,7 @@ public class DashStrings { public static String varName = "var"; public static String openName = "open"; public static String asName = "as"; - public static String boolName = "boolean/Bool"; - public static String trueName = "boolean/True"; - public static String falseName = "boolean/False"; + public static String noneName = "none"; public static String intName = "int"; public static String sigName = "sig"; @@ -29,7 +27,12 @@ public class DashStrings { // standard modules public static String utilBooleanName = "util/boolean"; - + public static String boolName = "boolean/Bool"; + public static String trueName = "boolean/True"; + public static String falseName = "boolean/False"; + public static String isTrue = "boolean/isTrue"; + public static String isFalse = "boolean/isFalse"; + //public static String utilOrderingName = "util/ordering"; public static String utilTracesName = "util/traces"; public static String tracesFirstName = "first"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index f020860cb..f1edda715 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -76,11 +76,19 @@ public static void addInit(DashModule d) { // so don't try to combine these steps Expr e; + List decls; if (!body.isEmpty()) { - if (!prs.isEmpty()) - e = createAll( - paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1), prs), - createAndFromList(body)); + if (!prs.isEmpty()) { + // all parameters are not used in init + decls = new ArrayList(); + e = createAndFromList(body); + for (int i=0; i < prs.size();i++) { + if (usedIn(paramVar(i,prs.get(i)),e )) { + decls.add(paramDecl(i,prs.get(i))); + } + } + if (!decls.isEmpty()) e = createAll(decls,e); + } else e = createAndFromList(body); body = new ArrayList(); body.add(e); @@ -90,9 +98,11 @@ public static void addInit(DashModule d) { if (DashOptions.isElectrum) { d.alloyString += d.addPredSimple(DashStrings.initFactName, new ArrayList(), body); } else { + // snapshot will always be needed as a parameter + // because it is used in conf (every model has at least one state) d.alloyString += d.addPredSimple( DashStrings.initFactName, - curParamsDecls(DashUtilFcns.listOfInt(0,prs.size()-1), prs), + curDecls(), body); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java index b1bd66cb9..d805abb3c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInv.java @@ -51,17 +51,27 @@ public static void addInv(DashModule d) { // so don't try to combine these steps Expr e; - if (!prs.isEmpty()) - e = createAll( - // might need to add "p" to the front of these - paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1), prs), - createAndFromList(body)); - else e = createAndFromList(body); List decls = new ArrayList(); - decls.add(curDecl()); + if (!body.isEmpty()) { + if (!prs.isEmpty()) { + // all parameters are not used in inv + e = createAndFromList(body); + for (int i=0; i < prs.size();i++) { + if (usedIn(paramVar(i,prs.get(i)),e )) { + decls.add(paramDecl(i,prs.get(i))); + } + } + if (!decls.isEmpty()) e = createAll(decls,e); + } + else e = createAndFromList(body); + body = new ArrayList(); + body.add(e); + } else e = createAndFromList(body); + if (usedIn(curVar(),e)) decls.add(curDecl()); if (!DashOptions.isElectrum) { body = new ArrayList(); - body.add(createAll(decls,e)); + if (!decls.isEmpty()) body.add(createAll(decls,e)); + else body.add(e); } d.alloyString += d.addFactSimple(DashStrings.invName, body); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 30ad1197f..8503da47a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -91,7 +91,7 @@ public static void addSnapshotSignature(DashModule d){ .filter(i -> d.getVarBufferParams(i).size() == 0 && isExprVar(d.getVarType(i))) .collect(Collectors.toList()); for (String v: allvfqnsNoParamsSimpleTyp) - d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar) translateExpr(d.getVarType(v),d)) ); + d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar) translateExpr(d.getVarType(v),d,true)) ); // vfqns with no params and arrow type (A -> B) // becomes sig A { var vfqn: B } @@ -109,7 +109,7 @@ public static void addSnapshotSignature(DashModule d){ if (!allvfqnsNoParamsArrowTyp.isEmpty()) { decls = new ArrayList(); for (String v: allvfqnsNoParamsArrowTyp) - decls.add(DeclExt.newVarDeclExt(translateFQN(v), translateExpr(d.getVarType(v),d))); + decls.add(DeclExt.newVarDeclExt(translateFQN(v), translateExpr(d.getVarType(v),d, true))); d.alloyString += d.addOneSigWithDeclsSimple(DashStrings.variablesName, decls); } @@ -135,10 +135,10 @@ public static void addSnapshotSignature(DashModule d){ decls = new ArrayList(); for (String v: allvfqnsWithThisFirstParam) { if (d.getVarBufferParams(v).size() == 1) { - decls.add(DeclExt.newVarDeclExt(v, translateExpr(d.getVarType(v),d))); + decls.add(DeclExt.newVarDeclExt(v, translateExpr(d.getVarType(v),d, true))); } else { plist = createVarList(d.getVarBufferParams(v).subList(1, d.getVarBufferParams(v).size()-1)); - plist.add(translateExpr(d.getVarType(v),d)); + plist.add(translateExpr(d.getVarType(v),d, true)); decls.add(DeclExt.newVarDeclExt(translateFQN(v),createArrowExprList(plist))); } } @@ -216,15 +216,21 @@ public static void addSnapshotSignature(DashModule d){ List typlist; for (String vfqn: d.getAllVarNames()) { typlist = createVarList(d.getVarBufferParams(vfqn)); // could be empty - typlist.add(translateExpr(d.getVarType(vfqn),d)); - if (typlist.size() > 1 ) + typlist.add(translateExpr(d.getVarType(vfqn),d, true)); + //System.out.println(d.getVarType(vfqn)); + //System.out.println(translateExpr(d.getVarType(vfqn),d, true)); + if (typlist.size() > 1 ) { decls.add((Decl) new DeclExt( translateFQN(vfqn), createArrowExprList(typlist))); - else + //System.out.println(decls); + } + else { decls.add((Decl) new DeclExt( translateFQN(vfqn), - typlist.get(0))); + typlist.get(0))); + //System.out.println(decls); + } } // add buffers for (String bfqn: d.getAllBufferNames()) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java index 973fb6150..956059e5e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTestIfNextStable.java @@ -31,31 +31,39 @@ public class AddTestIfNextStable { // only one per module public static void addTestIfNextStable(DashModule d) { - List decls = new ArrayList(); - List args = new ArrayList(); List body = new ArrayList(); + List decls = new ArrayList(); List allParams = d.getAllParamsInOrder(); if (!DashOptions.isElectrum) { decls.addAll(curNextDecls()); - args.addAll(curNextVars()); } for (int i=0; i < allParams.size(); i++) { decls.add(paramDecl(i,allParams.get(i))); } for (int i=0; i<= d.getMaxDepthParams(); i++) { decls.add(scopeDecl(i)); - args.add(scopeVar(i)); if (d.hasEventsAti(i)) { decls.add(genEventDecl(i)); - args.add(genEventVar(i)); } } + List args; + // this will include transition tfqn itself for (String tfqn: d.getAllTransNames()) { + args = new ArrayList(); + if (!DashOptions.isElectrum) args.addAll(curNextVars()); + for (int i=0; i o1: forall i. not(t1_nonOrthScopei in scopesi) - ev1: t1_on in (s.eventsi & EnvEvents) + genEventsi // if t1_on is internal this is false + ev1: t1_on in (s.eventsi :> EnvEvents) + genEventsi // if t1_on is internal this is false else { o2: forall i. not(t1_nonOrthScopei in scopesi + s'.scopesUsedi) ev2: t1_on in s.eventsi + genEventsi @@ -118,14 +118,14 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { DashRef ev = d.getTransOn(tfqn); Expr ev1, ev2; if (ev != null) { - //ev1: t1_on in (s.eventsi & EnvEvents) + genEventsi // if t1_on is internal this is false + //ev1: t1_on in (s.eventsi :> EnvEvents) + genEventsi // if t1_on is internal this is false if (d.isInternalEvent(ev.getName())) { ev1 = createFalse(); } else { ev1 = createIn( translateDashRefToArrow(ev), createUnion( - createIntersect( + createRangeRes( curEvents(ev.getParamValues().size()), allEnvironmentalEventsVar()), genEventVar(ev.getParamValues().size()))); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 580f71e7f..f048e5707 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -44,14 +44,14 @@ public class AddTransPost { // big step = one small step // only internal events are those generated by t1 // allow env events to change - forall i: eventsi' & InternalEvents = t1_send_ev (if i) + forall i: eventsi' :> InternalEvents = t1_send_ev (if i) } else { // case 2 // last small step of the big step // add t1's gen events to the internal events // allow env events to change - forall i: eventsi' & InternalEvent = - t1_send_ev (if i) + (InternalEvent & eventsi) + forall i: eventsi' :> InternalEvent = + t1_send_ev (if i) + (eventsi :> InternalEvent ) } } else { stable' = False @@ -60,9 +60,9 @@ public class AddTransPost { // case 3 // first small step of the big step // only internal events are those generated by t1 - forall i: eventsi' & InternalEvent = t1_send_ev (if i) + forall i: eventsi' :> InternalEvent = t1_send_ev (if i) // env events stay the same - eventsi' & EnvironmentlEvent = eventsi & EnvironmentalEvent + eventsi' :> EnvironmentalEvent = eventsi :> EnvironmentalEvent // empty previous scopes used and just add this one forall i : scopesUsedi' = scopesUsed } else { @@ -70,7 +70,7 @@ public class AddTransPost { // intermediate small step // add t1's gen event to the events // env events don't change - forall i: eventsi' = events + t1_send_ev (if i) + forall i: eventsi' = eventsi + t1_send_ev (if i) // just add to scopesUsed forall i : scopesUsedi' = scopesUsedi + scopesUsed } @@ -151,7 +151,7 @@ public static void addTransPost(DashModule d, String tfqn) { List scopesUsedEmpty = new ArrayList(); for (int i=0;i <= d.getMaxDepthParams(); i++) { - scopesUsedEmpty.add(createEquals(nextScopesUsed(i),createNone())); + scopesUsedEmpty.add(createEquals(nextScopesUsed(i),createNoneArrow(i))); } Expr stableTrueAndScopesUsedEmpty = createAnd(nextStableTrue(), createAndFromList(scopesUsedEmpty)); @@ -179,7 +179,7 @@ public static void addTransPost(DashModule d, String tfqn) { createRangeRes(nextEvents(i),allInternalEventsVar()), rhs1)); } - case3.add(createEquals(nextScopesUsed(i),createNone())); + case3.add(createEquals(nextScopesUsed(i),createNoneArrow(i))); } //if (case3.isEmpty()) c3 = createTrue(); c3 = createAndFromList(case3); @@ -271,7 +271,7 @@ private static Expr createTestIfNextStableCall(DashModule d, String tfqn) { .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); if (u.size() == 1) args.add(u.get(0)); - else if (u.size() ==0 ) args.add(createNone()); + else if (u.size() ==0 ) args.add(createNoneArrow(i)); else { DashErrors.createTestIfNextStableCallMultipleScopesAtSameLevel(); return null; } if (d.hasEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) args.add(translateDashRefToArrow(ev)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 9e996147e..101342b02 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -31,7 +31,7 @@ public class AddTransPre { // -------------------------------------------------------------------------------------- /* pred pre_t1[s:Snapshot,pparam0:Param0, ...] { - some (src_staet_t1 & .s.conf) + some (src_state_t1 & .s.conf) orthogonal to any scopes uses guard_cond_t1 [s] s.stable = True => @@ -48,6 +48,7 @@ .trig_events_t1 in (s.events & ExternalEvent ) */ public static void addTransPre(DashModule d, String tfqn) { List prsIdx = d.getTransParamsIdx(tfqn); + List params = d.getTransParams(tfqn); List body = new ArrayList(); String tout = translateFQN(tfqn); @@ -77,10 +78,15 @@ public static void addTransPre(DashModule d, String tfqn) { // trig_events_t1 DashRef ev = d.getTransOn(tfqn); int sz = ev.getParamValues().size(); - Expr ifBranch = createIn(translateDashRefToArrow(ev), - createRangeRes( - curEvents(sz), - allEnvironmentalEventsVar())); + Expr ifBranch; + if (d.isInternalEvent(ev.getName())) { + ifBranch = createFalse(); + } else { + ifBranch = createIn(translateDashRefToArrow(ev), + createRangeRes( + curEvents(sz), + allEnvironmentalEventsVar())); + } Expr elseBranch = createIn(translateDashRefToArrow(ev), curEvents(sz)); body.add(createITE( curStableTrue(), @@ -100,7 +106,7 @@ public static void addTransPre(DashModule d, String tfqn) { */ // not a higher priority transition enabled - d.alloyString += d.addPredSimple(tout+DashStrings.preName, curParamsDecls(prsIdx,d.getAllParamsInOrder()), body); + d.alloyString += d.addPredSimple(tout+DashStrings.preName, curParamsDecls(prsIdx,params), body); d.alloyString += "\n"; } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index ea63fc037..2d529b0e0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -52,6 +52,13 @@ public static Decl paramDecl(Integer n, String name) { // return (Decl) new DeclExt(DashStrings.pName+Integer.toString(i), DashStrings.identifierName); //} + // [s:Snapshot, s':Snapshot] + public static List curDecls() { + List o = new ArrayList(); + o.add(curDecl()); + return o; + } + // [s:Snapshot, s':Snapshot] public static List curNextDecls() { List o = new ArrayList(); @@ -209,19 +216,23 @@ public static Expr nextEvents(int size) { // s.stable == boolean/True public static Expr curStableTrue() { - return createEquals(curJoinExpr(stable()),createTrue()); + return createIsTrue(curJoinExpr(stable())); + //return createEquals(curJoinExpr(stable()),createTrue()); } // s.stable == boolean/False public static Expr curStableFalse() { - return createEquals(curJoinExpr(stable()),createFalse()); + return createIsFalse(curJoinExpr(stable())); + //return createEquals(curJoinExpr(stable()),createFalse()); } // s'.stable == boolean/True public static Expr nextStableTrue() { - return createEquals(nextJoinExpr(stable()),createTrue()); + return createIsTrue(nextJoinExpr(stable())); + //return createEquals(nextJoinExpr(stable()),createTrue()); } // s'.stable == boolean/False public static Expr nextStableFalse() { - return createEquals(nextJoinExpr(stable()),createFalse()); + return createIsFalse(nextJoinExpr(stable())); + //return createEquals(nextJoinExpr(stable()),createFalse()); } // s.name @@ -268,17 +279,33 @@ public static boolean isWeirdOne(String vfqn, DashModule d) { //System.out.println("Vqn: " + vfqn); return d.getVarBufferParams(vfqn).size() == 0 && isExprArrow(d.getVarType(vfqn)); } + + // common case public static Expr translateExpr(Expr exp, DashModule d) { + return translateExpr(exp,d,false); + } + + // onlyGetName = true is ONLY used for the case when + // translating type expressions of signatures + // there we only require the full name with underscores + public static Expr translateExpr(Expr exp, DashModule d, boolean onlyGetName ) { // special case for Variables.v1 if v1 has no params and has an // arrow type and isElectrum //System.out.println(exp); if (DashRef.isDashRef(exp)) { + //System.out.println(exp); String vName = ((DashRef) exp).getName(); + + // used for types in snapshot signature + if (onlyGetName) { + //System.out.println("here: " + createVar(vName)); + return createVar(translateFQN(vName)); + } // have to translate paramvalues // may be empty List paramValuesList = ((DashRef) exp).getParamValues().stream() - .map(i -> translateExpr(i,d)) + .map(i -> translateExpr(i,d, onlyGetName)) .collect(Collectors.toList()); //common subexpressions @@ -312,15 +339,15 @@ public static Expr translateExpr(Expr exp, DashModule d) { return ((ExprBinary) exp).op.make( exp.pos, exp.closingBracket, - translateExpr(getLeft(exp),d), - translateExpr(getRight(exp),d)); + translateExpr(getLeft(exp),d, onlyGetName), + translateExpr(getRight(exp),d, onlyGetName)); } else if (isExprBadJoin(exp)) { return ExprBadJoin.make( exp.pos, exp.closingBracket, - translateExpr(getLeft(exp),d), - translateExpr(getRight(exp),d)); + translateExpr(getLeft(exp),d, onlyGetName), + translateExpr(getRight(exp),d, onlyGetName)); } else if (exp instanceof ExprCall) { return ExprCall.make( @@ -328,7 +355,7 @@ public static Expr translateExpr(Expr exp, DashModule d) { exp.closingBracket, ((ExprCall) exp).fun, ((ExprCall) exp).args.stream() - .map(i -> translateExpr(i,d)) + .map(i -> translateExpr(i,d, onlyGetName)) .collect(Collectors.toList()), ((ExprCall) exp).extraWeight); @@ -336,7 +363,7 @@ public static Expr translateExpr(Expr exp, DashModule d) { //TODO: check into this cast // not sure why is it necessary ConstList x = (ConstList) ((ExprChoice) exp).choices.stream() - .map(i -> translateExpr(i,d)) + .map(i -> translateExpr(i,d, onlyGetName)) .collect(Collectors.toList()); return ExprChoice.make( false, @@ -347,9 +374,9 @@ public static Expr translateExpr(Expr exp, DashModule d) { } else if (exp instanceof ExprITE){ return ExprITE.make( exp.pos, - translateExpr(getCond(exp),d), - translateExpr(getLeft(exp),d), - translateExpr(getRight(exp),d)); + translateExpr(getCond(exp),d, onlyGetName), + translateExpr(getLeft(exp),d, onlyGetName), + translateExpr(getRight(exp),d, onlyGetName)); } else if (exp instanceof ExprList){ return ExprList.make( @@ -357,21 +384,21 @@ public static Expr translateExpr(Expr exp, DashModule d) { exp.closingBracket, ((ExprList) exp).op, ((ExprList) exp).args.stream() - .map(i -> translateExpr(i,d)) + .map(i -> translateExpr(i,d, onlyGetName)) .collect(Collectors.toList())); } else if (exp instanceof ExprUnary){ return ((ExprUnary) exp).op.make( exp.pos, - translateExpr(((ExprUnary) exp).sub,d)); + translateExpr(((ExprUnary) exp).sub,d, onlyGetName)); } else if (exp instanceof ExprLet){ //TODO rule out var name return ExprLet.make( exp.pos, ((ExprLet) exp).var, - translateExpr(((ExprLet) exp).expr,d), - translateExpr(((ExprLet) exp).sub,d)); + translateExpr(((ExprLet) exp).expr,d, onlyGetName), + translateExpr(((ExprLet) exp).sub,d, onlyGetName)); } else if (exp instanceof ExprQt){ @@ -383,13 +410,13 @@ public static Expr translateExpr(Expr exp, DashModule d) { i.disjoint2, i.isVar, i.names, - translateExpr(i.expr, d))) + translateExpr(i.expr, d, onlyGetName))) .collect(Collectors.toList()); return ((ExprQt) exp).op.make( exp.pos, exp.closingBracket, decls, - translateExpr(((ExprQt) exp).sub,d)); + translateExpr(((ExprQt) exp).sub,d, onlyGetName)); } else if (exp instanceof ExprConstant){ return exp; @@ -412,6 +439,8 @@ public static Expr createNoneArrow(int i) { return createArrowExprList(Collections.nCopies(i+1,createNone())); } } + + /* public static Expr predJoinCurParams(String name, List prs) { //p2.p1.p0.s.name diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java index 47ac85387..0d5f88aed 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java @@ -52,7 +52,7 @@ public static Expr resolveExpr( StateTable st, boolean thisOk, String sfqn, // could be parent of event or trans Expr exp) { - + //System.out.println("resolve: " + exp); if (isExprVar(exp) || isPrimedVar(exp) || DashRef.isDashRef(exp)) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index e249fc991..c87000196 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Collections; import java.util.stream.Collectors; @@ -26,12 +27,14 @@ public class VarTable { // stores Var, Buffer Decls in a HashMap based on the event FQN - private HashMap varTable; - private HashMap bufferTable; + // LinkedHashMap so order of keySet is consistent + // Alloy requires declaration before use for variables + private LinkedHashMap varTable; + private LinkedHashMap bufferTable; public VarTable() { - this.varTable = new HashMap(); - this.bufferTable = new HashMap(); + this.varTable = new LinkedHashMap(); + this.bufferTable = new LinkedHashMap(); } public class VarElement { From 2162d98abad7c5d284c1f700455f32f481f260d9 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 2 Jun 2023 12:07:40 -0400 Subject: [PATCH 051/129] code cleanup --- .../ca/uwaterloo/watform/core/DashErrors.java | 5 +- .../uwaterloo/watform/parser/DashModule.java | 82 +----- .../uwaterloo/watform/parser/EventTable.java | 89 +------ .../uwaterloo/watform/parser/ResolveExpr.java | 31 ++- .../uwaterloo/watform/parser/StateTable.java | 180 +------------ .../uwaterloo/watform/parser/TransTable.java | 246 +----------------- .../ca/uwaterloo/watform/parser/VarTable.java | 146 +---------- 7 files changed, 40 insertions(+), 739 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 216059bff..57377c899 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -123,7 +123,10 @@ public static void duplicateBufferName(Pos o, String s) { public static void tooMany(String xType, String tfqn) { throw new ErrorSyntax(tooManyMsg + xType + " in " + tfqn); } - + public static String cantSendAnEnvEventMsg = " can't send an environmental event: "; + public static void cantSendAnEnvEvent(Pos p, String expString) { + throw new ErrorSyntax(p + cantSendAnEnvEventMsg + expString); + } /* public static String ambiguousEventMsg = "Event name not unique within this conc/Root region: "; public static void ambiguousEvent(String xType, String v, String tfqn) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 592fce2a2..4dc2e86a0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -1,6 +1,6 @@ package ca.uwaterloo.watform.parser; -// tmp + import java.util.*; import java.io.FileReader; import java.io.BufferedReader; @@ -596,22 +596,7 @@ public void translate() { // if no errors status = Status.TRANSLATED_TO_ALLOY; } - /* - public void resolveAllAlloy(A4Reporter rep) { - // this method in CompModule is static and takes a CompModule as - // input and returns one as output even though it makes all the - // changes in place on the input CompModule and then just - // returns it as the output - // so here we cast DashModule to CompModule and ignore the - // output CompModule - //assert(status == Status.TRANSLATED_TO_ALLOY); - //System.out.println("Resolving Alloy"); - // this quits if it throws an error - resolveAll(rep == null ? A4Reporter.NOP : rep, (CompModule) this); - // if no errors - //status = Status.RESOLVED_ALLOY; - } - */ + // for testing public List getDefaults(String s) { return stateTable.getDefaults(s); @@ -619,11 +604,6 @@ public List getDefaults(String s) { - /* leftover - public String getRoot() { - return root.name(); // as root it is already FQN - } - */ public List getAllInternalEventNames() { //assert(hasInternalEvents()); return eventTable.getAllInternalEvents(); @@ -634,63 +614,5 @@ public List getAllEnvironmentalEventNames() { } - /* - public List getTransTriggerEvents(String t){ - return transTable.get(t).trigger(); - } - public List getTransGenEvents(String t) { - return transTable.get(t).genEvents(); - } - public List getEventParams(String e) { - return eventTable.get(e).getParams(); - } - - public int getNumParams() { - return params.size(); - } - public List getBufferIndices() { - List iList; - for (i = 0; i <= r.getBufferMax(); i++) { - iList.add(DashStrings.bufferIndexName + i) - return iList; - } - - - public List getDynSymbols() { - return symbolTable.values(); - } - public List getBuffers() { - - } - public List getInvariants() { - /???? - } - public List getTransitionsAtLevel(int i) { - ArrayList o = transTable.keys().stream().filter(t -> transTable.get(t).params.size() == i).collect(Collectors.toList()); - return o; - } - */ - - /* - public ArrayList getBasicStatesEnteredAtLevel(i){ - ArrayList bs = stateTable.get(root).basicStatesEntered; - ArrayList o = bs.stream().filter(s -> s.params.size() == i).collect(Collectors.toList()); - return o; - } - public List createStateArrow(String s) { - return createArrow(stateTable.get(s).params.add(s)); - } - - - public boolean hasBuffers() { - return (bufferMax != -1); - } - public int getBufferMax() { - return bufferMax; - } - - - - */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index 09f11c2fc..a908f454d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Collections; import java.util.stream.Collectors; @@ -22,7 +23,7 @@ public class EventTable { // stores Event Decls in a HashMap based on the event FQN - private HashMap table; + private LinkedHashMap table; public class EventElement { @@ -49,7 +50,7 @@ public String toString() { } public EventTable() { - this.table = new HashMap(); + this.table = new LinkedHashMap(); } public String toString() { @@ -130,89 +131,5 @@ public List getEventsOfState(String sfqn) { .filter(i -> DashFQN.chopPrefixFromFQN(i).equals(sfqn)) .collect(Collectors.toList()); } - /* - public DashRef resolveEvent(String xType, Expr exp, List region, String tfqn, List tparamsIdx, List tparams, VarTable vt) { - - // don't include isDashRefJoin here because that is only possible for actions not events - // which are tuples - // but a DashRefProcessRef could be either a value for an action - // or a tuple for an event - // Arrow: b1 -> a1 -> ev - // ProcessRef: A/B/C[a1,b1]/ev which became $$PROCESSREF$$. b1.a1.A/B/C/ev in parsing - // BadJoin: ev[a1,b1] which became b1.a1.ev in parsing - if (ExprHelper.isExprVar(exp) || - //DashRef.isDashRefArrow(exp) || - DashRef.isDashRef(exp))// || - //DashRef.isDashRefBadJoin(exp)) - { - String e; - List paramValues; - if (ExprHelper.isExprVar(exp)) { - e = ExprHelper.getVarName((ExprVar) exp); - paramValues = new ArrayList(); - } else { - e = exp.getName(); - paramValues = - // have to recursive through expressions in parameters - exp.getParamValues().stream() - .map(i -> vt.resolveExpr(xType, i, region, tfqn, tparamsIdx, tparams)) - .collect(Collectors.toList()); - } - String efqn = DashFQN.fqn(e); - - //System.out.println(efqn); - List matches = new ArrayList(); - if (paramValues.isEmpty()) { - // if no param values must be within the region of the same params (could be prefix of params) - for (String s:region) - for (String x:allEventsOfState(s)) { - if (DashFQN.suffix(x,efqn)) matches.add(x); - } - } else { - // if it has params values, could be suffix of any event - // and later we check it has the right number of params - for (String x:getAllEventNames()) { - if (DashFQN.suffix(x,efqn)) matches.add(x); - } - } - - if (matches.size() > 1) { - DashErrors.ambiguousEvent(xType, e, tfqn); - return null; - } else if (matches.isEmpty()) { - DashErrors.unknownEvent(xType, e,tfqn); - return null; - } else { - String m = matches.get(0); - if (paramValues.isEmpty()) { - // must have same param values as trans b/c in same conc region - if (getParams(m).size() > tparamsIdx.size()) { - // getRegion did not return things that all - // have the same parameter values - DashErrors.regionMatchesWrongParamNumber(); - return null; - } else { - // but could be a subset of transition param values - List prmValues = - Common.paramVars( - tparamsIdx.subList(0, getParamsIdx(m).size()), - tparams.subList(0,getParams(m).size()) ); - return new DashRef(m, prmValues); - } - } else if (getParams(m).size() != paramValues.size()) { - // came with parameters so must be right number - DashErrors.fqnEventMissingParameters(xType, e, tfqn); - return null; - } else { - return new DashRef(m,paramValues); - } - } - } else { - DashErrors.expNotEvent(xType, tfqn); - return null; - } - - } - */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java index 0d5f88aed..d60185ec8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java @@ -1,3 +1,22 @@ +/* + This function takes an Expr and sorts out any Dash names used in it to: + 1) make the names fully qualified + 2) figure out all the parameter values + 3) figures out what "thisState" means + 4) turns PRIME(v) into v' + + It is called from stateTable resolving for inits and invariants and that + It is called from varTable for resolving type of dynamic variables (where it resolves + only the name, not the parameters) + It is called from transTable to resolve all parts of transitions. + + Variation points for these uses is in where to search for + a name (stateTable, EventTable, varTable) + + Incoming Expr may also be a DashRef (from parsing for src/dest/on/send). + + Errors are given using "pos". +*/ package ca.uwaterloo.watform.parser; import java.util.List; @@ -164,18 +183,6 @@ static Expr resolveDashRef( StateTable st, String sfqn, // could be parent of event or trans Expr exp) { - // Join: b1.a1.var - - // DashRefProcessRef: A/B/C[a1,b1]/var which became $$PROCESSREF$$. b1.a1.A/B/C/var in parsing - // a DashRefProcessRef could be either a value for an exp - // or a tuple for an event - - // BadJoin: var[a1,b1] which became b1.a1.var in parsing - - // don't include isDashRefArrow here because that is only possible for - // events (which are tuples) not actions - - // turns PRIME(v) into v' assert(isExprVar(exp) || isPrimedVar(exp) || DashRef.isDashRef(exp)); assert(kind.equals("state") || kind.equals("event") || kind.equals("var")); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 5d6e59dec..e1cc7c9d6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -65,14 +65,7 @@ public class StateElement { // after resolve private List invs; private List inits; - /* - private ArrayList transWithThisSrc; - private ArrayList transWithThisScope; - // all trans with this scope or descendant scope - private ArrayList allTransWithinState; - private ArrayList basicStatesEntered; // following defaults - private ArrayList basicStatesExited; - */ + public StateElement( DashStrings.StateKind k, @@ -120,52 +113,7 @@ public String toString() { // add more return s; } - /* - this.substates = new ArrayList(); - this.dynSymbols = new ArrayList(); - this.events = new ArrayList(); - this.transitions = new ArrayList(); - this.init = new ArrayList(); - this.invariants = new ArrayList(); - - for (Object i: items) { - if (item instanceof DashState) { - this.substates.add(i); - } else if (item instanceof DashDecl) { - this.dynSymbols.add(i); - } else if (item instanceof DashEvent) { - this.events.add(i); - } else if (item instanceof DashTrans) { - this.transitions.add(i); - } else if (item instanceof DashInit) { - this.inits.add(i); - } else if (item instanceof DashInv) { - this.invariants.add(i); - } else { - // error - } - } - */ - /* - public Boolean allAttributesEmpty() { - return (kind == null && - param == null && - params == null && - def == null && - parent == null && - immChildren.isEmpty() ) ; - } - */ - /* - public Boolean attributesSame(DashStrings.StateKind k, String prm, List prms, DashStrings.DefKind d, String p, List iChildren) { - return (kind == k && - param.equals(prm) && - params.equals(prms) && - def.equals(d) && - parent.equals(p) && - immChildren.equals(iChildren)); - } - */ + } @@ -351,17 +299,7 @@ public String getClosestParamAnces(String s) { return concAnces; // might be null } - /* - public List getAllNonConcStatesWithinThisState(String concAnces) { - if (concAnces!=null) return getAllNonConcDesc(concAnces); - else { - // went back to root - List x = getAllNonConcDesc(root); - //System.out.println("getAllNonConcStatesWithinThisState: "+x); - return x; - } - } - */ + public List getAllNonParamDesc(String s) { // get all the descendants not WITHIN parameterized states // s is included @@ -422,111 +360,8 @@ public void resolve(String root, EventTable et, VarTable vt) { } isResolved = true; } - /* - public void resolve(String root, VarTable vt) { - // resolve inits and invariants - for (String sfqn: table.keySet()) { - inits.addAll( - table.get(sfqn).origInits.stream() - .map(i -> vt.resolveExpr("init", i.getInit(), - getRegion(sfqn), - sfqn, - getParamsIdx(sfqn), - getParams(sfqn))) - .collect(Collectors.toList())); - invs.addAll( - table.get(sfqn).origInvariants.stream() - .map(i -> vt.resolveExpr("inv", i.getInv(), - getRegion(sfqn), - sfqn, - getParamsIdx(sfqn), - getParams(sfqn))) - .collect(Collectors.toList())); - - // have to resolve variables here because need - // other parameters to resolveExpr - for (String vfqn: vt.getVarsOfState(sfqn)) { - vt.setVarType(vfqn, - vt.resolveExpr( - "var", - vt.getVarType(vfqn), - getRegion(sfqn), - sfqn, - getParamsIdx(sfqn), - getParams(sfqn))); - } - - } - isResolved = true; - } - */ - /* - * this fcn figures out the src/dest of a transition - * from its context - * if it has no src/dest, the parent state is used - * if it is already FQN, it is returned directly - * Otherwise, it looks at all uniquely named states up to an ancestor conc state - * Requires state table to have been built already - */ - - // tfqn is needed for error messages - /* - public DashRef resolveSrcDest(String xType, DashRef x, String tfqn, List tparamsIdx, List tparams, VarTable vt) { - - //System.out.println("Looking for: " + x); - String sfqn = DashFQN.fqn(x.getName()); - String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); - // param values might be empty - List paramValues = x.getParamValues().stream() - .map(i -> vt.resolveExpr("from", i, getRegion(parentFQN), tfqn, tparamsIdx, tparams)) - .collect(Collectors.toList()); - List matches = new ArrayList(); - if (paramValues.isEmpty()) { - // if no param values must be within the region of the same params (could be prefix of params) - for (String s:getRegion(parentFQN)) - if (DashFQN.suffix(s,sfqn)) matches.add(s); - } else { - // if it has params values, could be suffix of any event - // and later we check it has the right number of params - for (String s:getAllStateNames()) - if (DashFQN.suffix(s,sfqn)) matches.add(s); - } - - if (matches.size() > 1) { - DashErrors.ambiguousSrcDest(xType, tfqn); - return null; - } else if (matches.isEmpty()) { - DashErrors.unknownSrcDest(x.getName(),xType,tfqn); - return null; - } else { - String m = matches.get(0); - if (paramValues.isEmpty()) { - // must have same param values as trans b/c in same conc region - if (getParams(m).size() > tparamsIdx.size()) { - // getRegion did not return things that all - // have the same parameter values - DashErrors.regionMatchesWrongParamNumber(); - return null; - } else { - // but could be a subset of transition param values - List prmValues = - Common.paramVars( - tparamsIdx.subList(0, getParams(m).size()), - tparams.subList(0, getParams(m).size()) ); - return new DashRef(m, prmValues); - } - } else if (getParams(m).size() != paramValues.size()) { - // came with parameters so must be right number - DashErrors.fqnSrcDestMustHaveRightNumberParams(xType, tfqn); - return null; - } else { - return new DashRef(m,paramValues); - } - } - } - */ public List getInits() { return inits; } @@ -686,14 +521,5 @@ public List getLeafStatesEnteredInScope(DashRef context, DashRef dest) return r; } - /* seems like this goes in DashToAlloy - public Expr createStateArrow(String s) { - Expr e = createVar(s); - for (i:s.params.reverse()) { - e = createArrow(createVar(i),e); - } - return e; - } - */ } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 24d9565de..55b249549 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -26,8 +26,7 @@ import ca.uwaterloo.watform.dashtoalloy.Common; import static ca.uwaterloo.watform.parser.ResolveExpr.*; - // env events cannot be generated - // env vars cannot be primed anywhere + public class TransTable { @@ -67,13 +66,6 @@ public TransElement( List sl, List dl ) - /* - DashEvent w, - DashExpr o, - List a, - List s - ) - */ { this.params = prms; this.paramsIdx = prmsIdx; @@ -281,97 +273,12 @@ else if (!onExpList.isEmpty()) { .collect(Collectors.toList()); if (sendExpList.size() > 1) DashErrors.tooMany("send", tfqn); else if (!sendExpList.isEmpty()) { - table.get(tfqn) - .setSend((DashRef) resolveExpr(st, et, vt, "event", false, true, true, sfqn, sendExpList.get(0))); - } - - // determining the when (expr) - List whenExpList = - table.get(tfqn).whenList.stream() - .map(p -> (p.getWhen())) - .collect(Collectors.toList()); - if (whenExpList.size() > 1) DashErrors.tooMany("when", tfqn); - else if (!whenExpList.isEmpty()) { - table.get(tfqn) - .setWhen(resolveExpr(st, et, vt, "var", false, false, true, sfqn, whenExpList.get(0))); - } - - // determining the do - List doExpList = - table.get(tfqn).doList.stream() - .map(p -> (p.getDo())) - .collect(Collectors.toList()); - if (doExpList.size() > 1) DashErrors.tooMany("on", tfqn); - else if (!doExpList.isEmpty()) { - table.get(tfqn) - .setDo(resolveExpr(st, et, vt, "var", true, true, true, sfqn, doExpList.get(0))); - } - - } - isResolved = true; - } - - /* - public void resolve(StateTable st, EventTable et, VarTable vt) { - - //System.out.println(st); - //System.out.println(toString()); - //System.out.println("Resolving trans table"); - if (getAllTransNames().isEmpty()) DashErrors.noTrans(); - for (String tfqn: table.keySet()) { - //String tfqn = DashFQN.fqn(sfqn,t.name); - String sfqn = DashFQN.chopPrefixFromFQN(tfqn); - // determining the src state - List fList = - table.get(tfqn).fromList.stream() - .map(p -> (p.src)) - .collect(Collectors.toList()); - - if (fList.size() > 1) DashErrors.tooMany("from", tfqn); - else if (fList.isEmpty()) - // can be a loop on root - table.get(tfqn) - .setSrc(new DashRef(sfqn, Common.paramVars(getParamsIdx(tfqn), getParams(tfqn)))); - else - table.get(tfqn) - .setSrc(resolveExpr(st, et, vt, "state", false, false, true, sfqn, fList.get(0))); - - // determining the dest state - List gList = - table.get(tfqn).gotoList.stream() - .map(p -> (p.dest)) - .collect(Collectors.toList()); - - if (gList.size() > 1) DashErrors.tooMany("goto", tfqn); - else if (gList.isEmpty()) - // can be a loop on root - table.get(tfqn) - .setDest(new DashRef(sfqn, - Common.paramVars(getParamsIdx(tfqn),getParams(tfqn)))); - else - table.get(tfqn) - .setDest(resolveExpr(st, et, vt, "state", false, true, true, sfqn, gList.get(0))); - - // determining the on (event) - List onExpList = - table.get(tfqn).onList.stream() - .map(p -> (p.getExp())) - .collect(Collectors.toList()); - if (onExpList.size() > 1) DashErrors.tooMany("on", tfqn); - else if (!onExpList.isEmpty()) { - table.get(tfqn) - .setOn(resolveExpr(st, et, vt, "event", false, false, true, sfqn, onExpList.get(0))); - } - - // determining the send - List sendExpList = - table.get(tfqn).sendList.stream() - .map(p -> (p.getExp())) - .collect(Collectors.toList()); - if (sendExpList.size() > 1) DashErrors.tooMany("send", tfqn); - else if (!sendExpList.isEmpty()) { - table.get(tfqn) - .setSend(resolveExpr(st, et, vt, "event", false, true, true, sfqn, sendExpList.get(0))); + DashRef x = (DashRef) resolveExpr(st, et, vt, "event", false, true, true, sfqn, sendExpList.get(0)); + if (et.isEnvironmentalEvent(x.getName())) + DashErrors.cantSendAnEnvEvent(sendExpList.get(0).pos(),sendExpList.get(0).toString()); + else + table.get(tfqn) + . setSend((DashRef) resolveExpr(st, et, vt, "event", false, true, true, sfqn, sendExpList.get(0))); } // determining the when (expr) @@ -399,145 +306,6 @@ else if (!doExpList.isEmpty()) { } isResolved = true; } - */ - /* - public void resolve(StateTable st, EventTable et, VarTable vt) { - - //System.out.println(st); - //System.out.println(toString()); - //System.out.println("Resolving trans table"); - if (getAllTransNames().isEmpty()) DashErrors.noTrans(); - for (String tfqn: table.keySet()) { - //String tfqn = DashFQN.fqn(sfqn,t.name); - String parentFQN = DashFQN.chopPrefixFromFQN(tfqn); - // determining the src state - List fList = - table.get(tfqn).fromList.stream() - .map(p -> (p.src)) - .collect(Collectors.toList()); - - if (fList.size() > 1) DashErrors.tooMany("from", tfqn); - else if (fList.isEmpty()) - // can be a loop on root - table.get(tfqn) - .setSrc(new DashRef(parentFQN, Common.paramVars(getParamsIdx(tfqn), getParams(tfqn)))); - else - table.get(tfqn) - .setSrc( - st.resolveSrcDest("from", - fList.get(0), - tfqn, - getParamsIdx(tfqn), - getParams(tfqn), - vt)); - - // determining the dest state - List gList = - table.get(tfqn).gotoList.stream() - .map(p -> (p.dest)) - .collect(Collectors.toList()); - - if (gList.size() > 1) DashErrors.tooMany("goto", tfqn); - else if (gList.isEmpty()) - // can be a loop on root - table.get(tfqn) - .setDest(new DashRef(parentFQN, Common.paramVars(getParamsIdx(tfqn),getParams(tfqn)))); - else - table.get(tfqn) - .setDest( - st.resolveSrcDest("goto", - gList.get(0), - tfqn, - getParamsIdx(tfqn), - getParams(tfqn), - vt)); - - // determining the on (event) - List onExpList = - table.get(tfqn).onList.stream() - .map(p -> (p.getExp())) - .collect(Collectors.toList()); - if (onExpList.size() > 1) DashErrors.tooMany("on", tfqn); - else if (!onExpList.isEmpty()) { - table.get(tfqn) - .setOn( - et.resolveEvent("on", - onExpList.get(0), - st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), - tfqn, - getParamsIdx(tfqn), - getParams(tfqn), - vt)); - } - - // determining the send - List sendExpList = - table.get(tfqn).sendList.stream() - .map(p -> (p.getExp())) - .collect(Collectors.toList()); - if (sendExpList.size() > 1) DashErrors.tooMany("send", tfqn); - else if (!sendExpList.isEmpty()) { - table.get(tfqn) - .setSend( - et.resolveEvent("send", - sendExpList.get(0), - st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), - tfqn, - getParamsIdx(tfqn), - getParams(tfqn), - vt)); - } - - // determining the when (expr) - List whenExpList = - table.get(tfqn).whenList.stream() - .map(p -> (p.getWhen())) - .collect(Collectors.toList()); - if (whenExpList.size() > 1) DashErrors.tooMany("when", tfqn); - else if (!whenExpList.isEmpty()) { - table.get(tfqn) - .setWhen( - vt.resolveExpr("when", - whenExpList.get(0), - st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), - tfqn, - getParamsIdx(tfqn), - getParams(tfqn))); - } - - // determining the do - List doExpList = - table.get(tfqn).doList.stream() - .map(p -> (p.getDo())) - .collect(Collectors.toList()); - if (doExpList.size() > 1) DashErrors.tooMany("on", tfqn); - else if (!doExpList.isEmpty()) { - table.get(tfqn) - .setDo( - vt.resolveExpr("do", doExpList.get(0), - st.getRegion(DashFQN.chopPrefixFromFQN(tfqn)), - tfqn, - getParamsIdx(tfqn), - getParams(tfqn))); - } - - } - isResolved = true; - } - */ - - - - - // [n1,n2,...] - /*private List paramVars(List names) { - List o = new ArrayList(); - for (String n: names) o.add(ExprHelper.createVar(DashStrings.pName+n)); - return o; - }*/ - - - public boolean[] transAtThisParamDepth(int max) { boolean[] depthsInUse = new boolean[max+1]; // 0..max diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index c87000196..2440c0cae 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -99,12 +99,8 @@ public void resolve(StateTable st, EventTable et) { String sfqn = DashFQN.chopPrefixFromFQN(vfqn); setVarType(vfqn,ResolveExpr.resolveExpr(st, et, this, "var", false, false, true, sfqn,getVarType(vfqn) )); } - /* TODO: buffer types don't need resolving???? buf[element] - for (String bfqn: bufferTable.keySet()) { - String sfqn = DashFQN.chopPrefixFromFQN(bfqn); - vt.setVarType(vfqn,resolveExpr(null, null, this, "var", false, false, true, sfqn,vt.getVarType(bfqn) )); - } - */ + /* buffer types don't need resolving because just buf[element] */ + } @@ -218,147 +214,9 @@ public Boolean addBuffer(String vfqn, IntEnvKind k, List prms, List region, String fqn, List paramsIdx, List params) { - // Join: b1.a1.var - - // DashRefProcessRef: A/B/C[a1,b1]/var which became $$PROCESSREF$$. b1.a1.A/B/C/var in parsing - // a DashRefProcessRef could be either a value for an exp - // or a tuple for an event - - // BadJoin: var[a1,b1] which became b1.a1.var in parsing - - // don't include isDashRefArrow here because that is only possible for - // events (which are tuples) not actions - - // turns PRIME(v) into v' - - String v; - List paramsIdx - List paramValues; - if (isExprVar(exp)) { - v = getVarName((ExprVar) exp); - if (v.startsWith(thisName)) { - // thisSname gets replaced with p0_AID as a normal variable - // not a processref - String suffix = v.substring(thisName.length(),v.length()); - List match = new ArrayList(); - for (String x:region) - if (x.endsWith(suffix)) { - // x must exist because in region - Integer x = DashUtilFcns.lastElement(st.getParamsIdx(x)); - String p = DashUtilFcns.lastElement(st.getParams(x)); - match.add(Common.paramVar(x,p)); - } - if (match.size() == 1) - return match.get(0); - else if (match.size() > 1) - DashErrors.ambiguousUseOfThis(exp.toString()); - // else we carry on with it as a regular var name - } - paramValues = new ArrayList(); - } else if (isPrimedVar(exp)) { - v = getVarName((ExprVar) getSub(exp))+PRIME; - paramValues = new ArrayList(); - } else { - // name might not be fully resolved - v = DashRef.nameOfDashRefExpr(exp); - // have to recurse through param values - paramValues = DashRef.paramValuesOfDashRefExpr(exp).stream() - .map(i -> resolveExpr(st, xType, i, region, fqn, paramsIdx, params)) - .collect(Collectors.toList()); - } - String vfqn = DashFQN.fqn(v); - Boolean isPrimed = false; - if (hasPrime(v)) { - isPrimed = true; - vfqn = removePrime(vfqn); // vfqn.substring(0,vfqn.length()-1); - } - - // only place primes can be is in "do" expressions - if (!xType.equals("do") && isPrimed) { - DashErrors.noPrimedVarsIn(xType, v, fqn); - return null; - } - List matches = new ArrayList(); - if (paramValues.isEmpty()) { - // if no param values must be within the region of the same params (could be prefix of params) - for (String s:region) - // buffers and vars - for (String x:getNamesOfState(s)) { - if (DashFQN.suffix(x,vfqn)) matches.add(x); - } - } else { - // if it has params values, could be suffix of any var - // and later we check it has the right number of params - // vars and buffers - for (String x:getAllNames()) { - if (DashFQN.suffix(x,vfqn)) matches.add(x); - } - } - //System.out.println("vfqn: " + vfqn); - //System.out.println("matches: "+ matches); - //System.out.println("region: " + region); - if (matches.size() > 1) { - DashErrors.ambiguousVar(xType, v, fqn); - return null; - } else if (matches.isEmpty()) { - // its some var other than a dynamic variable - return exp; - } else { - String m = matches.get(0); - if (paramValues.isEmpty()) { - // must have same param values as trans b/c in same conc region - if (getParams(m).size() > paramsIdx.size()) { - // getRegion did not return things that all - // have the same parameter values - DashErrors.regionMatchesWrongParamNumber(); - return null; - } else { - // could be a subset of transition param values - List prmValues = - Common.paramVars( - paramsIdx.subList(0, getParams(m).size()), - params.subList(0,getParams(m).size())); - if (isPrimed) m = m + PRIME; - //System.out.println("here1" + m); - return DashRef.DashRefExpr(m, prmValues); - } - } else if (getParams(m).size() != paramValues.size()) { - // came with parameters so must be right number - DashErrors.fqnVarWrongNumberParameters(xType, v, fqn); - return null; - } else { - if (isPrimed && !isInternal(m)) { - DashErrors.cantPrimeAnExternal(v, fqn); - return null; - } - if (isPrimed) m = m+PRIME; - //System.out.println("here2" + m); - return DashRef.DashRefExpr( - m, - // have to recursive through expressions in parameters - paramValues.stream() - .map(i -> resolveExpr(st, xType, i, region, fqn, paramsIdx,params)) - .collect(Collectors.toList())); - } - } - } - */ // must be done after resolve // might be primed or unprimed From 557e90c2303eb923d9f004a2023468cb87fb439f Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 6 Jun 2023 21:07:47 -0400 Subject: [PATCH 052/129] fixed it so that CLI on .als does not run resolveAll twice (b/c it is run from within parseEverythingFromAlloyFile --- .../main/java/ca/uwaterloo/watform/dash4whole/Dash.java | 4 +--- .../ca/uwaterloo/watform/mainfunctions/MainFunctions.java | 4 +++- .../main/java/ca/uwaterloo/watform/parser/DashModule.java | 2 ++ .../main/java/ca/uwaterloo/watform/parser/ResolveExpr.java | 7 ++++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index fe4056240..d592b06fa 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -156,10 +156,8 @@ public static void main(String args[]) throws Exception { if (filename.endsWith(".als")) { try { - CompModule c = MainFunctions.parseAlloyFile(filename, rep); + CompModule c = MainFunctions.parseAlloyFileAndResolveAll(filename, rep); System.out.println("Parsed Alloy file"); - if (c == null) DashErrors.emptyFile(filename); - c = MainFunctions.resolveAlloy(c,rep); // will raise an exception if problems System.out.println("Resolved Alloy file"); executeCommands(c,cmdnum,rep); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index fe436c379..1a2660df0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -70,13 +70,15 @@ public static CompModule resolveAlloy(CompModule c, A4Reporter rep) { if (c == null) { DashErrors.emptyModule(); } else { + System.out.println("here1"); o = CompModule.resolveAll(rep,c); + System.out.println("here2"); } return o; } // make our CLI also work for .als files - public static CompModule parseAlloyFile(String filename, A4Reporter rep) { + public static CompModule parseAlloyFileAndResolveAll(String filename, A4Reporter rep) { CompModule c = CompUtil.parseEverything_fromFile(rep, null, filename); if (c == null) { DashErrors.emptyFile(filename); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 4dc2e86a0..32a992cf2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -541,6 +541,8 @@ public void debug(String tfqn) { if (tfqn != null) { System.out.println("src " + getTransSrc(tfqn)); System.out.println("dest " + getTransDest(tfqn)); + System.out.println("pre " + getTransWhen(tfqn)); + System.out.println("post " + getTransDo(tfqn)); System.out.println("getScope " + getScope(tfqn)); System.out.println("getClosestParamAnces: "+getClosestParamAnces(getTransSrc(tfqn).getName())); //System.out.println("getAllNonParamDesc: " +getAllNonParamDesc(getClosestConcAnces(getTransSrc(tfqn).getName()))); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java index d60185ec8..2898d680a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java @@ -186,6 +186,9 @@ static Expr resolveDashRef( StateTable st, assert(isExprVar(exp) || isPrimedVar(exp) || DashRef.isDashRef(exp)); assert(kind.equals("state") || kind.equals("event") || kind.equals("var")); + + //System.out.println("in: " + exp); + String v; List paramsIdx = st.getParamsIdx(sfqn); List params = st.getParams(sfqn); @@ -300,7 +303,9 @@ else if (matches.size() > 1) { else if (kind.equals("event")) { return DashRef.createEventDashRef(pos, m, paramValues); } else { //System.out.println(DashRef.createVarDashRef(pos, m, paramValues)); - return DashRef.createVarDashRef(pos, m, paramValues); + Expr out = DashRef.createVarDashRef(pos, m, paramValues); + //System.out.println("out: " + out); + return out; } } } From c97ae1433098294bfaf447a291c362a429094178 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 8 Jun 2023 21:15:45 -0400 Subject: [PATCH 053/129] added enter/exit/pred features + ranking scheme for matching references --- .../parser/Dash-cup-grammar.txt | 18 +- .../parser/Dash-cup-symbols.txt | 2 + .../parser/Dash-cup-terminals.txt | 2 + .../parser/Dash-lex-addition.txt | 2 + org.alloytools.alloy.dash/parser/Dash.cup | 22 +- org.alloytools.alloy.dash/parser/Dash.lex | 2 + .../ca/uwaterloo/watform/ast/DashAction.java | 32 --- .../uwaterloo/watform/ast/DashCondition.java | 32 --- .../ca/uwaterloo/watform/ast/DashEntered.java | 20 ++ .../ca/uwaterloo/watform/ast/DashExited.java | 20 ++ .../ca/uwaterloo/watform/ast/DashExpr.java | 113 ++------- .../ca/uwaterloo/watform/ast/DashInit.java | 16 +- .../ca/uwaterloo/watform/ast/DashInv.java | 33 +-- .../ca/uwaterloo/watform/ast/DashPred.java | 35 +++ .../ca/uwaterloo/watform/ast/DashState.java | 61 ++++- .../ca/uwaterloo/watform/core/DashErrors.java | 22 +- .../ca/uwaterloo/watform/core/DashFQN.java | 38 +++ .../uwaterloo/watform/core/DashStrings.java | 4 +- .../watform/dashtoalloy/AddTransPost.java | 49 ++-- .../uwaterloo/watform/parser/DashModule.java | 26 +- .../uwaterloo/watform/parser/EventTable.java | 12 + .../uwaterloo/watform/parser/PredTable.java | 76 ++++++ .../uwaterloo/watform/parser/ResolveExpr.java | 233 ++++++++++++------ .../uwaterloo/watform/parser/StateTable.java | 56 +++-- .../uwaterloo/watform/parser/TransTable.java | 22 +- .../ca/uwaterloo/watform/parser/VarTable.java | 5 +- .../alloy/dash/DashCoreFQNTests.java | 27 ++ .../alloy/dash/DashWffFailTests.java | 1 + .../resources/wfffail/ambiguousSrcDest1.dsh | 3 +- .../resources/wfffail/ambiguousSrcDest2.dsh | 8 + .../src/test/resources/wfffail/test11.dsh | 3 +- 31 files changed, 668 insertions(+), 327 deletions(-) delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEntered.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExited.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashPred.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/PredTable.java create mode 100644 org.alloytools.alloy.dash/src/test/resources/wfffail/ambiguousSrcDest2.dsh diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt index 034797bfe..9e571091a 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -263,9 +263,21 @@ StateItem ::= INIT:o Super:v StateItem ::= INVARIANT:o Super:v {: RESULT = new DashInv(o, v); :}; -StateItem ::= INVARIANT:o Name:n Super:v +// invariant +StateItem ::= INVARIANT:o Name: n Super:v {: RESULT = new DashInv(o, n.label, v); :}; +// entered +StateItem ::= ENTER:o Super:v + {: RESULT = new DashEntered(o, v); :}; + +// exited +StateItem ::= EXIT:o Super:v + {: RESULT = new DashExited(o, v); :}; + +//StateItem ::= INVARIANT:o Name:n Super:v +// {: RESULT = new DashInv(o, n.label, v); :}; + // action //StateItem ::= ACTION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE // {: RESULT = new DashAction(o, n.label, e); :}; @@ -274,6 +286,10 @@ StateItem ::= INVARIANT:o Name:n Super:v //StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE // {: RESULT = new DashCondition(o, n.label, e); :}; +// named expression +StateItem ::= PRED:o Name:n LBRACE Expr:e RBRACE + {: RESULT = new DashPred(o, n.label, e); :}; + // transition StateItem ::= TRANS:o Name:n LBRACE TransItemList:c RBRACE {: RESULT = new DashTrans(o, n.label, c); :}; diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt b/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt index 784ff979d..83bc72e55 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-symbols.txt @@ -14,6 +14,8 @@ ch.put(DashSym.INIT, "init"); ch.put(DashSym.INVARIANT, "invariant"); + ch.put(DashSym.ENTER, "enter"); + ch.put(DashSym.EXIT, "exit"); //ch.put(DashSym.ACTION, "action"); //ch.put(DashSym.CONDITION, "condition"); diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt b/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt index 5f1e76a77..47094a0a4 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-terminals.txt @@ -14,6 +14,8 @@ terminal Pos BUF; terminal Pos INIT; terminal Pos INVARIANT; +terminal Pos ENTER; +terminal Pos EXIT; //terminal Pos ACTION; //terminal Pos CONDITION; diff --git a/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt b/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt index fcf7e5092..43691b77c 100644 --- a/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt +++ b/org.alloytools.alloy.dash/parser/Dash-lex-addition.txt @@ -10,6 +10,8 @@ "init" { return alloy_sym(yytext(), DashSym.INIT );} "invariant" { return alloy_sym(yytext(), DashSym.INVARIANT );} +"enter" { return alloy_sym(yytext(), DashSym.ENTER );} +"exit" { return alloy_sym(yytext(), DashSym.EXIT );} //"action" { return alloy_sym(yytext(), DashSym.ACTION );} //"condition" { return alloy_sym(yytext(), DashSym.CONDITION );} diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index 19170a5ef..d7e4aeb9c 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -279,6 +279,8 @@ parser code {: ch.put(DashSym.INIT, "init"); ch.put(DashSym.INVARIANT, "invariant"); + ch.put(DashSym.ENTER, "enter"); + ch.put(DashSym.EXIT, "exit"); //ch.put(DashSym.ACTION, "action"); //ch.put(DashSym.CONDITION, "condition"); @@ -591,6 +593,8 @@ terminal Pos BUF; terminal Pos INIT; terminal Pos INVARIANT; +terminal Pos ENTER; +terminal Pos EXIT; //terminal Pos ACTION; //terminal Pos CONDITION; @@ -1517,9 +1521,21 @@ StateItem ::= INIT:o Super:v StateItem ::= INVARIANT:o Super:v {: RESULT = new DashInv(o, v); :}; -StateItem ::= INVARIANT:o Name:n Super:v +// invariant +StateItem ::= INVARIANT:o Name: n Super:v {: RESULT = new DashInv(o, n.label, v); :}; +// entered +StateItem ::= ENTER:o Super:v + {: RESULT = new DashEntered(o, v); :}; + +// exited +StateItem ::= EXIT:o Super:v + {: RESULT = new DashExited(o, v); :}; + +//StateItem ::= INVARIANT:o Name:n Super:v +// {: RESULT = new DashInv(o, n.label, v); :}; + // action //StateItem ::= ACTION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE // {: RESULT = new DashAction(o, n.label, e); :}; @@ -1528,6 +1544,10 @@ StateItem ::= INVARIANT:o Name:n Super:v //StateItem ::= CONDITION:o Name:n LBRACKET Expr:e RBRACKET LBRACE RBRACE // {: RESULT = new DashCondition(o, n.label, e); :}; +// named expression +StateItem ::= PRED:o Name:n LBRACE Expr:e RBRACE + {: RESULT = new DashPred(o, n.label, e); :}; + // transition StateItem ::= TRANS:o Name:n LBRACE TransItemList:c RBRACE {: RESULT = new DashTrans(o, n.label, c); :}; diff --git a/org.alloytools.alloy.dash/parser/Dash.lex b/org.alloytools.alloy.dash/parser/Dash.lex index 3f1bfdcda..36be89477 100644 --- a/org.alloytools.alloy.dash/parser/Dash.lex +++ b/org.alloytools.alloy.dash/parser/Dash.lex @@ -253,6 +253,8 @@ import edu.mit.csail.sdg.parser.CompModule; "init" { return alloy_sym(yytext(), DashSym.INIT );} "invariant" { return alloy_sym(yytext(), DashSym.INVARIANT );} +"enter" { return alloy_sym(yytext(), DashSym.ENTER );} +"exit" { return alloy_sym(yytext(), DashSym.EXIT );} //"action" { return alloy_sym(yytext(), DashSym.ACTION );} //"condition" { return alloy_sym(yytext(), DashSym.CONDITION );} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java deleted file mode 100644 index 288bcb32e..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashAction.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - These classes are used only during parsing because - we do not know what order items within a state will be parsed in. -*/ - -// Not currently used - -package ca.uwaterloo.watform.ast; - -import ca.uwaterloo.watform.core.DashStrings; - -import edu.mit.csail.sdg.alloy4.Pos; -import edu.mit.csail.sdg.ast.Expr; - -public class DashAction extends Dash { - - public String name; - public Expr expr; - - public DashAction(Pos p, String n, Expr e) { - assert(n != null & e != null); - this.pos = p; - this.name = n; - this.expr = e; - } - public String toString() { - String s = new String(); - s += DashStrings.actionName + " " + name + " [\n"; - s += expr.toString() + "\n"; - return s + "] { }\n"; - } -} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java deleted file mode 100644 index 34f094f12..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashCondition.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - These classes are used only during parsing because - we do not know what order items within a state will be parsed in. -*/ - -// Not used now - -package ca.uwaterloo.watform.ast; - -import ca.uwaterloo.watform.core.DashStrings; - -import edu.mit.csail.sdg.alloy4.Pos; -import edu.mit.csail.sdg.ast.Expr; - -public class DashCondition extends Dash { - - public String name; - public Expr expr; - - public DashCondition(Pos p, String n, Expr e) { - assert(n != null && e != null); - this.pos = p; - this.name = n; - this.expr = e; - } - public String toString() { - String s = new String(); - s += DashStrings.conditionName + " " + name + " [\n"; - s += expr.toString() + "\n"; - return s + "] { }\n"; - } -} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEntered.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEntered.java new file mode 100644 index 000000000..2ac330068 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashEntered.java @@ -0,0 +1,20 @@ +package ca.uwaterloo.watform.ast; + + + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashEntered extends DashExpr { + + + public DashEntered(Pos p, Expr e) { + super(p,e); + } + + public String toString() { + return super.toString(DashStrings.enterName); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExited.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExited.java new file mode 100644 index 000000000..1f6ea5252 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExited.java @@ -0,0 +1,20 @@ +package ca.uwaterloo.watform.ast; + + + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashExited extends DashExpr { + + + public DashExited(Pos p, Expr e) { + super(p,e); + } + + public String toString() { + return super.toString(DashStrings.exitName); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java index 691de29d5..08f184aea 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashExpr.java @@ -1,98 +1,33 @@ -/* is this used? */ +/* + These classes are used only during parsing because + we do not know what order items within a state will be parsed in. +*/ package ca.uwaterloo.watform.ast; -import edu.mit.csail.sdg.alloy4.Pos; -import edu.mit.csail.sdg.ast.Expr; - -public class DashExpr extends Dash { - /* a wrapper around an Alloy Expr */ - - private Expr ae; - - public DashExpr(Pos pos,Expr a) { - assert(a != null); - this.pos = pos; - this.ae = a; - - } - public String toString() { - return ae.toString(); - } - /* - private Expr recurseResolveAll(Expr e, Set ignore, String pth, symbolTable) { - // replace var names by FQNs - // replace "this" with ... - // replace buffers with ... - // do not need to record params b/c that will be in SymbolTable - // ignore is the set of bound variables +import ca.uwaterloo.watform.core.DashStrings; - if (e isinstance ExprVar) { - if (not (ignore.contains(e.label)) { - if e.label.endsWith(DashStrings.PRIME) String x = e.label.substring(0,e.label.size()-1); - else String x = e.label; - if (!isFQN(x)) { - // replace var with FQN - //NAD we are assuming that it has a no type - if e.label.endsWith(DashStrings.PRIME) Expr exp = createVar(fqn(pth,x) + DashStrings.PRIME) - else exp = createVar(fqn(pth + e.label.substring(0,e.label.size()-1))); - } - symbolTable.addUsed(x); - return exp; - } else return e; - } else if (e isinstance ExprUnary) { - return e.op.make(recurseResolveAll(e.sub, ignore,pth)); - } else if (e isinstance ExprBinary) { - Expr left = recurseResolveAll(e.left,ignore,pth); - Expr right = recurseResolveAll(e.right,ignore,path); - return e.op.make(left,right); - } else if (e isinstance ExprITE) { - Expr cond = recurseResolveAll(e.cond,ignore,pth); - Expr left = recurseResolveAll(e.left,ignore,pth); - Expr right = recurseResolveAll(e.right,ignore,path); - return createITE(cond,left,right); - } else if (e isinstance ExprQT) { - Set ig = new HashSet(); - for (d: e.decls) for (x: d.names) ig.all(x.label); - Expr sub = recurseResolveAll(e.sub, ignore.addAll(ig),pth); - return createExprQT(e.op,e.decls,sub); - } else { - // expr type not yet covered in code - } - } +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; - public Expr resolveAll(String pth, symbolTable) { - return DashExpr(recurseResolveAll(ae,emptySet(),pth)); - } +public abstract class DashExpr extends Dash { - private Set recurseGetDynamicSymbols(Expr e, Set ignore) { - // ignore is the set of bound variables - if (e isinstance ExprVar && not(ignore.contains(e.label)) { - if e.label.endsWith(DashStrings.PRIME) { - Set hs = new HashSet() - return hs.add(e) - } else return emtpySet(); - } else if (e isinstance ExprUnary) { - return recurseGetDynamicSymbols(e.sub, ignore) - } else if (e isinstance ExprBinary) { - return recurseGetDynamicSymbols(e.left,ignore).addAll(recurseGetDynamicSymbols(e.right, ignore)) - } else if (e isinstance ExprITE) { - return recurseGetDynamicSymbols(e.left,ignore).addAll(recurseGetDynamicSymbols(e.right.ignore)).addAll(recurseGetDynamicSymbols(e.cond,ignore)) - } else if (e isinstance ExprQT) { - Set ig = new HashSet(); - for (d: e.decls) for (x: d.names) ig.all(x.label) - return recurseGetDynamicSymbols(e.sub,ignore.addAll(ig)) - } else { - // expr type not yet covered in code - } - } - public Set getDynamicSymbols() { - // look for which unbound vars (fully qualified name + params) in the symbol table are used in this expression - assert(resolved == true); - return recurseGetDynamicSymbols(ae, emptySet()); - } - */ + public Expr exp; -} \ No newline at end of file + public DashExpr(Pos p, Expr e) { + assert(e != null); + this.pos = p; + this.exp = e; + } + public String toString(String name) { + String s = new String(); + s += name + " {\n"; + s += exp.toString() + "\n"; + return s + "}\n"; + } + public Expr getExp() { + return exp; + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java index b0b0e166c..0007497f1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInit.java @@ -12,22 +12,12 @@ import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Expr; -public class DashInit extends Dash { - - public Expr init; +public class DashInit extends DashExpr { public DashInit(Pos p, Expr i) { - assert(i != null); - this.pos = p; - this.init = i; + super(p,i); } public String toString() { - String s = new String(); - s += DashStrings.initName + " {\n"; - s += init.toString() + "\n"; - return s + "}\n"; - } - public Expr getInit() { - return init; + return super.toString(DashStrings.initName); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java index 6330b2f42..e4a2eb5fc 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashInv.java @@ -7,30 +7,21 @@ import ca.uwaterloo.watform.core.DashStrings; -public class DashInv extends Dash { - - public Expr inv; - public String name; // has no meaning - public DashInv(Pos pos, Expr inv) { - this.pos = pos; - this.name = null; - this.inv = inv; +public class DashInv extends DashExpr { + + String name; // unused + + public DashInv(Pos p, Expr inv) { + super(p,inv); + } - public DashInv(Pos p, String n, Expr i) { - assert(n != null && i != null); - this.pos = pos; + + public DashInv(Pos p, String n, Expr inv) { + super(p,inv); this.name = n; - this.inv = i; } + public String toString() { - String s = new String(); - s += DashStrings.invName +" "; - if (name != null) s += name; - s += " {\n"; - s += inv.toString() + "\n"; - return s + "}\n"; - } - public Expr getInv() { - return inv; + return super.toString(DashStrings.invName + " "+name); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashPred.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashPred.java new file mode 100644 index 000000000..4f6850a6b --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashPred.java @@ -0,0 +1,35 @@ +package ca.uwaterloo.watform.ast; + + + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashStrings; + +public class DashPred extends Dash { + + public Expr exp; + public String name; // has no meaning + + public DashPred(Pos p, String n, Expr i) { + assert(n != null && i != null); + this.pos = pos; + this.name = n; + this.exp = i; + } + public String toString() { + String s = new String(); + s += DashStrings.predName +" "; + if (name != null) s += name; + s += " {\n"; + s += exp.toString() + "\n"; + return s + "}\n"; + } + public Expr getExp() { + return exp; + } + public String getName() { + return name; + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java index 604f741b6..a23ead5b8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashState.java @@ -19,6 +19,7 @@ import ca.uwaterloo.watform.parser.TransTable; import ca.uwaterloo.watform.parser.EventTable; import ca.uwaterloo.watform.parser.VarTable; +import ca.uwaterloo.watform.parser.PredTable; import static ca.uwaterloo.watform.parser.ResolveExpr.*; @@ -122,7 +123,7 @@ public static List noSubstates() { * check for errors in the state hierarchy * and put all states in the state table */ - public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, List ances) { + public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, PredTable pt, List ances) { // this state is not yet in the st // but its parent is in the st @@ -158,6 +159,37 @@ public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, List< .collect(Collectors.toList()); xItems.removeAll(initList); + // entered --------------------- + List enteredList = new ArrayList(); + if (items != null) + enteredList = + items.stream() + .filter(i -> i instanceof DashEntered) + .map(p -> ((DashEntered) p).getExp()) + .collect(Collectors.toList()); + // enteredList is a list of Exp + // to remove, we need a list of items + xItems.removeAll( + items.stream() + .filter(i -> i instanceof DashEntered) + .collect(Collectors.toList())); + + // exited --------------------- + List exitedList = new ArrayList(); + if (items != null) + exitedList = + items.stream() + .filter(i -> i instanceof DashExited) + .map(p -> ((DashExited) p).getExp()) + .collect(Collectors.toList()); + // exitedList is a list of Exp + // to remove, we need a list of items + xItems.removeAll( + items.stream() + .filter(i -> i instanceof DashExited) + .collect(Collectors.toList())); + + /* // actions --------------------- List actionList = new ArrayList(); if (items != null) @@ -177,6 +209,7 @@ public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, List< .map(p -> (DashCondition) p) .collect(Collectors.toList()); xItems.removeAll(conditionList); + */ // --------------------- // process the children @@ -208,7 +241,7 @@ public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, List< if (substatesList.isEmpty() ) { if (!st.add(sfqn, kind, param, newParams, newParamsIdx, def,parentfqn, new ArrayList(), - invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; + invList, initList, enteredList, exitedList)) DashErrors.addStateToStateTableDup(sfqn);; } else { @@ -222,10 +255,10 @@ public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, List< // add this state to the table if (!st.add(sfqn,kind, param, newParams,newParamsIdx, def, parentfqn, childFQNs, - invList, initList, actionList, conditionList)) DashErrors.addStateToStateTableDup(sfqn);; + invList, initList, enteredList, exitedList)) DashErrors.addStateToStateTableDup(sfqn);; // add all substates to the table - for (DashState s: substatesList) s.load(st, tt, et, vt, newAnces); + for (DashState s: substatesList) s.load(st, tt, et, vt, pt, newAnces); // make sure defaults are correct // if there's only one child it is automatically the default @@ -306,6 +339,24 @@ public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, List< } xItems.removeAll(varDeclsList); + // add preds ------------------------ + List predsList = new ArrayList(); + if (items != null) + predsList = + items.stream() + .filter(i -> i instanceof DashPred) + .map(p -> (DashPred) p) + .collect(Collectors.toList()); + // put in var table with FQN + for (DashPred p:predsList) { + String name = p.getName(); + Expr e = p.getExp(); + if (DashFQN.isFQN(name)) DashErrors.nameCantBeFQN(p.getPos(), name); + String nfqn = DashFQN.fqn(sfqn,name); + if (!pt.addPred(nfqn,e)) DashErrors.duplicateName(p.getPos(),name); + } + xItems.removeAll(predsList); + // add declared buffers --------------------------- List bufferDeclsList = new ArrayList(); if (items != null) @@ -346,7 +397,7 @@ public void load(StateTable st, TransTable tt, EventTable et, VarTable vt, List< xItems.removeAll(transList); - if (!xItems.isEmpty()) DashErrors.nonEmptyStateItems(); + if (!xItems.isEmpty()) DashErrors.nonEmptyStateItems(xItems); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 57377c899..80c7a260d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -4,6 +4,8 @@ package ca.uwaterloo.watform.core; +import java.util.List; + import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.alloy4.Err; import edu.mit.csail.sdg.alloy4.ErrorSyntax; @@ -42,6 +44,10 @@ public static void allAndDefaults(String sfqn) throws Err { public static void stateNameCantBeFQN(Pos o, String name) throws Err { throw new ErrorSyntax(o,stateNameCantBeFQNMsg+name); } + public static String nameCantBeFQNMsg = "When declared, name cannot have slash: "; + public static void nameCantBeFQN(Pos o, String name) throws Err { + throw new ErrorSyntax(o,nameCantBeFQNMsg+name); + } public static String dupSiblingNamesMsg = "Duplicate sibling state names: "; public static void dupSiblingNames(String dups) throws Err { throw new ErrorSyntax(dupSiblingNamesMsg + dups); @@ -117,6 +123,10 @@ public static void bufferNameCantBeFQN(Pos o, String s) { public static void duplicateBufferName(Pos o, String s) { throw new ErrorSyntax(o, duplicateBufferNameMsg + s); } + public static String duplicateNameMsg = "Name already in use: "; + public static void duplicateName(Pos o, String s) { + throw new ErrorSyntax(o, duplicateNameMsg + s); + } // event errors public static String tooManyMsg = "Multiple "; @@ -184,7 +194,10 @@ public static String nonParamUseOfThis(Pos pos, String expString) { public static void wrongNumberParams(Pos pos, String expString) { throw new ErrorSyntax(pos + " " + wrongNumberParamsMsg + expString); } - + public static String varPredOverlapMsg = "Same name used for dynamic variable and Dash predicate: "; + public static void varPredOverlap(List s) { + throw new ErrorSyntax(varPredOverlapMsg + s); + } // parts of the code that should be unreachable ------------- public static String ancesNotPrefixMsg = " must be a prefix of "; @@ -219,6 +232,9 @@ public static void transDoesNotExist(String s1, String n) throws Err { public static void varDoesNotExist(String s1, String n) throws Err { throw new ErrorFatal("for function "+s1+", var "+n+ " does not exist in var table"); } + public static void predDoesNotExist(String s1, String n) throws Err { + throw new ErrorFatal("for function "+s1+", var "+n+ " does not exist in pred table"); + } public static void bufferDoesNotExist(String s1, String n) throws Err { throw new ErrorFatal("for function "+s1+", buffer "+n+ " does not exist in buffer table"); } @@ -239,8 +255,8 @@ public static void paramNumberProblem(String s) throws Err { public static void chopPrefixFromFQNwithNoPrefix(String s) throws Err { throw new ErrorFatal(chopPrefixFromFQNwithNoPrefixMsg + s); } - public static void nonEmptyStateItems() throws Err { - throw new ErrorFatal("Non-empty state items at end of state resolve"); + public static void nonEmptyStateItems(List x) throws Err { + throw new ErrorFatal("Non-empty state items at end of state resolve: " + x); } public static void nonEmptyTransItems() throws Err { throw new ErrorFatal("Non-empty trans items at end of trans resolve"); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java index 9117cf093..e8a0019fc 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashFQN.java @@ -77,6 +77,44 @@ public static String fqn(List pth, String parent, String child) { public static List splitFQN(String fqn) { return Arrays.asList(fqn.split(internalQualChar)); } + // A/B + B/C => A/B/C + // no longer used probably + public static String mergeFQN(String fqn1, String fqn2) { + List fqn1parts = splitFQN(fqn1); + List fqn2parts = splitFQN(fqn2); + int fqn1i = 0; + int fqn2i = 0; + List outparts = new ArrayList(); + while (fqn1i < fqn1parts.size() && !(fqn1parts.get(fqn1i).equals(fqn2parts.get(fqn2i))) ) { + outparts.add(fqn1parts.get(fqn1i)); + fqn1i++; + } + if (fqn1i == fqn1parts.size()) return ""; + while (fqn1i < fqn1parts.size() + && fqn2i < fqn2parts.size() + && fqn1parts.get(fqn1i).equals(fqn2parts.get(fqn2i)) + ) { + outparts.add(fqn1parts.get(fqn1i)); + fqn1i++; + fqn2i++; + } + if (fqn1i == fqn1parts.size() && fqn2i == fqn2parts.size()) return fqn(outparts); + if (fqn1i == fqn1parts.size() && fqn2i < fqn2parts.size()) { + while (fqn2i < fqn2parts.size()) { + outparts.add(fqn2parts.get(fqn2i)); + fqn2i++; + } + return fqn(outparts); + } + else return ""; + } + public static int commonPrefixLength(String s1, String s2) { + List parts1 = splitFQN(s1); + List parts2 = splitFQN(s2); + int i = 0; + while (i < parts1.size() && i < parts2.size() && parts1.get(i).equals(parts2.get(i))) i++; + return i; + } public static String chopNameFromFQN(String fqn) { // this is from an output FQN return DashUtilFcns.lastElement(splitFQN(fqn)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index b826786b6..192e1bd3e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -63,8 +63,8 @@ public class DashStrings { public static String gotoName = "goto"; public static String sendName = "send"; public static String invName = "inv"; - public static String actionName = "action"; - public static String conditionName = "condition"; + public static String enterName = "enter"; + public static String exitName = "exit"; public static String initName = "init"; // user must be aware of this name diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index f048e5707..da8bbca19 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -62,7 +62,7 @@ public class AddTransPost { // only internal events are those generated by t1 forall i: eventsi' :> InternalEvent = t1_send_ev (if i) // env events stay the same - eventsi' :> EnvironmentalEvent = eventsi :> EnvironmentalEvent + forall i: eventsi' :> EnvironmentalEvent = eventsi :> EnvironmentalEvent // empty previous scopes used and just add this one forall i : scopesUsedi' = scopesUsed } else { @@ -119,7 +119,7 @@ public static void addTransPost(DashModule d, String tfqn) { List case1 = new ArrayList(); Expr c1; for (int i=0;i <= d.getMaxDepthParams(); i++) { - if (d.hasEventsAti(i)) { + if (d.hasInternalEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) rhs = translateDashRefToArrow(ev); else rhs = createNoneArrow(i); case1.add(createEquals( @@ -136,7 +136,7 @@ public static void addTransPost(DashModule d, String tfqn) { List case2 = new ArrayList(); Expr c2; for (int i=0;i <= d.getMaxDepthParams(); i++) { - if (d.hasEventsAti(i)) { + if (d.hasInternalEventsAti(i)) { q = createRangeRes(curEvents(i), allInternalEventsVar()); if (ev != null && ev.getParamValues().size() == i) rhs = createUnion(translateDashRefToArrow(ev), q); else rhs = q; @@ -161,23 +161,28 @@ public static void addTransPost(DashModule d, String tfqn) { // (eventsi' :> InternalEvent = none) (if not i) // and (eventsi' :> EnvironmentalEvent = eventsi :> EnvironmentalEvent) List case3 = new ArrayList(); - Expr c3; + Expr c3; + // have to be initialized to something + Expr intEvExpr = createNone(); + Expr envEvExpr = createNone(); for (int i=0;i <= d.getMaxDepthParams(); i++) { - if (d.hasEventsAti(i)) { + if (d.hasInternalEventsAti(i)) { if (ev != null && ev.getParamValues().size() == i) rhs1 = translateDashRefToArrow(ev); else rhs1 = createNoneArrow(i); - if (d.hasEnvironmentalEvents()) - case3.add(createAnd( - createEquals( - createRangeRes(nextEvents(i),allInternalEventsVar()), - rhs1), - createEquals( - createRangeRes(nextEvents(i),allEnvironmentalEventsVar()), - createRangeRes(curEvents(i),allEnvironmentalEventsVar()) ))); - else - case3.add(createEquals( - createRangeRes(nextEvents(i),allInternalEventsVar()), - rhs1)); + intEvExpr = createEquals( + createRangeRes(nextEvents(i),allInternalEventsVar()), + rhs1); + } + if (d.hasEnvironmentalEventsAti(i)) { + envEvExpr = createEquals( + createRangeRes(nextEvents(i),allEnvironmentalEventsVar()), + createRangeRes(curEvents(i),allEnvironmentalEventsVar()) ); + } + if (d.hasInternalEventsAti(i)) { + if (d.hasEnvironmentalEventsAti(i)) case3.add(createAnd(intEvExpr, envEvExpr)); + else case3.add(intEvExpr); + } else { + if (d.hasEnvironmentalEventsAti(i)) case3.add(envEvExpr); } case3.add(createEquals(nextScopesUsed(i),createNoneArrow(i))); } @@ -240,11 +245,11 @@ public static void addTransPost(DashModule d, String tfqn) { } public static Expr createVarDoesNotChange(DashModule d, String x) { - return createAll( - paramDecls(d.getVarBufferParamsIdx(x),d.getAllParamsInOrder()), - createEquals( - createJoinList(DashUtilFcns.newListWith(curParamVars(d.getVarBufferParamsIdx(x), d.getVarBufferParams(x)),createVar(x))), - createJoinList(DashUtilFcns.newListWith(nextParamVars(d.getVarBufferParamsIdx(x), d.getVarBufferParams(x)),createVar(x))))); + Expr e = createEquals( + createJoinList(DashUtilFcns.newListWith(curParamVars(d.getVarBufferParamsIdx(x), d.getVarBufferParams(x)),createVar(translateFQN(x)))), + createJoinList(DashUtilFcns.newListWith(nextParamVars(d.getVarBufferParamsIdx(x), d.getVarBufferParams(x)),createVar(translateFQN(x))))); + if (d.getVarBufferParamsIdx(x).isEmpty()) return e; + else return createAll(paramDecls(d.getVarBufferParamsIdx(x),d.getAllParamsInOrder()),e); } // pred call: testIfNextStable[s,s',scope1, scope2, ... , send1, send2, ...] diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 32a992cf2..1d6920c67 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -52,7 +52,7 @@ public class DashModule extends CompModuleHelper { private TransTable transTable = new TransTable(); private EventTable eventTable = new EventTable(); private VarTable varTable = new VarTable(); - + private PredTable predTable = new PredTable(); // once created and parsed, the following are @@ -287,6 +287,12 @@ public boolean hasEvents() { public boolean hasEventsAti(int i) { return eventTable.hasEventsAti(i); } + public boolean hasInternalEventsAti(int i) { + return eventTable.hasInternalEventsAti(i); + } + public boolean hasEnvironmentalEventsAti(int i) { + return eventTable.hasEnvironmentalEventsAti(i); + } public boolean hasConcurrency() { return stateTable.hasConcurrency(root.name); } @@ -567,7 +573,7 @@ public void resolveAllDash(A4Reporter rep) { root = roots.get(0); // passed with empty set of params, empty set of ancestors stateTable.setRoot(root.name); - root.load(stateTable,transTable, eventTable, varTable, new ArrayList()); + root.load(stateTable,transTable, eventTable, varTable, predTable, new ArrayList()); // have to do states first so siblings of trans parent state // are in place to search for src/dest // root.resolveTransTable(stateTable,transTable); @@ -575,10 +581,20 @@ public void resolveAllDash(A4Reporter rep) { // if no transitions? // resolves inits, invariants - stateTable.resolve(getRootName(), eventTable, varTable); + stateTable.resolve(getRootName(), eventTable, varTable, predTable); + + transTable.resolve(stateTable, eventTable, varTable, predTable); + varTable.resolve(stateTable, eventTable, predTable); + + // varTable and predTable names cannot overlap + + if (!Collections.disjoint(varTable.getAllVarNames() , predTable.getAllNames())) { + List x = varTable.getAllVarNames(); + x.retainAll(predTable.getAllNames()); + DashErrors.varPredOverlap(x); + } + // TODO check for other overlaps?? - transTable.resolve(stateTable, eventTable, varTable); - varTable.resolve(stateTable, eventTable); maxDepthParams = stateTable.getMaxDepthParams(); transAtThisParamDepth = transTable.transAtThisParamDepth(maxDepthParams); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java index a908f454d..b4afb6a5b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/EventTable.java @@ -83,6 +83,18 @@ public boolean hasEventsAti(int i) { } return false; } + public boolean hasInternalEventsAti(int i) { + for (String e: table.keySet()) { + if (table.get(e).params.size() == i && table.get(e).kind == IntEnvKind.INT) return true; + } + return false; + } + public boolean hasEnvironmentalEventsAti(int i) { + for (String e: table.keySet()) { + if (table.get(e).params.size() == i && table.get(e).kind == IntEnvKind.ENV) return true; + } + return false; + } public boolean hasInternalEvents() { for (String e: table.keySet()) { if (table.get(e).kind == IntEnvKind.INT) return true; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/PredTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/PredTable.java new file mode 100644 index 000000000..9c3dd828a --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/PredTable.java @@ -0,0 +1,76 @@ +package ca.uwaterloo.watform.parser; + +import java.util.Set; +import java.util.List; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Collections; +import java.util.stream.Collectors; + + +import edu.mit.csail.sdg.ast.*; +import edu.mit.csail.sdg.alloy4.ConstList; + +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.core.*; +import static ca.uwaterloo.watform.core.DashUtilFcns.*; +import static ca.uwaterloo.watform.core.DashStrings.*; +import ca.uwaterloo.watform.core.DashRef; +import ca.uwaterloo.watform.dashtoalloy.Common; + +import ca.uwaterloo.watform.parser.StateTable; +import ca.uwaterloo.watform.parser.VarTable; + +public class PredTable { + + private HashMap predTable; + + public PredTable() { + this.predTable = new LinkedHashMap(); + } + + public class PredElement { + + // this expression must be resolved in the context of the guard/action + // it is used in + // because otherwise we might have orphan parameter values + // from the context where it is declared + private Expr exp; + + public PredElement( + Expr e) { + this.exp = e; + } + public String toString() { + String s = new String(); + s += "exp: "+exp.toString() + "\n"; + return s; + } + } + + public String toString() { + String s = new String("PRED TABLE\n"); + for (String k:predTable.keySet()) { + s += " ----- \n"; + s += k + "\n"; + s += predTable.get(k).toString(); + } + return s; + } + public Boolean addPred(String n, Expr e) { + if (predTable.containsKey(n)) return false; + else { predTable.put(n, new PredElement(e)); return true; } + } + public Expr getExp(String pfqn) { + if (predTable.containsKey(pfqn)) return predTable.get(pfqn).exp; + else { DashErrors.predDoesNotExist("getExp", pfqn); return null; } + } + public boolean contains(String pfqn) { + return predTable.containsKey(pfqn); + } + public List getAllNames() { + return new ArrayList(predTable.keySet()); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java index 2898d680a..8438a1fb2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/ResolveExpr.java @@ -65,6 +65,7 @@ public class ResolveExpr{ public static Expr resolveExpr( StateTable st, EventTable et, VarTable vt, + PredTable pt, String kind, boolean primeOk, boolean primeOkInPrmValues, @@ -76,21 +77,21 @@ public static Expr resolveExpr( StateTable st, isPrimedVar(exp) || DashRef.isDashRef(exp)) { - return resolveDashRef(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, exp); + return resolveDashRef(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, exp); } else if (isExprBinary(exp)) { return ((ExprBinary) exp).op.make( exp.pos, exp.closingBracket, - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); } else if (isExprBadJoin(exp)) { return ExprBadJoin.make( exp.pos, exp.closingBracket, - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); } else if (exp instanceof ExprCall) { return ExprCall.make( @@ -98,7 +99,7 @@ public static Expr resolveExpr( StateTable st, exp.closingBracket, ((ExprCall) exp).fun, ((ExprCall) exp).args.stream() - .map(i -> resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) + .map(i -> resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) .collect(Collectors.toList()), ((ExprCall) exp).extraWeight); @@ -106,7 +107,7 @@ public static Expr resolveExpr( StateTable st, //TODO: check into this cast // not sure why is it necessary ConstList x = (ConstList) ((ExprChoice) exp).choices.stream() - .map(i -> resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) + .map(i -> resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) .collect(Collectors.toList()); return ExprChoice.make( false, @@ -117,9 +118,9 @@ public static Expr resolveExpr( StateTable st, } else if (exp instanceof ExprITE){ return ExprITE.make( exp.pos, - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getCond(exp)), - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getCond(exp)), + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getLeft(exp)), + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, getRight(exp))); } else if (exp instanceof ExprList){ return ExprList.make( @@ -127,22 +128,22 @@ public static Expr resolveExpr( StateTable st, exp.closingBracket, ((ExprList) exp).op, ((ExprList) exp).args.stream() - .map(i -> resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) + .map(i -> resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i)) .collect(Collectors.toList()) ); } else if (exp instanceof ExprUnary){ return ((ExprUnary) exp).op.make( exp.pos, - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprUnary) exp).sub)); + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprUnary) exp).sub)); } else if (exp instanceof ExprLet){ //TODO rule out var name return ExprLet.make( exp.pos, ((ExprLet) exp).var, - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprLet) exp).expr), - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprLet) exp).sub) ); + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprLet) exp).expr), + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, ((ExprLet) exp).sub) ); } else if (exp instanceof ExprQt){ //TODO rule out var names in delcs as dynamic vars later @@ -155,14 +156,14 @@ public static Expr resolveExpr( StateTable st, i.disjoint2, i.isVar, i.names, - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i.expr))) + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn, i.expr))) .collect(Collectors.toList()); return ((ExprQt) exp).op.make( exp.pos, exp.closingBracket, decls, - resolveExpr(st, et, vt, kind, primeOk, primeOkInPrmValues, thisOk, sfqn,((ExprQt) exp).sub)); + resolveExpr(st, et, vt, pt,kind, primeOk, primeOkInPrmValues, thisOk, sfqn,((ExprQt) exp).sub)); } else if (exp instanceof ExprConstant){ return exp; @@ -176,6 +177,7 @@ public static Expr resolveExpr( StateTable st, static Expr resolveDashRef( StateTable st, EventTable et, VarTable vt, + PredTable pt, String kind, boolean primeOk, boolean primeOkInPrmValues, @@ -205,7 +207,7 @@ static Expr resolveDashRef( StateTable st, // thisSname gets replaced with p0_AID as a normal variable // not a dashsref String suffix = v.substring(thisName.length(),v.length()); - List matches = findMatchesInRegion(st,et,vt,"state",sfqn,suffix); + List matches = findMatchesInRegion(st,et,vt,pt,"state",sfqn,suffix); if (matches.size() == 1 && st.hasParam(matches.get(0))) return Common.paramVar(st.getParamIdx(matches.get(0)), st.getParam(matches.get(0))); else if (matches.size() == 1 && !st.hasParam(matches.get(0))) @@ -234,83 +236,95 @@ else if (matches.size() > 1) { } // have to recurse through param values as VARs paramValues = ((DashRef) exp).getParamValues().stream() - .map(i -> resolveExpr(st, et, vt, "var", primeOkInPrmValues, primeOkInPrmValues, thisOk, sfqn, i)) + .map(i -> resolveExpr(st, et, vt, pt,"var", primeOkInPrmValues, primeOkInPrmValues, thisOk, sfqn, i)) .collect(Collectors.toList()); } + // now we have v as the name, paramValues as the possible empty set of resolved param values // and isPrimed is set correctly - //System.out.println("looking for "+v); + + List matches; if (paramValues.isEmpty()) { // if no param values must be within region // that has same param values - matches = findMatchesInRegion(st,et,vt,kind,sfqn,v); + matches = findMatchesInRegion(st,et,vt,pt,kind,sfqn,v); } else { // if it has params values, could be suffix of any var // and later we check it has the right number of params - matches = findMatches(st, et, vt, kind, v); + matches = findMatches(st, et, vt, pt,kind, v); } - //System.out.println(matches); - if (matches.size() > 1) { - DashErrors.ambiguousRef(pos, exp.toString()); - return null; - } else if (matches.isEmpty()) { + + String m = ""; + if (matches.isEmpty()) { if (kind.equals("state")) {DashErrors.unknownState(pos, exp.toString()); return null; } else if (kind.equals("event")) { DashErrors.unknownEvent(pos, exp.toString()); return null; } - else { // it's some var other than a dynamic variable - //System.out.println("no match: "+exp.toString()); - return exp; + else { + // it's some var other than a dynamic variable or a predicate name + return exp; } } else { - // one match - String m = matches.get(0); - List mParams; - if (kind.equals("state")) mParams = st.getParams(m); - else if (kind.equals("event")) mParams = et.getParams(m); - else mParams = vt.getParams(m); - - if (paramValues.isEmpty()) { - // must have same param values as sfqn b/c in same region - if (mParams.size() > paramsIdx.size()) { - // getRegion did not return things that all - // have the same parameter values - - DashErrors.wrongNumberParams(pos, exp.toString()); - return null; - } else { - // could be a subset of param values - paramValues = - Common.paramVars( - paramsIdx.subList(0, mParams.size()), - params.subList(0,mParams.size())); - } - } else if (mParams.size() != paramValues.size()) { - // came with parameters so must be right number - //TODO could paramValues b less than mParams???? - // and paramValues be a suffix of mParams??? - // since the name can be a suffix - DashErrors.wrongNumberParams(pos, exp.toString()); + m = chooseMatch(sfqn, matches); + if (m == null) { + DashErrors.ambiguousRef(pos, exp.toString()); + return null; + } + if (pt.contains(m)) + // best match is a predicate name + // has to be treated a little differently + // because does not have params and have to put its exp + // directly in place unlike a DashRef + // resolve the predicate value in place and add it in place + return resolveExpr(st,et,vt,pt,"var",primeOkInPrmValues, primeOkInPrmValues, thisOk, sfqn, pt.getExp(m)); + } + + // m is one match from var/state or event table + List mParams; + if (kind.equals("state")) mParams = st.getParams(m); + else if (kind.equals("event")) mParams = et.getParams(m); + else mParams = vt.getParams(m); + + if (paramValues.isEmpty()) { + // must have same param values as sfqn b/c in same region + if (mParams.size() > paramsIdx.size()) { + // getRegion did not return things that all + // have the same parameter values + + DashErrors.wrongNumberParams(pos, exp.toString()); return null; - } else + } else { + // could be a subset of param values + paramValues = + Common.paramVars( + paramsIdx.subList(0, mParams.size()), + params.subList(0,mParams.size())); + } + } else if (mParams.size() != paramValues.size()) { + // came with parameters so must be right number + //TODO could paramValues b less than mParams???? + // and paramValues be a suffix of mParams??? + // since the name can be a suffix + DashErrors.wrongNumberParams(pos, exp.toString()); + return null; + } else - if (isPrimed && kind.equals("var")) - if (!vt.isInternal(m)) { - DashErrors.cantPrimeAnExternalVar(pos, v); - return null; - } - if (isPrimed) m = m+PRIME; - if (kind.equals("state")) { return DashRef.createStateDashRef(pos, m, paramValues); } - else if (kind.equals("event")) { return DashRef.createEventDashRef(pos, m, paramValues); } - else { - //System.out.println(DashRef.createVarDashRef(pos, m, paramValues)); - Expr out = DashRef.createVarDashRef(pos, m, paramValues); - //System.out.println("out: " + out); - return out; + if (isPrimed && kind.equals("var")) + if (!vt.isInternal(m)) { + DashErrors.cantPrimeAnExternalVar(pos, v); + return null; } + if (isPrimed) m = m+PRIME; + if (kind.equals("state")) { return DashRef.createStateDashRef(pos, m, paramValues); } + else if (kind.equals("event")) { return DashRef.createEventDashRef(pos, m, paramValues); } + else { + //System.out.println(DashRef.createVarDashRef(pos, m, paramValues)); + Expr out = DashRef.createVarDashRef(pos, m, paramValues); + //System.out.println("out: " + out); + return out; } } - private static List findMatchesInRegion(StateTable st, EventTable et, VarTable vt, String kind, String sfqn, String suffix) { + private static List findMatchesInRegion(StateTable st, EventTable et, VarTable vt, PredTable pt, String kind, String sfqn, String suffix) { List region = new ArrayList(); if (kind.equals("state")) region = st.getRegion(sfqn); @@ -320,7 +334,10 @@ else if (kind.equals("event")) { for (String x: st.getRegion(sfqn)) { region.addAll(vt.getVarsOfState(x)); region.addAll(vt.getBuffersOfState(x)); + // does not have to have to be within state + // because does not take parameter values } + region.addAll(pt.getAllNames()); } return compareMatches(suffix,region); } @@ -338,14 +355,82 @@ private static List compareMatches(String suffix, List region) { return matches; } - private static List findMatches(StateTable st, EventTable et, VarTable vt, String kind, String suffix) { + private static List findMatches(StateTable st, EventTable et, VarTable vt, PredTable pt, String kind, String suffix) { List region = new ArrayList(); if (kind.equals("state")) region.addAll(st.getAllStateNames()); else if (kind.equals("event")) region.addAll(et.getAllEventNames()); else if (kind.equals("var")) { region.addAll(vt.getAllVarNames()); region.addAll(vt.getAllBufferNames()); + region.addAll(pt.getAllNames()); } return compareMatches(suffix,region); } -} \ No newline at end of file + + + private static String chooseMatch(String sfqn, List matches) { + // get highest rank match based on sfqn + // if two have same rank, then ambiguous + int longestCommonPrefix = 0; + String bestmatch = ""; + Boolean multipleBestMatches = false; + for (String s: matches) { + if (DashFQN.commonPrefixLength(sfqn,s) > longestCommonPrefix) { + longestCommonPrefix = DashFQN.commonPrefixLength(sfqn,s); + bestmatch = s; + multipleBestMatches = false; + } else if (DashFQN.commonPrefixLength(sfqn,s) == longestCommonPrefix) { + multipleBestMatches = true; + } + } + if (!multipleBestMatches && longestCommonPrefix > 0) { + return bestmatch; + } else { + return null; + } + } + +} + + /* + // there is one or more match + // sfqn is the context + // might be a suffix of the name, not just v + String m = ""; + if (matches.size() >= 1) { + if (matches.contains(DashFQN.mergeFQN(sfqn,v)) || matches.contains(sfqn)) { + // first choice: if a match is sfqn+/+v or sfqn itself + // that's the best match (if both are in matches then ambiguous) + if (matches.contains(DashFQN.fqn(sfqn,v))) { + if (matches.contains(sfqn)) { + DashErrors.ambiguousRef(pos, exp.toString()); + return null; + } else { + m = sfqn; + } + } else { + m = DashFQN.mergeFQN(sfqn,v); + } + } else { + List matchesWithinSfqn = matches.stream() + .filter(i -> i.startsWith(sfqn)) + .collect(Collectors.toList()); + if (matchesWithinSfqn.size() > 0) { + // next best is something internal to sfqn so match is sfqn / .... / v (must only one) + if (matchesWithinSfqn.size() == 1) m = matchesWithinSfqn.get(0); + else { + DashErrors.ambiguousRef(pos, exp.toString()); + return null; + } + } else { + // Final choice is something external to sfqn (must be only one) + if (matches.size() > 1) { + DashErrors.ambiguousRef(pos, exp.toString()); + return null; + } else { + m = matches.get(0); + } + } + } + } + */ \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index e1cc7c9d6..36ffff136 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -60,8 +60,12 @@ public class StateElement { private List immChildren; // empty if none private List origInvariants; private List origInits; - private List actions; - private List conditions; + // this aren't resolved here + // so no need to keep original separate from resolved + private List entered; + private List exited; + //private List actions; + //private List conditions; // after resolve private List invs; private List inits; @@ -77,8 +81,11 @@ public StateElement( List iChildren, List invL, List initL, - List actL, - List condL) { + List entered, + List exited + //List actL, + //List condL + ) { assert(k != null); assert(prm == null || !prm.isEmpty()); @@ -87,8 +94,8 @@ public StateElement( assert(iChildren != null); // could be empty assert(invL != null); assert(initL != null); - assert(actL != null); - assert(condL != null); + //assert(actL != null); + //assert(condL != null); this.kind = k; this.param = prm; this.params = prms; @@ -98,8 +105,10 @@ public StateElement( this.immChildren = iChildren; this.origInvariants = invL; this.origInits = initL; - this.actions = actL; - this.conditions = condL; + this.entered = entered; + this.exited = exited; + //this.actions = actL; + //this.conditions = condL; } public String toString() { @@ -160,8 +169,8 @@ public boolean add( List iChildren, List invL, List initL, - List actL, - List condL) { + List enteredL, + List exitedL) { // if its null, make it empty to not throw exceptions //if (iChildren == null) iChildren = new ArrayList(); //if (table.containsKey(fqn)) { @@ -175,7 +184,7 @@ public boolean add( //else if (table.containsKey(fqn)) return false; else if (DashStrings.hasPrime(fqn)) { DashErrors.nameShouldNotBePrimed(fqn); return false; } - else { table.put(fqn, new StateElement(k,prm, prms,prmsIdx, d,p,iChildren, invL, initL, actL, condL)); return true; } + else { table.put(fqn, new StateElement(k,prm, prms,prmsIdx, d,p,iChildren, invL, initL, enteredL, exitedL)); return true; } //System.out.println("adding to State table: "+fqn+space+prm + space + prms+space+d+space+p+iChildren); } public void addInit(Expr exp) { @@ -345,18 +354,19 @@ public List getAllParamsInOrder() { //} //return DashUtilFcns.setToList(allParams); } - public void resolve(String root, EventTable et, VarTable vt) { + public void resolve(String root, EventTable et, VarTable vt, PredTable pt) { // resolve inits and invariants for (String sfqn: table.keySet()) { inits.addAll( table.get(sfqn).origInits.stream() - .map(i -> ResolveExpr.resolveExpr(this, et, vt, "var", false, false, true, sfqn, i.getInit())) + .map(i -> ResolveExpr.resolveExpr(this, et, vt, pt, "var", false, false, true, sfqn, i.getExp())) .collect(Collectors.toList())); invs.addAll( table.get(sfqn).origInvariants.stream() - .map(i -> ResolveExpr.resolveExpr(this, et, vt, "var", false, false, true, sfqn, i.getInv())) + .map(i -> ResolveExpr.resolveExpr(this, et, vt, pt, "var", false, false, true, sfqn, i.getExp())) .collect(Collectors.toList())); - + // nothing to do for entered and exited + // because they are resolved in context } isResolved = true; } @@ -368,6 +378,22 @@ public List getInits() { public List getInvs() { return invs; } + public List getEnteredAction(String sfqn) { + if (table.containsKey(sfqn)) + return table.get(sfqn).entered; // could be null + else { DashErrors.stateDoesNotExist("getEntered", sfqn); return null; } + } + public List getExitedAction(String sfqn) { + if (table.containsKey(sfqn)) + return table.get(sfqn).exited; // could be null + else { DashErrors.stateDoesNotExist("getExited", sfqn); return null; } + } + public boolean hasEnteredAction(String sfqn) { + return (getEnteredAction(sfqn) == null); + } + public boolean hasExitedAction(String sfqn) { + return (getExitedAction(sfqn) == null); + } public List getLeafStatesExited(DashRef s) { List r = new ArrayList(); //System.out.println("exiting" + s.toString()); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 55b249549..28931ae5d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -214,7 +214,7 @@ public List getHigherPriTrans(String t) { * must be done after resolveAllState * this fcn does not modify anything in this object */ - public void resolve(StateTable st, EventTable et, VarTable vt) { + public void resolve(StateTable st, EventTable et, VarTable vt, PredTable pt) { //System.out.println(st); //System.out.println(toString()); @@ -237,7 +237,7 @@ else if (fList.isEmpty()) Common.paramVars(getParamsIdx(tfqn), getParams(tfqn)))); else table.get(tfqn) - .setSrc((DashRef) resolveExpr(st, et, vt, "state", false, false, true, sfqn, fList.get(0))); + .setSrc((DashRef) resolveExpr(st, et, vt, pt, "state", false, false, true, sfqn, fList.get(0))); // determining the dest state List gList = @@ -253,7 +253,7 @@ else if (gList.isEmpty()) Common.paramVars(getParamsIdx(tfqn),getParams(tfqn)))); else table.get(tfqn) - .setDest((DashRef) resolveExpr(st, et, vt, "state", false, true, true, sfqn, gList.get(0))); + .setDest((DashRef) resolveExpr(st, et, vt, pt, "state", false, true, true, sfqn, gList.get(0))); // determining the on (event) List onExpList = @@ -263,7 +263,7 @@ else if (gList.isEmpty()) if (onExpList.size() > 1) DashErrors.tooMany("on", tfqn); else if (!onExpList.isEmpty()) { table.get(tfqn) - .setOn((DashRef) resolveExpr(st, et, vt, "event", false, false, true, sfqn, onExpList.get(0))); + .setOn((DashRef) resolveExpr(st, et, vt, pt, "event", false, false, true, sfqn, onExpList.get(0))); } // determining the send @@ -273,12 +273,12 @@ else if (!onExpList.isEmpty()) { .collect(Collectors.toList()); if (sendExpList.size() > 1) DashErrors.tooMany("send", tfqn); else if (!sendExpList.isEmpty()) { - DashRef x = (DashRef) resolveExpr(st, et, vt, "event", false, true, true, sfqn, sendExpList.get(0)); + DashRef x = (DashRef) resolveExpr(st, et, vt, pt, "event", false, true, true, sfqn, sendExpList.get(0)); if (et.isEnvironmentalEvent(x.getName())) DashErrors.cantSendAnEnvEvent(sendExpList.get(0).pos(),sendExpList.get(0).toString()); else table.get(tfqn) - . setSend((DashRef) resolveExpr(st, et, vt, "event", false, true, true, sfqn, sendExpList.get(0))); + . setSend((DashRef) resolveExpr(st, et, vt, pt, "event", false, true, true, sfqn, sendExpList.get(0))); } // determining the when (expr) @@ -289,7 +289,7 @@ else if (!sendExpList.isEmpty()) { if (whenExpList.size() > 1) DashErrors.tooMany("when", tfqn); else if (!whenExpList.isEmpty()) { table.get(tfqn) - .setWhen(resolveExpr(st, et, vt, "var", false, false, true, sfqn, whenExpList.get(0))); + .setWhen(resolveExpr(st, et, vt, pt, "var", false, false, true, sfqn, whenExpList.get(0))); } // determining the do @@ -299,8 +299,14 @@ else if (!whenExpList.isEmpty()) { .collect(Collectors.toList()); if (doExpList.size() > 1) DashErrors.tooMany("on", tfqn); else if (!doExpList.isEmpty()) { + // already resolved src/dest + Expr action = doExpList.get(0); + if (st.hasEnteredAction(getDest(tfqn).getName())) + action = ExprHelper.createAnd(action,ExprHelper.createAndList(st.getEnteredAction(getDest(tfqn).getName()))); + if (st.hasExitedAction(getSrc(tfqn).getName())) + action = ExprHelper.createAnd(action,ExprHelper.createAndList(st.getExitedAction(getSrc(tfqn).getName()))); table.get(tfqn) - .setDo(resolveExpr(st, et, vt, "var", true, true, true, sfqn, doExpList.get(0))); + .setDo(resolveExpr(st, et, vt, pt, "var", true, true, true, sfqn, action)); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index 2440c0cae..86629a5da 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -22,6 +22,7 @@ import ca.uwaterloo.watform.parser.StateTable; import ca.uwaterloo.watform.parser.EventTable; +import ca.uwaterloo.watform.parser.PredTable; public class VarTable { @@ -93,11 +94,11 @@ public Boolean addVar(String vfqn, IntEnvKind k, List prms, List Date: Sun, 11 Jun 2023 19:20:53 -0400 Subject: [PATCH 054/129] added check for not pre of higher priority transitions to pre --- .../watform/dashtoalloy/AddTransPre.java | 20 +++- .../uwaterloo/watform/parser/TransTable.java | 6 +- ...shStateTests.java => DashModuleTests.java} | 106 +++++++++++++++++- .../src/test/resources/pass/pri1.dsh | 3 + .../src/test/resources/pass/pri2.dsh | 6 + .../src/test/resources/pass/pri3.dsh | 9 ++ .../src/test/resources/pass/pri4.dsh | 13 +++ .../src/test/resources/pass/pri5.dsh | 13 +++ .../src/test/resources/pass/pri6.dsh | 9 ++ 9 files changed, 176 insertions(+), 9 deletions(-) rename org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/{DashStateTests.java => DashModuleTests.java} (92%) create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/pri1.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/pri2.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/pri3.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/pri4.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/pri5.dsh create mode 100644 org.alloytools.alloy.dash/src/test/resources/pass/pri6.dsh diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 101342b02..36e429e9b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -31,9 +31,12 @@ public class AddTransPre { // -------------------------------------------------------------------------------------- /* pred pre_t1[s:Snapshot,pparam0:Param0, ...] { + some (src_state_t1 & .s.conf) orthogonal to any scopes uses + guard_cond_t1 [s] + s.stable = True => { // beginning of a big step // transition can be triggered only by environmental events @@ -43,6 +46,7 @@ .trig_events_t1 in (s.events & ExternalEvent ) // transition can be triggered by any type of event .trig_events_t1 in s.events } + pre of a higher priority transition is not enabled } Assumption: prs for src state and trig events are a subset of prs for trans */ @@ -98,14 +102,18 @@ public static void addTransPre(DashModule d, String tfqn) { int sz = ev.getParamValues().size(); body.add(createIn(translateDashRefToArrow(ev),curEvents(sz))); } - - /* - // TODO - // guard_cond_t1 [s] - o.add(d.getTransGuard(t).convertToAlloy(d.symbolTable, curVar(), nextVar())); - */ // not a higher priority transition enabled + List priTrans = d.getHigherPriTrans(tfqn); + List args = new ArrayList(); + for (String t:priTrans) { + // src must directly above this trans in the hierarchy + // so its parameters must be a subset of the current parameters + // and we don't need to quantify over them + args = curParamVars(d.getTransParamsIdx(t), d.getTransParams(t)); + body.add(createNot(createPredCall(translateFQN(t)+DashStrings.preName, args))); + } + d.alloyString += d.addPredSimple(tout+DashStrings.preName, curParamsDecls(prsIdx,params), body); d.alloyString += "\n"; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java index 28931ae5d..b2e7c8a36 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/TransTable.java @@ -198,11 +198,13 @@ public List getTransWithTheseSrcs(List slist) { } public List getHigherPriTrans(String t) { // list returned could be empty + String src = table.get(t).src.getName(); List tlist = new ArrayList(); // have to look for transitions from sources earlier on the path of this transitions src - List allPrefixes = DashFQN.allPrefixes(table.get(t).src.getName()); + // allPrefixes includes t so it contains at least one item + List allPrefixes = DashFQN.allPrefixes(src); // remove the src state itself - allPrefixes.remove(allPrefixes.size()-1); + allPrefixes.remove(src); if (table.containsKey(t)) tlist.addAll(getTransWithTheseSrcs(allPrefixes)); else DashErrors.transDoesNotExist("getParams", t); return tlist; diff --git a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashModuleTests.java similarity index 92% rename from org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java rename to org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashModuleTests.java index f6f9c297a..70f8eb35c 100644 --- a/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashStateTests.java +++ b/org.alloytools.alloy.dash/src/test/java/org/alloytools/alloy/dash/DashModuleTests.java @@ -21,7 +21,7 @@ import ca.uwaterloo.watform.parser.DashUtil; import ca.uwaterloo.watform.mainfunctions.MainFunctions; -public class DashStateTests { +public class DashModuleTests { private static String resourcePath = "src/test/resources/pass"; @@ -982,4 +982,108 @@ public void overall13() { d.getAllParamsInOrder() .equals(Arrays.asList("AID","BID","BID","AID"))); } + + // priority + @Test + public void pri1() { + DashModule d = test("pri1"); + String tfqn = "Root/t1"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{}))); + + } + @Test + public void pri2() { + DashModule d = test("pri2"); + String tfqn = "Root/t1"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{}))); + tfqn = "Root/A/t2"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{ + "Root/t1" + }))); + } + + @Test + public void pri3() { + DashModule d = test("pri3"); + String tfqn = "Root/t1"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{}))); + tfqn = "Root/t2"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{}))); + tfqn = "Root/t3"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{ + "Root/t1", + "Root/t2" + }))); + } + + @Test + public void pri4() { + DashModule d = test("pri4"); + String tfqn = "Root/t1"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{}))); + tfqn = "Root/t2"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{ + "Root/t1" + }))); + + } + + @Test + public void pri5() { + DashModule d = test("pri5"); + String tfqn = "Root/t1"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{}))); + tfqn = "Root/t2"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{ + "Root/t1" + }))); + + } + + @Test + public void pri6() { + DashModule d = test("pri6"); + String tfqn = "Root/A/B/t1"; + + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{ + "Root/A/t2", + "Root/t3" + }))); + + tfqn = "Root/A/t2"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{ + "Root/t3" + }))); + + tfqn = "Root/t3"; + assertTrue( + d.getHigherPriTrans(tfqn) + .equals(ll(new String[]{ + }))); + } + } diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/pri1.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/pri1.dsh new file mode 100644 index 000000000..4d78f7aaa --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/pri1.dsh @@ -0,0 +1,3 @@ +state Root { + trans t1 {} +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/pri2.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/pri2.dsh new file mode 100644 index 000000000..46d700e5f --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/pri2.dsh @@ -0,0 +1,6 @@ +state Root { + trans t1 {} + state A { + trans t2 {} + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/pri3.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/pri3.dsh new file mode 100644 index 000000000..9c981f521 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/pri3.dsh @@ -0,0 +1,9 @@ +state Root { + trans t1 {} + trans t2 {} + state A {} + trans t3 { + from A + goto A + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/pri4.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/pri4.dsh new file mode 100644 index 000000000..9f1fec672 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/pri4.dsh @@ -0,0 +1,13 @@ +state Root { + state A { + state B {} + } + trans t1 { + from A + goto B + } + trans t2 { + from B + goto B + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/pri5.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/pri5.dsh new file mode 100644 index 000000000..4fc90f96f --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/pri5.dsh @@ -0,0 +1,13 @@ +state Root { + conc A [AID] { + conc B [BID] {} + } + trans t1 { + from A [a1] + goto B [a1,b1] + } + trans t2 { + from B [a2,b3] + goto B [a5, b6] + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/test/resources/pass/pri6.dsh b/org.alloytools.alloy.dash/src/test/resources/pass/pri6.dsh new file mode 100644 index 000000000..42aebd3a0 --- /dev/null +++ b/org.alloytools.alloy.dash/src/test/resources/pass/pri6.dsh @@ -0,0 +1,9 @@ +state Root { + conc A [AID] { + conc B [BID] { + trans t1 {} + } + trans t2 {} + } + trans t3 {} +} \ No newline at end of file From 3445e0e94599004519f8c7d5033469b476855a12 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 13 Jun 2023 16:00:00 -0400 Subject: [PATCH 055/129] added constraint that dynamic vars that don't change keep the same value --- .../watform/alloyasthelper/ExprHelper.java | 9 ++ .../ca/uwaterloo/watform/core/DashErrors.java | 6 ++ .../uwaterloo/watform/core/DashStrings.java | 3 +- .../watform/dashtoalloy/AddSmallStep.java | 36 +++++-- .../watform/dashtoalloy/AddTransPost.java | 94 +++++++++++++++++++ .../uwaterloo/watform/parser/DashModule.java | 12 ++- .../ca/uwaterloo/watform/parser/VarTable.java | 7 +- 7 files changed, 153 insertions(+), 14 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index a64555f22..877472e9a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -221,6 +221,15 @@ public static Expr createJoinList(List elist) { } return ret; } + public static Expr createJoinList(List elist, Expr e) { + assert(elist!=null); + Collections.reverse(elist); + Expr ret = e; + for (Expr el: elist) { + ret = createJoin(el,ret); + } + return ret; + } public static ExprBinary createRangeRes(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.RANGE.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java index 80c7a260d..ef310d646 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashErrors.java @@ -298,4 +298,10 @@ public static void doesNotExist(String fcnName, String m) { public static void noInitialEntered(){ throw new ErrorFatal("there are no default initial states"); } + public static void sistersDontChangeDoesNotHaveParams(String s) { + throw new ErrorFatal("sistersDontChangeDoesNotHaveParams: "+s); + } + public static void hasSpecificParamValues() { + throw new ErrorFatal("hasSpecificParamValues"); + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 192e1bd3e..614942ef8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -107,7 +107,7 @@ public class DashStrings { public static String preName = "_pre"; public static String postName = "_post"; //public static String semanticsName = "_semantics"; - public static String testIfNextStableName = "_testIfNextStable"; + public static String testIfNextStableName = "_nextIsStable"; public static String enabledAfterStepName = "_enabledAfterStep"; // variable/parameter names @@ -117,6 +117,7 @@ public class DashStrings { public static String pName = "p"; public static String genEventName = "dsh_genEvs"; public static String scopeName = "dsh_scp"; + public static String randomParamExt = "_aa"; // strings used internally public static String processRef = "$$PROCESSREF$$"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java index 67bb1bbb9..efa3bcfbe 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java @@ -30,17 +30,23 @@ public class AddSmallStep { /* pred small_step [s:Snapshot, s': Snapshot] { - some pparam0 : Param0 , pparam1 : Param1 ... | + (some pparam0 : Param0 , pparam1 : Param1 ... | { // for all t’s at level i with params Param5, Param6, ... (or t[s, s_next, pparam5, pparam6 ]) - // loop? big-step issue? - } + }) + or + (!(some pparam0 : Param0 , pparam1 : Param1 ... | + { // for all t’s at level i with params Param5, Param6, ... + (or t_pre[s, s_next, pparam5, pparam6 ]) ) + and s = s') + */ public static void addSmallStep(DashModule d) { ArrayList e = new ArrayList(); List prs = d.getAllParamsInOrder(); + // trans is taken for (String tfqn: d.getAllTransNames()) { String tout = translateFQN(tfqn); // p3.p2.p1.t for parameters of this transition @@ -48,12 +54,26 @@ public static void addSmallStep(DashModule d) { // p3.p2.p1.s'.s.t for parameters of this transition else e.add(createPredCall(tout,curNextParamVars(d.getTransParamsIdx(tfqn),d.getTransParams(tfqn)))); } - List body = new ArrayList(); - if (d.getAllParamsInOrder().isEmpty()) body.add(createOrFromList(e)); - else body.add(createSome(paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1),prs),createOrFromList(e))); + Expr transIsTaken; + if (d.getAllParamsInOrder().isEmpty()) transIsTaken = createOrFromList(e); + else transIsTaken = createSome(paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1),prs),createOrFromList(e)); - //TODO add loop if all notenabled + // no trans is enabled + e = new ArrayList(); + for (String tfqn: d.getAllTransNames()) { + String tout = translateFQN(tfqn); + // p3.p2.p1.t for parameters of this transition + if (DashOptions.isElectrum) e.add(createPredCall(tout,paramVars(d.getTransParamsIdx(tfqn), d.getTransParams(tfqn)))); + // p3.p2.p1.s'.s.t for parameters of this transition + else e.add(createPredCall(tout+DashStrings.preName,curParamVars(d.getTransParamsIdx(tfqn),d.getTransParams(tfqn)))); + } + Expr transIsNotEnabled; + if (d.getAllParamsInOrder().isEmpty()) transIsNotEnabled = createOrFromList(e); + else transIsNotEnabled = createSome(paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1),prs),createOrFromList(e)); + transIsNotEnabled = createAnd(createNot(transIsNotEnabled), createEquals(curVar(), nextVar())); - d.alloyString += d.addPredSimple(DashStrings.smallStepName,curNextDecls(),body); + e = new ArrayList(); + e.add(createOr(transIsTaken, transIsNotEnabled)); + d.alloyString += d.addPredSimple(DashStrings.smallStepName,curNextDecls(),e); } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index da8bbca19..17e20f7d5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.ArrayList; import java.util.Arrays; +import java.util.Set; +import java.util.HashSet; import edu.mit.csail.sdg.ast.Decl; import edu.mit.csail.sdg.ast.ExprVar; @@ -110,6 +112,83 @@ public static void addTransPost(DashModule d, String tfqn) { if (d.getTransDo(tfqn) != null) body.add(translateExpr(d.getTransDo(tfqn),d)); + // vars not mentioned in action do not change + // includes entered/exited + Set intVarsThatDontChange = DashUtilFcns.listToSet(d.getAllInternalVarNames()); + // TODO buffers? + + // remove variables mentioned in invariants + // whether they are primed or not + for (Expr i:d.getInvs()) { + List primedDashRefs = d.primedDashRefs(i); + for (DashRef r:primedDashRefs) { + intVarsThatDontChange.remove(r.getName()); + } + } + + // separate primed variables in transitions into those + // that we can't put any constraints on (remove these from intVarsThatDontChange) + // and those that we constrain the sister value os (sistersDontChange) + Set sistersDontChange = new HashSet(); + if (d.getTransDo(tfqn) != null) { + for (DashRef r: d.primedDashRefs(d.getTransDo(tfqn))) { + //System.out.println(r); + if (r.getParamValues().isEmpty()) intVarsThatDontChange.remove(r.getName()); + else if (hasSpecificParamValues(d, r)) { + //System.out.println("has specific param values"); + intVarsThatDontChange.remove(r.getName()); + // might not be in sistersDontChange + sistersDontChange.remove(r.getName()); + } else { + //System.out.println("has generic param values"); + // has generic param values + sistersDontChange.add(r.getName()); + intVarsThatDontChange.remove(r.getName()); + } + } + } + //System.out.println(tfqn); + //System.out.println(sistersDontChange); + List decls; + List args; + + // constraints on sister elements + for (String x: sistersDontChange) { + decls = new ArrayList(); + args = new ArrayList(); + List paramsIdx = d.getVarBufferParamsIdx(x); + List params = d.getVarBufferParams(x); + for (int i=0; i < params.size();i++) { + String p = params.get(i); + decls.add(new DeclExt(p + randomParamExt, + createDiff(createVar(p), paramVar(paramsIdx.get(i), p)))); + args.add(createVar(p + randomParamExt)); + } + if (decls.isEmpty()) DashErrors.sistersDontChangeDoesNotHaveParams(x); + else body.add(createAll(decls, + createEquals( + createJoinList(args, curJoinExpr(createVar(translateFQN(x)))), + createJoinList(args, nextJoinExpr(createVar(translateFQN(x))))))); + } + + + // constraint on untouched vars + for (String x:intVarsThatDontChange) { + decls = new ArrayList(); + args = new ArrayList(); + for (String p: d.getVarBufferParams(x)) { + decls.add(new DeclExt(p + randomParamExt, p)); + args.add(createVar(p + randomParamExt)); + } + if (decls.isEmpty()) body.add(createEquals( + curJoinExpr(createVar(translateFQN(x))), + nextJoinExpr(createVar(translateFQN(x))))); + else body.add(createAll(decls, createEquals( + createJoinList(args, curJoinExpr(createVar(translateFQN(x)))), + createJoinList(args, nextJoinExpr(createVar(translateFQN(x))))))); + } + + DashRef ev = d.getTransSend(tfqn); Expr rhs, rhs1, q; @@ -286,4 +365,19 @@ private static Expr createTestIfNextStableCall(DashModule d, String tfqn) { return createPredCall(testIfNextStableName,args); } + private static boolean hasSpecificParamValues(DashModule d, DashRef r) { + // only for variables + //TODO buffers?? + List genericPValues = paramVars(d.getVarBufferParamsIdx(r.getName()), d.getVarBufferParams(r.getName())); + List actualPValues = r.getParamValues(); + Boolean ret = false; + if (genericPValues.size() == actualPValues.size()) { + for (int i=0; i < genericPValues.size(); i++) { + //System.out.println("generic: " + genericPValues.get(i)); + //System.out.println("actual: " + actualPValues.get(i)); + if (!sEquals(genericPValues.get(i), actualPValues.get(i))) ret = ret || true; + } + } else DashErrors.hasSpecificParamValues(); + return ret; + } } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 1d6920c67..f1ac32507 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -347,9 +347,6 @@ public List getAllTransNames() { return transTable.getAllTransNames(); } - public List getParams(String tfqn) { - return transTable.getParams(tfqn); - } public DashRef getTransSrc(String tfqn) { return transTable.getSrc(tfqn); } @@ -381,6 +378,11 @@ public boolean isInternalEvent(String efqn) { public List getAllVarNames() { return varTable.getAllVarNames(); } + public List getAllInternalVarNames() { + return varTable.getAllVarNames().stream() + .filter(i -> varTable.isInternal(i)) + .collect(Collectors.toList()); + } public List getVarBufferParams(String vfqn) { return varTable.getParams(vfqn); } @@ -604,6 +606,10 @@ public void resolveAllDash(A4Reporter rep) { status = Status.RESOLVED_DASH; } + public List primedDashRefs(Expr exp) { + return varTable.primedDashRefs(exp); + } + public void translate() { assert(status == Status.RESOLVED_DASH); //System.out.println("Translating to Alloy"); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index 86629a5da..ac828af9f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -222,10 +222,13 @@ public Boolean addBuffer(String vfqn, IntEnvKind k, List prms, List collectDashRefs(Expr exp) { + assert(exp != null); List x = new ArrayList(); if (DashRef.isDashRef(exp)) { x.add((DashRef) exp); return x; + } else if (isExprVar(exp)) { + return x; } else if (isExprBinary(exp)) { x.addAll(collectDashRefs(getLeft(exp))); x.addAll(collectDashRefs(getRight(exp))); @@ -246,7 +249,7 @@ public List collectDashRefs(Expr exp) { x.addAll(collectDashRefs(getRight(exp))); return x; } else if (exp instanceof ExprList){ - for (Expr e: ((ExprCall) exp).args) x.addAll(collectDashRefs(e)); + for (Expr e: ((ExprList) exp).args) x.addAll(collectDashRefs(e)); return x; } else if (exp instanceof ExprUnary){ return collectDashRefs(((ExprUnary) exp).sub); @@ -264,7 +267,7 @@ public List collectDashRefs(Expr exp) { } else if (exp instanceof ExprConstant){ return new ArrayList(); } else { - DashErrors.UnsupportedExpr("collectDashRefs", ""); + DashErrors.UnsupportedExpr("collectDashRefs", exp.toString()); return null; } } From 9f05cc880df0f4eda22278aab9d0edaecba2f20b Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 13 Jun 2023 16:50:43 -0400 Subject: [PATCH 056/129] added low priority stutter that keeps internals the same --- .../uwaterloo/watform/core/DashStrings.java | 1 + .../watform/dashtoalloy/AddSmallStep.java | 2 +- .../watform/dashtoalloy/AddStutter.java | 61 +++++++++++++++++++ .../watform/dashtoalloy/DashToAlloy.java | 3 +- 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 614942ef8..2520d33bb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -77,6 +77,7 @@ public class DashStrings { public static String smallStepName = "dsh_small_step"; public static String stableName = "dsh_stable"; + public static String stutterName = "dsh_stutter"; //public static String equalsName = "equals"; public static String isEnabled = "dsh_isEnabled"; public static String tracesFactName = "dsh_traces_fact"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java index efa3bcfbe..abf51cda1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSmallStep.java @@ -70,7 +70,7 @@ public static void addSmallStep(DashModule d) { Expr transIsNotEnabled; if (d.getAllParamsInOrder().isEmpty()) transIsNotEnabled = createOrFromList(e); else transIsNotEnabled = createSome(paramDecls(DashUtilFcns.listOfInt(0,prs.size()-1),prs),createOrFromList(e)); - transIsNotEnabled = createAnd(createNot(transIsNotEnabled), createEquals(curVar(), nextVar())); + transIsNotEnabled = createAnd(createNot(transIsNotEnabled), createPredCall(DashStrings.stutterName, curNextVars())); e = new ArrayList(); e.add(createOr(transIsTaken, transIsNotEnabled)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java new file mode 100644 index 000000000..f199f5ef0 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java @@ -0,0 +1,61 @@ +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.IntStream; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddStutter { + + // low priority no environmental stutter predicate + + public static void addStutter(DashModule d) { + + + List body = new ArrayList(); + + // all the dsh defined parts of the snapshot stay the same + if (d.hasConcurrency()) body.add(noChange(DashStrings.stableName)); + for (int i = 0; i <= d.getMaxDepthParams(); i++) { + body.add(noChange(DashStrings.confName+Integer.toString(i))); + body.add(noChange(DashStrings.scopesUsedName+Integer.toString(i))); + if (d.hasEvents() && d.hasEventsAti(i)) + body.add(noChange(DashStrings.eventsName+Integer.toString(i))); + } + + // internal vars + // stays the same for all parameter values + // so can just say that the whole relation is the same and no parameter values needed !! + for (String vfqn: d.getAllInternalVarNames()) body.add(noChange(vfqn)); + // buffers are all internal + for (String bfqn: d.getAllBufferNames()) body.add(noChange(bfqn)); + d.alloyString += d.addPredSimple(DashStrings.stutterName, curNextDecls(), body); + + } + + private static Expr noChange(String n) { + return createEquals(nextJoinExpr(createVar(translateFQN(n))), curJoinExpr(createVar(translateFQN(n)))); + } +} + diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 7c1fad848..eb0c5db94 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -12,7 +12,7 @@ public class DashToAlloy { public static void translate(DashModule d) { assert(d.hasRoot()); // there is a Dash component in this module - AddSpaceSignatures.addSpaceSignatures(d); // state, transition, parameter, buffer space + AddSpaceSignatures.addSpaceSignatures(d); // state, parameter, buffer space AddSnapshotSignature.addSnapshotSignature(d); AddInit.addInit(d); AddInv.addInv(d); @@ -25,6 +25,7 @@ public static void translate(DashModule d) { } if (d.hasConcurrency()) AddTestIfNextStable.addTestIfNextStable(d); + AddStutter.addStutter(d); AddSmallStep.addSmallStep(d); if (DashOptions.isTraces) From 8741495dc393c619d5fa3871b68c244802052d69 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 13 Jun 2023 17:12:25 -0400 Subject: [PATCH 057/129] internal events do not persist --- .../uwaterloo/watform/dashtoalloy/AddStutter.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java index f199f5ef0..f735f18d1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java @@ -1,3 +1,10 @@ +/* + * + * In a weird case where a transition is triggered on an internal event + * but its guard depends on an external var value + * it won't be triggered after a stutter + */ + package ca.uwaterloo.watform.dashtoalloy; import java.util.Collections; @@ -40,8 +47,12 @@ public static void addStutter(DashModule d) { for (int i = 0; i <= d.getMaxDepthParams(); i++) { body.add(noChange(DashStrings.confName+Integer.toString(i))); body.add(noChange(DashStrings.scopesUsedName+Integer.toString(i))); - if (d.hasEvents() && d.hasEventsAti(i)) - body.add(noChange(DashStrings.eventsName+Integer.toString(i))); + if (d.hasEvents() && d.hasInternalEventsAti(i)) + // internal events go away + // external events can be added + body.add(createEquals( + createRangeRes(nextEvents(i),allInternalEventsVar()), + createNoneArrow(i))); } // internal vars From fdc2ba27dd58cde5549b563e2a15af843754c8f8 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 13 Jun 2023 19:39:39 -0400 Subject: [PATCH 058/129] buffers must be internal --- .../parser/Dash-cup-grammar.txt | 30 ------------------- org.alloytools.alloy.dash/parser/Dash.cup | 30 ------------------- 2 files changed, 60 deletions(-) diff --git a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt index 9e571091a..e7f6a6c9f 100644 --- a/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt +++ b/org.alloytools.alloy.dash/parser/Dash-cup-grammar.txt @@ -223,36 +223,6 @@ StateItem ::= Names:n COLON:o BUF LBRACKET SIGINT RBRACKET Integer endIndex = DashSituation.bufferIndex - 1; RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT, startIndex, endIndex); :}; -StateItem ::= ENV:o Names:n COLON BUF LBRACKET Name:m RBRACKET - {: - ArrayList ll = new ArrayList(); - Integer startIndex = DashSituation.bufferIndex; - for (ExprVar x: n) { - ll.add(x.label); - // it will do this the same way both passes through parsing - DashSituation.bufferElements.add(m.label); - DashSituation.bufferNames.add(x.label); - DashSituation.bufferIndex++; - } - // endIndex is inclusive - Integer endIndex = DashSituation.bufferIndex - 1; - RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV, startIndex, endIndex); - :}; -StateItem ::= ENV:o Names:n COLON BUF LBRACKET SIGINT RBRACKET - {: - ArrayList ll = new ArrayList(); - Integer startIndex = DashSituation.bufferIndex; - for (ExprVar x: n) { - ll.add(x.label); - // it will do this the same way both passes through parsing - DashSituation.bufferElements.add(DashStrings.intName); - DashSituation.bufferNames.add(x.label); - DashSituation.bufferIndex++; - } - // endIndex is inclusive - Integer endIndex = DashSituation.bufferIndex - 1; - RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV, startIndex, endIndex); - :}; // init // Super is a list of expressions joined by conjunction diff --git a/org.alloytools.alloy.dash/parser/Dash.cup b/org.alloytools.alloy.dash/parser/Dash.cup index d7e4aeb9c..95ed2fa21 100644 --- a/org.alloytools.alloy.dash/parser/Dash.cup +++ b/org.alloytools.alloy.dash/parser/Dash.cup @@ -1481,36 +1481,6 @@ StateItem ::= Names:n COLON:o BUF LBRACKET SIGINT RBRACKET Integer endIndex = DashSituation.bufferIndex - 1; RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.INT, startIndex, endIndex); :}; -StateItem ::= ENV:o Names:n COLON BUF LBRACKET Name:m RBRACKET - {: - ArrayList ll = new ArrayList(); - Integer startIndex = DashSituation.bufferIndex; - for (ExprVar x: n) { - ll.add(x.label); - // it will do this the same way both passes through parsing - DashSituation.bufferElements.add(m.label); - DashSituation.bufferNames.add(x.label); - DashSituation.bufferIndex++; - } - // endIndex is inclusive - Integer endIndex = DashSituation.bufferIndex - 1; - RESULT = new DashBufferDecls(o, ll, m.label, DashStrings.IntEnvKind.ENV, startIndex, endIndex); - :}; -StateItem ::= ENV:o Names:n COLON BUF LBRACKET SIGINT RBRACKET - {: - ArrayList ll = new ArrayList(); - Integer startIndex = DashSituation.bufferIndex; - for (ExprVar x: n) { - ll.add(x.label); - // it will do this the same way both passes through parsing - DashSituation.bufferElements.add(DashStrings.intName); - DashSituation.bufferNames.add(x.label); - DashSituation.bufferIndex++; - } - // endIndex is inclusive - Integer endIndex = DashSituation.bufferIndex - 1; - RESULT = new DashBufferDecls(o, ll, DashStrings.intName, DashStrings.IntEnvKind.ENV, startIndex, endIndex); - :}; // init // Super is a list of expressions joined by conjunction From 8087b693de1ebf1235abe50ad68c0c14843283fb Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 14 Jun 2023 09:56:43 -0400 Subject: [PATCH 059/129] ensuring buffers stay the same unless explicitly modified in a transition --- .../watform/dashtoalloy/AddTransPost.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 17e20f7d5..b85fa1cb0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -114,15 +114,19 @@ public static void addTransPost(DashModule d, String tfqn) { // vars not mentioned in action do not change // includes entered/exited - Set intVarsThatDontChange = DashUtilFcns.listToSet(d.getAllInternalVarNames()); - // TODO buffers? + Set intVarsBuffersThatDontChange = DashUtilFcns.listToSet(d.getAllInternalVarNames()); + intVarsBuffersThatDontChange.addAll(d.getAllBufferNames()); + // we treat buffers the same as variables because their index is the closest arg and + // either the entire buffer within a sister component stays the same or it doesn't -- there is no need + // to reference the buffer index argument. + //System.out.println(intVarsBuffersThatDontChange); // remove variables mentioned in invariants // whether they are primed or not for (Expr i:d.getInvs()) { List primedDashRefs = d.primedDashRefs(i); for (DashRef r:primedDashRefs) { - intVarsThatDontChange.remove(r.getName()); + intVarsBuffersThatDontChange.remove(r.getName()); } } @@ -133,22 +137,23 @@ public static void addTransPost(DashModule d, String tfqn) { if (d.getTransDo(tfqn) != null) { for (DashRef r: d.primedDashRefs(d.getTransDo(tfqn))) { //System.out.println(r); - if (r.getParamValues().isEmpty()) intVarsThatDontChange.remove(r.getName()); + if (r.getParamValues().isEmpty()) intVarsBuffersThatDontChange.remove(r.getName()); else if (hasSpecificParamValues(d, r)) { //System.out.println("has specific param values"); - intVarsThatDontChange.remove(r.getName()); + intVarsBuffersThatDontChange.remove(r.getName()); // might not be in sistersDontChange sistersDontChange.remove(r.getName()); } else { //System.out.println("has generic param values"); // has generic param values sistersDontChange.add(r.getName()); - intVarsThatDontChange.remove(r.getName()); + intVarsBuffersThatDontChange.remove(r.getName()); } } } //System.out.println(tfqn); //System.out.println(sistersDontChange); + //System.out.println("----"); List decls; List args; @@ -173,7 +178,7 @@ else if (hasSpecificParamValues(d, r)) { // constraint on untouched vars - for (String x:intVarsThatDontChange) { + for (String x:intVarsBuffersThatDontChange) { decls = new ArrayList(); args = new ArrayList(); for (String p: d.getVarBufferParams(x)) { From 6574e3af00fa7eef6785ed092b01062bf23ff4cc Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 15 Jun 2023 21:35:30 -0400 Subject: [PATCH 060/129] translation to Electrum added --- .../watform/alloyasthelper/DeclExt.java | 8 +++ .../watform/alloyasthelper/ExprHelper.java | 13 +++- .../watform/alloyasthelper/ExprToString.java | 3 + .../uwaterloo/watform/core/DashStrings.java | 1 + .../dashtoalloy/AddSnapshotSignature.java | 34 +++++++--- .../dashtoalloy/AddSpaceSignatures.java | 19 ++++-- .../uwaterloo/watform/dashtoalloy/Common.java | 56 ++++++++++++---- .../watform/parser/CompModuleHelper.java | 66 ++++++++++++++++--- .../uwaterloo/watform/parser/DashModule.java | 3 + .../ca/uwaterloo/watform/parser/VarTable.java | 4 +- 10 files changed, 173 insertions(+), 34 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java index 6a23e8fda..17bbf26d9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java @@ -11,6 +11,7 @@ import edu.mit.csail.sdg.ast.ExprVar; import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashStrings; import ca.uwaterloo.watform.alloyasthelper.ExprHelper; import ca.uwaterloo.watform.alloyasthelper.ExprToString; @@ -37,11 +38,17 @@ public DeclExt(String v, Expr e, boolean isVar) { isVar ? Pos.UNKNOWN:null, new ArrayList<>(Arrays.asList(ExprHelper.createVar(v))), e); + } public String toString() { // Decl does not have a toString() String x = new String(); StringJoiner sj = new StringJoiner(", "); + // var keyword + System.out.println("Decl" + names + (this.isVar==null)); + if (isVar != null) { + x += DashStrings.varName + " "; + } names.forEach(n -> sj.add(n.toString())); x += sj.toString(); x += " : "; @@ -68,6 +75,7 @@ public static DeclExt newSetDeclExt(String v, String typ) { // makes it seem like there is a pos for "var" // making it a "var" decl public static DeclExt newVarDeclExt(String v, Expr typ) { + return new DeclExt(v , typ, true); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 877472e9a..8d0708fbe 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -42,6 +42,15 @@ public static boolean isExprBinary(Expr e) { public static boolean isExprUnary(Expr e) { return (e instanceof ExprUnary); } + public static boolean isExprSet(Expr e) { + return ((e instanceof ExprUnary) && ((ExprUnary) e).op.equals(ExprUnary.Op.SETOF)); + } + public static boolean isExprOne(Expr e) { + return ((e instanceof ExprUnary) && ((ExprUnary) e).op.equals(ExprUnary.Op.ONE)); + } + public static boolean isExprLone(Expr e) { + return ((e instanceof ExprUnary) && ((ExprUnary) e).op.equals(ExprUnary.Op.LONE)); + } public static boolean isExprCard(Expr e) { return ((e instanceof ExprUnary) && ((ExprUnary) e).op.equals(ExprUnary.Op.CARDINALITY)); } @@ -183,7 +192,9 @@ public static Expr createBinaryExpr(Expr left, ExprBinary.Op op, Expr right) { public static Expr createUnaryExpr(ExprUnary.Op op, Expr sub) { return (ExprUnary) op.make(Pos.UNKNOWN, sub); } - + public static Expr createPrime(Expr sub) { + return ExprUnary.Op.PRIME.make(Pos.UNKNOWN, sub); + } public static Expr createExprList(ExprList.Op op, List args) { return (Expr) ExprList.make(Pos.UNKNOWN, Pos.UNKNOWN, op, args); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index 508b79e11..b018e0bd8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -511,6 +511,9 @@ private void DeclToOut(Decl decl) { // out.print(","); //} //first = false; + if (decl.isVar != null) { + out.print(DashStrings.varName + " "); + } out.print(DashUtilFcns.strCommaList(decl.names)); out.print(": "); ExprToOut(decl.expr); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 2520d33bb..90ecc35bf 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -13,6 +13,7 @@ public class DashStrings { public static String inName = "in"; public static String abstractName = "abstract"; public static String oneName = "one"; + public static String loneName = "lone"; public static String varName = "var"; public static String openName = "open"; public static String asName = "as"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 8503da47a..160af817a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -8,6 +8,7 @@ import edu.mit.csail.sdg.ast.Decl; import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.ExprUnary; import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.DashOptions; @@ -58,18 +59,18 @@ public static void addSnapshotSignature(DashModule d){ decls.add( DeclExt.newVarDeclExt( confName+Integer.toString(i), - createArrowExprList(DashUtilFcns.newListWith(cop, createVar(stateLabelName))))); + createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(stateLabelName)))))); // scopesUsed 1, etc. decls.add( DeclExt.newVarDeclExt( scopesUsedName+Integer.toString(i), - createArrowExprList(DashUtilFcns.newListWith(cop, createVar(stateLabelName))))); + createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(stateLabelName)))))); if (d.hasEvents() & d.hasEventsAti(i)) // events 1, etc. decls.add( DeclExt.newVarDeclExt( eventsName+Integer.toString(i), - createArrowExprList(DashUtilFcns.newListWith(cop, createVar(allEventsName))))); + createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(allEventsName)))))); } d.alloyString += d.addSigWithDeclsSimple(identifierName, decls); } @@ -87,13 +88,29 @@ public static void addSnapshotSignature(DashModule d){ // vfqns with no params and simple type // becomes var sig vfqn in var {} // no buffers in this case + // this is tricky if one/lone/set modifiers on type *** List allvfqnsNoParamsSimpleTyp = allvfqns.stream() - .filter(i -> d.getVarBufferParams(i).size() == 0 && isExprVar(d.getVarType(i))) + .filter(i -> d.getVarBufferParams(i).size() == 0 && !isWeirdOne(i,d)) .collect(Collectors.toList()); - for (String v: allvfqnsNoParamsSimpleTyp) - d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar) translateExpr(d.getVarType(v),d,true)) ); + for (String v: allvfqnsNoParamsSimpleTyp) { + + Expr typ = d.getVarType(v); + //System.out.println(typ.getClass()); + //System.out.println(((ExprUnary) typ).op); + if (isExprVar(typ)) { + d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar) translateExpr(typ,d,true)) ); + } else if (isExprSet(typ) && isExprVar(getSub(typ))) { + d.alloyString += d.addVarSigSimple(translateFQN(v), ((ExprVar)translateExpr(getSub(typ),d,true)) ); + } else if (isExprLone(typ) && isExprVar(getSub(typ))) { + d.alloyString += d.addVarLoneSigSimple(translateFQN(v), ((ExprVar)translateExpr(getSub(typ),d,true)) ); + } else if (isExprOne(typ) && isExprVar(getSub(typ))) { + d.alloyString += d.addVarOneSigSimple(translateFQN(v), ((ExprVar) translateExpr(getSub(typ),d,true)) ); + } else { + TranslationToAlloyErrors.Unsupported(typ); + } + } - // vfqns with no params and arrow type (A -> B) + // vfqns with no params and non-simple var types (weird ones) // becomes sig A { var vfqn: B } // but A has already been declared somewhere by the user // and we can't easily add a field to an existing signature in @@ -135,7 +152,7 @@ public static void addSnapshotSignature(DashModule d){ decls = new ArrayList(); for (String v: allvfqnsWithThisFirstParam) { if (d.getVarBufferParams(v).size() == 1) { - decls.add(DeclExt.newVarDeclExt(v, translateExpr(d.getVarType(v),d, true))); + decls.add(DeclExt.newVarDeclExt(translateFQN(v), translateExpr(d.getVarType(v),d, true))); } else { plist = createVarList(d.getVarBufferParams(v).subList(1, d.getVarBufferParams(v).size()-1)); plist.add(translateExpr(d.getVarType(v),d, true)); @@ -159,6 +176,7 @@ public static void addSnapshotSignature(DashModule d){ decls.add(DeclExt.newVarDeclExt(translateFQN(b),createArrowExprList(plist))); } d.alloyString += d.addSigExtendsWithDeclsSimple(prm, identifierName, decls); + } // buffers with no parameters diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index 5ba51c7f9..07f3c2939 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -79,12 +79,23 @@ public static void addSpaceSignatures(DashModule d) { } // abstract sig BufIdx {} if this model has buffers - // if not Electrum + // if not Electrum or if this buffer would be grouped under a parameter in Electrum declaration // o/w buffers have to be fields in sig BufIdx // and this functionality is within AddSnapshotSignatures - if (!DashOptions.isElectrum && d.hasBuffers()) { - for (int i: d.getBufferIndices()) { - d.alloyString += d.addSigSimple(DashStrings.bufferIndexName + i); + + if (d.hasBuffers()) { + // buffers with parameters + // every buffer has a different index + // so just one decl per sig + List allbfqns = d.getAllBufferNames(); + for (String b:allbfqns) { + if (DashOptions.isElectrum) { + if (d.getVarBufferParams(b).size() != 0) + // because buffer is declared under param + // o/w declared with buffer index in Snapshot stuff + d.alloyString += d.addSigSimple(DashStrings.bufferIndexName + d.getBufferIndex(b)); + } else + d.alloyString += d.addSigSimple(DashStrings.bufferIndexName + d.getBufferIndex(b)); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index 2d529b0e0..995bdd229 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -55,7 +55,8 @@ public static Decl paramDecl(Integer n, String name) { // [s:Snapshot, s':Snapshot] public static List curDecls() { List o = new ArrayList(); - o.add(curDecl()); + if (!DashOptions.isElectrum) + o.add(curDecl()); return o; } @@ -79,14 +80,14 @@ public static List paramDecls(List prsIdx , List prs) { // s:Snapshot, p0:P0, p1:P1, ...] public static List curParamsDecls(List prsIdx, List prs) { List o = new ArrayList(); - if (!DashOptions.isElectrum) o.add(curDecl()); + o.addAll(curDecls()); o.addAll(paramDecls(prsIdx, prs)); return o; } // s:Snapshot, s':Snapshot, p0:P0, p1:P1, ...] public static List curNextParamsDecls(List prsIdx, List prs) { List o = new ArrayList(); - if (!DashOptions.isElectrum) { o.add(curDecl()); o.add(nextDecl()); } + o.addAll(curNextDecls()); o.addAll(paramDecls(prsIdx, prs)); return o; } @@ -119,11 +120,27 @@ public static ExprVar curVar() { public static ExprVar nextVar() { return createVar(DashStrings.nextName); } + public static List curVars() { + List o = new ArrayList(); + if (!DashOptions.isElectrum) { + o.add(curVar()); + } + return o; + } + public static List nextVars() { + List o = new ArrayList(); + if (!DashOptions.isElectrum) { + o.add(nextVar()); + } + return o; + } //[s,s'] public static List curNextVars() { List o = new ArrayList(); - o.add(curVar()); - o.add(nextVar()); + if (!DashOptions.isElectrum) { + o.add(curVar()); + o.add(nextVar()); + } return o; } //pi: Identfiers @@ -144,14 +161,15 @@ public static List paramVars(List prsIdx, List prs) { // [s, p1,p2,...] public static List curParamVars(List prsIdx, List prs) { List o = new ArrayList(); - o.add(curVar()); + o.addAll(curVars()); o.addAll(paramVars(prsIdx,prs)); return o; } // [s', p1,p2,...] public static List nextParamVars(List prsIdx, List prs) { List o = new ArrayList(); - o.add(nextVar()); + + o.addAll(nextVars()); o.addAll(paramVars(prsIdx, prs)); return o; } @@ -237,17 +255,21 @@ public static Expr nextStableFalse() { // s.name public static Expr curJoinExpr(Expr e) { - return createJoin(curVar(), e); + if (DashOptions.isElectrum) return e; + else return createJoin(curVar(), e); } //s'.name public static Expr nextJoinExpr(Expr e) { if (DashOptions.isElectrum) { - //TODO -- prime all variables?? - return createTrue(); + assert(isExprVar(e)); + return primedVarExpr(e); } else { return createJoin(nextVar(), e); } } + public static Expr primedVarExpr(Expr e) { + return createPrime(e); + } /* // p3 -> p2 -> p1 -> x public static Expr paramsToXArrow(List prsIdx, List prs, String x) { @@ -274,10 +296,20 @@ public static Expr translateDashRefToJoin(DashRef e) { return createJoinList(ll); } - //TODO better name! + //in Electrum - if we have a dynamic var (not buffer) with a non-var, non-one var, non-lone var, non-set var + // type, we have to handle is specially public static boolean isWeirdOne(String vfqn, DashModule d) { //System.out.println("Vqn: " + vfqn); - return d.getVarBufferParams(vfqn).size() == 0 && isExprArrow(d.getVarType(vfqn)); + if (d.hasVar(vfqn)) { + Expr typ = d.getVarType(vfqn); + return (d.getVarBufferParams(vfqn).size() == 0 && + !((isExprOne(typ) && isExprVar(getSub(typ))) || + (isExprLone(typ) && isExprVar(getSub(typ))) || + (isExprSet(typ) && isExprVar(getSub(typ))))); + } else { + // it is a buffer and getVarType does not work on buffers + return false; + } } // common case diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 951258094..0cc30ae04 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -194,9 +194,11 @@ public String addSigWithDeclsSimple(String name, List decls) { null); String s = DashStrings.sigName + space + name; s += " {\n"+tab; - StringJoiner j = new StringJoiner(",\n"+tab); - decls.forEach(i -> j.add(ppDecl(i))); - s += j.toString() + "\n}\n"; + if (!decls.isEmpty()) { + StringJoiner j = new StringJoiner(",\n"+tab); + decls.forEach(i -> j.add(ppDecl(i))); + s += j.toString() + "\n}\n"; + } else s += "}\n"; //System.out.println(s); return s; } @@ -241,7 +243,7 @@ public String addOneSigWithDeclsSimple(String name, List decls) { null, null, null); - String s = DashStrings.sigName + space + name + space + "{\n"; + String s = DashStrings.oneName + space +DashStrings.sigName + space + name + space + "{\n"; //s += ppDecls(decls); StringJoiner j = new StringJoiner(",\n"); decls.forEach(i -> j.add(ppDecl(i))); @@ -249,6 +251,7 @@ public String addOneSigWithDeclsSimple(String name, List decls) { //System.out.println(s); return s; } + // var sig name in typ {} public String addVarSigSimple(String name, ExprVar typ) { // var sig s in typ {}; addSig( @@ -272,7 +275,6 @@ public String addVarSigSimple(String name, ExprVar typ) { //System.out.println(s); return s; } - public String addVarSigSimple(String name, List typ) { // var sig s in typ {}; addSig( @@ -297,6 +299,56 @@ public String addVarSigSimple(String name, List typ) { return s; } + // var one sig name in typ {} + public String addVarOneSigSimple(String name, ExprVar typ) { + // var one sig s in typ {}; + addSig( + Pos.UNKNOWN, + name, + createVar(DashStrings.inName), + Arrays.asList(typ), + new ArrayList(), + null, + null, + null, + AttrType.ONE.makenull(Pos.UNKNOWN), + null, + null, + AttrType.VARIABLE.makenull(Pos.UNKNOWN) + ); + String s = DashStrings.varName + space + DashStrings.oneName + space + DashStrings.sigName + space; + s += name + space + DashStrings.inName + space; + s += ppExpr(typ); + s += " { }\n"; + //System.out.println(s); + return s; + } + + // var lone sig name in typ {} + public String addVarLoneSigSimple(String name, ExprVar typ) { + // var lone sig s in typ {}; + addSig( + Pos.UNKNOWN, + name, + createVar(DashStrings.inName), + Arrays.asList(typ), + new ArrayList(), + null, + null, + null, + AttrType.LONE.makenull(Pos.UNKNOWN), + null, + null, + AttrType.VARIABLE.makenull(Pos.UNKNOWN) + ); + String s = DashStrings.varName + space + DashStrings.loneName + space + DashStrings.sigName + space; + s += name + space + DashStrings.inName + space; + s += ppExpr(typ); + s += " { }\n"; + //System.out.println(s); + return s; + } + /** @@ -348,9 +400,7 @@ public String addFactSimple(String name, List eList) { Expr body = createAndFromList(eList); addFact(Pos.UNKNOWN,name,body); String s = new String(); - s += DashStrings.factName + " " + name + " {"; - StringJoiner j = new StringJoiner(", "); - s += tab; + s += DashStrings.factName + " " + name + " {\n" + tab; StringJoiner sj = new StringJoiner("\n" + tab); for (Expr e: eList) { //ExprToString eToString = new ExprToString(false); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index f1ac32507..e2fb024e1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -375,6 +375,9 @@ public boolean isEnvironmentalEvent(String efqn) { public boolean isInternalEvent(String efqn) { return eventTable.isInternalEvent(efqn); } + public boolean hasVar(String name) { + return varTable.hasVar(name); + } public List getAllVarNames() { return varTable.getAllVarNames(); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java index ac828af9f..b9735d0e8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/VarTable.java @@ -104,7 +104,9 @@ public void resolve(StateTable st, EventTable et, PredTable pt) { } - + public boolean hasVar(String name) { + return (varTable.containsKey(name)); + } public List getAllVarNames() { return new ArrayList(varTable.keySet()); } From 9e142720987ea52a55deb3fe0cc665723a159a80 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 16 Jun 2023 09:52:04 -0400 Subject: [PATCH 061/129] translation to Electrum --- .../main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java index 17bbf26d9..233dc2746 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/DeclExt.java @@ -45,7 +45,7 @@ public String toString() { String x = new String(); StringJoiner sj = new StringJoiner(", "); // var keyword - System.out.println("Decl" + names + (this.isVar==null)); + //System.out.println("Decl" + names + (this.isVar==null)); if (isVar != null) { x += DashStrings.varName + " "; } From 04aa54b45961a59f5f0b7009da00da2ed4318fd4 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 16 Jun 2023 09:52:28 -0400 Subject: [PATCH 062/129] adding translation to alloy errors file --- .../dashtoalloy/TranslationToAlloyErrors.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/TranslationToAlloyErrors.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/TranslationToAlloyErrors.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/TranslationToAlloyErrors.java new file mode 100644 index 000000000..6d6f742b5 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/TranslationToAlloyErrors.java @@ -0,0 +1,20 @@ +/* + * All the errors that can be thrown in Dash code + */ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.List; + +import edu.mit.csail.sdg.alloy4.Pos; +import edu.mit.csail.sdg.alloy4.Err; +import edu.mit.csail.sdg.alloy4.ErrorSyntax; +import edu.mit.csail.sdg.alloy4.ErrorFatal; +import edu.mit.csail.sdg.ast.Expr; + +public class TranslationToAlloyErrors { + + public static void Unsupported(Expr e) throws Err { + throw new ErrorSyntax("Unsupported: " + e.toString()); + } +} \ No newline at end of file From 31ec56128cd4cebfdc0219e3f94eed4cba133f9f Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sat, 17 Jun 2023 11:14:54 -0400 Subject: [PATCH 063/129] added single event input --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 16 +++- .../watform/alloyasthelper/ExprHelper.java | 6 ++ .../uwaterloo/watform/core/DashOptions.java | 5 +- .../uwaterloo/watform/core/DashStrings.java | 5 +- .../dashtoalloy/AddSingleEventInputFact.java | 73 +++++++++++++++++++ .../watform/dashtoalloy/AddTcmcFact.java | 4 +- .../watform/dashtoalloy/AddTransPost.java | 2 +- .../watform/dashtoalloy/DashToAlloy.java | 2 + 8 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSingleEventInputFact.java diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index d592b06fa..e2fdd6ccc 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -66,9 +66,15 @@ public static void executeCommands(CompModule c, Integer cmdnum, A4Reporter rep) public static void main(String args[]) throws Exception { if(args.length == 0) { - System.out.println("Arguments: (-m traces|tcmc|electrum) (-c #) (-p) (-t) (-r) filename(s)"); - System.out.println(" -c is cmdnum; -t is translateOnly; -r is resolveOnly; -p is printDash"); - System.out.println("if given a .als files, it runs all its commands"); + System.out.println("Arguments: (-m traces|tcmc|electrum) (-single) (-c #) (-p) (-t) (-r) filename(s)"); + System.out.println("-m traces|tcmc|electrum is verification method"); + System.out.println("-single includes single event input"); + System.out.println("-c # is cmdnum to execute"); + System.out.println("-t is translateOnly"); + System.out.println("-r is resolveOnly"); + System.out.println("-e is echo file from internal parsed data"); + System.out.println("expects .dsh or .als file"); + System.out.println("if given a .als files, it ignores other options and runs all its commands"); System.exit(0); } @@ -111,10 +117,12 @@ public static void main(String args[]) throws Exception { i++; } else if (args[i].equals("-t")) { translateOnly = true; - } else if (args[i].equals("-p")) { + } else if (args[i].equals("-e")) { printOnly = true; } else if (args[i].equals("-r")) { resolveOnly = true; + } else if (args[i].equals("-single")) { + DashOptions.singleEventInput = true; } else { // everything else is a file name filelist.add(args[i]); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 8d0708fbe..9e390055f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -210,9 +210,15 @@ public static Expr createNot(Expr sub) { public static Expr createOne(Expr sub) { return (ExprUnary) ExprUnary.Op.ONE.make(Pos.UNKNOWN, sub); } + public static Expr createLone(Expr sub) { + return (ExprUnary) ExprUnary.Op.LONE.make(Pos.UNKNOWN, sub); + } public static Expr createSomeOf(Expr sub) { return (ExprUnary) ExprUnary.Op.SOMEOF.make(Pos.UNKNOWN, sub); } + public static Expr createNo(Expr sub) { + return (ExprUnary) ExprUnary.Op.NO.make(Pos.UNKNOWN, sub); + } public static Expr createSet(Expr sub) { return (ExprUnary) ExprUnary.Op.SETOF.make(Pos.UNKNOWN, sub); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java index 11571a19b..d350f3c6f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java @@ -9,10 +9,11 @@ public class DashOptions { public static boolean isElectrum = false; public static boolean isTcmc = false; public static boolean isTraces = true; - + public static boolean singleEventInput = false; + //NAD other stuff that might be removed //public static boolean variablesUnchanged = true; - //public static boolean assumeSingleInput = false; + //public static boolean generateSigAxioms = false; //public static boolean reachabilityCheck = false; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 90ecc35bf..7b3363e1f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -43,8 +43,8 @@ public class DashStrings { public static String utilBufferName = "util/buffer"; public static String utilTcmcPathName = "util/tcmc_path"; - public static String tcmcKsSigmaName = "tcmc/ks_sigma"; - public static String tcmcKsS0Name = "tcmc/ks_s0"; + public static String tcmcSigmaName = "tcmc_path/pathSigma"; + public static String tcmcInitialStateName = "tcmc_path/pathState"; // Dash input keywords @@ -67,6 +67,7 @@ public class DashStrings { public static String enterName = "enter"; public static String exitName = "exit"; public static String initName = "init"; + public static String singleEventName = "singleEvent"; // user must be aware of this name public static String bufferIndexName = "bufIdx"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSingleEventInputFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSingleEventInputFact.java new file mode 100644 index 000000000..387a641fc --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSingleEventInputFact.java @@ -0,0 +1,73 @@ +/* + * Optional fact for single "input" assumption + * For Dash+, this means only one env event per big step + * + * + * + * fact single_input { + * all s: Snapshot | + * lone s.events0 :> ExternalEvents and no s.events1:> ExternalEvents and no.events2:> ExternalEvents or ... + * no s.events0:> ExternalEvents and lone s.events1:> ExternalEvents and no s.events2 :> ExternalEventsor ... + * no s.events0 :> ExternalEvents and no s.events1:> ExternalEvents and lone s.events2:> ExternalEvents or ... + * } + */ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.IntStream; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddSingleEventInputFact { + + public static void addSingleEventInputFact(DashModule d) { + if (d.hasEnvironmentalEvents()) { + Expr e; + Expr b = createFalse(); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + if (d.hasEventsAti(i)) { + e = createTrue(); + for (int j=0;j <= d.getMaxDepthParams(); j++) { + if (d.hasEventsAti(j)) { + if (i==j) { + e = createAnd(e,createLone(createRangeRes(curEvents(i), allEnvironmentalEventsVar()))); + } else { + e = createAnd(e,createNo(createRangeRes(curEvents(i), allEnvironmentalEventsVar()))); + } + } + } + b = createOr(b,e); + } + } + List body = new ArrayList(); + if (DashOptions.isElectrum) body.add(b); + else body.add(createAll(curDecls(),b)); + d.alloyString += d.addFactSimple(DashStrings.singleEventName, body); + } + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java index 8cfbb892e..22167dfb8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTcmcFact.java @@ -60,7 +60,7 @@ public static void addTcmcFact(DashModule d) { createAll( decls, createIff( - createIn(curVar(), createVar(tcmcKsS0Name)), + createIn(curVar(), createVar(tcmcInitialStateName)), createPredCall(initFactName,args)))); body.add( @@ -69,7 +69,7 @@ public static void addTcmcFact(DashModule d) { createIff( createIn( createArrow(curVar(), nextVar()), - createVar(tcmcKsSigmaName)), + createVar(tcmcSigmaName)), createPredCall(smallStepName, curNextVars())))); d.alloyString += d.addFactSimple(tcmcFactName, body); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index b85fa1cb0..b54748319 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -80,7 +80,7 @@ public class AddTransPost { } */ - // TODO for Electrum! + public static void addTransPost(DashModule d, String tfqn) { String tout = translateFQN(tfqn); List prsIdx = d.getTransParamsIdx(tfqn); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index eb0c5db94..2c37c0c1f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -28,6 +28,8 @@ public static void translate(DashModule d) { AddStutter.addStutter(d); AddSmallStep.addSmallStep(d); + if (DashOptions.singleEventInput) + AddSingleEventInputFact.addSingleEventInputFact(d); if (DashOptions.isTraces) AddTracesFact.addTracesFact(d); else if (DashOptions.isTcmc) From 050264237433c7f11995aace78973b466826c5b9 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sun, 18 Jun 2023 16:08:18 -0400 Subject: [PATCH 064/129] used tcmc module (not tcmc_path); fixed bug to init sc_used --- .../main/java/ca/uwaterloo/watform/core/DashStrings.java | 7 ++++--- .../java/ca/uwaterloo/watform/dashtoalloy/AddInit.java | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 7b3363e1f..bfec7ba83 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -42,9 +42,10 @@ public class DashStrings { public static String utilBufferName = "util/buffer"; - public static String utilTcmcPathName = "util/tcmc_path"; - public static String tcmcSigmaName = "tcmc_path/pathSigma"; - public static String tcmcInitialStateName = "tcmc_path/pathState"; + public static String utilTcmcPathName = "util/tcmc"; + public static String tcmcInitialStateName = "tcmc/ks_s0"; + public static String tcmcSigmaName = "tcmc/ks_sigma"; + // Dash input keywords diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index f1edda715..080f940f1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -51,14 +51,14 @@ public static void addInit(DashModule d) { if (!ent.isEmpty()) body.add(createEquals(curConf(i),createUnionList(ent))); else body.add(createEquals(curConf(i), createNone())); } - for (int i = 1; i <= d.getMaxDepthParams(); i++) { + for (int i = 0; i <= d.getMaxDepthParams(); i++) { // scopesUsedi = none body.add(createEquals( curScopesUsed(i), createNoneArrow(i))); // no limits on initial set of events except that they must be environmental //s.events1 :> internalEvents = none -> none - if (d.hasEventsAti(i)) + if (d.hasInternalEventsAti(i)) body.add(createEquals( createRangeRes(curEvents(i), allInternalEventsVar()), createNoneArrow(i))); From 18e03527ded8417fc3c75a843d45684dda6bf5ef Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sun, 18 Jun 2023 18:38:03 -0400 Subject: [PATCH 065/129] added reachability fact --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 7 ++- .../watform/alloyasthelper/ExprHelper.java | 18 ++++++- .../watform/alloyasthelper/ExprToString.java | 12 ++++- .../uwaterloo/watform/core/DashOptions.java | 2 +- .../uwaterloo/watform/core/DashStrings.java | 51 ++++++++++--------- .../watform/dashtoalloy/DashToAlloy.java | 4 +- 6 files changed, 63 insertions(+), 31 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index e2fdd6ccc..b23a45143 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -66,9 +66,10 @@ public static void executeCommands(CompModule c, Integer cmdnum, A4Reporter rep) public static void main(String args[]) throws Exception { if(args.length == 0) { - System.out.println("Arguments: (-m traces|tcmc|electrum) (-single) (-c #) (-p) (-t) (-r) filename(s)"); + System.out.println("Arguments: (-m traces|tcmc|electrum) (-single) (-reach) (-c #) (-p) (-t) (-r) filename(s)"); System.out.println("-m traces|tcmc|electrum is verification method"); - System.out.println("-single includes single event input"); + System.out.println("-single includes single event input fact"); + System.out.println("-reach includes reachability fact (for tcmc only)"); System.out.println("-c # is cmdnum to execute"); System.out.println("-t is translateOnly"); System.out.println("-r is resolveOnly"); @@ -123,6 +124,8 @@ public static void main(String args[]) throws Exception { resolveOnly = true; } else if (args[i].equals("-single")) { DashOptions.singleEventInput = true; + } else if (args[i].equals("-reach")) { + DashOptions.reachability = true; } else { // everything else is a file name filelist.add(args[i]); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 9e390055f..34279fe69 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -54,7 +54,16 @@ public static boolean isExprLone(Expr e) { public static boolean isExprCard(Expr e) { return ((e instanceof ExprUnary) && ((ExprUnary) e).op.equals(ExprUnary.Op.CARDINALITY)); } - + + public static boolean isExprRClosure(Expr e) { + return ((e instanceof ExprUnary) && ((ExprUnary) e).op.equals(ExprUnary.Op.RCLOSURE)); + } + + public static boolean isExprClosure(Expr e) { + return ((e instanceof ExprUnary) && ((ExprUnary) e).op.equals(ExprUnary.Op.CLOSURE)); + } + + public static boolean isExprJoin(Expr e) { return ((e instanceof ExprBinary) && ((ExprBinary) e).op.equals(ExprBinary.Op.JOIN)); } @@ -222,6 +231,9 @@ public static Expr createNo(Expr sub) { public static Expr createSet(Expr sub) { return (ExprUnary) ExprUnary.Op.SETOF.make(Pos.UNKNOWN, sub); } + public static ExprUnary createReflexiveTransitiveClosure(Expr sub) { + return (ExprUnary) ExprUnary.Op.RCLOSURE.make(Pos.UNKNOWN, sub); + } public static ExprBinary createJoin(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.JOIN.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } @@ -250,6 +262,10 @@ public static Expr createJoinList(List elist, Expr e) { public static ExprBinary createRangeRes(Expr left, Expr right) { return (ExprBinary) ExprBinary.Op.RANGE.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } + public static ExprBinary createDomainRes(Expr left, Expr right) { + return (ExprBinary) ExprBinary.Op.DOMAIN.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } + public static Expr createUnionList(List elist) { Expr ret = null; assert(elist!=null); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index b018e0bd8..3c7e61ace 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -223,12 +223,20 @@ private void addBracketsIfNeededNoBlocks(Expr expr) { } private void addBracketsIfNeeded(Expr expr) { - if (!(isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr) ))) { + if (!(isExprVar(expr) || + (isExprUnary(expr) && + !isExprCard(expr)&& + !isExprRClosure(expr) && + !isExprClosure(expr)))) { out.beginC(2); out.print("("); } ExprToOut(expr); - if (!(isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr) ) )) { + if (!(isExprVar(expr) || + (isExprUnary(expr) && + !isExprCard(expr) && + !isExprRClosure(expr) && + !isExprClosure(expr)) )) { out.print(")"); out.end(); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java index d350f3c6f..3a5d720ea 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java @@ -10,7 +10,7 @@ public class DashOptions { public static boolean isTcmc = false; public static boolean isTraces = true; public static boolean singleEventInput = false; - + public static boolean reachability = true; //NAD other stuff that might be removed //public static boolean variablesUnchanged = true; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index bfec7ba83..46656bebd 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -68,43 +68,46 @@ public class DashStrings { public static String enterName = "enter"; public static String exitName = "exit"; public static String initName = "init"; - public static String singleEventName = "singleEvent"; + // user must be aware of this name public static String bufferIndexName = "bufIdx"; + public static String dsh_prefix = "dsh_"; // init is a reserved word in Dash - public static String initFactName = "dsh_initial"; - public static String electrumInitName = "dsh_init"; + public static String initFactName = dsh_prefix + "initial"; + public static String electrumInitName = dsh_prefix + "init"; // predicate names - public static String smallStepName = "dsh_small_step"; - public static String stableName = "dsh_stable"; - public static String stutterName = "dsh_stutter"; + public static String smallStepName = dsh_prefix + "small_step"; + public static String stableName = dsh_prefix + "stable"; + public static String stutterName = dsh_prefix + "stutter"; //public static String equalsName = "equals"; - public static String isEnabled = "dsh_isEnabled"; - public static String tracesFactName = "dsh_traces_fact"; - public static String electrumFactName = "dsh_electrum_fact"; - public static String tcmcFactName = "dsh_tcmc_fact"; - + public static String isEnabled = dsh_prefix + "isEnabled"; + public static String tracesFactName = dsh_prefix + "traces_fact"; + public static String electrumFactName = dsh_prefix + "electrum_fact"; + public static String tcmcFactName = dsh_prefix + "tcmc_fact"; + public static String singleEventName = dsh_prefix + "single_event"; + public static String reachabilityName = dsh_prefix + "reachability"; /* names used in Dash translation */ // sig names - public static String snapshotName = "DshSnapshot"; - public static String allEventsName = "DshEvents"; - public static String allEnvironmentalEventsName = "DshEnvEvents"; - public static String allInternalEventsName = "DshIntEvents"; - public static String variablesName = "DshVars"; - public static String stateLabelName = "DshStates"; + public static String DshPrefix = "Dsh"; + public static String snapshotName = DshPrefix + "Snapshot"; + public static String allEventsName = DshPrefix + "Events"; + public static String allEnvironmentalEventsName = DshPrefix + "EnvEvents"; + public static String allInternalEventsName = DshPrefix + "IntEvents"; + public static String variablesName = DshPrefix + "Vars"; + public static String stateLabelName = DshPrefix + "States"; //public static String systemStateName = "SystemState"; //public static String transitionLabelName = "TransitionLabel"; - public static String identifierName = "DshIds"; - public static String bufferName = "DshBuffer"; + public static String identifierName = DshPrefix + "Ids"; + public static String bufferName = DshPrefix + "Buffer"; // field names - public static String confName = "dsh_conf"; - public static String scopesUsedName = "dsh_sc_used"; - public static String eventsName = "dsh_events"; + public static String confName = dsh_prefix + "conf"; + public static String scopesUsedName = dsh_prefix + "sc_used"; + public static String eventsName = dsh_prefix + "events"; // predicate names //public static String tName = "dsh_t"; @@ -119,8 +122,8 @@ public class DashStrings { public static String curName = "s"; public static String nextName = "sn"; public static String pName = "p"; - public static String genEventName = "dsh_genEvs"; - public static String scopeName = "dsh_scp"; + public static String genEventName = "genEvs"; + public static String scopeName = "sc"; public static String randomParamExt = "_aa"; // strings used internally diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 2c37c0c1f..03bb3ecb7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -32,8 +32,10 @@ public static void translate(DashModule d) { AddSingleEventInputFact.addSingleEventInputFact(d); if (DashOptions.isTraces) AddTracesFact.addTracesFact(d); - else if (DashOptions.isTcmc) + else if (DashOptions.isTcmc) { + if (DashOptions.reachability) AddReachabilityFact.addReachabilityFact(d); AddTcmcFact.addTcmcFact(d); + } else if (DashOptions.isElectrum) AddElectrumFact.addElectrumFact(d); } From 4fabe7bf6a76e3c7559857d656476f87a264d0ec Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sun, 18 Jun 2023 19:05:29 -0400 Subject: [PATCH 066/129] added enoughOperations predicate with -enough option --- .../src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java | 3 +++ .../src/main/java/ca/uwaterloo/watform/core/DashOptions.java | 3 ++- .../src/main/java/ca/uwaterloo/watform/core/DashStrings.java | 1 + .../java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index b23a45143..a5343e401 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -70,6 +70,7 @@ public static void main(String args[]) throws Exception { System.out.println("-m traces|tcmc|electrum is verification method"); System.out.println("-single includes single event input fact"); System.out.println("-reach includes reachability fact (for tcmc only)"); + System.out.println("-enough includes enoughOperations pred"); System.out.println("-c # is cmdnum to execute"); System.out.println("-t is translateOnly"); System.out.println("-r is resolveOnly"); @@ -126,6 +127,8 @@ public static void main(String args[]) throws Exception { DashOptions.singleEventInput = true; } else if (args[i].equals("-reach")) { DashOptions.reachability = true; + } else if (args[i].equals("-enough")) { + DashOptions.enoughOperations = true; } else { // everything else is a file name filelist.add(args[i]); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java index 3a5d720ea..ed0ee4943 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java @@ -10,7 +10,8 @@ public class DashOptions { public static boolean isTcmc = false; public static boolean isTraces = true; public static boolean singleEventInput = false; - public static boolean reachability = true; + public static boolean reachability = false; + public static boolean enoughOperations = false; //NAD other stuff that might be removed //public static boolean variablesUnchanged = true; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 46656bebd..42d395210 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -89,6 +89,7 @@ public class DashStrings { public static String tcmcFactName = dsh_prefix + "tcmc_fact"; public static String singleEventName = dsh_prefix + "single_event"; public static String reachabilityName = dsh_prefix + "reachability"; + public static String enoughOperationsName = dsh_prefix + "enoughOperations"; /* names used in Dash translation */ // sig names diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 03bb3ecb7..336c2da50 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -28,6 +28,7 @@ public static void translate(DashModule d) { AddStutter.addStutter(d); AddSmallStep.addSmallStep(d); + if (DashOptions.enoughOperations) AddEnoughOperationsPred.addEnoughOperationsPred(d); if (DashOptions.singleEventInput) AddSingleEventInputFact.addSingleEventInputFact(d); if (DashOptions.isTraces) From 223a759d63118ba563f9fc20709c4153d6e73e1b Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Sun, 18 Jun 2023 19:33:35 -0400 Subject: [PATCH 067/129] added files missed last push; added complete big steps --- .../watform/alloyasthelper/ExprHelper.java | 3 + .../uwaterloo/watform/core/DashStrings.java | 4 +- .../dashtoalloy/AddCompleteBigSteps.java | 59 +++++++++++++++++++ .../dashtoalloy/AddEnoughOperationsPred.java | 57 ++++++++++++++++++ .../watform/dashtoalloy/AddReachability.java | 53 +++++++++++++++++ .../uwaterloo/watform/dashtoalloy/Common.java | 6 ++ .../watform/dashtoalloy/DashToAlloy.java | 3 +- 7 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddCompleteBigSteps.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddEnoughOperationsPred.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachability.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 34279fe69..6ee2438f7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -335,6 +335,9 @@ public static ExprList createOrList(List args) { public static Expr createIff(Expr left, Expr right) { return (Expr) ExprBinary.Op.IFF.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } + public static Expr createImplies(Expr left, Expr right) { + return (Expr) ExprBinary.Op.IMPLIES.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); + } public static ExprBinary createArrow(Expr left,Expr right) { return (ExprBinary) ExprBinary.Op.ARROW.make(Pos.UNKNOWN, Pos.UNKNOWN, left, right); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 42d395210..28e0ef596 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -89,8 +89,8 @@ public class DashStrings { public static String tcmcFactName = dsh_prefix + "tcmc_fact"; public static String singleEventName = dsh_prefix + "single_event"; public static String reachabilityName = dsh_prefix + "reachability"; - public static String enoughOperationsName = dsh_prefix + "enoughOperations"; - + public static String enoughOperationsName = dsh_prefix + "enough_operations"; + public static String completeBigStepsName = dsh_prefix + "complete_big_steps"; /* names used in Dash translation */ // sig names public static String DshPrefix = "Dsh"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddCompleteBigSteps.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddCompleteBigSteps.java new file mode 100644 index 000000000..b02cb06b3 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddCompleteBigSteps.java @@ -0,0 +1,59 @@ +/* + * completeBigStepsFact + * + * Every non-stable snapshot included in the next snapshot relation + * has a next snapshot, which means every big step must be complete. + * fact completeBigSteps { + * all s : Snapshot | s.stable == False => some s': Snapshot. small_step[s,s'] + * } + * + * The above works for all methods. + */ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.IntStream; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddCompleteBigSteps { + + public static void addCompleteBigSteps(DashModule d) { + if (d.hasConcurrency()) { + Expr b = createAll(curDecls(), + createImplies( + curStableFalse(), + createSome(nextDecls(), + createPredCall(DashStrings.smallStepName, curNextVars())))); + + List body = new ArrayList(); + body.add(b); + d.alloyString += d.addFactSimple(DashStrings.completeBigStepsName, body); + } + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddEnoughOperationsPred.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddEnoughOperationsPred.java new file mode 100644 index 000000000..07b08bca9 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddEnoughOperationsPred.java @@ -0,0 +1,57 @@ +/* + * There exists at least one representative of every transition + * + * pred operationsSignificance { + * some s, s’: Snapshot | some p0, p1 | T1[s, s’] + * some s, s’: Snapshot | T2[s, s’] + * some s, s’: Snapshot | T3[s, s’] + * ... + * } + */ + + +package ca.uwaterloo.watform.dashtoalloy; + +//import java.util.Collections; +//import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +//import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddEnoughOperationsPred { + + public static void addEnoughOperationsPred(DashModule d) { + + ArrayList body = new ArrayList(); + + for (String tfqn: d.getAllTransNames()) { + String tout = translateFQN(tfqn); + body.add(createSome( + curNextParamsDecls(d.getTransParamsIdx(tfqn),d.getTransParams(tfqn)), + createPredCall(tout,curNextParamVars(d.getTransParamsIdx(tfqn),d.getTransParams(tfqn))))); + } + ArrayList nodecls = new ArrayList(); + d.alloyString += d.addPredSimple(DashStrings.enoughOperationsName,nodecls, body); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachability.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachability.java new file mode 100644 index 000000000..1223da000 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachability.java @@ -0,0 +1,53 @@ +/* + * + * Every snapshot is reachable from an initial snapshot + * fact reachabilityAxiom { + * all s : Snapshot | s in Snapshot .(( initial) <: * (sigma)) + * } + */ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.IntStream; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddReachability { + + public static void addReachability(DashModule d) { + assert(!DashOptions.isElectrum && !DashOptions.isTraces); + Expr b = createAll(curDecls(), + createIn(curVar(), + createJoin(createVar(DashStrings.snapshotName), + createDomainRes(createVar(DashStrings.tcmcInitialStateName), + createReflexiveTransitiveClosure(createVar(DashStrings.tcmcSigmaName)))))); + List body = new ArrayList(); + body.add(b); + d.alloyString += d.addFactSimple(DashStrings.reachabilityName, body); + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index 995bdd229..c6ae7a706 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -59,6 +59,12 @@ public static List curDecls() { o.add(curDecl()); return o; } + public static List nextDecls() { + List o = new ArrayList(); + if (!DashOptions.isElectrum) + o.add(nextDecl()); + return o; + } // [s:Snapshot, s':Snapshot] public static List curNextDecls() { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 336c2da50..20d8c870e 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -27,6 +27,7 @@ public static void translate(DashModule d) { AddTestIfNextStable.addTestIfNextStable(d); AddStutter.addStutter(d); AddSmallStep.addSmallStep(d); + if (DashOptions.isTcmc) AddCompleteBigSteps.addCompleteBigSteps(d); if (DashOptions.enoughOperations) AddEnoughOperationsPred.addEnoughOperationsPred(d); if (DashOptions.singleEventInput) @@ -34,7 +35,7 @@ public static void translate(DashModule d) { if (DashOptions.isTraces) AddTracesFact.addTracesFact(d); else if (DashOptions.isTcmc) { - if (DashOptions.reachability) AddReachabilityFact.addReachabilityFact(d); + if (DashOptions.reachability) AddReachability.addReachability(d); AddTcmcFact.addTcmcFact(d); } else if (DashOptions.isElectrum) From b442ebdf7b329cf9468d1b1fdbc66657edb925df Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Mon, 19 Jun 2023 12:18:35 -0400 Subject: [PATCH 068/129] fixed bug in enter/exit --- .../uwaterloo/watform/dashtoalloy/AddTransPost.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index b54748319..e6eb2affa 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -97,13 +97,12 @@ public static void addTransPost(DashModule d, String tfqn) { List exi = DashRef.hasNumParams(exited,i).stream() .map(x -> translateDashRefToArrow(x)) .collect(Collectors.toList()); - Expr e = curConf(i); - for (Expr x:exi) { - // can't diff ((ent1 - ent2) - ent3) - // but have to diff from whole set - e = createDiff(e,x); - } - //if (!exi.isEmpty()) e = createDiff(e,createDiffList(exi)); + // both ent and exi could be empty at this level + Expr e; + if (!exi.isEmpty()) + e = createDiff(curConf(i),createUnionList(exi)); + else + e = curConf(i); if (!ent.isEmpty()) e = createUnion(e,createUnionList(ent)); body.add(createEquals(nextConf(i),e)); } From 184519a5679e81527d691695573f1a6ae9c145e5 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Tue, 20 Jun 2023 10:15:19 -0400 Subject: [PATCH 069/129] added transition taken to snapshot --- .../uwaterloo/watform/core/DashOptions.java | 1 + .../ca/uwaterloo/watform/core/DashRef.java | 8 ++- .../uwaterloo/watform/core/DashStrings.java | 4 +- .../watform/dashtoalloy/AddInit.java | 3 ++ .../watform/dashtoalloy/AddReachability.java | 53 ------------------- .../dashtoalloy/AddSnapshotSignature.java | 16 ++++-- .../dashtoalloy/AddSpaceSignatures.java | 12 ++--- .../watform/dashtoalloy/AddStutter.java | 4 +- .../watform/dashtoalloy/AddTransPost.java | 10 ++++ .../uwaterloo/watform/dashtoalloy/Common.java | 9 ++++ .../watform/dashtoalloy/DashToAlloy.java | 9 ++-- 11 files changed, 58 insertions(+), 71 deletions(-) delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachability.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java index ed0ee4943..b3e63b03a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java @@ -12,6 +12,7 @@ public class DashOptions { public static boolean singleEventInput = false; public static boolean reachability = false; public static boolean enoughOperations = false; + public static boolean includeTrans = true; // for debugging //NAD other stuff that might be removed //public static boolean variablesUnchanged = true; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index 7b9843763..b27073220 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -74,7 +74,8 @@ public class DashRef extends Expr { private static enum DashRefKind { STATE, EVENT, - VAR + VAR, + TRANS // BUFFER ???? } @@ -122,7 +123,10 @@ public static DashRef createEventDashRef(String n, List prmValues) { public static DashRef createVarDashRef(String n, List prmValues) { return new DashRef(DashRefKind.VAR,n, prmValues); } - + public static DashRef createTransDashRef(String n, List prmValues) { + return new DashRef(DashRefKind.TRANS,n, prmValues); + + } /* public static Expr createDashRef(Pos p, String n, List eList) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 28e0ef596..a4007e8ad 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -101,7 +101,7 @@ public class DashStrings { public static String variablesName = DshPrefix + "Vars"; public static String stateLabelName = DshPrefix + "States"; //public static String systemStateName = "SystemState"; - //public static String transitionLabelName = "TransitionLabel"; + public static String transitionLabelName = "Transitions"; public static String identifierName = DshPrefix + "Ids"; public static String bufferName = DshPrefix + "Buffer"; @@ -109,7 +109,7 @@ public class DashStrings { public static String confName = dsh_prefix + "conf"; public static String scopesUsedName = dsh_prefix + "sc_used"; public static String eventsName = dsh_prefix + "events"; - + public static String transTakenName = dsh_prefix + "taken"; // predicate names //public static String tName = "dsh_t"; public static String preName = "_pre"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 080f940f1..54e6a94e2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -56,6 +56,9 @@ public static void addInit(DashModule d) { body.add(createEquals( curScopesUsed(i), createNoneArrow(i))); + body.add(createEquals( + curTransTaken(i), + createNoneArrow(i))); // no limits on initial set of events except that they must be environmental //s.events1 :> internalEvents = none -> none if (d.hasInternalEventsAti(i)) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachability.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachability.java deleted file mode 100644 index 1223da000..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachability.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Every snapshot is reachable from an initial snapshot - * fact reachabilityAxiom { - * all s : Snapshot | s in Snapshot .(( initial) <: * (sigma)) - * } - */ - -package ca.uwaterloo.watform.dashtoalloy; - -import java.util.Collections; -import java.util.stream.Collectors; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.stream.IntStream; - -import edu.mit.csail.sdg.ast.Decl; -//import edu.mit.csail.sdg.ast.ExprVar; -import edu.mit.csail.sdg.ast.Expr; - -import ca.uwaterloo.watform.core.DashOptions; -import ca.uwaterloo.watform.core.DashStrings; -import ca.uwaterloo.watform.core.DashUtilFcns; -import ca.uwaterloo.watform.core.DashErrors; -import ca.uwaterloo.watform.core.DashRef; - -// shortens the code to import these statically -import static ca.uwaterloo.watform.core.DashFQN.*; -import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; - -//import ca.uwaterloo.watform.alloyasthelper.DeclExt; -//import ca.uwaterloo.watform.alloyasthelper.ExprToString; - -import ca.uwaterloo.watform.parser.DashModule; -import ca.uwaterloo.watform.parser.CompModuleHelper; - -import static ca.uwaterloo.watform.dashtoalloy.Common.*; - -public class AddReachability { - - public static void addReachability(DashModule d) { - assert(!DashOptions.isElectrum && !DashOptions.isTraces); - Expr b = createAll(curDecls(), - createIn(curVar(), - createJoin(createVar(DashStrings.snapshotName), - createDomainRes(createVar(DashStrings.tcmcInitialStateName), - createReflexiveTransitiveClosure(createVar(DashStrings.tcmcSigmaName)))))); - List body = new ArrayList(); - body.add(b); - d.alloyString += d.addFactSimple(DashStrings.reachabilityName, body); - } -} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 160af817a..3c01b53ab 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -39,6 +39,7 @@ public static void addSnapshotSignature(DashModule d){ d.alloyString += d.addVarSigSimple(scopesUsedName+"0", createVar(stateLabelName)); d.alloyString += d.addVarSigSimple(confName+"0", createVar(stateLabelName)); + d.alloyString += d.addVarSigSimple(transTakenName+"0", createVar(transitionLabelName)); if (d.hasEvents()) d.alloyString += d.addVarSigSimple(eventsName+"0", createVar(allEventsName)); @@ -60,6 +61,11 @@ public static void addSnapshotSignature(DashModule d){ DeclExt.newVarDeclExt( confName+Integer.toString(i), createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(stateLabelName)))))); + // conf 1, etc. + decls.add( + DeclExt.newVarDeclExt( + transTakenName+Integer.toString(i), + createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(transitionLabelName)))))); // scopesUsed 1, etc. decls.add( DeclExt.newVarDeclExt( @@ -206,6 +212,7 @@ public static void addSnapshotSignature(DashModule d){ //TODO: if no concurrency, don't need scopesUsed !! decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", stateLabelName)); decls.add(DeclExt.newSetDeclExt(confName+"0", stateLabelName)); + decls.add(DeclExt.newSetDeclExt(transTakenName+"0", transitionLabelName)); if (d.hasEvents()) decls.add(DeclExt.newSetDeclExt(eventsName+"0", allEventsName)); List cop; @@ -213,13 +220,16 @@ public static void addSnapshotSignature(DashModule d){ cop = Collections.nCopies(i,identifierName); // scopesUsed 1, etc. //if (d.transAtThisParamDepth(i)) - decls.add((Decl) new DeclExt( - scopesUsedName+Integer.toString(i), - createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); + decls.add((Decl) new DeclExt( + scopesUsedName+Integer.toString(i), + createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); // conf 1, etc. decls.add((Decl) new DeclExt( confName+Integer.toString(i), createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); + decls.add((Decl) new DeclExt( + transTakenName+Integer.toString(i), + createArrowStringList(DashUtilFcns.newListWith(cop, transitionLabelName)))); // event 1, etc. if (d.hasEvents() && d.hasEventsAti(i)) decls.add((Decl) new DeclExt( diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index 07f3c2939..a532d6349 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -39,14 +39,14 @@ public static void addSpaceSignatures(DashModule d) { recurseCreateStateSpaceSigs(d, d.getRootName()); d.alloyString += "\n"; - // we don't need transition names anymore (rather we use scopes) + // abstract sig TransLabel {} - // d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); + d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); // add all transitions as one sig extensions of TransLabel - //for (String t : d.getTransNames()) { - //d.alloyString += d.addOneExtendsSigSimple(translateFQN(t), DashStrings.transitionLabelName); - //} - //d.alloyString += "\n"; + for (String t : d.getAllTransNames()) { + d.alloyString += d.addOneExtendsSigSimple(translateFQN(t), DashStrings.transitionLabelName); + } + d.alloyString += "\n"; // abstract sig Identifiers {} if this model has parametrized components // if not Electrum diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java index f735f18d1..fa667aa5a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java @@ -47,7 +47,9 @@ public static void addStutter(DashModule d) { for (int i = 0; i <= d.getMaxDepthParams(); i++) { body.add(noChange(DashStrings.confName+Integer.toString(i))); body.add(noChange(DashStrings.scopesUsedName+Integer.toString(i))); - if (d.hasEvents() && d.hasInternalEventsAti(i)) + body.add(createEquals(nextTransTaken(i), + createNoneArrow(i))); + if (d.hasEvents() && d.hasInternalEventsAti(i)) // internal events go away // external events can be added body.add(createEquals( diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index e6eb2affa..90c477c23 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -111,6 +111,16 @@ public static void addTransPost(DashModule d, String tfqn) { if (d.getTransDo(tfqn) != null) body.add(translateExpr(d.getTransDo(tfqn),d)); + Expr ex; + DashRef dr; + for (int i=0;i <= d.getMaxDepthParams(); i++) { + if (prsIdx.size() == i) { + // for convenience of methods, make it a DashRef first + dr = DashRef.createTransDashRef(tout, paramVars(prsIdx,prs)); + ex = translateDashRefToArrow(dr); + } else ex = createNoneArrow(i); + body.add(createEquals(nextTransTaken(i), ex)); + } // vars not mentioned in action do not change // includes entered/exited Set intVarsBuffersThatDontChange = DashUtilFcns.listToSet(d.getAllInternalVarNames()); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index c6ae7a706..bebf7cb42 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -213,6 +213,9 @@ public static Expr confVar(int size) { public static Expr eventsVar(int size) { return createVar(DashStrings.eventsName + size); } + public static Expr transTakenVar(int size) { + return createVar(DashStrings.transTakenName + size); + } public static Expr curScopesUsed(int size) { return curJoinExpr(scopesUsedVar(size)); @@ -237,6 +240,12 @@ public static Expr curEvents(int size) { public static Expr nextEvents(int size) { return nextJoinExpr(eventsVar(size)); } + public static Expr curTransTaken(int size) { + return curJoinExpr(transTakenVar(size)); + } + public static Expr nextTransTaken(int size) { + return nextJoinExpr(transTakenVar(size)); + } // s.stable == boolean/True public static Expr curStableTrue() { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 20d8c870e..e5a992060 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -29,15 +29,16 @@ public static void translate(DashModule d) { AddSmallStep.addSmallStep(d); if (DashOptions.isTcmc) AddCompleteBigSteps.addCompleteBigSteps(d); - if (DashOptions.enoughOperations) AddEnoughOperationsPred.addEnoughOperationsPred(d); + if (DashOptions.enoughOperations) + AddEnoughOperationsPred.addEnoughOperationsPred(d); if (DashOptions.singleEventInput) AddSingleEventInputFact.addSingleEventInputFact(d); + if (DashOptions.isTcmc && DashOptions.reachability) + AddReachabilityPred.addReachabilityPred(d); if (DashOptions.isTraces) AddTracesFact.addTracesFact(d); - else if (DashOptions.isTcmc) { - if (DashOptions.reachability) AddReachability.addReachability(d); + else if (DashOptions.isTcmc) AddTcmcFact.addTcmcFact(d); - } else if (DashOptions.isElectrum) AddElectrumFact.addElectrumFact(d); } From ab0762d1cec7d29ec570dc298bada19cce521c7d Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 21 Jun 2023 10:17:40 -0400 Subject: [PATCH 070/129] fixed scopes Used to have its own atoms; added equality --- .../java/ca/uwaterloo/watform/core/DashStrings.java | 4 +++- .../watform/dashtoalloy/AddSnapshotSignature.java | 4 ++-- .../watform/dashtoalloy/AddSpaceSignatures.java | 5 +++++ .../uwaterloo/watform/dashtoalloy/AddTransPost.java | 2 +- .../ca/uwaterloo/watform/dashtoalloy/AddTransPre.java | 2 +- .../java/ca/uwaterloo/watform/dashtoalloy/Common.java | 11 ++++++++++- .../ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java | 2 +- 7 files changed, 23 insertions(+), 7 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index a4007e8ad..3826f2b18 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -100,10 +100,12 @@ public class DashStrings { public static String allInternalEventsName = DshPrefix + "IntEvents"; public static String variablesName = DshPrefix + "Vars"; public static String stateLabelName = DshPrefix + "States"; + public static String scopeLabelName = DshPrefix + "Scopes"; //public static String systemStateName = "SystemState"; public static String transitionLabelName = "Transitions"; public static String identifierName = DshPrefix + "Ids"; public static String bufferName = DshPrefix + "Buffer"; + public static String scopeSuffix = "Scope"; // field names public static String confName = dsh_prefix + "conf"; @@ -117,7 +119,7 @@ public class DashStrings { //public static String semanticsName = "_semantics"; public static String testIfNextStableName = "_nextIsStable"; public static String enabledAfterStepName = "_enabledAfterStep"; - + public static String allSnapshotsDifferentName = "allSnapshotsDifferent"; // variable/parameter names // how to name parameter variables public static String curName = "s"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 3c01b53ab..874104bd6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -210,7 +210,7 @@ public static void addSnapshotSignature(DashModule d){ // scopesUsed0, conf0, event0 //if (d.transAtThisParamDepth(0)) //TODO: if no concurrency, don't need scopesUsed !! - decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", stateLabelName)); + decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", scopeLabelName)); decls.add(DeclExt.newSetDeclExt(confName+"0", stateLabelName)); decls.add(DeclExt.newSetDeclExt(transTakenName+"0", transitionLabelName)); if (d.hasEvents()) @@ -222,7 +222,7 @@ public static void addSnapshotSignature(DashModule d){ //if (d.transAtThisParamDepth(i)) decls.add((Decl) new DeclExt( scopesUsedName+Integer.toString(i), - createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); + createArrowStringList(DashUtilFcns.newListWith(cop, scopeLabelName)))); // conf 1, etc. decls.add((Decl) new DeclExt( confName+Integer.toString(i), diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index a532d6349..ccb56ab64 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -36,6 +36,8 @@ public static void addSpaceSignatures(DashModule d) { // abstract sig Statelabel {} d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + d.alloyString += d.addAbstractSigSimple(DashStrings.scopeLabelName); + d.alloyString += d.addOneExtendsSigSimple(d.getRootName()+DashStrings.scopeSuffix,DashStrings.scopeLabelName); recurseCreateStateSpaceSigs(d, d.getRootName()); d.alloyString += "\n"; @@ -103,6 +105,9 @@ public static void addSpaceSignatures(DashModule d) { private static void recurseCreateStateSpaceSigs(DashModule d, String parent) { for (String child: d.getImmChildren(parent)) { //System.out.println(translateFQN(child)+" "+translateFQN(parent)); + // for scopes Used + d.alloyString += d.addOneExtendsSigSimple(translateFQN(child)+DashStrings.scopeSuffix,DashStrings.scopeLabelName); + // for conf if (d.isLeaf(child)) d.alloyString += d.addOneExtendsSigSimple(translateFQN(child),translateFQN(parent)); else { //if (d.isAnd(parent)) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 90c477c23..6a77ad54d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -296,7 +296,7 @@ else if (hasSpecificParamValues(d, r)) { } // scopesUsedi' = scopesUsedi + scopesUsed u = DashRef.hasNumParams(sU,i).stream() - .map(x -> translateDashRefToArrow(x)) + .map(x -> translateDashRefToArrow(replaceScope(x))) .collect(Collectors.toList()); e = curScopesUsed(i); if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 36e429e9b..58164b8d9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -71,7 +71,7 @@ public static void addTransPre(DashModule d, String tfqn) { List nonO = d.nonOrthogonalScopesOf(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { List u = DashRef.hasNumParams(nonO,i).stream() - .map(x -> translateDashRefToArrow(x)) + .map(x -> translateDashRefToArrow(replaceScope(x))) .collect(Collectors.toList()); for (Expr x: u) body.add(createNot(createIn(x,curScopesUsed(i)))); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java index bebf7cb42..e53ec1ea3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/Common.java @@ -246,7 +246,12 @@ public static Expr curTransTaken(int size) { public static Expr nextTransTaken(int size) { return nextJoinExpr(transTakenVar(size)); } - + public static Expr curStable() { + return curJoinExpr(stable()); + } + public static Expr nextStable() { + return nextJoinExpr(stable()); + } // s.stable == boolean/True public static Expr curStableTrue() { return createIsTrue(curJoinExpr(stable())); @@ -297,6 +302,10 @@ public static Expr paramsToXArrow(List prsIdx, List prs, String } */ + public static DashRef replaceScope(DashRef e) { + assert(e.isState()); + return DashRef.createStateDashRef(e.getName()+DashStrings.scopeSuffix, e.getParamValues()); + } public static Expr translateDashRefToArrow(DashRef e) { List ll = new ArrayList(e.getParamValues()); Collections.reverse(ll); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index e5a992060..1f7f24dc8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -28,7 +28,7 @@ public static void translate(DashModule d) { AddStutter.addStutter(d); AddSmallStep.addSmallStep(d); if (DashOptions.isTcmc) AddCompleteBigSteps.addCompleteBigSteps(d); - + if (DashOptions.isTcmc) AddAllSnapshotsDifferentFact.addAllSnapshotsDifferentFact(d); if (DashOptions.enoughOperations) AddEnoughOperationsPred.addEnoughOperationsPred(d); if (DashOptions.singleEventInput) From 34d21d380b0b585ba41f986c22b847744aa690f7 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 21 Jun 2023 10:18:11 -0400 Subject: [PATCH 071/129] added missing files --- .../AddAllSnapshotsDifferentFact.java | 59 +++++++++++++++++++ .../dashtoalloy/AddReachabilityPred.java | 54 +++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java new file mode 100644 index 000000000..9981fa9d8 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java @@ -0,0 +1,59 @@ +package ca.uwaterloo.watform.dashtoalloy; + +//import java.util.Collections; +//import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; + +//import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +//import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddAllSnapshotsDifferentFact { + /* + fact allSnapshotsDifferent { + all s:DshSnapshot, sn:DshSnapshot | + s.dsh_sc_used0 = sn.dsh_sc_used0 and + s.dsh_conf0 = sn.dsh_conf0 and + s.dsh_taken0 = sn.dsh_taken0 and + s.dsh_events0 = sn.dsh_events0 and + s.dsh_stable = sn.dsh_stable => + s = sn + } + */ + public static void addAllSnapshotsDifferentFact(DashModule d) { + List body = new ArrayList(); + Expr e; + for (int i = 0; i <= d.getMaxDepthParams(); i++) { + body.add(createEquals(curConf(i),nextConf(i))); + // s.scopesUsedi = sn.scopesUsedi + body.add(createEquals(curScopesUsed(i),nextScopesUsed(i))); + body.add(createEquals(curTransTaken(i),nextTransTaken(i))); + if (d.hasInternalEventsAti(i)) + body.add(createEquals(curEvents(i),nextEvents(i))); + } + body.add(createEquals(curStable(),nextStable())); + e = createAll(curNextDecls(), createImplies(createAndList(body), createEquals(curVar(), nextVar()))); + body = new ArrayList(); + body.add(e); + d.alloyString += d.addFactSimple(DashStrings.allSnapshotsDifferentName, body); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java new file mode 100644 index 000000000..e6e6e4c61 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java @@ -0,0 +1,54 @@ +/* + * + * Every snapshot is reachable from an initial snapshot + * fact reachabilityAxiom { + * all s : Snapshot | s in Snapshot .(( initial) <: * (sigma)) + * } + */ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.IntStream; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddReachabilityPred { + + public static void addReachabilityPred(DashModule d) { + assert(!DashOptions.isElectrum && !DashOptions.isTraces); + Expr b = createAll(curDecls(), + createIn(curVar(), + createJoin(createVar(DashStrings.snapshotName), + createDomainRes(createVar(DashStrings.tcmcInitialStateName), + createReflexiveTransitiveClosure(createVar(DashStrings.tcmcSigmaName)))))); + List body = new ArrayList(); + body.add(b); + List emptyDecls = new ArrayList(); + d.alloyString += d.addPredSimple(DashStrings.reachabilityName, emptyDecls, body); + } +} From b3621d469e01a8a4ec8340832ec7a595de0b1e52 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 21 Jun 2023 16:22:56 -0400 Subject: [PATCH 072/129] added needed brackets around ITE --- .../ca/uwaterloo/watform/alloyasthelper/ExprToString.java | 6 ++++-- .../main/java/ca/uwaterloo/watform/core/DashStrings.java | 1 + .../uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java | 1 + .../java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java | 4 +++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index 3c7e61ace..fcfc9b1c8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -309,6 +309,7 @@ else if (expr.op == ExprConstant.Op.STRING) private void ExprITEToOut(ExprITE expr) { out.beginC(2); + out.print("{"); addBracketsIfNeeded(expr.cond); out.print("=>"); out.brk(1,indent); @@ -318,6 +319,7 @@ private void ExprITEToOut(ExprITE expr) { //{") out.brk(1,indent); addBracketsIfNeeded(expr.right); + out.print("}"); //out.print(" }"); out.brk(1,-indent); out.end(); @@ -334,7 +336,7 @@ private void ExprLetToOut(ExprLet expr) { private void ExprListToOut(ExprList expr) { if (expr.op == ExprList.Op.AND ) { - String op = " and"; + String op = " &&"; out.beginC(2); for (int i = 0; i < expr.args.size(); i++) { if (i > 0) @@ -344,7 +346,7 @@ private void ExprListToOut(ExprList expr) { out.end(); } else if (expr.op == ExprList.Op.OR) { - String op = " or"; + String op = " ||"; out.print("{ "); out.beginC(2); for (int i = 0; i < expr.args.size(); i++) { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java index 3826f2b18..253fbddcf 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashStrings.java @@ -103,6 +103,7 @@ public class DashStrings { public static String scopeLabelName = DshPrefix + "Scopes"; //public static String systemStateName = "SystemState"; public static String transitionLabelName = "Transitions"; + public static String noTransName = "NO_TRANS"; public static String identifierName = DshPrefix + "Ids"; public static String bufferName = DshPrefix + "Buffer"; public static String scopeSuffix = "Scope"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index ccb56ab64..1dcdf9c71 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -44,6 +44,7 @@ public static void addSpaceSignatures(DashModule d) { // abstract sig TransLabel {} d.alloyString += d.addAbstractSigSimple(DashStrings.transitionLabelName); + d.alloyString += d.addOneExtendsSigSimple(DashStrings.noTransName, DashStrings.transitionLabelName); // add all transitions as one sig extensions of TransLabel for (String t : d.getAllTransNames()) { d.alloyString += d.addOneExtendsSigSimple(translateFQN(t), DashStrings.transitionLabelName); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java index fa667aa5a..2d153b092 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java @@ -47,7 +47,9 @@ public static void addStutter(DashModule d) { for (int i = 0; i <= d.getMaxDepthParams(); i++) { body.add(noChange(DashStrings.confName+Integer.toString(i))); body.add(noChange(DashStrings.scopesUsedName+Integer.toString(i))); - body.add(createEquals(nextTransTaken(i), + if (i == 0)body.add(createEquals(nextTransTaken(i), + createVar(DashStrings.noTransName))); + else body.add(createEquals(nextTransTaken(i), createNoneArrow(i))); if (d.hasEvents() && d.hasInternalEventsAti(i)) // internal events go away From 5fbf93fa0585999029e4a492c3ff648580c3b7f1 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 21 Jun 2023 16:29:31 -0400 Subject: [PATCH 073/129] reachability as a fact rather than a predicate --- .../dashtoalloy/AddReachabilityPred.java | 54 ------------------- .../watform/dashtoalloy/DashToAlloy.java | 2 +- 2 files changed, 1 insertion(+), 55 deletions(-) delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java deleted file mode 100644 index e6e6e4c61..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Every snapshot is reachable from an initial snapshot - * fact reachabilityAxiom { - * all s : Snapshot | s in Snapshot .(( initial) <: * (sigma)) - * } - */ - -package ca.uwaterloo.watform.dashtoalloy; - -import java.util.Collections; -import java.util.stream.Collectors; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.stream.IntStream; - -import edu.mit.csail.sdg.ast.Decl; -//import edu.mit.csail.sdg.ast.ExprVar; -import edu.mit.csail.sdg.ast.Expr; - -import ca.uwaterloo.watform.core.DashOptions; -import ca.uwaterloo.watform.core.DashStrings; -import ca.uwaterloo.watform.core.DashUtilFcns; -import ca.uwaterloo.watform.core.DashErrors; -import ca.uwaterloo.watform.core.DashRef; - -// shortens the code to import these statically -import static ca.uwaterloo.watform.core.DashFQN.*; -import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; - -//import ca.uwaterloo.watform.alloyasthelper.DeclExt; -//import ca.uwaterloo.watform.alloyasthelper.ExprToString; - -import ca.uwaterloo.watform.parser.DashModule; -import ca.uwaterloo.watform.parser.CompModuleHelper; - -import static ca.uwaterloo.watform.dashtoalloy.Common.*; - -public class AddReachabilityPred { - - public static void addReachabilityPred(DashModule d) { - assert(!DashOptions.isElectrum && !DashOptions.isTraces); - Expr b = createAll(curDecls(), - createIn(curVar(), - createJoin(createVar(DashStrings.snapshotName), - createDomainRes(createVar(DashStrings.tcmcInitialStateName), - createReflexiveTransitiveClosure(createVar(DashStrings.tcmcSigmaName)))))); - List body = new ArrayList(); - body.add(b); - List emptyDecls = new ArrayList(); - d.alloyString += d.addPredSimple(DashStrings.reachabilityName, emptyDecls, body); - } -} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 1f7f24dc8..1b5aefaa3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -34,7 +34,7 @@ public static void translate(DashModule d) { if (DashOptions.singleEventInput) AddSingleEventInputFact.addSingleEventInputFact(d); if (DashOptions.isTcmc && DashOptions.reachability) - AddReachabilityPred.addReachabilityPred(d); + AddReachabilityFact.addReachabilityFact(d); if (DashOptions.isTraces) AddTracesFact.addTracesFact(d); else if (DashOptions.isTcmc) From a8587591eab2dceba075f0b66c5e0cb186d94181 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Wed, 21 Jun 2023 20:51:03 -0400 Subject: [PATCH 074/129] added missing file --- .../AddAllSnapshotsDifferentFact.java | 6 +- .../dashtoalloy/AddReachabilityFact.java | 55 +++++++++++++++++++ .../watform/dashtoalloy/AddTransPre.java | 20 ++++--- .../watform/parser/CompModuleHelper.java | 1 + 4 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityFact.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java index 9981fa9d8..1d30295d3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java @@ -45,12 +45,14 @@ public static void addAllSnapshotsDifferentFact(DashModule d) { for (int i = 0; i <= d.getMaxDepthParams(); i++) { body.add(createEquals(curConf(i),nextConf(i))); // s.scopesUsedi = sn.scopesUsedi - body.add(createEquals(curScopesUsed(i),nextScopesUsed(i))); + if (d.hasConcurrency()) + body.add(createEquals(curScopesUsed(i),nextScopesUsed(i))); body.add(createEquals(curTransTaken(i),nextTransTaken(i))); if (d.hasInternalEventsAti(i)) body.add(createEquals(curEvents(i),nextEvents(i))); } - body.add(createEquals(curStable(),nextStable())); + if (d.hasConcurrency()) + body.add(createEquals(curStable(),nextStable())); e = createAll(curNextDecls(), createImplies(createAndList(body), createEquals(curVar(), nextVar()))); body = new ArrayList(); body.add(e); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityFact.java new file mode 100644 index 000000000..ed2f922f2 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityFact.java @@ -0,0 +1,55 @@ +/* + * + * Every snapshot is reachable from an initial snapshot + * fact reachabilityAxiom { + * all s : Snapshot | s in Snapshot .(( initial) <: * (sigma)) + * } + */ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.IntStream; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddReachabilityFact { + + public static void addReachabilityFact(DashModule d) { + assert(!DashOptions.isElectrum && !DashOptions.isTraces); + Expr b = createAll(curDecls(), + createIn(curVar(), + createJoin(createVar(DashStrings.snapshotName), + createDomainRes(createVar(DashStrings.tcmcInitialStateName), + createReflexiveTransitiveClosure(createVar(DashStrings.tcmcSigmaName)))))); + List body = new ArrayList(); + body.add(b); + List emptyDecls = new ArrayList(); + // d.alloyString += d.addPredSimple(DashStrings.reachabilityName, emptyDecls, body); + d.alloyString += d.addFactSimple(DashStrings.reachabilityName, body); + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 58164b8d9..9817fcb16 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -67,14 +67,16 @@ public static void addTransPre(DashModule d, String tfqn) { if (d.getTransWhen(tfqn) != null) body.add(translateExpr(d.getTransWhen(tfqn),d)); - // has a scope that is orthogonal to any scopes used - List nonO = d.nonOrthogonalScopesOf(tfqn); - for (int i=0;i <= d.getMaxDepthParams(); i++) { - List u = DashRef.hasNumParams(nonO,i).stream() - .map(x -> translateDashRefToArrow(replaceScope(x))) - .collect(Collectors.toList()); - for (Expr x: u) body.add(createNot(createIn(x,curScopesUsed(i)))); - } + //if (d.hasConcurrency()) { + // has a scope that is orthogonal to any scopes used + List nonO = d.nonOrthogonalScopesOf(tfqn); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List u = DashRef.hasNumParams(nonO,i).stream() + .map(x -> translateDashRefToArrow(replaceScope(x))) + .collect(Collectors.toList()); + for (Expr x: u) body.add(createNot(createIn(x,curScopesUsed(i)))); + } + //} // event trigger // only one triggering event @@ -113,7 +115,7 @@ public static void addTransPre(DashModule d, String tfqn) { args = curParamVars(d.getTransParamsIdx(t), d.getTransParams(t)); body.add(createNot(createPredCall(translateFQN(t)+DashStrings.preName, args))); } - + //System.out.println(body); d.alloyString += d.addPredSimple(tout+DashStrings.preName, curParamsDecls(prsIdx,params), body); d.alloyString += "\n"; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 0cc30ae04..3aa5ccb37 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -360,6 +360,7 @@ public String addVarLoneSigSimple(String name, ExprVar typ) { */ public String addPredSimple(String name, List decls, List eList) { Expr body = createAndFromList(eList); + //System.out.println(body); addFunc(Pos.UNKNOWN, Pos.UNKNOWN, createVar(name), null, decls, null, body); String s = new String(); s += DashStrings.predName + " " + name; From 8945158ecda22530fc0ec2670a310fb0248ad5be Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 22 Jun 2023 19:32:27 -0400 Subject: [PATCH 075/129] reachability as a predicate (rather than a fact) --- .../src/main/resources/models/util/tmcfc.als | 81 ------------------- .../dashtoalloy/AddReachabilityFact.java | 55 ------------- .../watform/dashtoalloy/AddTransPre.java | 1 + .../watform/dashtoalloy/DashToAlloy.java | 2 +- 4 files changed, 2 insertions(+), 137 deletions(-) delete mode 100755 org.alloytools.alloy.core/src/main/resources/models/util/tmcfc.als delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityFact.java diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/tmcfc.als b/org.alloytools.alloy.core/src/main/resources/models/util/tmcfc.als deleted file mode 100755 index cf9cb250d..000000000 --- a/org.alloytools.alloy.core/src/main/resources/models/util/tmcfc.als +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Original work Copyright (c) 2017, Amirhossein Vakili, Sabria Farheen, - * Nancy A. Day, Ali Abbassi - * Modified work Copyright (c) 2019, Mitchell Kember, Thi My Linh Tran, - * Yuezhou Gao, Nancy A. Day - * This file is part of the TCMC-Path project, which is released under the - * FreeBSD License. See LICENSE.txt for full license details, or visit - * https://opensource.org/licenses/BSD-2-Clause. - */ - -module tcmcfc[S] - -// ********** Kripke structure ************************************************* - -one sig TS { - S0: some S, - sigma: S -> S, - FC: set S -} - -// ********** Model setup functions ******************************************** - -// Set by users in their model files. - -fun initialState: S { TS.S0 } - -fun nextState: S -> S { TS.sigma } - -fun fc: S { TS.FC } - -// ********** Helper functions ************************************************* - -private fun domainRes[R: S -> S, X: S]: S -> S { X <: R } -private fun id[X:S]: S -> S { domainRes[iden,X] } - -// ********** Fair states definition ******************************************* - -// Fair is EcG true. -private fun Fair: S { - let R = TS.sigma | - *R.((^R & id[S]).S & TS.FC) -} - -// ********** Logical operators ************************************************ - -fun not_[phi: S]: S { S - phi } -fun and_[phi, si: S]: S { phi & si } -fun or_[phi, si: S]: S { phi + si } -fun imp_[phi, si: S]: S { not_[phi] + si } - -// ********** Temporal operators *********************************************** - -fun ex[phi: S]: S { TS.sigma.(phi & Fair) } - -fun ax[phi:S]: S { not_[ex[not_[phi]]] } - -fun ef[phi: S]: S { (*(TS.sigma)).(phi & Fair) } - -fun eg[phi:S]: S { - let R = domainRes[TS.sigma, phi] | - *R.(((^R & id[S]).S & TS.FC)) -} - -fun af[phi: S]: S { not_[eg[not_[phi]]] } - -fun ag[phi: S]: S { not_[ef[not_[phi]]] } - -fun eu[phi, si: S]: S { - (*(domainRes[TS.sigma, phi])).(si & Fair) -} - -// TODO: Why was this only defined in ctlfc.als and not ctl.als? -fun au[phi, si: S]: S { - not_[or_[eg[not_[si]], - eu[not_[si], not_[or_[phi, si]]]]] -} - -// ********** Model checking constraint **************************************** - -// Called by users for model checking in their model file. -pred ctlfc_mc[phi: S] { TS.S0 in phi } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityFact.java deleted file mode 100644 index ed2f922f2..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityFact.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Every snapshot is reachable from an initial snapshot - * fact reachabilityAxiom { - * all s : Snapshot | s in Snapshot .(( initial) <: * (sigma)) - * } - */ - -package ca.uwaterloo.watform.dashtoalloy; - -import java.util.Collections; -import java.util.stream.Collectors; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.stream.IntStream; - -import edu.mit.csail.sdg.ast.Decl; -//import edu.mit.csail.sdg.ast.ExprVar; -import edu.mit.csail.sdg.ast.Expr; - -import ca.uwaterloo.watform.core.DashOptions; -import ca.uwaterloo.watform.core.DashStrings; -import ca.uwaterloo.watform.core.DashUtilFcns; -import ca.uwaterloo.watform.core.DashErrors; -import ca.uwaterloo.watform.core.DashRef; - -// shortens the code to import these statically -import static ca.uwaterloo.watform.core.DashFQN.*; -import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; - -//import ca.uwaterloo.watform.alloyasthelper.DeclExt; -//import ca.uwaterloo.watform.alloyasthelper.ExprToString; - -import ca.uwaterloo.watform.parser.DashModule; -import ca.uwaterloo.watform.parser.CompModuleHelper; - -import static ca.uwaterloo.watform.dashtoalloy.Common.*; - -public class AddReachabilityFact { - - public static void addReachabilityFact(DashModule d) { - assert(!DashOptions.isElectrum && !DashOptions.isTraces); - Expr b = createAll(curDecls(), - createIn(curVar(), - createJoin(createVar(DashStrings.snapshotName), - createDomainRes(createVar(DashStrings.tcmcInitialStateName), - createReflexiveTransitiveClosure(createVar(DashStrings.tcmcSigmaName)))))); - List body = new ArrayList(); - body.add(b); - List emptyDecls = new ArrayList(); - // d.alloyString += d.addPredSimple(DashStrings.reachabilityName, emptyDecls, body); - d.alloyString += d.addFactSimple(DashStrings.reachabilityName, body); - } -} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index 9817fcb16..f61a347c2 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -116,6 +116,7 @@ public static void addTransPre(DashModule d, String tfqn) { body.add(createNot(createPredCall(translateFQN(t)+DashStrings.preName, args))); } //System.out.println(body); + //body.add(createNullExpr()); d.alloyString += d.addPredSimple(tout+DashStrings.preName, curParamsDecls(prsIdx,params), body); d.alloyString += "\n"; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java index 1b5aefaa3..1f7f24dc8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/DashToAlloy.java @@ -34,7 +34,7 @@ public static void translate(DashModule d) { if (DashOptions.singleEventInput) AddSingleEventInputFact.addSingleEventInputFact(d); if (DashOptions.isTcmc && DashOptions.reachability) - AddReachabilityFact.addReachabilityFact(d); + AddReachabilityPred.addReachabilityPred(d); if (DashOptions.isTraces) AddTracesFact.addTracesFact(d); else if (DashOptions.isTcmc) From 7517894580cbcd0ad44a60262eeeaabf753c43c6 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 22 Jun 2023 20:32:54 -0400 Subject: [PATCH 076/129] added file --- .../watform/dashtoalloy/AddInit.java | 11 +++- .../dashtoalloy/AddReachabilityPred.java | 55 +++++++++++++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 54e6a94e2..a6252e303 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -56,9 +56,14 @@ public static void addInit(DashModule d) { body.add(createEquals( curScopesUsed(i), createNoneArrow(i))); - body.add(createEquals( - curTransTaken(i), - createNoneArrow(i))); + if (i == 0 ) + body.add(createEquals( + curTransTaken(i), + createVar(DashStrings.noTransName))); + else + body.add(createEquals( + curTransTaken(i), + createNoneArrow(i))); // no limits on initial set of events except that they must be environmental //s.events1 :> internalEvents = none -> none if (d.hasInternalEventsAti(i)) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java new file mode 100644 index 000000000..de997cf84 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddReachabilityPred.java @@ -0,0 +1,55 @@ +/* + * + * Every snapshot is reachable from an initial snapshot + * fact reachabilityAxiom { + * all s : Snapshot | s in Snapshot .(( initial) <: * (sigma)) + * } + */ + +package ca.uwaterloo.watform.dashtoalloy; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.IntStream; + +import edu.mit.csail.sdg.ast.Decl; +//import edu.mit.csail.sdg.ast.ExprVar; +import edu.mit.csail.sdg.ast.Expr; + +import ca.uwaterloo.watform.core.DashOptions; +import ca.uwaterloo.watform.core.DashStrings; +import ca.uwaterloo.watform.core.DashUtilFcns; +import ca.uwaterloo.watform.core.DashErrors; +import ca.uwaterloo.watform.core.DashRef; + +// shortens the code to import these statically +import static ca.uwaterloo.watform.core.DashFQN.*; +import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; + +//import ca.uwaterloo.watform.alloyasthelper.DeclExt; +//import ca.uwaterloo.watform.alloyasthelper.ExprToString; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.parser.CompModuleHelper; + +import static ca.uwaterloo.watform.dashtoalloy.Common.*; + +public class AddReachabilityPred { + + public static void addReachabilityPred(DashModule d) { + assert(!DashOptions.isElectrum && !DashOptions.isTraces); + Expr b = createAll(curDecls(), + createIn(curVar(), + createJoin(createVar(DashStrings.snapshotName), + createDomainRes(createVar(DashStrings.tcmcInitialStateName), + createReflexiveTransitiveClosure(createVar(DashStrings.tcmcSigmaName)))))); + List body = new ArrayList(); + body.add(b); + List emptyDecls = new ArrayList(); + // d.alloyString += d.addPredSimple(DashStrings.reachabilityName, emptyDecls, body); + d.alloyString += d.addPredSimple(DashStrings.reachabilityName, emptyDecls, body); + } +} From e475e7dbba405bddc0e4082a936bea1fb0a677f7 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Thu, 22 Jun 2023 20:33:19 -0400 Subject: [PATCH 077/129] added tcmcfc.als file --- .../src/main/resources/models/util/tcmcfc.als | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100755 org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc.als diff --git a/org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc.als b/org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc.als new file mode 100755 index 000000000..cf9cb250d --- /dev/null +++ b/org.alloytools.alloy.core/src/main/resources/models/util/tcmcfc.als @@ -0,0 +1,81 @@ +/* + * Original work Copyright (c) 2017, Amirhossein Vakili, Sabria Farheen, + * Nancy A. Day, Ali Abbassi + * Modified work Copyright (c) 2019, Mitchell Kember, Thi My Linh Tran, + * Yuezhou Gao, Nancy A. Day + * This file is part of the TCMC-Path project, which is released under the + * FreeBSD License. See LICENSE.txt for full license details, or visit + * https://opensource.org/licenses/BSD-2-Clause. + */ + +module tcmcfc[S] + +// ********** Kripke structure ************************************************* + +one sig TS { + S0: some S, + sigma: S -> S, + FC: set S +} + +// ********** Model setup functions ******************************************** + +// Set by users in their model files. + +fun initialState: S { TS.S0 } + +fun nextState: S -> S { TS.sigma } + +fun fc: S { TS.FC } + +// ********** Helper functions ************************************************* + +private fun domainRes[R: S -> S, X: S]: S -> S { X <: R } +private fun id[X:S]: S -> S { domainRes[iden,X] } + +// ********** Fair states definition ******************************************* + +// Fair is EcG true. +private fun Fair: S { + let R = TS.sigma | + *R.((^R & id[S]).S & TS.FC) +} + +// ********** Logical operators ************************************************ + +fun not_[phi: S]: S { S - phi } +fun and_[phi, si: S]: S { phi & si } +fun or_[phi, si: S]: S { phi + si } +fun imp_[phi, si: S]: S { not_[phi] + si } + +// ********** Temporal operators *********************************************** + +fun ex[phi: S]: S { TS.sigma.(phi & Fair) } + +fun ax[phi:S]: S { not_[ex[not_[phi]]] } + +fun ef[phi: S]: S { (*(TS.sigma)).(phi & Fair) } + +fun eg[phi:S]: S { + let R = domainRes[TS.sigma, phi] | + *R.(((^R & id[S]).S & TS.FC)) +} + +fun af[phi: S]: S { not_[eg[not_[phi]]] } + +fun ag[phi: S]: S { not_[ef[not_[phi]]] } + +fun eu[phi, si: S]: S { + (*(domainRes[TS.sigma, phi])).(si & Fair) +} + +// TODO: Why was this only defined in ctlfc.als and not ctl.als? +fun au[phi, si: S]: S { + not_[or_[eg[not_[si]], + eu[not_[si], not_[or_[phi, si]]]]] +} + +// ********** Model checking constraint **************************************** + +// Called by users for model checking in their model file. +pred ctlfc_mc[phi: S] { TS.S0 in phi } From 77fbbef5e1e5058f247017b55afc49309ed7af43 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 22 Jun 2023 20:59:30 -0400 Subject: [PATCH 078/129] added tla command and to make empty tla file in the same folder as dsh file and write the hello world into it --- cnf/.project | 17 ++++++ .../org.eclipse.buildship.core.prefs | 2 + org.alloytools.alloy.application/.classpath | 17 ++++-- org.alloytools.alloy.application/.project | 17 ++++++ .../org.eclipse.buildship.core.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 6 +- .../ca/uwaterloo/watform/dash4whole/Dash.java | 59 +++++++++++++------ org.alloytools.alloy.core/.classpath | 22 ++++--- org.alloytools.alloy.core/.project | 17 ++++++ .../org.eclipse.buildship.core.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 6 +- org.alloytools.alloy.dash/.classpath | 9 ++- org.alloytools.alloy.dash/.project | 4 +- .../watform/dashtotla/DashtoTLA.java | 12 ++++ .../watform/mainfunctions/MainFunctions.java | 5 ++ org.alloytools.alloy.dist/.classpath | 17 ++++-- org.alloytools.alloy.dist/.project | 17 ++++++ .../org.eclipse.buildship.core.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 6 +- org.alloytools.alloy.extra/.classpath | 17 ++++-- org.alloytools.alloy.extra/.project | 17 ++++++ .../org.eclipse.buildship.core.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 6 +- 23 files changed, 226 insertions(+), 55 deletions(-) create mode 100644 cnf/.settings/org.eclipse.buildship.core.prefs create mode 100644 org.alloytools.alloy.application/.settings/org.eclipse.buildship.core.prefs create mode 100644 org.alloytools.alloy.core/.settings/org.eclipse.buildship.core.prefs create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java create mode 100644 org.alloytools.alloy.dist/.settings/org.eclipse.buildship.core.prefs create mode 100644 org.alloytools.alloy.extra/.settings/org.eclipse.buildship.core.prefs diff --git a/cnf/.project b/cnf/.project index 0b7164229..b0d9ea35d 100644 --- a/cnf/.project +++ b/cnf/.project @@ -5,6 +5,11 @@ + + org.eclipse.buildship.core.gradleprojectbuilder + + + org.eclipse.jdt.core.javabuilder @@ -13,5 +18,17 @@ org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + + 1687449709131 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/cnf/.settings/org.eclipse.buildship.core.prefs b/cnf/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 000000000..b1886adb4 --- /dev/null +++ b/cnf/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/org.alloytools.alloy.application/.classpath b/org.alloytools.alloy.application/.classpath index bcafe71e5..ae30f860a 100644 --- a/org.alloytools.alloy.application/.classpath +++ b/org.alloytools.alloy.application/.classpath @@ -1,12 +1,19 @@ - - - - + + + + + + + + + - + + + diff --git a/org.alloytools.alloy.application/.project b/org.alloytools.alloy.application/.project index 2f98f1715..1d348fb1e 100644 --- a/org.alloytools.alloy.application/.project +++ b/org.alloytools.alloy.application/.project @@ -10,6 +10,11 @@ + + org.eclipse.buildship.core.gradleprojectbuilder + + + bndtools.core.bndbuilder @@ -19,5 +24,17 @@ org.eclipse.jdt.core.javanature bndtools.core.bndnature + org.eclipse.buildship.core.gradleprojectnature + + + 1687449709165 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/org.alloytools.alloy.application/.settings/org.eclipse.buildship.core.prefs b/org.alloytools.alloy.application/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 000000000..b1886adb4 --- /dev/null +++ b/org.alloytools.alloy.application/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/org.alloytools.alloy.application/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.application/.settings/org.eclipse.jdt.core.prefs index 2f809de6d..0a692051b 100644 --- a/org.alloytools.alloy.application/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.application/.settings/org.eclipse.jdt.core.prefs @@ -26,9 +26,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.compliance=17 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -134,7 +134,7 @@ org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.processAnnotations=disabled org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.source=17 org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index a5343e401..4c17183c2 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -5,6 +5,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.Files; +import java.nio.file.StandardOpenOption; import java.io.BufferedWriter; import java.io.File; @@ -34,7 +35,7 @@ public class Dash { @SuppressWarnings("resource" ) - public static void executeCommands(CompModule c, Integer cmdnum, A4Reporter rep) { + public static void executeCommands(CompModule c, Integer commandNumber, A4Reporter rep) { // Choose some default options for how you want to execute the commands A4Options options = new A4Options(); @@ -42,7 +43,7 @@ public static void executeCommands(CompModule c, Integer cmdnum, A4Reporter rep) // this is an annoying way to convert a list to an array Integer i = 1; for (Command cmd : commands) { - if (i == cmdnum | cmdnum == 0) { + if (i == commandNumber | commandNumber == 0) { System.out.println("Executing command: " + cmd); A4Solution ans = null; try { @@ -58,23 +59,24 @@ public static void executeCommands(CompModule c, Integer cmdnum, A4Reporter rep) } i++; } - if (cmdnum >= i) { - System.err.println("Command number: " + cmdnum + " does not exist in file"); + if (commandNumber >= i) { + System.err.println("Command number: " + commandNumber + " does not exist in file"); } } public static void main(String args[]) throws Exception { if(args.length == 0) { - System.out.println("Arguments: (-m traces|tcmc|electrum) (-single) (-reach) (-c #) (-p) (-t) (-r) filename(s)"); + System.out.println("Arguments: (-m traces|tcmc|electrum) (-single) (-reach) (-c #) (-p) (-t) (-tla) (-r) filename(s)"); System.out.println("-m traces|tcmc|electrum is verification method"); System.out.println("-single includes single event input fact"); System.out.println("-reach includes reachability fact (for tcmc only)"); System.out.println("-enough includes enoughOperations pred"); - System.out.println("-c # is cmdnum to execute"); + System.out.println("-c # is commandNumber to execute"); System.out.println("-t is translateOnly"); System.out.println("-r is resolveOnly"); System.out.println("-e is echo file from internal parsed data"); + System.out.println("-tla produces a translation to TLA+, with the same file name as the dash file, in the same folder as the original dash file"); System.out.println("expects .dsh or .als file"); System.out.println("if given a .als files, it ignores other options and runs all its commands"); System.exit(0); @@ -87,10 +89,11 @@ public static void main(String args[]) throws Exception { // default values String method = "traces"; - Integer cmdnum = 0; - Boolean translateOnly = false; - Boolean printOnly = false; - Boolean resolveOnly = false; + int commandNumber = 0; + boolean translateOnly = false; + boolean printOnly = false; + boolean resolveOnly = false; + boolean translateTLA = false; for (int i=0; i - - - - + + + + + + + + + - + - + + - + + + diff --git a/org.alloytools.alloy.core/.project b/org.alloytools.alloy.core/.project index 36737ffb6..fc4184230 100644 --- a/org.alloytools.alloy.core/.project +++ b/org.alloytools.alloy.core/.project @@ -10,6 +10,11 @@ + + org.eclipse.buildship.core.gradleprojectbuilder + + + bndtools.core.bndbuilder @@ -19,5 +24,17 @@ org.eclipse.jdt.core.javanature bndtools.core.bndnature + org.eclipse.buildship.core.gradleprojectnature + + + 1687449709176 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/org.alloytools.alloy.core/.settings/org.eclipse.buildship.core.prefs b/org.alloytools.alloy.core/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 000000000..b1886adb4 --- /dev/null +++ b/org.alloytools.alloy.core/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/org.alloytools.alloy.core/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.core/.settings/org.eclipse.jdt.core.prefs index 2f809de6d..0a692051b 100644 --- a/org.alloytools.alloy.core/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.core/.settings/org.eclipse.jdt.core.prefs @@ -26,9 +26,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.compliance=17 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -134,7 +134,7 @@ org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.processAnnotations=disabled org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.source=17 org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME diff --git a/org.alloytools.alloy.dash/.classpath b/org.alloytools.alloy.dash/.classpath index c50c180fc..d0ac3bda3 100644 --- a/org.alloytools.alloy.dash/.classpath +++ b/org.alloytools.alloy.dash/.classpath @@ -12,7 +12,14 @@ - + + + + + + + + diff --git a/org.alloytools.alloy.dash/.project b/org.alloytools.alloy.dash/.project index 91acaca33..43454e74a 100644 --- a/org.alloytools.alloy.dash/.project +++ b/org.alloytools.alloy.dash/.project @@ -28,12 +28,12 @@ - 1678133835920 + 1687449709202 30 org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java new file mode 100644 index 000000000..36695fa44 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -0,0 +1,12 @@ +package ca.uwaterloo.watform.dashtotla; + +import ca.uwaterloo.watform.parser.DashModule; + +public class DashtoTLA +{ + public static String translate(DashModule d) + { + System.out.println("Hello World"); + return "Hello World"; + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index 1a2660df0..5154e6851 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -18,6 +18,7 @@ import ca.uwaterloo.watform.core.DashErrors; import ca.uwaterloo.watform.parser.DashUtil; import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.dashtotla.DashtoTLA; // no io in these! @@ -64,6 +65,10 @@ public static DashModule translate(DashModule d, A4Reporter rep) { } return d; } + public static String translateTLA(DashModule d) + { + return DashtoTLA.translate(d); + } public static CompModule resolveAlloy(CompModule c, A4Reporter rep) { CompModule o = null; diff --git a/org.alloytools.alloy.dist/.classpath b/org.alloytools.alloy.dist/.classpath index bcafe71e5..ae30f860a 100644 --- a/org.alloytools.alloy.dist/.classpath +++ b/org.alloytools.alloy.dist/.classpath @@ -1,12 +1,19 @@ - - - - + + + + + + + + + - + + + diff --git a/org.alloytools.alloy.dist/.project b/org.alloytools.alloy.dist/.project index 49081730a..abea09f05 100644 --- a/org.alloytools.alloy.dist/.project +++ b/org.alloytools.alloy.dist/.project @@ -10,6 +10,11 @@ + + org.eclipse.buildship.core.gradleprojectbuilder + + + bndtools.core.bndbuilder @@ -19,5 +24,17 @@ org.eclipse.jdt.core.javanature bndtools.core.bndnature + org.eclipse.buildship.core.gradleprojectnature + + + 1687449709325 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/org.alloytools.alloy.dist/.settings/org.eclipse.buildship.core.prefs b/org.alloytools.alloy.dist/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 000000000..b1886adb4 --- /dev/null +++ b/org.alloytools.alloy.dist/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/org.alloytools.alloy.dist/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.dist/.settings/org.eclipse.jdt.core.prefs index 6f9e91618..74a30a06a 100644 --- a/org.alloytools.alloy.dist/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.dist/.settings/org.eclipse.jdt.core.prefs @@ -26,9 +26,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.compliance=17 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -133,7 +133,7 @@ org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.processAnnotations=disabled -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.source=17 org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME diff --git a/org.alloytools.alloy.extra/.classpath b/org.alloytools.alloy.extra/.classpath index bcafe71e5..ae30f860a 100644 --- a/org.alloytools.alloy.extra/.classpath +++ b/org.alloytools.alloy.extra/.classpath @@ -1,12 +1,19 @@ - - - - + + + + + + + + + - + + + diff --git a/org.alloytools.alloy.extra/.project b/org.alloytools.alloy.extra/.project index 1fdd108b6..a6cfe8577 100644 --- a/org.alloytools.alloy.extra/.project +++ b/org.alloytools.alloy.extra/.project @@ -10,6 +10,11 @@ + + org.eclipse.buildship.core.gradleprojectbuilder + + + bndtools.core.bndbuilder @@ -19,5 +24,17 @@ org.eclipse.jdt.core.javanature bndtools.core.bndnature + org.eclipse.buildship.core.gradleprojectnature + + + 1687449709338 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/org.alloytools.alloy.extra/.settings/org.eclipse.buildship.core.prefs b/org.alloytools.alloy.extra/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 000000000..b1886adb4 --- /dev/null +++ b/org.alloytools.alloy.extra/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs index 2f809de6d..0a692051b 100644 --- a/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs @@ -26,9 +26,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.compliance=17 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -134,7 +134,7 @@ org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.processAnnotations=disabled org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.compiler.source=17 org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,NORMAL org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME From a8711c804f068c7b21f526a6c7997addb91b8f9e Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 23 Jun 2023 09:13:24 -0400 Subject: [PATCH 079/129] fixed allSnapshotsDifferentFact to include the var/buffer values must be the same --- .../dashtoalloy/AddAllSnapshotsDifferentFact.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java index 1d30295d3..df0f9f1c8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java @@ -45,7 +45,7 @@ public static void addAllSnapshotsDifferentFact(DashModule d) { for (int i = 0; i <= d.getMaxDepthParams(); i++) { body.add(createEquals(curConf(i),nextConf(i))); // s.scopesUsedi = sn.scopesUsedi - if (d.hasConcurrency()) + //if (d.hasConcurrency()) body.add(createEquals(curScopesUsed(i),nextScopesUsed(i))); body.add(createEquals(curTransTaken(i),nextTransTaken(i))); if (d.hasInternalEventsAti(i)) @@ -53,6 +53,13 @@ public static void addAllSnapshotsDifferentFact(DashModule d) { } if (d.hasConcurrency()) body.add(createEquals(curStable(),nextStable())); + List allVarsAndBuffers = d.getAllVarNames(); + allVarsAndBuffers.addAll(d.getAllBufferNames()); + for (String v: allVarsAndBuffers) { + body.add(createEquals(curJoinExpr(createVar(translateFQN(v))), nextJoinExpr(createVar(translateFQN(v))))); + } + + //TODO: have to add something for all dynamic variables !!!! e = createAll(curNextDecls(), createImplies(createAndList(body), createEquals(curVar(), nextVar()))); body = new ArrayList(); body.add(e); From 74d277e84415dc1553277982bb3b6471b5e337d8 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 23 Jun 2023 17:29:39 -0400 Subject: [PATCH 080/129] fixed bracketing bug in output --- .../watform/alloyasthelper/ExprHelper.java | 6 +- .../watform/alloyasthelper/ExprToString.java | 161 +++++------------- .../watform/parser/CompModuleHelper.java | 1 + 3 files changed, 45 insertions(+), 123 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index 6ee2438f7..b0b15f41f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -121,10 +121,14 @@ public static Expr getSub(Expr e) { DashErrors.getSubNotUnary(e.getClass().getName()); return null; } } - public static ExprBinary.Op getOp(Expr e) { + public static ExprBinary.Op getBinaryOp(Expr e) { assert(e instanceof ExprBinary); return ((ExprBinary) e).op; } + public static ExprUnary.Op getUnaryOp(Expr e) { + assert(e instanceof ExprUnary); + return ((ExprUnary) e).op; + } public static Expr getCond(Expr e) { assert(e instanceof ExprITE); return ((ExprITE) e).cond; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java index fcfc9b1c8..7b002ff4f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprToString.java @@ -36,6 +36,7 @@ .brk(int spacesifnotbroken, int spacestoaddorsubtractfromindentifbroken) .brk(x) = .brk(x,0) .brk() = .brk(1,0) + .close() - finish the string consistent block means if break required then all have breaks inconsistent block means put as much as possible on a line @@ -131,26 +132,8 @@ private Boolean isBinary(Expr e) { */ private void ExprBinaryToOut(ExprBinary expr) { if (DashRef.isDashRef(expr)) { - // Root/A/B[exp1, exp2]/v1 - /* - String v = DashRef.getName(expr); - String n = DashFQN.chopNameFromFQN(v); - String prefix = DashFQN.chopPrefixFromFQN(v); - //TODO: should do proper pretty printing for these! - String s = prefix; - s += "["; - List el = new ArrayList(); - List paramValues = - DashRef.getParamValues(expr).stream() - .map(i -> i.toString()) - .collect(Collectors.toList()); - Collections.reverse(paramValues); - s += DashUtilFcns.strCommaList(paramValues); - s += "]/" + v; - */ out.print(expr.toString()); - } - else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { + } else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { out.print("seq "); out.beginC(2); ExprToOut(expr.right); @@ -159,58 +142,31 @@ else if (expr.op == ExprBinary.Op.ISSEQ_ARROW_LONE) { } else if (expr.op == ExprBinary.Op.JOIN) { // there are really long join expressions //out.beginI(2); - addBracketsIfNeededNoBlocks(getLeft(expr)); + addBracketsIfNeeded(getLeft(expr)); //out.brk(1,0); out.print(expr.op); //out.brk(1,0); - addBracketsIfNeededNoBlocks(getRight(expr)); + addBracketsIfNeeded(getRight(expr)); //out.end(); } else { out.beginI(2); addBracketsIfNeeded(getLeft(expr)); - //out.brk(1,0); - out.print(" "); + out.brk(1,0); out.print(expr.op); out.brk(1,0); addBracketsIfNeeded(getRight(expr)); - out.end(); - - /* - } else if (expr.op == ExprBinary.Op.IMPLIES) { - ExprToOut(expr.left); - out.print(" => ").print("{ "); - ExprToOut(expr.right); - out.print(" } "); - } - - // This used to ensure that binary expressions have proper braces around them - } else if ( isBinary(expr.right) || isBinary(expr.left) ) { - if ( isBinary(expr.left) && !(exprOp(expr.left) == exprOp(expr)) && !(exprOp(expr.left) == ExprBinary.Op.JOIN)) { - out.print('{').print(' '); - ExprToOut(expr.left); - out.print(' ').print("}").print(' ').print(expr.op).print(' '); - } else { - ExprToOut(expr.left); - out.print(' ').print(expr.op).print(' '); - } - if (isBinary(expr.right) && !({exprOp}(expr.right) == exprOp(expr)) && !(exprOp(expr.right) == ExprBinary.Op.JOIN)){ - out.print('{').print(' '); - ExprToOut(expr.right); - out.print(' ').print("}"); - } else { - ExprToOut(expr.right); - } - } - else { - ExprToOut(expr.left); - out.print(' ').print(expr.op).print(' '); - ExprToOut(expr.right); - */ + out.end(); } - } +/* private void addBracketsIfNeededNoBlocks(Expr expr) { + Boolean bracketNotNeeded = + isExprVar(expr) || + (isExprUnary(expr) && + !isExprCard(expr)&& + !isExprRClosure(expr) && + !isExprClosure(expr)); if (!(isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr) ))) { //out.beginC(2); out.print("("); @@ -221,24 +177,27 @@ private void addBracketsIfNeededNoBlocks(Expr expr) { //out.end(); } } +*/ private void addBracketsIfNeeded(Expr expr) { - if (!(isExprVar(expr) || + Boolean bracketsNotNeeded = + isExprVar(expr) || (isExprUnary(expr) && !isExprCard(expr)&& !isExprRClosure(expr) && - !isExprClosure(expr)))) { - out.beginC(2); - out.print("("); - } + !isExprClosure(expr)); + if (!bracketsNotNeeded) { + //out.beginC(2); + out.print("("); + } + //System.out.println("---- class: " + expr.getClass().toString()); + //if (isExprUnary(expr)) System.out.println(getUnaryOp(expr).toString()); + //System.out.println("bracketsNotNeeded: " + bracketsNotNeeded.toString()); + //System.out.println(expr.toString()); ExprToOut(expr); - if (!(isExprVar(expr) || - (isExprUnary(expr) && - !isExprCard(expr) && - !isExprRClosure(expr) && - !isExprClosure(expr)) )) { + if (!bracketsNotNeeded) { out.print(")"); - out.end(); + //out.end(); } } @@ -247,32 +206,6 @@ private void ExprBadJoinToOut(ExprBadJoin expr) { out.print('.'); addBracketsIfNeeded(expr.right); } - - /* - private void ExprBinaryJoinToOut(ExprBinary expr) { - // The Alloy resolve dot joins (this) to a variable reference in a variable. We should not bring the ("this") - // We also do not print (Snapshot <: ...) - boolean clean = (expr.left.toString().equals("this") && isAfterAlloyResolveAll); - - if (expr.right.toString().charAt(0) == '(') { - if (!clean) { - ExprToOut(expr.left); - out.print(expr.op); - } - ExprToOut(expr.right); - } - else { - if (!clean) { - ExprToOut(expr.left); - out.print(expr.op).print(' ').print('('); - } - ExprToOut(expr.right); - if (!clean) { - out.print(")"); - } - } - } - */ private void ExprCallToOut(ExprCall expr) { out.print(cleanLabel(expr.fun.label)); @@ -327,7 +260,16 @@ private void ExprITEToOut(ExprITE expr) { } private void ExprLetToOut(ExprLet expr) { - out.print("(let ").print(cleanLabel(expr.var.label)).print("= ").print(expr.toString()).print(" | "); + out.print("(let"); + out.brk(1,0); + out.print(cleanLabel(expr.var.label)); + out.brk(1,0); + out.print("="); + out.brk(1,0); + ExprToOut(expr.expr); + out.brk(1,0); + out.print("|"); + out.brk(1,0); out.beginC(2); ExprToOut(expr.sub); out.end(); @@ -465,7 +407,8 @@ private void ExprUnaryToOut(ExprUnary expr) { addBracketsIfNeeded(expr.sub); break; case NOOP : - ExprToOut(expr.sub); + // { expr } is parsed as NOOP (expr) + addBracketsIfNeeded(expr.sub); break; default : // many operators print okay @@ -477,19 +420,6 @@ private void ExprUnaryToOut(ExprUnary expr) { } - /* - private void ExprVarToOut(ExprVar expr) { - out.print(cleanLabel(expr.label)); - } - - private void SigToOut(Sig sig) { - out.print(cleanLabel(sig.label)); - } - - private void FieldToOut(Field field) { - out.print("(").print(cleanLabel(field.label)).print(")"); - } - */ // Helper method to print a list of declarations private void DeclsToOut(List decls) { @@ -515,12 +445,6 @@ private void DeclToOut(Decl decl) { if (decl.disjoint != null) { out.print("disj").print(" "); } - //StringJoiner namesJoiner = new StringJoiner(","); - //decl.names.forEach(name -> namesJoiner.add(cleanLabel(name.label))); - //if (!first) { - // out.print(","); - //} - //first = false; if (decl.isVar != null) { out.print(DashStrings.varName + " "); } @@ -543,12 +467,5 @@ private String cleanLabel(String label) { return label; } - /* - private ExprBinary.Op exprOp (Expr expr) { - if (expr instanceof ExprBinary) - return ((ExprBinary) expr).op; - return null; - } - */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 3aa5ccb37..2eb70c339 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -384,6 +384,7 @@ public String addPredSimple(String name, List decls, List eList) { StringJoiner sj = new StringJoiner("\n" + tab); for (Expr e: eList) { //ExprToString eToString = new ExprToString(false); + //System.out.println(ppExpr(e)); sj.add(ppExpr(e)); } s += sj.toString(); From d8c83e4024fa9f9f0e979fbb48928ea3ea470ded Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 23 Jun 2023 17:57:33 -0400 Subject: [PATCH 081/129] added optimization: remove all states if there is only one state --- .../AddAllSnapshotsDifferentFact.java | 3 +- .../watform/dashtoalloy/AddInit.java | 20 +++++----- .../dashtoalloy/AddSnapshotSignature.java | 23 ++++++----- .../dashtoalloy/AddSpaceSignatures.java | 24 +++++++----- .../watform/dashtoalloy/AddStutter.java | 3 +- .../AddTransIsEnabledAfterStep.java | 24 ++++-------- .../watform/dashtoalloy/AddTransPost.java | 38 ++++++++++--------- .../watform/dashtoalloy/AddTransPre.java | 15 ++++---- .../uwaterloo/watform/parser/DashModule.java | 3 ++ .../uwaterloo/watform/parser/StateTable.java | 3 ++ 10 files changed, 84 insertions(+), 72 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java index df0f9f1c8..0f3c4dff7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java @@ -43,7 +43,8 @@ public static void addAllSnapshotsDifferentFact(DashModule d) { List body = new ArrayList(); Expr e; for (int i = 0; i <= d.getMaxDepthParams(); i++) { - body.add(createEquals(curConf(i),nextConf(i))); + if (!d.hasOnlyOneState()) + body.add(createEquals(curConf(i),nextConf(i))); // s.scopesUsedi = sn.scopesUsedi //if (d.hasConcurrency()) body.add(createEquals(curScopesUsed(i),nextScopesUsed(i))); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index a6252e303..471c00f19 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -41,15 +41,17 @@ public static void addInit(DashModule d) { List prs = d.getAllParamsInOrder(); List body = new ArrayList(); - // forall i. confi = default entries - List entered = d.initialEntered(); - if (entered.isEmpty()) DashErrors.noInitialEntered(); - for (int i=0;i <= d.getMaxDepthParams(); i++) { - List ent = DashRef.hasNumParams(entered,i).stream() - .map(x -> translateDashRefToArrow(x)) - .collect(Collectors.toList()); - if (!ent.isEmpty()) body.add(createEquals(curConf(i),createUnionList(ent))); - else body.add(createEquals(curConf(i), createNone())); + if (!d.hasOnlyOneState()) { + // forall i. confi = default entries + List entered = d.initialEntered(); + if (entered.isEmpty()) DashErrors.noInitialEntered(); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List ent = DashRef.hasNumParams(entered,i).stream() + .map(x -> translateDashRefToArrow(x)) + .collect(Collectors.toList()); + if (!ent.isEmpty()) body.add(createEquals(curConf(i),createUnionList(ent))); + else body.add(createEquals(curConf(i), createNone())); + } } for (int i = 0; i <= d.getMaxDepthParams(); i++) { // scopesUsedi = none diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 874104bd6..997da82ee 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -38,7 +38,8 @@ public static void addSnapshotSignature(DashModule d){ List decls; d.alloyString += d.addVarSigSimple(scopesUsedName+"0", createVar(stateLabelName)); - d.alloyString += d.addVarSigSimple(confName+"0", createVar(stateLabelName)); + if (!d.hasOnlyOneState()) + d.alloyString += d.addVarSigSimple(confName+"0", createVar(stateLabelName)); d.alloyString += d.addVarSigSimple(transTakenName+"0", createVar(transitionLabelName)); if (d.hasEvents()) d.alloyString += d.addVarSigSimple(eventsName+"0", createVar(allEventsName)); @@ -57,11 +58,12 @@ public static void addSnapshotSignature(DashModule d){ for (int i = 1; i <= d.getMaxDepthParams(); i++) { cop = new ArrayList (Collections.nCopies(i-1,createVar(identifierName))); // conf 1, etc. - decls.add( - DeclExt.newVarDeclExt( - confName+Integer.toString(i), - createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(stateLabelName)))))); - // conf 1, etc. + if (!d.hasOnlyOneState()) + decls.add( + DeclExt.newVarDeclExt( + confName+Integer.toString(i), + createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(stateLabelName)))))); + decls.add( DeclExt.newVarDeclExt( transTakenName+Integer.toString(i), @@ -211,7 +213,7 @@ public static void addSnapshotSignature(DashModule d){ //if (d.transAtThisParamDepth(0)) //TODO: if no concurrency, don't need scopesUsed !! decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", scopeLabelName)); - decls.add(DeclExt.newSetDeclExt(confName+"0", stateLabelName)); + if (!d.hasOnlyOneState()) decls.add(DeclExt.newSetDeclExt(confName+"0", stateLabelName)); decls.add(DeclExt.newSetDeclExt(transTakenName+"0", transitionLabelName)); if (d.hasEvents()) decls.add(DeclExt.newSetDeclExt(eventsName+"0", allEventsName)); @@ -224,9 +226,10 @@ public static void addSnapshotSignature(DashModule d){ scopesUsedName+Integer.toString(i), createArrowStringList(DashUtilFcns.newListWith(cop, scopeLabelName)))); // conf 1, etc. - decls.add((Decl) new DeclExt( - confName+Integer.toString(i), - createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); + if (!d.hasOnlyOneState()) + decls.add((Decl) new DeclExt( + confName+Integer.toString(i), + createArrowStringList(DashUtilFcns.newListWith(cop, stateLabelName)))); decls.add((Decl) new DeclExt( transTakenName+Integer.toString(i), createArrowStringList(DashUtilFcns.newListWith(cop, transitionLabelName)))); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index 1dcdf9c71..50b424379 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -34,8 +34,10 @@ public class AddSpaceSignatures { public static void addSpaceSignatures(DashModule d) { // abstract sig Statelabel {} - d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); - d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + if (!d.hasOnlyOneState()) { + d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); + d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); + } d.alloyString += d.addAbstractSigSimple(DashStrings.scopeLabelName); d.alloyString += d.addOneExtendsSigSimple(d.getRootName()+DashStrings.scopeSuffix,DashStrings.scopeLabelName); recurseCreateStateSpaceSigs(d, d.getRootName()); @@ -109,14 +111,16 @@ private static void recurseCreateStateSpaceSigs(DashModule d, String parent) { // for scopes Used d.alloyString += d.addOneExtendsSigSimple(translateFQN(child)+DashStrings.scopeSuffix,DashStrings.scopeLabelName); // for conf - if (d.isLeaf(child)) d.alloyString += d.addOneExtendsSigSimple(translateFQN(child),translateFQN(parent)); - else { - //if (d.isAnd(parent)) - //d.alloyString += d.addExtendsSigSimple(translateFQN(child), translateFQN(parent)); - //else - String x = d.addAbstractExtendsSigSimple(translateFQN(child), translateFQN(parent)); - d.alloyString += x; - //System.out.println("HERE" + x); + if (!d.hasOnlyOneState()) { + if (d.isLeaf(child)) d.alloyString += d.addOneExtendsSigSimple(translateFQN(child),translateFQN(parent)); + else { + //if (d.isAnd(parent)) + //d.alloyString += d.addExtendsSigSimple(translateFQN(child), translateFQN(parent)); + //else + String x = d.addAbstractExtendsSigSimple(translateFQN(child), translateFQN(parent)); + d.alloyString += x; + //System.out.println("HERE" + x); + } } if (!d.isLeaf(child)) recurseCreateStateSpaceSigs(d,child); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java index 2d153b092..6253f0269 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java @@ -45,7 +45,8 @@ public static void addStutter(DashModule d) { // all the dsh defined parts of the snapshot stay the same if (d.hasConcurrency()) body.add(noChange(DashStrings.stableName)); for (int i = 0; i <= d.getMaxDepthParams(); i++) { - body.add(noChange(DashStrings.confName+Integer.toString(i))); + if (!d.hasOnlyOneState()) + body.add(noChange(DashStrings.confName+Integer.toString(i))); body.add(noChange(DashStrings.scopesUsedName+Integer.toString(i))); if (i == 0)body.add(createEquals(nextTransTaken(i), createVar(DashStrings.noTransName))); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java index 750870fa2..c7824df9c 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransIsEnabledAfterStep.java @@ -74,13 +74,14 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { } } - // some (p3 -> p2 -> p1 -> src & s'.confi) - // src does not have to be a basic state - body.add( - createSomeOf( - createIntersect( - translateDashRefToArrow(d.getTransSrc(tfqn)), - nextConf(prsIdx.size())))); + if (!d.hasOnlyOneState()) + // some (p3 -> p2 -> p1 -> src & s'.confi) + // src does not have to be a basic state + body.add( + createSomeOf( + createIntersect( + translateDashRefToArrow(d.getTransSrc(tfqn)), + nextConf(prsIdx.size())))); // primed guard condition is true // TODO @@ -156,14 +157,5 @@ public static void addTransIsEnabledAfterStep(DashModule d, String tfqn) { d.alloyString += d.addPredSimple(tout+DashStrings.enabledAfterStepName,decls,body); } - /* - public static Decl genEventsDecl(int i) { - return (Decl) new DeclExt(DashStrings.genEventName + i, DashStrings.allEventsName); - } - - public static Expr genEventsVar(int i) { - return createVar(DashStrings.genEventName + i); - } - */ } \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 6a77ad54d..1b07ff93a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -87,24 +87,26 @@ public static void addTransPost(DashModule d, String tfqn) { List prs = d.getTransParams(tfqn); List body = new ArrayList(); - // confi' = confi - exitedi + enteredi - List entered = d.entered(tfqn); - List exited = d.exited(tfqn); - for (int i=0;i <= d.getMaxDepthParams(); i++) { - List ent = DashRef.hasNumParams(entered,i).stream() - .map(x -> translateDashRefToArrow(x)) - .collect(Collectors.toList()); - List exi = DashRef.hasNumParams(exited,i).stream() - .map(x -> translateDashRefToArrow(x)) - .collect(Collectors.toList()); - // both ent and exi could be empty at this level - Expr e; - if (!exi.isEmpty()) - e = createDiff(curConf(i),createUnionList(exi)); - else - e = curConf(i); - if (!ent.isEmpty()) e = createUnion(e,createUnionList(ent)); - body.add(createEquals(nextConf(i),e)); + if (!d.hasOnlyOneState()) { + // confi' = confi - exitedi + enteredi + List entered = d.entered(tfqn); + List exited = d.exited(tfqn); + for (int i=0;i <= d.getMaxDepthParams(); i++) { + List ent = DashRef.hasNumParams(entered,i).stream() + .map(x -> translateDashRefToArrow(x)) + .collect(Collectors.toList()); + List exi = DashRef.hasNumParams(exited,i).stream() + .map(x -> translateDashRefToArrow(x)) + .collect(Collectors.toList()); + // both ent and exi could be empty at this level + Expr e; + if (!exi.isEmpty()) + e = createDiff(curConf(i),createUnionList(exi)); + else + e = curConf(i); + if (!ent.isEmpty()) e = createUnion(e,createUnionList(ent)); + body.add(createEquals(nextConf(i),e)); + } } // action_t1[s,s'] diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index f61a347c2..c2e1ea179 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -56,13 +56,14 @@ public static void addTransPre(DashModule d, String tfqn) { List body = new ArrayList(); String tout = translateFQN(tfqn); - // p3 -> p2 -> p1 -> src & s.confVar(i) != none - // src does not have to be a basic state - body.add( - createSomeOf( - createIntersect( - translateDashRefToArrow(d.getTransSrc(tfqn)), - curConf(prsIdx.size())))); + if (!d.hasOnlyOneState()) + // p3 -> p2 -> p1 -> src & s.confVar(i) != none + // src does not have to be a basic state + body.add( + createSomeOf( + createIntersect( + translateDashRefToArrow(d.getTransSrc(tfqn)), + curConf(prsIdx.size())))); if (d.getTransWhen(tfqn) != null) body.add(translateExpr(d.getTransWhen(tfqn),d)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index e2fb024e1..7d7b6b03f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -265,6 +265,9 @@ public void setParsed() { public boolean hasRoot() { return (root != null); } + public boolean hasOnlyOneState() { + return stateTable.hasOnlyOneState(); + } public String getRootName() { if (root != null) return root.name; else { DashErrors.toAlloyNoDash(); return null; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index 36ffff136..a96068197 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -261,6 +261,9 @@ public Boolean hasConcurrency(String s) { return false; } else { DashErrors.stateDoesNotExist("hasConcurrency", s); return null; } } + public Boolean hasOnlyOneState() { + return (table.keySet().size() == 1 ); + } public String getParent(String child) { if (table.containsKey(child)) return table.get(child).parent; // could be null if root From d3dda587a235d537afd2fd0d21f132e5554cac7d Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Fri, 23 Jun 2023 18:36:12 -0400 Subject: [PATCH 082/129] added optimization to remove sc_used if no concurrency --- .../watform/alloyasthelper/ExprHelper.java | 3 ++ .../AddAllSnapshotsDifferentFact.java | 2 +- .../watform/dashtoalloy/AddInit.java | 7 ++-- .../dashtoalloy/AddSnapshotSignature.java | 29 ++++++++-------- .../dashtoalloy/AddSpaceSignatures.java | 9 +++-- .../watform/dashtoalloy/AddStutter.java | 13 ++++---- .../watform/dashtoalloy/AddTransPost.java | 33 +++++++++++-------- .../watform/dashtoalloy/AddTransPre.java | 4 +-- .../watform/parser/CompModuleHelper.java | 12 ++++++- 9 files changed, 70 insertions(+), 42 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java index b0b15f41f..94e63ee3f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/alloyasthelper/ExprHelper.java @@ -217,6 +217,9 @@ public static Expr createExprQt(ExprQt.Op op, List decls, Expr expr) { } /* a few useful specific ones */ + public static Expr createNoop(Expr sub) { + return (ExprUnary) ExprUnary.Op.NOOP.make(Pos.UNKNOWN, sub); + } public static Expr createNot(Expr sub) { return (ExprUnary) ExprUnary.Op.NOT.make(Pos.UNKNOWN, sub); } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java index 0f3c4dff7..09ccc9dfe 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddAllSnapshotsDifferentFact.java @@ -46,7 +46,7 @@ public static void addAllSnapshotsDifferentFact(DashModule d) { if (!d.hasOnlyOneState()) body.add(createEquals(curConf(i),nextConf(i))); // s.scopesUsedi = sn.scopesUsedi - //if (d.hasConcurrency()) + if (d.hasConcurrency()) body.add(createEquals(curScopesUsed(i),nextScopesUsed(i))); body.add(createEquals(curTransTaken(i),nextTransTaken(i))); if (d.hasInternalEventsAti(i)) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java index 471c00f19..c42b69bdb 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddInit.java @@ -55,9 +55,10 @@ public static void addInit(DashModule d) { } for (int i = 0; i <= d.getMaxDepthParams(); i++) { // scopesUsedi = none - body.add(createEquals( - curScopesUsed(i), - createNoneArrow(i))); + if (d.hasConcurrency()) + body.add(createEquals( + curScopesUsed(i), + createNoneArrow(i))); if (i == 0 ) body.add(createEquals( curTransTaken(i), diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java index 997da82ee..f2f283ba9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSnapshotSignature.java @@ -37,7 +37,8 @@ public static void addSnapshotSignature(DashModule d){ // scopesUsed0, conf0, event0 List decls; - d.alloyString += d.addVarSigSimple(scopesUsedName+"0", createVar(stateLabelName)); + if (d.hasConcurrency()) + d.alloyString += d.addVarSigSimple(scopesUsedName+"0", createVar(stateLabelName)); if (!d.hasOnlyOneState()) d.alloyString += d.addVarSigSimple(confName+"0", createVar(stateLabelName)); d.alloyString += d.addVarSigSimple(transTakenName+"0", createVar(transitionLabelName)); @@ -68,11 +69,12 @@ public static void addSnapshotSignature(DashModule d){ DeclExt.newVarDeclExt( transTakenName+Integer.toString(i), createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(transitionLabelName)))))); - // scopesUsed 1, etc. - decls.add( - DeclExt.newVarDeclExt( - scopesUsedName+Integer.toString(i), - createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(stateLabelName)))))); + if (d.hasConcurrency()) + // scopesUsed 1, etc. + decls.add( + DeclExt.newVarDeclExt( + scopesUsedName+Integer.toString(i), + createArrowExprList(DashUtilFcns.newListWith(cop, createSet(createVar(stateLabelName)))))); if (d.hasEvents() & d.hasEventsAti(i)) // events 1, etc. decls.add( @@ -210,9 +212,9 @@ public static void addSnapshotSignature(DashModule d){ List decls = new ArrayList(); // scopesUsed0, conf0, event0 - //if (d.transAtThisParamDepth(0)) - //TODO: if no concurrency, don't need scopesUsed !! - decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", scopeLabelName)); + + if (d.hasConcurrency()) + decls.add(DeclExt.newSetDeclExt(scopesUsedName+"0", scopeLabelName)); if (!d.hasOnlyOneState()) decls.add(DeclExt.newSetDeclExt(confName+"0", stateLabelName)); decls.add(DeclExt.newSetDeclExt(transTakenName+"0", transitionLabelName)); if (d.hasEvents()) @@ -221,10 +223,11 @@ public static void addSnapshotSignature(DashModule d){ for (int i = 1; i <= d.getMaxDepthParams(); i++) { cop = Collections.nCopies(i,identifierName); // scopesUsed 1, etc. - //if (d.transAtThisParamDepth(i)) - decls.add((Decl) new DeclExt( - scopesUsedName+Integer.toString(i), - createArrowStringList(DashUtilFcns.newListWith(cop, scopeLabelName)))); + //if (d.transAtThisParamDepth(i)) + if (d.hasConcurrency()) + decls.add((Decl) new DeclExt( + scopesUsedName+Integer.toString(i), + createArrowStringList(DashUtilFcns.newListWith(cop, scopeLabelName)))); // conf 1, etc. if (!d.hasOnlyOneState()) decls.add((Decl) new DeclExt( diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java index 50b424379..aed82a4f9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddSpaceSignatures.java @@ -38,8 +38,10 @@ public static void addSpaceSignatures(DashModule d) { d.alloyString += d.addAbstractSigSimple(DashStrings.stateLabelName); d.alloyString += d.addAbstractExtendsSigSimple(d.getRootName(),DashStrings.stateLabelName); } - d.alloyString += d.addAbstractSigSimple(DashStrings.scopeLabelName); - d.alloyString += d.addOneExtendsSigSimple(d.getRootName()+DashStrings.scopeSuffix,DashStrings.scopeLabelName); + if (d.hasConcurrency()) { + d.alloyString += d.addAbstractSigSimple(DashStrings.scopeLabelName); + d.alloyString += d.addOneExtendsSigSimple(d.getRootName()+DashStrings.scopeSuffix,DashStrings.scopeLabelName); + } recurseCreateStateSpaceSigs(d, d.getRootName()); d.alloyString += "\n"; @@ -109,7 +111,8 @@ private static void recurseCreateStateSpaceSigs(DashModule d, String parent) { for (String child: d.getImmChildren(parent)) { //System.out.println(translateFQN(child)+" "+translateFQN(parent)); // for scopes Used - d.alloyString += d.addOneExtendsSigSimple(translateFQN(child)+DashStrings.scopeSuffix,DashStrings.scopeLabelName); + if (d.hasConcurrency()) + d.alloyString += d.addOneExtendsSigSimple(translateFQN(child)+DashStrings.scopeSuffix,DashStrings.scopeLabelName); // for conf if (!d.hasOnlyOneState()) { if (d.isLeaf(child)) d.alloyString += d.addOneExtendsSigSimple(translateFQN(child),translateFQN(parent)); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java index 6253f0269..66a2a2953 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddStutter.java @@ -47,12 +47,13 @@ public static void addStutter(DashModule d) { for (int i = 0; i <= d.getMaxDepthParams(); i++) { if (!d.hasOnlyOneState()) body.add(noChange(DashStrings.confName+Integer.toString(i))); - body.add(noChange(DashStrings.scopesUsedName+Integer.toString(i))); - if (i == 0)body.add(createEquals(nextTransTaken(i), - createVar(DashStrings.noTransName))); - else body.add(createEquals(nextTransTaken(i), - createNoneArrow(i))); - if (d.hasEvents() && d.hasInternalEventsAti(i)) + if (d.hasConcurrency()) + body.add(noChange(DashStrings.scopesUsedName+Integer.toString(i))); + if (i == 0) + body.add(createEquals(nextTransTaken(i), createVar(DashStrings.noTransName))); + else + body.add(createEquals(nextTransTaken(i), createNoneArrow(i))); + if (d.hasEvents() && d.hasInternalEventsAti(i)) // internal events go away // external events can be added body.add(createEquals( diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java index 1b07ff93a..6664723ba 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPost.java @@ -243,13 +243,18 @@ else if (hasSpecificParamValues(d, r)) { //if (case2.isEmpty()) c2 = createTrue(); c2 = createAndFromList(case2); - List scopesUsedEmpty = new ArrayList(); - - for (int i=0;i <= d.getMaxDepthParams(); i++) { - scopesUsedEmpty.add(createEquals(nextScopesUsed(i),createNoneArrow(i))); + Expr stableTrueAndScopesUsedEmpty; + if (d.hasConcurrency()) { + List scopesUsedEmpty = new ArrayList(); + + for (int i=0;i <= d.getMaxDepthParams(); i++) { + scopesUsedEmpty.add(createEquals(nextScopesUsed(i),createNoneArrow(i))); + } + stableTrueAndScopesUsedEmpty = + createAnd(nextStableTrue(), createAndFromList(scopesUsedEmpty)); + } else { + stableTrueAndScopesUsedEmpty = nextStableTrue(); } - Expr stableTrueAndScopesUsedEmpty = - createAnd(nextStableTrue(), createAndFromList(scopesUsedEmpty)); // case 3 // forall i: (eventsi' :> InternalEvent = t1_send_ev (if i)) @@ -296,13 +301,15 @@ else if (hasSpecificParamValues(d, r)) { if (ev != null && ev.getParamValues().size() == i) case4.add(createEquals(nextEvents(i),createUnion(curEvents(i), translateDashRefToArrow(ev)))); } - // scopesUsedi' = scopesUsedi + scopesUsed - u = DashRef.hasNumParams(sU,i).stream() - .map(x -> translateDashRefToArrow(replaceScope(x))) - .collect(Collectors.toList()); - e = curScopesUsed(i); - if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); - case4.add(createEquals(nextScopesUsed(i),e)); + if (d.hasConcurrency()) { + // scopesUsedi' = scopesUsedi + scopesUsed + u = DashRef.hasNumParams(sU,i).stream() + .map(x -> translateDashRefToArrow(replaceScope(x))) + .collect(Collectors.toList()); + e = curScopesUsed(i); + if (!u.isEmpty()) e = createUnion(e,createUnionFromList(u)); + case4.add(createEquals(nextScopesUsed(i),e)); + } } //if (case4.isEmpty()) c4 = createTrue(); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java index c2e1ea179..3f1c092a5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtoalloy/AddTransPre.java @@ -68,7 +68,7 @@ public static void addTransPre(DashModule d, String tfqn) { if (d.getTransWhen(tfqn) != null) body.add(translateExpr(d.getTransWhen(tfqn),d)); - //if (d.hasConcurrency()) { + if (d.hasConcurrency()) { // has a scope that is orthogonal to any scopes used List nonO = d.nonOrthogonalScopesOf(tfqn); for (int i=0;i <= d.getMaxDepthParams(); i++) { @@ -77,7 +77,7 @@ public static void addTransPre(DashModule d, String tfqn) { .collect(Collectors.toList()); for (Expr x: u) body.add(createNot(createIn(x,curScopesUsed(i)))); } - //} + } // event trigger // only one triggering event diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java index 2eb70c339..6f2d26a30 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/CompModuleHelper.java @@ -359,8 +359,18 @@ public String addVarLoneSigSimple(String name, ExprVar typ) { * t is return type; null if predicate */ public String addPredSimple(String name, List decls, List eList) { - Expr body = createAndFromList(eList); + Expr body; + //NAD: no idea why a one line eList causes a problem + // but it does cause a problem in addFunc about multiplicity not allowed here + // at least if one formula starts with 'some ...' + if (eList.size() != 1) body = createAndFromList(eList); + else body = createNoop(eList.get(0)); + + + //System.out.println(createVar(name)); + //System.out.println(decls); //System.out.println(body); + addFunc(Pos.UNKNOWN, Pos.UNKNOWN, createVar(name), null, decls, null, body); String s = new String(); s += DashStrings.predName + " " + name; From 7fe215b898d08c1949987a12d5331926cd990e8e Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Fri, 23 Jun 2023 18:53:08 -0400 Subject: [PATCH 083/129] added module naming and attempted to extract internal data structures --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 7 ++++- .../watform/dashtotla/DashtoTLA.java | 28 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index 4c17183c2..b13b5bdd2 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -198,7 +198,12 @@ public static void main(String args[]) throws Exception { System.out.println(d.toStringAlloy()); } else if(translateTLA) { - String contents = MainFunctions.translateTLA(d); + String comment = "\\* Modification History\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; + String moduleName = f.getFileName().toString(); + String header = "------------------------------- MODULE "+moduleName.substring(0, moduleName.length()-4)+" -------------------------------"; + String footer = "============================================================================="; + String contents = header+"\n"+MainFunctions.translateTLA(d)+"\n"+footer+"\n"+comment; + String TLAfilename = filename.substring(0,filename.length()-4)+".tla"; File out = new File(TLAfilename); if (!out.exists()) out.createNewFile(); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 36695fa44..167e218a5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -1,12 +1,34 @@ package ca.uwaterloo.watform.dashtotla; -import ca.uwaterloo.watform.parser.DashModule; + +import java.util.List; + +import ca.uwaterloo.watform.parser.*; public class DashtoTLA { public static String translate(DashModule d) { - System.out.println("Hello World"); - return "Hello World"; + StringBuilder things = new StringBuilder(); + + List trans = d.getAllTransNames(); + things.append("\nTransitions:"); + for(String s : trans)things.append("\n----\n").append(s); + + List vars = d.getAllVarNames(); + things.append("\nVariables:"); + for(String s : vars)things.append("\n----\n").append(s); + + List env_events = d.getAllEnvironmentalEventNames(); + things.append("\nEnvironmental events:"); + for(String s : env_events)things.append("\n----\n").append(s); + + List events = d.getAllInternalEventNames(); + things.append("\nInternal events:"); + for(String s : events)things.append("\n----\n").append(s); + + System.out.print(d.toStringAlloy()); + + return "\\*Hello World\n(*"+things.toString()+"*)"; } } From 16089ad4c3f4b4294f8d72346984d11f300518d7 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Sun, 25 Jun 2023 09:37:52 -0400 Subject: [PATCH 084/129] cleaned up imports in DashModule and populated internal tables --- .../src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java | 1 + .../main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 2 ++ .../src/main/java/ca/uwaterloo/watform/parser/DashModule.java | 3 --- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index b13b5bdd2..b985082d1 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -198,6 +198,7 @@ public static void main(String args[]) throws Exception { System.out.println(d.toStringAlloy()); } else if(translateTLA) { + d = MainFunctions.resolveDash(d, rep); String comment = "\\* Modification History\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; String moduleName = f.getFileName().toString(); String header = "------------------------------- MODULE "+moduleName.substring(0, moduleName.length()-4)+" -------------------------------"; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 167e218a5..9d015255d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -12,6 +12,8 @@ public static String translate(DashModule d) StringBuilder things = new StringBuilder(); List trans = d.getAllTransNames(); + System.out.println("translength:"+trans.size()); + //System.out.print(d.getRootName()); things.append("\nTransitions:"); for(String s : trans)things.append("\n----\n").append(s); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index e2fb024e1..d0ab3a90d 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -1,14 +1,11 @@ package ca.uwaterloo.watform.parser; -import java.util.*; import java.io.FileReader; import java.io.BufferedReader; -import java.io.FileNotFoundException; import java.util.List; import java.util.ArrayList; import java.util.Arrays; -import java.util.Set; import java.util.Collections; import java.util.stream.Collectors; import java.time.format.DateTimeFormatter; From c9ea869794ba6881a1f55a906a0f5f42bbb9d678 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Sun, 25 Jun 2023 09:43:41 -0400 Subject: [PATCH 085/129] error if no root state --- .../main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 9d015255d..624eac6a1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -9,6 +9,11 @@ public class DashtoTLA { public static String translate(DashModule d) { + if(!d.hasRoot()) + { + System.out.println("Error - no root state, nothing to translate"); + return ""; + } StringBuilder things = new StringBuilder(); List trans = d.getAllTransNames(); From 04b95fd76dd2091a0999d8bf16aee42f2c1132c0 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Sun, 25 Jun 2023 09:49:52 -0400 Subject: [PATCH 086/129] extracted transition specifics --- .../main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 624eac6a1..f76c5b7cd 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -17,10 +17,9 @@ public static String translate(DashModule d) StringBuilder things = new StringBuilder(); List trans = d.getAllTransNames(); - System.out.println("translength:"+trans.size()); //System.out.print(d.getRootName()); - things.append("\nTransitions:"); - for(String s : trans)things.append("\n----\n").append(s); + things.append("\nTransitions\tsource\tdestination"); + for(String s : trans)things.append("\n"+s+"\t"+d.getTransSrc(s)+"\t"+d.getTransDest(s)); List vars = d.getAllVarNames(); things.append("\nVariables:"); From 3af720c16f3c1e64b561fea08fef9a819d2aa727 Mon Sep 17 00:00:00 2001 From: Nancy Day Date: Mon, 26 Jun 2023 11:04:38 -0400 Subject: [PATCH 087/129] added getAllStates --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 17 ++++++++++++++--- .../ca/uwaterloo/watform/core/DashOptions.java | 4 ++-- .../ca/uwaterloo/watform/parser/DashModule.java | 3 +++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index a5343e401..5e485d740 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -50,11 +50,22 @@ public static void executeCommands(CompModule c, Integer cmdnum, A4Reporter rep) } catch (Exception e) { DashUtilFcns.handleException(e); } - if (ans.satisfiable()) { - System.out.println("Result: SAT"); + if (ans.satisfiable()) { + if (cmd.expects == 1) + System.out.println("Result: SAT (CORRECT)"); + else if (cmd.expects == 0) + System.out.println("Result: SAT (INCORRECT)"); + else + System.out.println("Result: SAT (nothing expected)"); } else { - System.out.println("Result: UNSAT"); + if (cmd.expects == 0) + System.out.println("Result: UNSAT (CORRECT)"); + else if (cmd.expects == 1) + System.out.println("Result: UNSAT (INCORRECT)"); + else + System.out.println("Result: UNSAT (nothing expected)"); } + } i++; } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java index b3e63b03a..63b0bcdb7 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashOptions.java @@ -10,8 +10,8 @@ public class DashOptions { public static boolean isTcmc = false; public static boolean isTraces = true; public static boolean singleEventInput = false; - public static boolean reachability = false; - public static boolean enoughOperations = false; + public static boolean reachability = true; // predicate + public static boolean enoughOperations = true; // predicate public static boolean includeTrans = true; // for debugging //NAD other stuff that might be removed //public static boolean variablesUnchanged = true; diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index 7d7b6b03f..edee7f8a3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -307,6 +307,9 @@ public List getAllParamsInOrder() { return stateTable.getAllParamsInOrder(); } + public List getAllStateNames() { + return stateTable.getAllStateNames(); + } //stuff about states (some of these are to expose the stateTable for testing) public boolean isLeaf(String s) { From 3d92af994894fb53d0222b1cebbf8c4d82cb51d8 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Mon, 26 Jun 2023 14:13:32 -0400 Subject: [PATCH 088/129] added states locally --- .vscode/settings.json | 3 ++ .../.settings/org.eclipse.jdt.core.prefs | 30 +++++++++++++--- .../.settings/org.eclipse.jdt.core.prefs | 34 +++++++++++++++---- .../ca/uwaterloo/watform/ast/DashFrom.java | 2 -- .../.settings/org.eclipse.jdt.core.prefs | 30 +++++++++++++--- .../.settings/org.eclipse.jdt.core.prefs | 30 +++++++++++++--- 6 files changed, 105 insertions(+), 24 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..7b016a89f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.compile.nullAnalysis.mode": "automatic" +} \ No newline at end of file diff --git a/org.alloytools.alloy.application/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.application/.settings/org.eclipse.jdt.core.prefs index 0a692051b..978ab1820 100644 --- a/org.alloytools.alloy.application/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.application/.settings/org.eclipse.jdt.core.prefs @@ -91,7 +91,7 @@ org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning @@ -143,6 +143,7 @@ org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=4 org.eclipse.jdt.core.formatter.align_type_members_on_columns=true org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=51 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=50 @@ -150,21 +151,24 @@ org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_c org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 org.eclipse.jdt.core.formatter.alignment_for_assignment=2 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=2 org.eclipse.jdt.core.formatter.alignment_for_compact_if=2 org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=2 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=51 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=2 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=2 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=2 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=2 org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=2 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=2 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=50 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=2 @@ -256,11 +260,12 @@ org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert @@ -291,6 +296,8 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert @@ -315,13 +322,17 @@ org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert @@ -369,6 +380,8 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do no org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert @@ -405,9 +418,12 @@ org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not inser org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert @@ -446,10 +462,14 @@ org.eclipse.jdt.core.formatter.tabulation.char=space org.eclipse.jdt.core.formatter.tabulation.size=4 org.eclipse.jdt.core.formatter.use_on_off_tags=true org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true org.eclipse.jdt.core.incompatibleJDKLevel=ignore org.eclipse.jdt.core.incompleteClasspath=error diff --git a/org.alloytools.alloy.core/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.core/.settings/org.eclipse.jdt.core.prefs index 0a692051b..fee4ef9bf 100644 --- a/org.alloytools.alloy.core/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.core/.settings/org.eclipse.jdt.core.prefs @@ -23,7 +23,7 @@ org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignor org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 @@ -84,9 +84,9 @@ org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore @@ -143,6 +143,7 @@ org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=4 org.eclipse.jdt.core.formatter.align_type_members_on_columns=true org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=51 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=50 @@ -150,21 +151,24 @@ org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_c org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 org.eclipse.jdt.core.formatter.alignment_for_assignment=2 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=2 org.eclipse.jdt.core.formatter.alignment_for_compact_if=2 org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=2 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=51 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=2 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=2 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=2 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=2 org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=2 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=2 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=50 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=2 @@ -256,11 +260,12 @@ org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert @@ -291,6 +296,8 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert @@ -315,13 +322,17 @@ org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert @@ -369,6 +380,8 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do no org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert @@ -405,9 +418,12 @@ org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not inser org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert @@ -446,10 +462,14 @@ org.eclipse.jdt.core.formatter.tabulation.char=space org.eclipse.jdt.core.formatter.tabulation.size=4 org.eclipse.jdt.core.formatter.use_on_off_tags=true org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true org.eclipse.jdt.core.incompatibleJDKLevel=ignore org.eclipse.jdt.core.incompleteClasspath=error diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java index 86dfce17e..59f8c3fd6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/ast/DashFrom.java @@ -1,12 +1,10 @@ package ca.uwaterloo.watform.ast; -import java.util.List; import edu.mit.csail.sdg.alloy4.Pos; import edu.mit.csail.sdg.ast.Expr; import ca.uwaterloo.watform.core.DashStrings; -import ca.uwaterloo.watform.core.DashRef; public class DashFrom extends Dash { diff --git a/org.alloytools.alloy.dist/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.dist/.settings/org.eclipse.jdt.core.prefs index 74a30a06a..9eadd7a45 100644 --- a/org.alloytools.alloy.dist/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.dist/.settings/org.eclipse.jdt.core.prefs @@ -91,7 +91,7 @@ org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning @@ -142,6 +142,7 @@ org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=4 org.eclipse.jdt.core.formatter.align_type_members_on_columns=true org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=51 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=50 @@ -149,21 +150,24 @@ org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_c org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 org.eclipse.jdt.core.formatter.alignment_for_assignment=2 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=2 org.eclipse.jdt.core.formatter.alignment_for_compact_if=2 org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=2 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=51 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=2 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=2 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=2 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=2 org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=2 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=2 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=50 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=2 @@ -255,11 +259,12 @@ org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert @@ -290,6 +295,8 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert @@ -314,13 +321,17 @@ org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert @@ -368,6 +379,8 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do no org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert @@ -404,9 +417,12 @@ org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not inser org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert @@ -445,10 +461,14 @@ org.eclipse.jdt.core.formatter.tabulation.char=space org.eclipse.jdt.core.formatter.tabulation.size=4 org.eclipse.jdt.core.formatter.use_on_off_tags=true org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true org.eclipse.jdt.core.incompatibleJDKLevel=ignore org.eclipse.jdt.core.incompleteClasspath=error diff --git a/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs b/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs index 0a692051b..978ab1820 100644 --- a/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs +++ b/org.alloytools.alloy.extra/.settings/org.eclipse.jdt.core.prefs @@ -91,7 +91,7 @@ org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning @@ -143,6 +143,7 @@ org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=4 org.eclipse.jdt.core.formatter.align_type_members_on_columns=true org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=51 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=50 @@ -150,21 +151,24 @@ org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_c org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=2 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=2 org.eclipse.jdt.core.formatter.alignment_for_assignment=2 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=2 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=2 org.eclipse.jdt.core.formatter.alignment_for_compact_if=2 org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=2 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=51 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=2 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=2 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=2 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=2 org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=2 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=2 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=2 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=2 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=50 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=2 @@ -256,11 +260,12 @@ org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert @@ -291,6 +296,8 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert @@ -315,13 +322,17 @@ org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert @@ -369,6 +380,8 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do no org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert @@ -405,9 +418,12 @@ org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not inser org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert +org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert @@ -446,10 +462,14 @@ org.eclipse.jdt.core.formatter.tabulation.char=space org.eclipse.jdt.core.formatter.tabulation.size=4 org.eclipse.jdt.core.formatter.use_on_off_tags=true org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true org.eclipse.jdt.core.incompatibleJDKLevel=ignore org.eclipse.jdt.core.incompleteClasspath=error From 39aa04ee363cf08e90f42ffa2ff41139e1e46571 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 00:19:30 -0400 Subject: [PATCH 089/129] defined atomic states and got rid of dashmodule tests --- .../watform/dashtotla/DashtoTLA.java | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index f76c5b7cd..510cd29ff 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -1,6 +1,7 @@ package ca.uwaterloo.watform.dashtotla; +import java.util.ArrayList; import java.util.List; import ca.uwaterloo.watform.parser.*; @@ -16,25 +17,19 @@ public static String translate(DashModule d) } StringBuilder things = new StringBuilder(); - List trans = d.getAllTransNames(); - //System.out.print(d.getRootName()); - things.append("\nTransitions\tsource\tdestination"); - for(String s : trans)things.append("\n"+s+"\t"+d.getTransSrc(s)+"\t"+d.getTransDest(s)); + List states = d.getAllStateNames(); + StringBuilder constants = new StringBuilder(""); + for(int i =0; i vars = d.getAllVarNames(); - things.append("\nVariables:"); - for(String s : vars)things.append("\n----\n").append(s); - List env_events = d.getAllEnvironmentalEventNames(); - things.append("\nEnvironmental events:"); - for(String s : env_events)things.append("\n----\n").append(s); - - List events = d.getAllInternalEventNames(); - things.append("\nInternal events:"); - for(String s : events)things.append("\n----\n").append(s); - - System.out.print(d.toStringAlloy()); - - return "\\*Hello World\n(*"+things.toString()+"*)"; + return "\n\\*basic states"+constants; + } + public static String resolveName(String s) + { + return s.replace("/", "_"); } } From a66eea29736eaaf43e892897743ecc7b55341374 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 01:36:51 -0400 Subject: [PATCH 090/129] added transitions --- .../ca/uwaterloo/watform/core/DashRef.java | 12 +--- .../watform/dashtotla/DashtoTLA.java | 58 ++++++++++++++++--- .../uwaterloo/watform/parser/StateTable.java | 12 ++-- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index b27073220..1e0d00bec 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -26,23 +26,17 @@ package ca.uwaterloo.watform.core; import edu.mit.csail.sdg.alloy4.Err; -import edu.mit.csail.sdg.alloy4.ErrorFatal; -import edu.mit.csail.sdg.alloy4.ErrorType; import edu.mit.csail.sdg.alloy4.ErrorWarning; -import edu.mit.csail.sdg.alloy4.JoinableList; import edu.mit.csail.sdg.ast.Browsable; import edu.mit.csail.sdg.ast.Expr; -import edu.mit.csail.sdg.ast.ExprUnary; import edu.mit.csail.sdg.ast.Type; import edu.mit.csail.sdg.ast.VisitReturn; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import java.util.List; import java.util.ArrayList; //import java.util.JoinableList; @@ -52,13 +46,13 @@ //import edu.mit.csail.sdg.ast.Type; //import edu.mit.csail.sdg.ast.Browsable; //import edu.mit.csail.sdg.ast.VisitReturn; -import edu.mit.csail.sdg.ast.Expr; +//import edu.mit.csail.sdg.ast.Expr; //import edu.mit.csail.sdg.ast.ExprBinary; //import edu.mit.csail.sdg.ast.ExprVar; import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; -import ca.uwaterloo.watform.core.DashUtilFcns; -import ca.uwaterloo.watform.core.DashErrors; +//import ca.uwaterloo.watform.core.DashUtilFcns; +//import ca.uwaterloo.watform.core.DashErrors; import ca.uwaterloo.watform.core.DashRef; public class DashRef extends Expr { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 510cd29ff..1ca0fbff0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -1,10 +1,12 @@ package ca.uwaterloo.watform.dashtotla; + import java.util.ArrayList; import java.util.List; -import ca.uwaterloo.watform.parser.*; +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.core.DashRef; public class DashtoTLA { @@ -15,21 +17,59 @@ public static String translate(DashModule d) System.out.println("Error - no root state, nothing to translate"); return ""; } - StringBuilder things = new StringBuilder(); + StringBuilder translation = new StringBuilder("\nEXTENDS Integers, FiniteSets"); + translation.append("\nVARIABLE conf"); + translation.append(boilerplateBasicStates(d)); + translation.append(transitions(d)); + + + return translation.toString(); + } + public static String resolveName(String s) + { + return s.replace("/", "_"); + } + public static String boilerplateBasicStates(DashModule d) + { List states = d.getAllStateNames(); - StringBuilder constants = new StringBuilder(""); + StringBuilder basicStates = new StringBuilder(""); for(int i =0; i states = d.getAllStateNames(); + StringBuilder compositeStates = new StringBuilder(""); + for(int i =0; i tranList = d.getAllTransNames(); + for(String s : tranList) + { + String srcState = d.getTransSrc(s).toString(); + String destState = d.getTransDest(s).toString(); + ts.append("\n"+resolveName(s)+" == conf = "+srcState+" /\\ conf' = "+destState); + } + + ts.append("\n\nNext == "); + for(String s : tranList) + { + ts.append("/\\ "+resolveName(s)+"\n"); + } + + return ts.toString(); } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java index a96068197..6ae8ef361 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/StateTable.java @@ -6,13 +6,13 @@ package ca.uwaterloo.watform.parser; -import java.io.*; +//import java.io.*; -import java.util.Set; +//import java.util.Set; import java.util.HashMap; import java.util.List; import java.util.ArrayList; -import java.util.HashSet; +//import java.util.HashSet; import java.util.Collections; import java.util.stream.Collectors; @@ -22,13 +22,13 @@ import ca.uwaterloo.watform.core.DashRef; import static ca.uwaterloo.watform.core.DashUtilFcns.*; import static ca.uwaterloo.watform.core.DashStrings.*; -import static ca.uwaterloo.watform.core.DashFQN.*; +//import static ca.uwaterloo.watform.core.DashFQN.*; import ca.uwaterloo.watform.alloyasthelper.ExprHelper; import ca.uwaterloo.watform.ast.*; -import ca.uwaterloo.watform.parser.VarTable; -import ca.uwaterloo.watform.dashtoalloy.Common; +//import ca.uwaterloo.watform.parser.VarTable; +//import ca.uwaterloo.watform.dashtoalloy.Common; public class StateTable { private HashMap table; From 2eea9e0573c4d296d448292f8f5e7a6abea7409c Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 01:47:57 -0400 Subject: [PATCH 091/129] added Init --- .../ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 1ca0fbff0..f30f0c6d8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -22,7 +22,7 @@ public static String translate(DashModule d) translation.append("\nVARIABLE conf"); translation.append(boilerplateBasicStates(d)); translation.append(transitions(d)); - + translation.append(Init(d)); return translation.toString(); } @@ -50,7 +50,7 @@ public static String boilerplateCompositeStates(DashModule d) String s = states.get(i); if(d.isLeaf(s))continue; } - return "\n\\*composite states"+compositeStates; + return "\n\n\\*composite states"+compositeStates; } public static String transitions(DashModule d) { @@ -67,9 +67,16 @@ public static String transitions(DashModule d) ts.append("\n\nNext == "); for(String s : tranList) { - ts.append("/\\ "+resolveName(s)+"\n"); + ts.append("\n\t/\\ "+resolveName(s)); } return ts.toString(); } + public static String Init(DashModule d) + { + StringBuilder init = new StringBuilder("\n\nInit == "); + List defaultsOfRoot = d.getDefaults(d.getRootName()); + for(String s : defaultsOfRoot)init.append("\n\t\\/ "+resolveName(s)); + return init.toString(); + } } From 4c1c2ed588572c8f004a2a27bd1ed8b195370524 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 01:52:46 -0400 Subject: [PATCH 092/129] bug fix name resolution for conf' --- .../main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index f30f0c6d8..693f62a5a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -39,7 +39,7 @@ public static String boilerplateBasicStates(DashModule d) String s = states.get(i); if(d.isLeaf(s))basicStates.append("\n"+resolveName(s)+"=="+i); } - return "\n\\*basic states"+basicStates; + return "\n\n\\*basic states"+basicStates; } public static String boilerplateCompositeStates(DashModule d) { @@ -61,7 +61,7 @@ public static String transitions(DashModule d) { String srcState = d.getTransSrc(s).toString(); String destState = d.getTransDest(s).toString(); - ts.append("\n"+resolveName(s)+" == conf = "+srcState+" /\\ conf' = "+destState); + ts.append("\n"+resolveName(s)+" == conf = "+resolveName(srcState)+" /\\ conf' = "+resolveName(destState)); } ts.append("\n\nNext == "); From daa7f0c01db7393f318c5d5f03aeb4776e034f69 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 15:14:29 -0400 Subject: [PATCH 093/129] checking entered and exited --- .../watform/dashtotla/DashtoTLA.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 693f62a5a..2ba934456 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -39,7 +39,7 @@ public static String boilerplateBasicStates(DashModule d) String s = states.get(i); if(d.isLeaf(s))basicStates.append("\n"+resolveName(s)+"=="+i); } - return "\n\n\\*basic states"+basicStates; + return "\n\n\\* basic states"+basicStates; } public static String boilerplateCompositeStates(DashModule d) { @@ -55,10 +55,18 @@ public static String boilerplateCompositeStates(DashModule d) public static String transitions(DashModule d) { // assumption - trigger and guard are tautologies - StringBuilder ts = new StringBuilder("\n\n\\*transitions"); + StringBuilder ts = new StringBuilder("\n\n\\* transitions"); List tranList = d.getAllTransNames(); for(String s : tranList) { + List ENTER = toStringList(d.entered(s)); + List EXIT = toStringList(d.exited(s)); + System.out.println("\nTransition:"+s); + System.out.println("Entered:"); + for(String st : ENTER)System.out.print("|"+st); + System.out.println("\nExited:"); + for(String st : EXIT)System.out.print("|"+st); + String srcState = d.getTransSrc(s).toString(); String destState = d.getTransDest(s).toString(); ts.append("\n"+resolveName(s)+" == conf = "+resolveName(srcState)+" /\\ conf' = "+resolveName(destState)); @@ -79,4 +87,22 @@ public static String Init(DashModule d) for(String s : defaultsOfRoot)init.append("\n\t\\/ "+resolveName(s)); return init.toString(); } + public static List toStringList(List dfs) + { + List ls = new ArrayList<>(); + for(DashRef df : dfs)ls.add(df.toString()); + return ls; + } + public static List toStateDashRefList(List ls) + { + List dfs = new ArrayList<>(); + for(String s : ls)dfs.add(DashRef.createStateDashRef(s, null)); + return dfs; + } + public static List toTransitionDashRefList(List ls) + { + List dfs = new ArrayList<>(); + for(String s : ls)dfs.add(DashRef.createTransDashRef(s, null)); + return dfs; + } } From ecfc70a9a5b652d3ccdc87511550922a18f67d34 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 15:32:39 -0400 Subject: [PATCH 094/129] bug fix - Init should assign value to conf --- .../watform/dashtotla/DashtoTLA.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 2ba934456..5f45eb935 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -41,17 +41,6 @@ public static String boilerplateBasicStates(DashModule d) } return "\n\n\\* basic states"+basicStates; } - public static String boilerplateCompositeStates(DashModule d) - { - List states = d.getAllStateNames(); - StringBuilder compositeStates = new StringBuilder(""); - for(int i =0; i defaultsOfRoot = d.getDefaults(d.getRootName()); - for(String s : defaultsOfRoot)init.append("\n\t\\/ "+resolveName(s)); + for(String s : defaultsOfRoot)init.append("\n\t\\/ conf == "+resolveName(s)); return init.toString(); } public static List toStringList(List dfs) @@ -105,4 +94,16 @@ public static List toTransitionDashRefList(List ls) for(String s : ls)dfs.add(DashRef.createTransDashRef(s, null)); return dfs; } + public static String toSetOfStates(List states) + { + StringBuilder sb = new StringBuilder("{"); + for(int i=0;i Date: Tue, 27 Jun 2023 15:53:03 -0400 Subject: [PATCH 095/129] bug fix - indexing redefined to avoid gaps --- .../main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 5f45eb935..1a88ab0c6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -34,10 +34,11 @@ public static String boilerplateBasicStates(DashModule d) { List states = d.getAllStateNames(); StringBuilder basicStates = new StringBuilder(""); + int ct=0; for(int i =0; i toStringList(List dfs) { List ls = new ArrayList<>(); - for(DashRef df : dfs)ls.add(df.toString()); + for(DashRef df : dfs)ls.add(df.getName()); return ls; } public static List toStateDashRefList(List ls) From 35a38ecc866b0f468c085d195c2ce2bbd4c24db4 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 19:59:19 -0400 Subject: [PATCH 096/129] changed type of conf to set --- .../ca/uwaterloo/watform/core/DashRef.java | 2 +- .../watform/dashtotla/DashtoTLA.java | 49 +++++++++++++++---- .../uwaterloo/watform/parser/DashModule.java | 6 +-- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java index 1e0d00bec..6b8e82cf4 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/core/DashRef.java @@ -205,7 +205,7 @@ public String toString() { public void toString(StringBuilder out, int indent) { // STATE: Root/A/B[a1,b1] // other: Root/A/B[a1,b1]/var1 - String s = ""; + // String s = ""; if (kind == DashRefKind.STATE) { out.append(getName()); } else { diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 1a88ab0c6..bf3cd86ab 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -20,7 +20,8 @@ public static String translate(DashModule d) StringBuilder translation = new StringBuilder("\nEXTENDS Integers, FiniteSets"); translation.append("\nVARIABLE conf"); - translation.append(boilerplateBasicStates(d)); + translation.append(boilerplateLeafStates(d)); + translation.append(boilerplateAllStates(d)); translation.append(transitions(d)); translation.append(Init(d)); @@ -30,17 +31,42 @@ public static String resolveName(String s) { return s.replace("/", "_"); } - public static String boilerplateBasicStates(DashModule d) + public static String boilerplateLeafStates(DashModule d) { List states = d.getAllStateNames(); - StringBuilder basicStates = new StringBuilder(""); + StringBuilder leafStates = new StringBuilder(""); int ct=0; for(int i =0; i states = d.getAllStateNames(); + StringBuilder code = new StringBuilder(""); + for(String s : states) + { + + code.append("\n"+isInState(s)+" == "); + if(d.isLeaf(s)) + { + code.append(resolveName(s)+" \\in conf"); + continue; + } + // dealing with non-leaf states + List children = d.getImmChildren(s); + for(String ch : children) + code.append("\n\t\\/ "+isInState(ch)); + + } + return code.toString(); } public static String transitions(DashModule d) { @@ -51,6 +77,12 @@ public static String transitions(DashModule d) { List ENTER = toStringList(d.entered(s)); List EXIT = toStringList(d.exited(s)); + + List EXITresolved = new ArrayList<>(); + List ENTERresolved = new ArrayList<>(); + for(String st : ENTER)ENTERresolved.add(resolveName(st)); + for(String st : EXIT)EXITresolved.add(resolveName(st)); + System.out.println("\nTransition:"+s); System.out.println("Entered:"); for(String st : ENTER)System.out.print("|"+st); @@ -58,8 +90,7 @@ public static String transitions(DashModule d) for(String st : EXIT)System.out.print("|"+st); String srcState = d.getTransSrc(s).toString(); - String destState = d.getTransDest(s).toString(); - ts.append("\n"+resolveName(s)+" == conf = "+resolveName(srcState)+" /\\ conf' = "+resolveName(destState)); + ts.append("\n"+resolveName(s)+" == "+isInState(srcState)+" /\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved)); } System.out.println(); @@ -75,7 +106,7 @@ public static String Init(DashModule d) { StringBuilder init = new StringBuilder("\n\nInit == "); List defaultsOfRoot = d.getDefaults(d.getRootName()); - for(String s : defaultsOfRoot)init.append("\n\t\\/ conf == "+resolveName(s)); + for(String s : defaultsOfRoot)init.append("\n\t\\/ "+isInState(s)); return init.toString(); } public static List toStringList(List dfs) @@ -105,7 +136,5 @@ public static String toSetOfStates(List states) } sb.append("}"); return sb.toString(); - - } } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java index c675fcd74..9cc037e78 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/parser/DashModule.java @@ -15,7 +15,7 @@ -import edu.mit.csail.sdg.alloy4.Pair; +//import edu.mit.csail.sdg.alloy4.Pair; import edu.mit.csail.sdg.alloy4.A4Reporter; import edu.mit.csail.sdg.parser.CompModule; import edu.mit.csail.sdg.ast.Expr; @@ -25,9 +25,9 @@ import ca.uwaterloo.watform.ast.*; import static ca.uwaterloo.watform.alloyasthelper.ExprHelper.*; -import ca.uwaterloo.watform.parser.CompModuleHelper; +//import ca.uwaterloo.watform.parser.CompModuleHelper; import ca.uwaterloo.watform.dashtoalloy.DashToAlloy; -import ca.uwaterloo.watform.dashtoalloy.Common; +//import ca.uwaterloo.watform.dashtoalloy.Common; public class DashModule extends CompModuleHelper { From 1d7e1d9b20d9c7d83a439f02f76b7e91786e5d46 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 21:29:52 -0400 Subject: [PATCH 097/129] readability improvements --- .../src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index bf3cd86ab..f26f77663 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -50,7 +50,7 @@ public static String isInState(String state) public static String boilerplateAllStates(DashModule d) { List states = d.getAllStateNames(); - StringBuilder code = new StringBuilder(""); + StringBuilder code = new StringBuilder("\n\n\\* in states"); for(String s : states) { From a6684b2a8e49a18842a4c9c6d5525a4454a2431c Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Tue, 27 Jun 2023 23:57:20 -0400 Subject: [PATCH 098/129] internal names start with _ --- .../main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index f26f77663..73d9c275a 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -29,7 +29,8 @@ public static String translate(DashModule d) } public static String resolveName(String s) { - return s.replace("/", "_"); + char SP = '_'; + return SP+s.replace('/', SP); } public static String boilerplateLeafStates(DashModule d) { From 64c9a7a4194e9d3eab4c7a8b1945a011a4017e7b Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Wed, 28 Jun 2023 02:40:29 -0400 Subject: [PATCH 099/129] changed in states --- .../src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 73d9c275a..ae9b6914b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -46,7 +46,7 @@ public static String boilerplateLeafStates(DashModule d) } public static String isInState(String state) { - return "in_"+resolveName(state); + return "_in"+resolveName(state); } public static String boilerplateAllStates(DashModule d) { From 958d5874434b8094191f7dbe2ae22a148e857598 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Wed, 28 Jun 2023 14:53:35 -0400 Subject: [PATCH 100/129] added design doc --- .../src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md new file mode 100644 index 000000000..0040c86ae --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md @@ -0,0 +1,3 @@ +# Translating Dash to TLA+ + +No variable in the original file can start with underscore since that system is used to denote internal variables within the translation. \ No newline at end of file From 9340211ba892f413de2351e451b25b4d4f615e0c Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Wed, 28 Jun 2023 16:09:47 -0400 Subject: [PATCH 101/129] enable transition on events and send events --- .../watform/dashtotla/DashtoTLA.java | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index ae9b6914b..e52d090ab 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -19,9 +19,10 @@ public static String translate(DashModule d) } StringBuilder translation = new StringBuilder("\nEXTENDS Integers, FiniteSets"); - translation.append("\nVARIABLE conf"); + translation.append("\nVARIABLE conf, events"); translation.append(boilerplateLeafStates(d)); translation.append(boilerplateAllStates(d)); + translation.append(events(d)); translation.append(transitions(d)); translation.append(Init(d)); @@ -69,9 +70,18 @@ public static String boilerplateAllStates(DashModule d) } return code.toString(); } + public static String events(DashModule d) + { + StringBuilder code = new StringBuilder("\n\n\\* events"); + List events = d.getAllInternalEventNames(); + int ct = 0; + for(String ev : events) + code.append("\n"+resolveName(ev)+" == "+(ct++)); + return code.toString(); + } public static String transitions(DashModule d) { - // assumption - trigger and guard are tautologies + // assumption - guard is tautology StringBuilder ts = new StringBuilder("\n\n\\* transitions"); List tranList = d.getAllTransNames(); for(String s : tranList) @@ -84,14 +94,26 @@ public static String transitions(DashModule d) for(String st : ENTER)ENTERresolved.add(resolveName(st)); for(String st : EXIT)EXITresolved.add(resolveName(st)); - System.out.println("\nTransition:"+s); - System.out.println("Entered:"); - for(String st : ENTER)System.out.print("|"+st); - System.out.println("\nExited:"); - for(String st : EXIT)System.out.print("|"+st); + // System.out.println("\nTransition:"+s); + // System.out.println("Entered:"); + // for(String st : ENTER)System.out.print("|"+st); + // System.out.println("\nExited:"); + // for(String st : EXIT)System.out.print("|"+st); String srcState = d.getTransSrc(s).toString(); - ts.append("\n"+resolveName(s)+" == "+isInState(srcState)+" /\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved)); + String ON = ""; + String SEND = ""; + try + { + ON = resolveName(d.getTransOn(s).getName()); + SEND = resolveName(d.getTransSend(s).getName()); + } + catch(NullPointerException e){} + ts.append("\n"+resolveName(s)+" == "+ + "\n\t/\\"+isInState(srcState)+ + "\n\t/\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved)+ + "\n\t/\\ {"+ON+"} \\subseteq events"+ + "\n\t/\\ events' = (events / {"+ON+"}) \\union {"+SEND+"}"); } System.out.println(); @@ -105,9 +127,9 @@ public static String transitions(DashModule d) } public static String Init(DashModule d) { - StringBuilder init = new StringBuilder("\n\nInit == "); + StringBuilder init = new StringBuilder("\n\nInit == events = {}_/\\"); List defaultsOfRoot = d.getDefaults(d.getRootName()); - for(String s : defaultsOfRoot)init.append("\n\t\\/ "+isInState(s)); + for(String s : defaultsOfRoot)init.append("\n\t\t\\/ "+isInState(s)); return init.toString(); } public static List toStringList(List dfs) From b6c5489f29903cc98d41c4c2876357d69f772e2e Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Wed, 28 Jun 2023 17:57:46 -0400 Subject: [PATCH 102/129] toposort enabled --- .../watform/dashtotla/DashtoTLA.java | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index e52d090ab..97f3a7af1 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -3,6 +3,7 @@ import java.util.ArrayList; +import java.util.Collections; import java.util.List; import ca.uwaterloo.watform.parser.DashModule; @@ -51,7 +52,7 @@ public static String isInState(String state) } public static String boilerplateAllStates(DashModule d) { - List states = d.getAllStateNames(); + List states = topoSortStates(d); StringBuilder code = new StringBuilder("\n\n\\* in states"); for(String s : states) { @@ -101,21 +102,24 @@ public static String transitions(DashModule d) // for(String st : EXIT)System.out.print("|"+st); String srcState = d.getTransSrc(s).toString(); - String ON = ""; - String SEND = ""; - try + + String CONF = "\n\t/\\"+isInState(srcState); + String CONF_ = "\n\t/\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved); + + String EVENTS = ""; + String E = "events"; + if(d.getTransOn(s)!=null) { - ON = resolveName(d.getTransOn(s).getName()); - SEND = resolveName(d.getTransSend(s).getName()); - } - catch(NullPointerException e){} - ts.append("\n"+resolveName(s)+" == "+ - "\n\t/\\"+isInState(srcState)+ - "\n\t/\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved)+ - "\n\t/\\ {"+ON+"} \\subseteq events"+ - "\n\t/\\ events' = (events / {"+ON+"}) \\union {"+SEND+"}"); + String ON = resolveName(d.getTransOn(s).getName()); + E = "("+E+" \\ {"+ON+"})"; + EVENTS = "\n\t/\\ {"+ON+"} \\subseteq events"; + } + if(d.getTransSend(s)!=null) + E += " \\union {"+resolveName(d.getTransSend(s).getName())+"}"; + String EVENTS_ = "\n\t/\\ events' = "+E; + + ts.append("\n"+resolveName(s)+" == "+CONF+CONF_+EVENTS+EVENTS_); } - System.out.println(); ts.append("\n\nNext == "); for(String s : tranList) @@ -127,7 +131,7 @@ public static String transitions(DashModule d) } public static String Init(DashModule d) { - StringBuilder init = new StringBuilder("\n\nInit == events = {}_/\\"); + StringBuilder init = new StringBuilder("\n\nInit == events = {} /\\"); List defaultsOfRoot = d.getDefaults(d.getRootName()); for(String s : defaultsOfRoot)init.append("\n\t\t\\/ "+isInState(s)); return init.toString(); @@ -160,4 +164,18 @@ public static String toSetOfStates(List states) sb.append("}"); return sb.toString(); } + public static List topoSortStates(DashModule d) + { + List states = new ArrayList<>(); + states.add(d.getRootName()); + int i = 0; + while(i < states.size()) + { + List children = d.getImmChildren(states.get(i)); + i++; + for(String ch : children)states.add(ch); + } + Collections.reverse(states); + return states; + } } From c169bfa6a0844b237339581479536e299f4f2f18 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Wed, 28 Jun 2023 22:42:24 -0400 Subject: [PATCH 103/129] cleaned up header and footer and modulename, added comments --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 24 ++-- .../watform/dashtotla/DashtoTLA.java | 104 +++++++++--------- .../watform/mainfunctions/MainFunctions.java | 4 +- 3 files changed, 67 insertions(+), 65 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index d817fc9b3..acd3b8675 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -5,7 +5,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.Files; -import java.nio.file.StandardOpenOption; import java.io.BufferedWriter; import java.io.File; @@ -159,18 +158,17 @@ public static void main(String args[]) throws Exception { DashOptions.isTcmc = (method.equals("tcmc")); DashOptions.isElectrum = (method.equals("electrum")); - for (String filename : filelist) { // this whole section may need rewriting + for (String filename : filelist) { // add the .dsh extension if not included if (!filename.endsWith(".dsh") && !filename.endsWith(".als")) { int index = filename.lastIndexOf('.'); - if (index > 0) { + if (index > 0) // if the file has a dot and no "dsh" after it, it is assumed to be a different type of file + { System.err.println("Expected a Dash file with 'dsh' or 'als' extension: "+filename); break; - } else { - - filename = filename + ".dsh"; // use another variable? gets confusing - } + } + else filename = filename + ".dsh"; // if there is no dot, it is assumed that the user forgot to add .dsh } Path f = Paths.get(filename); @@ -210,13 +208,13 @@ public static void main(String args[]) throws Exception { } else if(translateTLA) { d = MainFunctions.resolveDash(d, rep); - String comment = "\\* Modification History\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; - String moduleName = f.getFileName().toString(); - String header = "------------------------------- MODULE "+moduleName.substring(0, moduleName.length()-4)+" -------------------------------"; - String footer = "============================================================================="; - String contents = header+"\n"+MainFunctions.translateTLA(d)+"\n"+footer+"\n"+comment; - + String moduleWithExtension = f.getFileName().toString(); + String moduleName = moduleWithExtension.substring(0, moduleWithExtension.length()-4); + String contents = MainFunctions.translateTLA(d,moduleName); + String TLAfilename = filename.substring(0,filename.length()-4)+".tla"; + + File out = new File(TLAfilename); if (!out.exists()) out.createNewFile(); System.out.println("Creating: " + TLAfilename); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 97f3a7af1..0c6192870 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -5,48 +5,54 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.*; import ca.uwaterloo.watform.parser.DashModule; import ca.uwaterloo.watform.core.DashRef; public class DashtoTLA { - public static String translate(DashModule d) + public static String translate(DashModule d, String moduleName) { if(!d.hasRoot()) { System.out.println("Error - no root state, nothing to translate"); - return ""; + return "\\* Error - no root state, nothing to translate"; } - StringBuilder translation = new StringBuilder("\nEXTENDS Integers, FiniteSets"); - translation.append("\nVARIABLE conf, events"); + String header = "------------------------------- MODULE "+moduleName+" -------------------------------"; + String Extends = "\nEXTENDS Integers, FiniteSets"; + String variables = "\nVARIABLE conf, events"; + StringBuilder translation = new StringBuilder(""); translation.append(boilerplateLeafStates(d)); translation.append(boilerplateAllStates(d)); - translation.append(events(d)); + translation.append(boilerplateInternalEvents(d)); translation.append(transitions(d)); translation.append(Init(d)); + translation.append(Next(d)); + String footer = "\n============================================================================="; + String comment = "\\* Modification History\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; - return translation.toString(); + return header+Extends+variables+translation.toString()+footer+comment; } - public static String resolveName(String s) + public static String resolveName(String s) // get rid of unsupported characters in full names { char SP = '_'; return SP+s.replace('/', SP); } - public static String boilerplateLeafStates(DashModule d) + public static String boilerplateLeafStates(DashModule d) // atoms for each leaf state { List states = d.getAllStateNames(); StringBuilder leafStates = new StringBuilder(""); int ct=0; for(int i =0; i children = d.getImmChildren(s); for(String ch : children) @@ -71,7 +77,7 @@ public static String boilerplateAllStates(DashModule d) } return code.toString(); } - public static String events(DashModule d) + public static String boilerplateInternalEvents(DashModule d) // atoms for each internal event in TLA+ { StringBuilder code = new StringBuilder("\n\n\\* events"); List events = d.getAllInternalEventNames(); @@ -94,15 +100,8 @@ public static String transitions(DashModule d) List ENTERresolved = new ArrayList<>(); for(String st : ENTER)ENTERresolved.add(resolveName(st)); for(String st : EXIT)EXITresolved.add(resolveName(st)); - - // System.out.println("\nTransition:"+s); - // System.out.println("Entered:"); - // for(String st : ENTER)System.out.print("|"+st); - // System.out.println("\nExited:"); - // for(String st : EXIT)System.out.print("|"+st); String srcState = d.getTransSrc(s).toString(); - String CONF = "\n\t/\\"+isInState(srcState); String CONF_ = "\n\t/\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved); @@ -120,51 +119,37 @@ public static String transitions(DashModule d) ts.append("\n"+resolveName(s)+" == "+CONF+CONF_+EVENTS+EVENTS_); } - - ts.append("\n\nNext == "); + return ts.toString(); + } + public static String Next(DashModule d) // Next formula in TLA+ + { + List tranList = d.getAllTransNames(); + StringBuilder next = new StringBuilder("\n\nNext == "); for(String s : tranList) { - ts.append("\n\t/\\ "+resolveName(s)); + next.append("\n\t/\\ "+resolveName(s)); } - - return ts.toString(); + return next.toString(); } - public static String Init(DashModule d) + public static String Init(DashModule d) // Init formula in TLA+ { StringBuilder init = new StringBuilder("\n\nInit == events = {} /\\"); List defaultsOfRoot = d.getDefaults(d.getRootName()); for(String s : defaultsOfRoot)init.append("\n\t\t\\/ "+isInState(s)); return init.toString(); } - public static List toStringList(List dfs) - { - List ls = new ArrayList<>(); - for(DashRef df : dfs)ls.add(df.getName()); - return ls; - } - public static List toStateDashRefList(List ls) - { - List dfs = new ArrayList<>(); - for(String s : ls)dfs.add(DashRef.createStateDashRef(s, null)); - return dfs; - } - public static List toTransitionDashRefList(List ls) - { - List dfs = new ArrayList<>(); - for(String s : ls)dfs.add(DashRef.createTransDashRef(s, null)); - return dfs; - } - public static String toSetOfStates(List states) + public static String toSetOfStates(List states) // set in TLA+ notation { StringBuilder sb = new StringBuilder("{"); - for(int i=0;i topoSortStates(DashModule d) + public static List topoSortStates(DashModule d) // each state occurs only after all its children occur { List states = new ArrayList<>(); states.add(d.getRootName()); @@ -178,4 +163,23 @@ public static List topoSortStates(DashModule d) Collections.reverse(states); return states; } + + // util functions to switch between DashRef and String + public static List toStringList(List dfs) + { + List ls = new ArrayList<>(); + for(DashRef df : dfs)ls.add(df.getName()); + return ls; + } + /* + public static List toDashRefList(List ls, Function createDashRef) + { + List dfs = new ArrayList<>(); + for (String s : ls) { + dfs.add(createDashRef.apply(s)); + } + return dfs; + } + */ + } diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index 5154e6851..ce6c927db 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -65,9 +65,9 @@ public static DashModule translate(DashModule d, A4Reporter rep) { } return d; } - public static String translateTLA(DashModule d) + public static String translateTLA(DashModule d, String moduleName) { - return DashtoTLA.translate(d); + return DashtoTLA.translate(d, moduleName); } public static CompModule resolveAlloy(CompModule c, A4Reporter rep) { From 77d4985f72bfd1fa70d9807f51505aa414bb085e Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 00:01:53 -0400 Subject: [PATCH 104/129] cleaned up spaghetti code in transitions() --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 17 +++++++++- .../watform/dashtotla/DashtoTLA.java | 32 ++++++++++--------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index acd3b8675..e65ae88c7 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -158,8 +158,9 @@ public static void main(String args[]) throws Exception { DashOptions.isTcmc = (method.equals("tcmc")); DashOptions.isElectrum = (method.equals("electrum")); - for (String filename : filelist) { + for (int i=0; i tranList = d.getAllTransNames(); for(String s : tranList) { + // formula for conf + String srcState = d.getTransSrc(s).toString(); + String CONF = "\n\t/\\"+isInState(srcState); + + // formula for conf' List ENTER = toStringList(d.entered(s)); List EXIT = toStringList(d.exited(s)); - List EXITresolved = new ArrayList<>(); List ENTERresolved = new ArrayList<>(); - for(String st : ENTER)ENTERresolved.add(resolveName(st)); - for(String st : EXIT)EXITresolved.add(resolveName(st)); - - String srcState = d.getTransSrc(s).toString(); - String CONF = "\n\t/\\"+isInState(srcState); + ENTER.forEach(st -> ENTERresolved.add(resolveName(st))); + EXIT.forEach(st -> EXITresolved.add(resolveName(st))); String CONF_ = "\n\t/\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved); - + + DashRef ON = d.getTransOn(s); + DashRef SEND = d.getTransSend(s); + + // formula for events String EVENTS = ""; + if(ON!=null)EVENTS = "\n\t/\\ {"+resolveName(ON.getName())+"} \\subseteq events"; + + // formula for events' String E = "events"; - if(d.getTransOn(s)!=null) - { - String ON = resolveName(d.getTransOn(s).getName()); - E = "("+E+" \\ {"+ON+"})"; - EVENTS = "\n\t/\\ {"+ON+"} \\subseteq events"; - } - if(d.getTransSend(s)!=null) - E += " \\union {"+resolveName(d.getTransSend(s).getName())+"}"; + if(ON!=null) E = "("+E+" \\ {"+resolveName(ON.getName())+"})"; // remove consumed events + if(SEND!=null) E += " \\union {"+resolveName(SEND.getName())+"}"; // add generated events String EVENTS_ = "\n\t/\\ events' = "+E; ts.append("\n"+resolveName(s)+" == "+CONF+CONF_+EVENTS+EVENTS_); From 040ada0b1e5f10f26e648c855aa82c69485c5b42 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 00:41:24 -0400 Subject: [PATCH 105/129] ' --- .../src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index e1f62f81e..93dd57d82 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -97,7 +97,7 @@ public static String transitions(DashModule d) String srcState = d.getTransSrc(s).toString(); String CONF = "\n\t/\\"+isInState(srcState); - // formula for conf' + // formula for conf' //t his a test of script List ENTER = toStringList(d.entered(s)); List EXIT = toStringList(d.exited(s)); List EXITresolved = new ArrayList<>(); From ebdda021644acdb56c7a8a12af6c7a33d2d47a48 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 00:42:31 -0400 Subject: [PATCH 106/129] ' --- .../src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 93dd57d82..f0b2b8961 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -97,7 +97,7 @@ public static String transitions(DashModule d) String srcState = d.getTransSrc(s).toString(); String CONF = "\n\t/\\"+isInState(srcState); - // formula for conf' //t his a test of script + // formula for conf' //t his a test of scr List ENTER = toStringList(d.entered(s)); List EXIT = toStringList(d.exited(s)); List EXITresolved = new ArrayList<>(); From d9ecaac7d106f48f9968a5d5d37974d49eccede9 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 00:48:29 -0400 Subject: [PATCH 107/129] ' --- .../ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index f0b2b8961..c901335d3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.function.*; +//import java.util.function.*; import ca.uwaterloo.watform.parser.DashModule; import ca.uwaterloo.watform.core.DashRef; @@ -31,7 +31,7 @@ public static String translate(DashModule d, String moduleName) translation.append(Init(d)); translation.append(Next(d)); String footer = "\n============================================================================="; - String comment = "\\* Modification History\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; + String comment = "\n\\* Modification History\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; return header+Extends+variables+translation.toString()+footer+comment; } @@ -54,7 +54,7 @@ public static String boilerplateLeafStates(DashModule d) // atoms for each leaf } private static String isInState(String state) { - return "_in"+resolveName(state); + return resolveName("in__"+state); } public static String boilerplateAllStates(DashModule d) { @@ -97,7 +97,7 @@ public static String transitions(DashModule d) String srcState = d.getTransSrc(s).toString(); String CONF = "\n\t/\\"+isInState(srcState); - // formula for conf' //t his a test of scr + // formula for conf' List ENTER = toStringList(d.entered(s)); List EXIT = toStringList(d.exited(s)); List EXITresolved = new ArrayList<>(); @@ -183,5 +183,4 @@ public static List toDashRefList(List ls, Function Date: Thu, 29 Jun 2023 00:55:09 -0400 Subject: [PATCH 108/129] ' --- .../src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index c901335d3..6b3ccf474 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -97,7 +97,7 @@ public static String transitions(DashModule d) String srcState = d.getTransSrc(s).toString(); String CONF = "\n\t/\\"+isInState(srcState); - // formula for conf' + // formula for conf' another test, message not working List ENTER = toStringList(d.entered(s)); List EXIT = toStringList(d.exited(s)); List EXITresolved = new ArrayList<>(); From dc2fe6d13eb2089cfd03aabf561c3a44479c3608 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 01:14:57 -0400 Subject: [PATCH 109/129] bug fix on autocommit --- .../src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 6b3ccf474..c901335d3 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -97,7 +97,7 @@ public static String transitions(DashModule d) String srcState = d.getTransSrc(s).toString(); String CONF = "\n\t/\\"+isInState(srcState); - // formula for conf' another test, message not working + // formula for conf' List ENTER = toStringList(d.entered(s)); List EXIT = toStringList(d.exited(s)); List EXITresolved = new ArrayList<>(); From 9a3d1e458743c27efa1889ad33202bda8afe7ce9 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 02:19:11 -0400 Subject: [PATCH 110/129] stricter constraints on use of underscore --- .../src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md index 0040c86ae..b52981ac0 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md @@ -1,3 +1,3 @@ # Translating Dash to TLA+ -No variable in the original file can start with underscore since that system is used to denote internal variables within the translation. \ No newline at end of file +No variable in the original file can contain underscore since that character is used to denote internal variables within the translation. From 9f686bdf0c0f8442fe8e10d6ba19088b1507477f Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 14:51:28 -0400 Subject: [PATCH 111/129] separated pre and post conditions --- .../ca/uwaterloo/watform/dash4whole/Dash.java | 1 + .../watform/dashtotla/DashtoTLA.java | 84 ++++++++++++------- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index e65ae88c7..744fede9d 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -86,6 +86,7 @@ public static void main(String args[]) throws Exception { System.out.println("-t is translateOnly"); System.out.println("-r is resolveOnly"); System.out.println("-e is echo file from internal parsed data"); + // TODO edit this System.out.println("-tla produces a translation to TLA+, with the same file name as the dash file, in the same folder as the original dash file"); System.out.println("expects .dsh or .als file"); System.out.println("if given a .als files, it ignores other options and runs all its commands"); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index c901335d3..285114cd5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -24,8 +24,8 @@ public static String translate(DashModule d, String moduleName) String Extends = "\nEXTENDS Integers, FiniteSets"; String variables = "\nVARIABLE conf, events"; StringBuilder translation = new StringBuilder(""); - translation.append(boilerplateLeafStates(d)); - translation.append(boilerplateAllStates(d)); + translation.append(createLeafStates(d)); + translation.append(createAllStates(d)); translation.append(boilerplateInternalEvents(d)); translation.append(transitions(d)); translation.append(Init(d)); @@ -40,7 +40,7 @@ public static String resolveName(String s) // get rid of unsupported characters char SP = '_'; return SP+s.replace('/', SP); } - public static String boilerplateLeafStates(DashModule d) // atoms for each leaf state + public static String createLeafStates(DashModule d) // atoms for each leaf state { List states = d.getAllStateNames(); StringBuilder leafStates = new StringBuilder(""); @@ -56,7 +56,7 @@ private static String isInState(String state) { return resolveName("in__"+state); } - public static String boilerplateAllStates(DashModule d) + public static String createAllStates(DashModule d) { List states = topoSortStates(d); StringBuilder code = new StringBuilder("\n\n\\* in states"); @@ -86,6 +86,48 @@ public static String boilerplateInternalEvents(DashModule d) // atoms for each i code.append("\n"+resolveName(ev)+" == "+(ct++)); return code.toString(); } + public static String postCondition(DashModule d, String trans) + { + StringBuilder code = new StringBuilder(""); + + // conf' + List ENTER = toStringList(d.entered(trans)); + List EXIT = toStringList(d.exited(trans)); + List EXITresolved = new ArrayList<>(); + List ENTERresolved = new ArrayList<>(); + ENTER.forEach(st -> ENTERresolved.add(resolveName(st))); + EXIT.forEach(st -> EXITresolved.add(resolveName(st))); + String CONF_ = "\n\t/\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved); + + // events' + DashRef ON = d.getTransOn(trans); + DashRef SEND = d.getTransSend(trans); + String E = "events"; + if(ON!=null) E = "("+E+" \\ {"+resolveName(ON.getName())+"})"; // remove consumed events + if(SEND!=null) E += " \\union {"+resolveName(SEND.getName())+"}"; // add generated events + String EVENTS_ = "\n\t/\\ events' = "+E; + + code.append(CONF_); + code.append(EVENTS_); + return code.toString(); + } + public static String preCondition(DashModule d, String trans) + { + StringBuilder code = new StringBuilder(""); + + // conf + String srcState = d.getTransSrc(trans).toString(); + String CONF = "\n\t/\\ "+isInState(srcState); + + // formula for events + DashRef ON = d.getTransOn(trans); + String EVENTS = ""; + if(ON!=null)EVENTS = "\n\t/\\ {"+resolveName(ON.getName())+"} \\subseteq events"; + + code.append(CONF); + code.append(EVENTS); + return code.toString(); + } public static String transitions(DashModule d) { // assumption - guard is tautology @@ -93,33 +135,11 @@ public static String transitions(DashModule d) List tranList = d.getAllTransNames(); for(String s : tranList) { - // formula for conf - String srcState = d.getTransSrc(s).toString(); - String CONF = "\n\t/\\"+isInState(srcState); - - // formula for conf' - List ENTER = toStringList(d.entered(s)); - List EXIT = toStringList(d.exited(s)); - List EXITresolved = new ArrayList<>(); - List ENTERresolved = new ArrayList<>(); - ENTER.forEach(st -> ENTERresolved.add(resolveName(st))); - EXIT.forEach(st -> EXITresolved.add(resolveName(st))); - String CONF_ = "\n\t/\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved); - - DashRef ON = d.getTransOn(s); - DashRef SEND = d.getTransSend(s); - - // formula for events - String EVENTS = ""; - if(ON!=null)EVENTS = "\n\t/\\ {"+resolveName(ON.getName())+"} \\subseteq events"; - - // formula for events' - String E = "events"; - if(ON!=null) E = "("+E+" \\ {"+resolveName(ON.getName())+"})"; // remove consumed events - if(SEND!=null) E += " \\union {"+resolveName(SEND.getName())+"}"; // add generated events - String EVENTS_ = "\n\t/\\ events' = "+E; - - ts.append("\n"+resolveName(s)+" == "+CONF+CONF_+EVENTS+EVENTS_); + String preConditionName = "_pre__"+resolveName(s); + String postConditionName = "_post__"+resolveName(s); + ts.append("\n\n"+preConditionName+" == "+preCondition(d, s)); + ts.append("\n"+postConditionName+" == "+postCondition(d, s)); + ts.append("\n"+resolveName(s)+" == "+preConditionName+" /\\ "+postConditionName); } return ts.toString(); } @@ -129,7 +149,7 @@ public static String Next(DashModule d) // Next formula in TLA+ StringBuilder next = new StringBuilder("\n\nNext == "); for(String s : tranList) { - next.append("\n\t/\\ "+resolveName(s)); + next.append("\n\t\\/ "+resolveName(s)); } return next.toString(); } From 28205aadeff7e2f0a70582094e67402718435004 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 16:26:35 -0400 Subject: [PATCH 112/129] update to DesignDocs --- .../uwaterloo/watform/dashtotla/DesignDoc.md | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md index b52981ac0..ee5816cbf 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md @@ -1,3 +1,48 @@ # Translating Dash to TLA+ -No variable in the original file can contain underscore since that character is used to denote internal variables within the translation. +## Preface + +This document specifies the design details of a program to convert `.dsh` files to [TLA+](https://lamport.azurewebsites.net/tla/tla.html). + +## Running the Translator + +### Prerequisites + +- A runnable `.jar` file built from [https://github.com/WatForm/org.alloytools.alloy](https://github.com/WatForm/org.alloytools.alloy) + +- The target files are in a destination which can be read and written into by the `.jar` file + +The general format to run the translator: + +``` +java -cp ca.uwaterloo.watform.dash4whole.Dash -tla +``` + +The `` consists of a list of complete paths to the `.dsh` files, separated by spaces. + +By default, the translated files are stored in the same location as the source files with the same name and a `.tla` extension. In case one wishes to give a custom path as the target file, one can insert the full path to the target file immediately after the corresponding source file path. + +For instance, the following command translates `file1.dsh` and writes the TLA+ code into `target.tla` +``` +java -cp ./org.alloytools.alloy.dist.jar ca.uwaterloo.watform.dash4whole.Dash -tla ./file1.dsh ../new_folder/target.tla +``` + +The same format is followed when multiple `.dsh` files are translated at a time. For each `.dsh` file, a default target is created if the target file is left unspecified. + +## Guide to the Source Code + +All translation is done by [DashtoTLA.java](). The argument `-tla` is defined in [Dash.java](), which calls `MainFunctions.translateTLA() ` in [MainFunctions.java](), which in turn calls `DashtoTLA.translate()`. + +## Design Decisions + +- No variable in the original file can contain underscore since that character is used to denote internal variables within the translation. + +- The entire translation is restricted to a single module since one `.tla` file is expected to contain exactly one module definition. + +- The module name in a `.tla` file must be the same as the name of the file, which is in turn the same as the name of the source `.dsh` file. Thus the name of the source file is passed to the translator which names the module. + +- The translator adds a comment stating the modification history at the end of the module, in a manner similar to the comment autogenerated by toolbox, the official TLA+ IDE. + +- Timestamp is given in terms of Unix epoch to avoid problems with international timezones and daylight savings. + + From db98aafdef1541232bf118d41981bf903afc9ecd Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 16:56:23 -0400 Subject: [PATCH 113/129] changed atoms to String type --- .../ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 11 +++++------ .../java/ca/uwaterloo/watform/dashtotla/DesignDoc.md | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 285114cd5..b4e6ffcd5 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -44,12 +44,11 @@ public static String createLeafStates(DashModule d) // atoms for each leaf state { List states = d.getAllStateNames(); StringBuilder leafStates = new StringBuilder(""); - int ct=0; - for(int i =0; i Date: Thu, 29 Jun 2023 17:18:36 -0400 Subject: [PATCH 114/129] got rid of capital varnames --- .../watform/dashtotla/DashtoTLA.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index b4e6ffcd5..c624576ae 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -90,24 +90,24 @@ public static String postCondition(DashModule d, String trans) StringBuilder code = new StringBuilder(""); // conf' - List ENTER = toStringList(d.entered(trans)); - List EXIT = toStringList(d.exited(trans)); - List EXITresolved = new ArrayList<>(); - List ENTERresolved = new ArrayList<>(); - ENTER.forEach(st -> ENTERresolved.add(resolveName(st))); - EXIT.forEach(st -> EXITresolved.add(resolveName(st))); - String CONF_ = "\n\t/\\ conf' = (conf \\ "+toSetOfStates(EXITresolved)+" ) \\union "+toSetOfStates(ENTERresolved); + List entered = toStringList(d.entered(trans)); + List exited = toStringList(d.exited(trans)); + List exitedResolved = new ArrayList<>(); + List enteredResolved = new ArrayList<>(); + entered.forEach(st -> enteredResolved.add(resolveName(st))); + exited.forEach(st -> exitedResolved.add(resolveName(st))); + String confPrimed = "\n\t/\\ conf' = (conf \\ "+toSetOfStates(exitedResolved)+" ) \\union "+toSetOfStates(enteredResolved); // events' - DashRef ON = d.getTransOn(trans); - DashRef SEND = d.getTransSend(trans); + DashRef on = d.getTransOn(trans); + DashRef send = d.getTransSend(trans); String E = "events"; - if(ON!=null) E = "("+E+" \\ {"+resolveName(ON.getName())+"})"; // remove consumed events - if(SEND!=null) E += " \\union {"+resolveName(SEND.getName())+"}"; // add generated events - String EVENTS_ = "\n\t/\\ events' = "+E; + if(on!=null) E = "("+E+" \\ {"+resolveName(on.getName())+"})"; // remove consumed events + if(send!=null) E += " \\union {"+resolveName(send.getName())+"}"; // add generated events + String eventsPrimed = "\n\t/\\ events' = "+E; - code.append(CONF_); - code.append(EVENTS_); + code.append(confPrimed); + code.append(eventsPrimed); return code.toString(); } public static String preCondition(DashModule d, String trans) From 62c2727b6a227f9a630c021751b8a9a98a2fd418 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 17:25:37 -0400 Subject: [PATCH 115/129] added global formula names --- .../uwaterloo/watform/dashtotla/DashtoTLA.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index c624576ae..d02a9fd00 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -12,6 +12,16 @@ public class DashtoTLA { + // common formulae shared by all functions + public static final String INIT = "Init"; + public static final String NEXT = "Next"; + public static final String TYPE_OK = "TypeOK"; + public static final String EXISTS_ENABLED_TRANSITION = "_exists_enabled_tranistions"; + public static final String STUTTER = "stutter"; + public static final String CONF = "conf"; + public static final String EVENTS = "events"; + + //public static final String = ""; public static String translate(DashModule d, String moduleName) { if(!d.hasRoot()) @@ -22,7 +32,7 @@ public static String translate(DashModule d, String moduleName) String header = "------------------------------- MODULE "+moduleName+" -------------------------------"; String Extends = "\nEXTENDS Integers, FiniteSets"; - String variables = "\nVARIABLE conf, events"; + String variables = "\nVARIABLE "+CONF+", "+EVENTS; StringBuilder translation = new StringBuilder(""); translation.append(createLeafStates(d)); translation.append(createAllStates(d)); @@ -64,7 +74,7 @@ public static String createAllStates(DashModule d) code.append("\n"+isInState(s)+" == "); if(d.isLeaf(s)) { - code.append(resolveName(s)+" \\in conf"); + code.append(resolveName(s)+" \\in "+CONF); continue; } @@ -96,7 +106,7 @@ public static String postCondition(DashModule d, String trans) List enteredResolved = new ArrayList<>(); entered.forEach(st -> enteredResolved.add(resolveName(st))); exited.forEach(st -> exitedResolved.add(resolveName(st))); - String confPrimed = "\n\t/\\ conf' = (conf \\ "+toSetOfStates(exitedResolved)+" ) \\union "+toSetOfStates(enteredResolved); + String confPrimed = "\n\t/\\ "+CONF+"' = ("+CONF+" \\ "+toSetOfStates(exitedResolved)+" ) \\union "+toSetOfStates(enteredResolved); // events' DashRef on = d.getTransOn(trans); From f0f72c2dfb80ed18417bc6910ff002a8f8fa62d9 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 17:46:44 -0400 Subject: [PATCH 116/129] added stutter --- .../watform/dashtotla/DashtoTLA.java | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index d02a9fd00..f22782287 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -18,8 +18,12 @@ public class DashtoTLA public static final String TYPE_OK = "TypeOK"; public static final String EXISTS_ENABLED_TRANSITION = "_exists_enabled_tranistions"; public static final String STUTTER = "stutter"; + + // variables public static final String CONF = "conf"; + public static final String CONF_PRIMED = CONF+"'"; public static final String EVENTS = "events"; + public static final String EVENTS_PRIMED = EVENTS+"'"; //public static final String = ""; public static String translate(DashModule d, String moduleName) @@ -39,6 +43,7 @@ public static String translate(DashModule d, String moduleName) translation.append(boilerplateInternalEvents(d)); translation.append(transitions(d)); translation.append(Init(d)); + translation.append(Stutter(d)); translation.append(Next(d)); String footer = "\n============================================================================="; String comment = "\n\\* Modification History\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; @@ -106,7 +111,7 @@ public static String postCondition(DashModule d, String trans) List enteredResolved = new ArrayList<>(); entered.forEach(st -> enteredResolved.add(resolveName(st))); exited.forEach(st -> exitedResolved.add(resolveName(st))); - String confPrimed = "\n\t/\\ "+CONF+"' = ("+CONF+" \\ "+toSetOfStates(exitedResolved)+" ) \\union "+toSetOfStates(enteredResolved); + String confPrimed = "\n\t/\\ "+CONF_PRIMED+" = ("+CONF+" \\ "+toSetOfStates(exitedResolved)+" ) \\union "+toSetOfStates(enteredResolved); // events' DashRef on = d.getTransOn(trans); @@ -142,6 +147,7 @@ public static String transitions(DashModule d) // assumption - guard is tautology StringBuilder ts = new StringBuilder("\n\n\\* transitions"); List tranList = d.getAllTransNames(); + List preCondList = new ArrayList<>(); for(String s : tranList) { String preConditionName = "_pre__"+resolveName(s); @@ -149,13 +155,26 @@ public static String transitions(DashModule d) ts.append("\n\n"+preConditionName+" == "+preCondition(d, s)); ts.append("\n"+postConditionName+" == "+postCondition(d, s)); ts.append("\n"+resolveName(s)+" == "+preConditionName+" /\\ "+postConditionName); + preCondList.add(postConditionName); } - return ts.toString(); + + StringBuilder somePrecond = new StringBuilder("\n"+EXISTS_ENABLED_TRANSITION+" == "); + for(String s : preCondList) + somePrecond.append("\n\t/\\ "+s); + + return ts.append(somePrecond).toString(); + } + public static String Stutter(DashModule d) + { + return "\n\n"+STUTTER+" == ~"+EXISTS_ENABLED_TRANSITION+ + "\n\t/\\ "+CONF_PRIMED+" = "+CONF+ + "\n\t/\\ "+EVENTS_PRIMED+" = "+EVENTS; + } public static String Next(DashModule d) // Next formula in TLA+ { List tranList = d.getAllTransNames(); - StringBuilder next = new StringBuilder("\n\nNext == "); + StringBuilder next = new StringBuilder("\n\n"+NEXT+" == "+STUTTER); for(String s : tranList) { next.append("\n\t\\/ "+resolveName(s)); @@ -164,7 +183,7 @@ public static String Next(DashModule d) // Next formula in TLA+ } public static String Init(DashModule d) // Init formula in TLA+ { - StringBuilder init = new StringBuilder("\n\nInit == events = {} /\\"); + StringBuilder init = new StringBuilder("\n\n"+INIT+" == "+EVENTS+" = {} /\\"); List defaultsOfRoot = d.getDefaults(d.getRootName()); for(String s : defaultsOfRoot)init.append("\n\t\t\\/ "+isInState(s)); return init.toString(); From fc3c8e26f922ef04215ac00c88198565e1b0489e Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 17:58:40 -0400 Subject: [PATCH 117/129] bug fix pre vs post --- .../java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 8 ++++---- .../main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index f22782287..fff4bf855 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -122,7 +122,7 @@ public static String postCondition(DashModule d, String trans) String eventsPrimed = "\n\t/\\ events' = "+E; code.append(confPrimed); - code.append(eventsPrimed); + //code.append(eventsPrimed); return code.toString(); } public static String preCondition(DashModule d, String trans) @@ -139,7 +139,7 @@ public static String preCondition(DashModule d, String trans) if(ON!=null)EVENTS = "\n\t/\\ {"+resolveName(ON.getName())+"} \\subseteq events"; code.append(CONF); - code.append(EVENTS); + //code.append(EVENTS); return code.toString(); } public static String transitions(DashModule d) @@ -155,10 +155,10 @@ public static String transitions(DashModule d) ts.append("\n\n"+preConditionName+" == "+preCondition(d, s)); ts.append("\n"+postConditionName+" == "+postCondition(d, s)); ts.append("\n"+resolveName(s)+" == "+preConditionName+" /\\ "+postConditionName); - preCondList.add(postConditionName); + preCondList.add(preConditionName); } - StringBuilder somePrecond = new StringBuilder("\n"+EXISTS_ENABLED_TRANSITION+" == "); + StringBuilder somePrecond = new StringBuilder("\n\n"+EXISTS_ENABLED_TRANSITION+" == "); for(String s : preCondList) somePrecond.append("\n\t/\\ "+s); diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md index 55c33fa83..f970e98ff 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md @@ -47,4 +47,6 @@ All translation is done by [DashtoTLA.java](). The argument `-tla` is defined in - TLA+ does not support non-primitive unspecified atoms, so each leaf state is defined using a string holding their fully qualified name. +- Transitions are formulae and remain so. there is no treatment of them as objects or use of a `TransTaken` set + From ec1cf32aa13027407027c84c67a4a408297a62d3 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 18:24:36 -0400 Subject: [PATCH 118/129] removed events from transitions and stringified atoms --- .../java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index fff4bf855..37d3c53b8 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -40,7 +40,7 @@ public static String translate(DashModule d, String moduleName) StringBuilder translation = new StringBuilder(""); translation.append(createLeafStates(d)); translation.append(createAllStates(d)); - translation.append(boilerplateInternalEvents(d)); + translation.append(atomsInternalEvents(d)); translation.append(transitions(d)); translation.append(Init(d)); translation.append(Stutter(d)); @@ -91,13 +91,12 @@ public static String createAllStates(DashModule d) } return code.toString(); } - public static String boilerplateInternalEvents(DashModule d) // atoms for each internal event in TLA+ + public static String atomsInternalEvents(DashModule d) // atoms for each internal event in TLA+ { StringBuilder code = new StringBuilder("\n\n\\* events"); List events = d.getAllInternalEventNames(); - int ct = 0; for(String ev : events) - code.append("\n"+resolveName(ev)+" == "+(ct++)); + code.append("\n"+resolveName(ev)+" == \""+ev+"\""); return code.toString(); } public static String postCondition(DashModule d, String trans) From f46703ba82e9dd381091ff431e93c7e78fc06e13 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 29 Jun 2023 18:31:04 -0400 Subject: [PATCH 119/129] edited help for command --- .../src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java index 744fede9d..19edc69b9 100644 --- a/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java +++ b/org.alloytools.alloy.application/src/main/java/ca/uwaterloo/watform/dash4whole/Dash.java @@ -22,7 +22,7 @@ import ca.uwaterloo.watform.core.DashOptions; import ca.uwaterloo.watform.core.DashErrors; -// import ca.uwaterloo.watform.parser.DashUtil; +import ca.uwaterloo.watform.parser.DashUtil; import ca.uwaterloo.watform.core.DashUtilFcns; import ca.uwaterloo.watform.parser.DashModule; import ca.uwaterloo.watform.mainfunctions.MainFunctions; @@ -86,8 +86,7 @@ public static void main(String args[]) throws Exception { System.out.println("-t is translateOnly"); System.out.println("-r is resolveOnly"); System.out.println("-e is echo file from internal parsed data"); - // TODO edit this - System.out.println("-tla produces a translation to TLA+, with the same file name as the dash file, in the same folder as the original dash file"); + System.out.println("-tla translates the file to TLA+, translated file has the same path and name unless otherwise specified"); System.out.println("expects .dsh or .als file"); System.out.println("if given a .als files, it ignores other options and runs all its commands"); System.exit(0); From 98f4c6e505a8e5baa6cf0dc3e544897336c487c0 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Fri, 30 Jun 2023 03:29:19 -0400 Subject: [PATCH 120/129] rewrote in a more modular form, cleaned up spaghetti code --- .../watform/dashtotla/DashtoTLA.java | 100 ++++++++++++++---- 1 file changed, 77 insertions(+), 23 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 37d3c53b8..ac67fee66 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -17,13 +17,18 @@ public class DashtoTLA public static final String NEXT = "Next"; public static final String TYPE_OK = "TypeOK"; public static final String EXISTS_ENABLED_TRANSITION = "_exists_enabled_tranistions"; - public static final String STUTTER = "stutter"; + public static final String STUTTER = "_stutter"; // variables - public static final String CONF = "conf"; - public static final String CONF_PRIMED = CONF+"'"; - public static final String EVENTS = "events"; - public static final String EVENTS_PRIMED = EVENTS+"'"; + public static final String CONF = "_conf"; + public static final String INTERNAL_EVENTS = "_internal_events"; + public static final String ENVIRONMENTAL_EVENTS = "_environmental_events"; + + // variable in next step + public static String prime(String variable){return variable+"'";} + + // set holding every value which can appear as element of variable + public static String maximal(String variable){return variable+"_maximal";} //public static final String = ""; public static String translate(DashModule d, String moduleName) @@ -36,11 +41,13 @@ public static String translate(DashModule d, String moduleName) String header = "------------------------------- MODULE "+moduleName+" -------------------------------"; String Extends = "\nEXTENDS Integers, FiniteSets"; - String variables = "\nVARIABLE "+CONF+", "+EVENTS; + String variables = "\nVARIABLE "+CONF+", "+INTERNAL_EVENTS+", "+ENVIRONMENTAL_EVENTS; StringBuilder translation = new StringBuilder(""); - translation.append(createLeafStates(d)); - translation.append(createAllStates(d)); + translation.append(atomsLeafStates(d)); translation.append(atomsInternalEvents(d)); + translation.append(maximalSets(d)); + translation.append(TypeOK(d)); + translation.append(createAllStates(d)); translation.append(transitions(d)); translation.append(Init(d)); translation.append(Stutter(d)); @@ -55,31 +62,57 @@ public static String resolveName(String s) // get rid of unsupported characters char SP = '_'; return SP+s.replace('/', SP); } - public static String createLeafStates(DashModule d) // atoms for each leaf state + public static String atomsLeafStates(DashModule d) // atoms for each leaf state { List states = d.getAllStateNames(); - StringBuilder leafStates = new StringBuilder(""); + StringBuilder leafStates = new StringBuilder("\n\n\\* basic states"); for(String s : states) - if(d.isLeaf(s)) + if(d.isLeaf(s)) leafStates.append("\n"+resolveName(s)+" == \""+s+"\""); + - return "\n\n\\* basic states"+leafStates; + return leafStates.toString(); } private static String isInState(String state) { return resolveName("in__"+state); } + public static String maximalSets(DashModule d) + { + StringBuilder code = new StringBuilder("\n"); + + // conf + List resolvedStateNames = new ArrayList<>(); + for(String s : d.getAllStateNames()) + if(d.isLeaf(s)) + resolvedStateNames.add(resolveName(s)); + code.append("\n"+maximal(CONF)+" == "+toSet(resolvedStateNames)); + + // internal events + List resolvedInternalEventNames = new ArrayList<>(); + for(String s : d.getAllInternalEventNames())resolvedInternalEventNames.add(resolveName(s)); + code.append("\n"+maximal(INTERNAL_EVENTS)+" == "+toSet(resolvedInternalEventNames)); + + // environmental events + List resolvedEnvironmentalEventNames = new ArrayList<>(); + for(String s : d.getAllEnvironmentalEventNames())resolvedEnvironmentalEventNames.add(resolveName(s)); + code.append("\n"+maximal(ENVIRONMENTAL_EVENTS)+" == "+toSet(resolvedEnvironmentalEventNames)); + + return code.toString(); + } public static String createAllStates(DashModule d) { List states = topoSortStates(d); + StringBuilder code = new StringBuilder("\n\n\\* in states"); for(String s : states) { code.append("\n"+isInState(s)+" == "); if(d.isLeaf(s)) { - code.append(resolveName(s)+" \\in "+CONF); + String resolved = resolveName(s); + code.append(resolved+" \\in "+CONF); continue; } @@ -110,7 +143,7 @@ public static String postCondition(DashModule d, String trans) List enteredResolved = new ArrayList<>(); entered.forEach(st -> enteredResolved.add(resolveName(st))); exited.forEach(st -> exitedResolved.add(resolveName(st))); - String confPrimed = "\n\t/\\ "+CONF_PRIMED+" = ("+CONF+" \\ "+toSetOfStates(exitedResolved)+" ) \\union "+toSetOfStates(enteredResolved); + String confPrimed = "\n\t/\\ "+prime(CONF)+" = ("+CONF+" \\ "+toSet(exitedResolved)+" ) \\union "+toSet(enteredResolved); // events' DashRef on = d.getTransOn(trans); @@ -166,8 +199,8 @@ public static String transitions(DashModule d) public static String Stutter(DashModule d) { return "\n\n"+STUTTER+" == ~"+EXISTS_ENABLED_TRANSITION+ - "\n\t/\\ "+CONF_PRIMED+" = "+CONF+ - "\n\t/\\ "+EVENTS_PRIMED+" = "+EVENTS; + "\n\t/\\ "+prime(CONF)+" = "+CONF+ + "\n\t/\\ "+prime(INTERNAL_EVENTS)+" = "+INTERNAL_EVENTS; } public static String Next(DashModule d) // Next formula in TLA+ @@ -180,24 +213,47 @@ public static String Next(DashModule d) // Next formula in TLA+ } return next.toString(); } + public static String TypeOK(DashModule d) // TypeOK formula in TLA+ + { + String variables[] = new String[]{CONF, INTERNAL_EVENTS, ENVIRONMENTAL_EVENTS}; + + StringBuilder code = new StringBuilder("\n\n\\* type-checking\n"+TYPE_OK+" == "); + for(String s : variables) + code.append("\n\t/\\ (\\A x \\in "+s+" : x \\in "+maximal(s)+")"); + + return code.toString(); + } public static String Init(DashModule d) // Init formula in TLA+ { - StringBuilder init = new StringBuilder("\n\n"+INIT+" == "+EVENTS+" = {} /\\"); + StringBuilder init = new StringBuilder("\n\n"+INIT+" == "+INTERNAL_EVENTS+" = {} /\\"); List defaultsOfRoot = d.getDefaults(d.getRootName()); for(String s : defaultsOfRoot)init.append("\n\t\t\\/ "+isInState(s)); return init.toString(); } - public static String toSetOfStates(List states) // set in TLA+ notation + public static String toSet(List elements) // set in TLA+ notation + { + StringBuilder sb = new StringBuilder("{"); + for(int i=0;i elements) // set of strings in TLA+ notation { StringBuilder sb = new StringBuilder("{"); - for(int i=0;i topoSortStates(DashModule d) // each state occurs only after all its children occur { List states = new ArrayList<>(); @@ -212,8 +268,6 @@ public static List topoSortStates(DashModule d) // each state occurs onl Collections.reverse(states); return states; } - - // util functions to switch between DashRef and String public static List toStringList(List dfs) { List ls = new ArrayList<>(); From 7d4408f0fb523050b057a58426c2ccbe85e7fc53 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Fri, 30 Jun 2023 18:24:44 -0400 Subject: [PATCH 121/129] commented and documented design --- .../watform/dashtotla/DashtoTLA.java | 59 +++++++++++-------- .../uwaterloo/watform/dashtotla/DesignDoc.md | 4 ++ 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index ac67fee66..b374d2bf6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -45,6 +45,7 @@ public static String translate(DashModule d, String moduleName) StringBuilder translation = new StringBuilder(""); translation.append(atomsLeafStates(d)); translation.append(atomsInternalEvents(d)); + translation.append(atomsEnvironmentalEvents(d)); translation.append(maximalSets(d)); translation.append(TypeOK(d)); translation.append(createAllStates(d)); @@ -53,13 +54,14 @@ public static String translate(DashModule d, String moduleName) translation.append(Stutter(d)); translation.append(Next(d)); String footer = "\n============================================================================="; - String comment = "\n\\* Modification History\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; + String comment = "\n\\* Modification History"+ + "\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; return header+Extends+variables+translation.toString()+footer+comment; } public static String resolveName(String s) // get rid of unsupported characters in full names { - char SP = '_'; + char SP = '_'; // SP is a specual character that cannot appear in any variablename in dash, but can in TLA+ return SP+s.replace('/', SP); } public static String atomsLeafStates(DashModule d) // atoms for each leaf state @@ -71,16 +73,15 @@ public static String atomsLeafStates(DashModule d) // atoms for each leaf state if(d.isLeaf(s)) leafStates.append("\n"+resolveName(s)+" == \""+s+"\""); - return leafStates.toString(); } - private static String isInState(String state) + private static String isInState(String state) // used to check if one is in a non-leaf state { return resolveName("in__"+state); } - public static String maximalSets(DashModule d) + public static String maximalSets(DashModule d) // define the set of all possible values for a variable's elements { - StringBuilder code = new StringBuilder("\n"); + StringBuilder code = new StringBuilder("\n\n\\* maximal states"); // conf List resolvedStateNames = new ArrayList<>(); @@ -101,7 +102,7 @@ public static String maximalSets(DashModule d) return code.toString(); } - public static String createAllStates(DashModule d) + public static String createAllStates(DashModule d) // formulae to determine if one is present in a state { List states = topoSortStates(d); @@ -126,12 +127,20 @@ public static String createAllStates(DashModule d) } public static String atomsInternalEvents(DashModule d) // atoms for each internal event in TLA+ { - StringBuilder code = new StringBuilder("\n\n\\* events"); + StringBuilder code = new StringBuilder("\n\n\\* internal events"); List events = d.getAllInternalEventNames(); for(String ev : events) code.append("\n"+resolveName(ev)+" == \""+ev+"\""); return code.toString(); } + public static String atomsEnvironmentalEvents(DashModule d) // atoms for each internal event in TLA+ + { + StringBuilder code = new StringBuilder("\n\n\\* environmental events"); + List events = d.getAllEnvironmentalEventNames(); + for(String ev : events) + code.append("\n"+resolveName(ev)+" == \""+ev+"\""); + return code.toString(); + } public static String postCondition(DashModule d, String trans) { StringBuilder code = new StringBuilder(""); @@ -139,22 +148,18 @@ public static String postCondition(DashModule d, String trans) // conf' List entered = toStringList(d.entered(trans)); List exited = toStringList(d.exited(trans)); - List exitedResolved = new ArrayList<>(); - List enteredResolved = new ArrayList<>(); - entered.forEach(st -> enteredResolved.add(resolveName(st))); - exited.forEach(st -> exitedResolved.add(resolveName(st))); - String confPrimed = "\n\t/\\ "+prime(CONF)+" = ("+CONF+" \\ "+toSet(exitedResolved)+" ) \\union "+toSet(enteredResolved); + String confPrimed = "\n\t/\\ "+prime(CONF)+" = ("+CONF+" \\ "+toSetResolved(exited)+" ) \\union "+toSetResolved(entered); // events' DashRef on = d.getTransOn(trans); DashRef send = d.getTransSend(trans); - String E = "events"; + String E = INTERNAL_EVENTS; if(on!=null) E = "("+E+" \\ {"+resolveName(on.getName())+"})"; // remove consumed events if(send!=null) E += " \\union {"+resolveName(send.getName())+"}"; // add generated events - String eventsPrimed = "\n\t/\\ events' = "+E; + String eventsPrimed = "\n\t/\\ "+prime(INTERNAL_EVENTS)+" = "+E; code.append(confPrimed); - //code.append(eventsPrimed); + code.append(eventsPrimed); return code.toString(); } public static String preCondition(DashModule d, String trans) @@ -168,10 +173,10 @@ public static String preCondition(DashModule d, String trans) // formula for events DashRef ON = d.getTransOn(trans); String EVENTS = ""; - if(ON!=null)EVENTS = "\n\t/\\ {"+resolveName(ON.getName())+"} \\subseteq events"; + if(ON!=null)EVENTS = "\n\t/\\ {"+resolveName(ON.getName())+"} \\subseteq "+INTERNAL_EVENTS; code.append(CONF); - //code.append(EVENTS); + code.append(EVENTS); return code.toString(); } public static String transitions(DashModule d) @@ -196,6 +201,7 @@ public static String transitions(DashModule d) return ts.append(somePrecond).toString(); } + // when no tranitions are enabled, the system stays in current state while waiting for an environmental event to be sent public static String Stutter(DashModule d) { return "\n\n"+STUTTER+" == ~"+EXISTS_ENABLED_TRANSITION+ @@ -213,7 +219,7 @@ public static String Next(DashModule d) // Next formula in TLA+ } return next.toString(); } - public static String TypeOK(DashModule d) // TypeOK formula in TLA+ + public static String TypeOK(DashModule d) // TLA+'s technique to ensure that types are appropriate { String variables[] = new String[]{CONF, INTERNAL_EVENTS, ENVIRONMENTAL_EVENTS}; @@ -225,9 +231,12 @@ public static String TypeOK(DashModule d) // TypeOK formula in TLA+ } public static String Init(DashModule d) // Init formula in TLA+ { - StringBuilder init = new StringBuilder("\n\n"+INIT+" == "+INTERNAL_EVENTS+" = {} /\\"); - List defaultsOfRoot = d.getDefaults(d.getRootName()); - for(String s : defaultsOfRoot)init.append("\n\t\t\\/ "+isInState(s)); + StringBuilder init = new StringBuilder("\n\n"+INIT+" == "); + + init.append("\n\t/\\ "+INTERNAL_EVENTS+" = {}"); + init.append("\n\t/\\ "+ENVIRONMENTAL_EVENTS+" = {}"); + init.append("\n\t/\\ "+CONF+" = "+toSetResolved(d.getDefaults(d.getRootName()))); + return init.toString(); } public static String toSet(List elements) // set in TLA+ notation @@ -241,14 +250,14 @@ public static String toSet(List elements) // set in TLA+ notation sb.append("}"); return sb.toString(); } - public static String toSetofStrings(List elements) // set of strings in TLA+ notation + public static String toSetResolved(List elements) // set of strings in TLA+ notation { StringBuilder sb = new StringBuilder("{"); for(int i=0;i Date: Fri, 30 Jun 2023 18:48:04 -0400 Subject: [PATCH 122/129] bug fix for init - leaf states are needed, earlier code took the defaults without filtering for leaf states --- .../watform/dashtotla/DashtoTLA.java | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index b374d2bf6..69b5e22d6 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -12,14 +12,14 @@ public class DashtoTLA { - // common formulae shared by all functions + // boilerplate formulae, shared by all functions public static final String INIT = "Init"; public static final String NEXT = "Next"; public static final String TYPE_OK = "TypeOK"; public static final String EXISTS_ENABLED_TRANSITION = "_exists_enabled_tranistions"; public static final String STUTTER = "_stutter"; - // variables + // boilerplate variables public static final String CONF = "_conf"; public static final String INTERNAL_EVENTS = "_internal_events"; public static final String ENVIRONMENTAL_EVENTS = "_environmental_events"; @@ -30,7 +30,6 @@ public class DashtoTLA // set holding every value which can appear as element of variable public static String maximal(String variable){return variable+"_maximal";} - //public static final String = ""; public static String translate(DashModule d, String moduleName) { if(!d.hasRoot()) @@ -235,10 +234,12 @@ public static String Init(DashModule d) // Init formula in TLA+ init.append("\n\t/\\ "+INTERNAL_EVENTS+" = {}"); init.append("\n\t/\\ "+ENVIRONMENTAL_EVENTS+" = {}"); - init.append("\n\t/\\ "+CONF+" = "+toSetResolved(d.getDefaults(d.getRootName()))); + init.append("\n\t/\\ "+CONF+" = "+toSetResolved(LeafDefaultsOf(d,d.getRootName()))); return init.toString(); } + + // util functions public static String toSet(List elements) // set in TLA+ notation { StringBuilder sb = new StringBuilder("{"); @@ -261,8 +262,24 @@ public static String toSetResolved(List elements) // set of strings in T sb.append("}"); return sb.toString(); } - - // util functions + public static List LeafDefaultsOf(DashModule d, String state) + { + List states = d.getDefaults(state); + int i = 0; + while(i < states.size()) + { + String s = states.get(i); + if(d.isLeaf(s)) // skip over defaults if they are already leaf states + { + i++; + continue; + } + // non-leaf state removed after its children are added + states.addAll(d.getDefaults(s)); + states.remove(i); + } + return states; // at this point, all elements of states are leaf states + } public static List topoSortStates(DashModule d) // each state occurs only after all its children occur { List states = new ArrayList<>(); From ca40b3ad3510a0c262d74e1fc04642a484222f66 Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Wed, 5 Jul 2023 22:13:19 -0400 Subject: [PATCH 123/129] edited root, atomic strings and renamed maximal --- .../watform/dashtotla/DashtoTLA.java | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 69b5e22d6..2aaa3f943 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -27,8 +27,11 @@ public class DashtoTLA // variable in next step public static String prime(String variable){return variable+"'";} - // set holding every value which can appear as element of variable - public static String maximal(String variable){return variable+"_maximal";} + // set holding every value which a variable can hold + public static String superset(String variable){return variable+"__superset";} + + // initial value of a variable + public static String initial(String variable){return variable+"__initial";} public static String translate(DashModule d, String moduleName) { @@ -45,7 +48,8 @@ public static String translate(DashModule d, String moduleName) translation.append(atomsLeafStates(d)); translation.append(atomsInternalEvents(d)); translation.append(atomsEnvironmentalEvents(d)); - translation.append(maximalSets(d)); + translation.append(supersets(d)); + translation.append(initialValues(d)); translation.append(TypeOK(d)); translation.append(createAllStates(d)); translation.append(transitions(d)); @@ -70,7 +74,7 @@ public static String atomsLeafStates(DashModule d) // atoms for each leaf state for(String s : states) if(d.isLeaf(s)) - leafStates.append("\n"+resolveName(s)+" == \""+s+"\""); + leafStates.append("\n"+resolveName(s)+" == \""+resolveName(s)+"\""); return leafStates.toString(); } @@ -78,26 +82,26 @@ private static String isInState(String state) // used to check if one is in a no { return resolveName("in__"+state); } - public static String maximalSets(DashModule d) // define the set of all possible values for a variable's elements + public static String supersets(DashModule d) // define the set of all possible values for a variable's elements { - StringBuilder code = new StringBuilder("\n\n\\* maximal states"); + StringBuilder code = new StringBuilder("\n\n\\* supersets"); // conf List resolvedStateNames = new ArrayList<>(); for(String s : d.getAllStateNames()) if(d.isLeaf(s)) resolvedStateNames.add(resolveName(s)); - code.append("\n"+maximal(CONF)+" == "+toSet(resolvedStateNames)); + code.append("\n"+superset(CONF)+" == "+toSet(resolvedStateNames)); // internal events List resolvedInternalEventNames = new ArrayList<>(); for(String s : d.getAllInternalEventNames())resolvedInternalEventNames.add(resolveName(s)); - code.append("\n"+maximal(INTERNAL_EVENTS)+" == "+toSet(resolvedInternalEventNames)); + code.append("\n"+superset(INTERNAL_EVENTS)+" == "+toSet(resolvedInternalEventNames)); // environmental events List resolvedEnvironmentalEventNames = new ArrayList<>(); for(String s : d.getAllEnvironmentalEventNames())resolvedEnvironmentalEventNames.add(resolveName(s)); - code.append("\n"+maximal(ENVIRONMENTAL_EVENTS)+" == "+toSet(resolvedEnvironmentalEventNames)); + code.append("\n"+superset(ENVIRONMENTAL_EVENTS)+" == "+toSet(resolvedEnvironmentalEventNames)); return code.toString(); } @@ -129,7 +133,7 @@ public static String atomsInternalEvents(DashModule d) // atoms for each interna StringBuilder code = new StringBuilder("\n\n\\* internal events"); List events = d.getAllInternalEventNames(); for(String ev : events) - code.append("\n"+resolveName(ev)+" == \""+ev+"\""); + code.append("\n"+resolveName(ev)+" == \""+resolveName(ev)+"\""); return code.toString(); } public static String atomsEnvironmentalEvents(DashModule d) // atoms for each internal event in TLA+ @@ -137,7 +141,7 @@ public static String atomsEnvironmentalEvents(DashModule d) // atoms for each in StringBuilder code = new StringBuilder("\n\n\\* environmental events"); List events = d.getAllEnvironmentalEventNames(); for(String ev : events) - code.append("\n"+resolveName(ev)+" == \""+ev+"\""); + code.append("\n"+resolveName(ev)+" == \""+resolveName(ev)+"\""); return code.toString(); } public static String postCondition(DashModule d, String trans) @@ -224,7 +228,7 @@ public static String TypeOK(DashModule d) // TLA+'s technique to ensure that typ StringBuilder code = new StringBuilder("\n\n\\* type-checking\n"+TYPE_OK+" == "); for(String s : variables) - code.append("\n\t/\\ (\\A x \\in "+s+" : x \\in "+maximal(s)+")"); + code.append("\n\t/\\ "+s+" \\subseteq "+superset(s)); return code.toString(); } @@ -234,7 +238,7 @@ public static String Init(DashModule d) // Init formula in TLA+ init.append("\n\t/\\ "+INTERNAL_EVENTS+" = {}"); init.append("\n\t/\\ "+ENVIRONMENTAL_EVENTS+" = {}"); - init.append("\n\t/\\ "+CONF+" = "+toSetResolved(LeafDefaultsOf(d,d.getRootName()))); + init.append("\n\t/\\ "+CONF+" = "+toSetResolved(toStringList(d.initialEntered()))); return init.toString(); } @@ -274,9 +278,10 @@ public static List LeafDefaultsOf(DashModule d, String state) i++; continue; } - // non-leaf state removed after its children are added - states.addAll(d.getDefaults(s)); - states.remove(i); + // if state is AND, all children are added + // if state is OR, only default child is added + states.addAll(d.getDefaults(s)); + states.remove(i); // non-leaf state removed after its children are added } return states; // at this point, all elements of states are leaf states } From 88b426f019e619b53919c33d577b75d8531da0ca Mon Sep 17 00:00:00 2001 From: Mathew K J Date: Thu, 6 Jul 2023 10:55:32 -0400 Subject: [PATCH 124/129] initial variables, but build is broken --- .../watform/dashtotla/DashtoTLA.java | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java index 2aaa3f943..61383dce9 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java @@ -236,13 +236,26 @@ public static String Init(DashModule d) // Init formula in TLA+ { StringBuilder init = new StringBuilder("\n\n"+INIT+" == "); - init.append("\n\t/\\ "+INTERNAL_EVENTS+" = {}"); - init.append("\n\t/\\ "+ENVIRONMENTAL_EVENTS+" = {}"); - init.append("\n\t/\\ "+CONF+" = "+toSetResolved(toStringList(d.initialEntered()))); + List variables = new ArrayList<>(); + variables.add(CONF); + variables.add(ENVIRONMENTAL_EVENTS); + variables.add(INTERNAL_EVENTS); + + for(String v : variables) + init.append("\n\t/\\"+v+" == "+initial(v)); return init.toString(); } + public static String initialValues(DashModule d) + { + StringBuilder code = new StringBuilder("\n\n\\* initial values"); + + code.append("\n"+initial(CONF)+" == "+toSetResolved(toStringList(d.initialEntered()))); + code.append("\n"+initial(ENVIRONMENTAL_EVENTS)+" == {}"); + code.append("\n"+initial(INTERNAL_EVENTS)+" == {}"); + return code.toString(); + } // util functions public static String toSet(List elements) // set in TLA+ notation { @@ -299,6 +312,7 @@ public static List topoSortStates(DashModule d) // each state occurs onl Collections.reverse(states); return states; } + public static List toStringList(List dfs) { List ls = new ArrayList<>(); From 4dbc97356d0e16e41df1e2a8fa06c1825f5a9683 Mon Sep 17 00:00:00 2001 From: Mathew Kuthur James Date: Wed, 4 Oct 2023 10:02:09 +0530 Subject: [PATCH 125/129] re-commit of movement to different files --- .../ca/uwaterloo/watform/dashtotla/AST.java | 21 ++ .../ca/uwaterloo/watform/dashtotla/Atom.java | 48 +++ .../watform/dashtotla/DashToTLA.java | 41 +++ .../watform/dashtotla/DashtoTLA.java | 332 ------------------ .../uwaterloo/watform/dashtotla/DesignDoc.md | 22 +- .../watform/dashtotla/StandardFormulae.java | 73 ++++ .../ca/uwaterloo/watform/dashtotla/State.java | 49 +++ .../ca/uwaterloo/watform/dashtotla/TLA.java | 73 ++++ .../watform/dashtotla/Transition.java | 77 ++++ .../ca/uwaterloo/watform/dashtotla/Util.java | 54 +++ .../uwaterloo/watform/dashtotla/Variable.java | 78 ++++ 11 files changed, 535 insertions(+), 333 deletions(-) create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Atom.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashToTLA.java delete mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/StandardFormulae.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/State.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/TLA.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Transition.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Util.java create mode 100644 org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Variable.java diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java new file mode 100644 index 000000000..0d134dd5f --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java @@ -0,0 +1,21 @@ +package ca.uwaterloo.watform.dashtotla; + +import de.uka.ilkd.pp.DataLayouter; +import de.uka.ilkd.pp.NoExceptions; +import de.uka.ilkd.pp.StringBackend; + +public class AST +{ + public String node; + public AST left; + public AST right; + public static String singleton(String set) // the constraint that sets the cardinality of this set to 1 + { + return TLA.parenthesis(TLA.FOR_ALL+" x,y "+TLA.IN+" "+set+" "+TLA.PREDICATE_SCOPE+" x=y "); + } + public String print() + { + StringBuilder code = new StringBuilder(""); + return code.toString(); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Atom.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Atom.java new file mode 100644 index 000000000..3939a10c5 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Atom.java @@ -0,0 +1,48 @@ +package ca.uwaterloo.watform.dashtotla; + +import java.util.List; + +import ca.uwaterloo.watform.parser.DashModule; + + +public class Atom +{ + public static String leafStates(DashModule d) // atoms for each leaf state + { + List states = d.getAllStateNames(); + StringBuilder leafStates = new StringBuilder("\n\n"+TLA.comment("basic states")); + + for(String s : states) + if(d.isLeaf(s)) + leafStates.append("\n"+Util.resolveName(s)+" "+TLA.DEFINE+" "+TLA.string(Util.resolveName(s))); + + return leafStates.toString(); + } + public static String nonLeafStates(DashModule d) // atoms for each leaf state + { + List states = d.getAllStateNames(); + StringBuilder leafStates = new StringBuilder("\n\n"+TLA.comment(" non-basic states")); + + for(String s : states) + if(!d.isLeaf(s)) + leafStates.append("\n"+Util.resolveName(s)+" "+TLA.DEFINE+" "+TLA.string(Util.resolveName(s))); + + return leafStates.toString(); + } + public static String internalEvents(DashModule d) // atoms for each internal event in TLA+ + { + StringBuilder code = new StringBuilder("\n\n"+TLA.comment(" internal events")); + List events = d.getAllInternalEventNames(); + for(String ev : events) + code.append("\n"+Util.resolveName(ev)+" "+TLA.DEFINE+" "+TLA.string(Util.resolveName(ev))); + return code.toString(); + } + public static String environmentalEvents(DashModule d) // atoms for each internal event in TLA+ + { + StringBuilder code = new StringBuilder("\n\n"+TLA.comment(" environmental events")); + List events = d.getAllEnvironmentalEventNames(); + for(String ev : events) + code.append("\n"+Util.resolveName(ev)+" "+TLA.DEFINE+" "+TLA.string(Util.resolveName(ev))); + return code.toString(); + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashToTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashToTLA.java new file mode 100644 index 000000000..3c02767f8 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashToTLA.java @@ -0,0 +1,41 @@ +package ca.uwaterloo.watform.dashtotla; + +import ca.uwaterloo.watform.parser.DashModule; +import ca.uwaterloo.watform.core.DashOptions; + +public class DashToTLA +{ + + public static String translate(Object[] args) throws Exception + { + if(args.length!=2)throw new Exception("Invalid arguments to translate to TLA"); + + DashModule d = (DashModule)args[0]; + String moduleName = (String)args[1]; + boolean singleEnvInput = DashOptions.singleEventInput; + + if(!d.hasRoot())throw new Exception("Error - no root state, nothing to translate"); + + StringBuilder code = new StringBuilder(""); + code.append(TLA.header(moduleName)); + code.append("\n"+TLA.extend(TLA.MODULES)); + code.append(Variable.declareVariables(d)); + code.append(Atom.leafStates(d)); + code.append(Atom.nonLeafStates(d)); + code.append(Atom.internalEvents(d)); + code.append(Atom.environmentalEvents(d)); + code.append(Variable.supersets(d)); + code.append(Variable.initialValues(d)); + code.append(StandardFormulae.TypeOK(d)); + code.append(State.createInStates(d)); + code.append(Transition.transitions(d)); + code.append(StandardFormulae.Init(d,singleEnvInput)); + code.append(StandardFormulae.Stutter(d,singleEnvInput)); + code.append(StandardFormulae.Next(d)); + code.append("\n"+TLA.FOOTER); + code.append("\n"+TLA.comment("Modification History")+ + "\n"+TLA.comment("Translated from Dash at "+System.currentTimeMillis()+" EPOCH")); + + return code.toString(); + } +} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java deleted file mode 100644 index 61383dce9..000000000 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DashtoTLA.java +++ /dev/null @@ -1,332 +0,0 @@ -package ca.uwaterloo.watform.dashtotla; - - - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -//import java.util.function.*; - -import ca.uwaterloo.watform.parser.DashModule; -import ca.uwaterloo.watform.core.DashRef; - -public class DashtoTLA -{ - // boilerplate formulae, shared by all functions - public static final String INIT = "Init"; - public static final String NEXT = "Next"; - public static final String TYPE_OK = "TypeOK"; - public static final String EXISTS_ENABLED_TRANSITION = "_exists_enabled_tranistions"; - public static final String STUTTER = "_stutter"; - - // boilerplate variables - public static final String CONF = "_conf"; - public static final String INTERNAL_EVENTS = "_internal_events"; - public static final String ENVIRONMENTAL_EVENTS = "_environmental_events"; - - // variable in next step - public static String prime(String variable){return variable+"'";} - - // set holding every value which a variable can hold - public static String superset(String variable){return variable+"__superset";} - - // initial value of a variable - public static String initial(String variable){return variable+"__initial";} - - public static String translate(DashModule d, String moduleName) - { - if(!d.hasRoot()) - { - System.out.println("Error - no root state, nothing to translate"); - return "\\* Error - no root state, nothing to translate"; - } - - String header = "------------------------------- MODULE "+moduleName+" -------------------------------"; - String Extends = "\nEXTENDS Integers, FiniteSets"; - String variables = "\nVARIABLE "+CONF+", "+INTERNAL_EVENTS+", "+ENVIRONMENTAL_EVENTS; - StringBuilder translation = new StringBuilder(""); - translation.append(atomsLeafStates(d)); - translation.append(atomsInternalEvents(d)); - translation.append(atomsEnvironmentalEvents(d)); - translation.append(supersets(d)); - translation.append(initialValues(d)); - translation.append(TypeOK(d)); - translation.append(createAllStates(d)); - translation.append(transitions(d)); - translation.append(Init(d)); - translation.append(Stutter(d)); - translation.append(Next(d)); - String footer = "\n============================================================================="; - String comment = "\n\\* Modification History"+ - "\n\\* Translated from Dash at "+System.currentTimeMillis()+" EPOCH"; - - return header+Extends+variables+translation.toString()+footer+comment; - } - public static String resolveName(String s) // get rid of unsupported characters in full names - { - char SP = '_'; // SP is a specual character that cannot appear in any variablename in dash, but can in TLA+ - return SP+s.replace('/', SP); - } - public static String atomsLeafStates(DashModule d) // atoms for each leaf state - { - List states = d.getAllStateNames(); - StringBuilder leafStates = new StringBuilder("\n\n\\* basic states"); - - for(String s : states) - if(d.isLeaf(s)) - leafStates.append("\n"+resolveName(s)+" == \""+resolveName(s)+"\""); - - return leafStates.toString(); - } - private static String isInState(String state) // used to check if one is in a non-leaf state - { - return resolveName("in__"+state); - } - public static String supersets(DashModule d) // define the set of all possible values for a variable's elements - { - StringBuilder code = new StringBuilder("\n\n\\* supersets"); - - // conf - List resolvedStateNames = new ArrayList<>(); - for(String s : d.getAllStateNames()) - if(d.isLeaf(s)) - resolvedStateNames.add(resolveName(s)); - code.append("\n"+superset(CONF)+" == "+toSet(resolvedStateNames)); - - // internal events - List resolvedInternalEventNames = new ArrayList<>(); - for(String s : d.getAllInternalEventNames())resolvedInternalEventNames.add(resolveName(s)); - code.append("\n"+superset(INTERNAL_EVENTS)+" == "+toSet(resolvedInternalEventNames)); - - // environmental events - List resolvedEnvironmentalEventNames = new ArrayList<>(); - for(String s : d.getAllEnvironmentalEventNames())resolvedEnvironmentalEventNames.add(resolveName(s)); - code.append("\n"+superset(ENVIRONMENTAL_EVENTS)+" == "+toSet(resolvedEnvironmentalEventNames)); - - return code.toString(); - } - public static String createAllStates(DashModule d) // formulae to determine if one is present in a state - { - List states = topoSortStates(d); - - StringBuilder code = new StringBuilder("\n\n\\* in states"); - for(String s : states) - { - code.append("\n"+isInState(s)+" == "); - if(d.isLeaf(s)) - { - String resolved = resolveName(s); - code.append(resolved+" \\in "+CONF); - continue; - } - - // dealing with non-leaf states - List children = d.getImmChildren(s); - for(String ch : children) - code.append("\n\t\\/ "+isInState(ch)); - - } - return code.toString(); - } - public static String atomsInternalEvents(DashModule d) // atoms for each internal event in TLA+ - { - StringBuilder code = new StringBuilder("\n\n\\* internal events"); - List events = d.getAllInternalEventNames(); - for(String ev : events) - code.append("\n"+resolveName(ev)+" == \""+resolveName(ev)+"\""); - return code.toString(); - } - public static String atomsEnvironmentalEvents(DashModule d) // atoms for each internal event in TLA+ - { - StringBuilder code = new StringBuilder("\n\n\\* environmental events"); - List events = d.getAllEnvironmentalEventNames(); - for(String ev : events) - code.append("\n"+resolveName(ev)+" == \""+resolveName(ev)+"\""); - return code.toString(); - } - public static String postCondition(DashModule d, String trans) - { - StringBuilder code = new StringBuilder(""); - - // conf' - List entered = toStringList(d.entered(trans)); - List exited = toStringList(d.exited(trans)); - String confPrimed = "\n\t/\\ "+prime(CONF)+" = ("+CONF+" \\ "+toSetResolved(exited)+" ) \\union "+toSetResolved(entered); - - // events' - DashRef on = d.getTransOn(trans); - DashRef send = d.getTransSend(trans); - String E = INTERNAL_EVENTS; - if(on!=null) E = "("+E+" \\ {"+resolveName(on.getName())+"})"; // remove consumed events - if(send!=null) E += " \\union {"+resolveName(send.getName())+"}"; // add generated events - String eventsPrimed = "\n\t/\\ "+prime(INTERNAL_EVENTS)+" = "+E; - - code.append(confPrimed); - code.append(eventsPrimed); - return code.toString(); - } - public static String preCondition(DashModule d, String trans) - { - StringBuilder code = new StringBuilder(""); - - // conf - String srcState = d.getTransSrc(trans).toString(); - String CONF = "\n\t/\\ "+isInState(srcState); - - // formula for events - DashRef ON = d.getTransOn(trans); - String EVENTS = ""; - if(ON!=null)EVENTS = "\n\t/\\ {"+resolveName(ON.getName())+"} \\subseteq "+INTERNAL_EVENTS; - - code.append(CONF); - code.append(EVENTS); - return code.toString(); - } - public static String transitions(DashModule d) - { - // assumption - guard is tautology - StringBuilder ts = new StringBuilder("\n\n\\* transitions"); - List tranList = d.getAllTransNames(); - List preCondList = new ArrayList<>(); - for(String s : tranList) - { - String preConditionName = "_pre__"+resolveName(s); - String postConditionName = "_post__"+resolveName(s); - ts.append("\n\n"+preConditionName+" == "+preCondition(d, s)); - ts.append("\n"+postConditionName+" == "+postCondition(d, s)); - ts.append("\n"+resolveName(s)+" == "+preConditionName+" /\\ "+postConditionName); - preCondList.add(preConditionName); - } - - StringBuilder somePrecond = new StringBuilder("\n\n"+EXISTS_ENABLED_TRANSITION+" == "); - for(String s : preCondList) - somePrecond.append("\n\t/\\ "+s); - - return ts.append(somePrecond).toString(); - } - // when no tranitions are enabled, the system stays in current state while waiting for an environmental event to be sent - public static String Stutter(DashModule d) - { - return "\n\n"+STUTTER+" == ~"+EXISTS_ENABLED_TRANSITION+ - "\n\t/\\ "+prime(CONF)+" = "+CONF+ - "\n\t/\\ "+prime(INTERNAL_EVENTS)+" = "+INTERNAL_EVENTS; - - } - public static String Next(DashModule d) // Next formula in TLA+ - { - List tranList = d.getAllTransNames(); - StringBuilder next = new StringBuilder("\n\n"+NEXT+" == "+STUTTER); - for(String s : tranList) - { - next.append("\n\t\\/ "+resolveName(s)); - } - return next.toString(); - } - public static String TypeOK(DashModule d) // TLA+'s technique to ensure that types are appropriate - { - String variables[] = new String[]{CONF, INTERNAL_EVENTS, ENVIRONMENTAL_EVENTS}; - - StringBuilder code = new StringBuilder("\n\n\\* type-checking\n"+TYPE_OK+" == "); - for(String s : variables) - code.append("\n\t/\\ "+s+" \\subseteq "+superset(s)); - - return code.toString(); - } - public static String Init(DashModule d) // Init formula in TLA+ - { - StringBuilder init = new StringBuilder("\n\n"+INIT+" == "); - - List variables = new ArrayList<>(); - variables.add(CONF); - variables.add(ENVIRONMENTAL_EVENTS); - variables.add(INTERNAL_EVENTS); - - for(String v : variables) - init.append("\n\t/\\"+v+" == "+initial(v)); - - return init.toString(); - } - public static String initialValues(DashModule d) - { - StringBuilder code = new StringBuilder("\n\n\\* initial values"); - - code.append("\n"+initial(CONF)+" == "+toSetResolved(toStringList(d.initialEntered()))); - code.append("\n"+initial(ENVIRONMENTAL_EVENTS)+" == {}"); - code.append("\n"+initial(INTERNAL_EVENTS)+" == {}"); - - return code.toString(); - } - // util functions - public static String toSet(List elements) // set in TLA+ notation - { - StringBuilder sb = new StringBuilder("{"); - for(int i=0;i elements) // set of strings in TLA+ notation - { - StringBuilder sb = new StringBuilder("{"); - for(int i=0;i LeafDefaultsOf(DashModule d, String state) - { - List states = d.getDefaults(state); - int i = 0; - while(i < states.size()) - { - String s = states.get(i); - if(d.isLeaf(s)) // skip over defaults if they are already leaf states - { - i++; - continue; - } - // if state is AND, all children are added - // if state is OR, only default child is added - states.addAll(d.getDefaults(s)); - states.remove(i); // non-leaf state removed after its children are added - } - return states; // at this point, all elements of states are leaf states - } - public static List topoSortStates(DashModule d) // each state occurs only after all its children occur - { - List states = new ArrayList<>(); - states.add(d.getRootName()); - int i = 0; - while(i < states.size()) - { - List children = d.getImmChildren(states.get(i)); - i++; - for(String ch : children)states.add(ch); - } - Collections.reverse(states); - return states; - } - - public static List toStringList(List dfs) - { - List ls = new ArrayList<>(); - for(DashRef df : dfs)ls.add(df.getName()); - return ls; - } - /* - public static List toDashRefList(List ls, Function createDashRef) - { - List dfs = new ArrayList<>(); - for (String s : ls) { - dfs.add(createDashRef.apply(s)); - } - return dfs; - } - */ -} \ No newline at end of file diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md index d0ab7a73b..51f5b2e26 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/DesignDoc.md @@ -31,7 +31,23 @@ The same format is followed when multiple `.dsh` files are translated at a time. ## Guide to the Source Code -All translation is done by [DashtoTLA.java](). The argument `-tla` is defined in [Dash.java](), which calls `MainFunctions.translateTLA() ` in [MainFunctions.java](), which in turn calls `DashtoTLA.translate()`. +- The argument `-tla` is defined in [Dash.java](), which calls `MainFunctions.translateTLA() ` in [MainFunctions.java](), which in turn calls `DashtoTLA.translate()`. + +- The functions and global constants used in the translation are stored in different classes, purely to enhance readability. The classes have no non-static elements and are not intended to be used as object templates + +- [Util.java] stores useful functions that perform operations independent of the context of the transation. + +- [Transition.java]() contains code responsible for providing the formulae for all the transitions. Each transition is broken into a precondition and a postcondition for output readability. + +- [Atom.java]() contains a class concerned with defining the literals to which symbols point to. The literals defined here are not meant to be referred to in any other part of the translatin; they exist only because `TLA+` does not alloy one to use variables without initialization to some primitive type (or a composition thereof) + +- [StandardFormulae.java]() holds functions which generate formulae that occur in every translation, like `stutter`, `Init`, `Next` and `TypeOK`. + +- [Variable.java]() holds functions and constants which deal with `TLA+` variables (both standard ones like `conf`, `internal_events`, `environmental_events`, `scope_used` etc and those defined in the input) + +- [State.java]() contains formulae dealing with the control states in the input. (Note that the term "control state" does not refer to the term "state" as commonly understood) + +-[TLA.java]() contains everything to do with the syntax of TLA+. All syntax is encoded here, nothing is hardcoded in other classes. This class serves as a layer of abstraction over the final TLA+ output ## Design Decisions @@ -53,4 +69,8 @@ All translation is done by [DashtoTLA.java](). The argument `-tla` is defined in - Internal and Environmental events are segregated +- isInState will not guarantee that current value of conf is legal, but /\ is used to check for conc states since /\ is faster to compute + +- Cardinality is expensive to compute so Cardinality(S)=1 is the same as \all x,y \in S : x=y + diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/StandardFormulae.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/StandardFormulae.java new file mode 100644 index 000000000..2c90f9a79 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/StandardFormulae.java @@ -0,0 +1,73 @@ +package ca.uwaterloo.watform.dashtotla; + +import java.util.ArrayList; +import java.util.List; + +import ca.uwaterloo.watform.parser.DashModule; + +public class StandardFormulae +{ + // boilerplate formulae, shared by all functions + public static final String INIT = "Init"; + public static final String NEXT = "Next"; + public static final String TYPE_OK = "TypeOK"; + + public static final String STUTTER = "_stutter"; + + public static String Next(DashModule d) // Next formula in TLA+ + { + List tranList = d.getAllTransNames(); + StringBuilder next = new StringBuilder("\n\n"+NEXT+" "+TLA.DEFINE+" "+STUTTER); + for(String s : tranList) + { + next.append("\n\t"+TLA.OR+" "+Util.resolveName(s)); + } + return next.toString(); + } + public static String TypeOK(DashModule d) // TLA+'s technique to ensure that types are appropriate + { + String variables[] = new String[]{Variable.CONF, Variable.INTERNAL_EVENTS, Variable.ENVIRONMENTAL_EVENTS, Variable.SCOPES_USED}; + + StringBuilder code = new StringBuilder("\n\n"+TLA.comment("type-checking")+"\n"+TYPE_OK+" "+TLA.DEFINE+" "); + for(String s : variables) + code.append("\n\t"+TLA.AND+" "+s+" "+TLA.SUBSET+" "+Variable.superset(s)); + + return code.toString(); + } + public static String Init(DashModule d, boolean singleEnvInput) // Init formula in TLA+ + { + StringBuilder init = new StringBuilder("\n\n"+INIT+" "+TLA.DEFINE+" "); + + List variables = new ArrayList<>(); // both boilerplate and actual variables + variables.add(Variable.CONF); + variables.add(Variable.INTERNAL_EVENTS); + variables.add(Variable.SCOPES_USED); + variables.add(Variable.STABLE); + + for(String v : variables) + init.append("\n\t"+TLA.AND+" "+v+TLA.EQUAL+Variable.initial(v)); + + init.append("\n\t"+TLA.AND+" "+Variable.ENVIRONMENTAL_EVENTS+" "+TLA.SUBSET+" "+Variable.superset(Variable.ENVIRONMENTAL_EVENTS)); + if(singleEnvInput) + init.append(" "+TLA.AND+AST.singleton(Variable.ENVIRONMENTAL_EVENTS)); + + return init.toString(); + } + + // when no tranitions are enabled, the system stays in current state while waiting for an environmental event to be sent + public static String Stutter(DashModule d, boolean singleEnvInput) + { + return "\n\n"+STUTTER+" "+TLA.DEFINE+" "+TLA.NOT+Transition.EXISTS_ENABLED_TRANSITION+ + "\n\t"+TLA.AND+" "+Variable.prime(Variable.CONF)+TLA.EQUAL+Variable.CONF+ + "\n\t"+TLA.AND+" "+Variable.prime(Variable.INTERNAL_EVENTS)+TLA.EQUAL+Variable.INTERNAL_EVENTS+ + "\n\t"+TLA.AND+"\t"+TLA.OR+" "+Variable.prime(Variable.ENVIRONMENTAL_EVENTS)+TLA.EQUAL+Variable.ENVIRONMENTAL_EVENTS+ + "\n\t\t"+TLA.OR+" "+TLA.parenthesis(Variable.prime(Variable.ENVIRONMENTAL_EVENTS)+" "+TLA.SUBSET+" "+Variable.superset(Variable.ENVIRONMENTAL_EVENTS)+" "+ + (singleEnvInput?TLA.AND+" "+AST.singleton(Variable.ENVIRONMENTAL_EVENTS):""))+ + "\n\t"+TLA.AND+" "+Variable.prime(Variable.SCOPES_USED)+TLA.EQUAL+TLA.NULL_SET+ + "\n\t"+TLA.AND+" "+Variable.prime(Variable.STABLE)+TLA.EQUAL+TLA.TRUE; + + + + + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/State.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/State.java new file mode 100644 index 000000000..e3ef1f755 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/State.java @@ -0,0 +1,49 @@ +package ca.uwaterloo.watform.dashtotla; + +import java.util.List; +import java.util.ArrayList; + +import ca.uwaterloo.watform.parser.DashModule; + +public class State +{ + public static String isInState(String state) // used to check if one is in a non-leaf state + { + return Util.resolveName("in__"+state); + } + public static String createInStates(DashModule d) // formulae to determine if one is present in a state + { + List states = Util.topoSortStates(d); + + StringBuilder code = new StringBuilder("\n\n"+TLA.comment(" in states")); + for(String s : states) + { + code.append("\n"+isInState(s)+" "+TLA.DEFINE+" "); + if(d.isLeaf(s)) + { + String resolved = Util.resolveName(s); + code.append(resolved+" \\in "+Variable.CONF); + continue; + } + + // dealing with non-leaf states + List children = d.getImmChildren(s); + List andChildren = new ArrayList<>(); //concurrency + + for(String ch : children) + if(d.isAnd(ch)) + andChildren.add(ch); + else + code.append("\n\t"+TLA.OR+" "+isInState(ch)); // can be in any "or" child + + // if is in one "and" child, must be in all "and" children + if(andChildren.size()==0) + continue; + code.append("\n\t"+TLA.OR); + for(String ch : andChildren) + code.append("\n\t\t"+TLA.AND+" "+isInState(ch)); + + } + return code.toString(); + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/TLA.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/TLA.java new file mode 100644 index 000000000..801dd0518 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/TLA.java @@ -0,0 +1,73 @@ +package ca.uwaterloo.watform.dashtotla; + +import java.util.List; + +public class TLA +{ + public static final String EQUAL = "="; + public static final String DEFINE = "=="; + + public static final String AND = "/\\"; + public static final String OR = "\\/"; + public static final String NOT = "~"; + + public static final String FOR_ALL = "\\A"; + public static final String EXISTS = "\\E"; + public static final String IN = "\\in"; + public static final String PREDICATE_SCOPE = "\\:"; + + public static final String TRUE = "TRUE"; + public static final String FALSE = "FALSE"; + + public static final String[] MODULES = new String[]{"Integers","FiniteSets"}; + + public static final String UNION = "\\union"; + public static final String INTERSECTION = "\\intersect"; + public static final String NULL_SET = set(""); + public static final String SUBSET = "\\subseteq"; + public static final String PROPER_SUBSET = "\\subset"; + public static final String SUPERSET = "\\superseteq"; + public static final String PROPER_SUPERSET = "\\superset"; + public static final String SET_DIFFERENCE = "\\"; + + public static String parenthesis(String exp){return "("+exp+")";} + public static String comment(String comment){return "\\* "+comment;} + public static String commentMultiLine(String comment){return "\n(*"+comment+"\n*)";} + public static String set(String exp){return "{"+exp+"}";} + public static String string(String exp){return "\""+exp+"\"";} + public static String cardinality(String exp){return "Cardinality("+exp+")";} + public static String set(List elements) // set in TLA+ notation + { + StringBuilder sb = new StringBuilder("{"); + for(int i=0;i variables) + { + if(variables.size()==0)return ""; + StringBuilder code = new StringBuilder("VARIABLES "); + for(int i=0;i entered = Util.toStringList(d.entered(trans)); + List exited = Util.toStringList(d.exited(trans)); + String confPrimed = "\n\t"+TLA.AND+" "+Variable.prime(Variable.CONF)+TLA.EQUAL + +TLA.parenthesis(Variable.CONF+" "+TLA.SET_DIFFERENCE+" "+TLA.set(Util.resolveList(exited)))+" "+TLA.UNION+" " + +TLA.set(Util.resolveList(entered)); + + // scopes_used' + List scopesUsed = Util.toStringList(d.scopesUsed(trans)); + String scopes = "\n\t"+TLA.AND+" "+Variable.prime(Variable.SCOPES_USED)+TLA.EQUAL+Variable.SCOPES_USED+" "+TLA.UNION+" "+TLA.set(Util.resolveList(scopesUsed)); + + code.append(confPrimed); + code.append(scopes); + code.append("\n\t"+TLA.AND+" "+Variable.prime(Variable.ENVIRONMENTAL_EVENTS)+TLA.EQUAL+Variable.ENVIRONMENTAL_EVENTS); + return code.toString(); + } + public static String preCondition(DashModule d, String trans) + { + StringBuilder code = new StringBuilder(""); + + // conf + String srcState = d.getTransSrc(trans).toString(); + String conf = "\n\t"+TLA.AND+" "+State.isInState(srcState); + + // formula for events + DashRef on = d.getTransOn(trans); + String events = ""; + if(on!=null)events = "\n\t"+TLA.AND+" "+TLA.set(Util.resolveName(on.getName()))+" "+TLA.SUBSET+" "+Variable.INTERNAL_EVENTS; + + // scopes_used + List nonOrthogonalScopes = Util.toStringList(d.nonOrthogonalScopesOf(trans)); + String scopes = "\n\t"+TLA.AND+" "+Variable.SCOPES_USED+" "+TLA.INTERSECTION+" "+TLA.set(Util.resolveList(nonOrthogonalScopes))+TLA.EQUAL+TLA.NULL_SET; + + code.append(conf); + code.append(events); + code.append(scopes); + return code.toString(); + } + public static String transitions(DashModule d) + { + // assumption - guard is tautology + StringBuilder ts = new StringBuilder("\n\n"+TLA.comment("transitions")); + List tranList = d.getAllTransNames(); + List preCondList = new ArrayList<>(); + for(String s : tranList) + { + String preConditionName = "_pre__"+Util.resolveName(s); + String postConditionName = "_post__"+Util.resolveName(s); + ts.append("\n\n"+preConditionName+" "+TLA.DEFINE+" "+preCondition(d, s)); + ts.append("\n"+postConditionName+" "+TLA.DEFINE+" "+postCondition(d, s)); + ts.append("\n"+Util.resolveName(s)+" "+TLA.DEFINE+" "+preConditionName+" "+TLA.AND+" "+postConditionName); + preCondList.add(preConditionName); + } + + StringBuilder somePrecond = new StringBuilder("\n\n"+EXISTS_ENABLED_TRANSITION+" "+TLA.DEFINE+" "); + for(String s : preCondList) + somePrecond.append("\n\t"+TLA.AND+" "+s); + + return ts.append(somePrecond).toString(); + } +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Util.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Util.java new file mode 100644 index 000000000..1fe0cce29 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Util.java @@ -0,0 +1,54 @@ +package ca.uwaterloo.watform.dashtotla; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import ca.uwaterloo.watform.core.DashRef; +import ca.uwaterloo.watform.parser.DashModule; + +public class Util +{ + public static String resolveName(String s) // get rid of unsupported characters in full names + { + char SP = '_'; // SP is a specual character that cannot appear in any variablename in dash, but can in TLA+ + return SP+s.replace('/', SP); + } + public static List topoSortStates(DashModule d) // each state occurs only after all its children occur + { + List states = new ArrayList<>(); + states.add(d.getRootName()); + int i = 0; + while(i < states.size()) + { + List children = d.getImmChildren(states.get(i)); + i++; + for(String ch : children)states.add(ch); + } + Collections.reverse(states); + return states; + } + public static List toStringList(List dfs) + { + List ls = new ArrayList<>(); + for(DashRef df : dfs)ls.add(df.getName()); + return ls; + } + + public static List resolveList(List elements) // set of strings in TLA+ notation + { + List resolvedNames = new ArrayList<>(); + elements.forEach(element -> {resolvedNames.add(resolveName(element));}); + return resolvedNames; + } + /* + public static List toDashRefList(List ls, Function createDashRef) + { + List dfs = new ArrayList<>(); + for (String s : ls) { + dfs.add(createDashRef.apply(s)); + } + return dfs; + } + */ +} diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Variable.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Variable.java new file mode 100644 index 000000000..cebb047f9 --- /dev/null +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/Variable.java @@ -0,0 +1,78 @@ +package ca.uwaterloo.watform.dashtotla; + +import java.util.ArrayList; +import java.util.List; + +import ca.uwaterloo.watform.parser.DashModule; + +public class Variable +{ + + + // boilerplate variables + public static final String CONF = "_conf"; + public static final String INTERNAL_EVENTS = "_internal_events"; + public static final String ENVIRONMENTAL_EVENTS = "_environmental_events"; + public static final String SCOPES_USED = "_scopes_used"; + public static final String STABLE = "_stable"; + + // variable in next step + public static String prime(String variable){return variable+"'";} + + // set holding every value which a variable can hold + public static String superset(String variable){return variable+"__superset";} + + // initial value of a variable + public static String initial(String variable){return variable+"__initial";} + + public static String initialValues(DashModule d) + { + StringBuilder code = new StringBuilder("\n\n"+TLA.comment(" initial values")); + + code.append("\n"+initial(Variable.CONF)+" "+TLA.DEFINE+" "+TLA.set(Util.resolveList(Util.toStringList(d.initialEntered())))); + code.append("\n"+initial(Variable.ENVIRONMENTAL_EVENTS)+" "+TLA.DEFINE+" "+TLA.NULL_SET); + code.append("\n"+initial(Variable.SCOPES_USED)+" "+TLA.DEFINE+" "+TLA.NULL_SET); + code.append("\n"+initial(Variable.STABLE)+" "+TLA.DEFINE+" "+TLA.TRUE); + + return code.toString(); + } + public static String declareVariables(DashModule d) + { + List variables = new ArrayList<>(); + variables.add(SCOPES_USED); + variables.add(CONF); + variables.add(INTERNAL_EVENTS); + variables.add(ENVIRONMENTAL_EVENTS); + variables.add(STABLE); + return "\n"+TLA.variables(variables); + } + public static String supersets(DashModule d) // define the set of all possible values for a variable's elements + { + StringBuilder code = new StringBuilder("\n\n"+TLA.comment(" supersets")); + + // conf, scopes used + List resolvedStateNames = new ArrayList<>(); + List resolvedBasicStateNames = new ArrayList<>(); + for(String s : d.getAllStateNames()) + { + resolvedStateNames.add(Util.resolveName(s)); + if(d.isLeaf(s)) + resolvedBasicStateNames.add(Util.resolveName(s)); + } + code.append("\n"+superset(Variable.CONF)+" "+TLA.DEFINE+" "+TLA.set(resolvedBasicStateNames)); + code.append("\n"+superset(Variable.SCOPES_USED)+" "+TLA.DEFINE+" "+TLA.set(resolvedStateNames)); + + // internal events + List resolvedInternalEventNames = new ArrayList<>(); + for(String s : d.getAllInternalEventNames())resolvedInternalEventNames.add(Util.resolveName(s)); + code.append("\n"+superset(Variable.INTERNAL_EVENTS)+" "+TLA.DEFINE+" "+TLA.set(resolvedInternalEventNames)); + + // environmental events + List resolvedEnvironmentalEventNames = new ArrayList<>(); + for(String s : d.getAllEnvironmentalEventNames())resolvedEnvironmentalEventNames.add(Util.resolveName(s)); + code.append("\n"+superset(Variable.ENVIRONMENTAL_EVENTS)+" "+TLA.DEFINE+" "+TLA.set(resolvedEnvironmentalEventNames)); + + + return code.toString(); + } +} From b6abc5ab8d11b05bd99e07b74ed720c8a039ecfc Mon Sep 17 00:00:00 2001 From: Mathew Kuthur James Date: Wed, 4 Oct 2023 10:20:18 +0530 Subject: [PATCH 126/129] edited name of class in MainFunctions --- .../ca/uwaterloo/watform/mainfunctions/MainFunctions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index ce6c927db..10daa8686 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -18,7 +18,7 @@ import ca.uwaterloo.watform.core.DashErrors; import ca.uwaterloo.watform.parser.DashUtil; import ca.uwaterloo.watform.parser.DashModule; -import ca.uwaterloo.watform.dashtotla.DashtoTLA; +import ca.uwaterloo.watform.dashtotla.DashToTLA; // no io in these! @@ -67,7 +67,7 @@ public static DashModule translate(DashModule d, A4Reporter rep) { } public static String translateTLA(DashModule d, String moduleName) { - return DashtoTLA.translate(d, moduleName); + return DashToTLA.translate(d, moduleName); } public static CompModule resolveAlloy(CompModule c, A4Reporter rep) { From 2189559345872caed014e73c3f29613882bd8490 Mon Sep 17 00:00:00 2001 From: Mathew Kuthur James Date: Wed, 4 Oct 2023 10:32:13 +0530 Subject: [PATCH 127/129] exception handling in mainFunctions --- .../uwaterloo/watform/mainfunctions/MainFunctions.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java index 10daa8686..04743ab31 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/mainfunctions/MainFunctions.java @@ -67,7 +67,15 @@ public static DashModule translate(DashModule d, A4Reporter rep) { } public static String translateTLA(DashModule d, String moduleName) { - return DashToTLA.translate(d, moduleName); + try + { + return DashToTLA.translate(new Object[]{d, moduleName}); + } + catch(Exception e) + { + + } + return null; } public static CompModule resolveAlloy(CompModule c, A4Reporter rep) { From cbba8b2486576dab4bfb9bbc3e3664dee702b906 Mon Sep 17 00:00:00 2001 From: Mathew Kuthur James Date: Tue, 10 Oct 2023 22:36:29 +0530 Subject: [PATCH 128/129] grammar edit to test commit script --- .../src/main/java/ca/uwaterloo/watform/dashtotla/AST.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java index 0d134dd5f..389659a5b 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java @@ -9,7 +9,7 @@ public class AST public String node; public AST left; public AST right; - public static String singleton(String set) // the constraint that sets the cardinality of this set to 1 + public static String singleton(String set) // the constraints that sets the cardinality of this set to 1 { return TLA.parenthesis(TLA.FOR_ALL+" x,y "+TLA.IN+" "+set+" "+TLA.PREDICATE_SCOPE+" x=y "); } From 38f8509a37ca70a72bab975144d9ca3702f2f821 Mon Sep 17 00:00:00 2001 From: Mathew Kuthur James Date: Tue, 10 Oct 2023 22:37:39 +0530 Subject: [PATCH 129/129] grammar edit to test commit script --- .../src/main/java/ca/uwaterloo/watform/dashtotla/AST.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java index 389659a5b..0d134dd5f 100644 --- a/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java +++ b/org.alloytools.alloy.dash/src/main/java/ca/uwaterloo/watform/dashtotla/AST.java @@ -9,7 +9,7 @@ public class AST public String node; public AST left; public AST right; - public static String singleton(String set) // the constraints that sets the cardinality of this set to 1 + public static String singleton(String set) // the constraint that sets the cardinality of this set to 1 { return TLA.parenthesis(TLA.FOR_ALL+" x,y "+TLA.IN+" "+set+" "+TLA.PREDICATE_SCOPE+" x=y "); }