diff --git a/.gitignore b/.gitignore index c6aa4d053..af1bb6d1a 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,6 @@ scribble-core/src/test/scrib/test/test9/ bin/scribblec.sh permissions-fix.sh +# IntelliJ metadata +*.iml +.idea/ diff --git a/pom.xml b/pom.xml index f0181a08d..de8b6b7e9 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ - 3.4 + 3.5.2 1.2.14 1.9.9 4.11 @@ -84,6 +84,8 @@ scribble-test scribble-dist scribble-demos + + scribble-go @@ -285,8 +287,11 @@ bin/*.sh scribblec.sh **/*.swp + scribble-f17/**/* + scribble-go/**/* + diff --git a/scribble-cli/src/main/java/org/scribble/cli/CommandLine.java b/scribble-cli/src/main/java/org/scribble/cli/CommandLine.java index 6b806299f..9a86b3022 100644 --- a/scribble-cli/src/main/java/org/scribble/cli/CommandLine.java +++ b/scribble-cli/src/main/java/org/scribble/cli/CommandLine.java @@ -152,7 +152,7 @@ protected void runBody() throws ScribParserException, AntlrSourceException, Comm // Attempt certain "output tasks" even if above failed, in case can still do some useful output (hacky) try { - doAttemptableOutputTasks(job); + tryOutputTasks(job); } catch (ScribbleException x) { @@ -189,7 +189,7 @@ protected void doValidationTasks(Job job) throws AntlrSourceException, ScribPars } } - protected void doAttemptableOutputTasks(Job job) throws CommandLineException, ScribbleException + protected void tryOutputTasks(Job job) throws CommandLineException, ScribbleException { // Following must be ordered appropriately -- ? if (this.args.containsKey(CLArgFlag.PROJECT)) @@ -436,7 +436,7 @@ protected void outputClasses(Map classes) throws ScribbleExcepti } else { - f = path -> { System.out.println(path + ":\n" + classes.get(path)); }; + f = path -> { System.out.println("\n[" + path + "]:\n" + classes.get(path)); }; } classes.keySet().stream().forEach(f); } @@ -468,7 +468,7 @@ protected static Path parseMainPath(String path) protected static List parseImportPaths(String paths) { - return Arrays.stream(paths.split(File.pathSeparator)).map((s) -> Paths.get(s)).collect(Collectors.toList()); + return Arrays.stream(paths.split(File.pathSeparator)).map(s -> Paths.get(s)).collect(Collectors.toList()); } protected static GProtocolName checkGlobalProtocolArg(JobContext jcontext, String simpname) throws CommandLineException diff --git a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STActionBuilder.java b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STActionBuilder.java index 64d718c6e..0b884c039 100644 --- a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STActionBuilder.java +++ b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STActionBuilder.java @@ -18,26 +18,26 @@ public abstract class STActionBuilder { - public abstract String getActionName(STStateChanAPIBuilder api, EAction a); - public abstract String buildArgs(EAction a); - public abstract String buildBody(STStateChanAPIBuilder api, EState curr, EAction a, EState succ); - - public String getReturnType(STStateChanAPIBuilder api, EState curr, EState succ) + public String build(STStateChanApiBuilder api, EState curr, EAction a) { - return api.getStateChanName(succ); + return api.buildAction(this, curr, a); // Because action builder hierarchy not suitable (extended by action kinds, not by target language) } - public String buildReturn(STStateChanAPIBuilder api, EState curr, EState succ) + public String buildReturn(STStateChanApiBuilder api, EState curr, EState succ) { return api.buildActionReturn(this, curr, succ); } - - public String build(STStateChanAPIBuilder api, EState curr, EAction a) + + public abstract String getActionName(STStateChanApiBuilder api, EAction a); + public abstract String buildArgs(STStateChanApiBuilder api, EAction a); + public abstract String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ); + + public String getReturnType(STStateChanApiBuilder api, EState curr, EState succ) { - return api.buildAction(this, curr, a); // Because action builder hierarchy not suitable (extended by action kinds, not by target language) + return api.getStateChanName(succ); } - public String getStateChanType(STStateChanAPIBuilder api, EState curr, EAction a) + public String getStateChanType(STStateChanApiBuilder api, EState curr, EAction a) { return api.getStateChanName(curr); } diff --git a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STBranchStateBuilder.java b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STBranchStateBuilder.java index 87f662188..387bd7ccd 100644 --- a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STBranchStateBuilder.java +++ b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STBranchStateBuilder.java @@ -25,12 +25,12 @@ public STBranchStateBuilder(STBranchActionBuilder bb) } @Override - public String build(STStateChanAPIBuilder api, EState s) + public String build(STStateChanApiBuilder api, EState s) { String out = getPreamble(api, s); out += "\n\n"; - out += this.bb.build(api, s, s.getActions().get(1)); // Getting 1 checks non-unary + out += this.bb.build(api, s, s.getActions().get(1)); // .get(1) checks non-unary return out; } diff --git a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STCaseBuilder.java b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STCaseBuilder.java index bc3fc04bf..76720fc16 100644 --- a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STCaseBuilder.java +++ b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STCaseBuilder.java @@ -27,7 +27,7 @@ public STCaseBuilder(STCaseActionBuilder cb) } @Override - public String build(STStateChanAPIBuilder api, EState s) + public String build(STStateChanApiBuilder api, EState s) { String out = getPreamble(api, s); @@ -47,5 +47,5 @@ public String build(STStateChanAPIBuilder api, EState s) return out; } - public abstract String getCaseStateChanName(STStateChanAPIBuilder api, EState s); + public abstract String getCaseStateChanName(STStateChanApiBuilder api, EState s); } diff --git a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STEndStateBuilder.java b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STEndStateBuilder.java index cc80d80b0..6af53b509 100644 --- a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STEndStateBuilder.java +++ b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STEndStateBuilder.java @@ -23,7 +23,7 @@ public STEndStateBuilder() } @Override - public String build(STStateChanAPIBuilder api, EState s) + public String build(STStateChanApiBuilder api, EState s) { return getPreamble(api, s); } diff --git a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STOutputStateBuilder.java b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STOutputStateBuilder.java index bd7ae7c8b..06ceed8b9 100644 --- a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STOutputStateBuilder.java +++ b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STOutputStateBuilder.java @@ -29,7 +29,7 @@ public STOutputStateBuilder(STSendActionBuilder sb) } @Override - public String build(STStateChanAPIBuilder api, EState s) + public String build(STStateChanApiBuilder api, EState s) { String out = getPreamble(api, s); /*"package " + getPackage(gpn) diff --git a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STReceiveStateBuilder.java b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STReceiveStateBuilder.java index dc5ebf640..7a7639304 100644 --- a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STReceiveStateBuilder.java +++ b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STReceiveStateBuilder.java @@ -28,7 +28,7 @@ public STReceiveStateBuilder(STReceiveActionBuilder rb) } @Override - public String build(STStateChanAPIBuilder api, EState s) + public String build(STStateChanApiBuilder api, EState s) { String out = getPreamble(api, s); diff --git a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanAPIBuilder.java b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanApiBuilder.java similarity index 68% rename from scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanAPIBuilder.java rename to scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanApiBuilder.java index a158f719a..a48722701 100644 --- a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanAPIBuilder.java +++ b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanApiBuilder.java @@ -26,7 +26,7 @@ import org.scribble.type.name.GProtocolName; import org.scribble.type.name.Role; -public abstract class STStateChanAPIBuilder +public abstract class STStateChanApiBuilder { public final Job job; @@ -40,9 +40,9 @@ public abstract class STStateChanAPIBuilder public final STCaseBuilder cb; public final STEndStateBuilder eb; - private Map names = new HashMap<>(); + protected Map names = new HashMap<>(); - protected STStateChanAPIBuilder(Job job, GProtocolName gpn, Role role, EGraph graph, + protected STStateChanApiBuilder(Job job, GProtocolName gpn, Role role, EGraph graph, STOutputStateBuilder ob, STReceiveStateBuilder rb, STBranchStateBuilder bb, STCaseBuilder cb, STEndStateBuilder eb) { this.job = job; @@ -58,7 +58,7 @@ protected STStateChanAPIBuilder(Job job, GProtocolName gpn, Role role, EGraph gr this.eb = eb; } - public abstract Map buildSessionAPI(); // filepath -> source // FIXME: factor out + //public abstract Map buildSessionAPI(); // filepath -> source // FIXME: factor out public Map build() // filepath -> source { @@ -70,31 +70,32 @@ public Map build() // filepath -> source { switch (s.getStateKind()) { - case ACCEPT: throw new RuntimeException("TODO"); - case OUTPUT: api.put(getFilePath(getStateChanName(s)), this.ob.build(this, s)); break; + case ACCEPT: throw new RuntimeException("[TODO]: " + s.getStateKind()); + case OUTPUT: api.put(getStateChannelFilePath(getStateChanName(s)), this.ob.build(this, s)); break; case POLY_INPUT: { - api.put(getFilePath(getStateChanName(s)), this.bb.build(this, s)); - api.put(getFilePath(this.cb.getCaseStateChanName(this, s)), this.cb.build(this, s)); // FIXME: factor out + api.put(getStateChannelFilePath(getStateChanName(s)), this.bb.build(this, s)); + api.put(getStateChannelFilePath(this.cb.getCaseStateChanName(this, s)), this.cb.build(this, s)); // FIXME: factor out break; } - case TERMINAL: api.put(getFilePath(getStateChanName(s)), this.eb.build(this, s)); break; // FIXME: without subpackages, all roles share same EndSocket + case TERMINAL: api.put(getStateChannelFilePath(getStateChanName(s)), this.eb.build(this, s)); break; // FIXME: without subpackages, all roles share same EndSocket case UNARY_INPUT: { - api.put(getFilePath(getStateChanName(s)), this.rb.build(this, s)); + api.put(getStateChannelFilePath(getStateChanName(s)), this.rb.build(this, s)); //api.put(getFilePath(getStateChanName(s) + "_Cases"), this.cb.build(this, s)); // FIXME: factor out break; } - case WRAP_SERVER: throw new RuntimeException("TODO"); + case WRAP_SERVER: throw new RuntimeException("[TODO]: " + s.getStateKind()); default: throw new RuntimeException("Shouldn't get in here: " + s); } } return api; } - - public abstract String getFilePath(String name); - public abstract String getPackage(); + // Returns path to use as offset to -d + public abstract String getStateChannelFilePath(String name); + + //public abstract String getPackage(); public String getStateChanName(EState s) { @@ -112,7 +113,7 @@ public String getStateChanName(EState s) public abstract String buildAction(STActionBuilder ab, EState curr, EAction a); - public abstract String getChannelName(STStateChanAPIBuilder api, EAction a); + public abstract String getChannelName(STStateChanApiBuilder api, EAction a); // FIXME: redundant? (supposed to be for Runtime MPChan references?) public abstract String buildActionReturn(STActionBuilder ab, EState curr, EState succ); // FIXME: refactor action builders as interfaces and use generic parameter for kind } diff --git a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanBuilder.java b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanBuilder.java index d2af364dc..86faec0d4 100644 --- a/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanBuilder.java +++ b/scribble-codegen/src/main/java/org/scribble/codegen/statetype/STStateChanBuilder.java @@ -17,6 +17,6 @@ public abstract class STStateChanBuilder { - public abstract String getPreamble(STStateChanAPIBuilder api, EState s); - public abstract String build(STStateChanAPIBuilder api, EState s); + public abstract String getPreamble(STStateChanApiBuilder api, EState s); + public abstract String build(STStateChanApiBuilder api, EState s); } diff --git a/scribble-core/src/main/java/org/scribble/ast/AstFactoryImpl.java b/scribble-core/src/main/java/org/scribble/ast/AstFactoryImpl.java index b175f23ce..755821954 100644 --- a/scribble-core/src/main/java/org/scribble/ast/AstFactoryImpl.java +++ b/scribble-core/src/main/java/org/scribble/ast/AstFactoryImpl.java @@ -34,7 +34,6 @@ import org.scribble.ast.global.GWrap; import org.scribble.ast.local.LAccept; import org.scribble.ast.local.LChoice; -import org.scribble.ast.local.LRequest; import org.scribble.ast.local.LContinue; import org.scribble.ast.local.LDelegationElem; import org.scribble.ast.local.LDisconnect; @@ -48,6 +47,7 @@ import org.scribble.ast.local.LProtocolHeader; import org.scribble.ast.local.LReceive; import org.scribble.ast.local.LRecursion; +import org.scribble.ast.local.LRequest; import org.scribble.ast.local.LSend; import org.scribble.ast.local.LWrapClient; import org.scribble.ast.local.LWrapServer; @@ -91,7 +91,6 @@ import org.scribble.del.global.GWrapDel; import org.scribble.del.local.LAcceptDel; import org.scribble.del.local.LChoiceDel; -import org.scribble.del.local.LRequestDel; import org.scribble.del.local.LContinueDel; import org.scribble.del.local.LDisconnectDel; import org.scribble.del.local.LDoDel; @@ -102,6 +101,7 @@ import org.scribble.del.local.LProtocolDefDel; import org.scribble.del.local.LReceiveDel; import org.scribble.del.local.LRecursionDel; +import org.scribble.del.local.LRequestDel; import org.scribble.del.local.LSendDel; import org.scribble.del.local.LWrapClientDel; import org.scribble.del.local.LWrapServerDel; diff --git a/scribble-core/src/main/java/org/scribble/ast/Choice.java b/scribble-core/src/main/java/org/scribble/ast/Choice.java index 5559358a3..4d75de830 100644 --- a/scribble-core/src/main/java/org/scribble/ast/Choice.java +++ b/scribble-core/src/main/java/org/scribble/ast/Choice.java @@ -57,7 +57,7 @@ public String toString() { String sep = " " + Constants.OR_KW + " "; return Constants.CHOICE_KW + " " + Constants.AT_KW + " " + this.subj + " " - + this.blocks.stream().map((b) -> b.toString()).collect(Collectors.joining(sep)); + + this.blocks.stream().map(b -> b.toString()).collect(Collectors.joining(sep)); } /*@Override diff --git a/scribble-core/src/main/java/org/scribble/ast/ConnectionAction.java b/scribble-core/src/main/java/org/scribble/ast/ConnectionAction.java index bbdb11151..5c3528b22 100644 --- a/scribble-core/src/main/java/org/scribble/ast/ConnectionAction.java +++ b/scribble-core/src/main/java/org/scribble/ast/ConnectionAction.java @@ -58,6 +58,6 @@ protected boolean isUnitMessage() return false; } MessageSigNode msn = (MessageSigNode) this.msg; - return msn.op.isEmpty() && msn.payloads.isEmpty(); + return msn.op.isEmpty() && msn.payload.isEmpty(); } } diff --git a/scribble-core/src/main/java/org/scribble/ast/Constants.java b/scribble-core/src/main/java/org/scribble/ast/Constants.java index fb62cde91..011701bba 100644 --- a/scribble-core/src/main/java/org/scribble/ast/Constants.java +++ b/scribble-core/src/main/java/org/scribble/ast/Constants.java @@ -52,4 +52,6 @@ public class Constants public static final String CATCHES_KW = "catches";*/ public static final String DO_KW = "do"; //public static final String SPAWN_KW = "spawn"; + + public static final String CHOICES_KW = "choices"; } diff --git a/scribble-core/src/main/java/org/scribble/ast/MessageSigNode.java b/scribble-core/src/main/java/org/scribble/ast/MessageSigNode.java index 6eed9f625..1192f40f2 100644 --- a/scribble-core/src/main/java/org/scribble/ast/MessageSigNode.java +++ b/scribble-core/src/main/java/org/scribble/ast/MessageSigNode.java @@ -23,32 +23,32 @@ public class MessageSigNode extends ScribNodeBase implements MessageNode { public final OpNode op; - public final PayloadElemList payloads; + public final PayloadElemList payload; public MessageSigNode(CommonTree source, OpNode op, PayloadElemList payload) { super(source); this.op = op; - this.payloads = payload; + this.payload = payload; } @Override public MessageNode project(AstFactory af) // Currently outside of visitor/env pattern { - return af.MessageSigNode(this.source, this.op, this.payloads.project(af)); // Original del not retained by projection + return af.MessageSigNode(this.source, this.op, this.payload.project(af)); // Original del not retained by projection } @Override protected MessageSigNode copy() { - return new MessageSigNode(this.source, this.op, this.payloads); + return new MessageSigNode(this.source, this.op, this.payload); } @Override public MessageSigNode clone(AstFactory af) { OpNode op = this.op.clone(af); - PayloadElemList payload = this.payloads.clone(af); + PayloadElemList payload = this.payload.clone(af); return af.MessageSigNode(this.source, op, payload); } @@ -64,7 +64,7 @@ public MessageSigNode reconstruct(OpNode op, PayloadElemList payload) public MessageSigNode visitChildren(AstVisitor nv) throws ScribbleException { OpNode op = (OpNode) visitChild(this.op, nv); - PayloadElemList payload = (PayloadElemList) visitChild(this.payloads, nv); + PayloadElemList payload = (PayloadElemList) visitChild(this.payload, nv); return reconstruct(op, payload); } @@ -79,7 +79,7 @@ public boolean isMessageSigNode() @Override public MessageSig toArg() { - return new MessageSig(this.op.toName(), this.payloads.toPayload()); + return new MessageSig(this.op.toName(), this.payload.toPayload()); } @Override @@ -91,6 +91,6 @@ public MessageSig toMessage() @Override public String toString() { - return this.op.toString() + this.payloads.toString(); + return this.op.toString() + this.payload.toString(); } } diff --git a/scribble-core/src/main/java/org/scribble/ast/PayloadElemList.java b/scribble-core/src/main/java/org/scribble/ast/PayloadElemList.java index d6ba1fcce..c3f642629 100644 --- a/scribble-core/src/main/java/org/scribble/ast/PayloadElemList.java +++ b/scribble-core/src/main/java/org/scribble/ast/PayloadElemList.java @@ -84,7 +84,7 @@ public List> getElements() public Payload toPayload() { //List> pts = this.elems.stream().map((pe) -> pe.name.toPayloadType()).collect(Collectors.toList()); - List> pts = this.elems.stream().map((pe) -> pe.toPayloadType()).collect(Collectors.toList()); + List> pts = this.elems.stream().map(pe -> pe.toPayloadType()).collect(Collectors.toList()); return new Payload(pts); } @@ -96,6 +96,6 @@ public boolean isEmpty() @Override public String toString() { - return "(" + this.elems.stream().map((pe) -> pe.toString()).collect(Collectors.joining(", " )) + ")"; + return "(" + this.elems.stream().map(pe -> pe.toString()).collect(Collectors.joining(", " )) + ")"; } } diff --git a/scribble-core/src/main/java/org/scribble/ast/RoleDecl.java b/scribble-core/src/main/java/org/scribble/ast/RoleDecl.java index a1b60d183..9e8f7f6a5 100644 --- a/scribble-core/src/main/java/org/scribble/ast/RoleDecl.java +++ b/scribble-core/src/main/java/org/scribble/ast/RoleDecl.java @@ -42,6 +42,7 @@ public RoleDecl clone(AstFactory af) } @Override + //public RoleDecl reconstruct(RoleNode name) // No: because super public RoleDecl reconstruct(SimpleNameNode name) { ScribDel del = del(); diff --git a/scribble-core/src/main/java/org/scribble/ast/RoleDeclList.java b/scribble-core/src/main/java/org/scribble/ast/RoleDeclList.java index 74d273895..3382c5234 100644 --- a/scribble-core/src/main/java/org/scribble/ast/RoleDeclList.java +++ b/scribble-core/src/main/java/org/scribble/ast/RoleDeclList.java @@ -66,7 +66,8 @@ public List getRoles() @Override public RoleDeclList project(AstFactory af, Role self) { - return af.RoleDeclList(this.source, getDecls()); + //return af.RoleDeclList(this.source, getDecls()); + return af.RoleDeclList(this.source, getDecls().stream().map(rd -> rd.project(af, self)).collect(Collectors.toList())); } @Override diff --git a/scribble-core/src/main/java/org/scribble/ast/global/GChoice.java b/scribble-core/src/main/java/org/scribble/ast/global/GChoice.java index 5718f822d..60e20c63b 100644 --- a/scribble-core/src/main/java/org/scribble/ast/global/GChoice.java +++ b/scribble-core/src/main/java/org/scribble/ast/global/GChoice.java @@ -107,15 +107,8 @@ public List getBlocks() return castBlocks(super.getBlocks()); } - private static List castBlocks(List> blocks) + protected static List castBlocks(List> blocks) { - return blocks.stream().map((b) -> (GProtocolBlock) b).collect(Collectors.toList()); + return blocks.stream().map(b -> (GProtocolBlock) b).collect(Collectors.toList()); } - - /*// FIXME: shouldn't be needed, but here due to Eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=436350 - @Override - public Global getKind() - { - return GCompoundInteractionNode.super.getKind(); - }*/ } diff --git a/scribble-core/src/main/java/org/scribble/ast/global/GMessageTransfer.java b/scribble-core/src/main/java/org/scribble/ast/global/GMessageTransfer.java index 944f8cedc..4555cbebf 100644 --- a/scribble-core/src/main/java/org/scribble/ast/global/GMessageTransfer.java +++ b/scribble-core/src/main/java/org/scribble/ast/global/GMessageTransfer.java @@ -103,11 +103,4 @@ public String toString() return this.msg + " " + Constants.FROM_KW + " " + this.src + " " + Constants.TO_KW + " " + getDestinations().stream().map(dest -> dest.toString()).collect(Collectors.joining(", ")) + ";"; } - - /*// FIXME: shouldn't be needed, but here due to Eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=436350 - @Override - public Global getKind() - { - return GSimpleInteractionNode.super.getKind(); - }*/ } diff --git a/scribble-core/src/main/java/org/scribble/ast/local/LChoice.java b/scribble-core/src/main/java/org/scribble/ast/local/LChoice.java index 68b176d2c..455b99727 100644 --- a/scribble-core/src/main/java/org/scribble/ast/local/LChoice.java +++ b/scribble-core/src/main/java/org/scribble/ast/local/LChoice.java @@ -77,7 +77,7 @@ public Role inferLocalChoiceSubject(ProjectedChoiceSubjectFixer fixer) private static List castBlocks(List> blocks) { - return blocks.stream().map((b) -> (LProtocolBlock) b).collect(Collectors.toList()); + return blocks.stream().map(b -> (LProtocolBlock) b).collect(Collectors.toList()); } @Override diff --git a/scribble-core/src/main/java/org/scribble/ast/name/simple/AmbigNameNode.java b/scribble-core/src/main/java/org/scribble/ast/name/simple/AmbigNameNode.java index e1730d08c..d74e07870 100644 --- a/scribble-core/src/main/java/org/scribble/ast/name/simple/AmbigNameNode.java +++ b/scribble-core/src/main/java/org/scribble/ast/name/simple/AmbigNameNode.java @@ -104,7 +104,7 @@ public boolean canEqual(Object o) public int hashCode() { int hash = 331; - hash = 31 * super.hashCode(); + hash = 31*hash + super.hashCode(); return hash; } } diff --git a/scribble-core/src/main/java/org/scribble/ast/name/simple/DummyProjectionRoleNode.java b/scribble-core/src/main/java/org/scribble/ast/name/simple/DummyProjectionRoleNode.java index a45b6257d..b66ff7f25 100644 --- a/scribble-core/src/main/java/org/scribble/ast/name/simple/DummyProjectionRoleNode.java +++ b/scribble-core/src/main/java/org/scribble/ast/name/simple/DummyProjectionRoleNode.java @@ -86,7 +86,7 @@ public boolean canEqual(Object o) public int hashCode() { int hash = 359; - hash = 31 * super.hashCode(); + hash = 31*hash + super.hashCode(); return hash; } } diff --git a/scribble-core/src/main/java/org/scribble/ast/name/simple/OpNode.java b/scribble-core/src/main/java/org/scribble/ast/name/simple/OpNode.java index 2bdb3047d..d7734fc5e 100644 --- a/scribble-core/src/main/java/org/scribble/ast/name/simple/OpNode.java +++ b/scribble-core/src/main/java/org/scribble/ast/name/simple/OpNode.java @@ -75,7 +75,7 @@ public boolean canEqual(Object o) public int hashCode() { int hash = 347; - hash = 31 * super.hashCode(); + hash = 31*hash + super.hashCode(); return hash; } } diff --git a/scribble-core/src/main/java/org/scribble/ast/name/simple/RecVarNode.java b/scribble-core/src/main/java/org/scribble/ast/name/simple/RecVarNode.java index 4f0283826..60ba5a6ac 100644 --- a/scribble-core/src/main/java/org/scribble/ast/name/simple/RecVarNode.java +++ b/scribble-core/src/main/java/org/scribble/ast/name/simple/RecVarNode.java @@ -77,7 +77,7 @@ public boolean canEqual(Object o) public int hashCode() { int hash = 349; - hash = 31 * super.hashCode(); + hash = 31*hash + super.hashCode(); return hash; } } diff --git a/scribble-core/src/main/java/org/scribble/ast/name/simple/RoleNode.java b/scribble-core/src/main/java/org/scribble/ast/name/simple/RoleNode.java index 9f8c65069..f0a911ddf 100644 --- a/scribble-core/src/main/java/org/scribble/ast/name/simple/RoleNode.java +++ b/scribble-core/src/main/java/org/scribble/ast/name/simple/RoleNode.java @@ -85,7 +85,7 @@ public boolean canEqual(Object o) public int hashCode() { int hash = 353; - hash = 31 * super.hashCode(); + hash = 31*hash + super.hashCode(); return hash; } } diff --git a/scribble-core/src/main/java/org/scribble/ast/name/simple/ScopeNode.java b/scribble-core/src/main/java/org/scribble/ast/name/simple/ScopeNode.java index 3423fc362..6985d52a1 100644 --- a/scribble-core/src/main/java/org/scribble/ast/name/simple/ScopeNode.java +++ b/scribble-core/src/main/java/org/scribble/ast/name/simple/ScopeNode.java @@ -68,7 +68,7 @@ public boolean canEqual(Object o) public int hashCode() { int hash = 359; - hash = 31 * super.hashCode(); + hash = 31*hash + super.hashCode(); return hash; } } diff --git a/scribble-core/src/main/java/org/scribble/del/MessageTransferDel.java b/scribble-core/src/main/java/org/scribble/del/MessageTransferDel.java index 4dba242a1..da1daf82d 100644 --- a/scribble-core/src/main/java/org/scribble/del/MessageTransferDel.java +++ b/scribble-core/src/main/java/org/scribble/del/MessageTransferDel.java @@ -91,7 +91,7 @@ public MessageTransfer leaveProtocolDeclContextBuilding(ScribNode parent, Scr MessageTransfer mt = (MessageTransfer) visited; if (mt.msg.isMessageSigNode()) { - for (PayloadElem pe : ((MessageSigNode) mt.msg).payloads.getElements()) + for (PayloadElem pe : ((MessageSigNode) mt.msg).payload.getElements()) { if (pe.isGlobalDelegationElem()) // FIXME: should always be GMessageTransfer { diff --git a/scribble-core/src/main/java/org/scribble/del/global/GChoiceDel.java b/scribble-core/src/main/java/org/scribble/del/global/GChoiceDel.java index 7fdf44fdf..0f07840ae 100644 --- a/scribble-core/src/main/java/org/scribble/del/global/GChoiceDel.java +++ b/scribble-core/src/main/java/org/scribble/del/global/GChoiceDel.java @@ -38,6 +38,7 @@ public class GChoiceDel extends ChoiceDel implements GCompoundInteractionNodeDel { + @Override public ScribNode leaveProtocolInlining(ScribNode parent, ScribNode child, ProtocolDefInliner inl, ScribNode visited) throws ScribbleException { diff --git a/scribble-core/src/main/java/org/scribble/del/global/GDelegationElemDel.java b/scribble-core/src/main/java/org/scribble/del/global/GDelegationElemDel.java index ba9656a43..e3094f7d3 100644 --- a/scribble-core/src/main/java/org/scribble/del/global/GDelegationElemDel.java +++ b/scribble-core/src/main/java/org/scribble/del/global/GDelegationElemDel.java @@ -95,7 +95,7 @@ public void leaveMessageTransferInProtocolDeclContextBuilding(MessageTransfer { GProtocolName gpn = de.proto.toName(); // leaveDisambiguation has fully qualified the target name builder.addGlobalProtocolDependency(mt.src.toName(), gpn, de.role.toName()); // FIXME: does it make sense to use projection role as dependency target role? (seems to be used for Job.getProjections) - mt.getDestinationRoles().forEach((r) -> builder.addGlobalProtocolDependency(r, gpn, de.role.toName())); + mt.getDestinationRoles().forEach(r -> builder.addGlobalProtocolDependency(r, gpn, de.role.toName())); } @Override @@ -115,7 +115,7 @@ public void enterDelegationProtocolRefCheck(ScribNode parent, ScribNode child, D // FIXME: does this already contain transitive do-dependencies? But doesn't contain transitive delegation-dependencies..? Set init = ((GProtocolDeclDel) targetgpd.del()).getProtocolDeclContext().getDependencyMap().getDependencies() - .values().stream().flatMap((v) -> v.keySet().stream()).collect(Collectors.toSet()); + .values().stream().flatMap(v -> v.keySet().stream()).collect(Collectors.toSet()); todo.addAll(init); Set seen = new HashSet<>(); @@ -134,8 +134,8 @@ public void enterDelegationProtocolRefCheck(ScribNode parent, ScribNode child, D ProtocolDecl nextgpd = checker.job.getContext().getModule(targetfullname.getPrefix()).getProtocolDecl(nextfullname.getSimpleName()); Set tmp = ((GProtocolDeclDel) nextgpd.del()).getProtocolDeclContext().getDependencyMap().getDependencies() - .values().stream().flatMap((v) -> v.keySet().stream()) - .filter((n) -> !seen.contains(n)) + .values().stream().flatMap(v -> v.keySet().stream()) + .filter(n -> !seen.contains(n)) .collect(Collectors.toSet()); todo.addAll(tmp); } diff --git a/scribble-core/src/main/java/org/scribble/del/global/GMessageTransferDel.java b/scribble-core/src/main/java/org/scribble/del/global/GMessageTransferDel.java index e605a16af..8fce8ad62 100644 --- a/scribble-core/src/main/java/org/scribble/del/global/GMessageTransferDel.java +++ b/scribble-core/src/main/java/org/scribble/del/global/GMessageTransferDel.java @@ -42,7 +42,7 @@ public ScribNode leaveDisambiguation(ScribNode parent, ScribNode child, NameDisa List dests = gmt.getDestinationRoles(); if (dests.contains(src)) { - throw new ScribbleException(gmt.getSource(), "[TODO] Self connections not supported: " + gmt); // Would currently be subsumed by unconnected check + throw new ScribbleException(gmt.getSource(), "[TODO] Self communications not supported: " + gmt); // Would currently be subsumed by unconnected check } return gmt; } diff --git a/scribble-core/src/main/java/org/scribble/del/local/LAcceptDel.java b/scribble-core/src/main/java/org/scribble/del/local/LAcceptDel.java index 1f25ba9da..a3df498fa 100644 --- a/scribble-core/src/main/java/org/scribble/del/local/LAcceptDel.java +++ b/scribble-core/src/main/java/org/scribble/del/local/LAcceptDel.java @@ -36,7 +36,7 @@ public LAccept leaveEGraphBuilding(ScribNode parent, ScribNode child, EGraphBuil Role peer = la.src.toName(); MessageId mid = la.msg.toMessage().getId(); Payload payload = la.msg.isMessageSigNode() // Hacky? - ? ((MessageSigNode) la.msg).payloads.toPayload() + ? ((MessageSigNode) la.msg).payload.toPayload() : Payload.EMPTY_PAYLOAD; builder.util.addEdge(builder.util.getEntry(), builder.job.ef.newEAccept(peer, mid, payload), builder.util.getExit()); //builder.builder.addEdge(builder.builder.getEntry(), new Accept(peer), builder.builder.getExit()); diff --git a/scribble-core/src/main/java/org/scribble/del/local/LReceiveDel.java b/scribble-core/src/main/java/org/scribble/del/local/LReceiveDel.java index 801b8510b..37fa8856c 100644 --- a/scribble-core/src/main/java/org/scribble/del/local/LReceiveDel.java +++ b/scribble-core/src/main/java/org/scribble/del/local/LReceiveDel.java @@ -34,7 +34,7 @@ public ScribNode leaveEGraphBuilding(ScribNode parent, ScribNode child, EGraphBu Role peer = lr.src.toName(); MessageId mid = lr.msg.toMessage().getId(); Payload payload = (lr.msg.isMessageSigNode()) // Hacky? - ? ((MessageSigNode) lr.msg).payloads.toPayload() + ? ((MessageSigNode) lr.msg).payload.toPayload() : Payload.EMPTY_PAYLOAD; builder.util.addEdge(builder.util.getEntry(), builder.job.ef.newEReceive(peer, mid, payload), builder.util.getExit()); //builder.builder.addEdge(builder.builder.getEntry(), Receive.get(peer, mid, payload), builder.builder.getExit()); diff --git a/scribble-core/src/main/java/org/scribble/del/local/LRequestDel.java b/scribble-core/src/main/java/org/scribble/del/local/LRequestDel.java index b4f49ad9c..0552c5389 100644 --- a/scribble-core/src/main/java/org/scribble/del/local/LRequestDel.java +++ b/scribble-core/src/main/java/org/scribble/del/local/LRequestDel.java @@ -34,7 +34,7 @@ public LRequest leaveEGraphBuilding(ScribNode parent, ScribNode child, EGraphBui Role peer = dest.toName(); MessageId mid = lc.msg.toMessage().getId(); Payload payload = lc.msg.isMessageSigNode() // Hacky? - ? ((MessageSigNode) lc.msg).payloads.toPayload() + ? ((MessageSigNode) lc.msg).payload.toPayload() : Payload.EMPTY_PAYLOAD; builder.util.addEdge(builder.util.getEntry(), builder.job.ef.newERequest(peer, mid, payload), builder.util.getExit()); //graph.builder.addEdge(graph.builder.getEntry(), new Connect(peer), graph.builder.getExit()); diff --git a/scribble-core/src/main/java/org/scribble/del/local/LSendDel.java b/scribble-core/src/main/java/org/scribble/del/local/LSendDel.java index 9433e1a56..428b8231c 100644 --- a/scribble-core/src/main/java/org/scribble/del/local/LSendDel.java +++ b/scribble-core/src/main/java/org/scribble/del/local/LSendDel.java @@ -43,7 +43,7 @@ public ScribNode leaveEGraphBuilding(ScribNode parent, ScribNode child, EGraphBu Role peer = dests.get(0).toName(); MessageId mid = ls.msg.toMessage().getId(); Payload payload = ls.msg.isMessageSigNode() // Hacky? - ? ((MessageSigNode) ls.msg).payloads.toPayload() + ? ((MessageSigNode) ls.msg).payload.toPayload() : Payload.EMPTY_PAYLOAD; builder.util.addEdge(builder.util.getEntry(), builder.job.ef.newESend(peer, mid, payload), builder.util.getExit()); //builder.builder.addEdge(builder.builder.getEntry(), Send.get(peer, mid, payload), builder.builder.getExit()); diff --git a/scribble-core/src/main/java/org/scribble/model/MState.java b/scribble-core/src/main/java/org/scribble/model/MState.java index 0dae3bb73..8190035b4 100644 --- a/scribble-core/src/main/java/org/scribble/model/MState.java +++ b/scribble-core/src/main/java/org/scribble/model/MState.java @@ -165,6 +165,7 @@ public final boolean isTerminal() return this.actions.isEmpty(); } + // Returns null if none public static , S extends MState, K extends ProtocolKind> S getTerminal(S start) { @@ -172,7 +173,7 @@ S getTerminal(S start) { return start; } - Set terms = MState.getReachableStates(start).stream().filter((s) -> s.isTerminal()).collect(Collectors.toSet()); + Set terms = MState.getReachableStates(start).stream().filter(s -> s.isTerminal()).collect(Collectors.toSet()); if (terms.size() > 1) { throw new RuntimeException("Shouldn't get in here: " + terms); diff --git a/scribble-core/src/main/java/org/scribble/model/endpoint/EGraphBuilderUtil.java b/scribble-core/src/main/java/org/scribble/model/endpoint/EGraphBuilderUtil.java index d771f8b57..8b808a8f8 100644 --- a/scribble-core/src/main/java/org/scribble/model/endpoint/EGraphBuilderUtil.java +++ b/scribble-core/src/main/java/org/scribble/model/endpoint/EGraphBuilderUtil.java @@ -64,7 +64,7 @@ public EGraphBuilderUtil(EModelFactory ef) public void init(EState init) { clear(); - reset(this.ef.newEState(Collections.emptySet()), this.ef.newEState(Collections.emptySet())); + reset(init, this.ef.newEState(Collections.emptySet())); } protected void clear() diff --git a/scribble-core/src/main/java/org/scribble/model/endpoint/EModelFactory.java b/scribble-core/src/main/java/org/scribble/model/endpoint/EModelFactory.java index 43e981467..bac432e54 100644 --- a/scribble-core/src/main/java/org/scribble/model/endpoint/EModelFactory.java +++ b/scribble-core/src/main/java/org/scribble/model/endpoint/EModelFactory.java @@ -29,6 +29,9 @@ public interface EModelFactory { + + EState newEState(Set labs); + ESend newESend(Role peer, MessageId mid, Payload payload); EReceive newEReceive(Role peer, MessageId mid, Payload payload); ERequest newERequest(Role peer, MessageId mid, Payload payload); @@ -36,6 +39,4 @@ public interface EModelFactory EDisconnect newEDisconnect(Role peer); EWrapClient newEWrapClient(Role peer); EWrapServer newEWrapServer(Role peer); - - EState newEState(Set labs); } diff --git a/scribble-core/src/main/java/org/scribble/model/endpoint/EModelFactoryImpl.java b/scribble-core/src/main/java/org/scribble/model/endpoint/EModelFactoryImpl.java index 3505dc96c..a06b3b288 100644 --- a/scribble-core/src/main/java/org/scribble/model/endpoint/EModelFactoryImpl.java +++ b/scribble-core/src/main/java/org/scribble/model/endpoint/EModelFactoryImpl.java @@ -31,6 +31,12 @@ public class EModelFactoryImpl implements EModelFactory { + @Override + public EState newEState(Set labs) + { + return new EState(labs); + } + @Override public ESend newESend(Role peer, MessageId mid, Payload payload) { @@ -72,10 +78,4 @@ public EWrapServer newEWrapServer(Role peer) { return new EWrapServer(this, peer); } - - @Override - public EState newEState(Set labs) - { - return new EState(labs); - } } diff --git a/scribble-core/src/main/java/org/scribble/model/endpoint/actions/EAction.java b/scribble-core/src/main/java/org/scribble/model/endpoint/actions/EAction.java index fc0121252..22f09a6e2 100644 --- a/scribble-core/src/main/java/org/scribble/model/endpoint/actions/EAction.java +++ b/scribble-core/src/main/java/org/scribble/model/endpoint/actions/EAction.java @@ -24,7 +24,7 @@ public abstract class EAction extends MAction { - public final Role peer; + public final Role peer; // this.peer == this.obj /*public final MessageId mid; public final Payload payload; // Empty for MessageSigNames*/ diff --git a/scribble-core/src/main/java/org/scribble/model/endpoint/actions/EReceive.java b/scribble-core/src/main/java/org/scribble/model/endpoint/actions/EReceive.java index 11b351dc2..c4bb258bb 100644 --- a/scribble-core/src/main/java/org/scribble/model/endpoint/actions/EReceive.java +++ b/scribble-core/src/main/java/org/scribble/model/endpoint/actions/EReceive.java @@ -91,9 +91,10 @@ public boolean equals(Object o) { return false; } - return ((EReceive) o).canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } + @Override public boolean canEqual(Object o) { return o instanceof EReceive; diff --git a/scribble-core/src/main/java/org/scribble/model/endpoint/actions/ESend.java b/scribble-core/src/main/java/org/scribble/model/endpoint/actions/ESend.java index fb8176cd6..9188a0d1b 100644 --- a/scribble-core/src/main/java/org/scribble/model/endpoint/actions/ESend.java +++ b/scribble-core/src/main/java/org/scribble/model/endpoint/actions/ESend.java @@ -90,7 +90,7 @@ public boolean equals(Object o) { return false; } - return ((ESend) o).canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } @Override diff --git a/scribble-core/src/main/java/org/scribble/sesstype/Arg.java b/scribble-core/src/main/java/org/scribble/sesstype/Arg.java deleted file mode 100644 index 20830210d..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/Arg.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype; - -import org.scribble.sesstype.kind.NonRoleArgKind; - -// A subprotocol argument (DoArgNode): SigKind or PayloadTypeKind -public interface Arg -{ - NonRoleArgKind getKind(); -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/Message.java b/scribble-core/src/main/java/org/scribble/sesstype/Message.java deleted file mode 100644 index e6c33dbef..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/Message.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype; - -import org.scribble.sesstype.kind.MessageIdKind; -import org.scribble.sesstype.kind.SigKind; -import org.scribble.sesstype.name.MessageId; - - - -// A sig kind name: MessageSignature value (or parameter) -public interface Message extends Arg -{ - MessageId getId(); -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/MessageSig.java b/scribble-core/src/main/java/org/scribble/sesstype/MessageSig.java deleted file mode 100644 index f54990e5a..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/MessageSig.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype; - -import org.scribble.sesstype.kind.OpKind; -import org.scribble.sesstype.kind.SigKind; -import org.scribble.sesstype.name.MessageId; -import org.scribble.sesstype.name.Op; - -public class MessageSig implements Message -{ - public final Op op; - public final Payload payload; - - public MessageSig(Op op, Payload payload) - { - this.op = op; - this.payload = payload; - } - - @Override - public SigKind getKind() - { - return SigKind.KIND; - } - - @Override - public MessageId getId() - { - return this.op; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof MessageSig)) - { - return false; - } - MessageSig sig = (MessageSig) o; - return this.op.equals(sig.op) && this.payload.equals(sig.payload); - } - - @Override - public int hashCode() - { - int hash = 3187; - hash = 31 * hash + this.op.hashCode(); - hash = 31 * hash + this.payload.hashCode(); - return hash; - } - - @Override - public String toString() - { - return this.op.toString() + this.payload.toString(); - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/Payload.java b/scribble-core/src/main/java/org/scribble/sesstype/Payload.java deleted file mode 100644 index 77cc6de32..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/Payload.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype; - -import java.util.Collections; -import java.util.List; - -import org.scribble.sesstype.kind.Kind; -import org.scribble.sesstype.kind.PayloadTypeKind; -import org.scribble.sesstype.name.PayloadElemType; - -public class Payload -{ - public static final Payload EMPTY_PAYLOAD = new Payload(Collections.emptyList()); - - public final List> elems; - - public Payload(List> payload) - { - this.elems = payload; - } - - public boolean isEmpty() - { - return this.elems.isEmpty(); - } - - @Override - public int hashCode() - { - int hash = 577; - hash = 31 * hash + this.elems.hashCode(); - return hash; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof Payload)) - { - return false; - } - return this.elems.equals(((Payload) o).elems); - } - - @Override - public String toString() - { - if (this.elems.isEmpty()) - { - return "()"; - } - String payload = "(" + this.elems.get(0); - for (PayloadElemType pt : this.elems.subList(1, this.elems.size())) - { - payload+= ", " + pt; - } - return payload + ")"; - } - - /*@Override - public boolean isParameter() - { - return false; - }*/ -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/SessionTypeFactory.java b/scribble-core/src/main/java/org/scribble/sesstype/SessionTypeFactory.java deleted file mode 100644 index 68c620de8..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/SessionTypeFactory.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype; - -import java.util.Arrays; - -import org.scribble.sesstype.name.GProtocolName; -import org.scribble.sesstype.name.ModuleName; -import org.scribble.sesstype.name.PackageName; - -@Deprecated -public class SessionTypeFactory -{ - public SessionTypeFactory() - { - - } - - /*public static ModuleName parseModuleName(String name) - { - String[] elems = name.split("\\."); - return new ModuleName(elems); - }*/ - - // From fullname - public static GProtocolName parseGlobalProtocolName(String name) - { - String[] elems = name.split("\\."); - if (elems.length < 2) - { - throw new RuntimeException("Bad protocol full name: " + name); - } - String membname = elems[elems.length - 1]; - ModuleName modname = new ModuleName(elems[elems.length - 2]); - if (elems.length > 2) - { - PackageName packname = new PackageName(Arrays.copyOfRange(elems, 0, elems.length - 2)); - modname = new ModuleName(packname, modname); - } - GProtocolName gpn = new GProtocolName(membname); - return new GProtocolName(modname, gpn); - } - - /*public static Scope parseScope(String name) - { - String[] elems = name.split("\\."); - return new Scope(elems); - }*/ -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/SubprotocolSig.java b/scribble-core/src/main/java/org/scribble/sesstype/SubprotocolSig.java deleted file mode 100644 index f9d994782..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/SubprotocolSig.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype; - -import java.util.LinkedList; -import java.util.List; - -import org.scribble.sesstype.kind.Kind; -import org.scribble.sesstype.kind.NonRoleArgKind; -import org.scribble.sesstype.kind.ProtocolKind; -import org.scribble.sesstype.name.ProtocolName; -import org.scribble.sesstype.name.Role; - -public class SubprotocolSig -{ - public ProtocolName fmn; - //public Scope scope; - public List roles; - public List> args; - - //public SubprotocolSignature(ProtocolName fmn, Scope scope, List roles, List> args) - public SubprotocolSig(ProtocolName fmn, List roles, List> args) - { - this.fmn = fmn; - //this.scope = scope; - this.roles = new LinkedList<>(roles); - this.args = new LinkedList<>(args); - } - - @Override - public int hashCode() - { - int hash = 1093; - hash = 31 * hash + this.fmn.hashCode(); - //hash = 31 * hash + this.scope.hashCode(); - hash = 31 * hash + this.roles.hashCode(); - hash = 31 * hash + this.args.hashCode(); - return hash; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - //if (o == null || this.getClass() != o.getClass()) - if (!(o instanceof SubprotocolSig)) - { - return false; - } - SubprotocolSig subsig = (SubprotocolSig) o; - return this.fmn.equals(subsig.fmn) //&& this.scope.equals(subsig.scope) - && this.roles.equals(subsig.roles) && this.args.equals(subsig.args); - } - - @Override - public String toString() - { - String args = this.args.toString(); - String roles = this.roles.toString(); - return //this.scope + ":" + - this.fmn + "<" + args.substring(1, args.length() - 1) + ">(" + roles.substring(1, roles.length() - 1) + ")"; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/AbstractKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/AbstractKind.java deleted file mode 100644 index 8f8f7a9e3..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/AbstractKind.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public abstract class AbstractKind implements Kind -{ - public AbstractKind() - { - - } - - @Override - public abstract boolean equals(Object o); - - public abstract boolean canEqual(Object o); // Not really needed due to singleton pattern - - @Override - public String toString() - { - String s = this.getClass().toString(); - return s.substring("class org.sribble.sesstype.kind.".length() + 1, s.length()); - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/AmbigKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/AmbigKind.java deleted file mode 100644 index e21abf6cb..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/AmbigKind.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -public class AmbigKind extends AbstractKind implements NonRoleArgKind//, PayloadTypeKind -{ - public static final AmbigKind KIND = new AmbigKind(); - - protected AmbigKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof AmbigKind)) - { - return false; - } - return ((AmbigKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof AmbigKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/DataTypeKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/DataTypeKind.java deleted file mode 100644 index 89ac37885..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/DataTypeKind.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public class DataTypeKind extends AbstractKind implements PayloadTypeKind, ImportKind, ModuleMemberKind -{ - public static final DataTypeKind KIND = new DataTypeKind(); - - protected DataTypeKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof DataTypeKind)) - { - return false; - } - return ((DataTypeKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof DataTypeKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/Global.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/Global.java deleted file mode 100644 index 3a9af8bd0..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/Global.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public class Global extends AbstractKind implements ProtocolKind -{ - public static final Global KIND = new Global(); - - protected Global() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof Global)) - { - return false; - } - return ((Global) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof Global; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/ImportKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/ImportKind.java deleted file mode 100644 index 043af163d..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/ImportKind.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -public interface ImportKind extends Kind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/Kind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/Kind.java deleted file mode 100644 index c94bd1ecb..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/Kind.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -import org.scribble.sesstype.name.Name; - -public interface Kind -{ - public static Name castName(K kind, Name name) - { - kind.getClass().cast(name.getKind()); - @SuppressWarnings("unchecked") - Name tmp = (Name) name; - return tmp; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/Local.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/Local.java deleted file mode 100644 index 462dde490..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/Local.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public class Local extends AbstractKind implements ProtocolKind, PayloadTypeKind -{ - public static final Local KIND = new Local(); - - protected Local() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof Local)) - { - return false; - } - return ((Local) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof Local; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/MessageIdKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/MessageIdKind.java deleted file mode 100644 index f0f6f6692..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/MessageIdKind.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -public interface MessageIdKind extends Kind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/ModuleKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/ModuleKind.java deleted file mode 100644 index 2c8606426..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/ModuleKind.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public class ModuleKind extends AbstractKind implements ImportKind -{ - public static final ModuleKind KIND = new ModuleKind(); - - protected ModuleKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof ModuleKind)) - { - return false; - } - return ((ModuleKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof ModuleKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/ModuleMemberKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/ModuleMemberKind.java deleted file mode 100644 index 967c5b115..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/ModuleMemberKind.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -public interface ModuleMemberKind extends Kind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/NonProtocolKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/NonProtocolKind.java deleted file mode 100644 index 291e6abd3..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/NonProtocolKind.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -public interface NonProtocolKind extends Kind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/NonRoleArgKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/NonRoleArgKind.java deleted file mode 100644 index 84a42a6dd..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/NonRoleArgKind.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -// Following sesstype.Arg hierarchy -// Non-role args -- includes AmbigKind (cf. AntlrNonRoleArgList) -public interface NonRoleArgKind extends NonProtocolKind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/NonRoleParamKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/NonRoleParamKind.java deleted file mode 100644 index 430729300..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/NonRoleParamKind.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -// Non-role params -public interface NonRoleParamKind extends NonRoleArgKind, ParamKind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/OpKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/OpKind.java deleted file mode 100644 index 27f812a9f..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/OpKind.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -import java.io.Serializable; - -public class OpKind extends AbstractKind implements MessageIdKind, Serializable -{ - private static final long serialVersionUID = 1L; - - public static final OpKind KIND = new OpKind(); - - protected OpKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof OpKind)) - { - return false; - } - return ((OpKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof OpKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/PackageKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/PackageKind.java deleted file mode 100644 index 2deb817bd..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/PackageKind.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public class PackageKind extends AbstractKind -{ - public static final PackageKind KIND = new PackageKind(); - - protected PackageKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof PackageKind)) - { - return false; - } - return ((PackageKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof PackageKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/ParamKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/ParamKind.java deleted file mode 100644 index 70d68aa32..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/ParamKind.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -public interface ParamKind extends Kind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/PayloadTypeKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/PayloadTypeKind.java deleted file mode 100644 index 592b55ba9..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/PayloadTypeKind.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -// Following sesstype.Arg hierarchy -public interface PayloadTypeKind extends NonRoleParamKind //ArgKind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/ProtocolKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/ProtocolKind.java deleted file mode 100644 index 089a7f7a8..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/ProtocolKind.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public interface ProtocolKind extends ModuleMemberKind -{ - -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/RecVarKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/RecVarKind.java deleted file mode 100644 index 6b1777982..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/RecVarKind.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public class RecVarKind extends AbstractKind -{ - public static final RecVarKind KIND = new RecVarKind(); - - protected RecVarKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof RecVarKind)) - { - return false; - } - return ((RecVarKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof RecVarKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/RoleKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/RoleKind.java deleted file mode 100644 index c90c33c0a..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/RoleKind.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public class RoleKind extends AbstractKind implements ParamKind -{ - public static final RoleKind KIND = new RoleKind(); - - protected RoleKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof RoleKind)) - { - return false; - } - return ((RoleKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof RoleKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/ScopeKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/ScopeKind.java deleted file mode 100644 index 97d73fadb..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/ScopeKind.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - -public class ScopeKind extends AbstractKind -{ - public static final ScopeKind KIND = new ScopeKind(); - - protected ScopeKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof ScopeKind)) - { - return false; - } - return ((ScopeKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof ScopeKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/kind/SigKind.java b/scribble-core/src/main/java/org/scribble/sesstype/kind/SigKind.java deleted file mode 100644 index d874f307d..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/kind/SigKind.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.kind; - - -// Following sesstype.Arg hierarchy -public class SigKind extends AbstractKind implements NonRoleParamKind, MessageIdKind, //ArgKind - ModuleMemberKind -{ - public static final SigKind KIND = new SigKind(); - - protected SigKind() - { - - } - - @Override - public int hashCode() - { - return super.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - { - return true; - } - if (!(o instanceof SigKind)) - { - return false; - } - return ((SigKind) o).canEqual(this); - } - - @Override - public boolean canEqual(Object o) - { - return o instanceof SigKind; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/AbstractName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/AbstractName.java deleted file mode 100644 index 749b4c65a..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/AbstractName.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import java.io.IOException; -import java.util.Arrays; - -import org.scribble.sesstype.kind.Kind; - -public abstract class AbstractName implements Name -{ - private static final long serialVersionUID = 1L; - - private K kind; // non-final for serialization - - private String[] elems; - - protected AbstractName(K kind, String... elems) - { - this.kind = kind; - this.elems = elems; - } - - @Override - public K getKind() - { - return this.kind; - } - - @Override - public int getElementCount() - { - return this.elems.length; - } - - @Override - public boolean isEmpty() - { - return this.elems.length == 0; - } - - @Override - public boolean isPrefixed() - { - return this.elems.length > 1; - } - - @Override - public String[] getElements() - { - return Arrays.copyOf(this.elems, this.elems.length); - } - @Override - public String[] getPrefixElements() - { - return Arrays.copyOfRange(this.elems, 0, this.elems.length - 1); - } - - // Not SimpleName so that e.g. ModuleName can return a simple ModuleName - @Override - public String getLastElement() - { - return this.elems[this.elems.length - 1]; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof AbstractName)) - { - return false; - } - AbstractName n = (AbstractName) o; - return n.canEqual(this) && this.kind.equals(n.kind) && Arrays.equals(this.elems, (n.elems)); - } - - public abstract boolean canEqual(Object o); - - @Override - public int hashCode() - { - int hash = 2749; - hash = 31 * hash + this.kind.hashCode(); - hash = 31 * hash + Arrays.hashCode(this.elems); - return hash; - } - - @Override - public String toString() - { - if (isEmpty()) - { - return ""; - } - String name = this.elems[0]; - for (int i = 1; i < this.elems.length; i++) - { - name += "." + this.elems[i]; - } - return name; - } - - private void writeObject(java.io.ObjectOutputStream out) throws IOException - { - out.writeObject(this.kind); - out.writeObject(this.elems); - } - - private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException - { - @SuppressWarnings("unchecked") - K k = (K) in.readObject(); - this.kind = k; - //this.kind = readKind(); // TODO: protected abstract -- will this work? - this.elems = (String[]) in.readObject(); - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/AmbigName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/AmbigName.java deleted file mode 100644 index 4b3122e1c..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/AmbigName.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.AmbigKind; - -public class AmbigName extends AbstractName -{ - private static final long serialVersionUID = 1L; - - public AmbigName(String text) - { - super(AmbigKind.KIND, text); - } - - public MessageSigName toMessageSigName() - { - return new MessageSigName(getLastElement()); - } - - public DataType toDataType() - { - return new DataType(getLastElement()); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof AmbigName)) - { - return false; - } - AmbigName n = (AmbigName) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof AmbigName; - } - - @Override - public int hashCode() - { - int hash = 2753; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/DataType.java b/scribble-core/src/main/java/org/scribble/sesstype/name/DataType.java deleted file mode 100644 index 5fb17ce4a..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/DataType.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.DataTypeKind; - - -// Potentially qualified/canonical payload type name; not the AST primitive identifier -public class DataType extends MemberName implements PayloadElemType -{ - private static final long serialVersionUID = 1L; - - public DataType(ModuleName modname, DataType membname) - { - super(DataTypeKind.KIND, modname, membname); - } - - public DataType(String simplename) - { - super(DataTypeKind.KIND, simplename); - } - - public boolean isDataType() - { - return true; - } - - @Override - public DataTypeKind getKind() - { - return DataTypeKind.KIND; - } - - @Override - public DataType getSimpleName() - { - return new DataType(getLastElement()); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof DataType)) - { - return false; - } - DataType n = (DataType) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof DataType; - } - - @Override - public int hashCode() - { - int hash = 2767; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/GDelegationType.java b/scribble-core/src/main/java/org/scribble/sesstype/name/GDelegationType.java deleted file mode 100644 index e24881cf5..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/GDelegationType.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import java.io.IOException; -import java.io.Serializable; - -import org.scribble.sesstype.kind.Local; - -// FIXME: factor out of name package? (and then PayloadType also needs to be moved out of name?) -public class GDelegationType implements PayloadElemType, Serializable -{ - private static final long serialVersionUID = 1L; - - private GProtocolName proto; // Cannot be final, for Serializable - private Role role; - - public GDelegationType(GProtocolName proto, Role role) - { - this.proto = proto; - this.role = role; - } - - @Override - public boolean isGDelegationType() - { - return true; - } - - public GProtocolName getGlobalProtocol() - { - return this.proto; - } - - public Role getRole() - { - return this.role; - } - - @Override - public Local getKind() - { - return Local.KIND; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof GDelegationType)) - { - return false; - } - GDelegationType them = (GDelegationType) o; - return them.canEqual(this) && this.proto.equals(them.proto) && this.role.equals(them.role); - } - - public boolean canEqual(Object o) - { - return o instanceof GDelegationType; - } - - @Override - public int hashCode() - { - int hash = 1381; - hash = 31 * this.proto.hashCode(); - hash = 31 * this.role.hashCode(); - return hash; - } - - private void writeObject(java.io.ObjectOutputStream out) throws IOException - { - out.writeObject(this.proto); - out.writeObject(this.role); - } - - private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException - { - this.proto = (GProtocolName) in.readObject(); - this.role = (Role) in.readObject(); - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/GProtocolName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/GProtocolName.java deleted file mode 100644 index 09fb1f9bb..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/GProtocolName.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.Global; - - -public class GProtocolName extends ProtocolName -{ - private static final long serialVersionUID = 1L; - - public GProtocolName(ModuleName modname, ProtocolName membname) - { - super(Global.KIND, modname, membname); - } - - public GProtocolName(String simpname) - { - super(Global.KIND, simpname); - } - - @Override - public GProtocolName getSimpleName() - { - return new GProtocolName(getLastElement()); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof GProtocolName)) - { - return false; - } - GProtocolName n = (GProtocolName) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof GProtocolName; - } - - @Override - public int hashCode() - { - int hash = 2777; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/LProtocolName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/LProtocolName.java deleted file mode 100644 index 6690e0996..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/LProtocolName.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.Local; - - -public class LProtocolName extends ProtocolName implements PayloadElemType //-- not needed, deleg elems currently have to be (Global@Role) -{ - private static final long serialVersionUID = 1L; - - public LProtocolName(ModuleName modname, ProtocolName membname) - { - super(Local.KIND, modname, membname); - } - - public LProtocolName(String simpname) - { - super(Local.KIND, simpname); - } - - /*@Override - public boolean isLDelegationType() - { - return true; - }*/ - - @Override - public LProtocolName getSimpleName() - { - return new LProtocolName(getLastElement()); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof LProtocolName)) - { - return false; - } - LProtocolName n = (LProtocolName) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof LProtocolName; - } - - @Override - public int hashCode() - { - int hash = 2789; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/MemberName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/MemberName.java deleted file mode 100644 index e18e339c4..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/MemberName.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.Kind; - - -// Simple name or qualified name -public abstract class MemberName extends QualifiedName -{ - private static final long serialVersionUID = 1L; - - public MemberName(K kind, ModuleName modname, Name membname) - { - super(kind, compileMemberName(modname, membname)); - } - - public MemberName(K kind, String simplename) - { - super(kind, Name.compileElements(ModuleName.EMPTY_MODULENAME.getElements(), simplename)); - } - - public ModuleName getPrefix() - { - return new ModuleName(getPrefixElements()); - } - - // Similar in ModuleName - private static String[] compileMemberName(ModuleName modname, Name membname) - { - return Name.compileElements(modname.getElements(), membname.getLastElement()); - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/MessageId.java b/scribble-core/src/main/java/org/scribble/sesstype/name/MessageId.java deleted file mode 100644 index b9fcfa95c..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/MessageId.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.MessageIdKind; - - -public interface MessageId extends Name -{ - default boolean isOp() - { - return false; - } - - default boolean isMessageSigName() - { - return false; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/MessageSigName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/MessageSigName.java deleted file mode 100644 index 382e66c59..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/MessageSigName.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.Message; -import org.scribble.sesstype.kind.SigKind; - - -// The name of a declared (imported) message signature member -public class MessageSigName extends MemberName implements Message, MessageId -{ - private static final long serialVersionUID = 1L; - - public MessageSigName(ModuleName modname, MessageSigName simplename) - { - super(SigKind.KIND, modname, simplename); - } - - public MessageSigName(String simplename) - { - super(SigKind.KIND, simplename); - } - - @Override - public SigKind getKind() - { - return SigKind.KIND; // Same as this.kind - } - - @Override - public MessageSigName getSimpleName() - { - return new MessageSigName(getLastElement()); - } - - @Override - public MessageId getId() - { - return this; // FIXME: should be resolved to a canonical name - } - - @Override - public boolean isMessageSigName() - { - return true; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof MessageSigName)) - { - return false; - } - MessageSigName n = (MessageSigName) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof MessageSigName; - } - - @Override - public int hashCode() - { - int hash = 2791; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/ModuleName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/ModuleName.java deleted file mode 100644 index 7b8e52fbc..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/ModuleName.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.scribble.ast.Constants; -import org.scribble.sesstype.kind.ModuleKind; - -// General name: simple or full (a central class for value comparison) -public class ModuleName extends QualifiedName -{ - private static final long serialVersionUID = 1L; - - protected static final ModuleName EMPTY_MODULENAME = new ModuleName(); - - protected ModuleName(String... elems) - { - super(ModuleKind.KIND, elems); - } - - public ModuleName(PackageName packname, ModuleName modname) - { - super(ModuleKind.KIND, compileModuleName(packname, modname)); - } - - public ModuleName(String modname) - { - super(ModuleKind.KIND, Name.compileElements(PackageName.EMPTY_PACKAGENAME.getElements(), modname)); - } - - public Path toPath() - { - String[] elems = getElements(); - String file = elems[0]; - for (int i = 1; i < elems.length; i++) - { - file += "/" + elems[i]; - } - return Paths.get(file + "." + Constants.SCRIBBLE_FILE_EXTENSION); - } - - public boolean isSimpleName() - { - return !isPrefixed(); - } - - @Override - public ModuleName getSimpleName() - { - return new ModuleName(getLastElement()); - } - - public PackageName getPrefix() - { - return new PackageName(getPrefixElements()); - } - - public PackageName getPackageName() - { - return getPrefix(); - } - - private static String[] compileModuleName(PackageName packname, ModuleName modname) - { - return Name.compileElements(packname.getElements(), modname.getLastElement()); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof ModuleName)) - { - return false; - } - ModuleName n = (ModuleName) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof ModuleName; - } - - @Override - public int hashCode() - { - int hash = 2797; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/Name.java b/scribble-core/src/main/java/org/scribble/sesstype/name/Name.java deleted file mode 100644 index cfe84e20f..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/Name.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import java.io.Serializable; -import java.util.Arrays; - -import org.scribble.sesstype.kind.Kind; - - -public interface Name extends Serializable -{ - public K getKind(); - - public int getElementCount(); - public boolean isEmpty(); - public boolean isPrefixed(); - - public String[] getElements(); - public String[] getPrefixElements(); - public String getLastElement(); - - static String[] compileElements(String[] cn, String n) - { - if (cn.length == 0) - { - return new String[] { n }; - } - String[] elems = Arrays.copyOf(cn, cn.length + 1); - elems[elems.length - 1] = n; - return elems; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/Named.java b/scribble-core/src/main/java/org/scribble/sesstype/name/Named.java deleted file mode 100644 index 5f9045875..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/Named.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.Kind; - - -public interface Named -{ - Name toName(); -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/Op.java b/scribble-core/src/main/java/org/scribble/sesstype/name/Op.java deleted file mode 100644 index a8378853a..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/Op.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.OpKind; - -public class Op extends AbstractName implements MessageId -{ - private static final long serialVersionUID = 1L; - - public static final Op EMPTY_OPERATOR = new Op(); - - protected Op() - { - super(OpKind.KIND); - } - - public Op(String text) - { - super(OpKind.KIND, text); - } - - @Override - public boolean isOp() - { - return true; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof Op)) - { - return false; - } - Op n = (Op) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof Op; - } - - @Override - public int hashCode() - { - int hash = 2801; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/PackageName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/PackageName.java deleted file mode 100644 index 2abadb580..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/PackageName.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.PackageKind; - -public class PackageName extends QualifiedName -{ - private static final long serialVersionUID = 1L; - - public static final PackageName EMPTY_PACKAGENAME = new PackageName(); - - public PackageName(String... elems) - { - super(PackageKind.KIND, elems); - } - - @Override - public PackageName getPrefix() - { - return new PackageName(getPrefixElements()); - } - - @Override - public PackageName getSimpleName() - { - return new PackageName(getLastElement()); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof PackageName)) - { - return false; - } - PackageName n = (PackageName) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof PackageName; - } - - @Override - public int hashCode() - { - int hash = 2803; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/PayloadElemType.java b/scribble-core/src/main/java/org/scribble/sesstype/name/PayloadElemType.java deleted file mode 100644 index 16f538e5d..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/PayloadElemType.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.Arg; -import org.scribble.sesstype.kind.PayloadTypeKind; - - -public interface PayloadElemType extends Arg -{ - default boolean isDataType() - { - return false; - } - - default boolean isGDelegationType() - { - return false; - } - - /*public boolean isLDelegationType() - { - return true; - }*/ -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/PayloadType.java b/scribble-core/src/main/java/org/scribble/sesstype/name/PayloadType.java deleted file mode 100644 index 570b011fc..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/PayloadType.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.Arg; -import org.scribble.sesstype.kind.PayloadTypeKind; - - -public interface PayloadType extends Arg -{ - default boolean isDataType() - { - return false; - } - - default boolean isGDelegationType() - { - return false; - } - - /*public boolean isLDelegationType() - { - return true; - }*/ -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/ProtocolName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/ProtocolName.java deleted file mode 100644 index 5c53ba6b5..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/ProtocolName.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.ProtocolKind; - - -// Potentially qualified/canonical protocol name; not the AST primitive identifier -public abstract class ProtocolName extends MemberName -{ - private static final long serialVersionUID = 1L; - - public ProtocolName(K kind, ModuleName modname, ProtocolName membname) - { - super(kind, modname, membname); - } - - public ProtocolName(K kind, String simpname) - { - super(kind, simpname); - } - - @Override - public abstract ProtocolName getSimpleName(); -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/QualifiedName.java b/scribble-core/src/main/java/org/scribble/sesstype/name/QualifiedName.java deleted file mode 100644 index 7c1fd2333..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/QualifiedName.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.Kind; - - - -public abstract class QualifiedName extends AbstractName -{ - private static final long serialVersionUID = 1L; - - public QualifiedName(K kind, String... elems) - { - super(kind, elems); - } - - @Override - public boolean isEmpty() - { - return super.isEmpty(); - } - - @Override - public boolean isPrefixed() - { - return super.isPrefixed(); - } - - // Also done by Scope - public abstract Name getPrefix(); - public abstract Name getSimpleName(); -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/RecVar.java b/scribble-core/src/main/java/org/scribble/sesstype/name/RecVar.java deleted file mode 100644 index ea4061d32..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/RecVar.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.RecVarKind; - -public class RecVar extends AbstractName //implements PathElement -{ - private static final long serialVersionUID = 1L; - - protected RecVar() - { - super(RecVarKind.KIND); - } - - public RecVar(String text) - { - super(RecVarKind.KIND, text); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof RecVar)) - { - return false; - } - RecVar n = (RecVar) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof RecVar; - } - - @Override - public int hashCode() - { - int hash = 2819; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/Role.java b/scribble-core/src/main/java/org/scribble/sesstype/name/Role.java deleted file mode 100644 index ac11f9d2b..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/Role.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.RoleKind; - - -public class Role extends AbstractName -{ - public static final Role EMPTY_ROLE = new Role(); - - private static final long serialVersionUID = 1L; - - protected Role() - { - super(RoleKind.KIND); - } - - public Role(String text) - { - super(RoleKind.KIND, text); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof Role)) - { - return false; - } - Role n = (Role) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof Role; - } - - @Override - public int hashCode() - { - int hash = 2741; - hash = 31 * super.hashCode(); - return hash; - } -} diff --git a/scribble-core/src/main/java/org/scribble/sesstype/name/Scope.java b/scribble-core/src/main/java/org/scribble/sesstype/name/Scope.java deleted file mode 100644 index 0c70718f8..000000000 --- a/scribble-core/src/main/java/org/scribble/sesstype/name/Scope.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright 2008 The Scribble Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - */ -package org.scribble.sesstype.name; - -import org.scribble.sesstype.kind.ScopeKind; - -// Should be a compound name? -public class Scope extends AbstractName -{ - private static final long serialVersionUID = 1L; - - public static final String IMPLICIT_SCOPE_PREFIX = "__scope"; - public static final Scope EMPTY_SCOPE = new Scope(); - public static final Scope ROOT_SCOPE = new Scope("__root"); - - protected Scope(String... elems) - { - super(ScopeKind.KIND, elems); - } - - public Scope(String name) - { - this(new String[] { name }); - } - - public Scope(Scope prefix, Name name) - { - this(compileScope(prefix, name)); - } - - // Also done by QualifiedName - public Scope getPrefix() - { - return new Scope(getPrefixElements()); - } - - public Scope getSimpleName() - { - return new Scope(getLastElement()); - } - - @Override - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (!(o instanceof Scope)) - { - return false; - } - Scope n = (Scope) o; - return n.canEqual(this) && super.equals(o); - } - - public boolean canEqual(Object o) - { - return o instanceof Scope; - } - - @Override - public int hashCode() - { - int hash = 2833; - hash = 31 * super.hashCode(); - return hash; - } - - private static String[] compileScope(Scope prefix, Name name) - { - String[] tmp = prefix.getElements(); - String[] elems = new String[tmp.length + 1]; - System.arraycopy(tmp, 0, elems, 0, tmp.length); - elems[elems.length - 1] = name.toString(); - return elems; - } -} diff --git a/scribble-core/src/main/java/org/scribble/type/name/AmbigName.java b/scribble-core/src/main/java/org/scribble/type/name/AmbigName.java index 7e71c4b2d..5237e9648 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/AmbigName.java +++ b/scribble-core/src/main/java/org/scribble/type/name/AmbigName.java @@ -45,8 +45,7 @@ public boolean equals(Object o) { return false; } - AmbigName n = (AmbigName) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/DataType.java b/scribble-core/src/main/java/org/scribble/type/name/DataType.java index 7e7aa6a8f..554e4b186 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/DataType.java +++ b/scribble-core/src/main/java/org/scribble/type/name/DataType.java @@ -59,8 +59,7 @@ public boolean equals(Object o) { return false; } - DataType n = (DataType) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/GDelegationType.java b/scribble-core/src/main/java/org/scribble/type/name/GDelegationType.java index 64a9dfd8d..05258ab4a 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/GDelegationType.java +++ b/scribble-core/src/main/java/org/scribble/type/name/GDelegationType.java @@ -23,14 +23,20 @@ public class GDelegationType implements PayloadElemType, Serializable { private static final long serialVersionUID = 1L; - private GProtocolName proto; // Cannot be final, for Serializable - private Role role; + protected GProtocolName proto; // Cannot be final, for Serializable + protected Role role; public GDelegationType(GProtocolName proto, Role role) { this.proto = proto; this.role = role; } + + @Override + public String toString() + { + return this.proto + "@" + this.role; + } @Override public boolean isGDelegationType() diff --git a/scribble-core/src/main/java/org/scribble/type/name/GProtocolName.java b/scribble-core/src/main/java/org/scribble/type/name/GProtocolName.java index 24172ab23..2a0976220 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/GProtocolName.java +++ b/scribble-core/src/main/java/org/scribble/type/name/GProtocolName.java @@ -47,8 +47,7 @@ public boolean equals(Object o) { return false; } - GProtocolName n = (GProtocolName) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/LProtocolName.java b/scribble-core/src/main/java/org/scribble/type/name/LProtocolName.java index 3c0540914..57c27613c 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/LProtocolName.java +++ b/scribble-core/src/main/java/org/scribble/type/name/LProtocolName.java @@ -53,8 +53,7 @@ public boolean equals(Object o) { return false; } - LProtocolName n = (LProtocolName) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/MessageSigName.java b/scribble-core/src/main/java/org/scribble/type/name/MessageSigName.java index 09a1837f0..5ed32e6ae 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/MessageSigName.java +++ b/scribble-core/src/main/java/org/scribble/type/name/MessageSigName.java @@ -17,7 +17,7 @@ import org.scribble.type.kind.SigKind; -// The name of a declared (imported) message signature member +// The name of a declared (imported) message signature member -- basically a session types "message label" public class MessageSigName extends MemberName implements Message, MessageId { private static final long serialVersionUID = 1L; @@ -67,8 +67,7 @@ public boolean equals(Object o) { return false; } - MessageSigName n = (MessageSigName) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/ModuleName.java b/scribble-core/src/main/java/org/scribble/type/name/ModuleName.java index d250feea3..0fd526cdc 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/ModuleName.java +++ b/scribble-core/src/main/java/org/scribble/type/name/ModuleName.java @@ -89,8 +89,7 @@ public boolean equals(Object o) { return false; } - ModuleName n = (ModuleName) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/Op.java b/scribble-core/src/main/java/org/scribble/type/name/Op.java index 56720b373..2e6052c50 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/Op.java +++ b/scribble-core/src/main/java/org/scribble/type/name/Op.java @@ -48,8 +48,7 @@ public boolean equals(Object o) { return false; } - Op n = (Op) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/PackageName.java b/scribble-core/src/main/java/org/scribble/type/name/PackageName.java index 843c1f6c5..20e911c11 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/PackageName.java +++ b/scribble-core/src/main/java/org/scribble/type/name/PackageName.java @@ -49,8 +49,7 @@ public boolean equals(Object o) { return false; } - PackageName n = (PackageName) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/RecVar.java b/scribble-core/src/main/java/org/scribble/type/name/RecVar.java index b69f8cde7..1487b3cea 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/RecVar.java +++ b/scribble-core/src/main/java/org/scribble/type/name/RecVar.java @@ -40,8 +40,7 @@ public boolean equals(Object o) { return false; } - RecVar n = (RecVar) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/type/name/Role.java b/scribble-core/src/main/java/org/scribble/type/name/Role.java index fa537fa51..762784952 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/Role.java +++ b/scribble-core/src/main/java/org/scribble/type/name/Role.java @@ -43,10 +43,10 @@ public boolean equals(Object o) { return false; } - Role n = (Role) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } + @Override public boolean canEqual(Object o) { return o instanceof Role; diff --git a/scribble-core/src/main/java/org/scribble/type/name/Scope.java b/scribble-core/src/main/java/org/scribble/type/name/Scope.java index b0ed6991d..63fe5bf43 100644 --- a/scribble-core/src/main/java/org/scribble/type/name/Scope.java +++ b/scribble-core/src/main/java/org/scribble/type/name/Scope.java @@ -61,8 +61,7 @@ public boolean equals(Object o) { return false; } - Scope n = (Scope) o; - return n.canEqual(this) && super.equals(o); + return super.equals(o); // Does canEqual } public boolean canEqual(Object o) diff --git a/scribble-core/src/main/java/org/scribble/util/Pair.java b/scribble-core/src/main/java/org/scribble/util/Pair.java index f6a3f2fc8..236fb469c 100644 --- a/scribble-core/src/main/java/org/scribble/util/Pair.java +++ b/scribble-core/src/main/java/org/scribble/util/Pair.java @@ -24,6 +24,12 @@ public Pair(T1 t1, T2 t2) this.right = t2; } + @Override + public String toString() + { + return "(" + this.left + ", " + this.right + ")"; + } + @Override public int hashCode() { diff --git a/scribble-core/src/main/java/org/scribble/util/ScribUtil.java b/scribble-core/src/main/java/org/scribble/util/ScribUtil.java index ba0ed752b..accdbb5c1 100644 --- a/scribble-core/src/main/java/org/scribble/util/ScribUtil.java +++ b/scribble-core/src/main/java/org/scribble/util/ScribUtil.java @@ -19,9 +19,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.Callable; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.scribble.ast.AstFactory; import org.scribble.ast.ScribNode; @@ -105,7 +108,13 @@ public static String[] runProcess(String... cmdAndArgs) throws ScribbleException // Warning: doesn't check if file exists public static void writeToFile(String path, String text) throws ScribbleException { + // TODO: add optional file existence check here (e.g., refactor from Z3Wrapper) File file = new File(path); + writeToFile(file, text); + } + + public static void writeToFile(File file, String text) throws ScribbleException + { File parent = file.getParentFile(); if (parent != null) { @@ -121,4 +130,19 @@ public static void writeToFile(String path, String text) throws ScribbleExceptio throw new ScribbleException(e); } } + + public static Set> makePowerSet(Set ts) + { + Set> pset = new HashSet<>(); + for (T t : ts) + { + Set curr = Stream.of(t).collect(Collectors.toSet()); + Set> tmp = pset.stream() + .map(x -> Stream.concat(x.stream(), Stream.of(t)).collect(Collectors.toSet())) + .collect(Collectors.toSet()); + pset.add(curr); + pset.addAll(tmp); // tmp.equals(curr) for first t + } + return pset; + } } diff --git a/scribble-core/src/main/java/org/scribble/visit/NoEnvInlinedProtocolVisitor.java b/scribble-core/src/main/java/org/scribble/visit/NoEnvInlinedProtocolVisitor.java index dd308b876..c93607716 100644 --- a/scribble-core/src/main/java/org/scribble/visit/NoEnvInlinedProtocolVisitor.java +++ b/scribble-core/src/main/java/org/scribble/visit/NoEnvInlinedProtocolVisitor.java @@ -15,6 +15,7 @@ import org.scribble.ast.ProtocolDecl; import org.scribble.main.Job; +import org.scribble.type.kind.ProtocolKind; import org.scribble.visit.env.DummyEnv; public abstract class NoEnvInlinedProtocolVisitor extends InlinedProtocolVisitor @@ -25,7 +26,7 @@ public NoEnvInlinedProtocolVisitor(Job job) } @Override - protected final DummyEnv makeRootProtocolDeclEnv(ProtocolDecl pd) + protected final DummyEnv makeRootProtocolDeclEnv(ProtocolDecl pd) { return DummyEnv.DUMMY; } diff --git a/scribble-dist/src/main/resources/scribblec.sh b/scribble-dist/src/main/resources/scribblec.sh index 5f2df50b3..8841ee7a8 100644 --- a/scribble-dist/src/main/resources/scribblec.sh +++ b/scribble-dist/src/main/resources/scribblec.sh @@ -25,7 +25,7 @@ # ANTLR 3 runtime location (if no lib jar) -ANTLR= +ANTLR='scribble-parser/lib/antlr-3.5.2-complete.jar' # e.g., '~/.m2/repository/org/antlr/antlr-runtime/3.4/antlr-runtime-3.4.jar' # or '/cygdrive/c/Users/[User]/.m2/repository/org/antlr/antlr-runtime/3.4/antlr-runtime-3.4.jar' # (i.e., the Maven install location) diff --git a/scribble-go/pom.xml b/scribble-go/pom.xml new file mode 100644 index 000000000..adf011b0c --- /dev/null +++ b/scribble-go/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + org.scribble + parent + 0.4.4-SNAPSHOT + + scribble-go + scribble-go + http://maven.apache.org + + UTF-8 + + + + org.scribble + scribble-core + + + org.scribble + scribble-cli + + + org.scribble + scribble-parser + + + org.scribble + scribble-codegen + + + junit + junit + test + + + + + + + org.antlr + antlr3-maven-plugin + ${antlr.version} + + + + antlr + + + + + + + + com.mycila + license-maven-plugin + + + **/*.g + **/*.java + **/*.scr + **/IGNORE + **/*.policy + **/*.xml + **/*.html + **/stylesheet.css + **/script.js + **/package-list + **/*.txt + **/*.go + + + + + + diff --git a/scribble-go/src/main/antlr3/org/scribble/parser/antlr/ParamScribble.g b/scribble-go/src/main/antlr3/org/scribble/parser/antlr/ParamScribble.g new file mode 100644 index 000000000..bcc7230a1 --- /dev/null +++ b/scribble-go/src/main/antlr3/org/scribble/parser/antlr/ParamScribble.g @@ -0,0 +1,1150 @@ +//$ java -cp scribble-parser/lib/antlr-3.5.2-complete.jar org.antlr.Tool -o scribble-go/target/generated-sources/antlr3 scribble-go/src/main/antlr3/org/scribble/parser/antlr/ParamScribble.g + +// Cygwin/Windows: +//$ java -cp scribble-parser/lib/antlr-3.5.2-complete.jar org.antlr.Tool -o scribble-go/target/generated-sources/antlr3/org/scribble/parser/antlr scribble-go/src/main/antlr3/org/scribble/parser/antlr/ParamScribble.g +//$ mv scribble-go/target/generated-sources/antlr3/org/scribble/parser/antlr/ParamScribble.tokens scribble-go/target/generated-sources/antlr3/ + + +grammar ParamScribble; + + +options +{ + language = Java; + output = AST; + ASTLabelType = CommonTree; + //backtrack = true; // backtracking disabled by default? Is it bad to require this option? + //memoize = true; +} + + +tokens +{ + /* + * Parser input constants (lexer output; keywords, Section 2.4) + */ + + MODULE_KW = 'module'; + IMPORT_KW = 'import'; + TYPE_KW = 'type'; + PROTOCOL_KW = 'protocol'; + GLOBAL_KW = 'global'; + LOCAL_KW = 'local'; + EXPLICIT_KW = 'explicit'; + AUX_KW = 'aux'; + ROLE_KW = 'role'; + ACCEPT_KW = 'accept'; + SELF_KW = 'self'; + SIG_KW = 'sig'; + //INSTANTIATES_KW = 'instantiates'; + AS_KW = 'as'; + + CONNECT_KW = 'connect'; + DISCONNECT_KW = 'disconnect'; + WRAP_KW = 'wrap'; + FROM_KW = 'from'; + TO_KW = 'to'; + CHOICE_KW = 'choice'; + AT_KW = 'at'; + OR_KW = 'or'; + REC_KW = 'rec'; + CONTINUE_KW = 'continue'; + //PAR_KW = 'par'; + AND_KW = 'and'; // Needed for disconnect + /*INTERRUPTIBLE_KW = 'interruptible'; + WITH_KW = 'with'; + BY_KW = 'by'; /* from for interrupts is more expected, but from is + not good for multiple roles (generally, the comma + in interrupt message list and role list looks like + "and" rather than "or") * / + THROWS_KW = 'throws'; + CATCHES_KW = 'catches';*/ + DO_KW = 'do'; + //SPAWN_KW = 'spawn'; + + DOT_KW = 'dot'; + CHOICES_KW = 'choices'; + + + PARAM_DELEG_KW = 'deleg'; + PARAM_FOREACH_KW = 'foreach'; + + + /* + * Parser output "node types" (corresponding to the various syntactic + * categories) i.e. the labels used to distinguish resulting AST nodes. + * The value of these token variables doesn't matter, only the token + * (i.e. variable) names themselves are used (for AST node root text + * field) + */ + + // Purely util constants -- not parsed as node types + + KIND_MESSAGESIGNATURE = 'KIND_MESSAGESIGNATURE'; + KIND_PAYLOADTYPE = 'KIND_PAYLOADTYPE'; + + + // "Node type" constants -- but not parsed "directly" by AntlrToScribParser + + EMPTY_ALIAS = 'EMTPY_ALIAS'; + /*EMPTY_SCOPENAME = '__empty_scopename'; + NO_SCOPE = '__no_scope';*/ + //EMPTY_PACKAGENAME = '__empty_packagebame'; + EMPTY_OPERATOR = 'EMPTY_OPERATOR'; + + //EMPTY_PARAMETERDECLLIST = '__empty_parameterdecllist'; + //EMPTY_ARGUMENTINSTANTIATIONLIST = '__empty_argumentinstantiationlist'; + /*EMPTY_LOCALTHROW = '__empty_localthrow'; + EMPTY_LOCAL_CATCHES = '__empty_local_catch';*/ + + //NAME = 'name'; + AMBIGUOUSNAME = 'AMBIGUOUSNAME'; + QUALIFIEDNAME = 'QUALIFIEDNAME'; + //PACKAGENAME = 'package-name'; + //FULLMODULENAME = 'full-module-name'; + //SIMPLEMEMBERNAME = 'simple-member-name'; + //QUALIFIEDMEMBERNAME = 'qualified-member-name'; + + MESSAGESIGNATURE = 'MESSAGESIGNATURE'; + //DELEGATION = 'DELEGATION'; + PARAM_DELEGATION = 'PARAM_DELEGATION'; + + + // Parsed "directly" by AntlrToScribParser + + PAYLOAD = 'PAYLOAD'; + //PAYLOADELEMENT = 'payloadelement'; + + //MODULE = 'module'; // Probably a keyword clash + MODULE = 'MODULE'; + //PACKAGEDECL = 'package-decl'; + MODULEDECL = 'MODULEDECL'; + //IMPORTDECL = 'import-decl'; + //FROMIMPORTDECL = 'from-import-decl'; + IMPORTMODULE = 'IMPORTMODULE'; + IMPORTMEMBER = 'IMPORTMEMBER'; + PAYLOADTYPEDECL = 'PAYLOADTYPEDECL'; + MESSAGESIGNATUREDECL = 'MESSAGESIGNATUREDECL'; + ROLEDECLLIST = 'ROLEDECLLIST'; + ROLEDECL = 'ROLEDECL'; + PARAMETERDECLLIST = 'PARAMETERDECLLIST'; + PARAMETERDECL = 'PARAMETERDECL'; + ROLEINSTANTIATIONLIST = 'ROLEINSTANTIATIONLIST'; + ROLEINSTANTIATION = 'ROLEINSTANTIATION'; // FIXME: not consistent with arginstas/payloadeles + ARGUMENTINSTANTIATIONLIST = 'ARGUMENTINSTANTIATIONLIST'; + //ARGUMENTINSTANTIATION = 'argument-instantiation'; + //CONNECTDECL = 'connect-decl'; + + GLOBALPROTOCOLDECL = 'GLOBALPROTOCOLDECL'; + GLOBALPROTOCOLDECLMODS = 'GLOBALPROTOCOLDECLMODS'; + GLOBALPROTOCOLHEADER = 'GLOBALPROTOCOLHEADER'; + GLOBALPROTOCOLDEF = 'GLOBALPROTOCOLDEF'; + GLOBALPROTOCOLBLOCK = 'GLOBALPROTOCOLBLOCK'; + GLOBALINTERACTIONSEQUENCE = 'GLOBALINTERACTIONSEQUENCE'; + GLOBALMESSAGETRANSFER = 'GLOBALMESSAGETRANSFER'; + GLOBALCONNECT = 'GLOBALCONNECT'; + GLOBALDISCONNECT = 'GLOBALDISCONNECT'; + GLOBALWRAP = 'GLOBALWRAP'; + GLOBALCHOICE = 'GLOBALCHOICE'; + GLOBALRECURSION = 'GLOBALRECURSION'; + GLOBALCONTINUE = 'GLOBALCONTINUE'; + /*GLOBALPARALLEL = 'GLOBALPARALLEL'; + GLOBALINTERRUPTIBLE = 'GLOBALINTERRUPTIBLE'; + GLOBALINTERRUPT = 'GLOBALINTERRUPT';*/ + GLOBALDO = 'GLOBALDO'; + + /*LOCALPROTOCOLDECL = 'local-protocol-decl'; + LOCALROLEDECLLIST = 'local-role-decl-list'; + LOCALROLEDECL = 'local-role-decl'; + SELFDECL = 'self-decl'; + LOCALPROTOCOLDEF = 'local-protocol-def'; + LOCALPROTOCOLINSTANCE = 'local-protocol-instance'; + LOCALPROTOCOLBLOCK = 'local-protocol-block'; + LOCALINTERACTIONSEQUENCE = 'local-interaction-sequence'; + LOCALMESSAGETRANSFER = 'local-message-transfer'; + LOCALCHOICE = 'local-choice'; + LOCALRECURSION = 'local-recursion'; + LOCALCONTINUE = 'local-continue'; + LOCALPARALLEL = 'local-parallel'; + LOCALINTERRUPTIBLE = 'local-interruptible'; + LOCALINTERRUPT = 'local-interrupt'; + LOCALDO = 'local-do'; + LOCALTHROWS = 'local-throws'; + LOCALCATCHES = 'local-catches'; + LOCALSEND = 'local-send'; + LOCALRECEIVE = 'local-receive';*/ + + + PARAM_BININDEXEXPR = 'PARAM_BININDEXEXPR'; // FIXME: rename bin part + //PARAM_ROLEDECL = 'PARAM_ROLEDECL'; + PARAM_GLOBALCROSSMESSAGETRANSFER = 'PARAM_GLOBALCROSSMESSAGETRANSFER'; + PARAM_GLOBALDOTMESSAGETRANSFER = 'PARAM_GLOBALDOTMESSAGETRANSFER'; + PARAM_GLOBALCHOICE = 'PARAM_GLOBALCHOICE'; + /*PARAM_GLOBALMULTICHOICES = 'PARAM_GLOBALMULTICHOICES'; + PARAM_GLOBALMULTICHOICESTRANSFER = 'PARAM_GLOBALMULTICHOICESTRANSFER';*/ + //PARAM_DELEGATION = 'PARAM_DELEGATION'; + PARAM_DELEGDECL = 'PARAM_DELEGDECL'; + PARAM_GLOBALFOREACH = 'PARAM_GLOBALFOREACH'; + + PARAM_INDEXINTERVAL = 'PARAM_INDEXINTERVAL'; + PARAM_FOREACHINTERVAL = 'PARAM_FOREACHINTERVAL'; + + PARAM_PAIR = 'PARAM_PAIR'; + //PARAM_NOMODS = 'PARAM_NOMODS'; + PARAM_GLOBALPROTOCOLHEADER = 'PARAM_GLOBALPROTOCOLHEADER'; +} + + +// Has to come after tokens? +@parser::header +{ + package org.scribble.parser.antlr; + + //import org.scribble.main.RuntimeScribbleException; +} + +@lexer::header +{ + package org.scribble.parser.antlr; + + //import org.scribble.main.RuntimeScribbleException; +} + +/*// Was swallowing parser error messages +@members { + //private org.scribble.logging.IssueLogger _logger=null; + private String _document=null; + private boolean _errorOccurred=false; + + /*public void setLogger(org.scribble.logging.IssueLogger logger) { + _logger = logger; + }* / + + public void setDocument(String doc) { + _document = doc; + } + + public void emitErrorMessage(String mesg) { + /*if (_logger == null) { + super.emitErrorMessage(mesg); + } else { + _logger.error(org.scribble.parser.antlr.ANTLRMessageUtil.getMessageText(mesg), + org.scribble.parser.antlr.ANTLRMessageUtil.getProperties(mesg, _document)); + }* / + _errorOccurred = true; + } + + public boolean isErrorOccurred() { + return(_errorOccurred); + } +}*/ + +@parser::members +{ + /*@Override + public void reportError(RecognitionException e) + { + super.reportError(e); + //throw new RuntimeScribbleException(e.getMessage()); + //System.exit(1); + }*/ + + // Abort tool run on parsing errors (and display user-friendly message) -- obsoletes CommonErrorNode check? + @Override + public void displayRecognitionError(String[] tokenNames, RecognitionException e) + { + /*String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, tokenNames); + //throw new RuntimeException(hdr + ":" + msg); + System.err.println(hdr + ":" + msg);*/ + super.displayRecognitionError(tokenNames, e); + System.exit(1); + } +} + +@lexer::members +{ + /*@Override + public void reportError(RecognitionException e) + { + super.reportError(e); + //throw new RuntimeScribbleException(e.getMessage()); + //System.exit(1); + }*/ + + @Override + public void displayRecognitionError(String[] tokenNames, RecognitionException e) + { + /*String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, tokenNames); + //throw new RuntimeException(hdr + ":" + msg); + System.err.println(hdr + ":" + msg);*/ + super.displayRecognitionError(tokenNames, e); + System.exit(1); + } +} + + +/**************************************************************************** + * Chapter 2 Lexical Structure (Lexer rules) + ***************************************************************************/ + +/* + * Section 2.1 White space (Section 2.1) + */ + +// Not referred to explicitly, deals with whitespace implicitly (don't delete this) +WHITESPACE: + ('\t' | ' ' | '\r' | '\n'| '\u000C')+ + { + $channel = HIDDEN; + } + +; + +/** + * Section 2.2 Comments + */ +COMMENT: + '/*' .* '*/' + { + $channel=HIDDEN; + } +; + +LINE_COMMENT: + '//' ~('\n'|'\r')* '\r'? '\n' + { + $channel=HIDDEN; + } +; + +/** + * Section 2.3 Identifiers + */ + +/* // Seems "conflict" with IDENTIFIER +number: + (DIGIT)+ +;*/ + + +IDENTIFIER: + (LETTER | DIGIT | UNDERSCORE)* + /* Underscore currently can cause ambiguities in the API generation naming scheme + * But maybe only consecutive underscores are the problem + * -- cannot completely disallow underscores as needed for projection naming scheme + * Or disallow underscores only for role/op/messagesig names + */ +// (LETTER | DIGIT)* +; + +fragment SYMBOL: + '{' | '}' | '(' | ')' | '[' | ']' | ':' | '/' | '\\' | '.' | '\#' +| + '&' | '?' | '!' | UNDERSCORE | ',' | '=' | '<' | '>' | '-' | '*' +; + +// Comes after SYMBOL due to an ANTLR syntax highlighting issue involving +// quotes. +// Parser doesn't work without quotes here (e.g. if inlined into parser rules) +EXTIDENTIFIER: + '\"' (LETTER | DIGIT | SYMBOL)* '\"' + //(LETTER | DIGIT | SYMBOL)* +; + +fragment LETTER: + 'a'..'z' | 'A'..'Z' +; + +fragment DIGIT: + '0'..'9' +; + +fragment UNDERSCORE: + '_' +; + + +/**************************************************************************** + * Chapter 3 Syntax (Parser rules) + ***************************************************************************/ + +/* + * Section 3.1 Primitive Names + */ + +simplename: + IDENTIFIER +/*-> + ^(SIMPLENAME IDENTIFIER)*/ +; + +//annotationname: simplename; +parametername: simplename; +recursionvarname: simplename; +rolename: simplename; +scopename: simplename; + +variantname: simplename; + +ambiguousname: + simplename +-> + ^(AMBIGUOUSNAME simplename) +; + + +/** + * Section 3.2.1 Package, Module and Module Member Names + */ + +simplemodulename: simplename; +simplepayloadtypename: simplename; +simplemessagesignaturename: simplename; +simpleprotocolname: simplename; +simplemembername: simplename; // Only for member declarations + +qualifiedname: + IDENTIFIER ('.' IDENTIFIER)* +-> + ^(QUALIFIEDNAME IDENTIFIER+) +; + +packagename: qualifiedname; +modulename: qualifiedname; +membername: qualifiedname; + +protocolname: membername; +payloadtypename: membername; +messagesignaturename: membername; + + +/** + * Section 3.2.2 Top-level Module Structure + */ +module: + moduledecl importdecl* datatypedecl* protocoldecl* EOF + //moduledecl importdecl* datatypedecl* delegdecl* protocoldecl* EOF +-> + ^(MODULE moduledecl importdecl* datatypedecl* protocoldecl*) + //^(MODULE moduledecl importdecl* datatypedecl* delegdecl* protocoldecl*) +; + + +/** + * Section 3.2.3 Module Declarations + */ +moduledecl: + MODULE_KW modulename ';' +-> + ^(MODULEDECL modulename) +; + + +/** + * Section 3.3 Import Declarations + */ +importdecl: + importmodule +| + importmember +; + +importmodule: + IMPORT_KW modulename ';' +-> + ^(IMPORTMODULE modulename EMPTY_ALIAS) +| + IMPORT_KW modulename AS_KW simplemodulename ';' +-> + ^(IMPORTMODULE modulename simplemodulename) +; + +importmember: + FROM_KW modulename IMPORT_KW simplemembername ';' +-> + ^(IMPORTMEMBER modulename simplemembername EMPTY_ALIAS) +| + FROM_KW modulename IMPORT_KW simplemembername AS_KW simplemembername ';' +-> + ^(IMPORTMEMBER modulename simplemembername simplemembername) +; + + +/** + * //Section 3.4 Payload Type Declarations + * Data Declarations + */ +datatypedecl: + payloadtypedecl +| + messagesignaturedecl +; + +payloadtypedecl: + TYPE_KW '<' IDENTIFIER '>' EXTIDENTIFIER FROM_KW EXTIDENTIFIER AS_KW simplepayloadtypename ';' +-> + ^(PAYLOADTYPEDECL IDENTIFIER EXTIDENTIFIER EXTIDENTIFIER simplepayloadtypename) +; + + +// param-core +/*delegdecl: + PARAM_DELEG_KW '<' IDENTIFIER '>' EXTIDENTIFIER FROM_KW EXTIDENTIFIER AS_KW simplepayloadtypename ';' +-> + ^(PARAM_DELEGDECL IDENTIFIER EXTIDENTIFIER EXTIDENTIFIER simplepayloadtypename) +;*/ + + +messagesignaturedecl: + SIG_KW '<' IDENTIFIER '>' EXTIDENTIFIER FROM_KW EXTIDENTIFIER AS_KW simplemessagesignaturename ';' +-> + ^(MESSAGESIGNATUREDECL IDENTIFIER EXTIDENTIFIER EXTIDENTIFIER simplemessagesignaturename) +; + + +/** + * Section 3.5 Message Signatures + */ +/*messageoperator: + IDENTIFIER +;*/ + +messagesignature: + '(' payload ')' +-> + ^(MESSAGESIGNATURE EMPTY_OPERATOR payload) +| + //messageoperator '(' payload ')' // Doesn't work (conflict with IDENTIFIER?) + IDENTIFIER '(' payload ')' +-> + ^(MESSAGESIGNATURE IDENTIFIER payload) +| + '(' ')' +-> + ^(MESSAGESIGNATURE EMPTY_OPERATOR ^(PAYLOAD)) +| + IDENTIFIER '(' ')' +-> + ^(MESSAGESIGNATURE IDENTIFIER ^(PAYLOAD)) +; + +payload: + payloadelement (',' payloadelement)* +-> + ^(PAYLOAD payloadelement+) +; + +// Payload type names need disambiguation pass (also do args) +payloadelement: +/* ambiguousname // Parser doesn't distinguish simple from qualified properly, even with backtrack +|*/ + qualifiedname // This case subsumes simple names // FIXME: ambiguousqualifiedname (or ambiguousname should just be qualified) +| + protocolname '@' variantname +-> + //^(DELEGATION rolename protocolname) + ^(PARAM_DELEGATION variantname protocolname) +/*| + protocolname '@' rolename '[' paramindexexpr ']' // FIXME: should be @variant -- need user syntax for variant +-> + ^(PARAM_DELEGATION rolename protocolname) paramindexexpr)*/ +| + protocolname ':' protocolname '@' variantname +-> + ^(PARAM_DELEGATION variantname protocolname protocolname) +; + + +/** + * Section 3.6 Protocol Declarations + */ +protocoldecl: + globalprotocoldecl +/*| + localprotocoldecl*/ +; + + +/** + * Section 3.7 Global Protocol Declarations + */ +globalprotocoldecl: + globalprotocolheader globalprotocoldefinition // TODO: refactor into below (e.g., PARAM_NOMODS) +-> + ^(GLOBALPROTOCOLDECL globalprotocolheader globalprotocoldefinition) +| + globalprotocoldeclmodifiers globalprotocolheader globalprotocoldefinition // HACK: backwards compat for "implicit" connections +-> + ^(GLOBALPROTOCOLDECL globalprotocolheader globalprotocoldefinition globalprotocoldeclmodifiers) +; + +/*// CHECKME: refactor to header? cf. Assrt +| + globalprotocolheader '@' EXTIDENTIFIER globalprotocoldefinition +-> + ^(GLOBALPROTOCOLDECL globalprotocolheader globalprotocoldefinition PARAM_NOMODS EXTIDENTIFIER) +| + globalprotocoldeclmodifiers globalprotocolheader '@' EXTIDENTIFIER globalprotocoldefinition +-> + ^(GLOBALPROTOCOLDECL globalprotocolheader globalprotocoldefinition globalprotocoldeclmodifiers EXTIDENTIFIER)*/ + +globalprotocoldeclmodifiers: + AUX_KW EXPLICIT_KW +-> + ^(GLOBALPROTOCOLDECLMODS AUX_KW EXPLICIT_KW) +| + EXPLICIT_KW +-> + ^(GLOBALPROTOCOLDECLMODS EXPLICIT_KW) +| + AUX_KW +-> + ^(GLOBALPROTOCOLDECLMODS AUX_KW) +; + +globalprotocolheader: + GLOBAL_KW PROTOCOL_KW simpleprotocolname roledecllist +-> + ^(GLOBALPROTOCOLHEADER simpleprotocolname ^(PARAMETERDECLLIST) roledecllist) +| + GLOBAL_KW PROTOCOL_KW simpleprotocolname parameterdecllist roledecllist +-> + ^(GLOBALPROTOCOLHEADER simpleprotocolname parameterdecllist roledecllist) + +// TODO: parameterdecllist and annot (cf. Assrt) +| + GLOBAL_KW PROTOCOL_KW simpleprotocolname roledecllist '@' EXTIDENTIFIER +-> + ^(PARAM_GLOBALPROTOCOLHEADER simpleprotocolname ^(PARAMETERDECLLIST) roledecllist EXTIDENTIFIER) +; + +roledecllist: + '(' roledecl (',' roledecl)* ')' +-> + ^(ROLEDECLLIST roledecl+) +; + +roledecl: + ROLE_KW rolename +-> + ^(ROLEDECL rolename) + +/*| + ROLE_KW rolename '(' simplename (',' simplename)* ')' +-> + ^(PARAM_ROLEDECL rolename simplename+)*/ +; + +parameterdecllist: + '<' parameterdecl (',' parameterdecl)* '>' +-> + ^(PARAMETERDECLLIST parameterdecl+) +; + +parameterdecl: + TYPE_KW parametername +-> + ^(PARAMETERDECL KIND_PAYLOADTYPE parametername) +| + SIG_KW parametername +-> + ^(PARAMETERDECL KIND_MESSAGESIGNATURE parametername) +; + + +/** + * Section 3.7.1 Global Protocol Definitions + */ +globalprotocoldefinition: + globalprotocolblock +-> + ^(GLOBALPROTOCOLDEF globalprotocolblock) +; + + +/** + * Section 3.7.3 Global Interaction Sequences and Blocks + */ +globalprotocolblock: + '{' globalinteractionsequence '}' +-> + ^(GLOBALPROTOCOLBLOCK globalinteractionsequence) +/*| + '(' connectdecl ')' '{' globalinteractionsequence '}' +-> + ^(GLOBALPROTOCOLBLOCK globalinteractionsequence connectdecl)*/ +; + +globalinteractionsequence: + globalinteraction* +-> + ^(GLOBALINTERACTIONSEQUENCE globalinteraction*) +; + +globalinteraction: + globalmessagetransfer +| + globalchoice +| + globalrecursion +| + globalcontinue +| + globaldo +| + globalconnect +| + globaldisconnect +| + globalwrap + +/*| + globalmultichoices +| + globalmultichoicetransfer*/ +| + globalforeach +; +/*| + globalparallel +| + globalinterruptible*/ + + + +/** + * Section 3.7.4 Global Message Transfer + */ +globalmessagetransfer: + message FROM_KW rolename TO_KW rolename (',' rolename )* ';' +-> + ^(GLOBALMESSAGETRANSFER message rolename rolename+) + +| + message FROM_KW rolename paramindexinterval TO_KW rolename paramindexinterval ';' +-> + ^(PARAM_GLOBALCROSSMESSAGETRANSFER message rolename rolename paramindexinterval paramindexinterval) +/*| + message DOT_KW rolename '[' paramindexexpr '..' paramindexexpr ']' TO_KW rolename '[' paramindexexpr '..' paramindexexpr ']' ';' +-> + ^(PARAM_GLOBALDOTMESSAGETRANSFER message rolename rolename paramindexexpr paramindexexpr paramindexexpr paramindexexpr)*/ +; + +// TODO: syntactically allow mix of indexed and non-indexed roles +paramindexinterval: + ('[' paramindexexpr? ',' paramindexexpr ']')=> '[' paramindexexpr? ',' paramindexexpr ']' +-> + ^(PARAM_INDEXINTERVAL paramindexexpr paramindexexpr) +| + '[' paramindexexpr ']' +-> + ^(PARAM_INDEXINTERVAL paramindexexpr paramindexexpr) +; + +/*rpindex: + rpsingletonindex +| + rpinterval +; + +rpsingletonindex: + '[' paramindexexpr ']' +-> + ... +; + +rpinterval: + '[' paramindexexpr ',' paramindexexpr ']' +-> + ... +;*/ + + +paramindexexpr: + unaryparamindexexpr (op=('+' | '-' | '*') unaryparamindexexpr)? +-> + ^(PARAM_BININDEXEXPR unaryparamindexexpr $op? unaryparamindexexpr?) +; +// FIXME: rename BIN constant + +unaryparamindexexpr: + simplename +| + '(' simplename ',' simplename ')' +-> + ^(PARAM_PAIR simplename simplename) +| + '(' paramindexexpr ')' +-> + paramindexexpr +; + +message: + messagesignature +| + ambiguousname // FIXME: qualified name +/*| + messagesignaturename // qualified messagesignaturename subsumes parametername case +| + parametername*/ +; + +globalconnect: + //message CONNECT_KW rolename TO_KW rolename + CONNECT_KW rolename TO_KW rolename ';' +-> + ^(GLOBALCONNECT rolename rolename ^(MESSAGESIGNATURE EMPTY_OPERATOR ^(PAYLOAD))) // Empty message sig duplicated from messagesignature +| + message CONNECT_KW rolename TO_KW rolename ';' +-> + ^(GLOBALCONNECT rolename rolename message) +; +/* '(' connectdecl (',' connectdecl)* ')' +-> + ^(CONNECTDECLLIST connectdecl+) +;* / + '(' connectdecl ')' +*/ + +/*connectdecl: + CONNECT_KW rolename '->>' rolename +-> + ^(CONNECTDECL rolename rolename) +;*/ + +globaldisconnect: + DISCONNECT_KW rolename AND_KW rolename ';' +-> + ^(GLOBALDISCONNECT rolename rolename ) +; + +globalwrap: + //message CONNECT_KW rolename TO_KW rolename + WRAP_KW rolename TO_KW rolename ';' +-> + ^(GLOBALWRAP rolename rolename) +; + + +/** + * Section 3.7.5 Global Choice + */ +globalchoice: + CHOICE_KW AT_KW rolename globalprotocolblock (OR_KW globalprotocolblock)* +-> + ^(GLOBALCHOICE rolename globalprotocolblock+) +| + CHOICE_KW AT_KW rolename '[' paramindexexpr ']' globalprotocolblock (OR_KW globalprotocolblock)* +-> + ^(PARAM_GLOBALCHOICE rolename paramindexexpr globalprotocolblock+) +; + + +/*globalmultichoices: + CHOICES_KW AT_KW rolename '[' simplename ':' paramindexexpr '..' paramindexexpr ']' globalprotocolblock (OR_KW globalprotocolblock)* +-> + ^(PARAM_GLOBALMULTICHOICES rolename simplename paramindexexpr paramindexexpr globalprotocolblock+) +; + +globalmultichoicetransfer: + message FROM_KW rolename '[' simplename ']' TO_KW rolename '[' paramindexexpr '..' paramindexexpr ']' ';' +-> + ^(PARAM_GLOBALMULTICHOICESTRANSFER message rolename rolename simplename paramindexexpr paramindexexpr) +;*/ + + + +/** + * Section 3.7.6 Global Recursion + */ +globalrecursion: + REC_KW recursionvarname globalprotocolblock +-> + ^(GLOBALRECURSION recursionvarname globalprotocolblock) +; + +globalcontinue: + CONTINUE_KW recursionvarname ';' +-> + ^(GLOBALCONTINUE recursionvarname) +; + + +/* + * Section 3.7.7 Global Parallel + * / +globalparallel: + PAR_KW globalprotocolblock (AND_KW globalprotocolblock)* +-> + ^(GLOBALPARALLEL globalprotocolblock+) +;*/ + + +/* + * Section 3.7.8 Global Interruptible + * / +globalinterruptible: + INTERRUPTIBLE_KW globalprotocolblock WITH_KW '{' globalinterrupt* '}' +-> + ^(GLOBALINTERRUPTIBLE EMPTY_SCOPENAME globalprotocolblock globalinterrupt*) +| + INTERRUPTIBLE_KW scopename globalprotocolblock WITH_KW '{' (globalinterrupt)* '}' +-> + ^(GLOBALINTERRUPTIBLE scopename globalprotocolblock globalinterrupt*) +; + +globalinterrupt: + message (',' message)* BY_KW rolename ';' +-> + ^(GLOBALINTERRUPT rolename message+) +;*/ + + +/** + * Section 3.7.9 Global Do + */ +globaldo: + DO_KW protocolname roleinstantiationlist ';' +-> + ^(GLOBALDO protocolname ^(ARGUMENTINSTANTIATIONLIST) roleinstantiationlist) +| + DO_KW protocolname argumentinstantiationlist roleinstantiationlist ';' +-> + ^(GLOBALDO protocolname argumentinstantiationlist roleinstantiationlist) +; + +roleinstantiationlist: + '(' roleinstantiation (',' roleinstantiation)* ')' +-> + ^(ROLEINSTANTIATIONLIST roleinstantiation+) +; + +roleinstantiation: + rolename +-> + ^(ROLEINSTANTIATION rolename) // FIXME: not consistent with arginstas/payloadeles +; + +argumentinstantiationlist: + '<' argumentinstantiation (',' argumentinstantiation)* '>' +-> + ^(ARGUMENTINSTANTIATIONLIST argumentinstantiation+) +; + +// Like PayloadElement, simple names need disambiguation +argumentinstantiation: + //message + // Grammatically same as message, but argument case can also be a payload type + messagesignature +/*| + ambiguousname // As for payloadelement: parser doesn't distinguish simple from qualified properly, even with backtrack*/ +| + qualifiedname +; + + + +globalforeach: + PARAM_FOREACH_KW paramforeachinterval (',' paramforeachinterval)* globalprotocolblock // TODO: generalise +-> + ^(PARAM_GLOBALFOREACH globalprotocolblock paramforeachinterval+) +; + +// Cf. paramindexinterval +paramforeachinterval: + rolename '[' simplename ':' paramindexexpr? ',' paramindexexpr ']' +-> + ^(PARAM_FOREACHINTERVAL rolename simplename paramindexexpr paramindexexpr) +; + + + + +/* + * Section 3.8 Local Protocol Declarations + * / +localprotocoldecl: + localprotocolheader localprotocoldefinition +-> + ^(LOCALPROTOCOLDECL localprotocolheader localprotocoldefinition) +; + +localprotocolheader: + LOCAL_KW PROTOCOL_KW simpleprotocolname localroledecllist +-> + //simpleprotocolname EMPTY_PARAMETERDECLLIST localroledecllist + simpleprotocolname ^(PARAMETERDECLLIST) localroledecllist +| + LOCAL_KW PROTOCOL_KW simpleprotocolname parameterdecllist localroledecllist +-> + simpleprotocolname parameterdecllist localroledecllist +; + +localroledecllist: + '(' localroledecl (',' localroledecl)* ')' +-> + ^(LOCALROLEDECLLIST localroledecl+) +; + +localroledecl: + roledecl +| + SELF_KW rolename +-> + ^(SELFDECL rolename) +; + + +/** + * Section 3.8.1 Local Protocol Definitions + * / +localprotocoldefinition: + localprotocolblock +-> + ^(LOCALPROTOCOLDEF localprotocolblock) +; + + +/** + * Section 3.8.3 Local Interaction Blocks and Sequences + * / +localprotocolblock: + '{' localinteractionsequence '}' +-> + ^(LOCALPROTOCOLBLOCK localinteractionsequence) +; + +localinteractionsequence: + (localinteraction)* +-> + ^(LOCALINTERACTIONSEQUENCE localinteraction*) +; + +localinteraction: + localsend +| + localreceive +| + localchoice +| + localparallel +| + localrecursion +| + localcontinue +| + localinterruptible +| + localdo +; + + +/** + * Section 3.8.4 Local Send and Receive + * / +localsend: + message TO_KW rolename (',' rolename)* ';' +-> + ^(LOCALSEND message rolename+) +; + +localreceive: + message FROM_KW IDENTIFIER ';' +-> + ^(LOCALRECEIVE message IDENTIFIER) +; + + +/** + * Section 3.8.5 Local Choice + * / +localchoice: + CHOICE_KW AT_KW rolename localprotocolblock (OR_KW localprotocolblock)* +-> + ^(LOCALCHOICE rolename localprotocolblock+) +; + + +/** + * Section 3.8.6 Local Recursion + * / +localrecursion: + REC_KW recursionvarname localprotocolblock +-> + ^(LOCALRECURSION recursionvarname localprotocolblock) +; + +localcontinue: + CONTINUE_KW recursionvarname ';' +-> + ^(LOCALCONTINUE recursionvarname) +; + + +/** + * Section 3.8.7 Local Parallel + * / +localparallel: + PAR_KW localprotocolblock (AND_KW localprotocolblock)* +-> + ^(LOCALPARALLEL localprotocolblock+) +; + + +/** + * Section 3.8.8 Local Interruptible + * / +localinterruptible: + INTERRUPTIBLE_KW scopename localprotocolblock WITH_KW '{' localcatches* '}' +-> + ^(LOCALINTERRUPTIBLE scopename localprotocolblock EMPTY_LOCALTHROW localcatches*) +| + INTERRUPTIBLE_KW scopename localprotocolblock WITH_KW '{' localthrows localcatches* '}' +-> + ^(LOCALINTERRUPTIBLE scopename localprotocolblock localthrows localcatches*) +; + +/*localthrowandorcatch: + localthrow (localcatch)* +| + (localcatch)+ +;* / + +localthrows: + THROWS_KW message (',' message)* TO_KW rolename (',' rolename)* ';' +-> + ^(LOCALTHROWS rolename+ TO_KW message+) +; + +localcatches: + CATCHES_KW message (',' message)* FROM_KW rolename ';' +-> + ^(LOCALCATCHES rolename message+) +; + + +/** + * Section 3.8.9 Local Do + * / +localdo: + DO_KW protocolname roleinstantiationlist ';' +-> + //^(LOCALDO NO_SCOPE protocolname EMPTY_ARGUMENTINSTANTIATIONLIST roleinstantiationlist) + ^(LOCALDO NO_SCOPE protocolname ^(ARGUMENTINSTANTIATIONLIST) roleinstantiationlist) +| + DO_KW protocolname argumentinstantiationlist roleinstantiationlist ';' +-> + ^(LOCALDO NO_SCOPE protocolname argumentinstantiationlist roleinstantiationlist) +| + DO_KW scopename ':' protocolname roleinstantiationlist ';' +-> + //^(LOCALDO scopename protocolname EMPTY_ARGUMENTINSTANTIATIONLIST roleinstantiationlist) + ^(LOCALDO scopename protocolname ^(ARGUMENTINSTANTIATIONLIST) roleinstantiationlist) +| + DO_KW scopename ':' protocolname argumentinstantiationlist roleinstantiationlist ';' +-> + ^(LOCALDO scopename protocolname argumentinstantiationlist roleinstantiationlist) +; +*/ diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/RPAstFactory.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPAstFactory.java new file mode 100644 index 000000000..8da40599d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPAstFactory.java @@ -0,0 +1,61 @@ +package org.scribble.ext.go.ast; + +import java.util.List; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.MessageNode; +import org.scribble.ast.NonRoleParamDeclList; +import org.scribble.ast.RoleDeclList; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.name.qualified.GProtocolNameNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.global.RPGChoice; +import org.scribble.ext.go.ast.global.RPGCrossMessageTransfer; +import org.scribble.ext.go.ast.global.RPGDelegationElem; +import org.scribble.ext.go.ast.global.RPGDotMessageTransfer; +import org.scribble.ext.go.ast.global.RPGForeach; +import org.scribble.ext.go.ast.global.RPGMultiChoices; +import org.scribble.ext.go.ast.global.RPGMultiChoicesTransfer; +import org.scribble.ext.go.ast.global.RPGProtocolHeader; +import org.scribble.ext.go.ast.name.simple.RPIndexedRoleNode; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexVar; + + +public interface RPAstFactory extends AstFactory +{ + ////ParamRoleDecl ParamRoleDecl(CommonTree source, RoleNode namenode, List params); + //RPRoleDecl ParamRoleDecl(CommonTree source, RoleNode namenode, List params); + + RPGCrossMessageTransfer ParamGCrossMessageTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd); + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd); + RPGDotMessageTransfer ParamGDotMessageTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd); + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd); + RPGChoice ParamGChoice(CommonTree source, RoleNode subj, RPIndexExpr expr, List blocks); + RPGForeach RPGForeach(CommonTree source, List subjs, + List params, List starts, List ends, GProtocolBlock block); + RPIndexedRoleNode RPIndexedRoleNode(CommonTree source, String identifier, RPIndexExpr start, RPIndexExpr end); + + @Deprecated + RPGMultiChoices ParamGMultiChoices(CommonTree source, RoleNode subj, RPIndexVar var, + RPIndexExpr start, RPIndexExpr end, List blocks); + @Deprecated + RPGMultiChoicesTransfer ParamGMultiChoicesTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + RPIndexVar var, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd); + + + // param-core -- RPCoreAstFactory is for core subset, "full" AST (Antlr) stuff still here + + //RPCoreDelegDecl ParamCoreDelegDecl(CommonTree source, String schema, String extName, String extSource, DataTypeNode name); + + RPGDelegationElem RPGDelegationElem(CommonTree source, GProtocolNameNode root, GProtocolNameNode state, RoleNode role); + //RPLDelegationElem RPLDelegationElem(CommonTree source, LProtocolNameNode proto); // Delegation currently supported only by core, and just uses RPCoreGDelegationType + + //RPGProtocolDecl RPGProtocolDecl(CommonTree source, List modifiers, GProtocolHeader header, GProtocolDef def, String annot); + + RPGProtocolHeader RPGProtocolHeader(CommonTree source, GProtocolNameNode name, RoleDeclList roledecls, NonRoleParamDeclList paramdecls, String annot); +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/RPAstFactoryImpl.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPAstFactoryImpl.java new file mode 100644 index 000000000..d67ccb76d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPAstFactoryImpl.java @@ -0,0 +1,253 @@ +package org.scribble.ext.go.ast; + +import java.util.List; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactoryImpl; +import org.scribble.ast.MessageNode; +import org.scribble.ast.NonRoleParamDeclList; +import org.scribble.ast.RoleDeclList; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.name.qualified.GProtocolNameNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.global.RPGChoice; +import org.scribble.ext.go.ast.global.RPGCrossMessageTransfer; +import org.scribble.ext.go.ast.global.RPGDelegationElem; +import org.scribble.ext.go.ast.global.RPGDotMessageTransfer; +import org.scribble.ext.go.ast.global.RPGForeach; +import org.scribble.ext.go.ast.global.RPGMultiChoices; +import org.scribble.ext.go.ast.global.RPGMultiChoicesTransfer; +import org.scribble.ext.go.ast.global.RPGProtocolHeader; +import org.scribble.ext.go.ast.name.simple.RPIndexedRoleNode; +import org.scribble.ext.go.del.global.RPGChoiceDel; +import org.scribble.ext.go.del.global.RPGDelegationElemDel; +import org.scribble.ext.go.del.global.RPGForeachDel; +import org.scribble.ext.go.del.global.RPGMessageTransferDel; +import org.scribble.ext.go.del.global.RPGMultiChoicesDel; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexVar; + + +public class RPAstFactoryImpl extends AstFactoryImpl implements RPAstFactory +{ + + + // Instantiating existing node classes with new dels + + /*@Override + public GProtocolDecl GProtocolDecl(CommonTree source, List mods, GProtocolHeader header, GProtocolDef def) + { + GProtocolDecl gpd = new GProtocolDecl(source, mods, header, def); + gpd = del(gpd, new AssrtGProtocolDeclDel()); + return gpd; + }*/ + + + // Returning new node classes in place of existing -- FIXME: do for GMessageTransfer and GChoice + + /*@Override + public RPRoleDecl RoleDecl(CommonTree source, RoleNode namenode) + { + RPRoleDecl rd = new RPRoleDecl(source, namenode); + rd = del(rd, new RoleDeclDel()); + return rd; + }*/ + + + // Explicitly creating new Assrt nodes + + /*@Override + //public ParamRoleDecl ParamRoleDecl(CommonTree source, RoleNode namenode, List params) + public RPRoleDecl ParamRoleDecl(CommonTree source, RoleNode namenode, List params) + { + RPRoleDecl rd = new RPRoleDecl(source, namenode, params); + rd = del(rd, new RoleDeclDel()); + return rd; + }*/ + + @Override + public RPGCrossMessageTransfer ParamGCrossMessageTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd) + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + RPGCrossMessageTransfer mt = new RPGCrossMessageTransfer(source, src, msg, dest, + srcRangeStart, srcRangeEnd, destRangeStart, destRangeEnd); + mt = del(mt, new RPGMessageTransferDel()); // FIXME: parameterised self connection check + return mt; + } + + // FIXME: deprecate -- pipe/pair instead + @Override + public RPGDotMessageTransfer ParamGDotMessageTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd) + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + RPGDotMessageTransfer mt = new RPGDotMessageTransfer(source, src, msg, dest, + srcRangeStart, srcRangeEnd, destRangeStart, destRangeEnd); + mt = del(mt, new RPGMessageTransferDel()); // FIXME: parameterised self connection check + return mt; + } + + @Override + public RPGChoice ParamGChoice(CommonTree source, RoleNode subj, RPIndexExpr expr, List blocks) + { + RPGChoice gc = new RPGChoice(source, subj, expr, blocks); + gc = del(gc, new RPGChoiceDel()); + return gc; + } + + @Override + public RPGForeach RPGForeach(CommonTree source, List subjs, + List params, List starts, List ends, GProtocolBlock block) + { + RPGForeach gf = new RPGForeach(source, subjs, params, starts, ends, block); + gf = del(gf, new RPGForeachDel()); + return gf; + } + + @Override + public RPIndexedRoleNode RPIndexedRoleNode(CommonTree source, String identifier, RPIndexExpr start, RPIndexExpr end) + { + RPIndexedRoleNode irn = new RPIndexedRoleNode(source, identifier, start, end); + irn = del(irn, createDefaultDelegate()); + return irn; + } + + // FIXME: deprecate -- explicit foreach instead + @Override + public RPGMultiChoices ParamGMultiChoices(CommonTree source, RoleNode subj, RPIndexVar var, + RPIndexExpr start, RPIndexExpr end, List blocks) + { + RPGMultiChoices gc = new RPGMultiChoices(source, subj, var, start, end, blocks); + gc = del(gc, new RPGMultiChoicesDel()); + return gc; + } + + // FIXME: deprecate -- explicit foreach instead + @Override + public RPGMultiChoicesTransfer ParamGMultiChoicesTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + RPIndexVar var, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + RPGMultiChoicesTransfer mt = new RPGMultiChoicesTransfer(source, src, msg, dest, + var, destRangeStart, destRangeEnd); + mt = del(mt, new RPGMessageTransferDel()); // FIXME: not a ParamGMessageTransfer + return mt; + } + + /*@Override + public NameNode SimpleNameNode(CommonTree source, K kind, String identifier) + { + NameNode snn = null; + + // Default del's + if (kind.equals(ParamRoleParamKind.KIND)) + { + snn = new ParamRoleParamNode(source, identifier); + return castNameNode(kind, del(snn, createDefaultDelegate())); + } + else + { + return super.SimpleNameNode(source, kind, identifier); + } + }*/ + + @Override + public RPGProtocolHeader RPGProtocolHeader(CommonTree source, GProtocolNameNode name, RoleDeclList roledecls, NonRoleParamDeclList paramdecls, String annot) + { + RPGProtocolHeader gph = new RPGProtocolHeader(source, name, roledecls, paramdecls, annot); + gph = del(gph, createDefaultDelegate()); + return gph; + } + + + + // param-core + + // Explicitly creating new Assrt nodes + + /*public RPCoreDelegDecl ParamCoreDelegDecl(CommonTree source, String schema, String extName, String extSource, DataTypeNode name) + { + RPCoreDelegDecl dtd = new RPCoreDelegDecl(source, schema, extName, extSource, name); + dtd = del(dtd, createDefaultDelegate()); + return dtd; + }*/ + + @Override + public RPGDelegationElem RPGDelegationElem(CommonTree source, GProtocolNameNode root, GProtocolNameNode state, RoleNode role) + { + RPGDelegationElem de = new RPGDelegationElem(source, root, state, role); + de = del(de, new RPGDelegationElemDel()); + return de; + } + + /*@Override + public RPCoreLDelegationElem RPCoreLDelegationElem(CommonTree source, LProtocolNameNode proto) + { + RPCoreLDelegationElem de = new RPCoreLDelegationElem(source, proto); + de = del(de, createDefaultDelegate()); + return de; + }*/ + + + + + + + @Override + protected RPDel createDefaultDelegate() + { + return new RPDefaultDel(); + } + + + + // Extra parsing checks + + /*@Override + public RoleDecl RoleDecl(CommonTree source, RoleNode namenode) + { + // Check here? Or in API gen -- cf. RPIndexFactory#ParamIntVar + char c = namenode.toString().charAt(0); + if (c < 'A' || c > 'Z') + { + throw new RuntimeException("[param] Role names must start uppercase for Go accessibility: " + namenode); + // FIXME: return proper parsing error -- refactor as param API gen errors + } + return super.RoleDecl(source, namenode); + } + + @Override + public NameNode SimpleNameNode(CommonTree source, K kind, String identifier) + { + // Check here? Or in API gen + if (kind.equals(OpKind.KIND)) + { + char c; + if (identifier.length() == 0 + || ((c = identifier.charAt(0))) < 'A' || c > 'Z') + { + throw new RuntimeException("[param] Op names must start uppercase for Go accessibility: " + identifier); + // FIXME: return proper parsing error -- refactor as param API gen errors + } + } + return super.SimpleNameNode(source, kind, identifier); + } + + @Override + public QualifiedNameNode QualifiedNameNode(CommonTree source, K kind, String... elems) + { + // Check here? Or in API gen + if (kind.equals(SigKind.KIND)) + { + char c; + if (elems[elems.length-1].length() == 0 + || ((c = elems[elems.length-1].charAt(0))) < 'A' || c > 'Z') + { + throw new RuntimeException("[param] Op names must start uppercase for Go accessibility: " + elems[elems.length-1]); + // FIXME: return proper parsing error -- refactor as param API gen errors + } + } + return super.QualifiedNameNode(source, kind, elems); + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDefaultDel.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDefaultDel.java new file mode 100644 index 000000000..daae7be2d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDefaultDel.java @@ -0,0 +1,10 @@ +package org.scribble.ext.go.ast; + +// Cf. DefaultDel +public class RPDefaultDel extends RPDelBase +{ + public RPDefaultDel() + { + + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDel.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDel.java new file mode 100644 index 000000000..88292a85c --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDel.java @@ -0,0 +1,20 @@ +package org.scribble.ext.go.ast; + +import org.scribble.ast.ScribNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.core.visit.RPCoreIndexVarCollector; +import org.scribble.main.ScribbleException; + +public interface RPDel extends ScribDel +{ + + default void enterIndexVarCollection(ScribNode parent, ScribNode child, RPCoreIndexVarCollector coll) + { + + } + + default ScribNode leaveIndexVarCollection(ScribNode parent, ScribNode child, RPCoreIndexVarCollector coll, ScribNode visited) throws ScribbleException + { + return visited; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDelBase.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDelBase.java new file mode 100644 index 000000000..e43ff20a8 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPDelBase.java @@ -0,0 +1,54 @@ +package org.scribble.ext.go.ast; + +import org.scribble.ast.ScribNode; +import org.scribble.del.ScribDel; +import org.scribble.visit.EnvVisitor; +import org.scribble.visit.env.Env; + +// Mutable for pass-specific Envs (by visitors) +// Only used by RPDefaultDel? -- concrete RPDel's should extend base Dels and implement RPDel i/face +public abstract class RPDelBase implements RPDel +{ + private Env env; + + public RPDelBase() + { + + } + + @Override + public Env env() + { + return this.env; + } + + // "setEnv" rather than "env" as a non-defensive setter (cf. ModelNodeBase#del) + @Override + //protected void setEnv(Env env) + public void setEnv(Env env) + { + this.env = env; + } + + public static > void pushVisitorEnv(ScribDel del, EnvVisitor ev) + { + T env = castEnv(ev, ev.peekEnv().enterContext()); // By default: copy + ev.pushEnv(env); + } + + public static , T2 extends ScribNode> + T2 popAndSetVisitorEnv(ScribDel del, EnvVisitor ev, T2 visited) + { + // No merge here: merging of child contexts into parent context is handled "manually" for each pass and (compound) interaction node as needed (e.g. WF-choice and reachability) + T1 env = ev.popEnv(); + ((RPDelBase) del).setEnv(env); + return visited; + } + + private static > T castEnv(EnvVisitor ev, Env env) + { + @SuppressWarnings("unchecked") + T tmp = (T) env; + return tmp; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/RPForeach.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPForeach.java new file mode 100644 index 000000000..0476787d8 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPForeach.java @@ -0,0 +1,64 @@ +package org.scribble.ext.go.ast; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.CompoundInteractionNode; +import org.scribble.ast.ProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.ProtocolKind; +import org.scribble.visit.AstVisitor; + +public abstract class RPForeach extends CompoundInteractionNode +{ + public final List subjs; + public final List params; + public final List starts; + public final List ends; + public final ProtocolBlock block; + + // Pre: subjs/params/starts/ends same length -- FIXME: factor out? + protected RPForeach(CommonTree source, List subjs, + List params, List starts, List ends, + ProtocolBlock block) + { + super(source); + this.subjs = Collections.unmodifiableList(subjs); + this.params = Collections.unmodifiableList(params); + this.starts = Collections.unmodifiableList(starts); + this.ends = Collections.unmodifiableList(ends); + this.block = block; + } + + public abstract RPForeach reconstruct(List subjs, + List params, List starts, List ends, ProtocolBlock block); + + @Override + public abstract RPForeach clone(AstFactory af); + + @Override + public RPForeach visitChildren(AstVisitor nv) throws ScribbleException + { + List subjs = visitChildListWithClassEqualityCheck(this, this.subjs, nv); + ProtocolBlock block = visitChildWithClassEqualityCheck(this, this.block, nv); + return reconstruct(subjs, this.params, this.starts, this.ends, block); + } + + public abstract ProtocolBlock getBlock(); + + @Override + public String toString() + { + return "foreach " + IntStream.of(0, this.subjs.size()-1).mapToObj(i -> + this.subjs.get(i) + "[" + this.params.get(i) + ":" + this.starts.get(i) + "," + this.ends.get(i) + "]" + ).collect(Collectors.joining(", ")) + + this.block; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/RPRoleDecl.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPRoleDecl.java new file mode 100644 index 000000000..54f75ad4e --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/RPRoleDecl.java @@ -0,0 +1,83 @@ +package org.scribble.ext.go.ast; + +import java.util.Collections; +import java.util.List; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.RoleDecl; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ast.name.simple.SimpleNameNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.RoleKind; +import org.scribble.type.name.Role; +import org.scribble.visit.AstVisitor; + +// FIXME: deprecate -- not done yet due to statetype and statetype2 API gen packages +public class RPRoleDecl extends RoleDecl +{ + //public final List params; + public final List params; + + public RPRoleDecl(CommonTree source, RoleNode name) + { + this(source, name, Collections.emptyList()); + } + + //public ParamRoleDecl(CommonTree source, RoleNode name, List params) + public RPRoleDecl(CommonTree source, RoleNode name, List params) // Separating params from base RoleNode better for subprotos? + { + super(source, name); + this.params = Collections.unmodifiableList(params); + } + + @Override + protected RPRoleDecl copy() + { + return new RPRoleDecl(this.source, (RoleNode) this.name, this.params); + } + + @Override + public RPRoleDecl clone(AstFactory af) + { + /*RoleNode role = (RoleNode) this.name.clone(af); + //List params = ScribUtil.cloneList(af, this.params); + List params = this.params; + return ((RPAstFactory) af).ParamRoleDecl(this.source, role, params);*/ + return null; + } + + @Override + public RPRoleDecl project(AstFactory af, Role self) + { + /*RoleDecl proj = super.project(af, self); + return reconstruct((SimpleNameNode) proj.name, this.params); // FIXME: */ + throw new RuntimeException("[param] TODO: " + this); // Not just project, but most passes after parsing + } + + @Override + public RPRoleDecl reconstruct(SimpleNameNode name) + { + throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + + //public ParamRoleDecl reconstruct(SimpleNameNode name, List params) + public RPRoleDecl reconstruct(SimpleNameNode name, List params) + { + ScribDel del = del(); + RPRoleDecl rd = new RPRoleDecl(this.source, (RoleNode) name, params); + rd = (RPRoleDecl) rd.del(del); + return rd; + } + + @Override + public RPRoleDecl visitChildren(AstVisitor nv) throws ScribbleException + { + RoleNode name = visitChildWithClassEqualityCheck(this, (RoleNode) this.name, nv); + //List params = visitChildListWithClassEqualityCheck(this, this.params, nv); + List params = this.params; + return reconstruct(name, params); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGChoice.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGChoice.java new file mode 100644 index 000000000..c93d0e741 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGChoice.java @@ -0,0 +1,86 @@ +package org.scribble.ext.go.ast.global; + +import java.util.List; +import java.util.stream.Collectors; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.Constants; +import org.scribble.ast.ProtocolBlock; +import org.scribble.ast.ScribNodeBase; +import org.scribble.ast.global.GChoice; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.local.LChoice; +import org.scribble.ast.local.LProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; +import org.scribble.util.ScribUtil; +import org.scribble.visit.AstVisitor; + +public class RPGChoice extends GChoice +{ + public final RPIndexExpr expr; + + public RPGChoice(CommonTree source, RoleNode subj, RPIndexExpr expr, List blocks) + { + super(source, subj, blocks); + this.expr = expr; + } + + // Similar pattern to reconstruct + // Idea is, if extending the AST class (more fields), then reconstruct/project should also be extended (and called from extended del) + public LChoice project(AstFactory af, Role self, List blocks) + { + throw new RuntimeException("[param] TODO: " + this); // Not just project, but most passes after parsing + } + + @Override + protected ScribNodeBase copy() + { + return new RPGChoice(this.source, this.subj, this.expr, getBlocks()); + } + + @Override + public RPGChoice clone(AstFactory af) + { + RoleNode subj = this.subj.clone(af); + List blocks = ScribUtil.cloneList(af, getBlocks()); + return ((RPAstFactory) af).ParamGChoice(this.source, subj, this.expr, blocks); + } + + @Override + public RPGChoice reconstruct(RoleNode subj, List> blocks) + { + throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + + public RPGChoice reconstruct(RoleNode subj, RPIndexExpr expr, List> blocks) + { + ScribDel del = del(); + RPGChoice gc = new RPGChoice(this.source, subj, expr, castBlocks(blocks)); + gc = (RPGChoice) gc.del(del); + return gc; + } + + @Override + public RPGChoice visitChildren(AstVisitor nv) throws ScribbleException + { + RoleNode subj = (RoleNode) visitChild(this.subj, nv); + List blocks = visitChildListWithClassEqualityCheck(this, getBlocks(), nv); + return reconstruct(subj, this.expr, blocks); + } + + @Override + public String toString() + { + String sep = " " + Constants.OR_KW + " "; + return Constants.CHOICE_KW + " " + Constants.AT_KW + " " + this.subj + + "[" + this.expr + "]" + + " " + getBlocks().stream().map(b -> b.toString()).collect(Collectors.joining(sep)); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGCrossMessageTransfer.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGCrossMessageTransfer.java new file mode 100644 index 000000000..a7406fa36 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGCrossMessageTransfer.java @@ -0,0 +1,66 @@ +package org.scribble.ext.go.ast.global; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.Constants; +import org.scribble.ast.MessageNode; +import org.scribble.ast.local.LNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.type.name.Role; + +// FIXME: rename -- use RPIndexedRoleNode? (currently deprecated) +// Subsumes scatter/gather, src/dest range length one +public class RPGCrossMessageTransfer extends RPGMessageTransfer +{ + public RPGCrossMessageTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd) + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + super(source, src, msg, dest, srcRangeStart, srcRangeEnd, destRangeStart, destRangeEnd); + } + + @Override + public LNode project(AstFactory af, Role self) + { + //return super.project(af, self); // FIXME + throw new RuntimeException("[param] TODO: " + this); // Not just project, but most passes after parsing + } + + @Override + protected RPGCrossMessageTransfer copy() + { + return new RPGCrossMessageTransfer(this.source, this.src, this.msg, getDestinations().get(0), + this.srcRangeStart, this.srcRangeEnd, this.destRangeStart, this.destRangeEnd); + } + + @Override + public RPGCrossMessageTransfer clone(AstFactory af) + { + RoleNode src = this.src.clone(af); + MessageNode msg = this.msg.clone(af); + RoleNode dest = getDestinations().get(0).clone(af); + return ((RPAstFactory) af).ParamGCrossMessageTransfer(this.source, src, msg, dest, + this.srcRangeStart, this.srcRangeEnd, this.destRangeStart, this.destRangeEnd); + } + + @Override + public RPGCrossMessageTransfer reconstruct(RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd) + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + ScribDel del = del(); + RPGCrossMessageTransfer gmt = new RPGCrossMessageTransfer(this.source, src, msg, dest, + srcRangeStart, srcRangeEnd, destRangeStart, destRangeEnd); + gmt = (RPGCrossMessageTransfer) gmt.del(del); + return gmt; + } + + @Override + public String toString() + { + return this.msg + " " + Constants.FROM_KW + " " + rangesToString(); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGDelegationElem.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGDelegationElem.java new file mode 100644 index 000000000..cba287934 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGDelegationElem.java @@ -0,0 +1,131 @@ +/** + * Copyright 2008 The Scribble Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.scribble.ext.go.ast.global; + +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.global.GDelegationElem; +import org.scribble.ast.local.LDelegationElem; +import org.scribble.ast.name.qualified.GProtocolNameNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.core.type.name.RPCoreGDelegationType; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexFactory; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.Local; +import org.scribble.type.name.PayloadElemType; +import org.scribble.visit.AstVisitor; + +public class RPGDelegationElem extends GDelegationElem +{ + public final GProtocolNameNode state; + + // super.proto used for root + // FIXME: RoleNode (its String value) is used for *variant name* -- cf. toPayloadType, RPRoleVariant construction + public RPGDelegationElem(CommonTree source, GProtocolNameNode root, GProtocolNameNode state, RoleNode role) + { + super(source, root, role); + this.state = state; + } + + @Override + public String toString() + { + return this.proto + ":" + this.state + "@" + this.role; + } + + @Override + public LDelegationElem project(AstFactory af) + { + //return af.RPCoreLDelegationElem(this.source, Projector.makeProjectedFullNameNode(af, this.source, this.proto.toName(), this.role.toName())); + throw new RuntimeException("[rp-core] Shouldn't here: " + this); + } + + @Override + protected RPGDelegationElem copy() + { + return new RPGDelegationElem(this.source, this.proto, this.state, this.role); + } + + @Override + public RPGDelegationElem clone(AstFactory af) + { + GProtocolNameNode root = (GProtocolNameNode) this.proto.clone(af); + GProtocolNameNode state = (GProtocolNameNode) this.state.clone(af); + RoleNode role = (RoleNode) this.role.clone(af); + return ((RPAstFactory) af).RPGDelegationElem(this.source, root, state, role); + } + + @Override + public RPGDelegationElem reconstruct(GProtocolNameNode root, RoleNode role) + { + throw new RuntimeException("Shouldn't get in here: " + this); + } + + public RPGDelegationElem reconstruct(GProtocolNameNode root, GProtocolNameNode state, RoleNode role) + { + ScribDel del = del(); + RPGDelegationElem elem = new RPGDelegationElem(this.source, root, state, role); + elem = (RPGDelegationElem) elem.del(del); + return elem; + } + + @Override + public RPGDelegationElem visitChildren(AstVisitor nv) throws ScribbleException + { + GProtocolNameNode root = (GProtocolNameNode) visitChild(this.proto, nv); + GProtocolNameNode state = (GProtocolNameNode) visitChild(this.state, nv); + RoleNode role = (RoleNode) visitChild(this.role, nv); + return reconstruct(root, state, role); + } + + @Override + public PayloadElemType toPayloadType() + { + // FIXME all HACK + String tmp = this.role.toString(); + int i = tmp.indexOf("_"); // Cf. RPCoreSTApiGenerator#getEndpointKindTypeName + // Treating singleton variant as special case (although not done elsewhere, e.g., A[1,1]) + String name; + RPIndexExpr start; + RPIndexExpr end; + if (i == -1) + { + name = tmp; + start = RPIndexFactory.ParamIntVal(1); + end = RPIndexFactory.ParamIntVal(1); + } + else + { + name = tmp.substring(0, i); + int j = tmp.indexOf("t", i+1); // "to" // HACK FIXME + String s = tmp.substring(i+1, j); + String e = tmp.substring(j+2); + start = (s.charAt(0) >= '0' && s.charAt(0) <= '9') ? RPIndexFactory.ParamIntVal(Integer.parseInt(s)) : RPIndexFactory.ParamIndexVar(s); + end = (e.charAt(0) >= '0' && e.charAt(0) <= '9') ? RPIndexFactory.ParamIntVal(Integer.parseInt(e)) : RPIndexFactory.ParamIndexVar(e); + } + RPRoleVariant variant = new RPRoleVariant(name, + Stream.of(new RPInterval(start, end)).collect(Collectors.toSet()), Collections.emptySet()); + + return new RPCoreGDelegationType(this.proto.toName(), this.state.toName(), variant); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGDotMessageTransfer.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGDotMessageTransfer.java new file mode 100644 index 000000000..0478e74f2 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGDotMessageTransfer.java @@ -0,0 +1,64 @@ +package org.scribble.ext.go.ast.global; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.Constants; +import org.scribble.ast.MessageNode; +import org.scribble.ast.local.LNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.type.name.Role; + +public class RPGDotMessageTransfer extends RPGMessageTransfer +{ + public RPGDotMessageTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd) + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + super(source, src, msg, dest, srcRangeStart, srcRangeEnd, destRangeStart, destRangeEnd); + } + + @Override + public LNode project(AstFactory af, Role self) + { + //return super.project(af, self); // FIXME + throw new RuntimeException("[param] TODO: " + this); // Not just project, but most passes after parsing + } + + @Override + protected RPGDotMessageTransfer copy() + { + return new RPGDotMessageTransfer(this.source, this.src, this.msg, getDestinations().get(0), + this.srcRangeStart, this.srcRangeEnd, this.destRangeStart, this.destRangeEnd); + } + + @Override + public RPGDotMessageTransfer clone(AstFactory af) + { + RoleNode src = this.src.clone(af); + MessageNode msg = this.msg.clone(af); + RoleNode dest = getDestinations().get(0).clone(af); + return ((RPAstFactory) af).ParamGDotMessageTransfer(this.source, src, msg, dest, + this.srcRangeStart, this.srcRangeEnd, this.destRangeStart, this.destRangeEnd); + } + + @Override + public RPGDotMessageTransfer reconstruct(RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd) + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + ScribDel del = del(); + RPGDotMessageTransfer gmt = new RPGDotMessageTransfer(this.source, src, msg, dest, + srcRangeStart, srcRangeEnd, destRangeStart, destRangeEnd); + gmt = (RPGDotMessageTransfer) gmt.del(del); + return gmt; + } + + @Override + public String toString() + { + return this.msg + " " + Constants.FROM_KW + " " + rangesToString(); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGForeach.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGForeach.java new file mode 100644 index 000000000..db0667b4e --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGForeach.java @@ -0,0 +1,67 @@ +package org.scribble.ext.go.ast.global; + +import java.util.List; +import java.util.stream.Collectors; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.ProtocolBlock; +import org.scribble.ast.ScribNodeBase; +import org.scribble.ast.global.GCompoundInteractionNode; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.local.LCompoundInteractionNode; +import org.scribble.ast.local.LProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.RPForeach; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; + +public class RPGForeach extends RPForeach implements GCompoundInteractionNode +{ + public RPGForeach(CommonTree source, List subjs, + List params, List starts, List ends, + GProtocolBlock block) + { + super(source, subjs, params, starts, ends, block); + } + + @Override + public GProtocolBlock getBlock() + { + return (GProtocolBlock) this.block; + } + + // Similar pattern to reconstruct + // Idea is, if extending the AST class (more fields), then reconstruct/project should also be extended (and called from extended del) + public LCompoundInteractionNode project(AstFactory af, Role self, List blocks) + { + throw new RuntimeException("[param] TODO: " + this); // Because -rp-core only // Not just project, but most passes after parsing + } + + @Override + protected ScribNodeBase copy() + { + return new RPGForeach(this.source, this.subjs, this.params, this.starts, this.ends, getBlock()); + } + + @Override + public RPGForeach clone(AstFactory af) + { + List subjs = this.subjs.stream().map(r -> r.clone(af)).collect(Collectors.toList()); + GProtocolBlock block = getBlock().clone(af); + return ((RPAstFactory) af).RPGForeach(this.source, subjs, this.params, this.starts, this.ends, block); + } + + @Override + public RPGForeach reconstruct(List subjs, List params, List starts, List ends, ProtocolBlock block) + { + ScribDel del = del(); + RPGForeach gc = new RPGForeach(this.source, subjs, params, starts, ends, (GProtocolBlock) block); + gc = (RPGForeach) gc.del(del); + return gc; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMessageTransfer.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMessageTransfer.java new file mode 100644 index 000000000..69d253084 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMessageTransfer.java @@ -0,0 +1,68 @@ +package org.scribble.ext.go.ast.global; + +import java.util.Arrays; +import java.util.List; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.Constants; +import org.scribble.ast.MessageNode; +import org.scribble.ast.MessageTransfer; +import org.scribble.ast.global.GMessageTransfer; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.Global; +import org.scribble.visit.AstVisitor; + +public abstract class RPGMessageTransfer extends GMessageTransfer //implements ParamActionAssertNode +{ + // ParamRoleNode? -- cf. ParamRoleDecl + // All >= 0; end >= start + /*public final ParamRoleParamNode srcRangeStart; + public final ParamRoleParamNode srcRangeEnd; // Inclusive + public final ParamRoleParamNode destRangeStart; + public final ParamRoleParamNode destRangeEnd; // Inclusive*/ + public final RPIndexExpr srcRangeStart; + public final RPIndexExpr srcRangeEnd; // Inclusive + public final RPIndexExpr destRangeStart; + public final RPIndexExpr destRangeEnd; // Inclusive + + public RPGMessageTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd) + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + super(source, src, msg, Arrays.asList(dest)); + this.srcRangeStart = srcRangeStart; + this.srcRangeEnd = srcRangeEnd; + this.destRangeStart = destRangeStart; + this.destRangeEnd = destRangeEnd; + } + + @Override + public RPGMessageTransfer reconstruct(RoleNode src, MessageNode msg, List dests) + { + throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + + public abstract RPGMessageTransfer reconstruct(RoleNode src, MessageNode msg, RoleNode dest, + //ParamRoleParamNode srcRangeStart, ParamRoleParamNode srcRangeEnd, ParamRoleParamNode destRangeStart, ParamRoleParamNode destRangeEnd); + RPIndexExpr srcRangeStart, RPIndexExpr srcRangeEnd, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd); + + @Override + public MessageTransfer visitChildren(AstVisitor nv) throws ScribbleException + { + RoleNode src = (RoleNode) visitChild(this.src, nv); + MessageNode msg = (MessageNode) visitChild(this.msg, nv); + RoleNode dest = (RoleNode) visitChild(getDestinations().get(0), nv); + return reconstruct(src, msg, dest, this.srcRangeStart, this.srcRangeEnd, this.destRangeStart, this.destRangeEnd); + } + + protected String rangesToString() + { + return + this.src + "[" + this.srcRangeStart + ".." + this.srcRangeEnd + "]" + + " " + Constants.TO_KW + " " + + getDestinations().get(0) + "[" + this.destRangeStart + ".." + this.destRangeEnd + "]" + + ";"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMultiChoices.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMultiChoices.java new file mode 100644 index 000000000..45398139e --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMultiChoices.java @@ -0,0 +1,94 @@ +package org.scribble.ext.go.ast.global; + +import java.util.List; +import java.util.stream.Collectors; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.Constants; +import org.scribble.ast.ProtocolBlock; +import org.scribble.ast.ScribNodeBase; +import org.scribble.ast.global.GChoice; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.local.LChoice; +import org.scribble.ast.local.LProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; +import org.scribble.util.ScribUtil; +import org.scribble.visit.AstVisitor; + +@Deprecated +public class RPGMultiChoices extends GChoice +{ + public final RPIndexVar var; + public final RPIndexExpr start; + public final RPIndexExpr end; + + public RPGMultiChoices(CommonTree source, RoleNode subj, RPIndexVar var, + RPIndexExpr start, RPIndexExpr end, List blocks) + { + super(source, subj, blocks); + this.var = var; + this.start = start; + this.end = end; + } + + // Similar pattern to reconstruct + // Idea is, if extending the AST class (more fields), then reconstruct/project should also be extended (and called from extended del) + public LChoice project(AstFactory af, Role self, List blocks) + { + throw new RuntimeException("[param] TODO: " + this); // Not just project, but most passes after parsing + } + + @Override + protected ScribNodeBase copy() + { + return new RPGMultiChoices(this.source, this.subj, this.var, this.start, this.end, getBlocks()); + } + + @Override + public RPGMultiChoices clone(AstFactory af) + { + RoleNode subj = this.subj.clone(af); + List blocks = ScribUtil.cloneList(af, getBlocks()); + return ((RPAstFactory) af).ParamGMultiChoices(this.source, subj, this.var, this.start, this.end, blocks); + } + + @Override + public RPGMultiChoices reconstruct(RoleNode subj, List> blocks) + { + throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + + public RPGMultiChoices reconstruct(RoleNode subj, RPIndexVar var, + RPIndexExpr start, RPIndexExpr end, List> blocks) + { + ScribDel del = del(); + RPGMultiChoices gc = new RPGMultiChoices(this.source, subj, var, start, end, castBlocks(blocks)); + gc = (RPGMultiChoices) gc.del(del); + return gc; + } + + @Override + public RPGMultiChoices visitChildren(AstVisitor nv) throws ScribbleException + { + RoleNode subj = (RoleNode) visitChild(this.subj, nv); + List blocks = visitChildListWithClassEqualityCheck(this, getBlocks(), nv); + return reconstruct(subj, this.var, this.start, this.end, blocks); + } + + @Override + public String toString() + { + String sep = " " + Constants.OR_KW + " "; + return Constants.CHOICES_KW + " " + Constants.AT_KW + " " + this.subj + + "[" + this.var + ":" + this.start + ".." + this.end + "]" + + " " + getBlocks().stream().map(b -> b.toString()).collect(Collectors.joining(sep)); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMultiChoicesTransfer.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMultiChoicesTransfer.java new file mode 100644 index 000000000..fe347571b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGMultiChoicesTransfer.java @@ -0,0 +1,98 @@ +package org.scribble.ext.go.ast.global; + +import java.util.Arrays; +import java.util.List; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.Constants; +import org.scribble.ast.MessageNode; +import org.scribble.ast.MessageTransfer; +import org.scribble.ast.global.GMessageTransfer; +import org.scribble.ast.local.LNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; +import org.scribble.visit.AstVisitor; + +// Subsumes scatter/gather, src/dest range length one +@Deprecated +public class RPGMultiChoicesTransfer extends GMessageTransfer +{ + public final RPIndexVar var; + public final RPIndexExpr destRangeStart; + public final RPIndexExpr destRangeEnd; // Inclusive + + public RPGMultiChoicesTransfer(CommonTree source, RoleNode src, MessageNode msg, RoleNode dest, + RPIndexVar var, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + super(source, src, msg, Arrays.asList(dest)); + this.var = var; + this.destRangeStart = destRangeStart; + this.destRangeEnd = destRangeEnd; + } + + @Override + public LNode project(AstFactory af, Role self) + { + //return super.project(af, self); // FIXME + throw new RuntimeException("[param] TODO: " + this); // Not just project, but most passes after parsing + } + + @Override + protected RPGMultiChoicesTransfer copy() + { + return new RPGMultiChoicesTransfer(this.source, this.src, this.msg, getDestinations().get(0), + this.var, this.destRangeStart, this.destRangeEnd); + } + + @Override + public RPGMultiChoicesTransfer clone(AstFactory af) + { + RoleNode src = this.src.clone(af); + MessageNode msg = this.msg.clone(af); + RoleNode dest = getDestinations().get(0).clone(af); + return ((RPAstFactory) af).ParamGMultiChoicesTransfer(this.source, src, msg, dest, + this.var, this.destRangeStart, this.destRangeEnd); + } + + @Override + public RPGMessageTransfer reconstruct(RoleNode src, MessageNode msg, List dests) + { + throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + + public RPGMultiChoicesTransfer reconstruct(RoleNode src, MessageNode msg, RoleNode dest, + RPIndexVar var, RPIndexExpr destRangeStart, RPIndexExpr destRangeEnd) + { + ScribDel del = del(); + RPGMultiChoicesTransfer gmt = new RPGMultiChoicesTransfer(this.source, src, msg, dest, + var, destRangeStart, destRangeEnd); + gmt = (RPGMultiChoicesTransfer) gmt.del(del); + return gmt; + } + + @Override + public MessageTransfer visitChildren(AstVisitor nv) throws ScribbleException + { + RoleNode src = (RoleNode) visitChild(this.src, nv); + MessageNode msg = (MessageNode) visitChild(this.msg, nv); + RoleNode dest = (RoleNode) visitChild(getDestinations().get(0), nv); + return reconstruct(src, msg, dest, this.var, this.destRangeStart, this.destRangeEnd); + } + + @Override + public String toString() + { + return this.msg + " " + Constants.FROM_KW + " " + + this.src + "[" + this.var + "]" + + " " + Constants.TO_KW + " " + + getDestinations().get(0) + "[" + this.destRangeStart + ".." + this.destRangeEnd + "]" + + ";"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGProtocolHeader.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGProtocolHeader.java new file mode 100644 index 000000000..bf0670078 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/global/RPGProtocolHeader.java @@ -0,0 +1,91 @@ +/** + * Copyright 2008 The Scribble Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.scribble.ext.go.ast.global; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.Constants; +import org.scribble.ast.NonRoleParamDeclList; +import org.scribble.ast.RoleDeclList; +import org.scribble.ast.ScribNodeBase; +import org.scribble.ast.global.GProtocolHeader; +import org.scribble.ast.local.LProtocolHeader; +import org.scribble.ast.name.qualified.GProtocolNameNode; +import org.scribble.ast.name.qualified.LProtocolNameNode; +import org.scribble.ast.name.qualified.ProtocolNameNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; +import org.scribble.visit.AstVisitor; + +public class RPGProtocolHeader extends GProtocolHeader +{ + public final String annot; + + public RPGProtocolHeader(CommonTree source, GProtocolNameNode name, RoleDeclList roledecls, NonRoleParamDeclList paramdecls, String annot) + { + super(source, name, roledecls, paramdecls); + this.annot = annot; + } + + @Override + protected ScribNodeBase copy() + { + return new RPGProtocolHeader(this.source, getNameNode(), this.roledecls, this.paramdecls, this.annot); + } + + @Override + public RPGProtocolHeader clone(AstFactory af) + { + GProtocolNameNode name = getNameNode().clone(af); + RoleDeclList roledecls = this.roledecls.clone(af); + NonRoleParamDeclList paramdecls = this.paramdecls.clone(af); + return ((RPAstFactory) af).RPGProtocolHeader(this.source, name, roledecls, paramdecls, this.annot); + } + + @Override + public RPGProtocolHeader visitChildren(AstVisitor nv) throws ScribbleException + { + RoleDeclList rdl = (RoleDeclList) visitChild(this.roledecls, nv); + NonRoleParamDeclList pdl = (NonRoleParamDeclList) visitChild(this.paramdecls, nv); + return reconstruct((GProtocolNameNode) this.name, rdl, pdl, this.annot); + } + + @Override + public RPGProtocolHeader reconstruct(ProtocolNameNode name, RoleDeclList rdl, NonRoleParamDeclList pdl) + { + throw new RuntimeException("Shouldn't get in here: " + this); + } + + public RPGProtocolHeader reconstruct(ProtocolNameNode name, RoleDeclList rdl, NonRoleParamDeclList pdl, String annot) + { + ScribDel del = del(); + RPGProtocolHeader gph = new RPGProtocolHeader(this.source, (GProtocolNameNode) name, rdl, pdl, annot); + gph = (RPGProtocolHeader) gph.del(del); + return gph; + } + + public LProtocolHeader project(AstFactory af, Role self, LProtocolNameNode name, RoleDeclList roledecls, NonRoleParamDeclList paramdecls) + { + throw new RuntimeException("Shouldn't get in here: " + this); + } + + @Override + public String toString() + { + return Constants.GLOBAL_KW + " " + super.toString() + " @\"" + this.annot + "\""; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/ast/name/simple/RPIndexedRoleNode.java b/scribble-go/src/main/java/org/scribble/ext/go/ast/name/simple/RPIndexedRoleNode.java new file mode 100644 index 000000000..3bb19ba8a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/ast/name/simple/RPIndexedRoleNode.java @@ -0,0 +1,76 @@ +package org.scribble.ext.go.ast.name.simple; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.name.simple.SimpleNameNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.kind.RPIndexedRoleKind; +import org.scribble.ext.go.type.name.RPIndexedRole; + + +// FIXME: not currently used, but should use in, e.g., RPGCrossMessageTransfer -- use for both "actual params" and int literals +@Deprecated +public class RPIndexedRoleNode extends SimpleNameNode // Not RoleNode, for distinct Kind -- (though distinction maybe unecessary) +{ + public final RPIndexExpr start; // Use "types" directly -- source syntax parsed directly to types (cf. scrib-assrt, AssrtAntlrToFormulaParser) + public final RPIndexExpr end; + + public RPIndexedRoleNode(CommonTree source, String identifier, RPIndexExpr start, RPIndexExpr end) + { + super(source, identifier); + this.start = start; + this.end = end; + } + + @Override + protected RPIndexedRoleNode copy() + { + return new RPIndexedRoleNode(this.source, getIdentifier(), this.start, this.end); + } + + @Override + public RPIndexedRoleNode clone(AstFactory af) + { + return ((RPAstFactory) af).RPIndexedRoleNode(this.source, getIdentifier(), this.start, this.end); + } + + @Override + public RPIndexedRole toName() + { + String id = getIdentifier(); + return new RPIndexedRole(id, this.start, this.end); + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPIndexedRoleNode)) + { + return false; + } + RPIndexedRoleNode them = (RPIndexedRoleNode) o; + return super.equals(o) // Doesn canEqual + && this.start.equals(them.start) && this.end.equals(them.end); + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPIndexedRoleNode; + } + + @Override + public int hashCode() + { + int hash = 7159; + hash = 31*hash + super.hashCode(); + hash = 31*hash + this.start.hashCode(); + hash = 31*hash + this.end.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCLArgFlag.java b/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCLArgFlag.java new file mode 100644 index 000000000..7f06a0583 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCLArgFlag.java @@ -0,0 +1,7 @@ +package org.scribble.ext.go.cli; + +public enum GoCLArgFlag +{ + // Non-unique flags + GO_API_GEN, +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCLArgParser.java b/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCLArgParser.java new file mode 100644 index 000000000..71af4bd05 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCLArgParser.java @@ -0,0 +1,102 @@ +package org.scribble.ext.go.cli; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.scribble.cli.CLArgParser; +import org.scribble.cli.CommandLineException; + +public class GoCLArgParser extends CLArgParser +{ + // Non-unique flags + public static final String GO_API_GEN_FLAG = "-goapi"; + + //private static final Map PARAM_UNIQUE_FLAGS = new HashMap<>(); + + private static final Map PARAM_NON_UNIQUE_FLAGS = new HashMap<>(); + { + GoCLArgParser.PARAM_NON_UNIQUE_FLAGS.put(GoCLArgParser.GO_API_GEN_FLAG, GoCLArgFlag.GO_API_GEN); + } + + private static final Map PARAM_FLAGS = new HashMap<>(); + { + GoCLArgParser.PARAM_FLAGS.putAll(GoCLArgParser.PARAM_NON_UNIQUE_FLAGS); + } + + private final Map paramParsed = new HashMap<>(); + + public GoCLArgParser(String[] args) throws CommandLineException + { + super(args); // Assigns this.args and calls parseArgs + } + + public Map getParamArgs() throws CommandLineException + { + //super.parseArgs(); // Needed + return this.paramParsed; + } + + @Override + protected boolean isFlag(String arg) + { + return GoCLArgParser.PARAM_FLAGS.containsKey(arg) || super.isFlag(arg); + } + + // Pre: i is the index of the current flag to parse + // Post: i is the index of the last argument parsed -- parseArgs does the index increment to the next current flag + @Override + protected int parseFlag(int i) throws CommandLineException + { + String flag = this.args[i]; + switch (flag) + { + // Non-unique flags + + case GoCLArgParser.GO_API_GEN_FLAG: + { + return goParseProtoAndRoleArgs(flag, i); + } + + + // Base CL + + default: + { + return super.parseFlag(i); + } + } + } + + // FIXME: factor out with core arg parser -- issue is GoCLArgFlag is currently an unlreated type to CLArgFlag + private int goParseProtoAndRoleArgs(String f, int i) throws CommandLineException + { + GoCLArgFlag flag = GoCLArgParser.PARAM_NON_UNIQUE_FLAGS.get(f); + if ((i + 2) >= this.args.length) + { + throw new CommandLineException("Missing protocol/role arguments"); + } + String proto = this.args[++i]; + String role = this.args[++i]; + goConcatArgs(flag, proto, role); + return i; + } + + // FIXME: factor out with core arg parser -- issue is GoCLArgFlag is currently an unlreated type to CLArgFlag + private void goConcatArgs(GoCLArgFlag flag, String... toAdd) + { + String[] args = this.paramParsed.get(flag); + if (args == null) + { + args = Arrays.copyOf(toAdd, toAdd.length); + } + else + { + String[] tmp = new String[args.length + toAdd.length]; + System.arraycopy(args, 0, tmp, 0, args.length); + System.arraycopy(toAdd, 0, tmp, args.length, toAdd.length); + args = tmp; + } + this.paramParsed.put(flag, args); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCommandLine.java b/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCommandLine.java new file mode 100644 index 000000000..83fe7fce9 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/cli/GoCommandLine.java @@ -0,0 +1,114 @@ +package org.scribble.ext.go.cli; + +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.cli.CLArgFlag; +import org.scribble.cli.CommandLine; +import org.scribble.cli.CommandLineException; +import org.scribble.ext.go.codegen.statetype.go.GoEndpointApiGenerator; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoMainContext; +import org.scribble.main.AntlrSourceException; +import org.scribble.main.Job; +import org.scribble.main.JobContext; +import org.scribble.main.ScribbleException; +import org.scribble.main.resource.DirectoryResourceLocator; +import org.scribble.main.resource.ResourceLocator; +import org.scribble.model.endpoint.EGraph; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; +import org.scribble.util.ScribParserException; + +// N.B. this is the CL for both -goapi and param-core extensions +public class GoCommandLine extends CommandLine +{ + protected final Map paramArgs; // Maps each flag to list of associated argument values + + // HACK: store in (Core) Job/JobContext? + protected GProtocolDecl gpd; + protected Map> P0; + protected Map> E0; + //protected ParamCoreSModel model; + + public GoCommandLine(String... args) throws CommandLineException + { + this(new GoCLArgParser(args)); + } + + private GoCommandLine(GoCLArgParser p) throws CommandLineException + { + super(p); // calls p.parse() + if (this.args.containsKey(CLArgFlag.INLINE_MAIN_MOD)) + { + // FIXME: should be fine + throw new RuntimeException("[param] Inline modules not supported:\n" + this.args.get(CLArgFlag.INLINE_MAIN_MOD)); + } + // FIXME? Duplicated from core + if (!this.args.containsKey(CLArgFlag.MAIN_MOD)) + { + throw new CommandLineException("No main module has been specified\r\n"); + } + this.paramArgs = p.getParamArgs(); + } + + @Override + protected GoMainContext newMainContext() throws ScribParserException, ScribbleException + { + boolean debug = this.args.containsKey(CLArgFlag.VERBOSE); // TODO: factor out with CommandLine (cf. MainContext fields) + boolean useOldWF = this.args.containsKey(CLArgFlag.OLD_WF); + boolean noLiveness = this.args.containsKey(CLArgFlag.NO_LIVENESS); + boolean minEfsm = this.args.containsKey(CLArgFlag.LTSCONVERT_MIN); + boolean fair = this.args.containsKey(CLArgFlag.FAIR); + boolean noLocalChoiceSubjectCheck = this.args.containsKey(CLArgFlag.NO_LOCAL_CHOICE_SUBJECT_CHECK); + boolean noAcceptCorrelationCheck = this.args.containsKey(CLArgFlag.NO_ACCEPT_CORRELATION_CHECK); + boolean noValidation = this.args.containsKey(CLArgFlag.NO_VALIDATION); + + List impaths = this.args.containsKey(CLArgFlag.IMPORT_PATH) + ? CommandLine.parseImportPaths(this.args.get(CLArgFlag.IMPORT_PATH)[0]) + : Collections.emptyList(); + ResourceLocator locator = new DirectoryResourceLocator(impaths); + if (this.args.containsKey(CLArgFlag.INLINE_MAIN_MOD)) + { + /*return new ParamMainContext(debug, locator, this.args.get(CLArgFlag.INLINE_MAIN_MOD)[0], useOldWF, noLiveness, minEfsm, fair, + noLocalChoiceSubjectCheck, noAcceptCorrelationCheck, noValidation, solver);*/ + throw new RuntimeException("[param] Shouldn't get in here:\n" + this.args.get(CLArgFlag.INLINE_MAIN_MOD)[0]); // Checked in constructor + } + else + { + Path mainpath = CommandLine.parseMainPath(this.args.get(CLArgFlag.MAIN_MOD)[0]); + return new GoMainContext(debug, locator, mainpath, useOldWF, noLiveness, minEfsm, fair, + noLocalChoiceSubjectCheck, noAcceptCorrelationCheck, noValidation); + } + } + + public static void main(String[] args) throws CommandLineException, AntlrSourceException + { + new GoCommandLine(args).run(); + } + + @Override + protected void doNonAttemptableOutputTasks(Job job) throws ScribbleException, CommandLineException + { + if (this.paramArgs.containsKey(GoCLArgFlag.GO_API_GEN)) + { + JobContext jcontext = job.getContext(); + String[] args = this.paramArgs.get(GoCLArgFlag.GO_API_GEN); + for (int i = 0; i < args.length; i += 2) + { + GProtocolName fullname = checkGlobalProtocolArg(jcontext, args[i]); + Role role = checkRoleArg(jcontext, fullname, args[i+1]); + Map goClasses = new GoEndpointApiGenerator(job).generateGoApi(fullname, role); + outputClasses(goClasses); + } + } + else + { + super.doNonAttemptableOutputTasks(job); + } + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoEndpointApiGenerator.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoEndpointApiGenerator.java new file mode 100644 index 000000000..ebd802e3b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoEndpointApiGenerator.java @@ -0,0 +1,68 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import java.util.Map; + +import org.scribble.codegen.java.endpointapi.StateChannelApiGenerator; +import org.scribble.main.Job; +import org.scribble.main.ScribbleException; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +public class GoEndpointApiGenerator // FIXME: make base STEndpointApiGenerator +{ + public final Job job; + + public GoEndpointApiGenerator(Job job) + { + this.job = job; + } + + + public Map generateGoApi(GProtocolName fullname, Role self) throws ScribbleException + { + this.job.debugPrintln("\n[Go API gen] Running " + StateChannelApiGenerator.class + " for " + fullname + "@" + self); + GoSTStateChanApiBuilder apigen = new GoSTStateChanApiBuilder(this.job, fullname, self, this.job.getContext().getEGraph(fullname, self)); + Map api = apigen.build(); // filepath -> source + api.putAll(apigen.buildSessionAPI()); // FIXME: factor better with STStateChanAPIBuilder + return api; + } + + + /*public Map generateSessionApi(GProtocolName fullname) throws ScribbleException + { + this.job.debugPrintln("\n[Java API gen] Running " + SessionApiGenerator.class + " for " + fullname); + SessionApiGenerator sg = new SessionApiGenerator(this.job, fullname); // FIXME: reuse? + Map map = sg.generateApi(); // filepath -> class source + return map; + } + + // FIXME: refactor an EndpointApiGenerator -- ? + public Map generateStateChannelApi(GProtocolName fullname, Role self, boolean subtypes) throws ScribbleException + { + /*JobContext jc = this.job.getContext(); + if (jc.getEndpointGraph(fullname, self) == null) + { + buildGraph(fullname, self); + }* / + job.debugPrintln("\n[Java API gen] Running " + StateChannelApiGenerator.class + " for " + fullname + "@" + self); + StateChannelApiGenerator apigen = new StateChannelApiGenerator(this.job, fullname, self); + IOInterfacesGenerator iogen = null; + try + { + iogen = new IOInterfacesGenerator(apigen, subtypes); + } + catch (RuntimeScribbleException e) // FIXME: use IOInterfacesGenerator.skipIOInterfacesGeneration + { + //System.err.println("[Warning] Skipping I/O Interface generation for protocol featuring: " + fullname); + this.job.warningPrintln("Skipping I/O Interface generation for: " + fullname + "\n Cause: " + e.getMessage()); + } + // Construct the Generators first, to build all the types -- then call generate to "compile" all Builders to text (further building changes will not be output) + Map api = new HashMap<>(); // filepath -> class source // Store results? + api.putAll(apigen.generateApi()); + if (iogen != null) + { + api.putAll(iogen.generateApi()); + } + return api; + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTBranchActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTBranchActionBuilder.java new file mode 100644 index 000000000..24eb3941d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTBranchActionBuilder.java @@ -0,0 +1,64 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import java.util.stream.Collectors; + +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.codegen.statetype.STBranchActionBuilder; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class GoSTBranchActionBuilder extends STBranchActionBuilder +{ + @Override + public String build(STStateChanApiBuilder api, EState curr, EAction a) // FIXME: "overriding" GSTStateChanAPIBuilder.buildAction to hack around *interface return // FIXME: factor out + { + EState succ = curr.getSuccessor(a); + return + "func (s *" + getStateChanType(api, curr, a) + ") " + getActionName(api, a) + "(" + + buildArgs(null, a) + + ") " + getReturnType(api, curr, succ) + " {\n" // HACK: Return type is interface, so no need for *return (unlike other state chans) + + "s.state.Use()\n" + + buildBody(api, curr, a, succ) + "\n" + + "}"; + } + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return "Branch_" + a.peer; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return ""; + } + + @Override + public String getReturnType(STStateChanApiBuilder api, EState curr, EState succ) + { + return api.cb.getCaseStateChanName(api, curr); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + return + //"tmp := " + api.getChannelName(api, a) + ".Read()\n" + "tmp := s.ep.Read(s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + ")\n" + //+ "op := tmp.(" + GSTBranchStateBuilder.getBranchEnumType(api, curr) + ")\n" + + "if s.ep.Err != nil {\n" + + "return nil\n" + + "}\n" + + "op := tmp.(string)\n" + + "switch op {\n" + + curr.getActions().stream().map(x -> + //"case " + GSTBranchStateBuilder.getBranchEnumValue(x.mid) + ":\n" + "case \"" + x.mid + "\":\n" + + "return &" + GoSTCaseBuilder.getOpTypeName(api, curr, x.mid) +"{ ep: s.ep, state: &net.LinearResource {} }\n" // FIXME: factor out + ).collect(Collectors.joining("")) + + "default: panic(\"Shouldn't get in here: \" + op)\n" + + "}\n" + + "return nil"; // FIXME: panic instead + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTBranchStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTBranchStateBuilder.java new file mode 100644 index 000000000..215e5d7a5 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTBranchStateBuilder.java @@ -0,0 +1,38 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import org.scribble.codegen.statetype.STBranchStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; + +public class GoSTBranchStateBuilder extends STBranchStateBuilder +{ + public GoSTBranchStateBuilder(GoSTBranchActionBuilder bb) + { + super(bb); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + /*String ename = getBranchEnumType(api, s); + List as = s.getActions();*/ + return GoSTStateChanApiBuilder.getStateChanPremable((GoSTStateChanApiBuilder) api, s) /*+ "\n" + + "\n" + + "type " + ename + " int\n" + + "\n" + + "const (\n" + + getBranchEnumValue(as.get(0).mid) + " " + ename + " = iota \n" + + as.subList(1, as.size()).stream().map(a -> getBranchEnumValue(a.mid)).collect(Collectors.joining("\n")) + "\n" + + ")"*/; + } + + /*protected static String getBranchEnumType(STStateChanAPIBuilder api, EState s) + { + return api.getStateChanName(s) + "_Enum"; + } + + protected static String getBranchEnumValue(MessageId mid) + { + return "_" + mid; + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTCaseActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTCaseActionBuilder.java new file mode 100644 index 000000000..a7919a510 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTCaseActionBuilder.java @@ -0,0 +1,48 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.codegen.statetype.STCaseActionBuilder; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class GoSTCaseActionBuilder extends STCaseActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return "Recv_" + a.peer + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> "arg" + i + " *" + a.payload.elems.get(i)).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + return + IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> + //"val" + i + " := " + api.getChannelName(api, a) + ".Read()\n" + "val" + i + " := s.ep.Read(s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + ")\n" + + "if s.ep.Err != nil {\n" + + "return nil\n" + + "}\n" + + "*arg" + i + " = val" + i + ".(" + a.payload.elems.get(i) + ")" + ).collect(Collectors.joining("\n")) + "\n" + + buildReturn(api, curr, succ); + } + + @Override + public String getStateChanType(STStateChanApiBuilder api, EState curr, EAction a) + { + return GoSTCaseBuilder.getOpTypeName(api, curr, a.mid); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTCaseBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTCaseBuilder.java new file mode 100644 index 000000000..b9bc0fe53 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTCaseBuilder.java @@ -0,0 +1,79 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +import org.scribble.codegen.statetype.STCaseBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.main.RuntimeScribbleException; +import org.scribble.model.endpoint.EState; +import org.scribble.type.name.MessageId; + +public class GoSTCaseBuilder extends STCaseBuilder +{ + public GoSTCaseBuilder(GoSTCaseActionBuilder cb) + { + super(cb); + } + + protected static String getCaseActionName(STStateChanApiBuilder api, EState s) + { + return api.getStateChanName(s) + "_Case"; + } + + @Override + public String getCaseStateChanName(STStateChanApiBuilder api, EState s) + { + String name = api.getStateChanName(s) + "_Cases"; + // Should be "private" or not, corresponding to GSTStateChanAPIBuilder.makeSTStateName + //return ((s.id == api.graph.init.id) ? "_" : "") + name; // Case state channel itself cannot be the initial state chan + return name; + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + String casename = getCaseActionName(api, s); + return GoSTStateChanApiBuilder.getPackageDecl((GoSTStateChanApiBuilder) api) + "\n" + + "\n" + + "import \"org/scribble/runtime/net\"\n" // Some parts duplicated from GSTStateChanAPIBuilder + + "\n" + + "type " + getCaseStateChanName(api, s) + " interface {\n" + + casename + "()\n" + + "}" + + s.getActions().stream().map(a -> + "\n\ntype " + getOpTypeName(api, s, a.mid) + " struct{\n" + + "ep *net.MPSTEndpoint\n" // FIXME: factor out + + "state *net.LinearResource\n" // FIXME: EndSocket special case? // FIXME: only seems to work as a pointer (something to do with method calls via value recievers? is it copying the value before calling the function?) + + "}\n" + + "\n" + + "func (*" + getOpTypeName(api, s, a.mid) + ") " + casename + "() {}" + ).collect(Collectors.joining("")); + } + + private static Map seen = new HashMap<>(); // FIXME HACK + + protected static String getOpTypeName(STStateChanApiBuilder api, EState s, MessageId mid) + { + String op = mid.toString(); + char c = op.charAt(0); + if (c < 'A' || c > 'Z') + { + throw new RuntimeScribbleException("[go-api-gen] Branch message op should start with a capital letter: " + op); // FIXME: + } + if (GoSTCaseBuilder.seen.containsKey(op)) + { + if (GoSTCaseBuilder.seen.get(op) != s.id) + { + String n = api.getStateChanName(s); // HACK + op = op + "_" + api.role + "_" + n.substring(n.lastIndexOf('_') + 1); + } + } + else + { + GoSTCaseBuilder.seen.put(op, s.id); + } + return op; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTEndStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTEndStateBuilder.java new file mode 100644 index 000000000..6edde534b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTEndStateBuilder.java @@ -0,0 +1,35 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.codegen.statetype.STEndStateBuilder; +import org.scribble.model.endpoint.EState; + +public class GoSTEndStateBuilder extends STEndStateBuilder +{ + public GoSTEndStateBuilder() + { + + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + return getPreamble(api, s); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + //return GSTStateChanAPIBuilder.getStateChanPremable(api, s); + String tname = api.getStateChanName(s); + String res = + GoSTStateChanApiBuilder.getPackageDecl((GoSTStateChanApiBuilder) api) + "\n" + + "\n" + + "import \"org/scribble/runtime/net\"\n" + + "\n" + + "type " + tname + " struct{\n" + + "ep *net.MPSTEndpoint\n" // FIXME: factor out + + "}"; + return res; // No LinearResource + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTOutputStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTOutputStateBuilder.java new file mode 100644 index 000000000..41d86523c --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTOutputStateBuilder.java @@ -0,0 +1,20 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.codegen.statetype.STOutputStateBuilder; +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.model.endpoint.EState; + +public class GoSTOutputStateBuilder extends STOutputStateBuilder +{ + public GoSTOutputStateBuilder(STSendActionBuilder sb) + { + super(sb); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + return GoSTStateChanApiBuilder.getStateChanPremable((GoSTStateChanApiBuilder) api, s); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTReceiveActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTReceiveActionBuilder.java new file mode 100644 index 000000000..75d4a6eac --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTReceiveActionBuilder.java @@ -0,0 +1,45 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class GoSTReceiveActionBuilder extends STReceiveActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return "Recv_" + a.peer + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> "arg" + i + " *" + a.payload.elems.get(i)).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + //String chan = api.getChannelName(api, a); + return + //"op := + //chan + ".Read()" + "s.ep.Read(s.ep.Proto.(*" + api.gpn.getSimpleName() +")." + a.peer + ")" + + IntStream.range(0, a.payload.elems.size()) + //.mapToObj(i -> "\n\nval" + i + " := " + chan + ".Read()\n" + .mapToObj(i -> "\n\nval" + i + " := s.ep.Read(s.ep.Proto.(*" + api.gpn.getSimpleName() + ")."+ a.peer + ")\n" + + "*arg" + i + " = val" + i + ".(" + a.payload.elems.get(i) + ")" + ).collect(Collectors.joining("")) + "\n" + + "if s.ep.Err != nil {\n" + + "return nil\n" + + "}\n" + + buildReturn(api, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTReceiveStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTReceiveStateBuilder.java new file mode 100644 index 000000000..4cb024216 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTReceiveStateBuilder.java @@ -0,0 +1,21 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STReceiveStateBuilder; +import org.scribble.model.endpoint.EState; + +public class GoSTReceiveStateBuilder extends STReceiveStateBuilder +{ + public GoSTReceiveStateBuilder(STReceiveActionBuilder rb) + { + super(rb); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + //return GSTStateChanAPIBuilder.getStateChanPremable(api, s); + return api.bb.getPreamble(api, s); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTSendActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTSendActionBuilder.java new file mode 100644 index 000000000..c9c4c0b64 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTSendActionBuilder.java @@ -0,0 +1,43 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class GoSTSendActionBuilder extends STSendActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return "Send_" + a.peer + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> "arg" + i + " " + a.payload.elems.get(i)).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + //String chan = api.getChannelName(api, a); + return + ////chan + ".Write(" + GSTBranchStateBuilder.getBranchEnumValue(a.mid) + ")\n" + //chan + ".Write(\"" + a.mid + "\")\n" + "s.ep.Write(s.ep.Proto.(*" + api.gpn.getSimpleName() +")." + a.peer + ", \"" + a.mid + "\")\n" + + IntStream.range(0, a.payload.elems.size()) + //.mapToObj(i -> chan + ".Write(arg" + i + ")").collect(Collectors.joining("\n")) + "\n" + .mapToObj(i -> "s.ep.Write(s.ep.Proto.(*" + api.gpn.getSimpleName() +")." + a.peer + ", arg" + i + ")").collect(Collectors.joining("\n")) + "\n" + + "if s.ep.Err != nil {\n" + + "return nil" + + "}\n" + + buildReturn(api, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTSessionApiBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTSessionApiBuilder.java new file mode 100644 index 000000000..13e7fa935 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTSessionApiBuilder.java @@ -0,0 +1,174 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.scribble.ast.Module; +import org.scribble.ast.ProtocolDecl; +import org.scribble.model.MState; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.EStateKind; +import org.scribble.type.kind.Global; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +public class GoSTSessionApiBuilder +{ + private GoSTStateChanApiBuilder api; + + public GoSTSessionApiBuilder(GoSTStateChanApiBuilder api) + { + this.api = api; + } + + //@Override + public Map buildSessionAPI() // FIXME: factor out + { + Module mod = api.job.getContext().getModule(api.gpn.getPrefix()); + GProtocolName simpname = api.gpn.getSimpleName(); + ProtocolDecl gpd = mod.getProtocolDecl(simpname); + /*MessageIdCollector coll = new MessageIdCollector(this.job, ((ModuleDel) mod.del()).getModuleContext()); + try + { + gpd.accept(coll); + } + catch (ScribbleException e) + { + throw new RuntimeScribbleException(e); + }*/ + + List roles = gpd.header.roledecls.getRoles(); + //Set> mids = coll.getNames(); + Set instates = new HashSet<>(); + Predicate f = (s) -> s.getStateKind() == EStateKind.UNARY_INPUT || s.getStateKind() == EStateKind.POLY_INPUT; + if (f.test(api.graph.init)) + { + instates.add(api.graph.init); + } + instates.addAll(MState.getReachableStates(api.graph.init).stream().filter(f).collect(Collectors.toSet())); + + Map res = new HashMap<>(); + String dir = api.gpn.toString().replaceAll("\\.", "/") + "/"; + + /*// endpoints + String endpoints = + "package " + getPackage() + "\n" + + roles.stream().map(r -> + "type endpoint" + r + " struct {\n" + + roles.stream().filter(rr -> !rr.equals(r)).map(rr -> rr + " chan T").collect(Collectors.joining("\n")) + "\n" + + "}\n" + + "\n" + + "func (ep endpoint" + r + ") Close() error {\n" + + roles.stream().filter(rr -> rr.toString().compareTo(r.toString()) > 0).map(rr -> "close(ep" + "." + rr + ")").collect(Collectors.joining("\n")) + "\n" + + "return nil\n" + + "}\n" + + "\n" + + "var role" + r + " endpoint" + r + ).collect(Collectors.joining("\n\n")); + res.put(dir + "endpoints.go", endpoints);*/ + + // roles + String sessclass = + "package " + api.getPackage() + "\n" // FIXME: factor out + + "\n" + + "import \"org/scribble/runtime/net\"\n" + + "\n" + + roles.stream().map(r -> + "type _" + r + " struct { }\n" + + "\n" + + "func (*_" + r +") GetRoleName() string {\n" + + "return \"" + r + "\"\n" + + "}\n" + + "\n" + + "var __" + r + " *_" + r + "\n" + + "\n" + + "func new" + r + "() *_" + r + " {\n" // FIXME: not concurrent + + "if __" + r + " == nil {\n" + + "__"+ r + " = &_" + r + "{}\n" + + "}\n" + + "return __" + r + "\n" + + "}" + ).collect(Collectors.joining("\n\n")) + "\n" + + "\n" + + "type " + simpname + " struct {\n" + + roles.stream().map(r -> r + " *_" + r).collect(Collectors.joining("\n")) + "\n" // FIXME: role constants should be pointers? + + "}\n" + + "\n" + + "func New" + simpname + "() *" + simpname + "{\n" + + "return &" + simpname + "{ " + roles.stream().map(r -> "new" + r + "()").collect(Collectors.joining(", ")) + " }\n" + + "}"; + + // Protocol and role specific endpoints + sessclass += + roles.stream().map(r -> + "\n\n" + + "type _Endpoint" + simpname + "_" + r + " struct {\n" // FIXME: factor out + + r + " *net.MPSTEndpoint\n" // FIXME: factor out + + "}\n" + + "\n" + + "func NewEndpoint" + simpname + "_" + r + "(P *" + simpname + ") *_Endpoint" + simpname + "_" + r + "{\n" // FIXME: factor out + + "return &_Endpoint" + simpname + "_" + r + " { " + r + ": net.NewMPSTEndpoint(P, P." + r + ") }\n" // FIXME: factor out + + "}" + ).collect(Collectors.joining("")); + + res.put(dir + simpname + ".go", sessclass); + /*for (Role r : roles) + { + String init = this.gpn.getSimpleName() + "_" + r + "_" + 1; // FIXME: factor out naming scheme + String role = + "package " + getPackage() + "\n" + + "\n" + + "import \"io\"\n" + + "\n" + + "func New" + r + "(" + + roles.stream().filter(rr -> !rr.equals(r)).map(rr -> rr + " chan T").collect(Collectors.joining(", ")) + + ") (" + init + ", io.Closer) {\n" + + "role" + r + " = endpoint" + r + "{\n" + + roles.stream().filter(rr -> !rr.equals(r)).map(rr -> rr + ": " + rr).collect(Collectors.joining(",\n")) + ",\n" + + "}\n" + + "return " + init + "{}, role" + r + "\n" + + "}"; + res.put(dir + "role_" + r + ".go", role); + }*/ + + // labels + /*String labels = + "package " + api.getPackage(); // FIXME: factor out + for (EState s : instates) + { + String ename = GSTBranchStateBuilder.getBranchEnumType(this.api, s); + List as = s.getActions(); + labels += + "\n\ntype " + ename + " int\n" + + "\n" + + "const (\n" + + GSTBranchStateBuilder.getBranchEnumValue(as.get(0).mid) + " " + ename + " = iota \n" + + as.subList(1, as.size()).stream().map(a -> GSTBranchStateBuilder.getBranchEnumValue(a.mid)).collect(Collectors.joining("\n")) + "\n" + + ")"; + }*/ + /*String labels = + "package " + getPackage() + "\n"; + /*for (MessageId mid : mids) + { + labels += + "\ntype op" + mid + " string\n" + + "\n" + + "const " + mid + " op" + mid + " = \"" + mid + "\"\n"; + }*/ + //res.put(dir + "labels_" + api.role + ".go", labels); + + /*// types + String types = + "package " + getPackage() + "\n" + + "\n" + + "type T interface {}"; + res.put(dir + "types.go", types);*/ + + return res; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTStateChanApiBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTStateChanApiBuilder.java new file mode 100644 index 000000000..4e84dedb2 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/codegen/statetype/go/GoSTStateChanApiBuilder.java @@ -0,0 +1,134 @@ +package org.scribble.ext.go.codegen.statetype.go; + +import java.util.Map; + +import org.scribble.codegen.statetype.STActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.main.Job; +import org.scribble.model.endpoint.EGraph; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +public class GoSTStateChanApiBuilder extends STStateChanApiBuilder +{ + private int counter = 1; + + public GoSTStateChanApiBuilder(Job job, GProtocolName gpn, Role role, EGraph graph) + { + super(job, gpn, role, graph, + new GoSTOutputStateBuilder(new GoSTSendActionBuilder()), + new GoSTReceiveStateBuilder(new GoSTReceiveActionBuilder()), + new GoSTBranchStateBuilder(new GoSTBranchActionBuilder()), + new GoSTCaseBuilder(new GoSTCaseActionBuilder()), + new GoSTEndStateBuilder()); + } + + //@Override + public String getPackage() + { + return this.gpn.getSimpleName().toString(); + } + + @Override + protected String makeSTStateName(EState s) + { + if (s.isTerminal()) + { + return "_EndState"; + } + String name = this.gpn.getSimpleName() + "_" + this.role + "_" + this.counter++; + //return (s.id == this.graph.init.id) ? name : "_" + name; // For "private" non-initial state channels + return name; + } + + @Override + public String getStateChannelFilePath(String filename) + { + if (filename.startsWith("_")) // Cannot use "_" prefix, ignored by Go + { + filename = "$" + filename.substring(1); + } + return this.gpn.toString().replaceAll("\\.", "/") + "/" + filename + ".go"; + } + + //@Override + public Map buildSessionAPI() // FIXME: factor out + { + return new GoSTSessionApiBuilder(this).buildSessionAPI(); + } + + protected static String getPackageDecl(GoSTStateChanApiBuilder api) + { + return "package " + api.getPackage(); + } + + protected static String getStateChanPremable(GoSTStateChanApiBuilder api, EState s) + { + String tname = api.getStateChanName(s); + String res = + GoSTStateChanApiBuilder.getPackageDecl(api) + "\n" + + "\n" + + "import \"org/scribble/runtime/net\"\n" + + "\n" + + "type " + tname + " struct{\n" + + "ep *net.MPSTEndpoint\n" // FIXME: factor out + + "state *net.LinearResource\n" // FIXME: EndSocket special case? // FIXME: only seems to work as a pointer (something to do with method calls via value recievers? is it copying the value before calling the function?) + + "}"; + + if (s.id == api.graph.init.id) + { + res += + "\n\n" + + "func New" + tname + "(ep *_Endpoint" + api.gpn.getSimpleName() + "_" + api.role + ") *" + tname + " {\n" // FIXME: factor out + + "ep." + api.role + ".SetInit()\n" + + "return &" + tname + " { ep: ep." + api.role + ", state: &net.LinearResource { } }\n" + + "}"; + } + + return res; + } + + // Here because action builder hierarchy not suitable (extended by action kind, not by target language) + @Override + public String buildAction(STActionBuilder ab, EState curr, EAction a) + { + EState succ = curr.getSuccessor(a); + return + "func (s *" + ab.getStateChanType(this, curr, a) + ") " + ab.getActionName(this, a) + "(" + + ab.buildArgs(this, a) + + ") *" + ab.getReturnType(this, curr, succ) + " {\n" + + "s.state.Use()\n" + + ab.buildBody(this, curr, a, succ) + "\n" + + "}"; + } + + @Override + public String getChannelName(STStateChanApiBuilder api, EAction a) + { + return + ////"s.ep.Chans[s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + "]"; + //"s.ep.GetChan(s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + ")"; + null; + } + + @Override + public String buildActionReturn(STActionBuilder ab, EState curr, EState succ) // FIXME: refactor action builders as interfaces and use generic parameter for kind + { + String res = ""; + + if (succ.isTerminal()) + { + res += "s.ep.SetDone()\n"; + } + res += "return &" + ab.getReturnType(this, curr, succ) + "{ ep: s.ep"; + if (!succ.isTerminal()) + { + res += ", state: &net.LinearResource {}"; // FIXME: EndSocket LinearResource special case + } + res += " }"; + + return res; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreActionKind.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreActionKind.java new file mode 100644 index 000000000..43460eea3 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreActionKind.java @@ -0,0 +1,8 @@ +package org.scribble.ext.go.core.ast; + +import org.scribble.type.kind.ProtocolKind; + +public interface RPCoreActionKind +{ + +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreAstFactory.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreAstFactory.java new file mode 100644 index 000000000..c4c9fef71 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreAstFactory.java @@ -0,0 +1,164 @@ +package org.scribble.ext.go.core.ast; + +import java.util.LinkedHashMap; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.core.ast.global.RPCoreGActionKind; +import org.scribble.ext.go.core.ast.global.RPCoreGChoice; +import org.scribble.ext.go.core.ast.global.RPCoreGCont; +import org.scribble.ext.go.core.ast.global.RPCoreGEnd; +import org.scribble.ext.go.core.ast.global.RPCoreGForeach; +import org.scribble.ext.go.core.ast.global.RPCoreGRec; +import org.scribble.ext.go.core.ast.global.RPCoreGRecVar; +import org.scribble.ext.go.core.ast.global.RPCoreGType; +import org.scribble.ext.go.core.ast.local.RPCoreLActionKind; +import org.scribble.ext.go.core.ast.local.RPCoreLCont; +import org.scribble.ext.go.core.ast.local.RPCoreLCrossChoice; +import org.scribble.ext.go.core.ast.local.RPCoreLEnd; +import org.scribble.ext.go.core.ast.local.RPCoreLForeach; +import org.scribble.ext.go.core.ast.local.RPCoreLRec; +import org.scribble.ext.go.core.ast.local.RPCoreLRecVar; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.type.Message; +import org.scribble.type.name.RecVar; +import org.scribble.type.name.Role; + + +// For "core" stuff -- not "full" AF (Antlr) AST +public class RPCoreAstFactory +{ + public RPCoreAstFactory() + { + + } + + public RPIndexedRole ParamRole(String name, RPInterval range) // ParamRange not "ast", so not made by af + { + return new RPIndexedRole(name, Stream.of(range).collect(Collectors.toSet())); + } + + // Pre: not null -- ? + /*public RPCoreMessage ParamCoreAction(Op op, Payload pay) + { + return new RPCoreMessage(op, pay); + }*/ + + public RPCoreGChoice ParamCoreGChoice(RPIndexedRole src, RPCoreGActionKind kind, RPIndexedRole dest, //LinkedHashMap cases) + LinkedHashMap cases) + { + return new RPCoreGChoice(src, kind, dest, cases); + } + + /*public RPCoreGMultiChoices ParamCoreGMultiChoices(RPIndexedRole src, RPIndexVar var, + RPIndexedRole dest, List cases, RPCoreGType cont) + { + return new RPCoreGMultiChoices(src, var, dest, cases, cont); + }*/ + + public RPCoreGRec ParamCoreGRec(RecVar recvar, RPCoreGType body) + { + return new RPCoreGRec(recvar, body); + } + + public RPCoreGRecVar ParamCoreGRecVar(RecVar recvar) + { + return new RPCoreGRecVar(recvar); + } + + public RPCoreGEnd ParamCoreGEnd() + { + return RPCoreGEnd.END; + } + + public RPCoreGCont ParamCoreGCont() + { + return RPCoreGCont.CONT; + } + + public RPCoreGForeach RPCoreGForeach(//Role role, RPForeachVar var, RPIndexExpr start, RPIndexExpr end, + Set roles, Set ivals, + RPCoreGType body, RPCoreGType seq) + { + return new RPCoreGForeach(//role, var, start, end, + roles, ivals, + body, seq); + } + + public RPCoreLCrossChoice ParamCoreLCrossChoice(RPIndexedRole role, RPCoreLActionKind kind, + //LinkedHashMap cases) + LinkedHashMap cases) + { + return new RPCoreLCrossChoice(role, kind, cases); + } + + /*public RPCoreLDotChoice ParamCoreLDotChoice(RPIndexedRole role, RPIndexExpr offset, RPCoreLActionKind kind, + LinkedHashMap cases) + { + return new RPCoreLDotChoice(role, offset, kind, cases); + } + + public RPCoreLMultiChoices ParamCoreLMultiChoices(RPIndexedRole role, RPIndexVar var, + List cases, RPCoreLType cont) + { + return new RPCoreLMultiChoices(role, var, cases, cont); + }*/ + + /*public ParamCoreLSend LSend(Role self, Role peer, Op op, Payload pay) + { + return new ParamCoreLSend(self, peer, op, pay); + } + + public ParamCoreLReceive LReceive(Role self, Role peer, Op op, Payload pay) + { + return new ParamCoreLReceive(self, peer, op, pay); + } + + public ParamCoreLConnect LConnect(Role self, Role peer, Op op, Payload pay) + { + return new ParamCoreLConnect(self, peer, op, pay); + } + + public ParamCoreLAccept LAccept(Role self, Role peer, Op op, Payload pay) + { + return new ParamCoreLAccept(self, peer, op, pay); + }*/ + + /*public ParamCoreLDisconnect LDisconnect(Role self, Role peer) + { + return new ParamCoreLDisconnect(self, peer); + }*/ + + public RPCoreLRec ParamCoreLRec(RecVar recvar, RPCoreLType body) + { + return new RPCoreLRec(recvar, body); + } + + public RPCoreLRecVar ParamCoreLRecVar(RecVar recvar) + { + return new RPCoreLRecVar(recvar); + } + + public RPCoreLEnd ParamCoreLEnd() + { + return RPCoreLEnd.END; + } + + public RPCoreLCont ParamCoreLCont() + { + return RPCoreLCont.CONT; + } + + public RPCoreLForeach RPCoreLForeach(//Role role, RPForeachVar var, RPIndexExpr start, RPIndexExpr end, + Set roles, Set ivals, + RPCoreLType body, RPCoreLType seq) + { + return new RPCoreLForeach(//role, var, start, end, + roles, ivals, + body, seq); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreChoice.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreChoice.java new file mode 100644 index 000000000..8041fa7ba --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreChoice.java @@ -0,0 +1,69 @@ +package org.scribble.ext.go.core.ast; + +import java.util.LinkedHashMap; +import java.util.stream.Collectors; + +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.type.Message; +import org.scribble.type.kind.ProtocolKind; + +public abstract class RPCoreChoice, K extends ProtocolKind> implements RPCoreType +{ + public final RPIndexedRole role; + public final RPCoreActionKind kind; + //public final LinkedHashMap cases; + public final LinkedHashMap cases; + + // Pre: cases.size() > 1 + //public RPCoreChoice(RPIndexedRole role, RPCoreActionKind kind, LinkedHashMap cases) + public RPCoreChoice(RPIndexedRole role, RPCoreActionKind kind, LinkedHashMap cases) + { + this.role = role; + this.kind = kind; + this.cases = new LinkedHashMap<>(cases); + } + + public abstract RPCoreActionKind getKind(); + + @Override + public int hashCode() + { + int hash = 29; + hash = 31 * hash + this.role.hashCode(); + hash = 31 * hash + this.kind.hashCode(); + hash = 31 * hash + this.cases.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreChoice)) + { + return false; + } + RPCoreChoice them = (RPCoreChoice) obj; + return them.canEquals(this) + && this.role.equals(them.role) && this.kind.equals(kind) && this.cases.equals(them.cases); + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreChoice; + } + + protected String casesToString() + { + String s = this.cases.entrySet().stream() + .map(e -> e.getKey() + "." + e.getValue()).collect(Collectors.joining(", ")); + s = (this.cases.size() > 1) + ? "{ " + s + " }" + : ":" + s; + return s; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreCont.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreCont.java new file mode 100644 index 000000000..6430e4df0 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreCont.java @@ -0,0 +1,30 @@ +package org.scribble.ext.go.core.ast; + +import org.scribble.type.kind.ProtocolKind; + +public abstract class RPCoreCont implements RPCoreType +{ + @Override + public String toString() + { + return "cont"; + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreCont)) + { + return false; + } + return ((RPCoreCont) obj).canEquals(this); + } + + public abstract boolean canEquals(Object o); + + @Override + public int hashCode() + { + return 31*2777; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreDelegDecl.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreDelegDecl.java new file mode 100644 index 000000000..556dc9a5a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreDelegDecl.java @@ -0,0 +1,53 @@ +package org.scribble.ext.go.core.ast; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.Constants; +import org.scribble.ast.DataTypeDecl; +import org.scribble.ast.ScribNodeBase; +import org.scribble.ast.name.qualified.DataTypeNode; +import org.scribble.ast.name.qualified.MemberNameNode; +import org.scribble.del.ScribDel; +import org.scribble.type.kind.DataTypeKind; + +// CHECKME: for declaring "deleg ..." declaration type imports? (variant types from external packages?) +// HACK -- extending P@r[e] syntax is not clear yet +@Deprecated +public class RPCoreDelegDecl extends DataTypeDecl +{ + public RPCoreDelegDecl(CommonTree source, String schema, String extName, String extSource, DataTypeNode name) + { + super(source, schema, extName, extSource, name); + } + + @Override + protected ScribNodeBase copy() + { + return new RPCoreDelegDecl(this.source, this.schema, this.extName, this.extSource, getNameNode()); + } + + @Override + public RPCoreDelegDecl clone(AstFactory af) + { + DataTypeNode name = (DataTypeNode) this.name.clone(af); + //return ((RPAstFactory) af).ParamCoreDelegDecl(this.source, this.schema, this.extName, this.extSource, name); + throw new RuntimeException("TODO"); + } + + @Override + public RPCoreDelegDecl reconstruct(String schema, String extName, String extSource, MemberNameNode name) + { + ScribDel del = del(); + RPCoreDelegDecl dtd = new RPCoreDelegDecl(this.source, schema, extName, extSource, (DataTypeNode) name); + dtd = (RPCoreDelegDecl) dtd.del(del); + return dtd; + } + + @Override + public String toString() + { + return "deleg" + " <" + this.schema + "> " + this.extName // FIXME: factor out constant + + " " + Constants.FROM_KW + " " + this.extSource + " " + + Constants.AS_KW + " " + this.name + ";"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreEnd.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreEnd.java new file mode 100644 index 000000000..ab2e836f3 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreEnd.java @@ -0,0 +1,30 @@ +package org.scribble.ext.go.core.ast; + +import org.scribble.type.kind.ProtocolKind; + +public abstract class RPCoreEnd implements RPCoreType +{ + @Override + public String toString() + { + return "end"; + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreEnd)) + { + return false; + } + return ((RPCoreEnd) obj).canEquals(this); + } + + public abstract boolean canEquals(Object o); + + @Override + public int hashCode() + { + return 31*2447; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreForeach.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreForeach.java new file mode 100644 index 000000000..e6c8eec99 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreForeach.java @@ -0,0 +1,86 @@ +package org.scribble.ext.go.core.ast; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.type.kind.ProtocolKind; +import org.scribble.type.name.Role; + +public abstract class RPCoreForeach, K extends ProtocolKind> implements RPCoreType +{ + /*public final Role role; + public final RPForeachVar param; + // FIXME: use RPInterval + public final RPIndexExpr start; // Gives the Scribble choices-subj range // Cf. ParamCoreGChoice singleton src + public final RPIndexExpr end; // this.dest == super.role -- arbitrary?*/ + + // FIXME: record original role-ival bindings -- to check valid foreach index usage per rolename in WF + public final Set roles; + public final Set ivals; // FIXME: co-intervals? + + public final B body; + public final B seq; + + // Pre: ivals vars are distinct + public RPCoreForeach(//Role role, RPForeachVar param, RPIndexExpr start, RPIndexExpr end, + Set roles, Set ivals, + B body, B cont) + { + /*this.role = role; + this.param = param; + this.start = start; + this.end = end;*/ + this.roles = new HashSet<>(roles); + this.ivals = new HashSet<>(ivals); + this.body = body; + this.seq = cont; + } + + @Override + public String toString() + { + return "foreach " //+ this.role + "[" + param + ":" + this.start + "," + this.end + "] do " + + "{" + this.roles.stream().map(r -> r.toString()).collect(Collectors.joining(", ")) + "}" + + "{" + this.ivals.stream().map(x -> x.var + ":" + x.start + ".." + x.end).collect(Collectors.joining(", ")) + "} do " + + this.body + " ; " + this.seq; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreForeach)) + { + return false; + } + RPCoreForeach them = (RPCoreForeach) obj; + return them.canEquals(this) && this.roles.equals(them.roles) + //&& this.param.equals(them.param) && this.start.equals(them.start) && this.end.equals(them.end) + && this.ivals.equals(them.ivals) + && this.body.equals(them.body) && this.seq.equals(them.seq); // FIXME: check B kind is equal? + } + + @Override + public abstract boolean canEquals(Object o); + + @Override + public int hashCode() + { + final int prime = 4271; + int result = 1; + /*result = prime * result + this.role.hashCode(); + result = prime * result + this.param.hashCode(); + result = prime * result + this.start.hashCode(); + result = prime * result + this.end.hashCode();*/ + result = prime * result + this.roles.hashCode(); + result = prime * result + this.ivals.hashCode(); + result = prime * result + this.body.hashCode(); + result = prime * result + this.seq.hashCode(); + return result; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreMessage.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreMessage.java new file mode 100644 index 000000000..48c4a78ad --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreMessage.java @@ -0,0 +1,7 @@ +package org.scribble.ext.go.core.ast; + +@Deprecated +public interface RPCoreMessage +{ + +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreMessageSig.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreMessageSig.java new file mode 100644 index 000000000..fd251f9e1 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreMessageSig.java @@ -0,0 +1,48 @@ +package org.scribble.ext.go.core.ast; + +import org.scribble.type.Payload; +import org.scribble.type.name.Op; + +@Deprecated +public class RPCoreMessageSig implements RPCoreMessage +{ + public final Op op; + public final Payload pay; + + public RPCoreMessageSig(Op op, Payload pay) + { + this.op = op; + this.pay = pay; + } + + @Override + public String toString() + { + return this.op.toString() + this.pay.toString(); + } + + @Override + public int hashCode() + { + int hash = 43; + hash = 31 * hash + this.op.hashCode(); + hash = 31 * hash + this.pay.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + { + return true; + } + if (!(obj instanceof RPCoreMessageSig)) + { + return false; + } + RPCoreMessageSig them = (RPCoreMessageSig) obj; + return //them.canEquals(this) && + this.op.equals(them.op) && this.pay.equals(them.pay); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreRec.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreRec.java new file mode 100644 index 000000000..5a1560c0f --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreRec.java @@ -0,0 +1,51 @@ +package org.scribble.ext.go.core.ast; + +import org.scribble.type.kind.ProtocolKind; +import org.scribble.type.name.RecVar; + +public abstract class RPCoreRec, K extends ProtocolKind> implements RPCoreType +{ + public final RecVar recvar; // FIXME: RecVarNode? (Cf. AssrtCoreAction.op/pay) + public final B body; + + public RPCoreRec(RecVar recvar, B body) + { + this.recvar = recvar; + this.body = body; + } + + @Override + public String toString() + { + return "mu " + this.recvar + "." + this.body; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreRec)) + { + return false; + } + RPCoreRec them = (RPCoreRec) obj; + return them.canEquals(this) && this.recvar.equals(them.recvar) + && this.body.equals(them.body); // FIXME: check B kind is equal? + } + + @Override + public abstract boolean canEquals(Object o); + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + this.recvar.hashCode(); + result = prime * result + this.body.hashCode(); + return result; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreRecVar.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreRecVar.java new file mode 100644 index 000000000..bf96e7df4 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreRecVar.java @@ -0,0 +1,43 @@ +package org.scribble.ext.go.core.ast; + +import org.scribble.type.kind.ProtocolKind; +import org.scribble.type.name.RecVar; + + +public abstract class RPCoreRecVar implements RPCoreType +{ + public final RecVar recvar; + + public RPCoreRecVar(RecVar var) + { + this.recvar = var; + } + + @Override + public String toString() + { + return this.recvar.toString(); + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreRecVar)) + { + return false; + } + RPCoreRecVar them = (RPCoreRecVar) obj; + return them.canEquals(this) && this.recvar.equals(them.recvar); + } + + @Override + public abstract boolean canEquals(Object o); + + @Override + public int hashCode() + { + int hash = 6733; + hash = 31*hash + this.recvar.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreSyntaxException.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreSyntaxException.java new file mode 100644 index 000000000..cc8e26945 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreSyntaxException.java @@ -0,0 +1,49 @@ +package org.scribble.ext.go.core.ast; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.main.AntlrSourceException; + +// For parsing errors due to core syntax restrictions (vs. "full" Scribble) -- distinction used for JUnit testing (i.e., to indicate non core syntax that are otherwise valid protocols) +// i.e., should only be thrown by AssrtCoreGProtocolDeclTranslator +// N.B. so should not be used for actual "semantic" WF errors +public class RPCoreSyntaxException extends AntlrSourceException // N.B. not Scribble/AssrttException -- cf. AssrtCoreTestBase::tests +{ + + /** + * + */ + private static final long serialVersionUID = 1L; + + + public RPCoreSyntaxException(String arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + public RPCoreSyntaxException(Throwable arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + public RPCoreSyntaxException(String arg0, Throwable arg1) + { + super(arg0, arg1); + // TODO Auto-generated constructor stub + } + + public RPCoreSyntaxException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + // TODO Auto-generated constructor stub + } + + public RPCoreSyntaxException(CommonTree blame, String arg0) + { + super(blame, arg0); + // TODO Auto-generated constructor stub + } + +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreType.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreType.java new file mode 100644 index 000000000..04425e569 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/RPCoreType.java @@ -0,0 +1,11 @@ +package org.scribble.ext.go.core.ast; + +import org.scribble.type.kind.ProtocolKind; + +// ast here means "core syntax" of session types -- it does not link the actual Scribble source (cf. base ast classes) +public interface RPCoreType +{ + boolean canEquals(Object o); + + RPCoreType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu); +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGActionKind.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGActionKind.java new file mode 100644 index 000000000..c69757e2d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGActionKind.java @@ -0,0 +1,21 @@ +package org.scribble.ext.go.core.ast.global; + +import org.scribble.ext.go.core.ast.RPCoreActionKind; +import org.scribble.type.kind.Global; + +public enum RPCoreGActionKind implements RPCoreActionKind +{ + CROSS_TRANSFER, + DOT_TRANSFER; + + @Override + public String toString() + { + switch (this) + { + case CROSS_TRANSFER: return "->"; + case DOT_TRANSFER: return "=>"; + default: throw new RuntimeException("[param-core] Won't get here: " + this); + } + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGChoice.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGChoice.java new file mode 100644 index 000000000..eca67d881 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGChoice.java @@ -0,0 +1,752 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Stack; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreChoice; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.ast.local.RPCoreLActionKind; +import org.scribble.ext.go.core.ast.local.RPCoreLCrossChoice; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.core.type.name.RPCoreGDelegationType; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPBinIndexExpr.Op; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexFactory; +import org.scribble.ext.go.type.index.RPIndexSelf; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.ext.go.util.Z3Wrapper; +import org.scribble.type.Message; +import org.scribble.type.MessageSig; +import org.scribble.type.kind.Global; +import org.scribble.type.name.GDelegationType; +import org.scribble.type.name.PayloadElemType; +import org.scribble.type.name.Role; + +public class RPCoreGChoice extends RPCoreChoice implements RPCoreGType +{ + public final RPIndexedRole src; // "Singleton" -- checked by isWellFormed + public final RPIndexedRole dest; // this.dest == super.role -- arbitrary? + + public RPCoreGChoice(RPIndexedRole src, RPCoreGActionKind kind, RPIndexedRole dest, + //LinkedHashMap cases) + LinkedHashMap cases) + { + super(dest, kind, cases); + this.src = src; + this.dest = dest; + } + + @Override + public RPCoreGType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreGType) neu; + } + else + { + LinkedHashMap tmp = new LinkedHashMap<>(); + this.cases.forEach((k, v) -> tmp.put(k, v.subs(af, old, neu))); // Immutable, so neu can be shared by multiple cases + return af.ParamCoreGChoice(this.src, RPCoreGActionKind.CROSS_TRANSFER, this.dest, tmp); + } + } + + // gpd only for calling Z3Wrapper.checkSat + @Override + public boolean isWellFormed(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t) + { + // src (i.e., choice subj) range size=1 for non-unary choices enforced by ParamScribble.g syntax + // Directed choice check by ParamCoreGProtocolDeclTranslator ensures all dests (including ranges) are (syntactically) the same + + RPInterval srcRange = this.src.getParsedRange(); + RPInterval destRange = this.dest.getParsedRange(); + Set vars = Stream.of(srcRange, destRange).flatMap(r -> r.getIndexVars().stream()).collect(Collectors.toSet()); + // FIXME: record foreachvars separately, for additional constraint generation + + //if (!checkNonEmptyIntervals(...)) + if (!checkIntervalRanges(job, gpd, vars, smt2t)) + { + return false; + } + + if (this.kind == RPCoreGActionKind.CROSS_TRANSFER) + { + if (this.cases.size() > 1) + { + if (!checkSingletonChoiceSubject(job, gpd, vars, smt2t)) + { + return false; + } + } + + if (!checkForeachVars(job, context, smt2t)) + { + return false; + } + } + + if (this.src.getName().equals(this.dest.getName())) + { + if (this.kind != RPCoreGActionKind.CROSS_TRANSFER) + { + throw new RuntimeException("Shouldn't get here: " + this.kind); + } + + if (!checkOverlappingIntervals(job, context, gpd, vars, smt2t) || !checkForeachVarAlignment(job, context, gpd, smt2t)) + { + return false; + } + } + + /*// Now redundant -- restore for "pair/pipe" sugar + if (this.kind == RPCoreGActionKind.DOT_TRANSFER) + { + String smt2 = "(assert" + + (vars.isEmpty() ? "" : " (forall (" + vars.stream().map(v -> "(" + v + " Int)").collect(Collectors.joining(" "))) + ") " + + "(and (= (- " + srcRange.end.toSmt2Formula() + " " + srcRange.start.toSmt2Formula() + ") (- " + + destRange.end.toSmt2Formula() + " " + destRange.start.toSmt2Formula() + "))" + + (!this.src.getName().equals(this.dest.getName()) ? "" : + " (not (= " + srcRange.start.toSmt2Formula() + " " + destRange.start.toSmt2Formula() + "))") + + ")" + + (vars.isEmpty() ? "" : ")") + + ")"; + + job.debugPrintln("\n[param-core] [WF] Checking dot-range alignment between " + srcRange + " and " + destRange + ":\n " + smt2); + + if (!Z3Wrapper.checkSat(job, gpd, smt2)) + { + return false; + } + }*/ + + return true; + } + + // Returns true if OK + private boolean checkForeachVarAlignment(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t) + { + RPInterval srcRange = this.src.getParsedRange(); + RPInterval destRange = this.dest.getParsedRange(); + + Map peek = context.isEmpty() ? Collections.emptyMap() : context.peek(); + // FIXME: only do if both are foreachvars + if (hasValidForeachVarIndex(context, this.src) && hasValidForeachVarIndex(context, this.dest)) + { + String sv = ((RPIndexVar) this.src.intervals.iterator().next().start).toString(); + String dv = ((RPIndexVar) this.dest.intervals.iterator().next().end).toString(); + RPInterval s = peek.get(RPIndexFactory.RPForeachVar(sv)); + RPInterval d = peek.get(RPIndexFactory.RPForeachVar(dv)); + Set vars = Stream.of(s, d).flatMap(r -> r.getIndexVars().stream()).collect(Collectors.toSet()); + // Duplicated from DOT_TRANSFER + /*String smt2 = "(assert" + + (tmp.isEmpty() ? "" : " (forall (" + vars.stream().map(v -> "(" + v + " Int)").collect(Collectors.joining(" "))) + ") " + + "(and (= (- " + s.end.toSmt2Formula() + " " + s.start.toSmt2Formula() + ") (- " + + d.end.toSmt2Formula() + " " + d.start.toSmt2Formula() + "))" + + (!this.src.getName().equals(this.dest.getName()) ? "" : + " (not (= " + s.start.toSmt2Formula() + " " + d.start.toSmt2Formula() + "))") + + ")" + + (tmp.isEmpty() ? "" : ")") + + ")";*/ + + List cs = new LinkedList<>(); + cs.add(smt2t.makeEq(smt2t.makeSub(s.end.toSmt2Formula(smt2t), s.start.toSmt2Formula(smt2t)), smt2t.makeSub(d.end.toSmt2Formula(smt2t), d.start.toSmt2Formula(smt2t)))); + if (this.src.getName().equals(this.dest.getName())) + { + cs.add(smt2t.makeNot(smt2t.makeEq(s.start.toSmt2Formula(smt2t), d.start.toSmt2Formula(smt2t)))); + } + String smt2 = (cs.size() == 1) ? cs.get(0) : smt2t.makeAnd(cs); + if (!vars.isEmpty()) + { + smt2 = smt2t.makeImplies( + smt2t.makeAnd(vars.stream().map(x -> smt2t.makeGte(x.toSmt2Formula(smt2t), smt2t.getDefaultBaseValue())).collect(Collectors.toList())), + smt2); + smt2 = smt2t.makeForall(vars.stream().map(x -> x.toSmt2Formula(smt2t)).collect(Collectors.toList()), smt2); + } + smt2 = smt2t.makeAssert(smt2); + + job.debugPrintln("\n[param-core] [WF] Checking foreach-var alignment between " + srcRange + " and " + destRange + ":\n " + smt2); + + if (!Z3Wrapper.checkSat(job, gpd, smt2)) + { + return false; + } + } + return true; + } + + /*private boolean checkSelfCommunication(...) + { + //Set curr = peek.keySet().stream().map(k -> k.toString()).collect(Collectors.toSet()); + if (isValidForeachIndexVar(context, this.src) && isValidForeachIndexVar(context, this.dest)) + { + String sv = srcVars.iterator().next().toString(); + String dv = destVars.iterator().next().toString(); + if (curr.contains(sv) && curr.contains(dv)) + { + RPIndexExpr s = peek.get(RPIndexFactory.RPForeachVar(sv)).start; + RPIndexExpr d = peek.get(RPIndexFactory.RPForeachVar(dv)).start; + if (!(s instanceof RPIndexInt) && !(s instanceof RPIndexInt)) + { + System.err.println("\n[param-core] Interval separation not being fully proved: " + s + " and " + d); + } + if (s.equals(d)) + // FIXME: use Z3 to prove intervals not equal (not just checking against syntactic equality) + { + job.debugPrintln("\n[param-core] (Potential) illegal self-communication: " + this); + return false; + } + } + } + }*/ + + // Returns true if OK + private boolean checkOverlappingIntervals(GoJob job, + Stack> context, GProtocolDecl gpd, Set vars, Smt2Translator smt2t) + { + RPInterval srcRange = this.src.getParsedRange(); + RPInterval destRange = this.dest.getParsedRange(); + Map peek = context.isEmpty() ? Collections.emptyMap() : context.peek(); + Set curr = peek.keySet().stream().map(k -> k.name).collect(Collectors.toSet()); + + /*String smt2 = "(assert (exists ((foobartmp Int)"; // FIXME: factor out + smt2 += vars.stream().map(v -> " (" + v.name + " Int)").collect(Collectors.joining("")); + smt2 += ") (and"; + smt2 += vars.isEmpty() ? "" : vars.stream().map(v -> " (>= " + v + " 1)").collect(Collectors.joining("")); + // FIXME: lower bound constant '1' -- replace by global invariant + + Set srcAndDestVars = new HashSet<>(); + srcAndDestVars.addAll(this.src.getIndexVars()); + srcAndDestVars.addAll(this.dest.getIndexVars()); + for (RPIndexVar sv : srcAndDestVars) + { + String tmp = sv.toString(); + if (curr.contains(tmp)) // FIXME: awkwardness of RPForeachVar and RPIndexVar + { + RPInterval ival = peek.get(RPIndexFactory.RPForeachVar(tmp)); + smt2 += " (= " + sv + " " + ival.start + ")"; + } + } + + smt2 += Stream.of(srcRange, destRange) + .map(r -> " (>= foobartmp " + r.start.toSmt2Formula() + ") (<= foobartmp " + r.end.toSmt2Formula() + ")") + .collect(Collectors.joining()); + smt2 += ")))";*/ + + List cs = new LinkedList<>(); + vars.forEach(x -> cs.add(smt2t.makeGte(x.toSmt2Formula(smt2t), smt2t.getDefaultBaseValue()))); + Set srcAndDestVars = new HashSet<>(); + srcAndDestVars.addAll(this.src.getIndexVars()); + srcAndDestVars.addAll(this.dest.getIndexVars()); + List tmp = new LinkedList<>(); + tmp.add("foobartmp"); + vars.forEach(x -> tmp.add(x.toSmt2Formula(smt2t))); + for (RPIndexVar sv : srcAndDestVars) + { + String tmp2 = sv.toString(); + if (curr.contains(tmp2)) // FIXME: awkwardness of RPForeachVar and RPIndexVar + { + RPInterval ival = peek.get(RPIndexFactory.RPForeachVar(tmp2)); + cs.add(smt2t.makeEq(sv.toSmt2Formula(smt2t), ival.start.toSmt2Formula(smt2t))); + ival.start.getVars().stream().map(x -> x.toSmt2Formula(smt2t)).forEach(x -> + { + tmp.add(x); + cs.add(smt2t.makeGte(x, smt2t.getDefaultBaseValue())); + }); + } + } + Stream.of(srcRange, destRange).forEach(r -> + { + cs.add(smt2t.makeGte("foobartmp", r.start.toSmt2Formula(smt2t))); + cs.add(smt2t.makeLte("foobartmp", r.end.toSmt2Formula(smt2t))); + }); + String smt2 = smt2t.makeAssert(smt2t.makeExists(tmp, smt2t.makeAnd(cs))); + + job.debugPrintln("\n[param-core] [WF] Checking non-overlapping ranges (potential self-communication) for " + this.src.getName() + ":\n " + smt2); + + if (Z3Wrapper.checkSat(job, gpd, smt2)) + { + return false; + } + + // CHECKME: projection cases for rolename self-comm but non-overlapping intervals + + return true; + } + + // Returns true if OK + private boolean checkForeachVars(GoJob job, Stack> context, Smt2Translator smt2t) + { + Set all = context.stream().flatMap(m -> m.keySet().stream().map(k -> k.name)).collect(Collectors.toSet()); // FIXME: awkwardness of RPForeachVar and RPIndexVar + Function checkForeachVarIndex = ir -> + { + Set vs = ir.getIndexVars().stream().map(x -> x.name).collect(Collectors.toSet()); // FIXME: awkwardness of RPForeachVar and RPIndexVar + if (vs.stream().anyMatch(x -> all.contains(x))) + { + if (!hasValidForeachVarIndex(context, ir)) + { + // FIXME: check in name disamb pass? + job.debugPrintln("\n[param-core] [WF] Illegal use/access of foreach-var: " + ir); + return false; + } + } + return true; + }; + if (!checkForeachVarIndex.apply(this.src) || !checkForeachVarIndex.apply(this.dest)) + { + return false; + } + return true; + } + + // Returns true if OK + private boolean checkSingletonChoiceSubject(GoJob job, GProtocolDecl gpd, Set vars, Smt2Translator smt2t) + { + RPInterval srcRange = this.src.getParsedRange(); + /*String bar = "(assert " + + (vars.isEmpty() ? "" : "(exists (" + vars.stream().map(v -> "(" + v.name + " Int)").collect(Collectors.joining(" ")) + ") (and ") + + vars.stream().map(v -> " (>= " + v + " 1)").collect(Collectors.joining("")) // FIXME: lower bound constant -- replace by global invariant + + "(not (= (- " + srcRange.end.toSmt2Formula() + " " + srcRange.start.toSmt2Formula() + ") 0))" + + (vars.isEmpty() ? "" : "))") + + ")";*/ + + List cs = new LinkedList<>(); + vars.forEach(v -> cs.add(smt2t.makeGte(v.toSmt2Formula(smt2t), smt2t.getDefaultBaseValue()))); + cs.add(smt2t.makeNot(smt2t.makeEq(smt2t.makeSub(srcRange.end.toSmt2Formula(smt2t), srcRange.start.toSmt2Formula(smt2t)), smt2t.getZeroValue()))); + String smt2 = smt2t.makeAnd(cs); + if (!vars.isEmpty()) + { + smt2 = smt2t.makeExists(vars.stream().map(x -> x.toSmt2Formula(smt2t)).collect(Collectors.toList()), smt2); + } + smt2 = smt2t.makeAssert(smt2); + + job.debugPrintln("\n[param-core] [WF] Checking singleton choice-subject for " + this.src + ":\n " + smt2); + + if (Z3Wrapper.checkSat(job, gpd, smt2)) + { + return false; + } + return true; + } + + /*// Returns true if OK + private boolean checkNonEmptyIntervals(...) + { + // CHECKME: is range size>0 already ensured by syntax? + Function foo1 = r -> + "(assert (exists ((foobartmp Int)" + + vars.stream().map(v -> " (" + v.name + " Int)").collect(Collectors.joining("")) + + ") (and" + + " (>= foobartmp " + r.start.toSmt2Formula() + ") (<= foobartmp " + r.end.toSmt2Formula() + ")" // FIXME: factor out with above + + ")))"; + Predicate foo2 = r -> + { + String foo = foo1.apply(srcRange); + + job.debugPrintln("\n[param-core] [WF] Checking non-empty ranges:\n " + foo); + + return Z3Wrapper.checkSat(job, gpd, foo); + }; + ... + */ + + // Returns true if OK + private boolean checkIntervalRanges(GoJob job, GProtocolDecl gpd, Set vars, Smt2Translator smt2t) + { + RPInterval srcRange = this.src.getParsedRange(); + RPInterval destRange = this.dest.getParsedRange(); + + /*Function foo1 = r -> // FIXME: factor out with above + "(assert " + + (vars.isEmpty() ? "" : "(exists (" + vars.stream().map(v -> "(" + v.name + " Int)").collect(Collectors.joining(" ")) + ") (and (and") + + vars.stream().map(v -> " (>= " + v + " 1)").collect(Collectors.joining("")) // FIXME: lower bound constant -- replace by global invariant + + (vars.isEmpty() ? "" : ")") + + " (> " + r.start.toSmt2Formula() + " " + r.end.toSmt2Formula() + ")" + //+ Z3Wrapper.getSmt2_gt(r.start, r.end) + + (vars.isEmpty() ? "" : "))") + + ")";*/ + + Function foo1 = r -> // FIXME: factor out with above + { + List cs = new LinkedList<>(); + vars.forEach(x -> cs.add(smt2t.makeGte(x.toSmt2Formula(smt2t), smt2t.getDefaultBaseValue()))); + cs.add(smt2t.makeGt(r.start.toSmt2Formula(smt2t), r.end.toSmt2Formula(smt2t))); + String smt2 = smt2t.makeAnd(cs); + if (!vars.isEmpty()) + { + smt2 = smt2t.makeExists(vars.stream().map(x -> x.toSmt2Formula(smt2t)).collect(Collectors.toList()), smt2); + } + return smt2t.makeAssert(smt2); + }; + Predicate foo2 = r -> + { + String foo = foo1.apply(r); + + job.debugPrintln("\n[param-core] [WF] Checking WF range interval for " + r + ":\n " + foo); + + return Z3Wrapper.checkSat(job, gpd, foo); + }; + if (foo2.test(srcRange) || foo2.test(destRange)) + { + return false; + } + return true; + } + + public static boolean hasValidForeachVarIndex(Stack> context, RPIndexedRole ir) + { + if (context.isEmpty()) + { + return false; + } + //Set curr = context.peek().keySet().stream().map(k -> k.toString()).collect(Collectors.toSet()); + Set all = context.stream().flatMap(m -> m.keySet().stream().map(k -> k.name)).collect(Collectors.toSet()); // FIXME: awkwardness of RPForeachVar and RPIndexVar + RPInterval ival = ir.intervals.iterator().next(); + return ir.intervals.size() == 1 && ival.isSingleton() + && (ival.start instanceof RPIndexVar) && all.contains(((RPIndexVar) ival.start).name); // N.B. RPIndexVar, not RPForeachVar (FIXME) + } + + @Override + public RPCoreGActionKind getKind() + { + return (RPCoreGActionKind) this.kind; + } + + @Override + public Set getIndexedRoles() + { + Set res = Stream.of(this.src, this.dest).collect(Collectors.toSet()); + this.cases.values().forEach(c -> res.addAll(c.getIndexedRoles())); + return res; + } + + @Override + public RPCoreLType project(RPCoreAstFactory af, //Role r, Set ranges) throws ParamCoreSyntaxException + RPRoleVariant subj, Smt2Translator smt2t) throws RPCoreSyntaxException + { + //LinkedHashMap + LinkedHashMap + projs = new LinkedHashMap<>(); + //for (Entry + for (Entry + e : this.cases.entrySet()) + { + //RPCoreMessage a = e.getKey(); + Message a = e.getKey(); + //projs.put(a, e.getValue().project(af, r, ranges)); + projs.put(a, e.getValue().project(af, subj, smt2t)); + // N.B. local actions directly preserved from globals -- so core-receive also has assertion (cf. ParamGActionTransfer.project, currently no ParamLReceive) + // FIXME: receive assertion projection -- should not be the same as send? + + if (a instanceof MessageSig) + { + for (PayloadElemType pet : //a.pay.elems) + ((MessageSig) a).payload.elems) + { + if (pet instanceof GDelegationType) + { + if (!(pet instanceof RPCoreGDelegationType)) + { + throw new RuntimeException("[rp-core] TODO: " + pet); + } + RPCoreGDelegationType gdt = (RPCoreGDelegationType) pet; // Payload types come from ParamCoreGProtocolDeclTranslator#parsePayload (toMessage) + + // cf. GDelegationElem#project + + //new LProtocolName(); // FIXME: need actual role (not just role name) + } + } + } + // MessageSigName is not delegation // FIXME: cf. "Sync@A" + } + + // "Simple" cases + Role srcName = this.src.getName(); + Role destName = this.dest.getName(); + Role subjName = subj.getName(); + RPInterval srcRange = this.src.getParsedRange(); + RPInterval destRange = this.dest.getParsedRange(); + if (this.kind == RPCoreGActionKind.CROSS_TRANSFER) + { + //if (this.src.getName().equals(r)) + if (srcName.equals(subjName) && subj.intervals.contains(srcRange)) // FIXME: factor out? + { + return af.ParamCoreLCrossChoice(this.dest, RPCoreLActionKind.CROSS_SEND, projs); + } + else if (destName.equals(subjName) && subj.intervals.contains(destRange)) + { + return af.ParamCoreLCrossChoice(this.src, RPCoreLActionKind.CROSS_RECEIVE, projs); + } + } + /*else if (this.kind == RPCoreGActionKind.DOT_TRANSFER) + { + if (srcName.equals(subjName) && subj.intervals.contains(srcRange)) // FIXME: factor out? + { + if (destName.equals(subjName) && subj.intervals.contains(destRange)) // Possible for dot-transfer (src.start != dest.start) -- cf. cross-transfer + { + RPIndexExpr offset = RPIndexFactory.ParamBinIndexExpr(RPBinIndexExpr.Op.Add, + RPIndexFactory.ParamIntVar("_id"), + RPIndexFactory.ParamBinIndexExpr(RPBinIndexExpr.Op.Subt, destRange.start, srcRange.start)); + /*Map tmp = projs.entrySet().stream().collect(Collectors.toMap(Entry::getKey, + p -> new ParamCoreLDotChoice(this.dest, offset, ParamCoreLActionKind.DOT_SEND, + Stream.of(p.getKey()).collect(Collectors.toMap(k -> k, k -> p.getValue()))) + ));* / + Function, LinkedHashMap> foo = e -> + { + LinkedHashMap res = new LinkedHashMap<>(); + res.put(e.getKey(), e.getValue()); + return res; + }; + LinkedHashMap tmp = new LinkedHashMap<>(); + projs.entrySet().forEach(e -> tmp.put(e.getKey(), + new RPCoreLDotChoice(this.dest, offset, RPCoreLActionKind.DOT_SEND, foo.apply(e)))); + RPIndexExpr offset2 = RPIndexFactory.ParamBinIndexExpr(RPBinIndexExpr.Op.Add, + RPIndexFactory.ParamIntVar("_id"), + RPIndexFactory.ParamBinIndexExpr(RPBinIndexExpr.Op.Subt, srcRange.start, destRange.start)); + return af.ParamCoreLDotChoice(this.src, offset2, RPCoreLActionKind.DOT_RECEIVE, tmp); + } + else + { + RPIndexExpr offset = RPIndexFactory.ParamBinIndexExpr(RPBinIndexExpr.Op.Add, + RPIndexFactory.ParamIntVar("_id"), + RPIndexFactory.ParamBinIndexExpr(RPBinIndexExpr.Op.Subt, destRange.start, srcRange.start)); + return af.ParamCoreLDotChoice(this.dest, offset, RPCoreLActionKind.DOT_SEND, projs); + } + } + else if (destName.equals(subjName) && subj.intervals.contains(destRange)) + { + RPIndexExpr offset = RPIndexFactory.ParamBinIndexExpr(RPBinIndexExpr.Op.Add, + RPIndexFactory.ParamIntVar("_id"), + RPIndexFactory.ParamBinIndexExpr(RPBinIndexExpr.Op.Subt, srcRange.start, destRange.start)); + return af.ParamCoreLDotChoice(this.src, offset, RPCoreLActionKind.DOT_RECEIVE, projs); + } + }*/ + else + { + throw new RuntimeException("[param-core] TODO: " + this); + } + + // src name != dest name + //return merge(af, r, ranges, projs); + return merge(af, subj, projs); + } + + // Duplicated from project above + @Override + public RPCoreLType project3(RPCoreAstFactory af, Set roles, Set ivals, RPIndexedRole subj) throws RPCoreSyntaxException + { + LinkedHashMap projs = new LinkedHashMap<>(); + for (Entry e : this.cases.entrySet()) + { + Message a = e.getKey(); + projs.put(a, e.getValue().project3(af, roles, ivals, subj)); + } + + Role srcName = this.src.getName(); + Role destName = this.dest.getName(); + //Role subjName = subj.getName(); + RPInterval srcRange = this.src.getParsedRange(); + RPInterval destRange = this.dest.getParsedRange(); + Set fvars = ivals.stream().map(x -> x.var.toString()).collect(Collectors.toSet()); + if (this.kind == RPCoreGActionKind.CROSS_TRANSFER) + { + if (this.src.equals(subj)) // N.B. subj uses RPIndexVar (not RPForeachVar) -- cf. the invocation of project3 in RPCoreGForeach#project2 + { + //return af.ParamCoreLCrossChoice(this.dest, RPCoreLActionKind.CROSS_SEND, projs); + if (srcRange.start.equals(srcRange.end) //&& srcRange.start instanceof RPIndexVar + && destRange.start.equals(destRange.end) //&& destRange.start instanceof RPIndexVar + ) + { + RPIndexExpr srcStart = srcRange.start; + RPIndexExpr destStart = destRange.start; + //Set tmp = Stream.of(srcStart, destStart).filter(x -> x instanceof RPIndexVar).map(x -> x.toString()).collect(Collectors.toSet()); + String srcTmp = (srcStart instanceof RPIndexVar) ? ((RPIndexVar) srcStart).name : null; + String destTmp = (destStart instanceof RPIndexVar) ? ((RPIndexVar) destStart).name : null; + // FIXME: awkwardness of RPIndexVar and RPForeachVar + Set tmp = Stream.of(srcTmp, destTmp).filter(x -> x != null).collect(Collectors.toSet()); + if (//!tmp.isEmpty() && + roles.contains(destName) && //fvars.contains(srcVar.toString()) && fvars.contains(destVar.toString())) + fvars.containsAll(tmp)) + { + RPIndexExpr upper = (destTmp != null) ? ivals.stream().filter(x -> x.var.name.equals(destTmp)).findFirst().get().start : destStart; + RPIndexExpr lower = (srcTmp != null) ? ivals.stream().filter(x -> x.var.name.equals(srcTmp)).findFirst().get().start : srcStart; + RPIndexExpr destExpr = RPIndexFactory.ParamBinIndexExpr(Op.Add, RPIndexSelf.SELF, + //RPIndexFactory.ParamBinIndexExpr(Op.Subt, destStart, srcStart)); + RPIndexFactory.ParamBinIndexExpr(Op.Subt, upper, lower)); + RPIndexedRole dest = new RPIndexedRole(destName.toString(), Stream.of(new RPInterval(destExpr, destExpr)).collect(Collectors.toSet())); + return af.ParamCoreLCrossChoice(dest, RPCoreLActionKind.CROSS_SEND, projs); + } + else if (!roles.contains(destName) || !(fvars.contains(srcStart.toString()) && fvars.contains(destStart.toString()))) + { + return af.ParamCoreLCrossChoice(this.dest, RPCoreLActionKind.CROSS_SEND, projs); + } + } + else if (!roles.contains(destName) || !(fvars.contains(srcRange.getIndexVars()) && fvars.contains(destRange.getIndexVars()))) + { + return af.ParamCoreLCrossChoice(this.dest, RPCoreLActionKind.CROSS_SEND, projs); + } + // Otherwise try merge (if neither src/dest are subj) + } + else if (this.dest.equals(subj)) + { + if (srcRange.start.equals(srcRange.end) //&& srcRange.start instanceof RPIndexVar + && destRange.start.equals(destRange.end) //&& destRange.start instanceof RPIndexVar) + ) + { + RPIndexExpr srcStart = srcRange.start; + RPIndexExpr destStart = destRange.start; + //Set tmp = Stream.of(srcStart, destStart).filter(x -> x instanceof RPIndexVar).map(x -> x.toString()).collect(Collectors.toSet()); + String srcTmp = (srcStart instanceof RPIndexVar) ? ((RPIndexVar) srcStart).name : null; + String destTmp = (destStart instanceof RPIndexVar) ? ((RPIndexVar) destStart).name : null; + // FIXME: awkwardness of RPIndexVar and RPForeachVar + Set tmp = Stream.of(srcTmp, destTmp).filter(x -> x != null).collect(Collectors.toSet()); + if (//!tmp.isEmpty() && + roles.contains(srcName) && //fvars.contains(srcVar.toString()) && fvars.contains(destVar.toString())) + fvars.containsAll(tmp)) + { + RPIndexExpr upper = (srcTmp != null) ? ivals.stream().filter(x -> x.var.name.equals(srcTmp)).findFirst().get().start : srcStart; + RPIndexExpr lower = (destTmp != null) ? ivals.stream().filter(x -> x.var.name.equals(destTmp)).findFirst().get().start : destStart; + RPIndexExpr srcExpr = RPIndexFactory.ParamBinIndexExpr(Op.Add, RPIndexSelf.SELF, + //RPIndexFactory.ParamBinIndexExpr(Op.Subt, srcStart, destStart)); + RPIndexFactory.ParamBinIndexExpr(Op.Subt, upper, lower)); + RPIndexedRole src = new RPIndexedRole(srcName.toString(), Stream.of(new RPInterval(srcExpr, srcExpr)).collect(Collectors.toSet())); + return af.ParamCoreLCrossChoice(src, RPCoreLActionKind.CROSS_RECEIVE, projs); + } + else if (!roles.contains(srcName) || !(fvars.contains(srcStart.toString()) && fvars.contains(destStart.toString()))) + { + return af.ParamCoreLCrossChoice(this.src, RPCoreLActionKind.CROSS_RECEIVE, projs); + } + } + else if (!roles.contains(srcName) || !(fvars.contains(srcRange.getIndexVars()) && fvars.contains(destRange.getIndexVars()))) + { + return af.ParamCoreLCrossChoice(this.src, RPCoreLActionKind.CROSS_RECEIVE, projs); + } + // Otherwise merge (if neither src/dest are subj) + } + } + else + { + throw new RuntimeException("[param-core] TODO: " + this); + } + + // CROSS_TRANSFER, and subj not sender nor receiver + if (!this.src.equals(subj) && !this.dest.equals(subj)) + { + return merge3(af, subj, projs); + } + else + { + throw new RuntimeException("[rp-core] Projection not defined: " + this + ", " + subj); + } + } + + //private ParamCoreLType merge(ParamCoreAstFactory af, Role r, Set ranges, Map projs) throws ParamCoreSyntaxException + private RPCoreLType merge(RPCoreAstFactory af, RPRoleVariant r, + //Map projs) throws RPCoreSyntaxException + Map projs) throws RPCoreSyntaxException + { + // "Merge" + Set values = new HashSet<>(projs.values()); + /*if (values.size() > 1) + { + throw new RPCoreSyntaxException("[param-core] Cannot project \n" + this + "\n onto " + r + //+ " for " + ranges + + ": cannot merge: " + projs); + }*/ + if (values.size() == 1) // Handles output choices + { + return values.iterator().next(); + } + RPIndexedRole peer = null; + LinkedHashMap cases = new LinkedHashMap<>(); + for (Message m : projs.keySet()) + { + RPCoreLType p = projs.get(m); + if (!(p instanceof RPCoreLCrossChoice)) + { + throw new RPCoreSyntaxException("[param-core] Cannot project \n" + this + "\n onto " + r + ": cannot merge: " + projs); + } + RPCoreLCrossChoice c = (RPCoreLCrossChoice) p; + if (c.kind != RPCoreLActionKind.CROSS_RECEIVE) // FIXME generalise + { + throw new RPCoreSyntaxException("[param-core] Cannot project \n" + this + "\n onto " + r + ": cannot merge: " + projs); + } + if (peer == null) + { + peer = c.role; + } + else if (!c.role.equals(peer)) + { + throw new RPCoreSyntaxException("[param-core] Cannot project \n" + this + "\n onto " + r + ": cannot merge: " + projs); + } + cases.putAll(c.cases); + } + return af.ParamCoreLCrossChoice(peer, RPCoreLActionKind.CROSS_RECEIVE, cases); + } + + // Cf. merge above + private RPCoreLType merge3(RPCoreAstFactory af, RPIndexedRole r, Map projs) throws RPCoreSyntaxException + { + Set values = new HashSet<>(projs.values()); + if (values.size() > 1) + { + throw new RPCoreSyntaxException("[param-core] Cannot project \n" + this + "\n onto " + r + ": cannot merge: " + values); + } + return values.iterator().next(); + } + + @Override + public int hashCode() + { + int hash = 2339; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.src.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreGChoice)) + { + return false; + } + return super.equals(obj) && this.src.equals(((RPCoreGChoice) obj).src); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreGChoice; + } + + @Override + public String toString() + { + return this.src.toString() + this.kind + this.dest + casesToString(); // toString needed? + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGCont.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGCont.java new file mode 100644 index 000000000..4628c3124 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGCont.java @@ -0,0 +1,91 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreCont; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.ast.local.RPCoreLCont; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; + + +public class RPCoreGCont extends RPCoreCont implements RPCoreGType +{ + public static final RPCoreGCont CONT = new RPCoreGCont(); + + private RPCoreGCont() + { + + } + + @Override + public RPCoreGType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreGType) neu; + } + return this; + } + + @Override + public boolean isWellFormed(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t) + { + return true; + } + + @Override + public Set getIndexedRoles() + { + return Collections.emptySet(); + } + + @Override + public RPCoreLType project(RPCoreAstFactory af, RPRoleVariant subj, Smt2Translator smt2t) throws RPCoreSyntaxException + { + return af.ParamCoreLCont(); + } + + // G proj R \vec{C} r[z] + @Override + public RPCoreLType project3(RPCoreAstFactory af, Set roles, Set ivals, RPIndexedRole subj) throws RPCoreSyntaxException + { + return RPCoreLCont.CONT; + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreGCont)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreGCont; + } + + @Override + public int hashCode() + { + return 31*2789; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGEnd.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGEnd.java new file mode 100644 index 000000000..f9b60cfc5 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGEnd.java @@ -0,0 +1,92 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreEnd; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.ast.local.RPCoreLEnd; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; + + +public class RPCoreGEnd extends RPCoreEnd implements RPCoreGType +{ + public static final RPCoreGEnd END = new RPCoreGEnd(); + + private RPCoreGEnd() + { + + } + + @Override + public RPCoreGType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreGType) neu; + } + return this; + } + + @Override + public boolean isWellFormed(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t) + { + return true; + } + + @Override + public Set getIndexedRoles() + { + return Collections.emptySet(); + } + + @Override + //public ParamCoreLEnd project(ParamCoreAstFactory af, Role r, Set ranges) + public RPCoreLType project(RPCoreAstFactory af, RPRoleVariant subj, Smt2Translator smt2t) throws RPCoreSyntaxException + { + return af.ParamCoreLEnd(); + } + + // G proj R \vec{C} r[z] + @Override + public RPCoreLType project3(RPCoreAstFactory af, Set roles, Set ivals, RPIndexedRole subj) throws RPCoreSyntaxException + { + return RPCoreLEnd.END; + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreGEnd)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreGEnd; + } + + @Override + public int hashCode() + { + return 31*2381; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGForeach.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGForeach.java new file mode 100644 index 000000000..dce8cf85b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGForeach.java @@ -0,0 +1,256 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreForeach; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.ast.local.RPCoreLCont; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexFactory; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.ext.go.util.Z3Wrapper; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; + +public class RPCoreGForeach extends RPCoreForeach implements RPCoreGType +{ + public RPCoreGForeach(//Role role, RPForeachVar var, RPIndexExpr start, RPIndexExpr end, + Set roles, Set ivals, + RPCoreGType body, RPCoreGType seq) + { + //super(role, var, start, end, body, seq); + super(roles, ivals, body, seq); + } + + @Override + public RPCoreGType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreGType) neu; + } + else + { + return af.RPCoreGForeach(//this.role, this.param, this.start, this.end, + this.roles, this.ivals, + this.body.subs(af, old, neu), this.seq.subs(af, old, neu)); + } + } + + @Override + public boolean isWellFormed(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t) + { + // CHECKME: interval constraints, nested foreach constraints, etc. -- cf. RPCoreGChoice + Map curr = new HashMap<>(); + this.ivals.forEach(ival -> curr.put(ival.var, ival)); + context.push(curr); + boolean res = this.body.isWellFormed(job, context, gpd, smt2t); + context.pop(); + return res; + } + + @Override + public Set getIndexedRoles() // cf. RPForeachDel#leaveIndexVarCollection (though not currently used) + { + /*RPIndexVar tmp = RPIndexFactory.ParamIntVar(this.param.toString()); + // HACK FIXME: because RPIndexVar and RPForeachVar now distinguished + + Set d = Stream.of(new RPInterval(this.start, this.end)).collect(Collectors.toSet()); + Set var = Stream.of(//new RPInterval(this.param, this.param) + new RPInterval(tmp, tmp) + ).collect(Collectors.toSet()); + Set irs = this.body.getIndexedRoles() + .stream().map( + ir -> ir.intervals.equals(var) + ? new RPIndexedRole(ir.getName().toString(), d) + : ir + ).collect(Collectors.toSet()); + irs.addAll(this.seq.getIndexedRoles());*/ + + Set found = this.body.getIndexedRoles(); + Set done = new HashSet<>(); + Set res = new HashSet<>(); + for (RPAnnotatedInterval ival : this.ivals) + { + RPIndexVar tmp = RPIndexFactory.ParamIndexVar(ival.var.toString()); + // HACK FIXME: because RPIndexVar and RPForeachVar now distinguished -- unify? + + Set var = Stream.of(new RPInterval(tmp, tmp)).collect(Collectors.toSet()); + for (RPIndexedRole ir : found) + { + if (ir.intervals.equals(var)) + { + done.add(ir); + Set d = Stream.of(new RPInterval(ival.start, ival.end)).collect(Collectors.toSet()); + // TODO: multidim intervals (currently singleton set for onedim) + res.add(new RPIndexedRole(ir.getName().toString(), d)); + } + } + } + + found.removeAll(done); + res.addAll(found); + res.addAll(this.seq.getIndexedRoles()); + return res; + } + + // G proj r \vec{D} + @Override + //public ParamCoreLType project(ParamCoreAstFactory af, Role r, Set ranges) throws ParamCoreSyntaxException + public RPCoreLType project(RPCoreAstFactory af, RPRoleVariant subj, Smt2Translator smt2t) throws RPCoreSyntaxException + { + RPCoreLType seq = this.seq.project(af, subj, smt2t); + if (this.roles.contains(subj.getName())) // FIXME: factor out -- cf. RPCoreGChoice#project + { + /*RPIndexVar tmp = RPIndexFactory.ParamIntVar(this.param.toString()); + // HACK FIXME: because RPIndexVar and RPForeachVar now distinguished*/ + + /* // FIXME: subj.intervals was meant for multidim nat intervals, but that should be refactored inside (a single) RPInterval + if (subj.intervals.size() != 1) + { + throw new RuntimeException("TODO: " + ) + }*/ + Set filtered = this.ivals.stream().filter(iv -> subj.intervals.stream().anyMatch(x -> iv.isSame(x))).collect(Collectors.toSet()); + // CHECKME: actual interval inclusion? (vs. "syntactic" equals) -- also RPCoreGChoice#project? + //RPIndexedRole tmp = new RPIndexedRole(subj.getName().toString(), filtered); // FIXME: should be this, but currently RPIndexedRole interval set for multidim nat intervals (but with >1 TODO exception) + RPCoreGForeach tmp = af.RPCoreGForeach(this.roles, this.ivals, body, af.ParamCoreGEnd()); + // CHECKME: should be "end" so that it will be discarded? seq will be substituted for cont in the final "unrolling" of foreach + + RPCoreLType proj = tmp.project2(af, subj.getName(), filtered, smt2t); + return proj.subs(af, RPCoreLCont.CONT, seq); + } + else + { + RPCoreLType body = this.body.project(af, subj, smt2t); + if (body instanceof RPCoreLCont) // Cf. project2, ivals.isEmpty case + { + return seq; + } + else + { + return af.RPCoreLForeach(this.roles, this.ivals, body, seq); + } + } + } + + // G proj r \vec{C} + private RPCoreLType project2(RPCoreAstFactory af, Role name, Set ivals, Smt2Translator smt2t) throws RPCoreSyntaxException + { + /*RPInterval v = new RPInterval(this.start, this.end); + if (subj.intervals.contains(v)) + { + RPRoleVariant indexed = new RPRoleVariant(subj.getName().toString(), + Stream.of(//new RPInterval(this.param, this.param)) + new RPInterval(tmp, tmp)).collect(Collectors.toSet()), Collections.emptySet()); + RPCoreLType body = proj.project(af, indexed); + return body.subs(af, RPCoreLEnd.END, seq); + } + else + { + // ...else substitute cont for end in body ? + throw new RuntimeException("Shouldn't get in here? " + this + ", " + subj); + }*/ + if (ivals.isEmpty()) + { + return RPCoreLCont.CONT; + } + + /*RPAnnotatedInterval max = ivals.stream() + .filter(x -> ivals.stream().filter(y -> !x.equals(y)) + .allMatch(y -> ((RPIndexVal) x.start).gtEq(((RPIndexVal) y.start)))) // FIXME: general index expressions + .findFirst().get(); + // FIXME: non-RPIndexInt start exprs for nat intervals -- FIXME: generalised interval comparison (multidim)*/ + + RPAnnotatedInterval max = null; + List vars = ivals.stream().flatMap(x -> x.getIndexVars().stream().map(y -> y.toSmt2Formula(smt2t))).distinct().collect(Collectors.toList()); + if (ivals.size() > 1) + { + for (RPAnnotatedInterval ival : ivals) + { + List cs = new LinkedList<>(); + cs.addAll(ivals.stream().filter(x -> !x.equals(ival)).map(x -> smt2t.makeLte(x.start.toSmt2Formula(smt2t), ival.start.toSmt2Formula(smt2t))).collect(Collectors.toList())); + String smt2 = smt2t.makeAnd(cs); + if (!vars.isEmpty()) + { + smt2 = smt2t.makeImplies( + smt2t.makeAnd(vars.stream().map(x -> smt2t.makeGte(x, smt2t.getDefaultBaseValue())).collect(Collectors.toList())), smt2); + smt2 = smt2t.makeForall(vars, smt2); + } + smt2 = smt2t.makeAssert(smt2); + if (Z3Wrapper.checkSat(smt2t.job, smt2t.global, smt2)) + { + max = ival; + break; + } + } + if (max == null) + { + throw new RuntimeException("Shouldn't get in here: " + ivals); + } + } + else + { + max = ivals.iterator().next(); + } + + RPIndexVar var = RPIndexFactory.ParamIndexVar(max.var.toString()); // N.B. not RPForeachVar -- occurrences in body are parsed as RPIndexVar, not RPForeachVar + RPCoreLType proj = this.body.project3(af, this.roles, this.ivals, + new RPIndexedRole(name.toString(), Stream.of(new RPInterval(var, var)).collect(Collectors.toSet()))); + Set tmp = new HashSet<>(ivals); + tmp.remove(max); + return proj.subs(af, RPCoreLCont.CONT, project2(af, name, tmp, smt2t)); + } + + // G proj R \vec{C} r[z] + @Override + public RPCoreLType project3(RPCoreAstFactory af, Set roles, Set ivals, RPIndexedRole subj) throws RPCoreSyntaxException + { + return af.RPCoreLForeach(this.roles, this.ivals, this.body.project3(af, roles, ivals, subj), this.seq.project3(af, roles, ivals, subj)); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreGForeach)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreGForeach; + } + + @Override + public int hashCode() + { + int hash = 4273; + hash = 31 * hash + super.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGMultiChoices.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGMultiChoices.java new file mode 100644 index 000000000..6801f5cff --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGMultiChoices.java @@ -0,0 +1,287 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Stack; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreChoice; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.ast.local.RPCoreLActionKind; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.type.Message; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; + +@Deprecated +public class RPCoreGMultiChoices extends RPCoreChoice implements RPCoreGType +{ + public final RPIndexedRole src; // Gives the Scribble choices-subj range // Cf. ParamCoreGChoice singleton src + public final RPIndexVar var; + + public final RPIndexedRole dest; // this.dest == super.role -- arbitrary? + + public RPCoreGMultiChoices(RPIndexedRole src, RPIndexVar var, RPIndexedRole dest, //List cases, + List cases, + RPCoreGType cont) + { + //super(dest, ParamCoreGActionKind.CROSS_TRANSFER, cases.stream().collect(Collectors.toMap(c -> c, c -> cont))); // FIXME + super(dest, RPCoreGActionKind.CROSS_TRANSFER, foo(cases, cont)); // FIXME + this.src = src; + this.dest = dest; + this.var = var; + } + + private static //LinkedHashMap foo(List cases, RPCoreGType cont) + LinkedHashMap foo(List cases, RPCoreGType cont) + { + //LinkedHashMap + LinkedHashMap + tmp = new LinkedHashMap<>(); + cases.forEach(c -> tmp.put(c, cont)); + return tmp; + } + + @Override + public boolean isWellFormed(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t) + { + // src (i.e., choice subj) range size=1 for non-unary choices enforced by ParamScribble.g syntax + // Directed choice check by ParamCoreGProtocolDeclTranslator ensures all dests (including ranges) are (syntactically) the same + + /*ParamRange srcRange = src.getParsedRange(); + ParamRange destRange = dest.getParsedRange(); + Set vars = Stream.of(srcRange, destRange).flatMap(r -> r.getVars().stream()).collect(Collectors.toSet()); + + Function foo1 = r -> // FIXME: factor out with above + "(assert " + + (vars.isEmpty() ? "" : "(exists (" + vars.stream().map(v -> "(" + v.name + " Int)").collect(Collectors.joining(" ")) + ") (and (and") + + vars.stream().map(v -> " (>= " + v + " 1)").collect(Collectors.joining("")) // FIXME: lower bound constant -- replace by global invariant + + (vars.isEmpty() ? "" : ")") + + " (> " + r.start.toSmt2Formula() + " " + r.end.toSmt2Formula() + ")" + + (vars.isEmpty() ? "" : "))") + + ")"; + Predicate foo2 = r -> + { + String foo = foo1.apply(r); + + job.debugPrintln("\n[param-core] [WF] Checking WF range interval for " + r + ":\n " + foo); + + return Z3Wrapper.checkSat(job, gpd, foo); + }; + if (foo2.test(srcRange) || foo2.test(destRange)) + { + return false; + } + + + String bar = "(assert " + + (vars.isEmpty() ? "" : "(exists (" + vars.stream().map(v -> "(" + v.name + " Int)").collect(Collectors.joining(" ")) + ") (and ") + + vars.stream().map(v -> " (>= " + v + " 1)").collect(Collectors.joining("")) // FIXME: lower bound constant -- replace by global invariant + + "(not (= (- " + srcRange.end.toSmt2Formula() + " " + srcRange.start.toSmt2Formula() + ") 0))" + + (vars.isEmpty() ? "" : "))") + + ")"; + + job.debugPrintln("\n[param-core] [WF] Checking singleton choice-subk for " + this.src + ":\n " + bar); + + if (Z3Wrapper.checkSat(job, gpd, bar)) + { + return false; + } + + + if (this.src.getName().equals(this.dest.getName())) + { + if (this.kind == ParamCoreGActionKind.CROSS_TRANSFER) + { + String smt2 = "(assert (exists ((foobartmp Int)"; // FIXME: factor out + smt2 += vars.stream().map(v -> " (" + v.name + " Int)").collect(Collectors.joining("")); + smt2 += ") (and"; + smt2 += vars.isEmpty() ? "" : vars.stream().map(v -> " (>= " + v + " 1)").collect(Collectors.joining("")); // FIXME: lower bound constant -- replace by global invariant + smt2 += Stream.of(srcRange, destRange) + .map(r -> " (>= foobartmp " + r.start.toSmt2Formula() + ") (<= foobartmp " + r.end.toSmt2Formula() + ")") + .collect(Collectors.joining()); + smt2 += ")))"; + + job.debugPrintln("\n[param-core] [WF] Checking non-overlapping ranges for " + this.src.getName() + ":\n " + smt2); + + if (Z3Wrapper.checkSat(job, gpd, smt2)) + { + return false; + } + // CHECKME: projection cases for rolename self-comm but non-overlapping intervals + } + } + + if (this.kind == ParamCoreGActionKind.DOT_TRANSFER) + { + String smt2 = "(assert" + + (vars.isEmpty() ? "" : " (forall (" + vars.stream().map(v -> "(" + v + " Int)").collect(Collectors.joining(" "))) + ") " + + "(and (= (- " + srcRange.end.toSmt2Formula() + " " + srcRange.start.toSmt2Formula() + ") (- " + + destRange.end.toSmt2Formula() + " " + destRange.start.toSmt2Formula() + "))" + + (!this.src.getName().equals(this.dest.getName()) ? "" : + " (not (= " + srcRange.start.toSmt2Formula() + " " + destRange.start.toSmt2Formula() + "))") + + ")" + + (vars.isEmpty() ? "" : ")") + + ")"; + + job.debugPrintln("\n[param-core] [WF] Checking dot-range alignment between " + srcRange + " and " + destRange + ":\n " + smt2); + + if (!Z3Wrapper.checkSat(job, gpd, smt2)) + { + return false; + } + }*/ + + return true; + } + + @Override + public RPCoreGActionKind getKind() + { + return (RPCoreGActionKind) this.kind; + } + + @Override + public Set getIndexedRoles() + { + Set res = Stream.of(this.src, this.dest).collect(Collectors.toSet()); + res.addAll(this.cases.values().iterator().next().getIndexedRoles()); + return res; + } + + @Override + //public ParamCoreLType project(ParamCoreAstFactory af, Role r, Set ranges) throws ParamCoreSyntaxException + public RPCoreLType project(RPCoreAstFactory af, RPRoleVariant subj, Smt2Translator smt2t) throws RPCoreSyntaxException + { + if (this.kind != RPCoreGActionKind.CROSS_TRANSFER) + { + throw new RuntimeException("[param-core] TODO: " + this); + } + + //LinkedHashMap projs + LinkedHashMap projs + = new LinkedHashMap<>(); + //for (Entry + for (Entry + e : this.cases.entrySet()) + { + //RPCoreMessage a + Message a + = e.getKey(); + //projs.put(a, e.getValue().project(af, r, ranges)); + projs.put(a, e.getValue().project(af, subj, smt2t)); + // N.B. local actions directly preserved from globals -- so core-receive also has assertion (cf. ParamGActionTransfer.project, currently no ParamLReceive) + // FIXME: receive assertion projection -- should not be the same as send? + } + + // FIXME: same condition as merge (factor out) // FIXME: no, already syntactic singleton continuation already checked by ParamCoreGProtocolDeclTranslator? + Set values = new HashSet<>(projs.values()); + if (values.size() > 1) + { + throw new RPCoreSyntaxException("[param-core] Cannot project \n" + this + "\n onto " + subj + //+ " for " + ranges + + ": cannot merge for: " + projs.keySet()); + } + + // "Simple" cases -- same projection as ParamCoreGChoice, i.e., same local types? -- index var redundant, apart from "syntactic consistency" for subsequent message actions? (i.e., only for Scribble syntax?) + if (this.src.getName().equals(subj.getName()) && subj.intervals.contains(this.src.getParsedRange())) // FIXME: factor out? + { + return af.ParamCoreLCrossChoice(this.dest, RPCoreLActionKind.CROSS_SEND, projs); + } + else if (this.dest.getName().equals(subj.getName()) && subj.intervals.contains(this.dest.getParsedRange())) + { + /*return af.ParamCoreLMultiChoices(this.src, this.var, projs.keySet().stream().collect(Collectors.toList()), + values.iterator().next());*/ + throw new RuntimeException("[rp-core] Shouldn't get in here: " + this); + } + + // src name != dest name + //return merge(af, r, ranges, projs); + return merge(af, subj, projs); + } + + // G proj R \vec{C} r[z] + @Override + public RPCoreLType project3(RPCoreAstFactory af, Set roles, Set ivals, RPIndexedRole subj) throws RPCoreSyntaxException + { + throw new RuntimeException("Shouldn't get in here: " + this); + } + + //private ParamCoreLType merge(ParamCoreAstFactory af, Role r, Set ranges, Map projs) throws ParamCoreSyntaxException + private RPCoreLType merge(RPCoreAstFactory af, RPRoleVariant r, //Map projs) throws RPCoreSyntaxException + Map projs) throws RPCoreSyntaxException + { + // "Merge" + Set values = new HashSet<>(projs.values()); + if (values.size() > 1) + { + throw new RPCoreSyntaxException("[param-core] Cannot project \n" + this + "\n onto " + r + //+ " for " + ranges + + ": cannot merge for: " + projs.keySet()); + } + + return values.iterator().next(); + } + + @Override + public String toString() + { + RPInterval r = this.src.getParsedRange(); + return this.src.getName() + "[" + this.var + ":" + r.start + ".." + r.end + "]" + + this.kind + "*" + this.dest + casesToString(); // toString needed? + } + + @Override + public int hashCode() + { + int hash = 2339; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.src.hashCode(); + hash = 31 * hash + this.var.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreGMultiChoices)) + { + return false; + } + RPCoreGMultiChoices them = (RPCoreGMultiChoices) obj; + return super.equals(obj) // Does canEquals + && this.src.equals(them.src) && this.var.equals(them.var); + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreGMultiChoices; + } + + @Override + public RPCoreGType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + throw new RuntimeException("TODO:"); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGProtocolDeclTranslator.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGProtocolDeclTranslator.java new file mode 100644 index 000000000..6872b3ace --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGProtocolDeclTranslator.java @@ -0,0 +1,672 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.ast.global.GChoice; +import org.scribble.ast.global.GContinue; +import org.scribble.ast.global.GInteractionNode; +import org.scribble.ast.global.GMessageTransfer; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ast.global.GProtocolDef; +import org.scribble.ast.global.GRecursion; +import org.scribble.ast.global.GSimpleInteractionNode; +import org.scribble.ast.name.simple.RecVarNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.global.GProtocolDefDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.global.RPGCrossMessageTransfer; +import org.scribble.ext.go.ast.global.RPGDotMessageTransfer; +import org.scribble.ext.go.ast.global.RPGForeach; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.main.Job; +import org.scribble.type.Message; +import org.scribble.type.kind.RecVarKind; +import org.scribble.type.name.DataType; +import org.scribble.type.name.RecVar; + +public class RPCoreGProtocolDeclTranslator +{ + public static final DataType UNIT_DATATYPE = new DataType("_Unit"); // FIXME: move + + private final Job job; + private final RPCoreAstFactory af; + + private static int recCounter = 1; + + @SuppressWarnings("unused") // Disabling this would make finding target state chan name of P1:P2@v easier (but not actually currently done) + private static String makeFreshRecVarName() + { + return "_X" + RPCoreGProtocolDeclTranslator.recCounter++; + } + + public RPCoreGProtocolDeclTranslator(Job job, RPCoreAstFactory af) + { + this.job = job; + this.af = af; + } + + public RPCoreGType translate(GProtocolDecl gpd) throws RPCoreSyntaxException + { + GProtocolDef inlined = ((GProtocolDefDel) gpd.def.del()).getInlinedProtocolDef(); + return parseSeq(inlined.getBlock().getInteractionSeq().getInteractions(), new HashMap<>(), false, false); + } + + // List because subList is useful for parsing the continuation + private RPCoreGType parseSeq(List is, Map rvs, + boolean checkChoiceGuard, boolean checkRecGuard) throws RPCoreSyntaxException + { + if (is.isEmpty()) + { + return this.af.ParamCoreGEnd(); + } + + GInteractionNode first = is.get(0); + if (first instanceof GSimpleInteractionNode && !(first instanceof GContinue)) + { + if (first instanceof GMessageTransfer) + { + return parseGMessageTransfer(is, rvs, (GMessageTransfer) first); + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + first); + } + } + else + { + if (checkChoiceGuard) // No "flattening" of nested choices not allowed? + { + throw new RPCoreSyntaxException(first.getSource(), "[rp-core] Unguarded in choice case: " + first); + } + if (!(first instanceof RPGForeach) && is.size() > 1) // Using Scribble sequencing for foreach continuation + { + throw new RPCoreSyntaxException(is.get(1).getSource(), "[rp-core] Bad sequential composition after: " + first); + } + + if (first instanceof GChoice) + { + /*if (first instanceof RPGMultiChoices) + { + return parseParamGMultiChoices(rvs, checkRecGuard, (RPGMultiChoices) first); + } + else*/ // GChoice or ParamGChoice + { + return parseGChoice(rvs, checkRecGuard, (GChoice) first); + } + } + else if (first instanceof GRecursion) + { + return parseGRecursion(rvs, checkChoiceGuard, (GRecursion) first); + } + else if (first instanceof GContinue) + { + return parseGContinue(rvs, checkRecGuard, (GContinue) first); + } + else if (first instanceof RPGForeach) + { + Map tmp = new HashMap<>(rvs); + RPCoreGType seq = parseSeq(is.subList(1, is.size()), tmp, false, false); // CHECKME: false guards + return parseRPGForeach(rvs, checkRecGuard, (RPGForeach) first, seq); + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + first); + } + } + } + + private RPCoreGType parseGChoice(Map rvs, + boolean checkRecGuard, GChoice gc) throws RPCoreSyntaxException + { + List children = new LinkedList<>(); + for (GProtocolBlock b : gc.getBlocks()) + { + children.add(parseSeq(b.getInteractionSeq().getInteractions(), rvs, true, checkRecGuard)); // Check cases are guarded + } + + RPCoreGActionKind kind = null; + RPIndexedRole src = null; + RPIndexedRole dest = null; + //LinkedHashMap + LinkedHashMap + cases = new LinkedHashMap<>(); + for (RPCoreGType c : children) + { + // Because all cases should be action guards (unary choices) + if (!(c instanceof RPCoreGChoice)) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + c); + } + RPCoreGChoice tmp = (RPCoreGChoice) c; + if (tmp.cases.size() > 1) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + c); + } + + if (src == null) + { + kind = tmp.getKind(); + src = tmp.src; + dest = tmp.dest; + } + else if (!kind.equals(tmp.kind)) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + gc + ", " + kind + ", " + tmp.kind); + } + else if (!src.equals(tmp.src) || !dest.equals(tmp.dest)) + { + throw new RPCoreSyntaxException(gc.getSource(), + "[rp-core] Non-directed choice not supported: " + gc + ", " + src + ", " + tmp.src + ", " + dest + ", " + tmp.dest); + } + + // "Flatten" nested choices (already checked they are guarded) -- Scribble choice subjects ignored + for //(Entry + (Entry + e : tmp.cases.entrySet()) + { + //RPCoreMessage k = e.getKey(); + Message k = e.getKey(); + if (cases.keySet().stream().anyMatch(x -> //x.op.equals(k.op))) + x.equals(k))) + { + throw new RPCoreSyntaxException(gc.getSource(), + "[rp-core] Non-deterministic actions not supported: " + k); + } + cases.put(k, e.getValue()); + } + } + + return this.af.ParamCoreGChoice(src, kind, dest, cases); + } + + /*private RPCoreGMultiChoices parseGMultiChoicesTransfer(List is, Map rvs) throws RPCoreSyntaxException + { + GInteractionNode in = is.get(0); + if (!(in instanceof RPGMultiChoicesTransfer)) + { + throw new RPCoreSyntaxException(in.getSource(), "[rp-core] Expected GMultiChoicesTransfer: " + in.getClass()); + } + + RPGMultiChoicesTransfer gmt = (RPGMultiChoicesTransfer) in; + RPCoreMessage a = this.af.ParamCoreAction(parseOp(gmt), parsePayload(gmt)); + + String srcName = parseSourceRole(gmt); + String destName = parseDestinationRole(gmt); + RPIndexedRole src = af.ParamRole(srcName, new RPInterval(gmt.var, gmt.var)); // HACK var -- multichoices needs src range (e.g., projection), but multichoicestransfer doesn't + RPIndexedRole dest = af.ParamRole(destName, new RPInterval(gmt.destRangeStart, gmt.destRangeEnd)); + + RPCoreGType cont = parseSeq(is.subList(1, is.size()), rvs, false, false); // Subseqeuent choice/rec is guarded by (at least) this action + return this.af.ParamCoreGMultiChoices(src, gmt.var, dest, Stream.of(a).collect(Collectors.toList()), cont); + } + + // FIXME: factor out with parseGChoice + private RPCoreGType parseParamGMultiChoices(Map rvs, + boolean checkRecGuard, RPGMultiChoices gc) throws RPCoreSyntaxException + { + List children = new LinkedList<>(); + for (GProtocolBlock b : gc.getBlocks()) + { + children.add(parseGMultiChoicesTransfer(b.getInteractionSeq().getInteractions(), rvs)); // Check cases are guarded + } + + RPCoreGActionKind kind = null; + RPIndexedRole src = null; + RPIndexedRole dest = null; + LinkedHashMap cases = new LinkedHashMap<>(); + for (RPCoreGMultiChoices c : children) + { + RPCoreGMultiChoices tmp = (RPCoreGMultiChoices) c; + if (tmp.cases.size() > 1) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + c); + } + + if (src == null) + { + kind = tmp.getKind(); + src = tmp.src; + dest = tmp.dest; + } + else if (!kind.equals(tmp.kind)) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + gc + ", " + kind + ", " + tmp.kind); + } + else if (!src.equals(tmp.src) || !dest.equals(tmp.dest)) + { + throw new RPCoreSyntaxException(gc.getSource(), + "[rp-core] Non-directed choice not supported: " + gc + ", " + src + ", " + tmp.src + ", " + dest + ", " + tmp.dest); + } + + // "Flatten" nested choices (already checked they are guarded) -- Scribble choice subjects ignored + for (Entry e : tmp.cases.entrySet()) + { + RPCoreMessage k = e.getKey(); + if (cases.keySet().stream().anyMatch(x -> x.op.equals(k.op))) + { + throw new RPCoreSyntaxException(gc.getSource(), + "[rp-core] Non-deterministic actions not supported: " + k.op); + } + cases.put(k, e.getValue()); + } + } + + if (new HashSet<>(cases.values()).size() > 1) + { + throw new RPCoreSyntaxException(gc.getSource(), + "[rp-core] Continuations not syntactically equal: " + cases.values()); + } + + return this.af.ParamCoreGMultiChoices( + //src, + new RPIndexedRole(gc.subj.toString(), Stream.of(new RPInterval(gc.start, gc.end)).collect(Collectors.toSet())), + gc.var, dest, cases.keySet().stream().collect(Collectors.toList()), cases.values().iterator().next()); + }*/ + + private RPCoreGType parseGRecursion(Map rvs, + boolean checkChoiceGuard, GRecursion gr) throws RPCoreSyntaxException + { + RecVar recvar = gr.recvar.toName(); + if (recvar.toString().contains("__")) // HACK: "inlined proto rec var" + { + String name = //makeFreshRecVarName(); + recvar.toString(); // FIXME HACK to support state lookup for delegation via inlined protocol name -- cf. RPCoreSTStateChanApiBuilder#getPayloadElemTypeName + RecVarNode rvn = (RecVarNode) ((RPAstFactory) this.job.af).SimpleNameNode(null, RecVarKind.KIND, name); + rvs.put(recvar, rvn.toName()); + recvar = rvn.toName(); + } + RPCoreGType body = parseSeq(gr.getBlock().getInteractionSeq().getInteractions(), rvs, checkChoiceGuard, true); // Check rec body is guarded + + return this.af.ParamCoreGRec(recvar, body); + } + + private RPCoreGType parseGContinue(Map rvs, boolean checkRecGuard, GContinue gc) + throws RPCoreSyntaxException + { + if (checkRecGuard) + { + throw new RPCoreSyntaxException(gc.getSource(), "[rp-core] Unguarded in recursion: " + gc); // FIXME: too conservative, e.g., rec X . A -> B . rec Y . X + } + RecVar recvar = gc.recvar.toName(); + if (rvs.containsKey(recvar)) + { + recvar = rvs.get(recvar); + } + return this.af.ParamCoreGRecVar(recvar); + } + + // FIXME: need "cont"? + private RPCoreGForeach parseRPGForeach(Map rvs, boolean checkRecGuard, RPGForeach gf, RPCoreGType seq) throws RPCoreSyntaxException + { + RPCoreGType body = parseSeq(gf.getBlock().getInteractionSeq().getInteractions(), Collections.emptyMap(), false, true); + body = body.subs(af, RPCoreGEnd.END, RPCoreGCont.CONT); + Set ivals = IntStream.range(0, gf.params.size()) + .mapToObj(i -> new RPAnnotatedInterval(gf.params.get(i), gf.starts.get(i), gf.ends.get(i))).collect(Collectors.toSet()); + return this.af.RPCoreGForeach(//gf.subj.toName(), gf.param, gf.start, gf.end, + gf.subjs.stream().map(r -> r.toName()).collect(Collectors.toSet()), ivals, + // FIXME: generalised foreach sig in source AST + body, seq); + } + + // Parses message interactions as unary choices + private RPCoreGChoice parseGMessageTransfer(List is, Map rvs, GMessageTransfer gmt) throws RPCoreSyntaxException + { + //RPCoreMessage a = this.af.ParamCoreAction(parseOp(gmt), parsePayload(gmt)); + Message a = gmt.msg.toMessage(); + if (a.getId().isOp()) // a instanceof MessageSig + { + /*if (((MessageSig) a).payload.elems.stream().anyMatch(pt -> pt instanceof GDelegationType)) // OK: main work is in API gen + { + throw new RuntimeException("[rp-core] TODO: delegation: " + a); + }*/ + } + String srcName = parseSourceRole(gmt); + String destName = parseDestinationRole(gmt); + RPCoreGActionKind kind; + RPIndexedRole src; + RPIndexedRole dest; + if (gmt instanceof RPGCrossMessageTransfer) + { + RPGCrossMessageTransfer cross = (RPGCrossMessageTransfer) gmt; + kind = RPCoreGActionKind.CROSS_TRANSFER; + /*src = af.ParamRole(srcName, new ParamRange(cross.srcRangeStart.toName(), cross.srcRangeEnd.toName())); + dest = af.ParamRole(destName, new ParamRange(cross.destRangeStart.toName(), cross.destRangeEnd.toName()));*/ + src = af.ParamRole(srcName, new RPInterval(cross.srcRangeStart, cross.srcRangeEnd)); + dest = af.ParamRole(destName, new RPInterval(cross.destRangeStart, cross.destRangeEnd)); + } + else if (gmt instanceof RPGDotMessageTransfer) + { + RPGDotMessageTransfer dot = (RPGDotMessageTransfer) gmt; + kind = RPCoreGActionKind.DOT_TRANSFER; + /*src = af.ParamRole(srcName, new ParamRange(dot.srcRangeStart.toName(), dot.srcRangeEnd.toName())); + dest = af.ParamRole(destName, new ParamRange(dot.destRangeStart.toName(), dot.destRangeEnd.toName()));*/ + src = af.ParamRole(srcName, new RPInterval(dot.srcRangeStart, dot.srcRangeEnd)); + dest = af.ParamRole(destName, new RPInterval(dot.destRangeStart, dot.destRangeEnd)); + } + else + { + /*src = af.ParamRole(srcName, 1, 1); + dest = af.ParamRole(destName, 1, 1);*/ + throw new RPCoreSyntaxException(gmt.getSource(), "[rp-core] Not supported: " + gmt.getClass() + "\n " + gmt); + } + return parseGSimpleInteractionNode(is, rvs, src, kind, a, dest); + } + + // Duplicated from parseGMessageTransfer (MessageTransfer and ConnectionAction have no common + + private RPCoreGChoice parseGSimpleInteractionNode( + List is, Map rvs, + RPIndexedRole src, RPCoreGActionKind kind, //RPCoreMessage a, + Message a, + RPIndexedRole dest) throws RPCoreSyntaxException + { + if (src.equals(dest)) + { + throw new RuntimeException("[rp-core] Shouldn't get in here (self-communication): " + src + ", " + dest); + } + + RPCoreGType cont = parseSeq(is.subList(1, is.size()), rvs, false, false); // Subseqeuent choice/rec is guarded by (at least) this action + //LinkedHashMap + LinkedHashMap + tmp = new LinkedHashMap<>(); + tmp.put(a, cont); + return this.af.ParamCoreGChoice(src, kind, dest, tmp); + //Stream.of(a).collect(Collectors.toMap(x -> x, x -> cont))); + } + + /*private Op parseOp(GMessageTransfer gmt) throws RPCoreSyntaxException + { + return parseOp(gmt.msg); + } + + private Op parseOp(MessageNode mn) throws RPCoreSyntaxException + { + if (!mn.isMessageSigNode()) + { + throw new RPCoreSyntaxException(mn.getSource(), " [rp-core] Message sig names not supported: " + mn); // TODO: MessageSigName + } + MessageSigNode msn = ((MessageSigNode) mn); + return msn.op.toName(); + } + + private Payload parsePayload(GMessageTransfer gmt) throws RPCoreSyntaxException + { + return parsePayload(gmt.msg); + } + + private Payload parsePayload(MessageNode mn) throws RPCoreSyntaxException + { + if (!mn.isMessageSigNode()) + { + throw new RPCoreSyntaxException(mn.getSource(), " [rp-core] Message sig names not supported: " + mn); // TODO: MessageSigName + } + return ((MessageSigNode) mn).toMessage().payload; + }*/ + + private String parseSourceRole(GMessageTransfer gmt) + { + return parseSourceRole(gmt.src); + } + + private String parseSourceRole(RoleNode rn) + { + return rn.toString(); + } + + private String parseDestinationRole(GMessageTransfer gmt) throws RPCoreSyntaxException + { + if (gmt.getDestinations().size() > 1) + { + throw new RPCoreSyntaxException(gmt.getSource(), " [TODO] Multicast not supported: " + gmt); + } + return parseDestinationRole(gmt.getDestinations().get(0)); + } + + private String parseDestinationRole(RoleNode rn) throws RPCoreSyntaxException + { + return rn.toString(); + } + + + + + + + + + + + /* + // Mostly duplicated from parseGMessageTransfer, but GMessageTransfer/GConnect have no useful base class + private ParamCoreGConnect parseGConnect(GConnect gc) throws F17Exception + { + Role src = gc.src.toName(); + Role dest = gc.dest.toName(); + if (!gc.msg.isMessageSigNode()) + { + throw new F17SyntaxException(gc.msg.getSource(), " [f17] Message kind not supported: " + gc.msg); + } + MessageSigNode msn = ((MessageSigNode) gc.msg); + Op op = msn.op.toName(); + Payload pay = null; + if (msn.payloads.getElements().isEmpty()) + { + pay = Payload.EMPTY_PAYLOAD; + } + else + { + String tmp = msn.payloads.getElements().get(0).toString().trim(); + int i = tmp.indexOf('@'); + if (i != -1) + { + throw new F17Exception("[f17] Delegation not supported: " + tmp); + } + else + { + pay = msn.payloads.toPayload(); + } + } + return this.factory.GConnect(src, dest, op, pay); + } + */ + + /*private ParamCoreGType parseSeq(JobContext jc, ModuleContext mc, List is, + boolean checkChoiceGuard, boolean checkRecGuard) throws F17Exception + { + //List is = block.getInteractionSeq().getInteractions(); + if (is.isEmpty()) + { + return this.factory.GEnd(); + } + + GInteractionNode first = is.get(0); + if (first instanceof GSimpleInteractionNode && !(first instanceof GContinue)) + { + if (first instanceof GMessageTransfer) + { + ParamCoreGMessageTransfer gmt = parseGMessageTransfer((GMessageTransfer) first); + ParamCoreGType cont = parseSeq(jc, mc, is.subList(1, is.size()), false, false); + Map cases = new HashMap<>(); + cases.put(gmt, cont); + return this.factory.GChoice(cases); + } + else if (first instanceof GConnect) + { + ParamCoreGConnect gc = parseGConnect((GConnect) first); + ParamCoreGType cont = parseSeq(jc, mc, is.subList(1, is.size()), false, false); + Map cases = new HashMap<>(); + cases.put(gc, cont); + return this.factory.GChoice(cases); + } + else if (first instanceof GDisconnect) + { + F17GDisconnect gdc = parseGDisconnect((GDisconnect) first); + ParamCoreGType cont = parseSeq(jc, mc, is.subList(1, is.size()), false, false); + Map cases = new HashMap<>(); + cases.put(gdc, cont); + return this.factory.GChoice(cases); + } + else + { + throw new RuntimeException("[f17] Shouldn't get in here: " + first); + } + } + else + { + if (checkChoiceGuard) + { + throw new F17SyntaxException(first.getSource(), "[f17] Unguarded in choice case: " + first); + } + if (is.size() > 1) + { + throw new F17SyntaxException(is.get(1).getSource(), "[f17] Bad sequential composition after: " + first); + } + + if (first instanceof GChoice) + { + /*if (checkRecGuard) + { + throw new F17Exception(first.getSource(), "[f17] Unguarded in choice case (2): " + first); + }* / + + GChoice gc = (GChoice) first; + List parsed = new LinkedList<>(); + for (GProtocolBlock b : gc.getBlocks()) + { + parsed.add(parseSeq(jc, mc, b.getInteractionSeq().getInteractions(), true, checkRecGuard)); // "Directly" nested choice will still return a GlobalSend (which is really a choice; uniform global choice constructor is convenient) + } + Map cases = new HashMap<>(); + for (ParamCoreGType p : parsed) + { + if (!(p instanceof ParamCoreGChoice)) + { + throw new RuntimeException("[f17] Shouldn't get in here: " + p); + } + ParamCoreGChoice tmp = (ParamCoreGChoice) p; + //tmp.cases.entrySet().forEach((e) -> cases.put(e.getKey(), e.getValue())); + for (Entry e : tmp.cases.entrySet()) + { + ParamCoreGAction k = e.getKey(); + if (k.isMessageAction()) + { + if (cases.keySet().stream().anyMatch((x) -> + x.isMessageAction() && ((F17MessageAction) k).getOp().equals(((F17MessageAction) x).getOp()))) + { + throw new F17SyntaxException("[f17] Non-determinism (" + e.getKey() + ") not supported: " + gc); + } + } + cases.put(k, e.getValue()); + } + } + return this.factory.GChoice(cases); + } + else if (first instanceof GRecursion) + { + GRecursion gr = (GRecursion) first; + RecVar recvar = gr.recvar.toName(); + ParamCoreGType body = parseSeq(jc, mc, gr.getBlock().getInteractionSeq().getInteractions(), checkChoiceGuard, true); + return new ParamCoreGRec(recvar, body); + } + else if (first instanceof GContinue) + { + if (checkRecGuard) + { + throw new F17SyntaxException(first.getSource(), "[f17] Unguarded in recursion: " + first); // FIXME: conservative, e.g., rec X . A -> B . rec Y . X + } + + return this.factory.GRecVar(((GContinue) first).recvar.toName()); + } + else + { + throw new RuntimeException("[f17] Shouldn't get in here: " + first); + } + } + } + + private ParamCoreGMessageTransfer parseGMessageTransfer(GMessageTransfer gmt) throws F17Exception + { + Role src = gmt.src.toName(); + if (gmt.getDestinations().size() > 1) + { + throw new F17Exception(gmt.getSource(), " [TODO] Multicast not supported: " + gmt); + } + Role dest = gmt.getDestinations().get(0).toName(); + if (!gmt.msg.isMessageSigNode()) + { + throw new F17SyntaxException(gmt.msg.getSource(), " [f17] Not supported: " + gmt.msg); // TODO: MessageSigName + } + MessageSigNode msn = ((MessageSigNode) gmt.msg); + Op op = msn.op.toName(); + Payload pay = null; + if (msn.payloads.getElements().isEmpty()) + { + pay = Payload.EMPTY_PAYLOAD; + } + else + { + String tmp = msn.payloads.getElements().get(0).toString().trim(); + int i = tmp.indexOf('@'); + if (i != -1) + { + throw new F17Exception("[f17] Delegation not supported: " + tmp); + } + else + { + pay = msn.payloads.toPayload(); + } + } + return this.factory.GMessageTransfer(src, dest, op, pay); + } + + // Mostly duplicated from parseGMessageTransfer, but GMessageTransfer/GConnect have no useful base class + private ParamCoreGConnect parseGConnect(GConnect gc) throws F17Exception + { + Role src = gc.src.toName(); + Role dest = gc.dest.toName(); + if (!gc.msg.isMessageSigNode()) + { + throw new F17SyntaxException(gc.msg.getSource(), " [f17] Message kind not supported: " + gc.msg); + } + MessageSigNode msn = ((MessageSigNode) gc.msg); + Op op = msn.op.toName(); + Payload pay = null; + if (msn.payloads.getElements().isEmpty()) + { + pay = Payload.EMPTY_PAYLOAD; + } + else + { + String tmp = msn.payloads.getElements().get(0).toString().trim(); + int i = tmp.indexOf('@'); + if (i != -1) + { + throw new F17Exception("[f17] Delegation not supported: " + tmp); + } + else + { + pay = msn.payloads.toPayload(); + } + } + return this.factory.GConnect(src, dest, op, pay); + } + + private F17GDisconnect parseGDisconnect(GDisconnect gdc) throws F17Exception + { + Role src = gdc.src.toName(); + Role dest = gdc.dest.toName(); + return this.factory.GDisconnect(src, dest); + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGRec.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGRec.java new file mode 100644 index 000000000..910708602 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGRec.java @@ -0,0 +1,109 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreRec; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.ast.local.RPCoreLEnd; +import org.scribble.ext.go.core.ast.local.RPCoreLRecVar; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.type.kind.Global; +import org.scribble.type.name.RecVar; +import org.scribble.type.name.Role; + +public class RPCoreGRec extends RPCoreRec implements RPCoreGType +{ + public RPCoreGRec(RecVar recvar, RPCoreGType body) + { + super(recvar, body); + } + + @Override + public RPCoreGType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreGType) neu; + } + else + { + return af.ParamCoreGRec(this.recvar, this.body.subs(af, old, neu)); + } + } + + @Override + public boolean isWellFormed(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t) + { + return this.body.isWellFormed(job, context, gpd, smt2t); + } + + @Override + public Set getIndexedRoles() + { + return this.body.getIndexedRoles(); + } + + @Override + //public ParamCoreLType project(ParamCoreAstFactory af, Role r, Set ranges) throws ParamCoreSyntaxException + public RPCoreLType project(RPCoreAstFactory af, RPRoleVariant subj, Smt2Translator smt2t) throws RPCoreSyntaxException + { + //ParamCoreLType proj = this.body.project(af, r, ranges); + RPCoreLType proj = this.body.project(af, subj, smt2t); + if (proj instanceof RPCoreLRecVar) + { + RPCoreLRecVar rv = (RPCoreLRecVar) proj; + return rv.recvar.equals(this.recvar) ? RPCoreLEnd.END : rv; + } + else + { + return af.ParamCoreLRec(this.recvar, proj); + } + } + + // G proj R \vec{C} r[z] + @Override + public RPCoreLType project3(RPCoreAstFactory af, Set roles, Set ivals, RPIndexedRole subj) throws RPCoreSyntaxException + { + return af.ParamCoreLRec(this.recvar, this.body.project3(af, roles, ivals, subj)); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreGRec)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreGRec; + } + + @Override + public int hashCode() + { + int hash = 2333; + hash = 31 * hash + super.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGRecVar.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGRecVar.java new file mode 100644 index 000000000..ce49a06f1 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGRecVar.java @@ -0,0 +1,92 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreRecVar; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.type.kind.Global; +import org.scribble.type.name.RecVar; +import org.scribble.type.name.Role; + + +public class RPCoreGRecVar extends RPCoreRecVar implements RPCoreGType +{ + public RPCoreGRecVar(RecVar var) + { + super(var); + } + + @Override + public RPCoreGType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) // Shouldn't happen? + { + return (RPCoreGType) neu; + } + return this; + } + + @Override + public boolean isWellFormed(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t) + { + return true; + } + + @Override + public Set getIndexedRoles() + { + return Collections.emptySet(); + } + + @Override + //public ParamCoreLRecVar project(ParamCoreAstFactory af, Role r, Set ranges) + public RPCoreLType project(RPCoreAstFactory af, RPRoleVariant subj, Smt2Translator smt2t) throws RPCoreSyntaxException + { + return af.ParamCoreLRecVar(this.recvar); + } + + // G proj R \vec{C} r[z] + @Override + public RPCoreLType project3(RPCoreAstFactory af, Set roles, Set ivals, RPIndexedRole subj) throws RPCoreSyntaxException + { + return af.ParamCoreLRecVar(this.recvar); + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreGRecVar)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public int hashCode() + { + int hash = 2411; + hash = 31*hash + super.hashCode(); + return hash; + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreGRecVar; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGType.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGType.java new file mode 100644 index 000000000..e7033cfda --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/global/RPCoreGType.java @@ -0,0 +1,38 @@ +package org.scribble.ext.go.core.ast.global; + +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.type.kind.Global; +import org.scribble.type.name.Role; + + +public interface RPCoreGType extends RPCoreType +{ + + // context records nested foreach vars -- only accesses to top-level vars are valid + boolean isWellFormed(GoJob job, Stack> context, GProtocolDecl gpd, Smt2Translator smt2t); + + // TODO: clarify, Role subj is used as "role name" + //ParamCoreLType project(ParamCoreAstFactory af, Role subj, Set ranges) throws ParamCoreSyntaxException; + RPCoreLType project(RPCoreAstFactory af, RPRoleVariant subj, Smt2Translator smt2t) throws RPCoreSyntaxException; // G proj r \vec{D} + RPCoreLType project3(RPCoreAstFactory af, Set roles, Set ivals, RPIndexedRole subj) throws RPCoreSyntaxException; // G proj R \vec{C} r[z] + + Set getIndexedRoles(); + + @Override + RPCoreGType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu); +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLActionKind.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLActionKind.java new file mode 100644 index 000000000..39309abe5 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLActionKind.java @@ -0,0 +1,27 @@ +package org.scribble.ext.go.core.ast.local; + +import org.scribble.ext.go.core.ast.RPCoreActionKind; +import org.scribble.type.kind.Local; + +public enum RPCoreLActionKind implements RPCoreActionKind +{ + CROSS_SEND, + CROSS_RECEIVE, // Multi-receive, but unary choice // Cf. API gen, unary vs. non-unary choice + MULTICHOICES_RECEIVE, // Multi-choice receive + DOT_SEND, + DOT_RECEIVE; + + @Override + public String toString() + { + switch (this) + { + case CROSS_SEND: return "!"; + case CROSS_RECEIVE: return "?"; + case MULTICHOICES_RECEIVE: return "?*"; + case DOT_SEND: return "!="; + case DOT_RECEIVE: return "?="; + default: throw new RuntimeException("[param-core] Won't get here: " + this); + } + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLChoice.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLChoice.java new file mode 100644 index 000000000..03947b57a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLChoice.java @@ -0,0 +1,69 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.LinkedHashMap; +import java.util.stream.Collectors; + +import org.scribble.ext.go.core.ast.RPCoreChoice; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.type.Message; +import org.scribble.type.kind.Local; + +public abstract class RPCoreLChoice extends RPCoreChoice implements RPCoreLType +{ + //protected RPCoreLChoice(RPIndexedRole role, RPCoreLActionKind kind, LinkedHashMap cases) + protected RPCoreLChoice(RPIndexedRole role, RPCoreLActionKind kind, LinkedHashMap cases) + { + super(role, kind, cases); + } + + @Override + public RPCoreLActionKind getKind() + { + return (RPCoreLActionKind) this.kind; + } + + @Override + public String toString() + { + return this.role.toString() + this.kind + casesToString(); + } + + @Override + protected String casesToString() + { + String s = this.cases.entrySet().stream() + .map(e -> e.getKey() + "." + e.getValue()).collect(Collectors.joining(", ")); + s = (this.cases.size() > 1) + ? "{ " + s + " }" + : s; // No ":", cf. global + return s; + } + + @Override + public int hashCode() + { + int hash = 2399; + hash = 31 * hash + super.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreLChoice)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLChoice; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLCont.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLCont.java new file mode 100644 index 000000000..044bcf754 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLCont.java @@ -0,0 +1,66 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.Collections; +import java.util.Set; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreCont; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.kind.Local; + + +public class RPCoreLCont extends RPCoreCont implements RPCoreLType +{ + public static final RPCoreLCont CONT = new RPCoreLCont(); + + private RPCoreLCont() + { + + } + + @Override + public RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant subj) + { + return this; + } + + @Override + public RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreLType) neu; + } + return this; + } + + @Override + public Set getIndexVars() + { + return Collections.emptySet(); + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreLCont)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLCont; + } + + @Override + public int hashCode() + { + return 31*2791; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLCrossChoice.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLCrossChoice.java new file mode 100644 index 000000000..08da2f855 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLCrossChoice.java @@ -0,0 +1,102 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Set; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.Message; +import org.scribble.type.kind.Local; + +// FIXME: rename +public class RPCoreLCrossChoice extends RPCoreLChoice +{ + //public RPCoreLCrossChoice(RPIndexedRole role, RPCoreLActionKind kind, LinkedHashMap cases) + public RPCoreLCrossChoice(RPIndexedRole role, RPCoreLActionKind kind, LinkedHashMap cases) + { + super(role, kind, cases); + if (kind != RPCoreLActionKind.CROSS_SEND && kind != RPCoreLActionKind.CROSS_RECEIVE) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + kind); + } + } + + @Override + public RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant vself) + { + // FIXME: factor out with RPCoreLForeach + int self = -1000; + RPRoleVariant msubj = vself.minimise(self); + if (msubj.isSingleton()) + { + RPInterval ival = msubj.intervals.iterator().next(); + if (ival.start instanceof RPIndexInt) + { + self = ((RPIndexInt) ival.start).val; + } + } + + RPIndexedRole mrole = this.role.minimise(self); + LinkedHashMap tmp = new LinkedHashMap<>(); + this.cases.forEach((k, v) -> tmp.put(k, v.minimise(af, vself))); + return af.ParamCoreLCrossChoice(mrole, getKind(), tmp); + } + + @Override + public RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreLType) neu; + } + else + { + LinkedHashMap tmp = new LinkedHashMap<>(); + this.cases.forEach((k, v) -> tmp.put(k, v.subs(af, old, neu))); + return af.ParamCoreLCrossChoice(this.role, getKind(), tmp); + } + } + + @Override + public Set getIndexVars() + { + Set ivars = new HashSet<>(); + ivars.addAll(this.role.getIndexVars()); + this.cases.values().forEach(c -> ivars.addAll(c.getIndexVars())); + return ivars; + } + + @Override + public int hashCode() + { + int hash = 7229; + hash = 31 * hash + super.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreLCrossChoice)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLCrossChoice; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLDotChoice.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLDotChoice.java new file mode 100644 index 000000000..9c48e74f2 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLDotChoice.java @@ -0,0 +1,86 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.LinkedHashMap; +import java.util.Set; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.Message; +import org.scribble.type.kind.Local; + +@Deprecated +public class RPCoreLDotChoice extends RPCoreLChoice +{ + public final RPIndexExpr offset; + + public RPCoreLDotChoice(RPIndexedRole role, RPIndexExpr offset, RPCoreLActionKind kind, //LinkedHashMap cases) + LinkedHashMap cases) + { + super(role, kind, cases); + if (kind != RPCoreLActionKind.DOT_SEND && kind != RPCoreLActionKind.DOT_RECEIVE) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + kind); + } + this.offset = offset; + } + + @Override + public RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant subj) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + this); + } + + @Override + public RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + this); + } + + @Override + public Set getIndexVars() + { + throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + + @Override + public String toString() + { + RPInterval g = this.role.intervals.iterator().next(); + return this.role.getName() + "[" + this.offset + ":" + g.start + ".." + g.end + "]" + + this.kind + casesToString(); + } + + @Override + public int hashCode() + { + int hash = 7237; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.offset.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreLDotChoice)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLDotChoice; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLEnd.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLEnd.java new file mode 100644 index 000000000..35a298953 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLEnd.java @@ -0,0 +1,66 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.Collections; +import java.util.Set; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreEnd; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.kind.Local; + + +public class RPCoreLEnd extends RPCoreEnd implements RPCoreLType +{ + public static final RPCoreLEnd END = new RPCoreLEnd(); + + private RPCoreLEnd() + { + + } + + @Override + public RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant subj) + { + return this; + } + + @Override + public RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreLType) neu; + } + return this; + } + + @Override + public Set getIndexVars() + { + return Collections.emptySet(); + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreLEnd)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLEnd; + } + + @Override + public int hashCode() + { + return 31*2383; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLForeach.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLForeach.java new file mode 100644 index 000000000..d152388b0 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLForeach.java @@ -0,0 +1,111 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreForeach; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.kind.Local; +import org.scribble.type.name.Role; + +public class RPCoreLForeach extends RPCoreForeach implements RPCoreLType +{ + public RPCoreLForeach(//Role role, RPForeachVar param, RPIndexExpr start, RPIndexExpr end, + Set roles, Set ivals, + RPCoreLType body, RPCoreLType cont) + { + super(//role, param, start, end, + roles, ivals, + body, cont); + } + + @Override + public RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant vself) + { + // FIXME: factor out with RPCoreLChoice + int self = -1000; + RPRoleVariant msubj = vself.minimise(self); + if (msubj.isSingleton()) + { + RPInterval ival = msubj.intervals.iterator().next(); + if (ival.start instanceof RPIndexInt) + { + self = ((RPIndexInt) ival.start).val; + } + } + + int y = self; + Set tmp = this.ivals.stream().map(x -> (RPAnnotatedInterval) x.minimise(y)).collect(Collectors.toSet()); + return af.RPCoreLForeach(this.roles, tmp, this.body.minimise(af, vself), this.seq.minimise(af, vself)); + } + + @Override + public RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreLType) neu; + } + else + { + return af.RPCoreLForeach(//this.role, this.param, this.start, this.end, + this.roles, this.ivals, + this.body.subs(af, old, neu), this.seq.subs(af, old, neu)); + } + } + + @Override + public Set getIndexVars() // For user-supplied params to endpoint kind constructor, i.e., excluding RPForeachVar + { + Set res = + //Stream.of(this.param).collect(Collectors.toSet()); + // FIXME: shouldn't include bound foreach params (cf. RPCoreGForeach#getIndexVars) -- currently included for hacked Foreach method loop (RPCoreSTStateChanApiBuilder) + new HashSet<>(); + res.addAll(this.body.getIndexVars()); + for (RPAnnotatedInterval iv : this.ivals) + { + //Set tmp = new HashSet<>(); + res = res.stream() + .filter(v -> !v.toString().equals(iv.var.toString())) // HACK FIXME -- RPIndexVar distinguished from RPForeachVar (equals) + .collect(Collectors.toSet()); + res.addAll(iv.start.getVars()); // CHECKME: already checked iv.var not in here? + res.addAll(iv.end.getVars()); + } + return res; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreLForeach)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLForeach; + } + + @Override + public int hashCode() + { + int hash = 4283; + hash = 31 * hash + super.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLMultiChoices.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLMultiChoices.java new file mode 100644 index 000000000..ad08cfd1b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLMultiChoices.java @@ -0,0 +1,98 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.Message; +import org.scribble.type.kind.Local; + +// FIXME: factor out better with ParamCore(L)Choice -- or deprecate and just use kind? +@Deprecated +public class RPCoreLMultiChoices extends RPCoreLChoice +{ + public final RPIndexVar var; // Redundant? + + // Pre: cases.size() > 1 + public RPCoreLMultiChoices(RPIndexedRole role, RPIndexVar var, //List cases, + List cases, + RPCoreLType cont) + { + super(role, RPCoreLActionKind.MULTICHOICES_RECEIVE, foo(cases, cont)); + this.var = var; + } + + @Override + public RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant subj) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + this); + } + + @Override + public RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + this); + } + + @Override + public Set getIndexVars() + { + throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + + private static //LinkedHashMap foo(List cases, RPCoreLType cont) + LinkedHashMap foo(List cases, RPCoreLType cont) + { + //LinkedHashMap + LinkedHashMap + tmp = new LinkedHashMap<>(); + cases.forEach(c -> tmp.put(c, cont)); + return tmp; + } + + public RPCoreLType getContinuation() + { + if (new HashSet<>(this.cases.values()).size() > 1) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this.cases); + } + return this.cases.values().iterator().next(); + } + + @Override + public int hashCode() + { + int hash = 7207; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.var.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreLMultiChoices)) + { + return false; + } + RPCoreLMultiChoices them = (RPCoreLMultiChoices) obj; + return super.equals(this) + && this.var.equals(them.var); + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLMultiChoices; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLRec.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLRec.java new file mode 100644 index 000000000..158f0bf20 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLRec.java @@ -0,0 +1,73 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.Set; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreRec; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.kind.Local; +import org.scribble.type.name.RecVar; + +public class RPCoreLRec extends RPCoreRec implements RPCoreLType +{ + public RPCoreLRec(RecVar recvar, RPCoreLType body) + { + //super(recvar, annot, init, body); + super(recvar, body); + } + + @Override + public RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant subj) + { + return af.ParamCoreLRec(this.recvar, this.body.minimise(af, subj)); + } + + @Override + public RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) + { + return (RPCoreLType) neu; + } + else + { + return af.ParamCoreLRec(this.recvar, this.body.subs(af, old, neu)); + } + } + + @Override + public Set getIndexVars() + { + return this.body.getIndexVars(); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPCoreLRec)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLRec; + } + + @Override + public int hashCode() + { + int hash = 2389; + hash = 31 * hash + super.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLRecVar.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLRecVar.java new file mode 100644 index 000000000..17bbc6f55 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLRecVar.java @@ -0,0 +1,67 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.Collections; +import java.util.Set; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreRecVar; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.kind.Local; +import org.scribble.type.name.RecVar; + + +public class RPCoreLRecVar extends RPCoreRecVar implements RPCoreLType +{ + public RPCoreLRecVar(RecVar var) + { + super(var); + } + + @Override + public RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant subj) + { + return this; + } + + @Override + public RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu) + { + if (this.equals(old)) // Shouldn't happen? + { + return (RPCoreLType) neu; + } + return this; + } + + @Override + public Set getIndexVars() + { + return Collections.emptySet(); + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof RPCoreLRecVar)) + { + return false; + } + return super.equals(obj); // Does canEquals + } + + @Override + public int hashCode() + { + int hash = 2417; + hash = 31*hash + super.hashCode(); + return hash; + } + + @Override + public boolean canEquals(Object o) + { + return o instanceof RPCoreLRecVar; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLType.java b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLType.java new file mode 100644 index 000000000..5a1701cde --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/ast/local/RPCoreLType.java @@ -0,0 +1,22 @@ +package org.scribble.ext.go.core.ast.local; + +import java.util.Set; + +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreType; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.kind.Local; + + +public interface RPCoreLType extends RPCoreType +{ + Set getIndexVars(); // FIXME: factor up? + + @Override + RPCoreLType subs(RPCoreAstFactory af, RPCoreType old, RPCoreType neu); + + // N.B. subj not necessarily minimised + // TODO: rename + RPCoreLType minimise(RPCoreAstFactory af, RPRoleVariant vself); +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCLArgFlag.java b/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCLArgFlag.java new file mode 100644 index 000000000..37bf6a9d8 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCLArgFlag.java @@ -0,0 +1,15 @@ +package org.scribble.ext.go.core.cli; + +public enum RPCoreCLArgFlag +{ + // Unique flags + RPCORE_PARAM, + RPCORE_SELECT_BRANCH, // Default is type switch + RPCORE_NO_COPY, + RPCORE_PARFOREACH, + + // Non-unique flags + RPCORE_EFSM, + RPCORE_EFSM_PNG, + RPCORE_API_GEN, +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCLArgParser.java b/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCLArgParser.java new file mode 100644 index 000000000..28ba4d5e5 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCLArgParser.java @@ -0,0 +1,222 @@ +package org.scribble.ext.go.core.cli; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.scribble.cli.CLArgParser; +import org.scribble.cli.CommandLineException; + +public class RPCoreCLArgParser extends CLArgParser +{ + // Unique flags + public static final String RPCORE_PARAM_FLAG = "-param"; + public static final String RPCORE_SELECT_BRANCH_FLAG = "-param-select"; + public static final String RPCORE_NOCOPY_FLAG = "-nocopy"; + public static final String RPCORE_PARFOREACH_FLAG = "-parforeach"; + + // Non-unique flags + public static final String RPCORE_EFSM_FLAG = "-param-fsm"; + public static final String RPCORE_EFSM_PNG_FLAG = "-param-fsmpng"; + public static final String RPCORE_API_GEN_FLAG = "-param-api"; + + private static final Map RPCORE_UNIQUE_FLAGS = new HashMap<>(); + { + RPCoreCLArgParser.RPCORE_UNIQUE_FLAGS.put(RPCoreCLArgParser.RPCORE_PARAM_FLAG, RPCoreCLArgFlag.RPCORE_PARAM); + RPCoreCLArgParser.RPCORE_UNIQUE_FLAGS.put(RPCoreCLArgParser.RPCORE_SELECT_BRANCH_FLAG, RPCoreCLArgFlag.RPCORE_SELECT_BRANCH); + RPCoreCLArgParser.RPCORE_UNIQUE_FLAGS.put(RPCoreCLArgParser.RPCORE_NOCOPY_FLAG, RPCoreCLArgFlag.RPCORE_NO_COPY); + RPCoreCLArgParser.RPCORE_UNIQUE_FLAGS.put(RPCoreCLArgParser.RPCORE_PARFOREACH_FLAG, RPCoreCLArgFlag.RPCORE_PARFOREACH); + } + + private static final Map RPCORE_NON_UNIQUE_FLAGS = new HashMap<>(); + { + RPCoreCLArgParser.RPCORE_NON_UNIQUE_FLAGS.put(RPCoreCLArgParser.RPCORE_EFSM_FLAG, RPCoreCLArgFlag.RPCORE_EFSM); + RPCoreCLArgParser.RPCORE_NON_UNIQUE_FLAGS.put(RPCoreCLArgParser.RPCORE_EFSM_PNG_FLAG, RPCoreCLArgFlag.RPCORE_EFSM_PNG); + RPCoreCLArgParser.RPCORE_NON_UNIQUE_FLAGS.put(RPCoreCLArgParser.RPCORE_API_GEN_FLAG, RPCoreCLArgFlag.RPCORE_API_GEN); + } + + private static final Map RPCORE_FLAGS = new HashMap<>(); + { + RPCoreCLArgParser.RPCORE_FLAGS.putAll(RPCoreCLArgParser.RPCORE_UNIQUE_FLAGS); + RPCoreCLArgParser.RPCORE_FLAGS.putAll(RPCoreCLArgParser.RPCORE_NON_UNIQUE_FLAGS); + } + + private final Map rpParsed = new HashMap<>(); + + public RPCoreCLArgParser(String[] args) throws CommandLineException + { + super(args); // Assigns this.args and calls parseArgs + } + + public Map getParamArgs() throws CommandLineException + { + //super.parseArgs(); // Needed + return this.rpParsed; + } + + @Override + protected boolean isFlag(String arg) + { + return RPCoreCLArgParser.RPCORE_FLAGS.containsKey(arg) || super.isFlag(arg); + } + + // Pre: i is the index of the current flag to parse + // Post: i is the index of the last argument parsed -- parseArgs does the index increment to the next current flag + @Override + protected int parseFlag(int i) throws CommandLineException + { + String flag = this.args[i]; + switch (flag) + { + // Unique flags + case RPCoreCLArgParser.RPCORE_PARAM_FLAG: + { + if (this.rpParsed.containsKey(RPCoreCLArgFlag.RPCORE_API_GEN) + || Arrays.asList(this.args).stream().anyMatch(a -> a.equals(RPCoreCLArgParser.RPCORE_API_GEN_FLAG)) ) // HACK FIXME -- also subsumes above condition + { + return rpParseParamAndPackagePath(i); + } + else + { + return rpParseParam(i); + } + } + case RPCoreCLArgParser.RPCORE_SELECT_BRANCH_FLAG: return rpParseSelectBranch(i); + case RPCoreCLArgParser.RPCORE_NOCOPY_FLAG: return rpParseNoCopy(i); + case RPCoreCLArgParser.RPCORE_PARFOREACH_FLAG: return rpParseParForeach(i); + + // Non-unique flags + case RPCoreCLArgParser.RPCORE_EFSM_FLAG: return rpParseRoleArg(flag, i); + case RPCoreCLArgParser.RPCORE_EFSM_PNG_FLAG: return rpParseRoleAndFileArgs(flag, i); + case RPCoreCLArgParser.RPCORE_API_GEN_FLAG: return rpParseRoleArg(flag, i); + + // Base CL + default: + { + return super.parseFlag(i); + } + } + } + + private int rpParseParam(int i) throws CommandLineException + { + if ((i + 1) >= this.args.length) + { + throw new CommandLineException("Missing simple global protocol name argument."); + } + String proto = this.args[++i]; + rpCheckAndAddUniqueFlag(RPCoreCLArgParser.RPCORE_PARAM_FLAG, new String[] { proto }); + return i; + } + + private int rpParseParamAndPackagePath(int i) throws CommandLineException + { + if ((i + 2) >= this.args.length) + { + throw new CommandLineException("Missing simple global protocol name and/or Go API package path arguments."); + } + String proto = this.args[++i]; + String packpath = this.args[++i]; + rpCheckAndAddUniqueFlag(RPCoreCLArgParser.RPCORE_PARAM_FLAG, new String[] { proto, packpath }); + return i; + } + + private int rpParseSelectBranch(int i) throws CommandLineException + { + rpCheckAndAddUniqueFlag(RPCoreCLArgParser.RPCORE_SELECT_BRANCH_FLAG, new String[] { }); + return i; + } + + private int rpParseNoCopy(int i) throws CommandLineException + { + rpCheckAndAddUniqueFlag(RPCoreCLArgParser.RPCORE_NOCOPY_FLAG, new String[] { }); + return i; + } + + private int rpParseParForeach(int i) throws CommandLineException + { + rpCheckAndAddUniqueFlag(RPCoreCLArgParser.RPCORE_PARFOREACH_FLAG, new String[] { }); + return i; + } + + private void rpCheckAndAddUniqueFlag(String flag, String[] args) throws CommandLineException + { + RPCoreCLArgFlag argFlag = RPCoreCLArgParser.RPCORE_UNIQUE_FLAGS.get(flag); + if (this.rpParsed.containsKey(argFlag)) + { + throw new CommandLineException("Duplicate flag: " + flag); + } + this.rpParsed.put(argFlag, args); + } + + private int rpParseRoleArg(String f, int i) throws CommandLineException + { + RPCoreCLArgFlag flag = RPCoreCLArgParser.RPCORE_NON_UNIQUE_FLAGS.get(f); + if ((i + 1) >= this.args.length) + { + throw new CommandLineException("Missing role argument"); + } + String role = this.args[++i]; + goConcatArgs(flag, role); + return i; + } + + private int rpParseRoleAndFileArgs(String f, int i) throws CommandLineException + { + RPCoreCLArgFlag flag = RPCoreCLArgParser.RPCORE_NON_UNIQUE_FLAGS.get(f); + if ((i + 2) >= this.args.length) + { + throw new CommandLineException("Missing role/file arguments"); + } + String role = this.args[++i]; + String png = this.args[++i]; + goConcatArgs(flag, role, png); + return i; + } + + /*// path is absolute package path prefix for API imports + private int rpParsePackagePathAndRoleArgs(String f, int i) throws CommandLineException + { + RPCoreCLArgFlag flag = RPCoreCLArgParser.RPCORE_NON_UNIQUE_FLAGS.get(f); + if ((i + 2) >= this.args.length) + { + throw new CommandLineException("Missing role/path arguments"); + } + String path = this.args[++i]; + String role = this.args[++i]; + goConcatArgs(flag, role, path); + return i; + }*/ + + /*// FIXME: factor out with core arg parser -- issue is GoCLArgFlag is currently an unlreated type to CLArgFlag + private int goParseProtoAndRoleArgs(String f, int i) throws CommandLineException + { + ParamCoreCLArgFlag flag = ParamCoreCLArgParser.PARAM_NON_UNIQUE_FLAGS.get(f); + if ((i + 2) >= this.args.length) + { + throw new CommandLineException("Missing protocol/role arguments"); + } + String proto = this.args[++i]; + String role = this.args[++i]; + goConcatArgs(flag, proto, role); + return i; + }*/ + + // FIXME: factor out with core arg parser -- issue is GoCLArgFlag is currently an unlreated type to CLArgFlag + private void goConcatArgs(RPCoreCLArgFlag flag, String... toAdd) + { + String[] args = this.rpParsed.get(flag); + if (args == null) + { + args = Arrays.copyOf(toAdd, toAdd.length); + } + else + { + String[] tmp = new String[args.length + toAdd.length]; + System.arraycopy(args, 0, tmp, 0, args.length); + System.arraycopy(toAdd, 0, tmp, args.length, toAdd.length); + args = tmp; + } + this.rpParsed.put(flag, args); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCommandLine.java b/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCommandLine.java new file mode 100644 index 000000000..765313fc8 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/cli/RPCoreCommandLine.java @@ -0,0 +1,1006 @@ +package org.scribble.ext.go.core.cli; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.Stack; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ast.Module; +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.cli.CLArgFlag; +import org.scribble.cli.CommandLine; +import org.scribble.cli.CommandLineException; +import org.scribble.ext.go.ast.global.RPGProtocolHeader; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.global.RPCoreGProtocolDeclTranslator; +import org.scribble.ext.go.core.ast.global.RPCoreGType; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +//import org.scribble.ext.go.core.codegen.statetype.ParamCoreSTEndpointApiGenerator; +//import org.scribble.ext.go.core.codegen.statetype2.ParamCoreSTEndpointApiGenerator; +import org.scribble.ext.go.core.codegen.statetype3.RPCoreSTApiGenerator; +import org.scribble.ext.go.core.codegen.statetype3.RPCoreSTApiGenerator.Mode; +import org.scribble.ext.go.core.main.RPCoreException; +import org.scribble.ext.go.core.main.RPCoreMainContext; +import org.scribble.ext.go.core.model.endpoint.RPCoreEGraphBuilder; +import org.scribble.ext.go.core.model.endpoint.RPCoreEModelFactory; +import org.scribble.ext.go.core.model.endpoint.RPCoreEState; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.annot.RPAnnotExpr; +import org.scribble.ext.go.type.index.RPIndexSelf; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.ext.go.util.IntPairSmt2Translator; +import org.scribble.ext.go.util.IntSmt2Translator; +import org.scribble.ext.go.util.RecursiveFunctionalInterface; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.ext.go.util.Z3Wrapper; +import org.scribble.main.AntlrSourceException; +import org.scribble.main.Job; +import org.scribble.main.JobContext; +import org.scribble.main.ScribbleException; +import org.scribble.main.resource.DirectoryResourceLocator; +import org.scribble.main.resource.ResourceLocator; +import org.scribble.model.MState; +import org.scribble.model.endpoint.EGraph; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; +import org.scribble.util.Pair; +import org.scribble.util.ScribParserException; +import org.scribble.util.ScribUtil; + +// N.B. this is the CL for both -goapi and rp-core extensions +public class RPCoreCommandLine extends CommandLine +{ + protected final Map rpArgs; // Maps each flag to list of associated argument values + + // HACK: store in (Core) Job/JobContext? + private GProtocolDecl gpd; + private RPCoreGType gt; + private Smt2Translator smt2t; + private Map> L0; + private Map> E0; + //protected ParamCoreSModel model; + private Set, Set>> families; // Factor out Family (cf. RPRoleVariant) + // families after subsumption + private Map, Set>, Set>> peers; + // variant-from-an-original-family -> an-original-family -> peer-variants-in-that-family + + private Map, Set>, Pair, Set>> subsum; + // new-family-after-subsumptions -> original-family-before-subsumptions + private Map, Set>, RPRoleVariant>> aliases; + // subsumed-variant -> original-family-subsumed-in -> subsuming-variant + // FIXME: can a variant be subsumed by mutiple other variants? currently only recording one + + public RPCoreCommandLine(String... args) throws CommandLineException + { + this(new RPCoreCLArgParser(args)); + } + + private RPCoreCommandLine(RPCoreCLArgParser p) throws CommandLineException + { + super(p); // calls p.parse() + if (this.args.containsKey(CLArgFlag.INLINE_MAIN_MOD)) + { + // FIXME: should be fine + throw new RuntimeException("[param] Inline modules not supported:\n" + this.args.get(CLArgFlag.INLINE_MAIN_MOD)); + } + // FIXME? Duplicated from core + if (!this.args.containsKey(CLArgFlag.MAIN_MOD)) + { + throw new CommandLineException("No main module has been specified\r\n"); + } + this.rpArgs = p.getParamArgs(); + } + + @Override + protected RPCoreMainContext newMainContext() throws ScribParserException, ScribbleException + { + boolean debug = this.args.containsKey(CLArgFlag.VERBOSE); // TODO: factor out with CommandLine (cf. MainContext fields) + boolean useOldWF = this.args.containsKey(CLArgFlag.OLD_WF); + boolean noLiveness = this.args.containsKey(CLArgFlag.NO_LIVENESS); + boolean minEfsm = this.args.containsKey(CLArgFlag.LTSCONVERT_MIN); + boolean fair = this.args.containsKey(CLArgFlag.FAIR); + boolean noLocalChoiceSubjectCheck = this.args.containsKey(CLArgFlag.NO_LOCAL_CHOICE_SUBJECT_CHECK); + boolean noAcceptCorrelationCheck = this.args.containsKey(CLArgFlag.NO_ACCEPT_CORRELATION_CHECK); + boolean noValidation = this.args.containsKey(CLArgFlag.NO_VALIDATION); + + boolean selectApi = this.rpArgs.containsKey(RPCoreCLArgFlag.RPCORE_SELECT_BRANCH); + boolean noCopy = this.rpArgs.containsKey(RPCoreCLArgFlag.RPCORE_NO_COPY); + boolean parForeach = this.rpArgs.containsKey(RPCoreCLArgFlag.RPCORE_PARFOREACH); + + List impaths = this.args.containsKey(CLArgFlag.IMPORT_PATH) + ? CommandLine.parseImportPaths(this.args.get(CLArgFlag.IMPORT_PATH)[0]) + : Collections.emptyList(); + ResourceLocator locator = new DirectoryResourceLocator(impaths); + if (this.args.containsKey(CLArgFlag.INLINE_MAIN_MOD)) + { + /*return new ParamMainContext(debug, locator, this.args.get(CLArgFlag.INLINE_MAIN_MOD)[0], useOldWF, noLiveness, minEfsm, fair, + noLocalChoiceSubjectCheck, noAcceptCorrelationCheck, noValidation, solver);*/ + throw new RuntimeException("[param] Shouldn't get in here:\n" + this.args.get(CLArgFlag.INLINE_MAIN_MOD)[0]); // Checked in constructor + } + else + { + Path mainpath = CommandLine.parseMainPath(this.args.get(CLArgFlag.MAIN_MOD)[0]); + return new RPCoreMainContext(debug, locator, mainpath, useOldWF, noLiveness, minEfsm, fair, + noLocalChoiceSubjectCheck, noAcceptCorrelationCheck, noValidation, noCopy, selectApi, parForeach); + } + } + + public static void main(String[] args) throws CommandLineException, AntlrSourceException + { + new RPCoreCommandLine(args).run(); + } + + @Override + protected void doValidationTasks(Job job) throws RPCoreSyntaxException, AntlrSourceException, ScribParserException, CommandLineException + { + if (this.rpArgs.containsKey(RPCoreCLArgFlag.RPCORE_PARAM)) + { + doParamCoreValidationTasks((GoJob) job); + } + else + { + super.doValidationTasks(job); + } + } + + @Override + protected void doNonAttemptableOutputTasks(Job job) throws ScribbleException, CommandLineException + { + GoJob gjob = (GoJob) job; + if (this.rpArgs.containsKey(RPCoreCLArgFlag.RPCORE_API_GEN)) + { + JobContext jcontext = job.getContext(); + String simpname = this.rpArgs.get(RPCoreCLArgFlag.RPCORE_PARAM)[0]; + GProtocolName fullname = checkGlobalProtocolArg(jcontext, simpname); + String impath = this.rpArgs.get(RPCoreCLArgFlag.RPCORE_PARAM)[1]; + String[] args = this.rpArgs.get(RPCoreCLArgFlag.RPCORE_API_GEN); + List roles = new LinkedList<>(); + for (int i = 0; i < args.length; i += 1) + { + Role role = checkRoleArg(jcontext, fullname, args[i]); + roles.add(role); + /*for (ParamActualRole ranges : this.P0.get(role).keySet()) + { + EGraph efsm = this.E0.get(role).get(ranges); + Map goClasses = new ParamCoreSTEndpointApiGenerator(job, fullname, ranges, efsm).build(); + outputClasses(goClasses); + }*/ + + /*job.debugPrintln("\n[rp-core] Running " + ParamCoreSTSessionApiBuilder.class + " for " + fullname); + + /*Map goClasses = new ParamCoreSTSessionApiBuilder((GoJob) job, fullname, this.E0).build();* / + //Map actuals = this.E0.get(role); + Map goClasses = new RPCoreSTApiGenerator(gjob, fullname, this.L0, this.E0, this.families, impath, role).build(); + outputClasses(goClasses);*/ + } + + Mode mode; + if (this.smt2t instanceof IntSmt2Translator) + { + mode = Mode.Int; + } + else if (this.smt2t instanceof IntPairSmt2Translator) + { + mode = Mode.IntPair; + } + else + { + throw new RuntimeException("Shouldn't get in here: " + this.smt2t.getClass()); + } + Map goClasses = new RPCoreSTApiGenerator(gjob, fullname, + this.L0, this.E0, this.families, this.peers, this.subsum, this.aliases, impath, roles, mode, this.smt2t).build(); + outputClasses(goClasses); + } + else + { + super.doNonAttemptableOutputTasks(job); + } + } + + private void doParamCoreValidationTasks(GoJob j) throws RPCoreSyntaxException, ScribbleException, ScribParserException, CommandLineException + { + /*if (this.args.containsKey(CLArgFlag.PROJECT)) // HACK + // modules/f17/src/test/scrib/demo/fase17/AppD.scr in [default] mode bug --- projection/EFSM not properly formed if this if is commented ???? + { + + }*/ + + paramCorePreContextBuilding(j); + + GProtocolName simpname = new GProtocolName(this.rpArgs.get(RPCoreCLArgFlag.RPCORE_PARAM)[0]); + if (simpname.toString().equals("[ParamCoreAllTest]")) // HACK: ParamCoreAllTest + { + paramCoreParseAndCheckWF(j); // Includes base passes + } + else + { + paramCoreParseAndCheckWF(j, simpname); // Includes base passes + } + + // FIXME? rp-core FSM building only used for rp-core validation -- output tasks, e.g., -api, will still use default Scribble FSMs + // -- but the FSMs should be the same? -- no: action assertions treated differently in core than base + } + + + // Refactor into Param(Core)Job? + // Following methods are for assrt-*core* + + private void paramCorePreContextBuilding(GoJob job) throws ScribbleException + { + job.runContextBuildingPasses(); + + //job.runVisitorPassOnParsedModules(RecRemover.class); // FIXME: Integrate into main passes? Do before unfolding? + // FIXME: no -- revise to support annots + } + + // Pre: assrtPreContextBuilding(job) + private void paramCoreParseAndCheckWF(GoJob job) throws RPCoreSyntaxException, ScribbleException, ScribParserException, CommandLineException + { + Module main = job.getContext().getMainModule(); + for (GProtocolDecl gpd : main.getGlobalProtocolDecls()) + { + if (!gpd.isAuxModifier()) + { + paramCoreParseAndCheckWF(job, gpd.getHeader().getDeclName()); // decl name is simple name + } + } + } + + // Pre: paramCorePreContextBuilding(job) + private void paramCoreParseAndCheckWF(GoJob job, GProtocolName simpname) throws RPCoreSyntaxException, ScribbleException, ScribParserException, CommandLineException + { + Module main = job.getContext().getMainModule(); + if (!main.hasProtocolDecl(simpname)) + { + throw new RPCoreException("[rp-core] Global protocol not found: " + simpname); + } + this.gpd = (GProtocolDecl) main.getProtocolDecl(simpname); + + RPCoreAstFactory af = new RPCoreAstFactory(); + this.gt = new RPCoreGProtocolDeclTranslator(job, af).translate(this.gpd); + + this.smt2t = Z3Wrapper.getSmt2Translator(job, this.gpd, gt); + + job.debugPrintln("\n[rp-core] Translated:\n " + gt); + + if (!gt.isWellFormed(job, new Stack<>(), gpd, smt2t)) + { + throw new RPCoreException("[rp-core] Global type not well-formed:\n " + gt); + } + + //Map>> + Map> + variants = getVariants(job, gt, smt2t); + + job.debugPrintln("\n[rp-core] Computed roles: " + variants); + + this.L0 = new HashMap<>(); + for (Role r : gpd.header.roledecls.getRoles()) // getRoles gives decl names // CHECKME: can ignore params? + { + //for (Set ranges : protoRoles.get(r)) + for (RPRoleVariant variant : variants.get(r)) + { + //ParamCoreLType lt = gt.project(af, r, ranges); + RPCoreLType lt = gt.project(af, variant, this.smt2t); + + lt = lt.minimise(af, variant); + + //Map, ParamCoreLType> tmp = P0.get(r); + Map tmp = L0.get(r); + if (tmp == null) + { + tmp = new HashMap<>(); + L0.put(r, tmp); + } + tmp.put(variant, lt); + + job.debugPrintln("\n[rp-core] Projected onto " + variant + ":\n " + lt); + } + } + + RPCoreEGraphBuilder builder = new RPCoreEGraphBuilder(job); + this.E0 = new HashMap<>(); + for (Role r : (Iterable) L0.keySet().stream().sorted( // For consistent state numbering + new Comparator() { + @Override + public int compare(Role o1, Role o2) { + return o1.toString().compareTo(o2.toString()); + } + } + )::iterator) + { + //for (Set ranges : this.P0.get(r).keySet()) + for (RPRoleVariant variant : (Iterable) this.L0.get(r).keySet().stream().sorted( + new Comparator() { + @Override + public int compare(RPRoleVariant o1, RPRoleVariant o2) { + return o1.toString().compareTo(o2.toString()); + } + } + )::iterator) + { + + //System.out.println("\nProjection onto " + variant + ": " + this.L0.get(r).get(variant)); + + EGraph g = builder.build(this.L0.get(r).get(variant)); + //Map, EGraph> tmp = this.E0.get(r); + Map tmp = this.E0.get(r); + if (tmp == null) + { + tmp = new HashMap<>(); + this.E0.put(r, tmp); + } + tmp.put(variant, g); + + job.debugPrintln("\n[rp-core] Built endpoint graph for " + //+ r + " for " + + variant + ":\n" + g.toDot()); + + RecursiveFunctionalInterface>> getNestedInits + = new RecursiveFunctionalInterface<>(); + getNestedInits.func = s -> + { + Set inits = new HashSet<>(); + if (s.hasNested()) + { + inits.add(s.getNested()); + } + inits.addAll(MState.getReachableStates(s).stream() + .filter(x -> ((RPCoreEState) x).hasNested()) + .map(x -> ((RPCoreEState) x).getNested()) + .collect(Collectors.toSet())); + inits.forEach(x -> inits.addAll(getNestedInits.func.apply(x))); + return inits; + }; + + getNestedInits.func.apply((RPCoreEState) g.init).stream() + .forEach(s -> job.debugPrintln("\n" + s.toDot())); + } + } + + /*assrtCoreValidate(job, simpname, gpd.isExplicitModifier());//, this.E0); // TODO + + /*if (!job.fair) + { + Map U0 = new HashMap<>(); + for (Role r : E0.keySet()) + { + EState u = E0.get(r).unfairTransform(); + U0.put(r, u); + + job.debugPrintln + //System.out.println + ("\n[rp-core] Unfair transform for " + r + ":\n" + u.toDot()); + } + + //validate(job, gpd.isExplicitModifier(), U0, true); //TODO + }*/ + + //((ParamJob) job).runF17ProjectionPasses(); // projections not built on demand; cf. models + + //return gt; + + this.families = new HashSet<>(); + this.families.addAll(getFamilies(job, smt2t)); + this.peers = new HashMap<>(); + this.peers.putAll(getPeers(job, smt2t)); + + minimise(); + } + + private void minimise() + { + this.subsum = new HashMap<>(); + this.aliases = new HashMap<>(); + + //Map> L0 = + //Map> E0; + /*Set, Set>> families + = this.families.stream().map( + p -> new Pair, Set>(new HashSet<>(p.left), new HashSet<>(p.right)) + ).collect(Collectors.toSet());*/ + + /*Map, Set>, Set>> peers + = + this.peers.entrySet().stream().collect(Collectors.toMap( + e -> e.getKey(), + e -> e.getValue().entrySet().stream().collect(Collectors.toMap( + ee -> ee.getKey(), + ee -> new HashSet<>(ee.getValue()) + )) + ));*/ + RPCoreAstFactory af = new RPCoreAstFactory(); + + Set, Set>> families = new HashSet<>(); + ////Map, Set>, Set>> peers = new HashMap<>(); + for (Pair, Set> fam : this.families) + { + Set tmp = new HashSet<>(); + Set vs = fam.left; + Next: for (RPRoleVariant v : vs) + { + if (!v.isSingleton()) + { + tmp.add(v); + } + else + { + for (RPRoleVariant u : vs.stream().filter(x -> x.getName().equals(v.getName())).collect(Collectors.toList())) + { + if (!u.equals(v)) + { + RPCoreLType vL = this.L0.get(v.getName()).get(v); + RPCoreLType uL = this.L0.get(u.getName()).get(u); + + //System.out.println("4444: " + v + " \n " + vL + " ,, " + vL.minimise(af, v) + " \n " + u + " ,, " + uL + " ,, " + uL.minimise(af, v) + "\n"); + if (vL.minimise(af, v).equals(uL.minimise(af, v))) + { + //System.out.println("5555: " + v + " subsumed by " + u); + + Map, Set>, RPRoleVariant> m = this.aliases.get(v); + if (m == null) + { + m = new HashMap<>(); + this.aliases.put(v, m); + } + m.put(fam, u); // FIXME: can a variant be subsumed by mutiple other variants? currently only recording one + + continue Next; + } + } + } + tmp.add(v); + } + } + + //if (!tmp.equals(fam.left)) + { + Pair, Set> compressed = new Pair<>(tmp, fam.right); + families.add(compressed); // Subsumed variants are neither in left nor right + + /*System.out.println("\nFamily:\n" + fam.left.stream().map(x -> x.toString()).collect(Collectors.joining("\n")) + + "\nCovars:\n" + fam.right.stream().map(x -> x.toString()).collect(Collectors.joining("\n")) + + "\nCompacted:\n" + tmp.stream().map(x -> x.toString()).collect(Collectors.joining("\n")));*/ + + if (!tmp.equals(fam.left)) + { + this.subsum.put(compressed, fam); + } + } + } + + this.families = families; + } + + // ..FIXME: generalise to multirole processes? i.e. all roles are A with different indices? -- also subsumes MP with single rolename? + + //..HERE FIXME ActualParam -- ParamRange is now already a Set + + + // Compute variant peers of each variant -- which peer variants (possibly self variant) can match the indexed-role peers of self's I/O actions + // for "common" endpoint kind factoring (w.r.t. dial/accept, i.e., to look for variants whose set of dial/accept methods is the same for all families it is involved in) + // FIXME: optimise, peers are symmetric + private Map, Set>, Set>> getPeers(GoJob job, Smt2Translator smt2t) + { + job.debugPrintln("\n[rp-core] Computing peers:"); + + Map, Set>, Set>> res = new HashMap<>(); + + /*String[] args = this.rpArgs.get(RPCoreCLArgFlag.RPCORE_API_GEN); + for (Role rname : (Iterable) Arrays.asList(args).stream().map(r -> new Role(r))::iterator)*/ + for (Role rname : this.gpd.header.roledecls.getRoles()) + { + for (RPRoleVariant self : this.E0.get(rname).keySet()) + { + /*for (Pair, Set> family : + (Iterable, Set>>) + this.families.keySet().stream().filter(f -> f.left.contains(variant))::iterator) // FIXME: use family to make accept/dial + {*/ + // CHECKME: use local types instead of FSMs? (RPCoreGForeach#getIndexedRoles) + Set actionIRs = //MState.getReachableActions + RPCoreEState.getReachableActions((RPCoreEModelFactory) job.ef, + (RPCoreEState) this.E0.get(rname).get(self).init).stream() // FIXME: static "overloading" (cf. MState) error prone + .map(a -> ((RPCoreEAction) a).getPeer()).collect(Collectors.toSet()); + // CHECKME: in presence of foreach, actions will include unqualified foreachvars -- is that what the following Z3 assertion is/should be doing? + + Set peers = new HashSet<>(); + next: for (RPRoleVariant peerVariant : (Iterable) // Candidate + this.E0.values().stream() + .flatMap(m -> m.keySet().stream())::iterator) + { + if (//!peerVariant.equals(self) && // No: e.g., pipe/ring middlemen + !peers.contains(peerVariant)) + { + job.debugPrintln("\n[rp-core] For " + self + ", checking peer candidate: " + peerVariant); + // "checking potential peer" means checking if any of our action-peer indexed roles fits the candidate variant-peer (so we would need a dial/accept for them) + + for (RPIndexedRole ir : actionIRs) + { + if (ir.getName().equals(peerVariant.getName())) + { + if (ir.intervals.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: multi-dimension intervals: " + ir); // No? Multiple intervals is not actually about multidim intervals, it's about constraint intersection? (A multdim interval should be a single interval value?) + } + RPInterval d = ir.intervals.stream().findAny().get(); + Set vars = Stream.concat(peerVariant.intervals.stream().flatMap(x -> x.getIndexVars().stream()), peerVariant.cointervals.stream().flatMap(x -> x.getIndexVars().stream())) + .collect(Collectors.toSet()); + vars.addAll(ir.getIndexVars()); + + /*String smt2 = "(assert "; + smt2 += "(exists ((peer Int) " + + (vars.isEmpty() ? "" : vars.stream() + .map(x -> "(" + x + " Int)").collect(Collectors.joining(" "))) + ")\n"; + smt2 += "(and \n"; + smt2 += vars.stream().map(x -> "(>= " + x + " 1)").collect(Collectors.joining(" ")) + "\n"; // FIXME: generalise, parameter domain annotations + + smt2 += peerVariant.intervals.stream() + .map(x -> "(>= peer " + x.start.toSmt2Formula() + ") (<= peer " + x.end.toSmt2Formula() + ")") + // Is there a peer index inside all the peer-variant intervals + .collect(Collectors.joining(" ")) + "\n"; + smt2 += peerVariant.cointervals.isEmpty() + ? "" + : "(or " + peerVariant.cointervals.stream() + .map(x -> "(< peer " + x.start.toSmt2Formula() + ") (> peer " + x.end.toSmt2Formula() + ")") + .collect(Collectors.joining(" ")) + ")\n"; + // ...and the peer index is outside one of the peer-variant cointervals + smt2 += "(>= peer " + d.start.toSmt2Formula() + ") (<= peer " + d.end.toSmt2Formula() + ")\n"; + // ...and the peer index is inside our I/O action interval -- then this is peer-variant is a peer + + if (vars.contains(RPIndexSelf.SELF)) + { + // FIXME: factor out variant/covariant inclusion/exclusion with above + smt2 += self.intervals.stream() + .map(x -> "(>= self " + x.start.toSmt2Formula() + ") (<= self " + x.end.toSmt2Formula() + ")") + // Is there a self index inside all the self-variant intervals + .collect(Collectors.joining(" ")) + "\n"; + smt2 += self.cointervals.isEmpty() + ? "" + : "(or " + self.cointervals.stream() + .map(x -> "(< self " + x.start.toSmt2Formula() + ") (> self " + x.end.toSmt2Formula() + ")") + .collect(Collectors.joining(" ")) + ")\n"; + // ...and the self index is outside one of the self-variant cointervals + } + + smt2 += ")"; + smt2 += ")"; + smt2 += ")"; + */ + + // CHECKME: need to further constrain K? (by family?) + + List cs = new LinkedList<>(); + cs.addAll(vars.stream().map(x -> smt2t.makeGte(x.toSmt2Formula(smt2t), smt2t.getDefaultBaseValue())).collect(Collectors.toList())); // FIXME: generalise, parameter domain annotations + + if (this.gpd.header instanceof RPGProtocolHeader) + { + // FIXME: WIP + RPAnnotExpr annot = RPAnnotExpr.parse(((RPGProtocolHeader) this.gpd.header).annot); + if (annot.getVars().stream().map(x -> x.toString()).allMatch(x -> + vars.stream().map(y -> y.toString()).anyMatch(y -> x.equals(y)))) // TODO: refactor + { + cs.add(annot.toSmt2Formula(smt2t)); + } + } + + for (RPInterval ival : peerVariant.intervals) // Is there a peer index inside all the peer-variant intervals + { + cs.add(smt2t.makeGte("peer", ival.start.toSmt2Formula(smt2t))); + cs.add(smt2t.makeLte("peer", ival.end.toSmt2Formula(smt2t))); + } + if (!peerVariant.cointervals.isEmpty()) + { + // ...and the peer index is outside one of the peer-variant cointervals + /*cs.add(smt2t.makeOr( + self.cointervals.stream().flatMap(x -> + Stream.of(smt2t.makeLt("peer", x.start.toSmt2Formula(smt2t)), smt2t.makeGt("peer", x.end.toSmt2Formula(smt2t))) + ).collect(Collectors.toList())));*/ + cs.addAll(peerVariant.cointervals.stream().map(x -> + smt2t.makeOr(smt2t.makeLt("peer", x.start.toSmt2Formula(smt2t)), smt2t.makeGt("peer", x.end.toSmt2Formula(smt2t))) + ).collect(Collectors.toList())); + } + // ...and the peer index is inside our I/O action interval -- then this is peer-variant is a peer + cs.add(smt2t.makeGte("peer", d.start.toSmt2Formula(smt2t))); + cs.add(smt2t.makeLte("peer", d.end.toSmt2Formula(smt2t))); + + if (vars.contains(RPIndexSelf.SELF)) + { + // If self name is peer name, peer index is not self index + if (peerVariant.getName().equals(self.getName())) + { + cs.add(smt2t.makeNot(smt2t.makeEq("peer", "self"))); + } + // TODO: factor out variant/covariant inclusion/exclusion with above + for (RPInterval ival : self.intervals) // Is there a self index inside all the self-variant intervals + { + cs.add(smt2t.makeGte("self", ival.start.toSmt2Formula(smt2t))); + cs.add(smt2t.makeLte("self", ival.end.toSmt2Formula(smt2t))); + } + if (!self.cointervals.isEmpty()) + { + // ...and the self index is outside one of the self-variant cointervals + /*cs.add(smt2t.makeOr( + self.cointervals.stream().flatMap(x -> + Stream.of(smt2t.makeLt("self", x.start.toSmt2Formula(smt2t)), smt2t.makeGt("self", x.end.toSmt2Formula(smt2t))) + ).collect(Collectors.toList())));*/ + cs.addAll(self.cointervals.stream().map(x -> + smt2t.makeOr(smt2t.makeLt("self", x.start.toSmt2Formula(smt2t)), smt2t.makeGt("self", x.end.toSmt2Formula(smt2t))) + ).collect(Collectors.toList())); + } + } + + String smt2 = smt2t.makeAnd(cs); + List tmp = new LinkedList<>(); + tmp.add("peer"); + tmp.addAll(vars.stream().map(x -> x.toSmt2Formula(smt2t)).collect(Collectors.toList())); + smt2 = smt2t.makeExists(tmp, smt2); + smt2 = smt2t.makeAssert(smt2); + + job.debugPrintln("[rp-core] Running Z3 on " + d + " :\n" + smt2); + + boolean isSat = Z3Wrapper.checkSat(job, this.gpd, smt2); + job.debugPrintln("[rp-core] Checked sat: " + isSat); + if (isSat) + { + peers.add(peerVariant); + continue next; + } + } + } + } + } + + Map, Set>, Set> tmp = new HashMap<>(); + res.put(self, tmp); + for (Pair, Set> fam : this.families) + { + if (fam.left.contains(self)) + { + Set tmp2 = new HashSet<>(peers); + tmp2.retainAll(fam.left); + tmp.put(fam, tmp2); + } + } + //} + + } + } + + return res; + } + + private Set, Set>> getFamilies(GoJob job, Smt2Translator smt2t) + { + job.debugPrintln("\n[rp-core] Computing families:"); + + Set, Set>> fams = new HashSet<>(); + + Set all = this.L0.values().stream() + .flatMap(m -> m.keySet().stream()).collect(Collectors.toSet()); + Set vars = all.stream() + .flatMap(v -> v.getIndexVars().stream()).collect(Collectors.toSet()); + Set> pset = ScribUtil.makePowerSet(all).stream() + .filter(x -> x.size() >= 2).collect(Collectors.toSet()); + + int size = pset.size(); + int i = 1; + for (Set cand : pset) + { + Set coset = all.stream() + .filter(x -> !cand.contains(x)).collect(Collectors.toSet()); + + String smt2 = makeFamilyCheck(smt2t, vars, cand, coset); + + job.debugPrintln("\n[rp-core] Family candidate (" + i++ + "/" + size + "): " + cand); + job.debugPrintln("[rp-core] Co-set: " + coset); + job.debugPrintln("[rp-core] Running Z3 on:\n" + smt2); + + boolean isSat = Z3Wrapper.checkSat(job, smt2t.global, smt2); + if (isSat) + { + fams.add(new Pair<>(Collections.unmodifiableSet(cand), Collections.unmodifiableSet(coset))); + } + job.debugPrintln("[rp-core] Checked sat: " + isSat); + } + + return fams; + } + + public static String makeFamilyCheck(Smt2Translator smt2t, Set vars, Set cand, Set coset) + { + List cs = new LinkedList<>(); + cs.addAll(vars.stream().map(x -> smt2t.makeGte(x.toSmt2Formula(smt2t), smt2t.getDefaultBaseValue())).collect(Collectors.toList())); // FIXME: generalise, parameter domain annotations + cs.addAll(cand.stream().map(v -> makePhiSmt2(v.intervals, v.cointervals, smt2t, false)).collect(Collectors.toList())); + cs.addAll(coset.stream().map(v -> makePhiSmt2(v.intervals, v.cointervals, smt2t, true)).collect(Collectors.toList())); + + if (!vars.isEmpty()) + { + if (smt2t.global.header instanceof RPGProtocolHeader) + { + // FIXME: WIP + RPAnnotExpr annot = RPAnnotExpr.parse(((RPGProtocolHeader) smt2t.global.header).annot); + if (annot.getVars().stream().map(x -> x.toString()).allMatch(x -> + vars.stream().map(y -> y.toString()).anyMatch(y -> x.equals(y)))) // TODO: refactor + { + cs.add(annot.toSmt2Formula(smt2t)); + } + } + } + + String smt2 = smt2t.makeAnd(cs); + if (!vars.isEmpty()) + { + smt2 = smt2t.makeExists(vars.stream().map(x -> x.toSmt2Formula(smt2t)).collect(Collectors.toList()), smt2); + } + smt2 = smt2t.makeAssert(smt2); + return smt2; + } + + private //Map>> + Map> + getVariants(GoJob job, RPCoreGType gt, Smt2Translator smt2t) + { + Set prs = gt.getIndexedRoles(); + + Map> map + = prs.stream() + .map(x -> x.getName()) + .distinct() + .collect(Collectors.toMap(x -> x, x -> prs.stream().filter(y -> y.getName().equals(x)).collect(Collectors.toSet()))); + + Map>> powersets = map.keySet().stream().collect(Collectors.toMap(k -> k, k -> new HashSet<>())); + for (Role n : map.keySet()) + { + Set tmp = map.get(n); + Optional foo = tmp.stream().filter(x -> x.intervals.size() > 1).findAny(); + if (foo.isPresent()) + { + throw new RuntimeException("[rp-core] TODO: multi-dimension intervals: " + foo.get()); + } + powersets.put(n, ScribUtil.makePowerSet(tmp.stream().flatMap(v -> v.intervals.stream()).collect(Collectors.toSet()))); + } + + //Map>> protoRoles = powersets.keySet().stream().collect(Collectors.toMap(x -> x, x -> new HashSet<>())); + Map> variants = powersets.keySet().stream().collect(Collectors.toMap(x -> x, x -> new HashSet<>())); + for (Role r : powersets.keySet()) + { + Set> powset = powersets.get(r); + int i = 1; + int size = powset.size(); + + job.debugPrintln("\n[rp-core] Ranges powerset for " + r + ": " + powset); + + for (Set cand : powset) + { + Set coset = powset.stream() + .filter(f -> f.stream().noneMatch(g -> cand.contains(g))) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + + String z3 = makePhiSmt2(cand, coset, smt2t, false); + List vars = Stream.concat( + cand.stream().flatMap(c -> c.getIndexVars().stream()), + coset.stream().flatMap(c -> c.getIndexVars().stream()) + ).distinct().collect(Collectors.toList()); + if (!vars.isEmpty()) + { + //z3 = "(exists (" + vars.stream().map(p -> "(" + p + " Int)").collect(Collectors.joining(" ")) + ") " + z3 + ")"; + List tmp = vars.stream().map(v -> smt2t.makeLte(smt2t.getDefaultBaseValue(), v.toSmt2Formula(smt2t))).collect(Collectors.toList()); + + if (this.gpd.header instanceof RPGProtocolHeader) + { + // FIXME: WIP + RPAnnotExpr annot = RPAnnotExpr.parse(((RPGProtocolHeader) this.gpd.header).annot); + if (annot.getVars().stream().map(x -> x.toString()).allMatch(x -> + vars.stream().map(y -> y.toString()).anyMatch(y -> x.equals(y)))) // TODO: refactor + { + tmp.add(annot.toSmt2Formula(smt2t)); + } + } + + tmp.add(z3); + z3 = smt2t.makeAnd(tmp); + z3 = smt2t.makeExists(vars.stream().map(v -> v.toSmt2Formula(smt2t)).collect(Collectors.toList()), z3); + } + //z3 = smt2t.makeExists(Stream.of("self").collect(Collectors.toList()), z3); + z3 = smt2t.makeAssert(z3); + + job.debugPrintln("\n[rp-core] Variant candidate (" + i++ + "/" + size + "): " + cand); + job.debugPrintln("[rp-core] Co-set: " + coset); + job.debugPrintln("[rp-core] Running Z3 on:\n" + z3); + + boolean isSat = Z3Wrapper.checkSat(job, this.gpd, z3); + if (isSat) + { + //protoRoles.get(r).add(cand); + variants.get(r).add(new RPRoleVariant(r.toString(), cand, coset)); + } + job.debugPrintln("[rp-core] Checked sat: " + isSat); + } + } + + return variants; + } + + // Doesn't include "assert", nor exists-bind index vars (but does exists-bind self) + private static String makePhiSmt2(Set cand, Set coset, Smt2Translator smt2t, boolean not) + { + List cs = new LinkedList<>(); + List dom = new LinkedList<>(); + + //if (cand.size() > 0) + { + //z3 += smt2t.makeAnd( + cs.addAll( + cand.stream().map(c -> + //"(and (>= self " + c.start.toSmt2Formula() + ") (<= self " + c.end.toSmt2Formula() + ")" + ((!c.start.isConstant() || !c.end.isConstant()) ? " (<= " + c.start.toSmt2Formula() + " " + c.end.toSmt2Formula() + ")" : "") + ")" + { + List tmp = new LinkedList<>(); + tmp.add(smt2t.makeGte("self", c.start.toSmt2Formula(smt2t))); + tmp.add(smt2t.makeLte("self", c.end.toSmt2Formula(smt2t))); + if (!c.start.isConstant() || !c.end.isConstant()) + { + dom.add(smt2t.makeLte(c.start.toSmt2Formula(smt2t), c.end.toSmt2Formula(smt2t))); + } + return smt2t.makeAnd(tmp); + }) + //.reduce((c1, c2) -> "(and " + c1 + " " + c2 +")").get(); + .collect(Collectors.toList()) + ); + } + + /*if (coset.size() > 0) + { + if (cand.size() > 0) + { + z3 = "(and " + z3 + " "; + }*/ + cs.addAll( + coset.stream().map(c -> + //z3 += coset.stream().map(c -> "(and (not (and (>= self " + c.start.toSmt2Formula() + ") (<= self " + c.end.toSmt2Formula() + ")))" + ((!c.start.isConstant() || !c.end.isConstant()) ? " (<= " + c.start.toSmt2Formula() + " " + c.end.toSmt2Formula() + ")" : "") + ")") + { + List tmp = new LinkedList<>(); + //tmp.add(smt2t.makeOr(smt2t.makeLt("self", c.start.toSmt2Formula()), smt2t.makeGt("self", c.end.toSmt2Formula()))); + tmp.add(smt2t.makeNot(smt2t.makeAnd(smt2t.makeGte("self", c.start.toSmt2Formula(smt2t)), smt2t.makeLte("self", c.end.toSmt2Formula(smt2t))))); + if (!c.start.isConstant() || !c.end.isConstant()) + { + dom.add(smt2t.makeLte(c.start.toSmt2Formula(smt2t), c.end.toSmt2Formula(smt2t))); // Must be outside the not (if one) + } + return (tmp.size() == 1) ? tmp.get(0) : smt2t.makeAnd(tmp); + }) + //.reduce((c1, c2) -> "(and " + c1 + " " + c2 +")").get(); + .collect(Collectors.toList()) + + //(and (not (and (and (>= self 1) (<= self K))) (<= 1 K))) + ); + /*if (cand.size() > 0) + { + z3 += ")"; + } + }*/ + + String z3 = //"(exists ((self Int))" + z3 + ")"; + smt2t.makeExists(Stream.of("self").collect(Collectors.toList()), smt2t.makeAnd(cs)); // CHECKME: need explicit self >= 1? + if (not) + { + z3 = smt2t.makeNot(z3); + } + dom.add(z3); + z3 = smt2t.makeAnd(dom); + + return z3; + } + + // FIXME: factor out -- cf. super.doAttemptableOutputTasks + @Override + protected void tryOutputTasks(Job job) throws CommandLineException, ScribbleException + { + if (this.rpArgs.containsKey(RPCoreCLArgFlag.RPCORE_EFSM)) + { + String[] args = this.rpArgs.get(RPCoreCLArgFlag.RPCORE_EFSM); + for (int i = 0; i < args.length; i += 1) + { + Role role = CommandLine.checkRoleArg(job.getContext(), this.gpd.getHeader().getDeclName(), args[i]); + this.E0.get(role).entrySet().forEach(e -> + { + String out = e.getValue().toDot(); + System.out.println("\nEndpoint FSM for " + e.getKey() + ":\n" + out); // Endpoint graphs are "inlined" (a single graph is built) + }); + } + } + if (this.rpArgs.containsKey(RPCoreCLArgFlag.RPCORE_EFSM_PNG)) + { + String[] args = this.rpArgs.get(RPCoreCLArgFlag.RPCORE_EFSM_PNG); + for (int i = 0; i < args.length; i += 2) + { + Role role = CommandLine.checkRoleArg(job.getContext(), this.gpd.getHeader().getDeclName(), args[i]); + String png = args[i+1]; + //for (Entry, EGraph> e : this.E0.get(role).entrySet()) + for (Entry e : this.E0.get(role).entrySet()) + { + String out = e.getValue().init.toDot(); + runDot(out, png); + } + } + } + /*if (this.paramArgs.containsKey(ParamCLArgFlag.PARAM_CORE_MODEL)) + { + System.out.println("\n" + model.toDot()); + } + if (this.paramArgs.containsKey(ParamCLArgFlag.PARAM_CORE_MODEL_PNG)) + { + String[] arg = this.paramArgs.get(ParamCLArgFlag.PARAM_CORE_MODEL_PNG); + String png = arg[0]; + runDot(model.toDot(), png); + }*/ + } + + /*private void assrtCoreValidate(Job job, GProtocolName simpname, boolean isExplicit, + //Map E0, + boolean... unfair) throws ScribbleException, CommandLineException + { + this.model = new ParamCoreSModelBuilder(job.sf).build(this.E0, isExplicit); + + job.debugPrintln("\n[rp-core] Built model:\n" + this.model.toDot()); + + if (unfair.length == 0 || !unfair[0]) + { + ParamCoreSafetyErrors serrs = this.model.getSafetyErrors(job, simpname); // job just for debug printing + if (serrs.isSafe()) + { + job.debugPrintln("\n[rp-core] Protocol safe."); + } + else + { + throw new ParamException("[rp-core] Protocol not safe:\n" + serrs); + } + } + + /*F17ProgressErrors perrs = m.getProgressErrors(); + if (perrs.satisfiesProgress()) + { + job.debugPrintln + //System.out.println + ("\n[f17] " + ((unfair.length == 0) ? "Fair protocol" : "Protocol") + " satisfies progress."); + } + else + { + + // FIXME: refactor eventual reception as 1-bounded stable check + Set staberrs = m.getStableErrors(); + if (perrs.eventualReception.isEmpty()) + { + if (!staberrs.isEmpty()) + { + throw new RuntimeException("[f17] 1-stable check failure: " + staberrs); + } + } + else + { + if (staberrs.isEmpty()) + { + throw new RuntimeException("[f17] 1-stable check failure: " + perrs); + } + } + + throw new F17Exception("\n[f17] " + ((unfair.length == 0) ? "Fair protocol" : "Protocol") + " violates progress.\n" + perrs); + }* / + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTApiGenConstants.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTApiGenConstants.java new file mode 100644 index 000000000..dff127cfa --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTApiGenConstants.java @@ -0,0 +1,46 @@ +package org.scribble.ext.go.core.codegen.statetype; + +public class ParamCoreSTApiGenConstants +{ + //public static final String GO_SCRIBBLERUNTIME_PACKAGE = "org/scribble/runtime/net"; + public static final String GO_SCRIBBLERUNTIME_SESSION_PACKAGE = "github.com/scribble/go-runtime/session"; + public static final String GO_SCRIBBLERUNTIME_SESSIONPARAM_PACKAGE = "github.com/scribble/go-runtime/session/param"; + public static final String GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE = "github.com/scribble/go-runtime/transport"; + public static final String GO_SCRIBBLERUNTIME_SHM_PACKAGE = "github.com/scribble/go-runtime/transport/shm"; + public static final String GO_SCRIBBLERUNTIME_BYTES_PACKAGE = "bytes"; + public static final String GO_SCRIBBLERUNTIME_GOB_PACKAGE = "encoding/gob"; + + public static final String GO_ENDPOINT_TYPE = "session.Endpoint"; // net.MPSTEndpoint; + public static final String GO_ENDPOINT_CONSTRUCTOR = "session.NewEndpoint"; + public static final String GO_ENDPOINT_PROTO = "Proto"; + public static final String GO_ENDPOINT_ERR = "Err"; + public static final String GO_ENDPOINT_WRITEALL = "WriteAll"; + public static final String GO_ENDPOINT_READALL = "ReadAll"; + public static final String GO_ENDPOINT_STARTPROTOCOL = "StartProtocol"; + public static final String GO_ENDPOINT_FINISHPROTOCOL = "FinishProtocol"; + public static final String GO_ENDPOINT_FINALISE = "Finalise"; + public static final String GO_ENDPOINT_ENDPOINT = "Endpoint"; + + public static final String GO_FINALISER_TYPE = "session.Finaliser"; // net.MPSTEndpoint; + + public static final String GO_ROLE_TYPE = "session.Role"; + public static final String GO_ROLE_CONSTRUCTOR = "session.NewPRole"; + + public static final String GO_PARAMROLE_TYPE = "session.ParamRole"; + + public static final String GO_LINEARRESOURCE_TYPE = "session.LinearResource"; // net.LinearResource + public static final String GO_LINEARRESOURCE_USE = "Use"; // net.LinearResource + + public static final String GO_SCHAN_ENDPOINT = "ept"; // ep; + public static final String GO_SCHAN_LINEARRESOURCE = "res"; // state + + public static final String GO_SCHAN_END_TYPE = "End"; + + public static final String GO_IO_FUN_RECEIVER = "s"; + + public static final String GO_CROSS_SEND_FUN_PREFIX = "Send"; + public static final String GO_CROSS_SEND_FUN_ARG = "arg"; + public static final String GO_CROSS_RECEIVE_FUN_PREFIX = "Recv"; + public static final String GO_CROSS_RECEIVE_FUN_ARG = "arg"; + +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTBranchActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTBranchActionBuilder.java new file mode 100644 index 000000000..fdf5a7346 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTBranchActionBuilder.java @@ -0,0 +1,143 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STBranchActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.main.GoJob; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class ParamCoreSTBranchActionBuilder extends STBranchActionBuilder +{ + /*@Override + public String build(STStateChanApiBuilder api, EState curr, EAction a) // FIXME: "overriding" GSTStateChanAPIBuilder.buildAction to hack around *interface return // FIXME: factor out + { + EState succ = curr.getSuccessor(a); + return + "func (s *" + getStateChanType(api, curr, a) + ") " + getActionName(api, a) + "(" + + buildArgs(a) + + ") " + getReturnType(api, curr, succ) + " {\n" // HACK: Return type is interface, so no need for *return (unlike other state chans) + + "s.state.Use()\n" + + buildBody(api, curr, a, succ) + "\n" + + "}"; + }*/ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_PREFIX + "_" + + ParamCoreSTStateChanApiBuilder.getGeneratedParamRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_ARG + + i + " *" + a.payload.elems.get(i) + //+ ", reduceFn" + i + " func(" + ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + i + " []int) int" // No: singleton choice subj (not multichoices) + ).collect(Collectors.joining(", ")); + } + + /*@Override + public String getReturnType(STStateChanApiBuilder api, EState curr, EState succ) + { + return api.cb.getCaseStateChanName(api, curr); + }*/ + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + /*String sEpRecv = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + /*ParamRole r = (ParamRole) a.peer; + ParamRange g = r.ranges.iterator().next(); + Function foo = e -> + { + if (e instanceof ParamIndexInt) + { + return e.toString(); + } + else if (e instanceof ParamIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + };*/ + + String res = + /*sEpRecv + + "(" + sEpProto + + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "\"" + a.mid + "\")\n" + + IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> sEpRecv + "(" + sEpProto + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "arg" + i + ")") + .collect(Collectors.joining("\n")) + "\n" + /*+ "if " + sEpErr + " != nil {\n" + + "return nil\n" + + "}\n"*/ + //buildReturn(api, curr, succ); + "ch, selected := <-s._" + a.mid + "_Chan\n" + + "if !selected {\n" + + "\treturn nil // select ignores nilchan\n" + + "}\n"; + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + + res += + //+ "data := make([]int, " + foo.apply(g.end) + ")\n" + //+ "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" // FIXME: num args + "var decoded int\n" + + "bs := <-s.data\n"; + + res += + ((((GoJob) api.job).noCopy) + ? + "decoded = *bs[0].(*" + a.payload.elems.get(0) + ")\n" + : + "if err := gob.NewDecoder(bytes.NewReader(bs[0])).Decode(&decoded); err != nil {\n" + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Errors <- session.DeserialiseFailed(err, \"" + getActionName(api, a) + "\"," + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Self.Name())\n" + + "}\n" + //+ "data[0] = decoded\n" + //+ "}\n" + ) + + //+ "*arg0 = reduceFn0(data)\n" // FIXME: arg0 + // + "*arg0 = data[0]\n" + + "*arg0 = decoded\n"; + } + + return res + + "return ch"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTBranchStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTBranchStateBuilder.java new file mode 100644 index 000000000..91566ac21 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTBranchStateBuilder.java @@ -0,0 +1,186 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.codegen.statetype.STBranchStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.model.endpoint.actions.EReceive; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +public class ParamCoreSTBranchStateBuilder extends STBranchStateBuilder +{ + public ParamCoreSTBranchStateBuilder(ParamCoreSTBranchActionBuilder bb) + { + super(bb); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + String sEpRecv = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + + //return ((ParamCoreSTStateChanApiBuilder) api).getStateChanPremable(s); + ParamCoreSTStateChanApiBuilder apigen = (ParamCoreSTStateChanApiBuilder) api; + Role r = apigen.actual.getName(); + GProtocolName simpname = apigen.apigen.proto.getSimpleName(); + String tname = apigen.getStateChanName(s); + String epType = ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, r); + String res = + apigen.apigen.generateRootPackageDecl() + "\n" + + "\n" + + apigen.apigen.generateScribbleRuntimeImports() + "\n" + + + (((GoJob) api.job).noCopy ? "" : + Stream.of(ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_BYTES_PACKAGE, ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_GOB_PACKAGE) + .map(x -> "import \"" + x + "\"").collect(Collectors.joining("\n"))) + + + "\n" + + "type " + tname + " struct{\n" + //+ ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + ParamCoreSTApiGenConstants.GO_ENDPOINT_TYPE + "\n" + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epType + "\n" + + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE +"\n" + + s.getActions().stream().map(a -> "_" + a.mid + "_Chan chan chan *" + apigen.getStateChanName(s.getSuccessor(a)) + "\n") + .collect(Collectors.joining("")) + + (((GoJob) apigen.job).noCopy ? "data chan []interface{}" : "data chan [][]byte\n" ) + + "}\n"; + + res += "\n" + + "func (ep *" + epType + ") New" + + ((s.id != api.graph.init.id) ? tname + : ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(((ParamCoreSTStateChanApiBuilder) api).actual) + "_1") // cf. ParamCoreSTStateChanApiBuilder::getStateChanPremable init state case + + "() *" + tname + " {\n" // FIXME: factor out + + "s := &" + tname + " { " + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": ep" + + ", " + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + ": new(" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "), " + + s.getActions().stream().map(a -> "_" + a.mid + "_Chan: make(chan chan *" + apigen.getStateChanName(s.getSuccessor(a))+ ", 1)") + .collect(Collectors.joining(", ")) + ", " + + + "data: make(chan " + (((GoJob) api.job).noCopy ? "[]interface{}" : "[][]byte") + ", 1)" + + + "}\n" + + "s.foo()\n" + + "return s\n" + + "}\n"; + + res += "\n" + + "func (s *" + tname + ") foo() {\n" + + "s." + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + "." + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n"; + + RPIndexedRole peer = (RPIndexedRole) s.getActions().iterator().next().peer; + RPInterval g = peer.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + + if (((GoJob) apigen.job).noCopy) + { + res += + "label := " + sEpRecv + "Raw(" + sEpProto + "." + peer.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n" + + "op := *label[0].(*string)\n"; // FIXME: cast for safety? + } + else + { + res += + "label := " + sEpRecv + "(" + sEpProto + "." + peer.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n" + + "op := string(label[0])\n"; // FIXME: cast for safety? + } + + List as = s.getActions(); + boolean allEmpty = as.stream().allMatch(a -> a.payload.elems.isEmpty()); + if (!allEmpty) // FIXME: + { + res += + "b := " + sEpRecv + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + peer.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n"; + // See below for sending b to s.data + // FIXME: arg0 // FIXME: args depends on label // FIXME: store args in s.args + } + + res+= "switch op {\n" + + s.getActions().stream().map(a -> + { + String sEp = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + return + "\tcase \"" + a.mid + "\":\n" + + "\t\tch := make(chan *" + apigen.getStateChanName(s.getSuccessor(a)) + ", 1)\n" + + "\t\tch <- " + apigen.getSuccStateChan(this.bb, s, s.getSuccessor(a), sEp) + "\n" + + "\t\ts._" + a.mid + "_Chan <- ch\n" + + "\t\t" + s.getActions().stream() + .filter(otheract -> otheract.mid != a.mid) + .map(otheract -> { return "close(s._" + otheract.mid + "_Chan)"; }) + .collect(Collectors.joining("\n\t")) + "\n"; + }).collect(Collectors.joining("\n")) + + "\n" + + "\tdefault:\n" // default case captures unrecognised choice label + + "\t\t" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + + "Errors <- session.UnknownChoiceLabelError{Label: op}\n" + + "\t}\n"; // End of switch + + if (!allEmpty) + { + // b is result of a sEpRecv/sEpRecvRaw + res += "\ts.data <- b\n"; + } + + res += "}\n"; // End of func foo + + return res; + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + String out = getPreamble(api, s); + + for (EAction a : s.getActions()) + { + out += "\n\n"; + if (a instanceof EReceive) // FIXME: factor out action kind + { + out += this.bb.build(api, s, a); // Getting 1 checks non-unary + } + else + { + throw new RuntimeException("Shouldn't get in here: " + a); + } + } + + return out; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTEndStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTEndStateBuilder.java new file mode 100644 index 000000000..df20e35e1 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTEndStateBuilder.java @@ -0,0 +1,39 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import org.scribble.codegen.statetype.STEndStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; + +public class ParamCoreSTEndStateBuilder extends STEndStateBuilder +{ + public ParamCoreSTEndStateBuilder() + { + + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + return getPreamble(api, s); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + ParamCoreSTStateChanApiBuilder schangen = (ParamCoreSTStateChanApiBuilder) api; + //return GSTStateChanAPIBuilder.getStateChanPremable(api, s); + String tname = api.getStateChanName(s); + String res = + schangen.apigen.generateRootPackageDecl() + "\n" + + "\n" + ////+ "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PACKAGE + "\"\n" + ////+ schangen.apigen.generateScribbleRuntimeImports() + "\n" + //+ "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n" + + "\n" + + "type " + tname + " struct{\n" + //+ ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + ParamCoreSTApiGenConstants.GO_ENDPOINT_TYPE + "\n" // FIXME: factor out + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(api.gpn.getSimpleName(), api.role) + "\n" // FIXME: factor out + + "}"; + return res; // No LinearResource + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTEndpointApiGenerator.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTEndpointApiGenerator.java new file mode 100644 index 000000000..d4474a694 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTEndpointApiGenerator.java @@ -0,0 +1,124 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.main.Job; +import org.scribble.main.ScribbleException; +import org.scribble.model.endpoint.EGraph; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +// Duplicated from org.scribble.ext.go.codegen.statetype.go.GoSTEndpointApiGenerator +public class ParamCoreSTEndpointApiGenerator +{ + public final Job job; + public final GProtocolName proto; + public final Role self; // FIXME: base endpoint API gen is role-oriented, while session API generator should be neutral + //public final Map actuals; + public final Map> actuals; + //public final EGraph graph; + + //public final Map> all; + + public ParamCoreSTEndpointApiGenerator(Job job, GProtocolName fullname, Role self, //Map actuals) + Map> actuals) + { + this.job = job; + this.proto = fullname; + this.self = self; + this.actuals = Collections.unmodifiableMap(actuals); + //this.graph = graph; + //this.all = Collections.unmodifiableMap(all); + } + + // N.B. the base EGraph class will probably be replaced by a more specific (and more helpful) param-core class later + public Map build() throws ScribbleException + { + Map res = new HashMap<>(); // filepath -> source + res.putAll(buildSessionApi()); + for (Entry actual : this.actuals.get(this.self).entrySet()) + { + res.putAll(buildStateChannelApi(actual.getKey(), actual.getValue())); + } + return res; + } + + //@Override + public Map buildSessionApi() // FIXME: factor out + { + this.job.debugPrintln("\n[param-core] Running " + ParamCoreSTSessionApiBuilder.class + " for " + this.proto + "@" + this.self); + //throw new RuntimeException("[param-core] TODO:"); + return new ParamCoreSTSessionApiBuilder(this).build(); + } + + public Map buildStateChannelApi(RPRoleVariant actual, EGraph graph) // FIXME: factor out + { + this.job.debugPrintln("\n[param-core] Running " + ParamCoreSTStateChanApiBuilder.class + " for " + this.proto + "@" + this.self); + return new ParamCoreSTStateChanApiBuilder(this, actual, graph).build(); + } + + public String getGeneratedEndpointType() + { + /*return "Endpoint_" + this.proto.getSimpleName() + "_" + //+ getGeneratedActualRoleName(); // No: endpoint covers all actual roles of this role name + + this.self;*/ + return getGeneratedEndpointType(this.proto.getSimpleName(), this.self); + } + + public static String getGeneratedEndpointType(GProtocolName simpname, Role r) + { + //return "Endpoint_" + simpname + "_" + r; + return simpname + "_" + r; + } + + // Doesn't use coranges -- same as getGeneratedParamRoleName? + public static String getGeneratedActualRoleName(RPRoleVariant actual) + { + /*return actual.getName() + + actual.ranges.toString().replaceAll("\\[", "_").replaceAll("\\]", "_").replaceAll("\\.", "_");*/ + if (actual.intervals.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + actual); + } + RPInterval g = actual.intervals.iterator().next(); + return actual.getName() + "_" + g.start + "To" + g.end; + } + + //@Override + public String getRootPackage() // Derives only from proto name + { + //throw new RuntimeException("[param-core] TODO:"); + return this.proto.getSimpleName().toString(); + } + + public String generateRootPackageDecl() + { + //throw new RuntimeException("[param-core] TODO: "); + return "package " + getRootPackage(); + } + + //@Override + public List getScribbleRuntimeImports() // FIXME: factor up + { + return Stream.of( + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSIONPARAM_PACKAGE + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_BYTES_PACKAGE, + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_GOB_PACKAGE + ).collect(Collectors.toList()); + } + + public String generateScribbleRuntimeImports() + { + return getScribbleRuntimeImports().stream().map(x -> "import \"" + x + "\"").collect(Collectors.joining("\n")); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTOutputStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTOutputStateBuilder.java new file mode 100644 index 000000000..31fef28ae --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTOutputStateBuilder.java @@ -0,0 +1,20 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import org.scribble.codegen.statetype.STOutputStateBuilder; +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; + +public class ParamCoreSTOutputStateBuilder extends STOutputStateBuilder +{ + public ParamCoreSTOutputStateBuilder(STSendActionBuilder sb) + { + super(sb); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + return ((ParamCoreSTStateChanApiBuilder) api).getStateChanPremable(s); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTReceiveActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTReceiveActionBuilder.java new file mode 100644 index 000000000..2193257a6 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTReceiveActionBuilder.java @@ -0,0 +1,138 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class ParamCoreSTReceiveActionBuilder extends STReceiveActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_PREFIX + "_" + + ParamCoreSTStateChanApiBuilder.getGeneratedParamRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_ARG + + i + " *" + a.payload.elems.get(i) + + ", reduceFn" + i + " func(" + ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + i + " []int) int" + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + String sEpRecv = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval g = r.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + /*sEpRecv + + "(" + sEpProto + + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "\"" + a.mid + "\")\n" + + IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> sEpRecv + "(" + sEpProto + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "arg" + i + ")") + .collect(Collectors.joining("\n")) + "\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + "\tvar decoded "+a.payload.elems.get(0)+"\n" + + "\tif err := gob.NewDecoder(bytes.NewReader(b[i-"+foo.apply(g.start)+"])).Decode(&decoded); err != nil {\n\t\t" + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Errors <- session.DeserialiseFailed(err, \"" + getActionName(api, a) +"\", " + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Self.Name())\n" + + "\t}\n" + + "\tdata[i-"+foo.apply(g.start)+"] = decoded\n" + + "}\n" + + "*arg0 = reduceFn(data)" + /*+ "if " + sEpErr + " != nil {\n" + + "return nil\n" + + "}\n"*/ + + String res = + sEpRecv + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + r.getName() + ", " + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n"; // Discard op + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + res += + (((GoJob) api.job).noCopy + ? + "b := " + sEpRecv + "Raw(" + sEpProto + "." + r.getName() + ", " + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n" + + "data := make([]" + a.payload.elems.get(0) + ", len(b))\n" + + "for i := 0; i < len(b); i++ {\n" + + "data[i] = *b[i].(*" + a.payload.elems.get(0) + ")\n" + + "}\n" + + "*arg0 = reduceFn0(data)\n" + : + "b := " + sEpRecv + "(" + sEpProto + "." + r.getName() + ", " + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n" + + "data := make([]int, " + foo.apply(g.end) + ")\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" // FIXME: num args + + "var decoded int\n" + + "if err := gob.NewDecoder(bytes.NewReader(b[i-1])).Decode(&decoded); err != nil {\n" + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Errors <- session.DeserialiseFailed(err, \"" + getActionName(api, a) + "\"," + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Self.Name())\n" + + "}\n" + + "data[i-1] = decoded\n" + + "}\n" + + "*arg0 = reduceFn0(data)\n"); // FIXME: arg0 + } + + return res + + buildReturn(api, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTReceiveStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTReceiveStateBuilder.java new file mode 100644 index 000000000..14bda71ff --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTReceiveStateBuilder.java @@ -0,0 +1,20 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STReceiveStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; + +public class ParamCoreSTReceiveStateBuilder extends STReceiveStateBuilder +{ + public ParamCoreSTReceiveStateBuilder(STReceiveActionBuilder sb) + { + super(sb); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + return ((ParamCoreSTStateChanApiBuilder) api).getStateChanPremable(s); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTSendActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTSendActionBuilder.java new file mode 100644 index 000000000..3e08a3686 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTSendActionBuilder.java @@ -0,0 +1,148 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class ParamCoreSTSendActionBuilder extends STSendActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_PREFIX + "_" + + ParamCoreSTStateChanApiBuilder.getGeneratedParamRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + + i + " " + a.payload.elems.get(i) + + ", splitFn" + i + " func(" + ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + i + " int, i" + i + " int) int" + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + String sEpWrite = + //s.ep.Write + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval g = r.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + + String res = + (((GoJob) api.job).noCopy + ? + "labels := make([]interface{}, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" + + "tmp := \"" + a.mid + "\"\n" + + "\tlabels[i-" + foo.apply(g.start) + "] = &tmp\n" + + "}\n" + : + "labels := make([][]byte, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" + + "\tlabels[i-" + foo.apply(g.start) + "] = []byte(\"" + a.mid + "\")\n" + + "}\n") + + + sEpWrite + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "labels)\n"; + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + res += + (((GoJob) api.job).noCopy + ? + "b := make([]interface{}, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end)+"; i++ {\n" + + "tmp := splitFn0(arg0, i)\n" + + "\tb[i-"+foo.apply(g.start)+"] = &tmp\n" + + "}\n" + : + "b := make([][]byte, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + "\tvar buf bytes.Buffer\n" + + "\tif err := gob.NewEncoder(&buf).Encode(splitFn0(arg0, i)); err != nil {\n\t\t" // only arg0 + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Errors <- session.SerialiseFailed(err, \"" + getActionName(api, a) +"\", " + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Self.Name())\n" + + "\t}\n" + + "\tb[i-"+foo.apply(g.start)+"] = buf.Bytes()\n" + + "}\n") + + + sEpWrite + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + //+ ".(*" + api.gpn.getSimpleName() +")" + + "." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + //+ "\"" + a.mid + "\"" + + "b" + + ")\n"; + /*+ IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> sEpWrite + "(" + sEpProto + //+ ".(*" + api.gpn.getSimpleName() +")." + + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "arg" + i + ")") + .collect(Collectors.joining("\n")) + "\n"*/ + /*+ "if " + sEpErr + " != nil {\n" + + "return nil\n" + + "}\n"*/ + } + + return + res + + buildReturn(api, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTSessionApiBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTSessionApiBuilder.java new file mode 100644 index 000000000..5766249bf --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTSessionApiBuilder.java @@ -0,0 +1,194 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.scribble.ast.Module; +import org.scribble.ast.ProtocolDecl; +import org.scribble.ext.go.ast.RPRoleDecl; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EGraph; +import org.scribble.type.kind.Global; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +// Cf. STStateChanApiBuilder +public class ParamCoreSTSessionApiBuilder // FIXME: make base STSessionApiBuilder +{ + private ParamCoreSTEndpointApiGenerator apigen; + + //private final Map> actuals; + + public ParamCoreSTSessionApiBuilder(ParamCoreSTEndpointApiGenerator apigen)//, Map> actuals) + { + this.apigen = apigen; + //this.actuals = Collections.unmodifiableMap(actuals); + } + + //@Override + public Map build() // FIXME: factor out + { + Module mod = this.apigen.job.getContext().getModule(this.apigen.proto.getPrefix()); + GProtocolName simpname = this.apigen.proto.getSimpleName(); + ProtocolDecl gpd = mod.getProtocolDecl(simpname); + List roles = gpd.header.roledecls.getRoles(); + + /*Set instates = new HashSet<>(); + Predicate f = s -> s.getStateKind() == EStateKind.UNARY_INPUT || s.getStateKind() == EStateKind.POLY_INPUT; + if (f.test(this.apigen.graph.init)) + { + instates.add(this.apigen.graph.init); + } + instates.addAll(MState.getReachableStates(this.apigen.graph.init).stream().filter(f).collect(Collectors.toSet()));*/ + + // roles + String sessPack = + //"package " + this.apigen.getRootPackage() + "\n" // FIXME: factor out + this.apigen.generateRootPackageDecl() + "\n" + + "\n" + //+ "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PACKAGE + "\"\n" + + this.apigen.generateScribbleRuntimeImports() + "\n"; + + sessPack += "\n" + + "type " + simpname + " struct {\n" + + roles.stream().map(r -> r + " " + ParamCoreSTApiGenConstants.GO_ROLE_TYPE + "\n").collect(Collectors.joining("")) + // Just need role name constants for now -- params not fixed until endpoint creation + + "}\n" + + "\n" + + "func New" + simpname + "() *" + simpname + " {\n" + + "return &" + simpname + "{ " + roles.stream().map(r -> ParamCoreSTApiGenConstants.GO_ROLE_CONSTRUCTOR + + "(\"" + r + "\")").collect(Collectors.joining(", ")) + " }\n" + // Singleton types? + + "}\n"; + + /*sessPack += + roles.stream().map(r -> + "type _" + r + " struct { }\n" + + "\n" + + "func (*_" + r +") GetRoleName() string {\n" + + "return \"" + r + "\"\n" + + "}\n" + + "\n" + + "var __" + r + " *_" + r + "\n" + + "\n" + + "func new" + r + "() *_" + r + " {\n" // FIXME: not concurrent + + "if __" + r + " == nil {\n" + + "__"+ r + " = &_" + r + "{}\n" + + "}\n" + + "return __" + r + "\n" + + "}" + ).collect(Collectors.joining("\n\n")) + "\n" + + "\n";*/ + + // Protocol and role specific endpoints + //Function epTypeName = r -> "_Endpoint" + simpname + "_" + r; + sessPack += + roles.stream().map(r -> + { + String epTypeName = ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, r); + List vars = + gpd.getHeader().roledecls.getDecls().stream().filter(rd -> rd.getDeclName().equals(r)) + .flatMap(rd -> ((RPRoleDecl) rd).params.stream()).collect(Collectors.toList()); + return + "\n\ntype " + epTypeName + " struct {\n" // FIXME: factor out + + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO + " *" + simpname + "\n" + + this.apigen.actuals.get(r).keySet().stream() + //.filter(a -> a.getName().equals(r)) + .map(a -> + //+ this.apigen.actuals.entrySet().stream().flatMap(e -> e.getValue().keySet().stream()).map(a -> + { + String actualName = ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(a); + /*return "Sub_" + actualName + " func(*" + simpname + "_" + actualName + "_1) *" // FIXME: init statechan, factor out with makeSTStateName + //+ ParamCoreSTApiGenConstants.GO_SCHAN_END_TYPE + "\n"; + + ParamCoreSTStateChanApiBuilder.makeEndStateName(simpname, a) + "\n";*/ + return actualName + "s map[int] func(*" + simpname + "_" + actualName + "_1) *" // FIXME: init statechan, factor out with makeSTStateName + + ParamCoreSTStateChanApiBuilder.makeEndStateName(simpname, a) + "\n"; + }).collect(Collectors.joining("")) + + " *" + ParamCoreSTApiGenConstants.GO_ENDPOINT_TYPE + "\n" + + "}\n" + + "\n" + + "func (p *" + simpname + ") New" + epTypeName + //+ "(params map[string]int) + + "(" + + vars.stream().map(v -> v + " int").collect(Collectors.joining(", ")) + ")" + + "(*" + epTypeName + ") {\n" + + + "ep := &" + epTypeName + "{ " + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO + ": p,\n" + + + this.apigen.actuals.get(r).keySet().stream() + .map(a -> + { + String actualName = ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(a); + return actualName + "s: make(map[int] func(*" + simpname + "_" + actualName + "_1) *" // FIXME: init statechan, factor out with makeSTStateName + + ParamCoreSTStateChanApiBuilder.makeEndStateName(simpname, a) + ")"; + }).collect(Collectors.joining(", ")) + ",\n" + + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + ": " + + ParamCoreSTApiGenConstants.GO_ENDPOINT_CONSTRUCTOR + "(p, p." + r + ")}\n" + + + this.apigen.actuals.entrySet().stream().filter(e -> !e.getKey().equals(r)) + .map(e -> + { + Map tmp = e.getValue(); + if (tmp.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + tmp); + } + RPRoleVariant peer = tmp.keySet().iterator().next(); + RPInterval g = peer.intervals.iterator().next(); + Function foo = ee -> + { + if (ee instanceof RPIndexInt) + { + return ee.toString(); + } + else if (ee instanceof RPIndexVar) + { + return "ep.Params[\"" + ee + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + ee); + } + }; + return + "ep.Params = map[string]int {" + vars.stream().map(v -> "\"" + v + "\": " + v).collect(Collectors.joining(", ")) + "}\n" + + "ep.Peers[p." + peer.getName() + "] = struct{Start int; End int}{" + foo.apply(g.start) + ", " + foo.apply(g.end) + "}\n" + + "for i := ep." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + ".Peers[p." + peer.getName() + "].Start; i <= ep.Peers[p." + peer.getName() + "].End; i++ {\n" + + "\tp." + peer.getName() + ".(session.ParamRole).Register(i)\n" + + "}\n"; + }).collect(Collectors.joining("")) + + + "return ep\n" + + "}\n" + + this.apigen.actuals.get(r).keySet().stream() + //.filter(a -> a.getName().equals(r)) + .map(a -> + //+ this.apigen.actuals.entrySet().stream().flatMap(e -> e.getValue().keySet().stream()).map(a -> + { + String actualName = ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(a); + return + "\nfunc (ep *" + epTypeName + ") " + + "Register_" + actualName + + "(i int, impl func(*" + simpname + "_" + actualName + "_1) *" // FIXME: factor out with above + //+ ParamCoreSTApiGenConstants.GO_SCHAN_END_TYPE + ") {\n" + + ParamCoreSTStateChanApiBuilder.makeEndStateName(simpname, a) + ") {\n" + //+ "ep.Sub_" + actualName + " = impl\n" + + "ep." + actualName + "s[i] = impl\n" + + "ep.Proto."+ r +".(session.ParamRole).Register(i)\n" + + "}\n"; + }).collect(Collectors.joining("")); + }).collect(Collectors.joining("")); + + String dir = this.apigen.proto.toString().replaceAll("\\.", "/") + "/"; + Map res = new HashMap<>(); + res.put(dir + simpname + ".go", sessPack); + return res; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTStateChanApiBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTStateChanApiBuilder.java new file mode 100644 index 000000000..27082571a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype/ParamCoreSTStateChanApiBuilder.java @@ -0,0 +1,311 @@ +package org.scribble.ext.go.core.codegen.statetype; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.codegen.statetype.STActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossSend; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEDotReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEDotSend; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEMultiChoicesReceive; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.model.MState; +import org.scribble.model.endpoint.EGraph; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +// Duplicated from org.scribble.ext.go.codegen.statetype.go.GoSTStateChanAPIBuilder +public class ParamCoreSTStateChanApiBuilder extends STStateChanApiBuilder +{ + protected final ParamCoreSTEndpointApiGenerator apigen; + public final RPRoleVariant actual; // this.apigen.self.equals(this.actual.getName()) + //public final EGraph graph; + + private int counter = 1; + + // N.B. the base EGraph class will probably be replaced by a more specific (and more helpful) param-core class later + // actual.getName().equals(this.role) + public ParamCoreSTStateChanApiBuilder(ParamCoreSTEndpointApiGenerator apigen, RPRoleVariant actual, EGraph graph) + { + super(apigen.job, apigen.proto, apigen.self, graph, + new ParamCoreSTOutputStateBuilder(new ParamCoreSTSendActionBuilder()), + new ParamCoreSTReceiveStateBuilder(new ParamCoreSTReceiveActionBuilder()), + new ParamCoreSTBranchStateBuilder(new ParamCoreSTBranchActionBuilder()), + null, //new GoSTCaseBuilder(new GoSTCaseActionBuilder()), + new ParamCoreSTEndStateBuilder()); + + //throw new RuntimeException("[param-core] TODO:"); + this.apigen = apigen; + this.actual = actual; + } + + protected RPRoleVariant getSelf() + { + return (RPRoleVariant) this.getSelf(); + } + + // Not actual roles; param roles in EFSM actions -- cf. ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName + public static String getGeneratedParamRoleName(RPIndexedRole r) + { + //return r.toString().replaceAll("\\[", "_").replaceAll("\\]", "_").replaceAll("\\.", "_"); + if (r.intervals.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + r); + } + RPInterval g = r.intervals.iterator().next(); + return r.getName() + "_" + g.start + "To" + g.end; + } + + + /*@Override + public String getPackage() + { + //throw new RuntimeException("[param-core] TODO:"); + return this.gpn.getSimpleName().toString(); + }*/ + + @Override + protected String makeSTStateName(EState s) + { + //throw new RuntimeException("[param-core] TODO:"); + if (s.isTerminal()) + { + ////return "_EndState"; + //return ParamCoreSTApiGenConstants.GO_SCHAN_END_TYPE; + return makeEndStateName(this.apigen.proto.getSimpleName(), this.actual); + } + return this.apigen.proto.getSimpleName() + "_" + + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(this.actual) + + "_" + this.counter++; + } + + public static String makeEndStateName(GProtocolName simpname, RPRoleVariant r) + { + return simpname + "_" + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(r) + "_" + ParamCoreSTApiGenConstants.GO_SCHAN_END_TYPE; + } + + @Override + public String getStateChannelFilePath(String filename) + { + //throw new RuntimeException("[param-core] TODO:"); + if (filename.startsWith("_")) // Cannot use "_" prefix, ignored by Go + { + filename = "$" + filename.substring(1); + } + return this.gpn.toString().replaceAll("\\.", "/") + "/" + filename + ".go"; + } + + public String getActualRoleName() + { + return this.apigen.self.toString(); + } + + protected String getStateChanPremable(EState s) + { + //throw new RuntimeException("[param-core] TODO: "); + Role r = this.actual.getName(); + GProtocolName simpname = this.apigen.proto.getSimpleName(); + String tname = this.getStateChanName(s); + String epType = ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, r); + String res = + this.apigen.generateRootPackageDecl() + "\n" + + "\n" + + this.apigen.generateScribbleRuntimeImports() + "\n" + + (s.isTerminal() || ((GoJob) apigen.job).noCopy ? "" : + Stream.of(ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_BYTES_PACKAGE, ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_GOB_PACKAGE) + .map(x -> "import \"" + x + "\"").collect(Collectors.joining("\n"))) + + "\n" + + "type " + tname + " struct{\n" + //+ ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + ParamCoreSTApiGenConstants.GO_ENDPOINT_TYPE + "\n" + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epType + "\n" + + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE +"\n" + + "}\n"; + + if (s.id == this.graph.init.id) + { + res += "\n" + + "func (ep *" + epType + ") New" + //+ tname + + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(this.actual) + "_1" // cf. makeSTStateName + + "() *" + tname + " {\n" // FIXME: factor out + //+ "ep." + this.role + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_STARTPROTOCOL + "()\n" + + "return &" + tname + " { " + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": ep" + + ", " + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + ": new(" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ")}\n" + + "}"; + } + + return res; + } + + @Override + public String buildAction(STActionBuilder ab, EState curr, EAction a) // Here because action builder hierarchy not suitable (extended by action kind, not by target language) + { + EState succ = curr.getSuccessor(a); + if (getStateKind(curr) == ParamCoreEStateKind.CROSS_RECEIVE && curr.getActions().size() > 1) + { + return + "func (" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + " *" + ab.getStateChanType(this, curr, a) + ") " + ab.getActionName(this, a) + "(" + + ab.buildArgs(this, a) + + ") <-chan *" + ab.getReturnType(this, curr, succ) + " {\n" + + ab.buildBody(this, curr, a, succ) + "\n" + + "}"; + } + else + { + //throw new RuntimeException("[param-core] TODO: "); + return + "func (" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + " *" + ab.getStateChanType(this, curr, a) + ") " + ab.getActionName(this, a) + "(" + + ab.buildArgs(this, a) + + ") *" + ab.getReturnType(this, curr, succ) + " {\n" + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + "." + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n" + + ab.buildBody(this, curr, a, succ) + "\n" + + "}"; + } + } + + @Override + public String getChannelName(STStateChanApiBuilder api, EAction a) + { + //throw new RuntimeException("[param-core] TODO: "); + return + //"s.ep.Chans[s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + "]"; + "s.ep.GetChan(s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + ")"; + } + + @Override + public String buildActionReturn(STActionBuilder ab, EState curr, EState succ) // FIXME: refactor action builders as interfaces and use generic parameter for kind + { + //throw new RuntimeException("[param-core] TODO: "); + String sEp = + //"s.ep" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + String res = ""; + + if (succ.isTerminal()) + { + res += sEp + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_FINISHPROTOCOL + "()\n"; + } + res += "return " + getSuccStateChan(ab, curr, succ, sEp); + return res; + } + + public String getSuccStateChan(STActionBuilder ab, EState curr, EState succ, String sEp) + { + if (getStateKind(succ) == ParamCoreEStateKind.CROSS_RECEIVE && succ.getActions().size() > 1) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + + "New" + //+ getStateChanName(succ) + + ((succ.id != this.graph.init.id) ? getStateChanName(succ) + : ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(this.actual) + "_1") // cf. ParamCoreSTStateChanApiBuilder::getStateChanPremable init state case + + "()"; + } + else + { + String res = "&" + ab.getReturnType(this, curr, succ) + "{ " + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": " + sEp; + if (!succ.isTerminal()) + { + res += ", " + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + ": new(" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ")"; // FIXME: EndSocket LinearResource special case + } + res += " }"; + return res; + } + } + + @Override + public Map build() // filepath -> source + { + Map api = new HashMap<>(); + Set states = new LinkedHashSet<>(); + states.add(this.graph.init); + states.addAll(MState.getReachableStates(this.graph.init)); + for (EState s : states) + { + switch (getStateKind(s)) + { + case CROSS_SEND: api.put(getStateChannelFilePath(getStateChanName(s)), this.ob.build(this, s)); break; + case CROSS_RECEIVE: + { + if (s.getActions().size() > 1) + { + api.put(getStateChannelFilePath(getStateChanName(s)), this.bb.build(this, s)); + //api.put(getFilePath(this.cb.getCaseStateChanName(this, s)), this.cb.build(this, s)); // FIXME: factor out + } + else + { + api.put(getStateChannelFilePath(getStateChanName(s)), this.rb.build(this, s)); + } + break; + } + case DOT_SEND: + { + throw new RuntimeException("[param-core] TODO: " + s); + } + case DOT_RECEIVE: + { + throw new RuntimeException("[param-core] TODO: " + s); + } + case MULTICHOICES_RECEIVE: + { + throw new RuntimeException("[param-core] TODO: " + s); + } + case TERMINAL: api.put(getStateChannelFilePath(getStateChanName(s)), this.eb.build(this, s)); break; // FIXME: without subpackages, all roles share same EndSocket + default: throw new RuntimeException("[param-core] Shouldn't get in here: " + s); + } + } + return api; + } + + + // FIXME: make ParamCoreEState + enum ParamCoreEStateKind { CROSS_SEND, CROSS_RECEIVE, DOT_SEND, DOT_RECEIVE, MULTICHOICES_RECEIVE, TERMINAL } + + protected static ParamCoreEStateKind getStateKind(EState s) + { + List as = s.getActions(); + if (as.isEmpty()) + { + return ParamCoreEStateKind.TERMINAL; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreECrossSend)) + { + return ParamCoreEStateKind.CROSS_SEND; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreECrossReceive)) + { + return ParamCoreEStateKind.CROSS_RECEIVE; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreEDotSend)) + { + return ParamCoreEStateKind.DOT_SEND; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreEDotReceive)) + { + return ParamCoreEStateKind.DOT_RECEIVE; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreEMultiChoicesReceive)) + { + return ParamCoreEStateKind.MULTICHOICES_RECEIVE; + } + else + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + s); + } + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTApiGenConstants.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTApiGenConstants.java new file mode 100644 index 000000000..ffebb8835 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTApiGenConstants.java @@ -0,0 +1,49 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +public class ParamCoreSTApiGenConstants +{ + //public static final String GO_SCRIBBLERUNTIME_PACKAGE = "org/scribble/runtime/net"; + public static final String GO_SCRIBBLERUNTIME_SESSION_PACKAGE = "github.com/rhu1/scribble-go-runtime/runtime/session"; + public static final String GO_SCRIBBLERUNTIME_SESSIONPARAM_PACKAGE = "github.com/scribble/go-runtime/session/param"; + public static final String GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE = "github.com/rhu1/scribble-go-runtime/runtime/transport"; + public static final String GO_SCRIBBLERUNTIME_SHM_PACKAGE = "github.com/scribble/go-runtime/transport/shm"; + public static final String GO_SCRIBBLERUNTIME_BYTES_PACKAGE = "bytes"; + public static final String GO_SCRIBBLERUNTIME_GOB_PACKAGE = "encoding/gob"; + + public static final String GO_ENDPOINT_TYPE = "session.Endpoint"; // net.MPSTEndpoint; + public static final String GO_ENDPOINT_CONSTRUCTOR = "session.NewEndpoint"; + public static final String GO_ENDPOINT_PROTO = "Proto"; + public static final String GO_ENDPOINT_ERR = "Err"; + public static final String GO_ENDPOINT_WRITEALL = "Send"; + public static final String GO_ENDPOINT_READALL = "Recv"; + public static final String GO_ENDPOINT_STARTPROTOCOL = "StartProtocol"; + public static final String GO_ENDPOINT_FINISHPROTOCOL = "FinishProtocol"; + public static final String GO_ENDPOINT_FINALISE = "Finalise"; + //public static final String GO_ENDPOINT_ENDPOINT = "Endpoint"; + public static final String GO_ENDPOINT_ENDPOINT = "ept"; + + public static final String GO_FINALISER_TYPE = "session.Finaliser"; // net.MPSTEndpoint; + + public static final String GO_ROLE_TYPE = "session.Role"; + public static final String GO_ROLE_CONSTRUCTOR = "session.NewRole"; + + public static final String GO_PARAMROLE_TYPE = "session.ParamRole"; + + public static final String GO_LINEARRESOURCE_TYPE = "session.LinearResource"; // net.LinearResource + public static final String GO_LINEARRESOURCE_USE = "Use"; // net.LinearResource + + public static final String GO_SCHAN_ENDPOINT = "Ept"; // ep; + public static final String GO_SCHAN_LINEARRESOURCE = "Res"; // state + + public static final String GO_SCHAN_END_TYPE = "End"; + + public static final String GO_IO_FUN_RECEIVER = "s"; + + public static final String GO_CROSS_SPLIT_FUN_PREFIX = "Split"; + public static final String GO_CROSS_SEND_FUN_PREFIX = "Send"; + public static final String GO_CROSS_SEND_FUN_ARG = "arg"; + public static final String GO_CROSS_REDUCE_FUN_PREFIX = "Reduce"; + public static final String GO_CROSS_RECEIVE_FUN_PREFIX = "Recv"; + public static final String GO_CROSS_RECEIVE_FUN_ARG = "arg"; + +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTBranchActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTBranchActionBuilder.java new file mode 100644 index 000000000..2cc34065d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTBranchActionBuilder.java @@ -0,0 +1,200 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STBranchActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; + +public class ParamCoreSTBranchActionBuilder extends STBranchActionBuilder +{ + /*@Override + public String build(STStateChanApiBuilder api, EState curr, EAction a) // FIXME: "overriding" GSTStateChanAPIBuilder.buildAction to hack around *interface return // FIXME: factor out + { + EState succ = curr.getSuccessor(a); + return + "func (s *" + getStateChanType(api, curr, a) + ") " + getActionName(api, a) + "(" + + buildArgs(a) + + ") " + getReturnType(api, curr, succ) + " {\n" // HACK: Return type is interface, so no need for *return (unlike other state chans) + + "s.state.Use()\n" + + buildBody(api, curr, a, succ) + "\n" + + "}"; + }*/ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_PREFIX + "_" + + ParamCoreSTStateChanApiBuilder.getGeneratedParamRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_ARG + + i + " *" + a.payload.elems.get(i) + //+ ", reduceFn" + i + " func(" + ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + i + " []int) int" // No: singleton choice subj (not multichoices) + ).collect(Collectors.joining(", ")); + } + + /*@Override + public String getReturnType(STStateChanApiBuilder api, EState curr, EState succ) + { + return api.cb.getCaseStateChanName(api, curr); + }*/ + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + /*String sEpRecv = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + /*ParamRole r = (ParamRole) a.peer; + ParamRange g = r.ranges.iterator().next(); + Function foo = e -> + { + if (e instanceof ParamIndexInt) + { + return e.toString(); + } + else if (e instanceof ParamIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + };*/ + + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + boolean isDeleg = a.payload.elems.stream().anyMatch(pet -> + //pet.isGDelegationType() // FIXME: currently deleg specified by ParmaCoreDelegDecl, not GDelegationElem + ((ParamCoreSTStateChanApiBuilder) api).isDelegType((DataType) pet)); + if (isDeleg) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + String res = + /*sEpRecv + + "(" + sEpProto + + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "\"" + a.mid + "\")\n" + + IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> sEpRecv + "(" + sEpProto + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "arg" + i + ")") + .collect(Collectors.joining("\n")) + "\n" + /*+ "if " + sEpErr + " != nil {\n" + + "return nil\n" + + "}\n"*/ + //buildReturn(api, curr, succ); + //"ch, selected := <-s._" + a.mid + "_Chan\n" + "_, selected := <-s._" + a.mid + "_Chan\n" + + "if !selected {\n" + + "\treturn nil // select ignores nilchan\n" + + "}\n"; + + RPIndexedRole peer = (RPIndexedRole) curr.getActions().iterator().next().peer; + RPInterval g = peer.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + String sEpRecv = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT; + //+ "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + + ParamCoreSTStateChanApiBuilder apigen = (ParamCoreSTStateChanApiBuilder) api; + String sEp = ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + + res += + //+ "data := make([]int, " + foo.apply(g.end) + ")\n" + //+ "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" // FIXME: num args + ""; + + res += + ((((GoJob) api.job).noCopy) + ? + "decoded = *bs[0].(*" + a.payload.elems.get(0) + ")\n" + : + "" + //+ "data[0] = decoded\n" + //+ "}\n" + ); + + //+ "*arg0 = reduceFn0(data)\n" // FIXME: arg0 + // + "*arg0 = data[0]\n" + + //+ "*arg0 = (<-s.data).(" + ((DataType) a.payload.elems.get(0)).getSimpleName() + ")\n"; + + res += + "if err := " + sEpRecv + (((GoJob) api.job).noCopy ? "Raw" : "") + + ".Conn[" + sEpProto + "." + peer.getName() + ".Name()][" + foo.apply(g.start) + "].Recv(&arg0); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "\n" + + "\tch := make(chan *" + apigen.getStateChanName(curr.getSuccessor(a)) + ", 1)\n" + + "\tch <- " + apigen.getSuccStateChan(this, curr, curr.getSuccessor(a), sEp) + "\n"; + + // FIXME: arg0 // FIXME: args depends on label // FIXME: store args in s.args + + } + + return res + + "return ch"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTBranchStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTBranchStateBuilder.java new file mode 100644 index 000000000..5637d5d30 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTBranchStateBuilder.java @@ -0,0 +1,185 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.scribble.codegen.statetype.STBranchStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.model.endpoint.actions.EReceive; +import org.scribble.type.name.GProtocolName; + +public class ParamCoreSTBranchStateBuilder extends STBranchStateBuilder +{ + public ParamCoreSTBranchStateBuilder(ParamCoreSTBranchActionBuilder bb) + { + super(bb); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + String sEpRecv = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT; + //+ "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + + //return ((ParamCoreSTStateChanApiBuilder) api).getStateChanPremable(s); + ParamCoreSTStateChanApiBuilder apigen = (ParamCoreSTStateChanApiBuilder) api; + //Role r = apigen.actual.getName(); + GProtocolName simpname = apigen.apigen.proto.getSimpleName(); + String tname = apigen.getStateChanName(s); + //String epType = ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, r); + String epType = ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, apigen.actual); + String res = + apigen.apigen.generateRootPackageDecl() + "\n" + + "\n" + + apigen.apigen.generateScribbleRuntimeImports() + "\n" + + "import \"log\"\n" + + //+ (((GoJob) api.job).noCopy ? "" : Stream.of(ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_BYTES_PACKAGE, ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_GOB_PACKAGE) .map(x -> "import \"" + x + "\"").collect(Collectors.joining("\n"))) + + + "\n" + + "type " + tname + " struct{\n" + //+ ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + ParamCoreSTApiGenConstants.GO_ENDPOINT_TYPE + "\n" + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epType + "\n" + + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE +"\n" + + s.getActions().stream().map(a -> "_" + a.mid + "_Chan chan string\n") // chan *" + apigen.getStateChanName(s.getSuccessor(a)) + "\n") + .collect(Collectors.joining("")) + /*+ (((GoJob) apigen.job).noCopy ? "data chan []interface{}" : + //"data chan [][]byte\n" + "data chan interface{}\n" + )*/ + + "}\n"; + + res += "\n" + + "func (ep *" + epType + ") New" + + ((s.id != api.graph.init.id) ? tname + : ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(((ParamCoreSTStateChanApiBuilder) api).actual) + "_1") // cf. ParamCoreSTStateChanApiBuilder::getStateChanPremable init state case + + "() *" + tname + " {\n" // FIXME: factor out + + "s := &" + tname + " { " + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": ep" + + ", " + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + ": new(" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "), " + + s.getActions().stream().map(a -> "_" + a.mid + "_Chan: make(chan "//chan *" + apigen.getStateChanName(s.getSuccessor(a)) + + "string" + + ", 1)") + .collect(Collectors.joining(", ")) + ", " + + /*+ "data: make(chan " + (((GoJob) api.job).noCopy ? "[]interface{}" : + //"[][]byte" + " interface{}" + ) + ", 1)"*/ + + + "}\n" + + "go s.foo()\n" + + "return s\n" + + "}\n"; + + res += "\n" + + "func (s *" + tname + ") foo() {\n" + + "s." + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + "." + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n" + + "var op string\n"; + + RPIndexedRole peer = (RPIndexedRole) s.getActions().iterator().next().peer; + RPInterval g = peer.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + + if (((GoJob) apigen.job).noCopy) + { + res += + "label := " + sEpRecv + "Raw(" + sEpProto + "." + peer.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n" + + "op := *label[0].(*string)\n"; // FIXME: cast for safety? + } + else + { + res += + "if err := " + sEpRecv + ".Conn[" + sEpProto + "." + peer.getName() + ".Name()][" + + foo.apply(g.start) + "].Recv(&op); err != nil {\n" // g.end = g.start + + "log.Fatal(err)\n" + + "}\n"; + } + + /*List as = s.getActions(); + boolean allEmpty = as.stream().allMatch(a -> a.payload.elems.isEmpty()); + if (!allEmpty) // FIXME: + { + res += + "var b string\n" // HACK? + //"var b int\n" + + "if err := " + sEpRecv + (((GoJob) api.job).noCopy ? "Raw" : "") + + ".Conn[" + sEpProto + "." + peer.getName() + ".Name()][" + foo.apply(g.start) + "-1].Recv(&b); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "s.data <- b\n"; + // FIXME: arg0 // FIXME: args depends on label // FIXME: store args in s.args + }*/ + + res+= "if " + + s.getActions().stream().map(a -> + { + //String sEp = ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + return + "op == \"" + a.mid + "\" {\n" + /*+ "\tch := make(chan *" + apigen.getStateChanName(s.getSuccessor(a)) + ", 1)\n" + + "\tch <- " + apigen.getSuccStateChan(this.bb, s, s.getSuccessor(a), sEp) + "\n" + + "\ts._" + a.mid + "_Chan <- ch\n"*/ + + "\ts._" + a.mid + "_Chan <- \"" + a.mid +"\"\n" + + "\t" + s.getActions().stream() + .filter(otheract -> otheract.mid != a.mid) + .map(otheract -> { return "close(s._" + otheract.mid + "_Chan)"; }) + .collect(Collectors.joining("\n\t")) + "\n" + + "}"; + }).collect(Collectors.joining(" else if ")) + "\n" + + "}\n"; + + return res; + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + String out = getPreamble(api, s); + + for (EAction a : s.getActions()) + { + out += "\n\n"; + if (a instanceof EReceive) // FIXME: factor out action kind + { + out += this.bb.build(api, s, a); // Getting 1 checks non-unary + } + else + { + throw new RuntimeException("Shouldn't get in here: " + a); + } + } + + return out; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTEndStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTEndStateBuilder.java new file mode 100644 index 000000000..25ee036cb --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTEndStateBuilder.java @@ -0,0 +1,40 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import org.scribble.codegen.statetype.STEndStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; + +public class ParamCoreSTEndStateBuilder extends STEndStateBuilder +{ + public ParamCoreSTEndStateBuilder() + { + + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + return getPreamble(api, s); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + ParamCoreSTStateChanApiBuilder schangen = (ParamCoreSTStateChanApiBuilder) api; + //return GSTStateChanAPIBuilder.getStateChanPremable(api, s); + String tname = api.getStateChanName(s); + String res = + schangen.apigen.generateRootPackageDecl() + "\n" + + "\n" + ////+ "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PACKAGE + "\"\n" + ////+ schangen.apigen.generateScribbleRuntimeImports() + "\n" + //+ "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n" + + "\n" + + "type " + tname + " struct{\n" + //+ ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + ParamCoreSTApiGenConstants.GO_ENDPOINT_TYPE + "\n" // FIXME: factor out + //+ ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(api.gpn.getSimpleName(), api.role) + "\n" // FIXME: factor out + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(api.gpn.getSimpleName(), schangen.actual) + "\n" // FIXME: factor out + + "}"; + return res; // No LinearResource + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTEndpointApiGenerator.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTEndpointApiGenerator.java new file mode 100644 index 000000000..baf413fdb --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTEndpointApiGenerator.java @@ -0,0 +1,129 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.main.Job; +import org.scribble.main.ScribbleException; +import org.scribble.model.endpoint.EGraph; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +// Duplicated from org.scribble.ext.go.codegen.statetype.go.GoSTEndpointApiGenerator +public class ParamCoreSTEndpointApiGenerator +{ + public final Job job; + public final GProtocolName proto; + public final Role self; // FIXME: base endpoint API gen is role-oriented, while session API generator should be neutral + //public final Map actuals; + public final Map> actuals; + //public final EGraph graph; + + //public final Map> all; + + public ParamCoreSTEndpointApiGenerator(Job job, GProtocolName fullname, Role self, //Map actuals) + Map> actuals) + { + this.job = job; + this.proto = fullname; + this.self = self; + this.actuals = Collections.unmodifiableMap(actuals); + //this.graph = graph; + //this.all = Collections.unmodifiableMap(all); + } + + // N.B. the base EGraph class will probably be replaced by a more specific (and more helpful) param-core class later + public Map build() throws ScribbleException + { + Map res = new HashMap<>(); // filepath -> source + res.putAll(buildSessionApi()); + for (Entry actual : this.actuals.get(this.self).entrySet()) + { + res.putAll(buildStateChannelApi(actual.getKey(), actual.getValue())); + } + return res; + } + + //@Override + public Map buildSessionApi() // FIXME: factor out + { + this.job.debugPrintln("\n[param-core] Running " + ParamCoreSTSessionApiBuilder.class + " for " + this.proto + "@" + this.self); + //throw new RuntimeException("[param-core] TODO:"); + return new ParamCoreSTSessionApiBuilder(this).build(); + } + + public Map buildStateChannelApi(RPRoleVariant actual, EGraph graph) // FIXME: factor out + { + this.job.debugPrintln("\n[param-core] Running " + ParamCoreSTStateChanApiBuilder.class + " for " + this.proto + "@" + this.self); + return new ParamCoreSTStateChanApiBuilder(this, actual, graph).build(); + } + + /*public String getGeneratedEndpointType() + { + /*return "Endpoint_" + this.proto.getSimpleName() + "_" + //+ getGeneratedActualRoleName(); // No: endpoint covers all actual roles of this role name + + this.self;* / + return getGeneratedEndpointType(this.proto.getSimpleName(), this.self); + }*/ + + //public static String getGeneratedEndpointType(GProtocolName simpname, Role r) + public static String getGeneratedEndpointType(GProtocolName simpname, RPRoleVariant r) + { + //return "Endpoint_" + simpname + "_" + r; + return simpname + "_" + getGeneratedActualRoleName(r); + } + + // Doesn't use coranges -- same as getGeneratedParamRoleName? // Old + public static String getGeneratedActualRoleName(RPRoleVariant actual) + { + /*return actual.getName() + + actual.ranges.toString().replaceAll("\\[", "_").replaceAll("\\]", "_").replaceAll("\\.", "_");*/ + /*if (actual.ranges.size() > 1 || actual.coranges.size() > 0) + { + throw new RuntimeException("[param-core] TODO: " + actual); + } + ParamRange g = actual.ranges.iterator().next(); + return actual.getName() + "_" + g.start + "To" + g.end;*/ + return actual.getName() + "_" + + actual.intervals.stream().map(g -> g.start + "To" + g.end).sorted().collect(Collectors.joining("and")) + + (actual.cointervals.isEmpty() ? "" : "_not_") + + actual.cointervals.stream().map(g -> g.start + "To" + g.end).sorted().collect(Collectors.joining("and")); + } + + //@Override + public String getRootPackage() // Derives only from proto name + { + //throw new RuntimeException("[param-core] TODO:"); + return this.proto.getSimpleName().toString(); + } + + public String generateRootPackageDecl() + { + //throw new RuntimeException("[param-core] TODO: "); + return "package " + getRootPackage(); + } + + //@Override + public List getScribbleRuntimeImports() // FIXME: factor up + { + return Stream.of( + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + ////ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSIONPARAM_PACKAGE + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE + + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_BYTES_PACKAGE, + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_GOB_PACKAGE + ).collect(Collectors.toList()); + } + + public String generateScribbleRuntimeImports() + { + return getScribbleRuntimeImports().stream().map(x -> "import \"" + x + "\"\n").collect(Collectors.joining()); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTOutputStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTOutputStateBuilder.java new file mode 100644 index 000000000..ba2b206b8 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTOutputStateBuilder.java @@ -0,0 +1,66 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import org.scribble.codegen.statetype.STOutputStateBuilder; +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.model.endpoint.actions.EDisconnect; +import org.scribble.model.endpoint.actions.ERequest; +import org.scribble.model.endpoint.actions.ESend; +import org.scribble.type.name.DataType; + +public class ParamCoreSTOutputStateBuilder extends STOutputStateBuilder +{ + public final ParamCoreSTSendActionBuilder nb; + + // sb is ParamCoreSTSplitActionBuilder + public ParamCoreSTOutputStateBuilder(STSendActionBuilder sb, ParamCoreSTSendActionBuilder nb) + { + super(sb); + this.nb = nb; + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + return ((ParamCoreSTStateChanApiBuilder) api).getStateChanPremable(s); + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + String out = getPreamble(api, s); + + for (EAction a : s.getActions()) + { + out += "\n\n"; + if (a instanceof ESend) // FIXME: factor out action kind + { + out += this.sb.build(api, s, a); + + // FIXME: delegation + if (!a.payload.elems.stream() + .anyMatch(pet -> ((ParamCoreSTStateChanApiBuilder) api).isDelegType((DataType) pet))) + { + out += "\n\n"; + out += this.nb.build(api, s, a); + } + } + else if (a instanceof ERequest) + { + throw new RuntimeException("TODO: " + a); + } + else if (a instanceof EDisconnect) + { + throw new RuntimeException("TODO: " + a); + } + else + { + throw new RuntimeException("Shouldn't get in here: " + a); + } + } + + return out; + } +} \ No newline at end of file diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReceiveActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReceiveActionBuilder.java new file mode 100644 index 000000000..c474cf154 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReceiveActionBuilder.java @@ -0,0 +1,201 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class ParamCoreSTReceiveActionBuilder extends STReceiveActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_PREFIX + "_" + + ParamCoreSTStateChanApiBuilder.getGeneratedParamRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_ARG + + i + " *[]" + ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(a.payload.elems.get(i)) //a.payload.elems.get(i) + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder apigen, EState curr, EAction a, EState succ) + { + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + String sEpRecv = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + "." + "Conn";//ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval g = r.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + /*sEpRecv + + "(" + sEpProto + + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "\"" + a.mid + "\")\n" + + IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> sEpRecv + "(" + sEpProto + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "arg" + i + ")") + .collect(Collectors.joining("\n")) + "\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + "\tvar decoded "+a.payload.elems.get(0)+"\n" + + "\tif err := gob.NewDecoder(bytes.NewReader(b[i-"+foo.apply(g.start)+"])).Decode(&decoded); err != nil {\n\t\t" + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Errors <- session.DeserialiseFailed(err, \"" + getActionName(api, a) +"\", " + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Self.Name())\n" + + "\t}\n" + + "\tdata[i-"+foo.apply(g.start)+"] = decoded\n" + + "}\n" + + "*arg0 = reduceFn(data)" + /*+ "if " + sEpErr + " != nil {\n" + + "return nil\n" + + "}\n"*/ + + /*String res = + sEpRecv + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + r.getName() + ", " + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n"; // Discard op*/ + String res = ""; + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + + String extName = ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(a.payload.elems.get(0)); + + res += + (((GoJob) apigen.job).noCopy + ? + "data := make([]" + a.payload.elems.get(0) + ", len(b))\n" + + "for i := 0; i < len(b); i++ {\n" + + "data[i] = *b[i].(*" + a.payload.elems.get(0) + ")\n" + + "}\n" + + "*arg0 = reduceFn0(data)\n" + : + //"data := make([]" + "data := make(map[int]" + + extName//a.payload.elems.get(0) + + ", " + foo.apply(g.end) + ")\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" // FIXME: num args + + + (a.mid.toString().equals("") ? "" : // HACK + "var lab string\n" + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "&lab" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n") + + + "var tmp " + extName + "\n" + + (extName.startsWith("[]") ? "tmp = make(" + extName + ", len(*arg0))\n" : "") // HACK? for passthru? + + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + //+ "&data[i-1]" + + "&tmp" + + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "data[i-1] = tmp\n" + + "}\n" + //+ "*arg0 = data\n"); // FIXME: arg0 + + //+ "*arg0 = " + hackGetValues(extName) + "(data)\n"; // FIXME: arg0 + + //+ ((!Stream.of("int", "string", "[]byte").collect(Collectors.toSet()).contains(extName) + // ? + + "f := func(m map[int] " + extName + ") []" + extName + " {\n" + + "xs := make([]" + extName + ", len(m))\n" + + "keys := make([]int, 0)\n" + + "for k, _ := range m {\n" + + "keys = append(keys, k)\n" + + "}\n" + + "sort.Ints(keys)\n" + + "for i, k := range keys {\n" + + "xs[i] = m[k]\n" + + "}\n" + + "return xs\n" + + "}\n" + + "*arg0 = f(data)\n"); + // : "") + } + + return res + + buildReturn(apigen, curr, succ); + } + + protected static String hackGetValues(String t) + { + if (t.equals("int")) + { + return "util.GetValuesInt"; + } + else if (t.equals("string")) + { + return "util.GetValuesString"; + } + else if (t.equals("[]byte")) + { + return "util.GetValuesBates"; + } + else + { + throw new RuntimeException("[TODO] " + t); + //return t; + } + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReceiveStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReceiveStateBuilder.java new file mode 100644 index 000000000..9b6954c60 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReceiveStateBuilder.java @@ -0,0 +1,55 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.List; + +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STReceiveStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; + +public class ParamCoreSTReceiveStateBuilder extends STReceiveStateBuilder +{ + public final ParamCoreSTReceiveActionBuilder vb; + + // sb is ParamCoreSTReduceActionBuilder + public ParamCoreSTReceiveStateBuilder(STReceiveActionBuilder sb, ParamCoreSTReceiveActionBuilder vb) + { + super(sb); + this.vb = vb; + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + return ((ParamCoreSTStateChanApiBuilder) api).getStateChanPremable(s); + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + String out = getPreamble(api, s); + + List as = s.getActions(); + if (as.size() > 1) + { + throw new RuntimeException("Shouldn't get in here: " + as); + } + EAction a = as.get(0); + + out += "\n\n"; + out += this.rb.build(api, s, a); + + // FIXME: delegation + if (!a.payload.elems.stream() + .anyMatch(pet -> ((ParamCoreSTStateChanApiBuilder) api).isDelegType((DataType) pet))) + { + out += "\n\n"; + out += this.vb.build(api, s, a); + } + + return out; + } +} + diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReduceActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReduceActionBuilder.java new file mode 100644 index 000000000..51227b15d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTReduceActionBuilder.java @@ -0,0 +1,243 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; + +public class ParamCoreSTReduceActionBuilder extends STReceiveActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + //return ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_PREFIX + "_" + return ParamCoreSTApiGenConstants.GO_CROSS_REDUCE_FUN_PREFIX + "_" + + ParamCoreSTStateChanApiBuilder.getGeneratedParamRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + DataType[] pet = new DataType[1]; + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_ARG + + i + " *" + ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(pet[0] = (DataType) a.payload.elems.get(i)) //a.payload.elems.get(i) + + // HACK + + ((((ParamCoreSTStateChanApiBuilder) apigen).isDelegType(pet[0])) ? "" : + ", reduceFn" + i + " func(" + ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + i + //+ " []" + a.payload.elems.get(i) + ") " + a.payload.elems.get(i) + + " []" + + + ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(pet[0]) + + + ") " + + + ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(pet[0]) + ) + + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder apigen, EState curr, EAction a, EState succ) + { + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + String sEpRecv = + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + "." + "Conn";//ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval g = r.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + /*sEpRecv + + "(" + sEpProto + + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "\"" + a.mid + "\")\n" + + IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> sEpRecv + "(" + sEpProto + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "arg" + i + ")") + .collect(Collectors.joining("\n")) + "\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + "\tvar decoded "+a.payload.elems.get(0)+"\n" + + "\tif err := gob.NewDecoder(bytes.NewReader(b[i-"+foo.apply(g.start)+"])).Decode(&decoded); err != nil {\n\t\t" + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Errors <- session.DeserialiseFailed(err, \"" + getActionName(api, a) +"\", " + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Self.Name())\n" + + "\t}\n" + + "\tdata[i-"+foo.apply(g.start)+"] = decoded\n" + + "}\n" + + "*arg0 = reduceFn(data)" + /*+ "if " + sEpErr + " != nil {\n" + + "return nil\n" + + "}\n"*/ + + // FIXME: single arg // Currently never true because of ParamCoreSTOutputStateBuilder + boolean isDeleg = a.payload.elems.stream().anyMatch(pet -> + //pet.isGDelegationType() // FIXME: currently deleg specified by ParmaCoreDelegDecl, not GDelegationElem + ((ParamCoreSTStateChanApiBuilder) apigen).isDelegType((DataType) pet)); + + /*String res = + sEpRecv + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + r.getName() + ", " + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n"; // Discard op*/ + String res = ""; + + if (isDeleg) + { + /*var ept *session.Endpoint + err := conn.Recv(&ept) + if err != nil { + log.Fatalf("Wrong value received..") + } + sesss[i] = &Game_a_Init{ept: ept} // Delegated session initialisation + + st.ept.ConnMu.RUnlock() + return sesss, &ClientA_p_End{}*/ + + String extName = ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(a.payload.elems.get(0)); + + res = + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" // FIXME: num args + + + (a.mid.toString().equals("") ? "" : // HACK + "var lab string\n" + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "&lab" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n") + + + "var tmp *" + + extName + "\n" + //extName.substring(0, extName.indexOf('_', extName.indexOf('_', extName.indexOf('_')+1)+1)) + "\n" // FIXME HACK + + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + //+ "&data[i-1]" + + "&tmp" + + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "arg0 = &" + extName + "{" + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": tmp." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " }\n" + + "}\n"; + + } + else if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + + String extName = ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(a.payload.elems.get(0)); + + res += + (((GoJob) apigen.job).noCopy + ? + "data := make([]" + a.payload.elems.get(0) + ", len(b))\n" + + "for i := 0; i < len(b); i++ {\n" + + "data[i] = *b[i].(*" + a.payload.elems.get(0) + ")\n" + + "}\n" + + "*arg0 = reduceFn0(data)\n" + : + /*"data := make([]" + ParamCoreSTStateChanApiBuilder.batesHack(a.payload.elems.get(0)) //a.payload.elems.get(0) + + ", " + foo.apply(g.end) + ")\n"*/ + "data := make(map[int]" + extName + ")\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" // FIXME: num args + + + (a.mid.toString().equals("") ? "" : // HACK + "var lab string\n" + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "&lab" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n") + + + "var tmp " + extName + "\n" + + + (extName.startsWith("[]") ? "tmp = make(" + extName + ", len(*arg0))\n" : "") // HACK? for passthru? + + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + //+ "&data[i-1]" + + "&tmp" + + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "data[i] = tmp\n" + + "}\n" + //+ "*arg0 = reduceFn0(" + // + ParamCoreSTReceiveActionBuilder.hackGetValues(((ParamCoreSTStateChanApiBuilder) apigen).batesHack(a.payload.elems.get(0))) + "(data))\n"); // FIXME: arg0 + + + "f := func(m map[int] " + extName + ") []" + extName + " {\n" + + + "xs := make([]" + extName + ", len(m))\n" + + "keys := make([]int, 0)\n" + + "for k, _ := range m {\n" + + "keys = append(keys, k)\n" + + "}\n" + + "sort.Ints(keys)\n" // Needed? + + "for i, k := range keys {\n" + + "xs[i] = m[k]\n" + + "}\n" + + "return xs\n" + + "}\n" + + "*arg0 = reduceFn0(f(data))\n"); + } + + return res + + buildReturn(apigen, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSendActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSendActionBuilder.java new file mode 100644 index 000000000..c81f7ae09 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSendActionBuilder.java @@ -0,0 +1,191 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; + +public class ParamCoreSTSendActionBuilder extends STSendActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_PREFIX + "_" + + ParamCoreSTStateChanApiBuilder.getGeneratedParamRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + + i + " []" + ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(a.payload.elems.get(i)) //a.payload.elems.get(i) + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder apigen, EState curr, EAction a, EState succ) + { + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + List as = curr.getActions(); + if (as.size() > 1 && as.stream().anyMatch(b -> b.mid.toString().equals(""))) // HACK + { + throw new //ParamCoreException + RuntimeException("[param-core] Empty labels not allowed in non-unary choices: " + curr.getActions()); + } + + String sEpWrite = + //s.ep.Write + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + //+ "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL; + + ".Conn"; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval g = r.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + + /*String res = + (((GoJob) api.job).noCopy + ? + "labels := make([]interface{}, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" + + "tmp := \"" + a.mid + "\"\n" + + "\tlabels[i-" + foo.apply(g.start) + "] = &tmp\n" + + "}\n" + : + "labels := make([][]byte, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" + + "\tlabels[i-" + foo.apply(g.start) + "] = []byte(\"" + a.mid + "\")\n" + + "}\n") + + + sEpWrite + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "labels)\n"; + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + res += + (((GoJob) api.job).noCopy + ? + "b := make([]interface{}, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end)+"; i++ {\n" + + "tmp := splitFn0(arg0, i)\n" + + "\tb[i-"+foo.apply(g.start)+"] = &tmp\n" + + "}\n" + : + "b := make([][]byte, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + "\tvar buf bytes.Buffer\n" + + "\tif err := gob.NewEncoder(&buf).Encode(splitFn0(arg0, i)); err != nil {\n\t\t" // only arg0 + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Errors <- session.SerialiseFailed(err, \"" + getActionName(api, a) +"\", " + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Self.Name())\n" + + "\t}\n" + + "\tb[i-"+foo.apply(g.start)+"] = buf.Bytes()\n" + + "}\n") + + + sEpWrite + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + + "." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + //+ "\"" + a.mid + "\"" + + "b" + + ")\n"; + }*/ + + // FIXME: single arg // Currently never true because of ParamCoreSTOutputStateBuilder + boolean isDeleg = a.payload.elems.stream().anyMatch(pet -> + //pet.isGDelegationType() // FIXME: currently deleg specified by ParmaCoreDelegDecl, not GDelegationElem + ((ParamCoreSTStateChanApiBuilder) apigen).isDelegType((DataType) pet)); + + String res = + //st1.Use() + "j := 0\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + //+ ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + (a.mid.toString().equals("") ? "" : // HACK + "if err := " + sEpWrite + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "\"" + a.mid + "\"" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n") + + //+ ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + ((isDeleg) //... FIXME: delegation: take pointer? send underlying ept? -- don't do (multi)"send"? + ? + "log.Fatal(\"TODO\")\n" + : + "if err := " + sEpWrite + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "arg0[j]" //+ "splitFn0(arg0, i)" // FIXME: hardcoded arg0 + + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "j = j+1\n" + + "}\n"); + + /*for i, v := range pl { + st1.ept.Conn[Worker][i].Send(a.mid) + st1.ept.Conn[Worker][i].Send(v) + }*/ + + return + res + + buildReturn(apigen, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSessionApiBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSessionApiBuilder.java new file mode 100644 index 000000000..c8ee84c53 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSessionApiBuilder.java @@ -0,0 +1,265 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.scribble.ast.Module; +import org.scribble.ast.ProtocolDecl; +import org.scribble.ext.go.ast.RPRoleDecl; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EStateKind; +import org.scribble.type.kind.Global; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; + +// Cf. STStateChanApiBuilder +public class ParamCoreSTSessionApiBuilder // FIXME: make base STSessionApiBuilder +{ + private ParamCoreSTEndpointApiGenerator apigen; + + //private final Map> actuals; + + public ParamCoreSTSessionApiBuilder(ParamCoreSTEndpointApiGenerator apigen)//, Map> actuals) + { + this.apigen = apigen; + //this.actuals = Collections.unmodifiableMap(actuals); + } + + //@Override + public Map build() // FIXME: factor out + { + Module mod = this.apigen.job.getContext().getModule(this.apigen.proto.getPrefix()); + GProtocolName simpname = this.apigen.proto.getSimpleName(); + ProtocolDecl gpd = mod.getProtocolDecl(simpname); + List roles = gpd.header.roledecls.getRoles(); + + /*Set instates = new HashSet<>(); + Predicate f = s -> s.getStateKind() == EStateKind.UNARY_INPUT || s.getStateKind() == EStateKind.POLY_INPUT; + if (f.test(this.apigen.graph.init)) + { + instates.add(this.apigen.graph.init); + } + instates.addAll(MState.getReachableStates(this.apigen.graph.init).stream().filter(f).collect(Collectors.toSet()));*/ + + // roles + String sessPack = + //"package " + this.apigen.getRootPackage() + "\n" // FIXME: factor out + this.apigen.generateRootPackageDecl() + "\n" + + "\n" + //+ "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PACKAGE + "\"\n" + + this.apigen.generateScribbleRuntimeImports() + + "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE + "\"\n"; + //+ "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE + "/tcp\"\n"; + + sessPack += "\n" + + "type " + simpname + " struct {\n" + + roles.stream().map(r -> r + " " + ParamCoreSTApiGenConstants.GO_ROLE_TYPE + "\n").collect(Collectors.joining("")) + // Just need role name constants for now -- params not fixed until endpoint creation + + "}\n" + + "\n" + + "func New" + simpname + "() *" + simpname + " {\n" + + "return &" + simpname + "{ " + roles.stream().map(r -> ParamCoreSTApiGenConstants.GO_ROLE_CONSTRUCTOR + + "(\"" + r + "\")").collect(Collectors.joining(", ")) + " }\n" + // Singleton types? + + "}\n"; + + + /*sessPack += + roles.stream().map(r -> + "type _" + r + " struct { }\n" + + "\n" + + "func (*_" + r +") GetRoleName() string {\n" + + "return \"" + r + "\"\n" + + "}\n" + + "\n" + + "var __" + r + " *_" + r + "\n" + + "\n" + + "func new" + r + "() *_" + r + " {\n" // FIXME: not concurrent + + "if __" + r + " == nil {\n" + + "__"+ r + " = &_" + r + "{}\n" + + "}\n" + + "return __" + r + "\n" + + "}" + ).collect(Collectors.joining("\n\n")) + "\n" + + "\n";*/ + + // Protocol and role specific endpoints + //Function epTypeName = r -> "_Endpoint" + simpname + "_" + r; + sessPack += + roles.stream().map(rfoo -> + { + Set actuals = this.apigen.actuals.get(rfoo).keySet(); + return + actuals.stream().map(actual -> + { + String epTypeName = ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, actual); + List decls = + gpd.getHeader().roledecls.getDecls().stream().filter(rd -> rd.getDeclName().equals(actual.getName())) + .map(rd -> (RPRoleDecl) rd).collect(Collectors.toList()); + if (decls.size() > 1) + { + throw new RuntimeException("Shouldn't get in here: " + actual); + } + List vars = decls.stream().flatMap(d -> d.params.stream()).collect(Collectors.toList()); + //.flatMap(rd -> ((ParamRoleDecl) rd).params.stream()).collect(Collectors.toList()); + + /*if (actual.ranges.size() > 1) + { + throw new RuntimeException("TODO: " + actual); + }*/ + //ParamRange g = actual.ranges.iterator().next(); + + return + + "\nfunc (p *" + ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, actual) + ") Ept() *session.Endpoint {\n" + + "return p.ept\n" + + "}\n" + + + "\n\ntype " + epTypeName + " struct {\n" // FIXME: factor out + + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO + " *" + simpname + "\n" + /*+ this.apigen.actuals.get(r).keySet().stream() + .map(a -> + { + String actualName = ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(a); + return actualName + "s map[int] func(*" + simpname + "_" + actualName + "_1) *" // FIXME: init statechan, factor out with makeSTStateName + + ParamCoreSTStateChanApiBuilder.makeEndStateName(simpname, a) + "\n"; + }).collect(Collectors.joining(""))*/ + + "*session.LinearResource\n" + + "ept *" + ParamCoreSTApiGenConstants.GO_ENDPOINT_TYPE + "\n" + + "Params map[string]int\n" + + "}\n" + + "\n" + + + /*+ "func (ini *" + epTypeName + ") Accept(rolename session.Role, id int, addr, port string) error {\n" + + "ini.ept.Conn[rolename.Name()][id-1] = tcp.NewConnection(addr, port).Accept().(*tcp.Conn)\n" + + "return nil\n" + + "}\n" + + "\n" + + "func (ini *" + epTypeName + ") Connect(rolename session.Role, id int, addr, port string) error {\n" + + "ini.ept.Conn[rolename.Name()][id-1] = tcp.NewConnection(addr, port).Connect()\n" + + "return nil\n" + + "}\n" + + "\n"*/ + + "func (ini *" + epTypeName + ") Accept(rolename session.Role, id int, acceptor transport.Transport) error {\n" + + "ini.ept.Conn[rolename.Name()][id] = acceptor.Accept()\n" + + "return nil\n" // FIXME: runtime currently does log.Fatal on error + + "}\n" + + "\n" + + "func (ini *" + epTypeName + ") Request(rolename session.Role, id int, requestor transport.Transport) error {\n" + + "ini.ept.Conn[rolename.Name()][id] = requestor.Connect()\n" + + "return nil\n" // FIXME: runtime currently does log.Fatal on error + + "}\n" + + "\n" + + + + + "func (p *" + simpname + ") New" + epTypeName + + "(" + + vars.stream().map(v -> v + " int, ").collect(Collectors.joining("")) + + "self int" + + ")" + + "(*" + epTypeName + ") {\n" + + /*+ "ep := &" + epTypeName + "{ " + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO + ": p,\n" + + + this.apigen.actuals.get(r).keySet().stream() + .map(a -> + { + String actualName = ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(a); + return actualName + "s: make(map[int] func(*" + simpname + "_" + actualName + "_1) *" // FIXME: init statechan, factor out with makeSTStateName + + ParamCoreSTStateChanApiBuilder.makeEndStateName(simpname, a) + ")"; + }).collect(Collectors.joining(", ")) + ",\n" + + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + ": " + + ParamCoreSTApiGenConstants.GO_ENDPOINT_CONSTRUCTOR + "(p, p." + r + ")}\n" + + + this.apigen.actuals.entrySet().stream().filter(e -> !e.getKey().equals(r)) + .map(e -> + { + Map tmp = e.getValue(); + if (tmp.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + tmp); + } + ParamActualRole peer = tmp.keySet().iterator().next(); + ParamRange g = peer.ranges.iterator().next(); + Function foo = ee -> + { + if (ee instanceof ParamIndexInt) + { + return ee.toString(); + } + else if (ee instanceof ParamIndexVar) + { + return "ep.Params[\"" + ee + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + ee); + } + }; + return + "ep.Params = map[string]int {" + vars.stream().map(v -> "\"" + v + "\": " + v).collect(Collectors.joining(", ")) + "}\n" + + "ep.Peers[p." + peer.getName() + "] = struct{Start int; End int}{" + foo.apply(g.start) + ", " + foo.apply(g.end) + "}\n" + + "for i := ep." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + ".Peers[p." + peer.getName() + "].Start; i <= ep.Peers[p." + peer.getName() + "].End; i++ {\n" + + "\tp." + peer.getName() + ".(session.ParamRole).Register(i)\n" + + "}\n"; + }).collect(Collectors.joining("")) + + + "return ep\n"*/ + //+ "conns := make(map[string][]transport.Channel)\n" + + "conns := make(map[string]map[int]transport.Channel)\n" + + + //+ this.apigen.actuals.entrySet().stream().filter(e -> !e.getKey().equals(actual.getName())) + + this.apigen.actuals.entrySet().stream() + .map(e -> "conns[p." + e.getKey() + ".Name()] = " + /*+ "make([]transport.Channel, " + + e.getValue().keySet().iterator().next().ranges.iterator().next().end + "-" // FIXME: e.getValues().size() > 1 + + e.getValue().keySet().iterator().next().ranges.iterator().next().start + "+1)\n")*/ + + "make(map[int]transport.Channel)\n") + .collect(Collectors.joining("")) + + + + "params := make(map[string]int)\n" + + decls.iterator().next().params.stream().map(x -> "params[\"" + x + "\"] = " + x + "\n").collect(Collectors.joining("")) + + "return &" + epTypeName + "{p, &session.LinearResource{}, session.NewEndpoint(self, " //-1, + + "conns), params}\n" // FIXME: numRoles + + "}\n" + + /*+ this.apigen.actuals.get(r).keySet().stream() + .map(a -> + { + String actualName = ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(a); + return + "\nfunc (ep *" + epTypeName + ") " + + "Register_" + actualName + + "(i int, impl func(*" + simpname + "_" + actualName + "_1) *" // FIXME: factor out with above + + ParamCoreSTStateChanApiBuilder.makeEndStateName(simpname, a) + ") {\n" + + "ep." + actualName + "s[i] = impl\n" + + "ep.Proto."+ r +".(session.ParamRole).Register(i)\n" + + "}\n"; + }).collect(Collectors.joining(""));*/ + + + + "\nfunc (ini *" + epTypeName + ") Init() (*" + epTypeName + "_1) {\n" + + "ini.Use()\n" + + "ini.ept.CheckConnection()\n" + + + ((this.apigen.actuals.get(rfoo).get(actual).init.getStateKind() == EStateKind.POLY_INPUT) + ? "return ini.New" + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(actual) + "_1()\n" + : "return &" + epTypeName + "_1{&session.LinearResource{}, ini}\n") + + "}"; + }).collect(Collectors.joining("")); + }).collect(Collectors.joining("\n")); + + String dir = this.apigen.proto.toString().replaceAll("\\.", "/") + "/"; + Map res = new HashMap<>(); + res.put(dir + simpname + ".go", sessPack); + return res; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSplitActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSplitActionBuilder.java new file mode 100644 index 000000000..9068e8c41 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTSplitActionBuilder.java @@ -0,0 +1,199 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; + +public class ParamCoreSTSplitActionBuilder extends STSendActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return ParamCoreSTApiGenConstants.GO_CROSS_SPLIT_FUN_PREFIX + "_" + + ParamCoreSTStateChanApiBuilder.getGeneratedParamRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + DataType[] pet = new DataType[1]; + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + + i + " " + + // HACK + + ((((ParamCoreSTStateChanApiBuilder) apigen).isDelegType(pet[0] = ((DataType) a.payload.elems.get(i)))) ? "*" : "") + + ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(pet[0]) //a.payload.elems.get(i) + + + ", splitFn" + i + " func(" + ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + i + " " + + // HACK + + ((((ParamCoreSTStateChanApiBuilder) apigen).isDelegType(pet[0])) ? "*" : "") + + ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(pet[0]) + + + ", i" + i + " int) " + + + ((((ParamCoreSTStateChanApiBuilder) apigen).isDelegType(pet[0])) ? "*" : "") + + ((ParamCoreSTStateChanApiBuilder) apigen).batesHack(pet[0]) + + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + List as = curr.getActions(); + if (as.size() > 1 && as.stream().anyMatch(b -> b.mid.toString().equals(""))) // HACK + { + throw new //ParamCoreException + RuntimeException("[param-core] Empty labels not allowed in non-unary choices: " + curr.getActions()); + } + + String sEpWrite = + //s.ep.Write + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + //+ "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL; + + ".Conn"; + String sEpProto = + //"s.ep.Proto" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval g = r.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + + /*String res = + (((GoJob) api.job).noCopy + ? + "labels := make([]interface{}, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" + + "tmp := \"" + a.mid + "\"\n" + + "\tlabels[i-" + foo.apply(g.start) + "] = &tmp\n" + + "}\n" + : + "labels := make([][]byte, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" + + "\tlabels[i-" + foo.apply(g.start) + "] = []byte(\"" + a.mid + "\")\n" + + "}\n") + + + sEpWrite + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "labels)\n"; + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + res += + (((GoJob) api.job).noCopy + ? + "b := make([]interface{}, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end)+"; i++ {\n" + + "tmp := splitFn0(arg0, i)\n" + + "\tb[i-"+foo.apply(g.start)+"] = &tmp\n" + + "}\n" + : + "b := make([][]byte, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + "\tvar buf bytes.Buffer\n" + + "\tif err := gob.NewEncoder(&buf).Encode(splitFn0(arg0, i)); err != nil {\n\t\t" // only arg0 + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Errors <- session.SerialiseFailed(err, \"" + getActionName(api, a) +"\", " + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Self.Name())\n" + + "\t}\n" + + "\tb[i-"+foo.apply(g.start)+"] = buf.Bytes()\n" + + "}\n") + + + sEpWrite + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + + "." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + //+ "\"" + a.mid + "\"" + + "b" + + ")\n"; + }*/ + + String res = + //st1.Use() + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + //+ ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + (a.mid.toString().equals("") ? "" : // HACK + "if err := " + sEpWrite + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "\"" + a.mid + "\"" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n") + + + ((((ParamCoreSTStateChanApiBuilder) api).isDelegType((DataType) a.payload.elems.get(0))) ? "arg0.Res.Use()\n" : "") + + //+ ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "if err := " + sEpWrite + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + + "splitFn0(arg0, i)" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "}\n"; + + /*for i, v := range pl { + st1.ept.Conn[Worker][i].Send(a.mid) + st1.ept.Conn[Worker][i].Send(v) + }*/ + + return + res + + buildReturn(api, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTStateChanApiBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTStateChanApiBuilder.java new file mode 100644 index 000000000..5f8f967af --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype2/ParamCoreSTStateChanApiBuilder.java @@ -0,0 +1,404 @@ +package org.scribble.ext.go.core.codegen.statetype2; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.scribble.ast.DataTypeDecl; +import org.scribble.codegen.statetype.STActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.ast.RPCoreDelegDecl; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossSend; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEDotReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEDotSend; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEMultiChoicesReceive; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.model.MState; +import org.scribble.model.endpoint.EGraph; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.EStateKind; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.PayloadElemType; + +// Duplicated from org.scribble.ext.go.codegen.statetype.go.GoSTStateChanAPIBuilder +public class ParamCoreSTStateChanApiBuilder extends STStateChanApiBuilder +{ + protected final ParamCoreSTEndpointApiGenerator apigen; + public final RPRoleVariant actual; // this.apigen.self.equals(this.actual.getName()) + //public final EGraph graph; + + public final ParamCoreSTReceiveActionBuilder vb; + + private int counter = 1; + + private final Set datats; // FIXME: use "main.getDataTypeDecl((DataType) pt);" instead -- cf. OutputSocketGenerator#addSendOpParams + + // N.B. the base EGraph class will probably be replaced by a more specific (and more helpful) param-core class later + // actual.getName().equals(this.role) + public ParamCoreSTStateChanApiBuilder(ParamCoreSTEndpointApiGenerator apigen, RPRoleVariant actual, EGraph graph) + { + super(apigen.job, apigen.proto, apigen.self, graph, + new ParamCoreSTOutputStateBuilder(new ParamCoreSTSplitActionBuilder(), new ParamCoreSTSendActionBuilder()), + new ParamCoreSTReceiveStateBuilder(new ParamCoreSTReduceActionBuilder(), new ParamCoreSTReceiveActionBuilder()), + new ParamCoreSTBranchStateBuilder(new ParamCoreSTBranchActionBuilder()), + null, //new GoSTCaseBuilder(new GoSTCaseActionBuilder()), + new ParamCoreSTEndStateBuilder()); + + //throw new RuntimeException("[param-core] TODO:"); + this.apigen = apigen; + this.actual = actual; + + this.vb = ((ParamCoreSTReceiveStateBuilder) this.rb).vb; + + this.datats = this.apigen.job.getContext().getMainModule().getNonProtocolDecls().stream() + .filter(d -> (d instanceof DataTypeDecl)).map(d -> ((DataTypeDecl) d)).collect(Collectors.toSet()); + } + + protected RPRoleVariant getSelf() + { + return (RPRoleVariant) this.getSelf(); + } + + // Not actual roles; param roles in EFSM actions -- cf. ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName + public static String getGeneratedParamRoleName(RPIndexedRole r) + { + //return r.toString().replaceAll("\\[", "_").replaceAll("\\]", "_").replaceAll("\\.", "_"); + if (r.intervals.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + r); + } + RPInterval g = r.intervals.iterator().next(); + return r.getName() + "_" + g.start + "To" + g.end; + } + + + /*@Override + public String getPackage() + { + //throw new RuntimeException("[param-core] TODO:"); + return this.gpn.getSimpleName().toString(); + }*/ + + @Override + protected String makeSTStateName(EState s) + { + //throw new RuntimeException("[param-core] TODO:"); + if (s.isTerminal()) + { + ////return "_EndState"; + //return ParamCoreSTApiGenConstants.GO_SCHAN_END_TYPE; + return makeEndStateName(this.apigen.proto.getSimpleName(), this.actual); + } + return this.apigen.proto.getSimpleName() + "_" + + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(this.actual) + + "_" + this.counter++; + } + + public static String makeEndStateName(GProtocolName simpname, RPRoleVariant r) + { + return simpname + "_" + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(r) + "_" + ParamCoreSTApiGenConstants.GO_SCHAN_END_TYPE; + } + + @Override + public String getStateChannelFilePath(String filename) + { + //throw new RuntimeException("[param-core] TODO:"); + if (filename.startsWith("_")) // Cannot use "_" prefix, ignored by Go + { + filename = "$" + filename.substring(1); + } + return this.gpn.toString().replaceAll("\\.", "/") + "/" + filename + ".go"; + } + + public String getActualRoleName() + { + return this.apigen.self.toString(); + } + + public boolean isDelegType(DataType t) + { + return this.datats.stream().filter(i -> i.getDeclName().equals(t)).iterator().next() instanceof RPCoreDelegDecl; // FIXME: make a map + } + + protected String getExtName(DataType t) + { + return this.datats.stream().filter(i -> i.getDeclName().equals(t)).iterator().next().extName; // FIXME: make a map + } + + protected String getExtSource(DataType t) + { + return this.datats.stream().filter(i -> i.getDeclName().equals(t)).iterator().next().extSource; // FIXME: make a map + } + + private String makeImportExtName(DataType t) + { + String extName = getExtName(t); + switch (extName) + { + case "int": // FIXME: factor out with batesHack + case "[]int": + case "[][]int": + case "string": + case "[]string": + case "[][]string": + case "byte": + case "[]byte": + case "[][]byte": + { + return ""; + } + default: + { + return "import \"" + getExtSource(t) + "\"\n"; + } + } + } + + protected String getStateChanPremable(EState s) + { + //Role r = this.actual.getName(); + + GProtocolName simpname = this.apigen.proto.getSimpleName(); + String tname = this.getStateChanName(s); + //String epType = ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, r); + String epType = ParamCoreSTEndpointApiGenerator.getGeneratedEndpointType(simpname, this.actual); + + String res = + this.apigen.generateRootPackageDecl() + "\n" + + "\n" + + this.apigen.generateScribbleRuntimeImports() + "\n" + + "import \"log\"\n" + + /*+ (s.isTerminal() || ((GoJob) apigen.job).noCopy ? "" : + Stream.of(ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_BYTES_PACKAGE, ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_GOB_PACKAGE) + .map(x -> "import \"" + x + "\"").collect(Collectors.joining("\n"))) + + "\n"*/ + + ((s.getStateKind() == EStateKind.UNARY_INPUT || s.getStateKind() == EStateKind.POLY_INPUT) // FIXME: refactor into state builders + //? "import \"github.com/rhu1/scribble-go-runtime/test/util\"\n" : "") + ? "import \"sort\"\n" : "") + + + ((s.getStateKind() == EStateKind.OUTPUT || s.getStateKind() == EStateKind.UNARY_INPUT || s.getStateKind() == EStateKind.POLY_INPUT) + ? s.getActions().stream().flatMap(a -> a.payload.elems.stream()).collect(Collectors.toSet()).stream() + .map(p -> makeImportExtName((DataType) p)) + .collect(Collectors.joining("")) + : "") + + + ((s.getStateKind() == EStateKind.UNARY_INPUT || s.getStateKind() == EStateKind.POLY_INPUT) + ? "\nvar _ = sort.Sort\n" : "") + + + "\n" + + "type " + tname + " struct{\n" + + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE +"\n" + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epType + "\n" + + "}\n"; + + if (s.id == this.graph.init.id) + { + res += "\n" + + "func (ep *" + epType + ") New" + + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(this.actual) + "_1" // cf. makeSTStateName + + "() *" + tname + " {\n" // FIXME: factor out + + "return &" + tname + " { " + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": ep" + + ", " + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + ": new(" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ")}\n" + + "}"; + } + + return res; + } + + @Override + public String buildAction(STActionBuilder ab, EState curr, EAction a) // Here because action builder hierarchy not suitable (extended by action kind, not by target language) + { + EState succ = curr.getSuccessor(a); + if (getStateKind(curr) == ParamCoreEStateKind.CROSS_RECEIVE && curr.getActions().size() > 1) + { + return + "func (" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + " *" + ab.getStateChanType(this, curr, a) + ") " + ab.getActionName(this, a) + "(" + + ab.buildArgs(this, a) + + ") <-chan *" + ab.getReturnType(this, curr, succ) + " {\n" + + ab.buildBody(this, curr, a, succ) + "\n" + + "}"; + } + else + { + //throw new RuntimeException("[param-core] TODO: "); + return + "func (" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + + " *" + ab.getStateChanType(this, curr, a) + ") " + ab.getActionName(this, a) + "(" + + ab.buildArgs(this, a) + + ") *" + ab.getReturnType(this, curr, succ) + " {\n" + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + "." + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n" + + ab.buildBody(this, curr, a, succ) + "\n" + + "}"; + } + } + + @Override + public String getChannelName(STStateChanApiBuilder api, EAction a) + { + //throw new RuntimeException("[param-core] TODO: "); + return + //"s.ep.Chans[s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + "]"; + "s.ep.GetChan(s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + ")"; + } + + @Override + public String buildActionReturn(STActionBuilder ab, EState curr, EState succ) // FIXME: refactor action builders as interfaces and use generic parameter for kind + { + //throw new RuntimeException("[param-core] TODO: "); + String sEp = + //"s.ep" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + String res = ""; + + /*if (succ.isTerminal()) // FIXME + { + res += sEp + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_FINISHPROTOCOL + "()\n"; + }*/ + + res += "return " + getSuccStateChan(ab, curr, succ, sEp); + return res; + } + + public String getSuccStateChan(STActionBuilder ab, EState curr, EState succ, String sEp) + { + if (getStateKind(succ) == ParamCoreEStateKind.CROSS_RECEIVE && succ.getActions().size() > 1) + { + return ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + + "New" + //+ getStateChanName(succ) + + ((succ.id != this.graph.init.id) ? getStateChanName(succ) + : ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(this.actual) + "_1") // cf. ParamCoreSTStateChanApiBuilder::getStateChanPremable init state case + + "()"; + } + else + { + String res = "&" + ab.getReturnType(this, curr, succ) + "{ " + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": " + sEp; + if (!succ.isTerminal()) + { + res += ", " + ParamCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + ": new(" + ParamCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ")"; // FIXME: EndSocket LinearResource special case + } + res += " }"; + return res; + } + } + + @Override + public Map build() // filepath -> source + { + Map api = new HashMap<>(); + Set states = new LinkedHashSet<>(); + states.add(this.graph.init); + states.addAll(MState.getReachableStates(this.graph.init)); + for (EState s : states) + { + switch (getStateKind(s)) + { + case CROSS_SEND: api.put(getStateChannelFilePath(getStateChanName(s)), this.ob.build(this, s)); break; + case CROSS_RECEIVE: + { + if (s.getActions().size() > 1) + { + api.put(getStateChannelFilePath(getStateChanName(s)), this.bb.build(this, s)); + //api.put(getFilePath(this.cb.getCaseStateChanName(this, s)), this.cb.build(this, s)); // FIXME: factor out + } + else + { + api.put(getStateChannelFilePath(getStateChanName(s)), this.rb.build(this, s)); + } + break; + } + case DOT_SEND: + { + throw new RuntimeException("[param-core] TODO: " + s); + } + case DOT_RECEIVE: + { + throw new RuntimeException("[param-core] TODO: " + s); + } + case MULTICHOICES_RECEIVE: + { + throw new RuntimeException("[param-core] TODO: " + s); + } + case TERMINAL: api.put(getStateChannelFilePath(getStateChanName(s)), this.eb.build(this, s)); break; // FIXME: without subpackages, all roles share same EndSocket + default: throw new RuntimeException("[param-core] Shouldn't get in here: " + s); + } + } + return api; + } + + protected String batesHack(PayloadElemType t) + { + /*String tmp = t.toString(); + return (tmp.equals("bates")) ? "[]byte" : tmp;*/ + DataType dt = (DataType) t; + String extName = getExtName(dt); + + switch (extName) + { + case "int": + case "[]int": // FIXME: generalise arbitrary dimension array + case "[][]int": + case "string": + case "[]string": + case "[][]string": + case "byte": + case "[]byte": + case "[][]byte": + { + return extName; + } + default: + { + return extName; // FIXME + } + } + } + + // FIXME: make ParamCoreEState + enum ParamCoreEStateKind { CROSS_SEND, CROSS_RECEIVE, DOT_SEND, DOT_RECEIVE, MULTICHOICES_RECEIVE, TERMINAL } + + protected static ParamCoreEStateKind getStateKind(EState s) + { + List as = s.getActions(); + if (as.isEmpty()) + { + return ParamCoreEStateKind.TERMINAL; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreECrossSend)) + { + return ParamCoreEStateKind.CROSS_SEND; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreECrossReceive)) + { + return ParamCoreEStateKind.CROSS_RECEIVE; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreEDotSend)) + { + return ParamCoreEStateKind.DOT_SEND; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreEDotReceive)) + { + return ParamCoreEStateKind.DOT_RECEIVE; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreEMultiChoicesReceive)) + { + return ParamCoreEStateKind.MULTICHOICES_RECEIVE; + } + else + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + s); + } + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTApiGenConstants.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTApiGenConstants.java new file mode 100644 index 000000000..6f1f91be7 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTApiGenConstants.java @@ -0,0 +1,77 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +public class RPCoreSTApiGenConstants +{ + //public static final String GO_SCRIBBLERUNTIME_PACKAGE = "org/scribble/runtime/net"; + public static final String GO_SCRIBBLERUNTIME_SESSION_PACKAGE = "github.com/rhu1/scribble-go-runtime/runtime/session2"; + public static final String GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE = "github.com/rhu1/scribble-go-runtime/runtime/twodim/session2"; + public static final String GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE = "github.com/rhu1/scribble-go-runtime/runtime/transport2"; + //public static final String GO_SCRIBBLERUNTIME_SHM_PACKAGE = "github.com/scribble/go-runtime/transport2/shm"; + public static final String GO_SCRIBBLERUNTIME_BYTES_PACKAGE = "bytes"; + public static final String GO_SCRIBBLERUNTIME_GOB_PACKAGE = "encoding/gob"; + public static final String GO_SCRIBBLERUNTIME_UTIL_PACKAGE = "github.com/rhu1/scribble-go-runtime/runtime/util"; + + public static final String GO_SCRIBBLERUNTIME_SESSIONPARAM_PACKAGE = "github.com/scribble/go-runtime/session2/param"; + + public static final String GO_MPCHAN_TYPE = "session2.MPChan"; // net.MPSTEndpoint; + public static final String GO_MPCHAN_CONSTRUCTOR = "session2.NewMPChan"; + public static final String GO_MPCHAN_PROTO = "Proto"; + public static final String GO_MPCHAN_ERR = "Err"; + public static final String GO_MPCHAN_FINALISE = "Finalise"; + public static final String GO_MPCHAN_SESSCHAN = "MPChan"; + public static final String GO_MPCHAN_PARAMS = "Params"; + public static final String GO_MPCHAN_CONN_WG = "ConnWg"; // Counts initiated but unestablished connection + public static final String GO_MPCHAN_CONN_MAP = "Conns"; + public static final String GO_MPCHAN_FORMATTER_MAP = "Fmts"; + public static final String GO_MPCHAN_MSEND = "MSend"; + public static final String GO_MPCHAN_MRECV = "MRecv"; + public static final String GO_MPCHAN_ISEND = "ISend"; + public static final String GO_MPCHAN_IRECV = "IRecv"; + + public static final String GO_MPCHAN_WRITEALL = "Send"; + public static final String GO_MPCHAN_READALL = "Recv"; + public static final String GO_MPCHAN_STARTPROTOCOL = "StartProtocol"; + public static final String GO_MPCHAN_FINISHPROTOCOL = "FinishProtocol"; + + public static final String GO_FORMATTER_SERIALIZE = "Serialize"; + public static final String GO_FORMATTER_DESERIALIZE = "Deserialize"; + public static final String GO_FORMATTER_ENCODE_INT = "EncodeInt"; + public static final String GO_FORMATTER_DECODE_INT = "DecodeInt"; + public static final String GO_FORMATTER_ENCODE_STRING = "EncodeString"; + public static final String GO_FORMATTER_DECODE_STRING = "DecodeString"; + + public static final String GO_FINALISER_TYPE = "session2.Finaliser"; // net.MPSTEndpoint; + + public static final String GO_ROLE_TYPE = "session2.Role"; + public static final String GO_ROLE_CONSTRUCTOR = "session2.NewRole"; + + public static final String GO_PARAMROLE_TYPE = "session2.ParamRole"; + + public static final String GO_PROTOCOL_TYPE = "session2.Protocol"; + public static final String GO_SCRIBMESSAGE_TYPE = "session2.ScribMessage"; + public static final String GO_FORMATTER_TYPE = "session2.ScribMessageFormatter"; + public static final String GO_SCRIB_LISTENER_TYPE = "transport2.ScribListener"; + public static final String GO_SCRIB_BINARY_CHAN_TYPE = "transport2.BinChannel"; + + public static final String GO_LINEARRESOURCE_TYPE = "session2.LinearResource"; // net.LinearResource + public static final String GO_LINEARRESOURCE_USE = "Use"; // net.LinearResource + + public static final String GO_SCHAN_ENDPOINT = "Ept"; // ep; + public static final String GO_SCHAN_LINEARRESOURCE = "Res"; // state + public static final String GO_SCHAN_ERROR = "Err"; // error + + public static final String GO_SCHAN_END_TYPE = "End"; + + public static final String GO_IO_METHOD_RECEIVER = "s"; + + public static final String GO_CROSS_SPLIT_FUN_PREFIX = "Split"; + public static final String GO_CROSS_SEND_FUN_PREFIX = "Send"; + public static final String GO_CROSS_SEND_METHOD_ARG = "arg"; + public static final String GO_CROSS_REDUCE_FUN_PREFIX = "Reduce"; + public static final String GO_CROSS_RECEIVE_FUN_PREFIX = "Recv"; + public static final String GO_CROSS_RECEIVE_METHOD_ARG = "arg"; + public static final String GO_CASE_METHOD_ARG = "arg"; + + public static final String RP_SCATTER_METHOD_PREFIX = "Scatter"; + public static final String RP_GATHER_METHOD_PREFIX = "Gather"; +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTApiGenerator.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTApiGenerator.java new file mode 100644 index 000000000..69a87fbf7 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTApiGenerator.java @@ -0,0 +1,396 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; + +import org.scribble.ast.Module; +import org.scribble.ast.ProtocolDecl; +import org.scribble.del.ModuleDel; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.cli.RPCoreCLArgParser; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.core.visit.RPCoreIndexVarCollector; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPBinIndexExpr; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexIntPair; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.main.ScribbleException; +import org.scribble.model.endpoint.EGraph; +import org.scribble.type.kind.Global; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.Role; +import org.scribble.util.Pair; +import org.scribble.visit.util.MessageIdCollector; + +// Duplicated from org.scribble.ext.go.codegen.statetype.go.GoSTEndpointApiGenerator +public class RPCoreSTApiGenerator +{ + public enum Mode { Int, IntPair } + + public final GoJob job; + public final GProtocolName proto; // Full name + public final Mode mode; + + // FIXME: factor out an RPCoreJob(Context) + public final Map> projections; + public final Map> variants; + //public final Map, Set>>> families; + public final Map, Set>, Integer> families; // int is arbitrary familiy id + public final Map, Set>, Set>> peers; + // For "common" endpoint kind factoring (dial/accept methods) + + public final Map, Set>, Pair, Set>> subsum; + public final Map, Set>, RPRoleVariant>> aliases; + + public final String packpath; + // Prefix for absolute imports in generated APIs (e.g., "github.com/rhu1/scribble-go-runtime/test2/bar/bar02/Bar2") -- not supplied by Scribble module + //public final Role self; + public final List selfs; + // FIXME? just a role name -- cf. CL arg + // FIXME: any way to separate Session API (Protocol) from Endpoint/StateChan APIs? + + public final Smt2Translator smt2t; + + public RPCoreSTApiGenerator(GoJob job, GProtocolName fullname, Map> projections, + Map> variants, Set, Set>> families, + Map, Set>, Set>> peers, + Map, Set>, Pair, Set>> subsum, + Map, Set>, RPRoleVariant>> aliases, + String packpath, //Role self) + List selfs, Mode mode, Smt2Translator smt2t) + { + this.job = job; + this.proto = fullname; + this.projections = Collections.unmodifiableMap( + projections.entrySet().stream().collect(Collectors.toMap( + e -> e.getKey(), + e -> Collections.unmodifiableMap(e.getValue()) + ))); + this.variants = Collections.unmodifiableMap( + variants.entrySet().stream().collect(Collectors.toMap( + e -> e.getKey(), + e -> Collections.unmodifiableMap(e.getValue()) + ))); + + /*Map, Set>>> fs = new HashMap<>(); + for (Pair, Set> f : families) + { + for (RPRoleVariant v : f.left) + { + Set, Set>> tmp2 = fs.get(v); + if (tmp2 == null) + { + tmp2 = new HashSet<>(); + fs.put(v, tmp2); + } + tmp2.add(f); + } + } + this.families = Collections.unmodifiableMap( + fs.entrySet().stream().collect(Collectors.toMap( + e -> e.getKey(), + e -> Collections.unmodifiableSet(e.getValue()) + )));*/ + int[] i = { 1 }; + Comparator variantComp = new Comparator() // FIXME: factor out + { + @Override + public int compare(RPRoleVariant i1, RPRoleVariant i2) + { + return i1.toString().compareTo(i2.toString()); + } + }; + this.families = Collections.unmodifiableMap(families.stream() + .sorted(new Comparator, Set>>() + { + // FIXME refactor properly + @Override + public int compare(Pair, Set> f1, Pair, Set> f2) + { + //return f1.toString().compareTo(f2.toString()); // No: Set elements + return (f1.left.stream().sorted(variantComp).map(x -> x.toString()).collect(Collectors.joining("_")) + "_not_" + f1.right.stream().sorted(variantComp).map(x -> x.toString()).collect(Collectors.joining("_"))) + .compareTo(f2.left.stream().sorted(variantComp).map(x -> x.toString()).collect(Collectors.joining("_")) + "_not_" + f2.right.stream().sorted(variantComp).map(x -> x.toString()).collect(Collectors.joining("_"))); + }}) + .collect(Collectors.toMap(f -> f, f -> i[0]++))); + // CHECKME: deep copy? + + this.packpath = packpath; + //this.self = self; + this.selfs = Collections.unmodifiableList(selfs); + + this.peers = Collections.unmodifiableMap( + peers.entrySet().stream().collect(Collectors.toMap( + e -> e.getKey(), + e -> Collections.unmodifiableMap(e.getValue()) + ))); + + this.subsum = Collections.unmodifiableMap(subsum); + this.aliases = Collections.unmodifiableMap(aliases); + // FIXME: deep copies + + this.mode = mode; + this.smt2t = smt2t; + } + + // N.B. the base EGraph class will probably be replaced by a more specific (and more helpful) param-core class later + public Map build() throws ScribbleException + { + for (Role r : this.variants.keySet()) + { + char c = r.toString().charAt(0); + if (c < 'A' || c > 'Z') + { + throw new ScribbleException("[rp-core] [" + RPCoreCLArgParser.RPCORE_API_GEN_FLAG + "]" + + " Role names must start uppercase for Go accessibility: " + r); + } + } + + // Duplicated from RPCoreSTSessionApiBuilder#build + Module mod = this.job.getContext().getModule(this.proto.getPrefix()); + MessageIdCollector midcol = new MessageIdCollector(this.job, ((ModuleDel) mod.del()).getModuleContext()); + ProtocolDecl gpd = mod.getProtocolDecl(this.proto.getSimpleName()); + + // Duplicated from. SessionApiGeneration#constructOpClasses + gpd.accept(midcol); + for (MessageId mid : midcol.getNames()) + { + String mname = mid.toString(); + char c; + if (mname.length() == 0 || ((c = mname.charAt(0))) < 'A' || c > 'Z') + { + throw new ScribbleException("[rpcore] [" + RPCoreCLArgParser.RPCORE_API_GEN_FLAG + "]" + + " Message identifiers must start uppercase for Go accessibility: " + mname); + } + } + + RPCoreIndexVarCollector ivarcol = new RPCoreIndexVarCollector(this.job); + gpd.accept(ivarcol); + for (RPIndexVar ivar : ivarcol.getIndexVars()) + { + char c = ivar.name.charAt(0); + if (c < 'A' || c > 'Z') + { + throw new ScribbleException("[rp-core] [" + RPCoreCLArgParser.RPCORE_API_GEN_FLAG + "]" + + " Index variables must be uppercase for Go accessibility: " + ivar); + } + } + + // Build Session API (Protocol and Endpoint types) and State Channel API + //makeStateChanNames(); + Map res = new HashMap<>(); // filepath -> source + res.putAll(buildSessionApi()); + for (Role self : this.selfs.stream().sorted(new Comparator() + { + @Override + public int compare(Role o1, Role o2) + { + return o1.toString().compareTo(o2.toString()); + } + }).collect(Collectors.toList())) + { + for (Entry e : this.variants.get(self).entrySet().stream().sorted(new Comparator>() + { + @Override + public int compare(Entry o1, Entry o2) + { + return o1.getValue().init.id - o2.getValue().init.id; + } + }).collect(Collectors.toList())) + { + RPRoleVariant variant = e.getKey(); + for (Pair, Set> family : + this.families.entrySet().stream().filter(x -> x.getKey().left.contains(variant)) + .sorted(new Comparator, Set>, Integer>>() + { + @Override + public int compare(Entry, Set>, Integer> o1, + Entry, Set>, Integer> o2) + { + return o1.getValue() - o2.getValue(); + } + }).map(x -> x.getKey()).collect(Collectors.toList())) + { + res.putAll(buildStateChannelApi(family, variant, e.getValue())); + } + } + } + return res; + } + + private Map> stateChanNames = new HashMap<>(); + + //@Override + public Map buildSessionApi() // FIXME: factor out + { + this.job.debugPrintln("\n[rp-core] Running " + RPCoreSTSessionApiBuilder.class + " for " + this.proto + "@" + this.selfs); + RPCoreSTSessionApiBuilder b = new RPCoreSTSessionApiBuilder(this); + this.stateChanNames.putAll(b.stateChanNames); + return b.build(); + } + + public Map buildStateChannelApi( + Pair, Set> family, RPRoleVariant variant, EGraph graph) // FIXME: factor out + { + this.job.debugPrintln("\n[rp-core] Running " + RPCoreSTStateChanApiBuilder.class + " for " + this.proto + "@" + variant); + return new RPCoreSTStateChanApiBuilder(this, family, variant, graph, this.stateChanNames.get(variant)).build(); + } + + //@Override + public String getApiRootPackageName() // Derives only from simple proto name + { + return this.proto.getSimpleName().toString(); + } + + /*public String makeApiRootPackageDecl() + { + return "package " + getApiRootPackageName(); + }*/ + + public String getFamilyPackageName(Pair, Set> family) + { + return "family_" + this.families.get(family); + } + + public static String getEndpointKindPackageName(RPRoleVariant variant) + { + return getGeneratedRoleVariantName(variant); + } + + // FIXME: doesn't need simpname + // Role variant = Endpoint kind -- e.g., S_1To1, W_1Ton + public static String getEndpointKindTypeName(GProtocolName simpname, RPRoleVariant variant) + { + //return simpname + "_" + getGeneratedActualRoleName(r); + return getGeneratedRoleVariantName(variant); + } + + public static String getGeneratedRoleVariantName(RPRoleVariant variant) + { + /*return actual.getName() + + actual.ranges.toString().replaceAll("\\[", "_").replaceAll("\\]", "_").replaceAll("\\.", "_");*/ + /*if (actual.ranges.size() > 1 || actual.coranges.size() > 0) + { + throw new RuntimeException("[param-core] TODO: " + actual); + } + ParamRange g = actual.ranges.iterator().next(); + return actual.getName() + "_" + g.start + "To" + g.end;*/ + return variant.getName() + "_" + + variant.intervals.stream().map(g -> getGeneratedNameLabel(g.start) + "to" + getGeneratedNameLabel(g.end)) + .sorted().collect(Collectors.joining("and")) + + (variant.cointervals.isEmpty() + ? "" + : "_not_" + variant.cointervals.stream().map(g -> getGeneratedNameLabel(g.start) + "to" + getGeneratedNameLabel(g.end)) + .sorted().collect(Collectors.joining("and"))); + } + + // For type name generation -- not code exprs, cf. RPCoreSTStateChanApiBuilder#generateIndexExpr + public static String getGeneratedNameLabel(RPIndexExpr e) + { + if (e instanceof RPIndexInt) + { + return e.toGoString(); + } + else if (e instanceof RPIndexVar) + { + return e.toGoString(); + } + else if (e instanceof RPIndexIntPair) + { + //return e.toGoString(); // No: that gives the "value" expression + RPIndexIntPair p = (RPIndexIntPair) e; + int l = ((RPIndexInt) p.left).val; + int r = ((RPIndexInt) p.right).val; + String ll = (l < 0) ? "neg" + (-1*l) : Integer.toString(l); + String rr = (r < 0) ? "neg" + (-1*r) : Integer.toString(r); + return "l" + ll + "r" + rr; + } + else if (e instanceof RPBinIndexExpr) + { + RPBinIndexExpr b = (RPBinIndexExpr) e; + String op; + switch (b.op) + { + case Add: op = "plus"; break; + case Subt: op = "sub"; break; + case Mult: op = "mul"; //break; + default: throw new RuntimeException("TODO: " + b.op); + } + return getGeneratedNameLabel(b.left) + op + getGeneratedNameLabel(b.right); // FIXME: pre/postfix more consistent? + } + else + { + throw new RuntimeException("Shouldn't get here: " + e); + } + } + + public boolean isCommonEndpointKind(RPRoleVariant variant) + { + // For factoring out "common" endpoint kinds from families -- FIXME: do earlier with/after family computation? + // Means current variant talks to at most the same single peer in all families (but maybe not involved in some families -- but that is fine, considering a distributed projection needs only to know what to do in its relevant families) + // Note: without explicit connections, even if don't directly talk with a family co-member, basic session model still forms the connection + // E.g., basic pipeline, left/right not "common" because of "connections to right/[middle]/left" distinguished from "connections to *neighbours*" + // Ideally, want to reason about dial/accept to make only the "necessary connections" => explicit connections + //boolean isCommonEndpointKind = this.apigen.peers.get(variant).size() == 1; + // CHECKME: why 1, should it be generalised? + // CHECKME: peers doesn't consider families -- should isCommonEndpointKind be determined from families? + /*boolean isCommonEndpointKind = this.families.keySet().stream().filter(p -> p.left.contains(variant)) + // Would also be reasonable to require variant to be in every family -- but not necessary since a distributed projection is only for the families that the variant is involved in + .allMatch(p -> p.left.containsAll(this.peers.get(variant))); + return isCommonEndpointKind;*/ + return this.families.size() == 1; // Now essentially disabled, to make "variant equivalence" easier + + /*// "Syntactically" determining common endpoint kinds difficult because concrete peers depends on param (and foreachvar) values, e.g., M in PGet w.r.t. #F + // Also, family factoring is more about dial/accept + isCommonEndpointKind = true; + Set peers = null; + X: for (Pair, Set> fam : this.apigen.families.keySet()) + { + if (fam.left.contains(variant)) + { + EGraph g = this.apigen.variants.get(rname).get(variant); + Set as = RPCoreEState.getReachableActions((RPCoreEModelFactory) this.apigen.job.ef, (RPCoreEState) g.init); + Set tmp = as.stream().map(a -> a.getPeer()).collect(Collectors.toSet()); + if (peers == null) + { + peers = tmp; + } + else if (!peers.equals(tmp)) + { + isCommonEndpointKind = false; + break X; + } + } + } + //*/ + } + + + + /*//@Override + public List getScribbleRuntimeImports() // FIXME: factor up + { + return Stream.of( + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + ////ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSIONPARAM_PACKAGE + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE + + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_BYTES_PACKAGE, + //ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_GOB_PACKAGE + ).collect(Collectors.toList()); + } + + public String generateScribbleRuntimeImports() + { + return getScribbleRuntimeImports().stream().map(x -> "import \"" + x + "\"\n").collect(Collectors.joining()); + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTBranchActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTBranchActionBuilder.java new file mode 100644 index 000000000..7a5f7a34e --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTBranchActionBuilder.java @@ -0,0 +1,167 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.List; +import java.util.stream.Collectors; + +import org.scribble.codegen.statetype.STBranchActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.MessageSigName; + +public class RPCoreSTBranchActionBuilder extends STBranchActionBuilder +{ + // Called by STBranchStateBuilder#build on .get(1) action (a hack for Branch states) + @Override + public String build(STStateChanApiBuilder api, EState curr, EAction a) // FIXME: "overriding" STStateChanAPIBuilder.buildAction to hack around *interface return // FIXME: factor out + { + + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + //String scTypeName = rpapi.getStateChanName(curr); + + EState succ = curr.getSuccessor(a); + + String branchComment = + "// " + getActionName(api, a) + " is a branch with branch label\n" + + "// " + curr.getActions().stream().map(action -> action.mid.toString()).collect(Collectors.joining(" or ")) + "\n"; + + String res = + branchComment + + "func (s *" + getStateChanType(api, curr, a) + ") " + getActionName(api, a) + "(" + + buildArgs(null, a) + + ") " + getReturnType(api, curr, succ) + " {\n" // HACK: return type is interface, so no need for *return (unlike other state chans) + + "if " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " != nil {\n" + + "panic(" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + ")\n" + + "}\n"; + + if (rpapi.apigen.job.parForeach) + { + res += RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + "." + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n"; + } + else + { + res += "if " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + "id != " // Not using atomic.LoadUint64 on id for now + //+ "atomic.LoadUint64(&" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + "lin)" + + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + "lin" + + " {\n" + + "panic(\"Linear resource already used\")\n" // + reflect.TypeOf(" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "))\n" + + "}\n"; + } + + res += buildBody(api, curr, a, succ) + "\n" + + "}"; + + return res; + } + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return RPCoreSTStateChanApiBuilder.getGeneratedIndexedRoleName((RPIndexedRole) a.peer) + "_Branch"; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + return ""; + } + + @Override + public String getReturnType(STStateChanApiBuilder api, EState curr, EState succ) + { + return api.cb.getCaseStateChanName(api, curr); + } + + // "a" and "succ" are the .get(1) action (a hack for Branch states) + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + + List as = curr.getAllActions(); + if (!as.stream().allMatch(x -> x.mid.isOp()) && !as.stream().allMatch(x -> x.mid.isMessageSigName())) + { + throw new RuntimeException("[rp-core] [-param-api] Mixed choice of message sig and sig names not supported: " + as); + } + + RPIndexedRole peer = (RPIndexedRole) a.peer; // Singleton interval + String sEpRecv = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN; /*+ "." + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_MAP + + "[\"" + peer.getName() + "\"]";*/ + + String res = ""; + + // FIXME: factor out with RPCoreSTStateChanApiBuilder#getSuccStateChan -- don't need terminal check for succ though + String ret = RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": " + + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ", " + + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + ": new(" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ")" + + (rpapi.apigen.job.parForeach ? ", Thread: " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + ".Thread" : ""); + + // Duplicated from RPCoreSTReceiveActionBuilder + RPInterval d = peer.intervals.iterator().next(); + if (peer.intervals.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: " + a); + } + if (!d.isSingleton()) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + a); + } + if (a.mid.isOp()) // Currently, assuming all mids are Ops; else all mids are sig names + { + // Duplicated from RPCoreSTReceiveActionBuilder + res += "var lab string\n" // cf. RPCoreSTReceiveActionBuilder + + "if err := " + sEpRecv /*+ "[1]" // FIXME: use peer interval + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_IRECV + "(" + "&lab" + ")"*/ + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_IRECV + "(\"" + peer.getName() + "\", " + + rpapi.generateIndexExpr(d.start) + ", &lab" + ")" // peer must have singleton interval + + "; err != nil {\n" + //+ "log.Fatal(err)\n" + //+ "return " + rpapi.makeCreateSuccStateChan(succ) + "\n" // FIXME: disable linearity check for error chan? Or doesn't matter -- only need to disable completion check? + + "panic(err)\n" // FIXME: which case object to return for error? make "default" error case object? + + "}\n"; + + // Switch and return Cases value + res += "\n" + + "switch lab {\n" + + as.stream().map(x -> + "case \"" + x.mid + "\":\n" + "return &" + RPCoreSTCaseBuilder.getOpTypeName(api, curr, x.mid) + //+ "{ Ept: s.Ept, Res: new(session.LinearResource) }\n" + + "{" + ret + "}\n" + ).collect(Collectors.joining("")) + + "default: panic(\"Shouldn't get in here: \" + lab)\n" + + "}\n" + + "return nil\n"; // FIXME: panic instead + } + else //if (a.mid.isMessageSigName()) + { + // FIXME: factor out futher (receive, case) + res += //"var msg session.T\n" // var decl needed for deserialization -- FIXME? + "var msg session2.ScribMessage\n" + + "if err := " + sEpRecv /*+ "[1]" // FIXME: use peer interval + + "." //+ RPCoreSTApiGenConstants.GO_MPCHAN_READALL + "(" + "&msg" + ")"*/ + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_MRECV + "(\"" + peer.getName() + "\", " + + rpapi.generateIndexExpr(d.start) + ", &msg" + ")" // peer must have singleton interval + + "; err != nil {\n" + //+ "log.Fatal(err)\n" + + "panic(err)\n" // FIXME: which case object to return for error? make "default" error case object? + + "}\n"; + + res += "\n" + + "switch x := msg.(type) {\n" + + as.stream().map(x -> + "case *" + ((RPCoreSTStateChanApiBuilder) api).getExtName((MessageSigName) x.mid) + ":\n" + + "return &" + RPCoreSTCaseBuilder.getOpTypeName(api, curr, x.mid) + " { " + + ret + ", msg: x }\n" + ).collect(Collectors.joining("")) + + "default: panic(\"Shouldn't get in here: \" + reflect.TypeOf(msg).String())\n" + + "}\n" + + "return nil\n"; // FIXME: panic instead + } + + return res; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTBranchStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTBranchStateBuilder.java new file mode 100644 index 000000000..15cfd2d94 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTBranchStateBuilder.java @@ -0,0 +1,118 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import org.scribble.codegen.statetype.STBranchStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.codegen.statetype3.RPCoreSTApiGenerator.Mode; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.EStateKind; +import org.scribble.type.name.GProtocolName; + +// Type switch branch -- cf., RPCoreSTSelectStateBuilder +public class RPCoreSTBranchStateBuilder extends STBranchStateBuilder +{ + public RPCoreSTBranchStateBuilder(RPCoreSTBranchActionBuilder bb) + { + super(bb); + } + + // Cf. RPCoreSTStateChanApiBuilder -- the hierarchy splits off branch state building separately + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + + /*GProtocolName simpname = rpapi.apigen.proto.getSimpleName(); + String scTypeName = rpapi.getStateChanName(s); + String epTypeName = RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, rpapi.variant); */ + + String res = //rpapi.getStateChanPremable(s); + getStateChanPremable(rpapi, s); + + /*// Explicit constructor -- for compatibility with RPCoreSTSelectStateBuilder -- not currently needed: assuming select/typeswitch API gen mutually exclusive + res += "\n" + + "func (ep *" + epTypeName + ") NewBranchInit" // FIXME: factor out + + "() *" + scTypeName + " {\n" + + "s := &" + scTypeName + " { " + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": ep" + ", " + + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + ": new(" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ") " + + "}\n" + + "return s\n" + + "}\n";*/ + + return res; + } + + // FIXME refactor -- duplicated from RPCoreSTStateChanApiBuilder#getStateChanPremable, just to set false in apib.makeMessageImports(s, false); + protected String getStateChanPremable(RPCoreSTStateChanApiBuilder apib, EState s) + { + GProtocolName simpname = apib.apigen.proto.getSimpleName(); + String scTypeName = apib.getStateChanName(s); + String epkindTypeName = RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, apib.variant); + + String res = + "package " + RPCoreSTApiGenerator.getEndpointKindPackageName(apib.variant) + "\n" + + "\n"; + + // Not needed by select-branch or Case objects // FIXME: refactor back into state-specific builders? + if (s.getStateKind() == EStateKind.OUTPUT || s.getStateKind() == EStateKind.UNARY_INPUT + || (s.getStateKind() == EStateKind.POLY_INPUT && !apib.apigen.job.selectApi)) + { + res += apib.makeMessageImports(s, false); + } + + // FIXME: still needed? -- refactor back into state-specific builders? + if (s.getStateKind() == EStateKind.UNARY_INPUT || s.getStateKind() == EStateKind.POLY_INPUT) + { + switch (apib.apigen.mode) + { + case Int: res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n"; break; + case IntPair: res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE + "\"\n"; break; + default: throw new RuntimeException("Shouldn't get in here:" + apib.apigen.mode); + } + + res += "import \"sync/atomic\"\n"; + res += "import \"reflect\"\n"; + res += "import \"sort\"\n"; + res += "\n"; + + res += "var _ = session2.NewMPChan\n"; + + res += "var _ = atomic.AddUint64\n"; + res += "var _ = reflect.TypeOf\n"; + res += "var _ = sort.Sort\n"; + } + else if (s.getStateKind() == EStateKind.OUTPUT) + { + if (apib.apigen.mode == Mode.IntPair) + { + res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE + "\"\n"; + res += "\n"; + res += "var _ = session2.XY\n"; // For nested states that only use foreach vars (so no session2.XY) + } + } + + // State channel type + res += "\n" + + "type " + scTypeName + " struct {\n" + + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " error\n"; + + if (apib.apigen.job.parForeach) + { + res += RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "\n"; + } + else + { + res += "id uint64\n"; + } + + res += RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epkindTypeName + "\n"; + + if (apib.apigen.job.parForeach) + { + res += "Thread int\n"; + } + + res += "}\n"; + + return res; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTCaseActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTCaseActionBuilder.java new file mode 100644 index 000000000..91b8a3fda --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTCaseActionBuilder.java @@ -0,0 +1,109 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STCaseActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; +import org.scribble.type.name.MessageSigName; + +public class RPCoreSTCaseActionBuilder extends STCaseActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return //RPCoreSTStateChanApiBuilder.getGeneratedIndexedRoleName((RPIndexedRole) a.peer) + "_" + + "Recv_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder api, EAction a) + { + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + if (a.mid.isOp()) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> RPCoreSTApiGenConstants.GO_CASE_METHOD_ARG + i + + " *" + rpapi.getExtName((DataType) a.payload.elems.get(i))) + .collect(Collectors.joining(", ")); + } + else //if (a.mid.isMessageSigName()) + { + return RPCoreSTApiGenConstants.GO_CASE_METHOD_ARG + "0 *" + + rpapi.getExtName((MessageSigName) a.mid); + } + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + RPIndexedRole peer = (RPIndexedRole) a.peer; // Singleton interval + + String sEpRecv = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN; /*+ "." + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_MAP + + "[\"" + peer.getName() + "\"]";*/ + + // Duplicated from RPCoreSTReceiveActionBuilder + RPInterval d = peer.intervals.iterator().next(); + if (peer.intervals.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: " + a); + } + if (!d.isSingleton()) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + a); + } + // makeCaseReceive is called only for payload type which involves the + // use of IRecv. The caller is Recv_Label(arg0 *T) for Label(T) message. + // IRecv accepts pointer as parameter so passing arg0 here (of type *T) + // instead of &arg0 (or type **T). + Function makeCaseReceive = pt -> + //+ (extName.startsWith("[]") ? "tmp = make(" + extName + ", len(*arg0))\n" : "") // HACK: [] // N.B. *arg0 matches buildArgs + "if err := " + sEpRecv /*+ "[1]" // FIXME: use peer interval + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_READALL + "(&tmp)"*/ + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_IRECV + "(\"" + peer.getName() + "\", " + + rpapi.generateIndexExpr(d.start) + ", arg0)" + + "; err != nil {\n" + //+ "log.Fatal(err)\n" + //+ "return " + rpapi.makeCreateSuccStateChan(succ) + "\n" // FIXME: disable linearity check for error chan? Or doesn't matter -- only need to disable completion check? + + rpapi.makeReturnSuccStateChan(succ) + "\n" + + "}\n"; + //+ "*arg0 = tmp.(" + extName + ")\n"; // N.B. *arg0 matches buildArgs + //+ "*arg0 = *(tmp.(*" + pt + "))\n"; // Cf. RPCoreSTReceiveActionBuilder // N.B. *arg0 matches buildArgs + + String res = ""; + if (a.mid.isOp()) + { + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[rp-core] [-param-api] TODO: " + a); + } + + res += makeCaseReceive.apply(rpapi.getExtName((DataType) a.payload.elems.get(0))); // Payload "type" + } + } + else //if (a.mid.isMessageSigName()) + { + //res += f.apply(rpapi.getExtName((MessageSigName) a.mid)); + // FIXME: no -- Branch() should already receive the sig message and case action should just return it + res += "*arg0 = *s.msg\n"; + } + return res + buildReturn(rpapi, curr, succ); + } + + @Override + public String getStateChanType(STStateChanApiBuilder api, EState curr, EAction a) + { + return RPCoreSTCaseBuilder.getOpTypeName(api, curr, a.mid); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTCaseBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTCaseBuilder.java new file mode 100644 index 000000000..f841fa9d4 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTCaseBuilder.java @@ -0,0 +1,107 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.HashMap; +import java.util.Map; + +import org.scribble.codegen.statetype.STCaseBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.main.RuntimeScribbleException; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.MessageSigName; + +public class RPCoreSTCaseBuilder extends STCaseBuilder +{ + public RPCoreSTCaseBuilder(RPCoreSTCaseActionBuilder cb) + { + super(cb); + } + + protected static String getCaseActionName(STStateChanApiBuilder api, EState s) + { + return api.getStateChanName(s) + "_Case"; + } + + @Override + public String getCaseStateChanName(STStateChanApiBuilder api, EState s) + { + String name = api.getStateChanName(s) + "_Cases"; + return name; + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + String casename = getCaseActionName(api, s); + String res = "package " + RPCoreSTApiGenerator.getEndpointKindPackageName(rpapi.variant) + "\n" + + "\n"; + + switch (rpapi.apigen.mode) + { + case Int: res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n"; break; + case IntPair: res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE + "\"\n"; break; + default: throw new RuntimeException("Shouldn't get in here: " + rpapi.apigen.mode); + } + + res += + "import \"log\"\n" + + ((RPCoreSTStateChanApiBuilder) api).makeMessageImports(s, true) + + "\n" + + "var _ = log.Fatal\n" + + "\n" + + // Case object interface + + "type " + getCaseStateChanName(api, s) + " interface {\n" + + casename + "()\n" + + "}\n"; + + // Case object types + for (EAction a: s.getAllActions()) + { + String extName = (a.mid.isOp()) ? //rpapi.getExtName((DataType) a.mid) + getOpTypeName(api, s, a.mid) + : rpapi.getExtName((MessageSigName) a.mid); + res += "\ntype " + getOpTypeName(api, s, a.mid) + " struct {\n" + + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " error\n" // FIXME: never set -- branch action won't return an actual case object upon error + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + RPCoreSTApiGenerator.getEndpointKindTypeName(null, rpapi.variant) + "\n" + + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "\n" + + (a.mid.isMessageSigName() ? "msg *" + extName + "\n" : "") + + (rpapi.apigen.job.parForeach ? "Thread int\n" : "") + + "}\n" + + + "\n" + + + "func (*" + getOpTypeName(api, s, a.mid) + ") " + casename + "() {}\n"; + } + + return res; + } + + private static Map seen = new HashMap<>(); // FIXME HACK + + // For type switch on Ops as types ("enum") + protected static String getOpTypeName(STStateChanApiBuilder api, EState s, MessageId mid) + { + String op = mid.toString(); + char c = op.charAt(0); + if (c < 'A' || c > 'Z') + { + throw new RuntimeScribbleException("[rp-core] Branch message op should start with a capital letter: " + op); // FIXME: + } + if (RPCoreSTCaseBuilder.seen.containsKey(op)) + { + if (RPCoreSTCaseBuilder.seen.get(op) != s.id) + { + String n = api.getStateChanName(s); // HACK + op = op + "_" + api.role + "_" + n.substring(n.lastIndexOf('_') + 1); + } + } + else + { + RPCoreSTCaseBuilder.seen.put(op, s.id); + } + return op; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTEndStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTEndStateBuilder.java new file mode 100644 index 000000000..005da9e70 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTEndStateBuilder.java @@ -0,0 +1,43 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import org.scribble.codegen.statetype.STEndStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; + +public class RPCoreSTEndStateBuilder extends STEndStateBuilder +{ + public RPCoreSTEndStateBuilder() + { + + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + return getPreamble(api, s); + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + RPCoreSTStateChanApiBuilder schangen = (RPCoreSTStateChanApiBuilder) api; + String scTypeName = api.getStateChanName(s); + String res = + "package " + RPCoreSTApiGenerator.getEndpointKindPackageName(((RPCoreSTStateChanApiBuilder) api).variant) + "\n" + + "\n" + //+ "import \"" + ParamCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n" + + "\n" + + "type " + scTypeName + " struct {\n" + + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " error\n" + + + "id uint64\n" + + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + + RPCoreSTApiGenerator.getEndpointKindTypeName(api.gpn.getSimpleName(), schangen.variant) + "\n" // FIXME: factor out + + + (((RPCoreSTStateChanApiBuilder) api).apigen.job.parForeach ? "Thread int\n" : "") + + + "}"; + return res; // No LinearResource + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTOutputStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTOutputStateBuilder.java new file mode 100644 index 000000000..9e2328d1d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTOutputStateBuilder.java @@ -0,0 +1,66 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import org.scribble.codegen.statetype.STOutputStateBuilder; +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.model.endpoint.actions.EDisconnect; +import org.scribble.model.endpoint.actions.ERequest; +import org.scribble.model.endpoint.actions.ESend; + +public class RPCoreSTOutputStateBuilder extends STOutputStateBuilder +{ + public final RPCoreSTSendActionBuilder nb; + + // sb is ParamCoreSTSplitActionBuilder + public RPCoreSTOutputStateBuilder(STSendActionBuilder sb, RPCoreSTSendActionBuilder nb) + { + super(sb); + this.nb = nb; + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + return ((RPCoreSTStateChanApiBuilder) api).getStateChanPremable(s); + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + String out = getPreamble(api, s); + + for (EAction a : s.getActions()) + { + out += "\n\n"; + if (a instanceof ESend) // FIXME: factor out action kind + { + //out += this.sb.build(api, s, a); + + /*// FIXME: delegation + if (!a.payload.elems.stream() + .anyMatch(pet -> ((RPCoreSTStateChanApiBuilder) api)//.isDelegType((DataType) pet))) + .isDelegType(pet)))*/ + { + out += "\n\n"; + out += this.nb.build(api, s, a); + } + } + else if (a instanceof ERequest) + { + throw new RuntimeException("TODO: " + a); + } + else if (a instanceof EDisconnect) + { + throw new RuntimeException("TODO: " + a); + } + else + { + throw new RuntimeException("Shouldn't get in here: " + a); + } + } + + return out; + } +} \ No newline at end of file diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReceiveActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReceiveActionBuilder.java new file mode 100644 index 000000000..722cc2068 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReceiveActionBuilder.java @@ -0,0 +1,200 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.main.GoJob; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.MessageSigName; + +public class RPCoreSTReceiveActionBuilder extends STReceiveActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return RPCoreSTStateChanApiBuilder.getGeneratedIndexedRoleName(((RPCoreEAction) a).getPeer()) + + "_" + RPCoreSTApiGenConstants.RP_GATHER_METHOD_PREFIX // FIXME: make unary Receive special case + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder api, EAction a) + { + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + if (a.mid.isOp()) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> RPCoreSTApiGenConstants.GO_CROSS_RECEIVE_METHOD_ARG + i + " []" + + rpapi.getPayloadElemTypeName(a.payload.elems.get(i))) + .collect(Collectors.joining(", ")); + } + else //if (a.mid.isMessageSigName()) + { + return RPCoreSTApiGenConstants.GO_CROSS_RECEIVE_METHOD_ARG + "0 []" + + rpapi.getExtName((MessageSigName) a.mid); + } + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + RPIndexedRole peer = (RPIndexedRole) a.peer; + RPInterval d = peer.intervals.iterator().next(); + if (peer.intervals.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: " + a); + } + + String sEpRecv = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN; /*+ "." //+ RPCoreSTApiGenConstants.GO_CONNECTION_MAP + + RPCoreSTApiGenConstants.GO_MPCHAN_FORMATTER_MAP + + "[\"" + peer.getName() + "\"]";*/ + + String res = ""; + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + + if (((GoJob) rpapi.job).noCopy) + { + /*res += "data := make([]" + a.payload.elems.get(0) + ", len(b))\n" + + "for i := 0; i < len(b); i++ {\n" + + "data[i] = *b[i].(*" + a.payload.elems.get(0) + ")\n" + + "}\n" + + "*arg0 = reduceFn0(data)\n";*/ + throw new RuntimeException("[rp-core] TODO: -nocopy: " + a); // FIXME: currently missing from sender side? + } + else + { + + // TODO: factor out with send, etc. + String lte; + String inc; + switch (rpapi.apigen.mode) + { + case Int: + { + lte = " <= " + rpapi.generateIndexExpr(d.end); + inc = "i+1"; + break; + } + case IntPair: + { + lte = ".Lte(" + rpapi.generateIndexExpr(d.end) + ")"; + inc = "i.Inc(" + rpapi.generateIndexExpr(d.end) + ")"; + break; + } + default: throw new RuntimeException("Shouldn't get in here: " + rpapi.apigen.mode); + } + + String start = rpapi.generateIndexExpr(d.start); + res += //"var err error\n" + "for i, j := " + start + ", 0;" + + " i " + lte + "; i, j = " + inc + ", j+1 {\n"; + + // For payloads -- FIXME: currently hardcoded for exactly one payload + + String errorField = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + + "_" + rpapi.getSuccStateChanName(succ) + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_ERR; + + if (a.mid.isOp()) + { + //if (!a.mid.toString().equals("")) // HACK FIXME? // Now redundant, -param-api checks mid starts uppercase + { + res += "var lab string\n" + + "if " + errorField + " = " + sEpRecv /*+ "[i]" + + "." //+ RPCoreSTApiGenConstants.GO_ENDPOINT_READALL + "(" + "&lab" + ")" + + RPCoreSTApiGenConstants.GO_FORMATTER_DECODE_STRING + "()"*/ + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_IRECV + "(\"" + peer.getName() + "\", i, &lab)" + + "; " + errorField + " != nil {\n" + //+ "log.Fatal(err)\n" + //+ "return " + rpapi.makeCreateSuccStateChan(succ) + "\n" // FIXME: disable linearity check for error chan? Or doesn't matter -- only need to disable completion check? + + rpapi.makeReturnSuccStateChan(succ) + "\n" + + "}\n"; + } + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[rp-core] [-param-api] TODO: " + a); + } + + Function makeReceivePayType = pt -> + //+ (extName.startsWith("[]") ? "tmp = make(" + extName + ", len(arg0))\n" : "") // HACK? for passthru? + "if " + errorField + " = " + sEpRecv /*+ "[i]" // FIXME: use peer interval + + "." //+ RPCoreSTApiGenConstants.GO_ENDPOINT_READALL + "(&tmp)" + + RPCoreSTApiGenConstants.GO_FORMATTER_DECODE_INT + "()"*/ + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_IRECV + "(\"" + peer.getName() + "\", i, &arg0[j])" + + + "; " + errorField + " != nil {\n" + //+ "log.Fatal(err)\n" + //+ "return " + rpapi.makeCreateSuccStateChan(succ) + "\n" // FIXME: disable linearity check for error chan? Or doesn't matter -- only need to disable completion check? + + rpapi.makeReturnSuccStateChan(succ) + "\n" + + "}\n"; + // + "arg0[i-" + start + "] = *(tmp.(*" + pt + "))\n"; // FIXME: doesn't work for gob, pointer decoding seems flattened? ("*" dropped) ... // Cf. ISend in RPCoreSTSendActionBuilder + //+ "arg0[i-" + start + "] = tmp.(" + pt + ")\n"; // FIXME: ... but doesn't work for shm + res += makeReceivePayType.apply(rpapi.getPayloadElemTypeName(a.payload.elems.get(0))); + } + } + else //if (a.mid.isMessageSigName()) + { + Function makeReceiveExtName = extName -> + "var tmp " + RPCoreSTApiGenConstants.GO_SCRIBMESSAGE_TYPE + "\n" // var tmp needed for deserialization -- FIXME? + + "if " + errorField + " = " + sEpRecv /*+ "[i]" // FIXME: use peer interval + + RPCoreSTApiGenConstants.GO_FORMATTER_DECODE_INT + "()"*/ + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_MRECV + "(\"" + peer.getName() + "\", i, &tmp)" + + + "; " + errorField + " != nil {\n" + //+ "log.Fatal(err)\n" + //+ "return " + rpapi.makeCreateSuccStateChan(succ) + "\n" // FIXME: disable linearity check for error chan? Or doesn't matter -- only need to disable completion check? + + rpapi.makeReturnSuccStateChan(succ) + "\n" + + "}\n" + + "arg0[j] = *(tmp.(*" + extName + "))\n"; // Cf. ISend in RPCoreSTSendActionBuilder + res += makeReceiveExtName.apply(rpapi.getExtName((MessageSigName) a.mid)); + } + + res += "}\n"; + } + + return res + buildReturn(rpapi, curr, succ); + } + + /*protected static String hackGetValues(String t) + { + if (t.equals("int")) + { + return "util.GetValuesInt"; + } + else if (t.equals("string")) + { + return "util.GetValuesString"; + } + else if (t.equals("[]byte")) + { + return "util.GetValuesBates"; + } + else + { + throw new RuntimeException("[TODO] " + t); + //return t; + } + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReceiveStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReceiveStateBuilder.java new file mode 100644 index 000000000..24c07184e --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReceiveStateBuilder.java @@ -0,0 +1,55 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.List; + +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STReceiveStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; + +public class RPCoreSTReceiveStateBuilder extends STReceiveStateBuilder +{ + public final RPCoreSTReceiveActionBuilder vb; + + // sb is ParamCoreSTReduceActionBuilder + public RPCoreSTReceiveStateBuilder(STReceiveActionBuilder sb, RPCoreSTReceiveActionBuilder vb) + { + super(sb); + this.vb = vb; + } + + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + return ((RPCoreSTStateChanApiBuilder) api).getStateChanPremable(s); + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + String out = getPreamble(api, s); + + List as = s.getActions(); + if (as.size() > 1) + { + throw new RuntimeException("Shouldn't get in here: " + as); + } + EAction a = as.get(0); + + /*out += "\n\n"; + out += this.rb.build(api, s, a);*/ + + /*// FIXME: delegation + if (!a.payload.elems.stream() + .anyMatch(pet -> ((RPCoreSTStateChanApiBuilder) api)//.isDelegType((DataType) pet))) + .isDelegType(pet)))*/ + { + out += "\n\n"; + out += this.vb.build(api, s, a); + } + + return out; + } +} + diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReduceActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReduceActionBuilder.java new file mode 100644 index 000000000..7b804ca44 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTReduceActionBuilder.java @@ -0,0 +1,247 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STReceiveActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; +import org.scribble.type.name.PayloadElemType; + +public class RPCoreSTReduceActionBuilder extends STReceiveActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + //return ParamCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_PREFIX + "_" + return RPCoreSTApiGenConstants.GO_CROSS_REDUCE_FUN_PREFIX + "_" + + RPCoreSTStateChanApiBuilder.getGeneratedIndexedRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + RPCoreSTStateChanApiBuilder api = (RPCoreSTStateChanApiBuilder) apigen; + //DataType[] pet = new DataType[1]; + PayloadElemType[] pet = new PayloadElemType[1]; + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> RPCoreSTApiGenConstants.GO_CROSS_RECEIVE_METHOD_ARG + + i + " *" + api.getPayloadElemTypeName(pet[0] = a.payload.elems.get(i)) //a.payload.elems.get(i) + + // HACK + + (api.isDelegType(pet[0]) ? "" : + ", reduceFn" + i + " func(" + RPCoreSTApiGenConstants.GO_CROSS_SEND_METHOD_ARG + i + //+ " []" + a.payload.elems.get(i) + ") " + a.payload.elems.get(i) + + " []" + + + api.getPayloadElemTypeName(pet[0]) + + + ") " + + + api.getPayloadElemTypeName(pet[0]) + ) + + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder apigen, EState curr, EAction a, EState succ) + { + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + String sEpRecv = + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + + "." + "Conn";//ParamCoreSTApiGenConstants.GO_ENDPOINT_READALL; + String sEpProto = + //"s.ep.Proto" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + RPCoreSTApiGenConstants.GO_MPCHAN_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval g = r.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + /*sEpRecv + + "(" + sEpProto + + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "\"" + a.mid + "\")\n" + + IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> sEpRecv + "(" + sEpProto + ".(*" + api.gpn.getSimpleName() +")." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "arg" + i + ")") + .collect(Collectors.joining("\n")) + "\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + "\tvar decoded "+a.payload.elems.get(0)+"\n" + + "\tif err := gob.NewDecoder(bytes.NewReader(b[i-"+foo.apply(g.start)+"])).Decode(&decoded); err != nil {\n\t\t" + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Errors <- session.DeserialiseFailed(err, \"" + getActionName(api, a) +"\", " + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Self.Name())\n" + + "\t}\n" + + "\tdata[i-"+foo.apply(g.start)+"] = decoded\n" + + "}\n" + + "*arg0 = reduceFn(data)" + /*+ "if " + sEpErr + " != nil {\n" + + "return nil\n" + + "}\n"*/ + + // FIXME: single arg // Currently never true because of ParamCoreSTOutputStateBuilder + boolean isDeleg = a.payload.elems.stream().anyMatch(pet -> + //pet.isGDelegationType() // FIXME: currently deleg specified by ParmaCoreDelegDecl, not GDelegationElem + ((RPCoreSTStateChanApiBuilder) apigen)//.isDelegType((DataType) pet)); + .isDelegType(pet)); + + /*String res = + sEpRecv + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + r.getName() + ", " + foo.apply(g.start) + ", " + foo.apply(g.end) + ")\n"; // Discard op*/ + String res = ""; + + if (isDeleg) + { + /*var ept *session.Endpoint + err := conn.Recv(&ept) + if err != nil { + log.Fatalf("Wrong value received..") + } + sesss[i] = &Game_a_Init{ept: ept} // Delegated session initialisation + + st.ept.ConnMu.RUnlock() + return sesss, &ClientA_p_End{}*/ + + String extName = ((RPCoreSTStateChanApiBuilder) apigen).getExtName((DataType) a.payload.elems.get(0)); + + res = + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" // FIXME: num args + + + (a.mid.toString().equals("") ? "" : // HACK + "var lab string\n" + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "&lab" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n") + + + "var tmp *" + + extName + "\n" + //extName.substring(0, extName.indexOf('_', extName.indexOf('_', extName.indexOf('_')+1)+1)) + "\n" // FIXME HACK + + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + //+ "&data[i-1]" + + "&tmp" + + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "arg0 = &" + extName + "{" + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": tmp." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " }\n" + + "}\n"; + + } + else if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + + String extName = ((RPCoreSTStateChanApiBuilder) apigen).getExtName((DataType) a.payload.elems.get(0)); + + res += + (((GoJob) apigen.job).noCopy + ? + "data := make([]" + a.payload.elems.get(0) + ", len(b))\n" + + "for i := 0; i < len(b); i++ {\n" + + "data[i] = *b[i].(*" + a.payload.elems.get(0) + ")\n" + + "}\n" + + "*arg0 = reduceFn0(data)\n" + : + /*"data := make([]" + ParamCoreSTStateChanApiBuilder.batesHack(a.payload.elems.get(0)) //a.payload.elems.get(0) + + ", " + foo.apply(g.end) + ")\n"*/ + "data := make(map[int]" + extName + ")\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" // FIXME: num args + + + (a.mid.toString().equals("") ? "" : // HACK + "var lab string\n" + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "&lab" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n") + + + "var tmp " + extName + "\n" + + + (extName.startsWith("[]") ? "tmp = make(" + extName + ", len(*arg0))\n" : "") // HACK? for passthru? + + + "if err := " + sEpRecv + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_READALL + + "(" //+ sEpProto + "." + r.getName() + ", " + //+ "&data[i-1]" + + "&tmp" + + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "data[i] = tmp\n" + + "}\n" + //+ "*arg0 = reduceFn0(" + // + ParamCoreSTReceiveActionBuilder.hackGetValues(((ParamCoreSTStateChanApiBuilder) apigen).batesHack(a.payload.elems.get(0))) + "(data))\n"); // FIXME: arg0 + + + "f := func(m map[int] " + extName + ") []" + extName + " {\n" + + + "xs := make([]" + extName + ", len(m))\n" + + "keys := make([]int, 0)\n" + + "for k, _ := range m {\n" + + "keys = append(keys, k)\n" + + "}\n" + + "sort.Ints(keys)\n" // Needed? + + "for i, k := range keys {\n" + + "xs[i] = m[k]\n" + + "}\n" + + "return xs\n" + + "}\n" + + "*arg0 = reduceFn0(f(data))\n"); + } + + return res + + buildReturn(apigen, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSelectActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSelectActionBuilder.java new file mode 100644 index 000000000..2932b949a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSelectActionBuilder.java @@ -0,0 +1,124 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STBranchActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.codegen.statetype3.RPCoreSTStateChanApiBuilder.RPCoreEStateKind; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.main.GoJob; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; + +// Case/Recv action on select case objects +// N.B. Select means Go select statement for input-choice; not output-choice +public class RPCoreSTSelectActionBuilder extends STBranchActionBuilder +{ + @Override + public String build(STStateChanApiBuilder api, EState curr, EAction a) + { + EState succ = curr.getSuccessor(a); + if (//((GoJob) api.job).selectApi && + RPCoreSTStateChanApiBuilder.getStateKind(curr) == RPCoreEStateKind.CROSS_RECEIVE && curr.getActions().size() > 1) + { + // HACK FIXME: move to action builder + return + "func (" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + + " *" + getStateChanType(api, curr, a) + ") " + getActionName(api, a) + "(" + + buildArgs(api, a) + + ") <-chan *" + getReturnType(api, curr, succ) + " {\n" + + buildBody(api, curr, a, succ) + "\n" + + "}"; + } + else + { + return super.build(api, curr, a); + } + } + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return RPCoreSTStateChanApiBuilder.getGeneratedIndexedRoleName(((RPCoreEAction) a).getPeer()) + + "_" + RPCoreSTApiGenConstants.GO_CROSS_RECEIVE_FUN_PREFIX + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder api, EAction a) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> RPCoreSTApiGenConstants.GO_CROSS_RECEIVE_METHOD_ARG + + i + " *" + ((RPCoreSTStateChanApiBuilder) api).getExtName((DataType) a.payload.elems.get(i)) + //+ ", reduceFn" + i + " func(" + ParamCoreSTApiGenConstants.GO_CROSS_SEND_FUN_ARG + i + " []int) int" // No: singleton choice subj (not multichoices) + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + + boolean isDeleg = a.payload.elems.stream().anyMatch(pet -> + //pet.isGDelegationType() // FIXME: currently deleg specified by ParmaCoreDelegDecl, not GDelegationElem + ((RPCoreSTStateChanApiBuilder) api)//.isDelegType((DataType) pet)); + .isDelegType(pet)); + if (isDeleg) + { + throw new RuntimeException("[rp-core] TODO: " + a); + } + + RPIndexedRole peer = (RPIndexedRole) curr.getActions().iterator().next().peer; + RPInterval d = peer.intervals.iterator().next(); + + String sEp = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + String sEpRecv = sEp + "." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN; /*+ "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_MAP + "[\"" + peer.getName() + "\"]";*/ + + String res = "_, selected := <-s._" + a.mid + "_Chan\n" + + "if !selected {\n" + + "\treturn nil // select ignores nilchan\n" + + "}\n"; + + if (a.mid.isOp()) + { + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: payload size > 1: " + a); + } + String extName = ((RPCoreSTStateChanApiBuilder) api).getExtName((DataType) a.payload.elems.get(0)); + + if (((GoJob) api.job).noCopy) + { + //res += "decoded = *bs[0].(*" + a.payload.elems.get(0) + ")\n"; + throw new RuntimeException("[rp-core] TODO: -nocopy: " + a); + } + + res += "if err := " + sEpRecv // + (((GoJob) api.job).noCopy ? "Raw" : ""); + //+ "[" + RPCoreSTStateChanApiBuilder.generateIndexExpr(d.start) + "].Recv(&arg0)" + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_IRECV + "(\"" + peer.getName() + "\", " + + rpapi.generateIndexExpr(d.start) + ", &arg0)" + + "; err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + //+ "*arg0 = tmp.(" + extName + ")\n" + + "ch := make(chan *" + rpapi.getStateChanName(curr.getSuccessor(a)) + ", 1)\n" + //+ "ch <- " + rpapi.makeCreateSuccStateChan(this, curr, curr.getSuccessor(a), sEp) + "\n"; + + "ch <- " + rpapi.makeCreateSuccStateChan(curr.getSuccessor(a)) + "\n"; + // FIXME: arg0 // FIXME: args depends on label // FIXME: store args in s.args + } + } + else //if (a.mid.isMessageSigName()) + { + throw new RuntimeException("[rp-core] TODO: " + a.mid); + } + + return res + "return ch"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSelectStateBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSelectStateBuilder.java new file mode 100644 index 000000000..647e6c71b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSelectStateBuilder.java @@ -0,0 +1,137 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.stream.Collectors; + +import org.scribble.codegen.statetype.STBranchStateBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.main.GoJob; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.model.endpoint.actions.EReceive; +import org.scribble.type.name.GProtocolName; + +// N.B. Select means Go select statement for input-choice; not output-choice +public class RPCoreSTSelectStateBuilder extends STBranchStateBuilder +{ + public RPCoreSTSelectStateBuilder(RPCoreSTSelectActionBuilder bb) + { + super(bb); + } + + @Override + public String build(STStateChanApiBuilder api, EState s) + { + String out = getPreamble(api, s); + + for (EAction a : s.getActions()) + { + out += "\n\n"; + if (a instanceof EReceive) // FIXME: factor out action kind + { + out += this.bb.build(api, s, a); // Getting 1 checks non-unary + } + else + { + throw new RuntimeException("Shouldn't get in here: " + a); + } + } + + return out; + } + + // Cf. RPCoreSTStateChanApiBuilder -- the hierarchy splits off branch state building separately + @Override + public String getPreamble(STStateChanApiBuilder api, EState s) + { + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + + GProtocolName simpname = rpapi.apigen.proto.getSimpleName(); + RPRoleVariant variant = ((RPCoreSTStateChanApiBuilder) api).variant; + String scTypeName = rpapi.getStateChanName(s); + String epTypeName = RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, rpapi.variant); + + String sEpRecv = + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN; + + String res = + "package " + RPCoreSTApiGenerator.getGeneratedRoleVariantName(variant) + "\n" + + "\n" + + "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n" + + "import \"log\"\n" + + // State channel type + + "\n" + + "type " + scTypeName + " struct{\n" + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epTypeName + "\n" + + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE +"\n" + + s.getActions().stream().map(a -> "_" + a.mid + "_Chan chan string\n").collect(Collectors.joining("")) + + "}\n"; + + // Explicit constructor -- for creating internal channels + res += "\n" + + "func newBranch" // FIXME: factor out, RPCoreSTStateChanApiBuilder#getSuccStateChan and RPCoreSTSelectActionBuilder#buildEndpointKindApi + + scTypeName + "(ep *" + epTypeName + ") *" + scTypeName + " {\n" + + "s := &" + scTypeName + " { " + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": ep" + ", " + + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + ": new(" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "), " + + s.getActions().stream().map(a -> "_" + a.mid + "_Chan: make(chan string, 1)").collect(Collectors.joining(", ")) + " " + + "}\n" + + "go s.branch()\n" + + "return s\n" + + "}\n"; + + RPIndexedRole peer = (RPIndexedRole) s.getActions().iterator().next().peer; // All branch actions have same subject + RPInterval d = peer.intervals.iterator().next(); + if (peer.intervals.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: " + s); + } + + // Branch background thread -- receive label, and signal corresponding channel + if (s.getAllActions().get(1).mid.isMessageSigName()) + { + throw new RuntimeException("[rp-core] TODO: " + s.getAllActions()); + } + + res += "\n" + + "func (" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + " *" + scTypeName + ") branch() {\n" + + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + "." + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n"; + if (((GoJob) rpapi.job).noCopy) + { + /*res += + "label := " + sEpRecv + "Raw(\"" + peer.getName() + "\", " + + RPCoreSTStateChanApiBuilder.generateIndexExpr(g.start) + ", " + RPCoreSTStateChanApiBuilder.generateIndexExpr(g.end) + ")\n" + + "op := *label[0].(*string)\n"; // FIXME: cast for safety?*/ + throw new RuntimeException("[rp-core] TODO: -nocopy: " + s); + } + else + { + res += + "if err := " + sEpRecv + "." /*+ RPCoreSTApiGenConstants.GO_MPCHAN_CONN_MAP + "[\"" + peer.getName() + "\"][" + + RPCoreSTStateChanApiBuilder.generateIndexExpr(d.start) + "].Recv(&op)*/ + + RPCoreSTApiGenConstants.GO_MPCHAN_IRECV + "(\"" + peer.getName() + "\", " + + rpapi.generateIndexExpr(d.start) + ", &op)" + + "; err != nil {\n" // g.end = g.start -- CFSM only has ? for input + + "log.Fatal(err)\n" + + "}\n"; + } + res+= "if " + s.getActions().stream().map(a -> + { + return "op == \"" + a.mid + "\" {\n" + + "\ts._" + a.mid + "_Chan <- \"" + a.mid +"\"\n" + + "\t" + s.getActions().stream() + .filter(otheract -> otheract.mid != a.mid) + .map(otheract -> { return "close(s._" + otheract.mid + "_Chan)"; }) + .collect(Collectors.joining("\n\t")) + "\n" + + "}"; + }).collect(Collectors.joining(" else if ")) + "\n" + + "}\n"; + + return res; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSendActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSendActionBuilder.java new file mode 100644 index 000000000..cc64d3680 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSendActionBuilder.java @@ -0,0 +1,195 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.MessageSigName; + +public class RPCoreSTSendActionBuilder extends STSendActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return RPCoreSTStateChanApiBuilder.getGeneratedIndexedRoleName(((RPCoreEAction) a).getPeer()) + + "_" + RPCoreSTApiGenConstants.RP_SCATTER_METHOD_PREFIX // FIXME: make unary Send special case + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder api, EAction a) + { + RPCoreSTStateChanApiBuilder apigen = (RPCoreSTStateChanApiBuilder) api; + if (a.mid.isOp()) + { + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> RPCoreSTApiGenConstants.GO_CROSS_SEND_METHOD_ARG + i + " []" + + apigen.getPayloadElemTypeName(a.payload.elems.get(i))) //a.payload.elems.get(i) + .collect(Collectors.joining(", ")); + } + else //if (a.mid.isMessageSigName()) + { + return RPCoreSTApiGenConstants.GO_CROSS_SEND_METHOD_ARG + "0 []" + + apigen.getExtName((MessageSigName) a.mid); + } + } + + /** + * checkError helper function surrounds the given expression expr with Go's error check + * and assigns errorField with err if it exists, i.e. + * + *
{@code
+	 * if err := $expression; err != nil {
+	 * 	 $errField = err
+	 * }
+	 * }
+ * + * @param expr Expression that returns error + * @param errField Location to store the error + * @return code fragment of expr with error check + */ + private String checkError(String expr, String errField) { + return "if err := " + expr + "; err != nil {\n" + errField + " = err\n" + "}\n"; + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + List as = curr.getActions(); + if (as.size() > 1 && as.stream().anyMatch(b -> b.mid.toString().equals(""))) // HACK + { + throw new RuntimeException("[param-core] Empty labels not allowed in non-unary choices: " + curr.getActions()); + } + + RPCoreSTStateChanApiBuilder rpapi = (RPCoreSTStateChanApiBuilder) api; + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval d = r.intervals.iterator().next(); + if (r.intervals.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: " + a); + } + + String sEpWrite = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN; /*+ "." //+ RPCoreSTApiGenConstants.GO_CONNECTION_MAP + + RPCoreSTApiGenConstants.GO_MPCHAN_FORMATTER_MAP + + "[\"" + r.getName() + "\"]";*/ + + // FIXME: single arg // Currently never true because of RPCoreSTOutputStateBuilder + //boolean isDeleg = + a.payload.elems.stream().anyMatch(pet -> + //pet.isGDelegationType() // FIXME: currently deleg specified by ParamCoreDelegDecl, not GDelegationElem + rpapi//.isDelegType((DataType) pet)); + .isDelegType(pet)); + + // TODO: factor out with receive, etc. + String lte; + String inc; + switch (rpapi.apigen.mode) + { + case Int: + { + lte = " <= " + rpapi.generateIndexExpr(d.end); + inc = "i+1"; + break; + } + case IntPair: + { + lte = ".Lte(" + rpapi.generateIndexExpr(d.end) + ")"; + inc = "i.Inc(" + rpapi.generateIndexExpr(d.end) + ")"; + break; + } + default: throw new RuntimeException("Shouldn't get in here: " + rpapi.apigen.mode); + } + + String res = "for i, j := " + rpapi.generateIndexExpr(d.start) + ", 0;" + + " i" + lte + "; i, j = " + inc + ", j+1 {\n"; + + String errorField = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + + "_" + rpapi.getSuccStateChanName(succ) + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_ERR; + + if (a.mid.isOp()) + { + // Write label + if (!a.mid.toString().equals("")) { // HACK FIXME? + res += "op := \"" + a.mid + "\"\n" // FIXME: API constant? + + "if " + errorField + " = " + sEpWrite /*+ "[i]" + + "." //+ RPCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL + + RPCoreSTApiGenConstants.GO_FORMATTER_ENCODE_STRING + + "(\"" + a.mid + "\"" + ")" */ + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_ISEND + "(\"" + r.getName() + "\", i, &op)" + + "; " + errorField + " != nil {\n" + //+ "log.Fatal(err)\n" // FIXME + //+ "return " + rpapi.makeCreateSuccStateChan(succ) + "\n" // FIXME: disable linearity check for error chan? Or doesn't matter -- only need to disable completion check? + + rpapi.makeReturnSuccStateChan(succ) + "\n" + + "}\n"; + } + } + + // Write message sig or payload + /*if (isDeleg) //... FIXME: delegation: take pointer? send underlying ept? -- don't do (multi)"send"? + { + res += "log.Fatal(\"TODO\")\n"; + } + else*/ + { + /*if (a.mid.isOp() && a.payload.elems.size() < 1) + { + throw new RuntimeException("[rp-core] [param-api] TODO: " + a); + }*/ + if (a.mid.isOp()) + { + /*res += "if err := " + sEpWrite /*+ "[i]" + + "." //+ RPCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL + + RPCoreSTApiGenConstants.GO_FORMATTER_ENCODE_INT + + "(" + "arg0[j])" // FIXME: hardcoded arg0* / + + "." + + (a.mid.isOp() ? RPCoreSTApiGenConstants.GO_MPCHAN_ISEND : RPCoreSTApiGenConstants.GO_MPCHAN_MSEND) + + "(\"" + r.getName() + "\", i, &arg0[j])" + + "; err != nil {\n" + + "log.Fatal(err)\n" + + "}\n";*/ + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[rp-core] [param-api] TODO: " + a); + } + + res += checkError(sEpWrite + + "." + + (a.mid.isOp() ? RPCoreSTApiGenConstants.GO_MPCHAN_ISEND : RPCoreSTApiGenConstants.GO_MPCHAN_MSEND) + + "(\"" + r.getName() + "\", i" + + IntStream.range(0, a.payload.elems.size()).mapToObj(i -> ", &arg" + i + "[j]").collect(Collectors.joining("")) + + ")", errorField); + } + } + else //(a.mid.isMessageSigName) + { + // FIXME: factor out with above + res += checkError( sEpWrite + + "." + + (a.mid.isOp() ? RPCoreSTApiGenConstants.GO_MPCHAN_ISEND : RPCoreSTApiGenConstants.GO_MPCHAN_MSEND) + + "(\"" + r.getName() + "\", i, &arg0[j])", errorField); + } + } + + res += "}\n"; + + return res + buildReturn(api, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSessionApiBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSessionApiBuilder.java new file mode 100644 index 000000000..728798268 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSessionApiBuilder.java @@ -0,0 +1,1186 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ast.Module; +import org.scribble.ast.ProtocolDecl; +import org.scribble.ext.go.core.cli.RPCoreCommandLine; +import org.scribble.ext.go.core.codegen.statetype3.RPCoreSTApiGenerator.Mode; +import org.scribble.ext.go.core.model.endpoint.RPCoreEState; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.type.index.RPBinIndexExpr; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexIntPair; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.ext.go.util.IntPairSmt2Translator; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.ext.go.util.Z3Wrapper; +import org.scribble.model.endpoint.EGraph; +import org.scribble.model.endpoint.EStateKind; +import org.scribble.type.kind.Global; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; +import org.scribble.util.Pair; + +// Build Session API for this.apigen.selfs +// RP Session API = Protocol API + Endpoint Kind APIs +// Cf. STStateChanApiBuilder +public class RPCoreSTSessionApiBuilder +{ + private final RPCoreSTApiGenerator apigen; + + /*... move stateChanNames (and peers?) here + ... cache reachable states, use for state chan pre-creation (to include intermed states -- and case objects?) + ... do "global" linearity counter*/ + + protected final Map> reachable = new HashMap<>(); + protected final Map> stateChanNames; // State2 + //private Map> foreachNames = new HashMap<>(); // State2_ intermediary name (N.B. RPCoreSTStateChanApiBuilder swaps them around for convenience) + + private static final Comparator IVAR_COMP = new Comparator() + { + @Override + public int compare(RPIndexVar i1, RPIndexVar i2) + { + return i1.toString().compareTo(i2.toString()); + } + }; + + private static final Comparator ESTATE_COMP = new Comparator() + { + @Override + public int compare(RPCoreEState o1, RPCoreEState o2) + { + return new Integer(o1.id).compareTo(o2.id); + } + }; + + public RPCoreSTSessionApiBuilder(RPCoreSTApiGenerator apigen) + { + this.apigen = apigen; + + this.stateChanNames = Collections.unmodifiableMap(makeStateChanNames() + .entrySet().stream().collect(Collectors.toMap( + e -> e.getKey(), + e -> Collections.unmodifiableMap(e.getValue()))) + ); + } + + private Map> makeStateChanNames() + { + Map> names = new HashMap<>(); + for (Entry e : (Iterable>) + this.apigen.selfs.stream() + .map(r -> this.apigen.variants.get(r)) + .flatMap(v -> v.entrySet().stream())::iterator) + { + int[] counter = {2}; + RPRoleVariant v = e.getKey(); + EGraph g = e.getValue(); + + Map curr = new HashMap<>(); + //Map inames = new HashMap<>(); + names.put(v, curr); + //this.foreachNames.put(v, inames); + Set rs = RPCoreEState.getReachableStates((RPCoreEState) g.init); // FIXME: cast needed to select correct static + rs.add((RPCoreEState) g.init); // Adding for following loop; removed again later + + this.reachable.put(v, Collections.unmodifiableSet(new HashSet<>(rs))); + + for (RPCoreEState s : new HashSet<>(rs)) + { + if (s.hasNested()) // Nested inits + { + RPCoreEState nested = s.getNested(); + curr.put(nested.id, "Init_" + nested.id); + rs.remove(nested); + } + } + // Handling top-level init/end must come after handling nested + curr.put(g.init.id, "Init"); + rs.remove(g.init); + if (g.term != null && g.term.id != g.init.id) + { + rs.remove(g.term); // Remove top-level term from rs + curr.put(g.term.id, "End"); + } + rs.forEach(s -> + { + String n = s.isTerminal() + ? (s.hasNested() ? "End_" + s.id : "End") // Nested or "regular" term + : "State" + counter[0]++; + /*if (s.hasNested()) + { + inames.put(s.id, n); + n = n + "_"; + }*/ + curr.put(s.id, n); + }); + } + return names; + } + + //@Override + public Map build() // FIXME: factor out + { + String indexType; + switch (this.apigen.mode) + { + case Int: indexType = "int"; break; // Factor into the mode? + case IntPair: indexType = "session2.Pair"; break; + default: throw new RuntimeException("Shouldn't get in here: " + this.apigen.mode); + } + + Module mod = this.apigen.job.getContext().getModule(this.apigen.proto.getPrefix()); + ProtocolDecl gpd = mod.getProtocolDecl(this.apigen.proto.getSimpleName()); + Map res = new HashMap<>(); // filepath -> source + buildProtocolApi(gpd, res, indexType); + buildEndpointKindApi(gpd, res, indexType); + return res; + } + + private void buildProtocolApi(ProtocolDecl gpd, Map res, String indexType) + { + GProtocolName simpname = this.apigen.proto.getSimpleName(); + List rolenames = //gpd.header.roledecls.getRoles(); + this.apigen.selfs; + + // roles + String protoFile = + + "// Package " + this.apigen.getApiRootPackageName() + " is the generated API for the " + this.apigen.proto.getPrefix().getSimpleName().toString() + "." + this.apigen.getApiRootPackageName() + " protocol.\n" + + "// Use functions in this package to create instances of role variants.\n" + + "package " + this.apigen.getApiRootPackageName() + "\n" + + "\n" + + "import \"strconv\"\n" + + "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_UTIL_PACKAGE + "\"\n" + + "\n"; + + if (this.apigen.mode == Mode.IntPair) + { + protoFile += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE + "\"\n"; + } + + protoFile += + // Import Endpoint Kind APIs -- FIXME: CL args + (rolenames.stream().map(rname -> + { + Set variants = this.apigen.variants.get(rname).keySet(); + return + variants.stream().map(v -> + { + String epkindPackName = RPCoreSTApiGenerator.getEndpointKindPackageName(v); + // Cf. getEndpointKindFilePath + boolean isCommonEndpointKind = //this.apigen.families.keySet().stream().allMatch(f -> f.left.contains(v)); // No: doesn't consider dial/accept + //this.apigen.families.keySet().stream().filter(f -> f.left.contains(v)).distinct().count() == 1; // No: too conservative -- should be about required peer endpoint kinds (to dial/accept with) + //this.apigen.peers.get(v).size() == 1; // Cf. + this.apigen.isCommonEndpointKind(v); + + return isCommonEndpointKind + ? "import " + epkindPackName + + " \"" + this.apigen.packpath + "/" + this.apigen.getApiRootPackageName() // "Absolute" -- cf. getProtocol/EndpointKindFilePath, "relative" + + "/" + epkindPackName + "\"\n" + : this.apigen.families.keySet().stream().filter(f -> f.left.contains(v)).map(f -> + { + return "import " + this.apigen.getFamilyPackageName(f) + "_" + epkindPackName + + " \"" + this.apigen.packpath + "/" + this.apigen.getApiRootPackageName() // "Absolute" -- cf. getProtocol/EndpointKindFilePath, "relative" + + "/" + this.apigen.getFamilyPackageName(f) + + "/" + epkindPackName + "\"\n"; + }).collect(Collectors.joining("")); + }).collect(Collectors.joining("")); + }).collect(Collectors.joining(""))); + + protoFile += "\nvar _ = strconv.Itoa\n"; + protoFile += "var _ = util.IsectIntIntervals\n"; + + protoFile += "\n" + // Protocol type + + "// " + simpname + " is an instance of the " + this.apigen.proto.getPrefix().getSimpleName().toString() + "." + this.apigen.getApiRootPackageName() + " protocol.\n" + + "type " + simpname + " struct {\n" + + "}\n" + + // session.Protocol interface + + "\n" + + "func (*" + simpname +") IsProtocol() {\n" + + "}\n" + + // Protocol type constructor + + "\n" + + "// New returns a new instance of the protocol.\n" + + "func New() *" + simpname + " {\n" + + "return &" + simpname + "{ }\n" + + "}\n"; + + for (Role rname : rolenames) + { + for (RPRoleVariant variant : this.apigen.variants.get(rname).keySet()) + { + boolean isCommonEndpointKind = this.apigen.isCommonEndpointKind(variant); + + // HACK: setting family to null for common endpoint kind + Set, Set>> families = isCommonEndpointKind + ? Stream.of((Pair, Set>) null).collect(Collectors.toSet()) // FIXME HACK: when isCommonEndpointKind, just loop once (to make one New) + : this.apigen.families.keySet().stream().filter(f -> f.left.contains(variant)).collect(Collectors.toSet()); + + for (Pair, Set> family : + families) // FIXME: use family to make accept/dial + { + + // Factor out with below + Pair, Set> orig = (this.apigen.subsum.containsKey(family)) ? this.apigen.subsum.get(family) : family; + RPRoleVariant subbdbyus = null; + for (RPRoleVariant subbd : this.apigen.aliases.keySet()) + { + Map, Set>, RPRoleVariant> ais = this.apigen.aliases.get(subbd); + if (ais.containsKey(orig) && ais.get(orig).equals(variant)) + { + subbdbyus = subbd; // We subsumed "subbd", so we need to inherit all their peers + break; + } + } + + /*RPCoreIndexVarCollector coll = new RPCoreIndexVarCollector(this.apigen.job); + try + { + gpd.accept(coll); // FIXME: should be lpd -- not currently used due to using RPCoreType + } + catch (ScribbleException e) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: ", e); + } + List ivars = coll.getIndexVars().stream().sorted().collect(Collectors.toList());*/ + List ivars = getParameters(variant); + String epkindTypeName = RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, variant); + + String fnName = "New_" + (isCommonEndpointKind ? "" : this.apigen.getFamilyPackageName(family) + "_") + epkindTypeName; + + // Endpoint Kind constructor -- makes index var value maps + String tmp = "// " + fnName + " returns a new instance of " + epkindTypeName + " role variant.\n" + + "func (p *" + simpname + ") " + fnName // FIXME: factor out common variants between families + + "(" + ivars.stream().filter(x -> !x.name.equals("self")) // CHECKME: can check for RPIndexSelf instead? + .map(v -> v + " " + indexType + ", ").collect(Collectors.joining("")) + "self " + indexType + ")" + + " *" + + (isCommonEndpointKind ? "" : this.apigen.getFamilyPackageName(family) + "_") + + RPCoreSTApiGenerator.getGeneratedRoleVariantName(variant) // FIXME: factor out (and separate type name from package name) + + "." + epkindTypeName + + " {\n"; + /*+ "params := make(map[string]int)\n" + //+ decls.iterator().next().params + + ivars + .stream().map(x -> "params[\"" + x + "\"] = " + x + "\n").collect(Collectors.joining(""))*/ + + tmp += makeFamilyCheck((family == null) ? this.apigen.families.keySet().iterator().next() : family, ivars); // FIXME: due to above family null hack + tmp += makeSelfCheck1(variant, ivars, subbdbyus); + tmp += makeSelfCheck2(variant, ivars, subbdbyus); + + tmp += "return " + + (isCommonEndpointKind ? "" : this.apigen.getFamilyPackageName(family) + "_") + + RPCoreSTApiGenerator.getEndpointKindPackageName(variant) // FIXME: factor out + + ".New" + "(p" //", params" + + ivars.stream().filter(x -> !x.name.equals("self")) // CHECKME: can check for RPIndexSelf instead? + .map(x -> ", " + x).collect(Collectors.joining("")) + + ", self)\n" + + "}\n"; + + protoFile += "\n" + tmp; + } + } + } + + res.put(getProtocolFilePath() + simpname + ".go", protoFile); + } + + private String makeFamilyCheck(Pair, Set> fff, List ivars) + { + switch (this.apigen.mode) + { + case Int: return makeFamilyCheckIntIntervals(fff, ivars); + case IntPair: return makeFamilyCheckIntPairIntervals(fff, ivars); + default: throw new RuntimeException("Shouldn't get in here: " + this.apigen.mode); + } + } + + private String makeFamilyCheckIntPairIntervals(Pair, Set> fff, List ivars) + { + Smt2Translator smt2t = this.apigen.smt2t; //new IntPairSmt2Translator(null, null); // FIXME: factor out, and null arg hacks + return "util.CheckSat(\"" + RPCoreCommandLine.makeFamilyCheck(smt2t, new HashSet<>(ivars), fff.left, fff.right) + "\")\n"; + } + + private String makeFamilyCheckIntIntervals(Pair, Set> fff, List ivars) + { + if (ivars.isEmpty()) + { + return ""; + } + + String res = ""; + String ivalkind; + switch (this.apigen.mode) + { + case Int: ivalkind = "IntInterval"; break; + case IntPair: ivalkind = "IntPairInterval"; break; // FIXME: now redundant (and etc. below) + default: throw new RuntimeException("Shouldn't get in here: " + this.apigen.mode); + } + + res += "var tmp []util." + ivalkind + "\n"; + res += "var tmp2 []util." + ivalkind + "\n"; + Function makeIvals = vvv -> + { + List ivals = new LinkedList<>(); + for (RPInterval x : vvv.intervals) + { + if (ivars.containsAll(x.getIndexVars())) + { + String start = (this.apigen.mode == Mode.Int) ? x.start.toGoString() : makeGoIndexExpr(x.start); + String end = (this.apigen.mode == Mode.Int) ? x.end.toGoString() : makeGoIndexExpr(x.end); + ivals.add("util." + ivalkind + "{" + start + ", " + end + "}"); + } + } + return ivals.isEmpty() ? null : "tmp = []util." + ivalkind + "{" + ivals.stream().collect(Collectors.joining(", ")) + "}\n"; + }; + Function makeCoIvals = vvv -> + { + List coivals = new LinkedList<>(); + vvv.cointervals.forEach(x -> + { + String start = (this.apigen.mode == Mode.Int) ? x.start.toGoString() : makeGoIndexExpr(x.start); + String end = (this.apigen.mode == Mode.Int) ? x.end.toGoString() : makeGoIndexExpr(x.end); + coivals.add("util." + ivalkind + "{" + start + ", " + end + "}"); + }); + return "tmp2 = []util." + ivalkind + "{" + coivals.stream().collect(Collectors.joining(", ")) + "}\n"; + }; + + for (RPRoleVariant v : fff.left) + { + String tmp = makeIvals.apply(v); + if (tmp != null) + { + res += tmp; + res += makeCoIvals.apply(v); + res += "if util.Isect" + ivalkind + "s(tmp).SubIntIntervals(tmp2)" // FIXME: non int intervals + + ".IsEmpty() {\n"; + res += makeParamsSelfPanic(ivars); + res += "}\n"; + } + } + for (RPRoleVariant v : fff.right) + { + res += makeIvals.apply(v); + res += makeCoIvals.apply(v); + res += "if !util.Isect" + ivalkind + "s(tmp).SubIntIntervals(tmp2)" + + ".IsEmpty() {\n"; + res += makeParamsSelfPanic(ivars); + res += "}\n"; + } + return res; + } + + private String makeSelfCheck1(RPRoleVariant vvv, List ivars, RPRoleVariant subbd) + { + /*if (ivars.isEmpty()) + { + return "if self != " + ((this.apigen.mode == Mode.Int) ? "1" : "session2.XY(1, 1)") + " {\n" + + makeParamsSelfPanic(ivars) + + "}\n"; + }*/ + + String res = "if " + + vvv.intervals.stream().map(x -> + ((this.apigen.mode == Mode.Int) + ? "(self < " + x.start.toGoString() + ") || (self > " + x.end.toGoString() + ")" + : "(self.Lt(" + makeGoIndexExpr(x.start) + ")) || (self.Gt(" + makeGoIndexExpr(x.end) + "))" + ) + ).collect(Collectors.joining(" || ")) + " {\n"; + if (subbd != null) + { + res += makeSelfCheck1(subbd, ivars, null); + } + else + { + res += makeParamsSelfPanic(ivars); + } + res += "}\n"; + return res; + } + + private String makeSelfCheck2(RPRoleVariant vvv, List ivars, RPRoleVariant subbd) + { + /*if (ivars.isEmpty()) + { + return ""; + }*/ + + String res = ""; + if (!vvv.cointervals.isEmpty()) { + res += "if " + + vvv.cointervals.stream().map(x -> + ((this.apigen.mode == Mode.Int) + ? "(self >= " + x.start.toGoString() + ") && (self <= " + x.end.toGoString() + ")" + : "(self.Gte(" + makeGoIndexExpr(x.start) + ")) && (self.Lt(" + makeGoIndexExpr(x.end) + "))" + ) + ).collect(Collectors.joining(" || ")) + " {\n"; + } + if (subbd != null) + { + res += makeSelfCheck2(subbd, ivars, null); + } + else + { + if (!vvv.cointervals.isEmpty()) + { + res += makeParamsSelfPanic(ivars); + } + } + if (!vvv.cointervals.isEmpty()) + { + res += "}\n"; + } + return res; + } + + private String makeParamsSelfPanic(List ivars) + { + return "panic(\"Invalid params/self: \" + " + + ivars.stream().filter(x -> !x.name.equals("self")).map(x -> + ((this.apigen.mode == Mode.Int) + ? "strconv.Itoa(" + x.toGoString() + ")" + : x.toGoString() + ".String()" + ) + " + \", \" + ").collect(Collectors.joining("")) + + ((this.apigen.mode == Mode.Int) ? "strconv.Itoa(self)" : "self.String()") + + ")\n"; + } + + // Factor out with RPCoreSTStateChanApiGenerator#generateIndexExpr + private String makeGoIndexExpr(RPIndexExpr e) + { + if (e instanceof RPIndexIntPair || e instanceof RPIndexVar) + { + return e.toGoString(); + } + else if (e instanceof RPBinIndexExpr) + { + RPBinIndexExpr b = (RPBinIndexExpr) e; + // TODO: factor out + String op; + switch (b.op) + { + case Add: op = "Plus"; break; + case Subt: op = "Sub"; break; + case Mult: + default: throw new RuntimeException("[rp-core] Shouldn't get in here: " + e); + } + return "(" + makeGoIndexExpr(b.left) + "." + op + "(" + makeGoIndexExpr(b.right) + "))"; + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + e); + } + } + + private String makeGoIndexExprInt2(RPIndexExpr e) + { + if (e instanceof RPIndexInt) + { + return e.toGoString(); + } + else if (e instanceof RPIndexVar) + { + return "ini." + e.toGoString(); + } + else if (e instanceof RPBinIndexExpr) + { + RPBinIndexExpr b = (RPBinIndexExpr) e; + // TODO: factor out + String op; + switch (b.op) + { + case Add: op = " + "; break; + case Subt: op = " - "; break; + case Mult: + default: throw new RuntimeException("[rp-core] Shouldn't get in here: " + e); + } + return "(" + makeGoIndexExprInt2(b.left) + op + "(" + makeGoIndexExprInt2(b.right) + "))"; + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + e); + } + } + + private String makeGoIndexIntPairExpr2(RPIndexExpr e) + { + if (e instanceof RPIndexIntPair) + { + return e.toGoString(); + } + else if (e instanceof RPIndexVar) + { + return "ini." + e.toGoString(); + } + else if (e instanceof RPBinIndexExpr) + { + RPBinIndexExpr b = (RPBinIndexExpr) e; + // TODO: factor out + String op; + switch (b.op) + { + case Add: op = "Plus"; break; + case Subt: op = "Sub"; break; + case Mult: + default: throw new RuntimeException("[rp-core] Shouldn't get in here: " + e); + } + return "(" + makeGoIndexIntPairExpr2(b.left) + "." + op + "(" + makeGoIndexIntPairExpr2(b.right) + "))"; + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + e); + } + } + + // TODO: factor out with above + private String makePeerIdCheck1(RPRoleVariant vvv, List ivars, RPRoleVariant subbd) + { + String res = "if " + + vvv.intervals.stream().map(x -> + ((this.apigen.mode == Mode.Int) + ? "(id < " + makeGoIndexExprInt2(x.start) + ") || (id > " + makeGoIndexExprInt2(x.end) + ")" + : "(id.Lt(" + makeGoIndexIntPairExpr2(x.start) + ")) || (id.Gt(" + makeGoIndexIntPairExpr2(x.end) + "))" + ) + ).collect(Collectors.joining(" || ")) + " {\n"; + if (subbd != null) + { + res += makePeerIdCheck1(subbd, ivars, null); + } + else + { + res += makeParamsPeerIdPanic(ivars); + } + res += "}\n"; + return res; + } + + private String makePeerIdCheck2(RPRoleVariant vvv, List ivars, RPRoleVariant subbd) + { + + String res = ""; + if (!vvv.cointervals.isEmpty()) { + res += "if " + + vvv.cointervals.stream().map(x -> + ((this.apigen.mode == Mode.Int) + ? "(id >= " + makeGoIndexExprInt2(x.start) + ") && (id <= " + makeGoIndexExprInt2(x.end) + ")" + : "(id.Gte(" + makeGoIndexIntPairExpr2(x.start) + ")) && (id.Lt(" + makeGoIndexIntPairExpr2(x.end) + "))" + ) + ).collect(Collectors.joining(" || ")) + " {\n"; + } + if (subbd != null) + { + res += makePeerIdCheck2(subbd, ivars, null); + } + else + { + if (!vvv.cointervals.isEmpty()) + { + res += makeParamsPeerIdPanic(ivars); + } + } + if (!vvv.cointervals.isEmpty()) + { + res += "}\n"; + } + return res; + } + + private String makeParamsPeerIdPanic(List ivars) + { + return "panic(\"Invalid params/id: \" + " + + ivars.stream().filter(x -> !x.name.equals("self")).map(x -> + ((this.apigen.mode == Mode.Int) + ? "strconv.Itoa(ini." + x.toGoString() + ")" + : "ini." + x.toGoString() + ".String()" + ) + " + \", \" + ").collect(Collectors.joining("")) + + ((this.apigen.mode == Mode.Int) ? "strconv.Itoa(id)" : "id.String()") + + ")\n"; + } + + // FIXME: should be lpd + private void buildEndpointKindApi(ProtocolDecl gpd, Map res, String indexType) + { + GProtocolName simpname = this.apigen.proto.getSimpleName(); + List roles = //gpd.header.roledecls.getRoles(); + this.apigen.selfs; + + String epkindImports = "\n"; // Package decl done later (per variant) + switch (this.apigen.mode) + { + case Int: epkindImports += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n"; break; + case IntPair: epkindImports += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE + "\"\n"; break; + default: throw new RuntimeException("Shouldn't get in here: " + this.apigen.mode); + } + epkindImports += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_TRANSPORT_PACKAGE + "\"\n"; + epkindImports += "import \"strconv\"\n"; + + epkindImports += "\nvar _ = strconv.Itoa\n"; + + // Endpoint Kind API per role variant + for (Role rname : roles) + { + for (RPRoleVariant variant : this.apigen.variants.get(rname).keySet()) + { + for (Pair, Set> family : + (Iterable, Set>>) + this.apigen.families.keySet().stream().filter(f -> f.left.contains(variant))::iterator) + { + + // Factor out with above + Pair, Set> orig = (this.apigen.subsum.containsKey(family)) ? this.apigen.subsum.get(family) : family; + RPRoleVariant subbdbyus = null; + for (RPRoleVariant subbd : this.apigen.aliases.keySet()) + { + Map, Set>, RPRoleVariant> ais = this.apigen.aliases.get(subbd); + if (ais.containsKey(orig) && ais.get(orig).equals(variant)) + { + subbdbyus = subbd; // We subsumed "subbd", so we need to inherit all their peers + break; + } + } + + //System.out.println("ffff: " + family + "\n" + variant + " ,, " + peers); + + + /*RPCoreIndexVarCollector coll = new RPCoreIndexVarCollector(this.apigen.job); + try + { + gpd.accept(coll); // FIXME: should be lpd -- not currently used due to using RPCoreType + } + catch (ScribbleException e) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: ", e); + } + List ivars = coll.getIndexVars().stream().sorted().collect(Collectors.toList());*/ + + List ivars = getParameters(variant); + + String epkindTypeName = RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, variant); + + String epkindFile = "//" + family.left.toString() + "\n\n"; + + epkindFile += + epkindImports + "\n" + + // Endpoint Kind type + + "type " + epkindTypeName + " struct {\n" + + RPCoreSTApiGenConstants.GO_MPCHAN_PROTO + " " + RPCoreSTApiGenConstants.GO_PROTOCOL_TYPE + "\n"; + + switch (this.apigen.mode) + { + case Int: epkindFile += "Self int\n"; break; + case IntPair: epkindFile += "Self session2.Pair\n"; break; + default: throw new RuntimeException("Shouldn't get in here: " + this.apigen.mode); + } + + epkindFile += + "*" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "\n" // This is for the Endpoint itself + + "lin uint64\n" + + + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + " *" + RPCoreSTApiGenConstants.GO_MPCHAN_TYPE + "\n" + + ivars.stream().map(x -> x + " " + indexType + "\n").collect(Collectors.joining("")); + + if (this.apigen.job.parForeach) + { + epkindFile += "Params map[int]map[string]" + indexType + "\n"; // FIXME: currently used to record foreach params (and provide access to user) + } + else + { + epkindFile += "Params map[string]" + indexType + "\n"; // FIXME: currently used to record foreach params (and provide access to user) + } + + /*+ this.apigen.stateChanNames.get(variant).entrySet().stream().sorted( + new Comparator>() + { + @Override + public int compare(Entry o1, Entry o2) + { + return o1.getKey().compareTo(o2.getKey()); + } + } + )*/ + + epkindFile += + // FIXME TODO: case objects? + this.reachable.get(variant).stream().sorted(ESTATE_COMP) + //.map(s -> this.stateChanNames.get(s.id)) + .flatMap(s -> + { + String n = this.stateChanNames.get(variant).get(s.id); + return s.hasNested() + ? Stream.of(n, s.isTerminal() ? "End" : n + "_") // FIXME: factor out with RPCoreSTStateChanApiBuilder#getStateChanName + : Stream.of(n); + }) + .distinct() + .map(n -> + { + return "_" + n + " *" + n + "\n"; + }).collect(Collectors.joining()); + + if (this.apigen.job.parForeach) + { + epkindFile += "Thread int\n"; // FIXME: deprecate -- recorded in state chan instead + } + + epkindFile += "}\n" + + // Endpoint Kind type constructor -- makes connection maps + + "\n" + + "func New(p " + RPCoreSTApiGenConstants.GO_PROTOCOL_TYPE + ", " //+"params map[string]int," + + ivars.stream().filter(x -> !x.name.equals("self")).map(x -> x + " " + indexType + ", ").collect(Collectors.joining("")) // CHECKME: can check for RPIndexSelf instead? + + "self " + indexType + ") *" + epkindTypeName + " {\n" + /*+ "conns := make(map[string]map[int]transport.Channel)\n" + + this.apigen.variants.entrySet().stream() + .map(e -> "conns[\"" + e.getKey().getLastElement() + "\"] = " + "make(map[int]transport.Channel)\n") + .collect(Collectors.joining(""))*/ + + "ep := &" + epkindTypeName + "{\n" + + "p,\n" + + "self,\n" + + + "&" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "{},\n" // For Endpoint itself + + "1,\n" + + + RPCoreSTApiGenConstants.GO_MPCHAN_CONSTRUCTOR + "(self, "//conns)" //"params + + "[]string{" + roles.stream().map(x -> "\"" + x + "\"").collect(Collectors.joining(", ")) + "}),\n" + + ivars.stream().map(x -> x + ",\n").collect(Collectors.joining("")); + + if (this.apigen.job.parForeach) + { + epkindFile += "make(map[int]map[string]" + indexType + "),\n"; + } + else + { + epkindFile += "make(map[string]" + indexType + "),\n"; // Trailing comma needed + } + + epkindFile += + //+ this.apigen.stateChanNames.get(variant).values().stream().distinct().map(k -> "nil,\n").collect(Collectors.joining()) + // FIXME: factor out with above + this.reachable.get(variant).stream().sorted(ESTATE_COMP) + .flatMap(s -> + { + String n = this.stateChanNames.get(variant).get(s.id); + return s.hasNested() + ? Stream.of(n, s.isTerminal() ? "End" : n + "_") // FIXME: factor out with RPCoreSTStateChanApiBuilder#getStateChanName + : Stream.of(n); + }) + .distinct() + .map(k -> "nil,\n").collect(Collectors.joining()); + + if (this.apigen.job.parForeach) + { + epkindFile += "1,\n"; + } + + epkindFile += "}\n" + + // FIXME: factor out with above + + this.reachable.get(variant).stream().sorted(ESTATE_COMP) + .flatMap(s -> + { + String n = this.stateChanNames.get(variant).get(s.id); + return s.hasNested() + ? Stream.of(n, s.isTerminal() ? "End" : n + "_") // FIXME: factor out with RPCoreSTStateChanApiBuilder#getStateChanName + : Stream.of(n); + }) + .distinct() // CHECKME: for End's? + .map(n -> + { + // FIXME TODO: case objects? + return "ep._" + n + " = " + makeStateChanInstance(this.apigen, n, "ep", "1"); + // cf. state chan builder // CHECKME: reusing pre-created chan structs OK for Err handling? + } + ) + /*.map(s -> + { + String n = this.stateChanNames.get(variant).get(s.id); + String tmp = makeStateChanInstance(this.apigen, n); + if (s.hasNested()) + { + tmp = tmp + (s.isTerminal() + ? makeStateChanInstance(this.apigen, n + "_") + : makeStateChanInstance(this.apigen, "End")); + } + return tmp; + })*/ + .collect(Collectors.joining()); + + if (this.apigen.job.parForeach) + { + epkindFile += "ep.Params[ep.Thread] = make(map[string]" + indexType + ")\n"; + } + + epkindFile += "return ep\n"; + + epkindFile += "}\n"; + + // Dial/Accept methdos -- FIXME: internalise peers + /*+ "\n" + + "func (ini *" + epkindTypeName + ") Accept(rolename string, id int, acc transport.Transport) error {\n" + + "ini." + RPCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + "." + + RPCoreSTApiGenConstants.GO_CONNECTION_MAP + "[rolename][id] = acc.Accept()\n" + + "return nil\n" // FIXME: runtime currently does log.Fatal on error + + "}\n" + + "\n" + + "func (ini *" + epkindTypeName + ") Dial(rolename string, id int, req transport.Transport) error {\n" + + "ini." + RPCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + "." + + RPCoreSTApiGenConstants.GO_CONNECTION_MAP + "[rolename][id] = req.Connect()\n" + + "return nil\n" // FIXME: runtime currently does log.Fatal on error + + "}\n";*/ + + //Map map = this.apigen.variants.get(rname); + + /*for (RPRoleVariant v : (Iterable) + this.apigen.variants.values().stream() + .flatMap(m -> m.keySet().stream())::iterator)*/ + + /*for (RPRoleVariant v : this.apigen.peers.get(variant)) + { + if (//!v.equals(variant) && // No: e.g., pipe/ring middlemen + family.left.contains(v)) // FIXME: endpoint families -- and id value checks + // FIXME: should record peers according to families and lookup directly -- wouldn't need to re-check family inclusion here + {*/ + + Set peers = this.apigen.peers.get(variant).get(orig); + + epkindFile = makeDialsAccepts(indexType, variant, family, orig, ivars, epkindTypeName, epkindFile, peers); + + if (subbdbyus != null) + { + Set peers2 = this.apigen.peers.get(subbdbyus).get(orig); + peers2.removeAll(peers); + epkindFile = makeDialsAccepts(indexType, variant, family, orig, ivars, epkindTypeName, epkindFile, peers2); + } + + /*if (subbdbyus != null) + { + // FIXME: factor out with above + RPRoleVariant pp = subbdbyus; + // Accept/Dial methods + String r = pp.getLastElement(); + String vname = RPCoreSTApiGenerator.getGeneratedRoleVariantName(pp); + epkindFile += "\n" + + "func (ini *" + epkindTypeName + ") " + vname + "_Accept(id " + indexType + + ", ss " + RPCoreSTApiGenConstants.GO_SCRIB_LISTENER_TYPE + + ", sfmt " + RPCoreSTApiGenConstants.GO_FORMATTER_TYPE + ") error {\n" + + "defer ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_WG + ".Done()\n" + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_WG + ".Add(1)\n" + + "c, err := ss.Accept()\n" + + "if err != nil {\n" + + "return err\n" + + "}\n" + + "\n" + + "sfmt.Wrap(c)\n" + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_MAP + "[\"" + r + "\"][id] = c\n" // CHECKME: connection map keys (cf. variant?) + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_FORMATTER_MAP + "[\"" + r + "\"][id] = sfmt\n" + + "return err\n" // FIXME: runtime currently does log.Fatal on error + + "}\n" + + "\n" + + "func (ini *" + epkindTypeName + ") " + vname + "_Dial(id " + indexType + + ", host string, port int" + + ", dialler func (string, int) (" + RPCoreSTApiGenConstants.GO_SCRIB_BINARY_CHAN_TYPE + ", error)" + + ", sfmt " + RPCoreSTApiGenConstants.GO_FORMATTER_TYPE + ") error {\n" + + "defer ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_WG + ".Done()\n" + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_WG + ".Add(1)\n" + + "c, err := dialler(host, port)\n" + + "if err != nil {\n" + + "return err\n" + + "}\n" + + "\n" + + "sfmt.Wrap(c)\n" + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_MAP + "[\"" + r + "\"][id] = c\n" // CHECKME: connection map keys (cf. variant?) + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_FORMATTER_MAP + "[\"" + r + "\"][id] = sfmt\n" // FIXME: factor out with Accept + + "return err\n" // FIXME: runtime currently does log.Fatal on error + + "}\n"; + }*/ + + + + // Top-level Run method // FIXME: add session completion check + /*EGraph g = this.apigen.variants.get(variant.getName()).get(variant); + //String endName = g.init.isTerminal() ? "Init" : "End"; // FIXME: factor out -- cf. RPCoreSTStateChanApiBuilder#makeSTStateName( + EState term = MState.getTerminal(g.init); + String endName = (g.init.id == term.id ? "Init" : "End") + ((term != null && ((RPCoreEState) term).hasNested()) ? "_" + term.id : "");*/ + String endName = "End"; + String init = //"Init_" + this.apigen.variants.get(variant.getName()).get(variant).init; + "Init"; + epkindFile += "\n" + + "func (ini *" + epkindTypeName + ") Run(f func(*" + init + ") " + endName + ") " + endName + " {\n" // f specifies non-pointer End + /*+ "defer ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + ".Close()\n" + + "ini.Use()\n" // FIXME: int-counter linearity + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + ".CheckConnection()\n"*/ + + "defer ini.Close()\n" + //+ "ini.Init()\n" + + // FIXME: factor out with RPCoreSTStateChanApiBuilder#buildActionReturn (i.e., returning initial state) + // (FIXME: factor out with RPCoreSTSessionApiBuilder#getSuccStateChan and RPCoreSTSelectStateBuilder#getPreamble) + /*+ ((this.apigen.job.selectApi && this.apigen.variants.get(rname).get(variant).init.getStateKind() == EStateKind.POLY_INPUT) + ? "return f(newBranch" + init + "(ini))\n" + : //"end := f(&" + init + "{ nil, new(" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "), ini })\n") + // cf. state chan builder // FIXME: chan struct reuse + //"ini._" + init + ".id = 1\n" + + "return f(ini._" + init + ")\n")*/ + + "end := f(ini.Init())\n" + + "if end." + RPCoreSTApiGenConstants.GO_MPCHAN_ERR + " != nil {\n" + + "panic(end." + RPCoreSTApiGenConstants.GO_MPCHAN_ERR + ")\n" + + "}\n" + + "return end\n" + + + "}"; + + epkindFile += "\n\n" + + "func (ini *" + epkindTypeName + ") Init() *Init {\n" + + "ini.Use()\n" // FIXME: int-counter linearity + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + ".CheckConnection()\n" + + // TODO: Factor out with RPCoreSTStateChanApiBuilder#makeReturnSuccStateChan + + "return " + + ((this.apigen.job.selectApi && this.apigen.variants.get(rname).get(variant).init.getStateKind() == EStateKind.POLY_INPUT) + ? "newBranch" + init + "(ini)" + : "ini._" + init) + "\n" + + + "}"; + + epkindFile += "\n\n" + + "func (ini *" + epkindTypeName + ") Close() {\n" + + "defer ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + ".Close()\n" + + "}"; + + res.put(getEndpointKindFilePath(family, variant) + + "/" + RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, variant) + ".go", + "// Generated API for the " + variant.getName() + humanReadableName(variant) + " role variant.\n" + + "package " + RPCoreSTApiGenerator.getEndpointKindPackageName(variant) + "\n" + epkindFile); + } + } + } + } + + /*public static String makeStateChanInstance(RPCoreSTApiGenerator apigen, EState s) + { + return makeStateChanInstance(apigen, this.stateChanNames.get(variant).get(s.id)); + }*/ + + public static String makeStateChanInstance(RPCoreSTApiGenerator apigen, String n, String ep, String id) + { + return ((n.equals("End")) // Terminal foreach will be suffixed (and need linear check) // FIXME: factor out properly + ? "&End{ nil, 0, " // Now same as below? + : "&" + n + "{ nil, " + + (apigen.job.parForeach + ? " new(" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ")," + : (n.equals("Init") ? " 1," : " 0,")) + ) + + + ep + (apigen.job.parForeach ? ", " + id : "") + " }\n"; + } + + private String makeDialsAccepts(String indexType, RPRoleVariant variant, + Pair, Set> family, Pair, Set> orig, + List ivars, String epkindTypeName, String epkindFile, Set peers) + { + for (RPRoleVariant v : peers) + { + RPRoleVariant pp = v; + + // TODO: factor out with above + Pair, Set> peerorig = (this.apigen.subsum.containsKey(family)) ? this.apigen.subsum.get(family) : family; + RPRoleVariant subbdbypeer = null; + for (RPRoleVariant subbd : this.apigen.aliases.keySet()) + { + Map, Set>, RPRoleVariant> ais = this.apigen.aliases.get(subbd); + if (ais.containsKey(peerorig) && ais.get(peerorig).equals(variant)) + { + subbdbypeer = subbd; // We can connect to peer or who they subbd + break; + } + } + + if (this.apigen.aliases.containsKey(v)) + { + Map, Set>, RPRoleVariant> ali = this.apigen.aliases.get(v); + if (ali.containsKey(orig)) + { + pp = ali.get(orig); // Replace subsumed-peer by subsuming-peer + if (peers.contains(pp)) // ...but skip if we're already peers with subsuming-peer + { + continue; + } + } + } + + // Accept/Dial methods + String r = pp.getLastElement(); + String vname = RPCoreSTApiGenerator.getGeneratedRoleVariantName(pp); + epkindFile += "\n" + + "func (ini *" + epkindTypeName + ") " + vname + "_Accept(id " + indexType + + ", ss " + RPCoreSTApiGenConstants.GO_SCRIB_LISTENER_TYPE + + ", sfmt " + RPCoreSTApiGenConstants.GO_FORMATTER_TYPE + ") error {\n" + + + makePeerIdCheck1(v, ivars, subbdbypeer) + + makePeerIdCheck2(v, ivars, subbdbypeer) + + + "defer ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_WG + ".Done()\n" + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_WG + ".Add(1)\n" + + "c, err := ss.Accept()\n" + + "if err != nil {\n" + + "return err\n" + + "}\n" + + "\n" + + "sfmt.Wrap(c)\n" + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_MAP + "[\"" + r + "\"][id] = c\n" // CHECKME: connection map keys (cf. variant?) + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_FORMATTER_MAP + "[\"" + r + "\"][id] = sfmt\n" + + "return err\n" // FIXME: runtime currently does log.Fatal on error + + "}\n" + + "\n" + + "func (ini *" + epkindTypeName + ") " + vname + "_Dial(id " + indexType + + ", host string, port int" + + ", dialler func (string, int) (" + RPCoreSTApiGenConstants.GO_SCRIB_BINARY_CHAN_TYPE + ", error)" + + ", sfmt " + RPCoreSTApiGenConstants.GO_FORMATTER_TYPE + ") error {\n" + + + makePeerIdCheck1(v, ivars, subbdbypeer) + + makePeerIdCheck2(v, ivars, subbdbypeer) + + + "defer ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_WG + ".Done()\n" + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_WG + ".Add(1)\n" + + "c, err := dialler(host, port)\n" + + "if err != nil {\n" + + "return err\n" + + "}\n" + + "\n" + + "sfmt.Wrap(c)\n" + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_CONN_MAP + "[\"" + r + "\"][id] = c\n" // CHECKME: connection map keys (cf. variant?) + + "ini." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + "." + + RPCoreSTApiGenConstants.GO_MPCHAN_FORMATTER_MAP + "[\"" + r + "\"][id] = sfmt\n" // FIXME: factor out with Accept + + "return err\n" // FIXME: runtime currently does log.Fatal on error + + "}\n"; + //} + } + return epkindFile; + } + + private String humanReadableName(RPRoleVariant variant) { + StringBuilder sb = new StringBuilder(); + sb.append("["); // array index notation. + for (RPInterval iv : variant.intervals) { + sb.append("{"); + if (iv.isSingleton()) { + sb.append(iv.start.toString()); + } else { + sb.append(iv.start.toString()); + sb.append(",..,"); + sb.append(iv.end.toString()); + } + sb.append("}"); + sb.append("∩"); + } + sb.deleteCharAt(sb.length()-1); + if (variant.cointervals.size() > 0) { + sb.append(" - "); + for (RPInterval iv : variant.cointervals) { + sb.append("{"); + if (iv.isSingleton()) { + sb.append(iv.start.toString()); + } else { + sb.append(iv.start.toString()); + sb.append(",..,"); + sb.append(iv.end.toString()); + } + sb.append("}"); + sb.append("∪"); + } + sb.deleteCharAt(sb.length()-1); + } + sb.append("]"); // array index notation. + return sb.toString(); + } + + private List getParameters(RPRoleVariant variant) + { + List ivars = this.apigen.projections.get(variant.getName()).get(variant) + .getIndexVars().stream().collect(Collectors.toList()); // N.B., params only from action subjects (not self) + ivars.addAll(variant.getIndexVars().stream().filter(x -> !ivars.contains(x)) + .collect(Collectors.toList())); // Do variant params subsume projection params? -- nope: often projections [self] and variant [K] + return ivars.stream().sorted(IVAR_COMP).collect(Collectors.toList()); + } + + // Returns path to use as offset to -d + // -- cf. packpath, "absolute" Go import path (github.com/...) -- would coincide if protocol full name (i.e., module) used "github.com/..." + // FIXME: factor up to super -- cf. STStateChanApiBuilder#getStateChannelFilePath + public String getProtocolFilePath() + { + String basedir = this.apigen.proto.toString().replaceAll("\\.", "/") + "/"; // Full name + return basedir; + } + + // Returns path to use as offset to -d + // -- cf. packpath, "absolute" Go import path (github.com/...) -- would coincide if protocol full name (i.e., module) used "github.com/..." + // FIXME: factor up to super -- cf. STStateChanApiBuilder#getStateChannelFilePath + public String getEndpointKindFilePath(Pair, Set> family, RPRoleVariant variant) + { + boolean isCommonEndpointKind = //this.apigen.families.keySet().stream().allMatch(f -> f.left.contains(variant)); // No: doesn't consider dial/accept + //this.apigen.families.keySet().stream().filter(f -> f.left.contains(variant)).distinct().count() == 1; + //this.apigen.peers.get(variant).size() == 1; + this.apigen.isCommonEndpointKind(variant); + String basedir = this.apigen.proto.toString().replaceAll("\\.", "/") + "/"; // Full name + return basedir + //+ "/" + this.apigen.getFamilyPackageName(family) + + (isCommonEndpointKind ? "" : "/" + this.apigen.getFamilyPackageName(family)) + + "/" + RPCoreSTApiGenerator.getEndpointKindPackageName(variant); + + /*// "Syntactically" determining common endpoint kinds difficult because concrete peers depends on param (and foreachvar) values, e.g., M in PGet w.r.t. #F + // Also, family factoring is more about dial/accept + isCommonEndpointKind = true; + Set peers = null; + X: for (Pair, Set> fam : this.apigen.families.keySet()) + { + if (fam.left.contains(variant)) + { + EGraph g = this.apigen.variants.get(rname).get(variant); + Set as = RPCoreEState.getReachableActions((RPCoreEModelFactory) this.apigen.job.ef, (RPCoreEState) g.init); + Set tmp = as.stream().map(a -> a.getPeer()).collect(Collectors.toSet()); + if (peers == null) + { + peers = tmp; + } + else if (!peers.equals(tmp)) + { + isCommonEndpointKind = false; + break X; + } + } + } + //*/ + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSplitActionBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSplitActionBuilder.java new file mode 100644 index 000000000..2d7f86dd7 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTSplitActionBuilder.java @@ -0,0 +1,202 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.scribble.codegen.statetype.STSendActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; +import org.scribble.type.name.PayloadElemType; + +public class RPCoreSTSplitActionBuilder extends STSendActionBuilder +{ + + @Override + public String getActionName(STStateChanApiBuilder api, EAction a) + { + return RPCoreSTApiGenConstants.GO_CROSS_SPLIT_FUN_PREFIX + "_" + + RPCoreSTStateChanApiBuilder.getGeneratedIndexedRoleName(((RPCoreEAction) a).getPeer()) + + "_" + a.mid; + } + + @Override + public String buildArgs(STStateChanApiBuilder apigen, EAction a) + { + RPCoreSTStateChanApiBuilder api = (RPCoreSTStateChanApiBuilder) apigen; + //DataType[] pet = new DataType[1]; + PayloadElemType[] pet = new PayloadElemType[1]; + return IntStream.range(0, a.payload.elems.size()) + .mapToObj(i -> RPCoreSTApiGenConstants.GO_CROSS_SEND_METHOD_ARG + + i + " " + + // HACK + + ((api.isDelegType(pet[0] = a.payload.elems.get(i))) ? "*" : "") + + api.getPayloadElemTypeName(pet[0]) //a.payload.elems.get(i) + + + ", splitFn" + i + " func(" + RPCoreSTApiGenConstants.GO_CROSS_SEND_METHOD_ARG + i + " " + + // HACK + + (api.isDelegType(pet[0]) ? "*" : "") + + api.getPayloadElemTypeName(pet[0]) + + + ", i" + i + " int) " + + + (api.isDelegType(pet[0]) ? "*" : "") + + api.getPayloadElemTypeName(pet[0]) + + ).collect(Collectors.joining(", ")); + } + + @Override + public String buildBody(STStateChanApiBuilder api, EState curr, EAction a, EState succ) + { + if(a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] TODO: " + a); + } + + List as = curr.getActions(); + if (as.size() > 1 && as.stream().anyMatch(b -> b.mid.toString().equals(""))) // HACK + { + throw new //ParamCoreException + RuntimeException("[param-core] Empty labels not allowed in non-unary choices: " + curr.getActions()); + } + + String sEpWrite = + //s.ep.Write + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_SESSCHAN + //+ "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_WRITEALL; + + ".Conn"; + String sEpProto = + //"s.ep.Proto" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + RPCoreSTApiGenConstants.GO_MPCHAN_PROTO; + /*String sEpErr = + //"s.ep.Err" + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ERR;*/ + + RPIndexedRole r = (RPIndexedRole) a.peer; + RPInterval g = r.intervals.iterator().next(); + Function foo = e -> + { + if (e instanceof RPIndexInt) + { + return e.toString(); + } + else if (e instanceof RPIndexVar) + { + return RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Params[\"" + e + "\"]"; + } + else + { + throw new RuntimeException("[param-core] TODO: " + e); + } + }; + + /*String res = + (((GoJob) api.job).noCopy + ? + "labels := make([]interface{}, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" + + "tmp := \"" + a.mid + "\"\n" + + "\tlabels[i-" + foo.apply(g.start) + "] = &tmp\n" + + "}\n" + : + "labels := make([][]byte, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end) + "; i++ {\n" + + "\tlabels[i-" + foo.apply(g.start) + "] = []byte(\"" + a.mid + "\")\n" + + "}\n") + + + sEpWrite + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + "." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + + "labels)\n"; + + if (!a.payload.elems.isEmpty()) + { + if (a.payload.elems.size() > 1) + { + throw new RuntimeException("[param-core] [TODO] payload size > 1: " + a); + } + res += + (((GoJob) api.job).noCopy + ? + "b := make([]interface{}, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= " + foo.apply(g.end)+"; i++ {\n" + + "tmp := splitFn0(arg0, i)\n" + + "\tb[i-"+foo.apply(g.start)+"] = &tmp\n" + + "}\n" + : + "b := make([][]byte, " + foo.apply(g.end) + "-" + foo.apply(g.start) + "+1)\n" + + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + "\tvar buf bytes.Buffer\n" + + "\tif err := gob.NewEncoder(&buf).Encode(splitFn0(arg0, i)); err != nil {\n\t\t" // only arg0 + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Errors <- session.SerialiseFailed(err, \"" + getActionName(api, a) +"\", " + + ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + ParamCoreSTApiGenConstants.GO_ENDPOINT_ENDPOINT + + ".Self.Name())\n" + + "\t}\n" + + "\tb[i-"+foo.apply(g.start)+"] = buf.Bytes()\n" + + "}\n") + + + sEpWrite + (((GoJob) api.job).noCopy ? "Raw" : "") + + "(" + sEpProto + + "." + r.getName() + ", " + + foo.apply(g.start) + ", " + foo.apply(g.end) + ", " + //+ "\"" + a.mid + "\"" + + "b" + + ")\n"; + }*/ + + String res = + //st1.Use() + "for i := " + foo.apply(g.start) + "; i <= "+foo.apply(g.end)+"; i++ {\n" + + //+ ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + (a.mid.toString().equals("") ? "" : // HACK + "if err := " + sEpWrite + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_WRITEALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + "\"" + a.mid + "\"" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n") + + + ((((RPCoreSTStateChanApiBuilder) api).isDelegType((DataType) a.payload.elems.get(0))) ? "arg0.Res.Use()\n" : "") + + //+ ParamCoreSTApiGenConstants.GO_IO_FUN_RECEIVER + "." + ParamCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "if err := " + sEpWrite + + "[" + sEpProto + "." + r.getName() + ".Name()][i]" + + "." + RPCoreSTApiGenConstants.GO_MPCHAN_WRITEALL + + "(" //+ sEpProto + "." + r.getName() + ", " + + + "splitFn0(arg0, i)" + "); err != nil {\n" + + "log.Fatal(err)\n" + + "}\n" + + "}\n"; + + /*for i, v := range pl { + st1.ept.Conn[Worker][i].Send(a.mid) + st1.ept.Conn[Worker][i].Send(v) + }*/ + + return + res + + buildReturn(api, curr, succ); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTStateChanApiBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTStateChanApiBuilder.java new file mode 100644 index 000000000..9bb1f1fe2 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/codegen/statetype3/RPCoreSTStateChanApiBuilder.java @@ -0,0 +1,1095 @@ +package org.scribble.ext.go.core.codegen.statetype3; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.scribble.ast.DataTypeDecl; +import org.scribble.ast.MessageSigNameDecl; +import org.scribble.ast.Module; +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.codegen.statetype.STActionBuilder; +import org.scribble.codegen.statetype.STStateChanApiBuilder; +import org.scribble.ext.go.core.ast.RPCoreAstFactory; +import org.scribble.ext.go.core.ast.RPCoreSyntaxException; +import org.scribble.ext.go.core.ast.global.RPCoreGProtocolDeclTranslator; +import org.scribble.ext.go.core.ast.global.RPCoreGType; +import org.scribble.ext.go.core.codegen.statetype3.RPCoreSTApiGenerator.Mode; +import org.scribble.ext.go.core.model.endpoint.RPCoreEState; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossSend; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.ext.go.core.type.name.RPCoreGDelegationType; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPBinIndexExpr; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexInt; +import org.scribble.ext.go.type.index.RPIndexIntPair; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.model.MState; +import org.scribble.model.endpoint.EGraph; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.EStateKind; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.name.DataType; +import org.scribble.type.name.GDelegationType; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.MessageSigName; +import org.scribble.type.name.PayloadElemType; +import org.scribble.util.Pair; + +// Duplicated from org.scribble.ext.go.codegen.statetype.go.GoSTStateChanAPIBuilder +public class RPCoreSTStateChanApiBuilder extends STStateChanApiBuilder +{ + protected final RPCoreSTApiGenerator apigen; + public final Pair, Set> family; + public final RPRoleVariant variant; // variant.getName().equals(this.role) + + //private int counter = 2; // 1 named as Init + private final Set dtds; // FIXME: use "main.getDataTypeDecl((DataType) pt);" instead -- cf. OutputSocketGenerator#addSendOpParams + private final Set msnds; + + //private Map imedNames = new HashMap<>(); // "Original" state names -- FIXME: deprecate // Cf. STStateChanApiBuilder.names + + private final Set fvars = new HashSet<>(); // HACK FIXME: should make explicit RPIndexExprNode ast and name disamb endpoint vs. foreach vars + private final List todo = new LinkedList<>(); // HACK FIXME: to preserve "order" of state building -- cf. fvars hack for var scope + + // N.B. the base EGraph class will probably be replaced by a more specific (and more helpful) rp-core class later + // Pre: variant.getName().equals(this.role) + public RPCoreSTStateChanApiBuilder(RPCoreSTApiGenerator apigen, + Pair, Set> family, RPRoleVariant variant, EGraph graph, Map names) + { + this(apigen, family, variant, graph, //2, + names, //Collections.emptyMap(), + Collections.emptySet()); + } + + private RPCoreSTStateChanApiBuilder(RPCoreSTApiGenerator apigen, + Pair, Set> family, RPRoleVariant variant, EGraph graph, + //int counter, + Map names, + //Map imedNames, + Set fvars) + // HACK FIXME -- make a "nested builder" -- problem is final this.graph + // FIXME: probably easier to to make a "nested" constructor + { + super(apigen.job, apigen.proto, //apigen.self, + variant.getName(), + graph, + new RPCoreSTOutputStateBuilder(new RPCoreSTSplitActionBuilder(), new RPCoreSTSendActionBuilder()), + new RPCoreSTReceiveStateBuilder(new RPCoreSTReduceActionBuilder(), new RPCoreSTReceiveActionBuilder()), + + // Select-based branch, or type switch branch by default + (apigen.job.selectApi) + ? new RPCoreSTSelectStateBuilder(new RPCoreSTSelectActionBuilder()) + : new RPCoreSTBranchStateBuilder(new RPCoreSTBranchActionBuilder()), + (apigen.job.selectApi) + ? null + : new RPCoreSTCaseBuilder(new RPCoreSTCaseActionBuilder()), + + new RPCoreSTEndStateBuilder()); + + this.apigen = apigen; + this.family = family; + this.variant = variant; + + Module mod = apigen.job.getContext().getModule(this.apigen.proto.getPrefix()); + this.dtds = mod.getNonProtocolDecls().stream() + .filter(d -> (d instanceof DataTypeDecl)).map(d -> ((DataTypeDecl) d)).collect(Collectors.toSet()); + this.msnds = mod.getNonProtocolDecls().stream() + .filter(d -> (d instanceof MessageSigNameDecl)).map(d -> ((MessageSigNameDecl) d)).collect(Collectors.toSet()); + + //this.counter = counter; + this.names.putAll(names); + //this.imedNames.putAll(imedNames); + this.fvars.addAll(fvars); + } + + @Override + public Map build() // filepath -> source + { + Map res = new HashMap<>(); + Set states = new LinkedHashSet<>(); + states.add(this.graph.init); + states.addAll(MState.getReachableStates(this.graph.init)); + boolean hasTerm = false; + for (EState s : states.stream().sorted(new Comparator() + { + @Override + public int compare(EState o1, EState o2) + { + return o1.id - o2.id; + } + }).collect(Collectors.toList())) + { + switch (RPCoreSTStateChanApiBuilder.getStateKind(s)) + { + case CROSS_SEND: res.put(getStateChannelFilePath(getStateChanName(s)), this.ob.build(this, s)); break; + case CROSS_RECEIVE: + { + if (s.getActions().size() > 1) + { + if (((GoJob) this.job).selectApi) // Select-based branch + { + res.put(getStateChannelFilePath(getStateChanName(s)), this.bb.build(this, s)); + } + else // Type switch -based branch + { + res.put(getStateChannelFilePath(getStateChanName(s)), this.bb.build(this, s)); + res.put(getStateChannelFilePath(this.cb.getCaseStateChanName(this, s)), this.cb.build(this, s)); + } + } + else + { + res.put(getStateChannelFilePath(getStateChanName(s)), this.rb.build(this, s)); + } + break; + } + /*case DOT_SEND: // FIXME: CFSMs should have only !^1, ! and ? + { + throw new RuntimeException("[rp-core] TODO: " + s); + } + case DOT_RECEIVE: + { + throw new RuntimeException("[rp-core] TODO: " + s); + } + case MULTICHOICES_RECEIVE: + { + throw new RuntimeException("[rp-core] TODO: " + s); + }*/ + case TERMINAL: + String name = getStateChanName(s); // HACK FIXME: to generate names even if state not generated here + if (s.id != this.graph.init.id) // "End" not built for for single (nested) state FSMs (will be "Init") + { + if (!((RPCoreEState) s).hasNested()) + { + res.put(getStateChannelFilePath(name), this.eb.build(this, s)); + hasTerm = true; + } + } + break; + default: throw new RuntimeException("[rp-core] Shouldn't get in here: " + s); + } + RPCoreEState s1 = (RPCoreEState) s; + if (s1.hasNested()) + { + Map tmp = buildForeachIntermediaryState(s1); + res.putAll(tmp); + if (s.isTerminal()) + { + hasTerm = true; + } + } + } + if (!hasTerm) //&& res.keySet().stream().noneMatch(k -> k.endsWith("End.go"))) // FIXME -- Need to distinguish "End" if nested -- only use "End" for non-nested? + { + // Always make an "End" (including non-terminating FSMs) -- doesn't matter it's not the actual end state + //RPCoreEState end = ((RPCoreEModelFactory) this.job.ef).newEState(Collections.emptySet()); + + // FIXME: factor out with getStateChanPremable + GProtocolName simpname = this.apigen.proto.getSimpleName(); + String epkindTypeName = RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, this.variant); + String end = "package " + RPCoreSTApiGenerator.getEndpointKindPackageName(this.variant) + "\n" + + "\n" + + "type End struct {\n" + + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " error\n" + //+ RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE +"\n" + + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epkindTypeName + "\n" + + + (this.apigen.job.parForeach ? "Thread int\n" : "") + + + "}\n"; + res.put(getStateChannelFilePath("End"), end); + } + + // FIXME HACK + for (EGraph g : this.todo) + { + RPCoreSTStateChanApiBuilder nested = new RPCoreSTStateChanApiBuilder( + this.apigen, this.family, this.variant, g, + //this.counter, + this.names, //this.imedNames, + this.fvars); + res.putAll(nested.build()); + } + + return res; + } + + // Returns path to use as offset to -d + // -- cf. packpath, "absolute" Go import path (github.com/...) -- would coincide if protocol full name (i.e., module) used "github.com/..." + @Override + public String getStateChannelFilePath(String filename) + { + if (filename.startsWith("_")) // Cannot use "_" prefix, ignored by Go + { + filename = "$" + filename.substring(1); + } + boolean isCommonEndpointKind = //this.apigen.families.keySet().stream().allMatch(f -> f.left.contains(this.variant)); // No: doesn't consider dial/accept + //this.apigen.families.keySet().stream().filter(f -> f.left.contains(this.variant)).distinct().count() == 1; // No: too conservative -- should be about required peer endpoint kinds (to dial/accept with) + //this.apigen.peers.get(this.variant).size() == 1; + this.apigen.isCommonEndpointKind(variant); + return //getStateChannelPackagePathPrefix() + // Duplicated from RPCoreSTSessionApiBuilder#getEndpointKindFilePath + this.gpn.toString().replaceAll("\\.", "/") + //+ "/" + this.apigen.getFamilyPackageName(family) + + (isCommonEndpointKind ? "" : "/" + this.apigen.getFamilyPackageName(this.family)) + + "/" + RPCoreSTApiGenerator.getEndpointKindPackageName(this.variant) // State chans located with Endpoint Kind API + + "/" + filename + ".go"; + } + + // Pre: s.hasNested() -- i.e., s is the "outer" state + // TODO: factor out with getStateChanPremable + protected Map buildForeachIntermediaryState(RPCoreEState s) + { + GProtocolName simpname = this.apigen.proto.getSimpleName(); + String scTypeName = this.names.get(s.id); //this.getStateChanName(s); //this.getIntermediaryStateChanName(s); + String epkindTypeName = RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, this.variant); + + Map res = new HashMap<>(); + + String feach = + "package " + RPCoreSTApiGenerator.getEndpointKindPackageName(this.variant) + "\n" + + "\n"; + + if (this.apigen.mode == Mode.IntPair) + { + feach += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE + "\"\n"; + } + else if (this.apigen.job.parForeach) + { + feach += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n"; + } + + // State channel type + feach += "\n" + + "type " + scTypeName + " struct {\n" + + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " error\n"; + + if (this.apigen.job.parForeach) + { + feach += RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "\n"; + } + else + { + feach += "id uint64\n"; + } + + feach += RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epkindTypeName + "\n"; + + if (this.apigen.job.parForeach) + { + feach += "Thread int\n"; + } + + feach += "}\n"; + + // Foreach method -- cf. RPCoreSTSessionApiBuilder, top-level Run + String sEp = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + RPCoreEState init = s.getNested(); + RPCoreEState term = (RPCoreEState) MState.getTerminal(init); + String initName = this.names.get(init.id); //"Init_" + init.id; + String termName = (term == null) ? "End" : this.names.get(term.id); + String succName = s.isTerminal() ? "End" : getStateChanName(s); // FIXME: factor out + //getIntermediaryStateChanName(s); // Functionality subsumed by getStateChanName + RPForeachVar p = s.getParam(); + + this.fvars.add(p); // HACK FIXME: state visiting order not guaranteed (w.r.t. lexical var scope) + + // TODO: factor out with send, receive, etc. + String lte; + String inc; + switch (this.apigen.mode) + { + case Int: + { + lte = " <= " + generateIndexExpr(s.getInterval().end); + inc = p + "+1"; + break; + } + case IntPair: + { + lte = ".Lte(" + generateIndexExpr(s.getInterval().end) + ")"; + inc = p + ".Inc(" + generateIndexExpr(s.getInterval().end) + ")"; + break; + } + default: throw new RuntimeException("Shouldn't get in here: " + this.apigen.mode); + } + + String initState = sEp + "._" + initName; + feach += "\n" + + "func (" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + " *" + scTypeName + + ") Foreach(f func(*" + initName + ") " + termName + ") *" + succName + " {\n"; + + // Duplicated from buildAction + feach += + "if " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " != nil {\n" + + "panic(" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + ")\n" + + "}\n"; + + if (this.apigen.job.parForeach) + { + feach += RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + "." + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n"; + } + else + { + feach += "if " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + "id != " // Not using atomic.LoadUint64 on id for now + //+ "atomic.LoadUint64(&" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + "lin)" + + sEp + "." + "lin" + + " {\n" + + "panic(\"Linear resource already used\")\n" // + reflect.TypeOf(" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "))\n" + + "}\n"; + } + + feach += + "for " + p + " := " + generateIndexExpr(s.getInterval().start) + "; " // FIXME: general interval expressions + + p + lte + "; " + p + " = " + inc + "{\n"; + //+ sEp + "." + s.getParam() + "=" + s.getParam() + "\n" // FIXME: nested Endpoint type/struct? + + if (this.apigen.job.parForeach) + { + feach += sEp + ".Params[" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + ".Thread][\"" + p + "\"] = " + p + " \n"; + } + else + { + feach += sEp + ".Params[\"" + p + "\"] = " + p + "\n"; // FIXME: nested Endpoint type/struct? + } + + if (this.apigen.job.parForeach) + { + feach += "nested := " + RPCoreSTSessionApiBuilder.makeStateChanInstance(apigen, initName, sEp, RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + ".Thread"); + //feach += "nested.id = " + sEp + ".lin\n"; + feach += "f(nested)\n"; + } + else + { + feach += + // Duplicated from RPCoreSTSessionApiBuilder // FIXME: factor out with makeReturnSuccStateChan + /*+ ((this.apigen.job.selectApi && init.getStateKind() == EStateKind.POLY_INPUT) + ? "f(newBranch" + initName + "(ini))\n" + : "f(&" + initName + "{ nil, new(" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "), " + sEp + " })\n") // cf. state chan builder // FIXME: chan struct reuse*/ + sEp + ".lin = " // FIXME: sync + + sEp + ".lin + 1\n"; + feach += initState +".id = " + sEp + ".lin\n"; + feach += "f(" + initState + ")\n"; + } + + feach += "}\n"; + + feach += //+ "return " + makeCreateSuccStateChan(s, succName) + "\n" + makeReturnSuccStateChan(s, succName) + "\n" + + "}\n"; + + // Parallel method + if (this.apigen.job.parForeach) + { + feach += "\n" + + "func (" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + " *" + scTypeName + + ") Parallel(f func(*" + initName + ") " + termName + ") *" + succName + " {\n"; + + // Duplicated from buildAction + feach += + "if " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " != nil {\n" + + "panic(" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + ")\n" + + "}\n"; + + feach += RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + "." + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n"; + + feach += "chs := make(map[int]chan int)\n"; + + feach += + "for " + p + " := " + generateIndexExpr(s.getInterval().start) + "; " // FIXME: general interval expressions + + p + lte + "; " + p + " = " + inc + "{\n"; + //+ sEp + "." + s.getParam() + "=" + s.getParam() + "\n" // FIXME: nested Endpoint type/struct? + + // inc Ept thread + // copy Ept params for new thread + // make new nested init with new thread + // spawn + feach += "tid := " + sEp + ".Thread + 1\n"; // FIXME: sync (factor up as a sync function in the ep) -- e.g., if a thread spawns more subthreads + feach += sEp + ".Thread = tid\n"; + feach += "tmp := make(map[string]int)\n"; + // FIXME: sync (factor up as a sync function in the ep) -- e.g., if a thread spawns more subthreads + feach += "for k,v := range " + sEp + ".Params[" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + ".Thread]" + "{\n"; + feach += "tmp[k] = v\n"; + feach += "}\n"; + feach += sEp + ".Params[tid] = tmp\n"; + + feach += "tmp[\"" + p + "\"] = " + p + "\n"; + + feach += "nested := " + RPCoreSTSessionApiBuilder.makeStateChanInstance(apigen, initName, sEp, "tid"); + feach += "chs[" + p + "] = make(chan int)\n"; + feach += "go func(ch chan int) {\n"; + feach += "f(nested)\n"; + feach += "ch <- 0\n"; + feach += "}(chs[" + p + "])\n"; + + feach += "}\n"; + + feach += + "for " + p + " := " + generateIndexExpr(s.getInterval().start) + "; " // FIXME: general interval expressions + + p + lte + "; " + p + " = " + inc + "{\n"; + feach += "<- chs[" + p + "]\n"; + feach += "}\n"; + + feach += //+ "return " + makeCreateSuccStateChan(s, succName) + "\n" + makeReturnSuccStateChan(s, succName) + "\n" + + "}\n"; + } + + + res.put(getStateChannelFilePath(scTypeName), feach); + + //RPCoreEState term = (RPCoreEState) MState.getTerminal(init); + //res.putAll(new RPCoreSTStateChanApiBuilder(this.apigen, this.variant, new EGraph(init, term)).build()); + if (term != null) + { + this.todo.add(new EGraph(init, term)); + } + + return res; + } + + // Factored out here from state-specific builders + protected String getStateChanPremable(EState s) + { + GProtocolName simpname = this.apigen.proto.getSimpleName(); + String scTypeName = this.getStateChanName(s); + String epkindTypeName = RPCoreSTApiGenerator.getEndpointKindTypeName(simpname, this.variant); + + String res = + "package " + RPCoreSTApiGenerator.getEndpointKindPackageName(this.variant) + "\n" + + "\n"; + //+ "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n"; + + // FIXME: error handling via Err field -- fallback should be panic + //+ "import \"log\"\n"; + + // Not needed by select-branch or Case objects // FIXME: refactor back into state-specific builders? + if (s.getStateKind() == EStateKind.OUTPUT || s.getStateKind() == EStateKind.UNARY_INPUT + || (s.getStateKind() == EStateKind.POLY_INPUT && !this.apigen.job.selectApi)) + { + res += makeMessageImports(s, true); + } + + // FIXME: still needed? -- refactor back into state-specific builders? + if (s.getStateKind() == EStateKind.UNARY_INPUT || s.getStateKind() == EStateKind.POLY_INPUT) + { + switch (this.apigen.mode) + { + case Int: res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n"; break; + case IntPair: res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE + "\"\n"; break; + default: throw new RuntimeException("Shouldn't get in here:" + this.apigen.mode); + } + + res += "import \"sync/atomic\"\n"; + res += "import \"reflect\"\n"; + res += "import \"sort\"\n"; + res += "\n"; + + res += "var _ = session2.NewMPChan\n"; + + res += "var _ = atomic.AddUint64\n"; + res += "var _ = reflect.TypeOf\n"; + res += "var _ = sort.Sort\n"; + } + else if (s.getStateKind() == EStateKind.OUTPUT) + { + if (this.apigen.mode == Mode.IntPair) + { + res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_PAIR_SESSION_PACKAGE + "\"\n"; + res += "\n"; + res += "var _ = session2.XY\n"; // For nested states that only use foreach vars (so no session2.XY) + } + else if (this.apigen.job.parForeach) + { + res += "import \"" + RPCoreSTApiGenConstants.GO_SCRIBBLERUNTIME_SESSION_PACKAGE + "\"\n"; + } + } + + // State channel type + res += "\n" + + "type " + scTypeName + " struct {\n" + + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " error\n"; + + if (this.apigen.job.parForeach) + { + res += RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + " *" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + "\n"; + } + else + { + res += "id uint64\n"; + } + + res += RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + " *" + epkindTypeName + "\n"; + + if (this.apigen.job.parForeach) + { + res += "Thread int\n"; + } + + res += "}\n"; + + return res; + } + + public String makeMessageImports(EState s, boolean pays) + { + String res = ""; + if (pays) + { + for (String extSource : (Iterable) s.getAllActions().stream() + .filter(a -> a.mid.isOp()) + .flatMap(a -> a.payload.elems.stream().filter(p -> !(p instanceof GDelegationType)) + .filter(p -> !getExtName((DataType) p).matches("(\\[\\])*(int|string|byte)")) + .filter(p -> !getExtName((DataType) p).matches("(\\*)*(int|string|byte)"))) + .map(p -> getExtSource((DataType) p)) + .distinct()::iterator) + { + res += "import \"" + extSource + "\"\n"; + } + for (PayloadElemType pet : (Iterable>) s.getAllActions().stream() + .filter(a -> a.mid.isOp()) + .flatMap(a -> a.payload.elems.stream().filter(p -> (p instanceof RPCoreGDelegationType)) + //.map(p -> getDelegatedChanPackageName((RPCoreGDelegationType) p)) + ) + .distinct()::iterator) + { + res += "import \"" + this.apigen.packpath + "/" + ((RPCoreGDelegationType) pet).getGlobalProtocol().getSimpleName() + // *pet* gpn name (i.e., for state chan type being delegated) -- cf. *this*.gpn.toString() in getStateChannelFilePath + + "/" + getDelegatedChanPackageName((RPCoreGDelegationType) pet) + "\"\n"; + } + } + for (String extSource : (Iterable) s.getAllActions().stream() + .filter(a -> a.mid.isMessageSigName()) + .map(a -> getExtSource((MessageSigName) a.mid)).distinct()::iterator) + { + res += "import \"" + extSource + "\"\n"; + } + return res; + } + + // "Base case" -- more specific versions should be overriden in action builders + // Here because action builder hierarchy not suitable (extended by action kind, not by target language) + @Override + public String buildAction(STActionBuilder ab, EState curr, EAction a) + { + EState succ = curr.getSuccessor(a); + String res = + "func (" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + + " *" + ab.getStateChanType(this, curr, a) + ") " + ab.getActionName(this, a) + "(" + + ab.buildArgs(this, a) + + ") *" //+ ab.getReturnType(this, curr, succ) // No: uses getStateChanName, which returns intermed name for nested states + + getSuccStateChanName(succ) + + " {\n" + + // FIXME: currently redundant for case objects (cf. branch action err handling) + + "if " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + " != nil {\n" + + "panic(" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + ")\n" + + "}\n"; + + if (this.apigen.job.parForeach) + { + res += RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + "." + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n"; + } + else + { + res += + // HACK FIXME: pre-create case objects + ((ab instanceof RPCoreSTCaseActionBuilder) + ? RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + "." + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_USE + "()\n" + : "if " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + "id != " // Not using atomic.LoadUint64 on id for now + //+ "atomic.LoadUint64(&" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + "lin)" + + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + "lin" + + " {\n" + + "panic(\"Linear resource already used\")\n" // + reflect.TypeOf(" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "))\n" + + "}\n" + ); + /*+ "atomic.AddUint64(" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + + "." + "lin" + ")\n"*/ + } + + res += ab.buildBody(this, curr, a, succ) + "\n" + + "}"; + + return res; + } + + // "Base case" -- more specific versions should be overriden in action builders + // FIXME: refactor action builders as interfaces and use generic parameter for kind + @Override + public String buildActionReturn(STActionBuilder ab, EState curr, EState succ) + { + String res = ""; + res += /*"return " + //makeCreateSuccStateChan(ab, curr, succ); + makeCreateSuccStateChan(succ);*/ + makeReturnSuccStateChan(succ); + return res; + } + + protected String getSuccStateChanName(EState succ) + { + /*RPCoreEState s = (RPCoreEState) succ; + String name = s.hasNested() + //? (s.isTerminal() ? getStateChanName(s) : getIntermediaryStateChanName(s)) // HACK FIXME -- first call to getStateChanName (intermed name not made yet) + ? getIntermediaryStateChanName(s) + : getStateChanName(s); //ab.getReturnType(this, curr, succ) + return name;*/ + return this.names.get(succ.id); + } + + //protected String makeCreateSuccStateChan(STActionBuilder ab, EState curr, EState succ) + @Deprecated + protected String makeCreateSuccStateChan(EState succ) + { + String name = getSuccStateChanName(succ); + return makeCreateSuccStateChan(succ, name); + } + + @Deprecated + protected String makeCreateSuccStateChan(EState succ, String name) + { + String sEp = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + if (((GoJob) this.job).selectApi && + getStateKind(succ) == RPCoreEStateKind.CROSS_RECEIVE && succ.getActions().size() > 1) + { + // Needs to be here (not in action builder) -- build (hacked) return for all state kinds + // FIXME: factor out with RPCoreSTSessionApiBuilder and RPCoreSTSelectStateBuilder#getPreamble + return "newBranch" + name + "(" + sEp + ")"; + } + else + { + /*String res = "&" + name + "{ " + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + ": " + RPCoreSTApiGenConstants.GO_IO_METHOD_ERROR + + ", " + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": " + sEp; + if (!succ.isTerminal()) // FIXME: terminal foreach state + { + res += ", " + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + ": new(" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ")"; // FIXME: EndSocket LinearResource special case + } + res += " }";*/ + String res = + /*"succ := " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "._" + name + "\n" + + "succ." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + "." + RPCoreSTApiGenConstants.GO_MPCHAN_ERR + " = err\n" + + "return succ\n"*/ + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "._" + name; + return res; + } + } + + protected String makeReturnSuccStateChan(EState succ) + { + String name = getSuccStateChanName(succ); + return makeReturnSuccStateChan(succ, name); + } + + protected String makeReturnSuccStateChan(EState succ, String name) + { + String sEp = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + if (((GoJob) this.job).selectApi && + getStateKind(succ) == RPCoreEStateKind.CROSS_RECEIVE && succ.getActions().size() > 1) + { + // Needs to be here (not in action builder) -- build (hacked) return for all state kinds + // FIXME: factor out with RPCoreSTSessionApiBuilder and RPCoreSTSelectStateBuilder#getPreamble + return "return newBranch" + name + "(" + sEp + ")"; + } + else + { + /*String res = "&" + name + "{ " + RPCoreSTApiGenConstants.GO_SCHAN_ERROR + ": " + RPCoreSTApiGenConstants.GO_IO_METHOD_ERROR + + ", " + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ": " + sEp; + if (!succ.isTerminal()) // FIXME: terminal foreach state + { + res += ", " + RPCoreSTApiGenConstants.GO_SCHAN_LINEARRESOURCE + + ": new(" + RPCoreSTApiGenConstants.GO_LINEARRESOURCE_TYPE + ")"; // FIXME: EndSocket LinearResource special case + } + res += " }";*/ + + String nextState; + if (this.apigen.job.parForeach) + { + nextState = "succ := " + + RPCoreSTSessionApiBuilder.makeStateChanInstance( + this.apigen, + name, + sEp, + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + ".Thread" + ); + String res = nextState + + "return succ\n"; + return res; + } + else + { + nextState = sEp + "._" + name; + String res = sEp + ".lin = " // FIXME: sync + + sEp + ".lin + 1\n" + + nextState + ".id = " + sEp + ".lin\n"; + res += "return "+ nextState + "\n"; + return res; + } + + /*if (this.apigen.job.parForeach) + { + res += RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Thread = " // FIXME: sync + + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Thread + 1\n" + + nextState + ".Thread = " + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT + ".Thread\n"; + }*/ + } + } + + @Override + public String getChannelName(STStateChanApiBuilder api, EAction a) // Not used? + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + a); + //return "s.ep.GetChan(s.ep.Proto.(*" + api.gpn.getSimpleName() + ")." + a.peer + ")"; + } + + // Super is used for both state chan type name (type decl and method receivers), and return type of actions + // Now, only using for state chan type name -- return type hardcoded to "base" name (via this.names) of successor + @Override + public String getStateChanName(EState s) + { + /*String name = this.imedNames.get(s.id); + if (name == null) + { + RPCoreEState rps = (RPCoreEState) s; + name = makeSTStateName(rps); + this.imedNames.put(rps.id, name); // The "original" name, now used for foreach -- doing this way round for convenience of original state channel naming + if (rps.hasNested() && !rps.isTerminal()) + { + name = name + "_"; // FIXME + } + this.names.put(s.id, name); + }*/ + if (!this.names.containsKey(s.id)) // Should not be needed, but do for debugging + { + throw new RuntimeException("[rp-core] Shouldn't get here: " + s); + } + String n = this.names.get(s.id); + /*if (n.equals("Init")) + { + return n; + }*/ + return ((RPCoreEState) s).hasNested() ? n + "_" : n; + } + + /*public String getIntermediaryStateChanName(EState s) + { + /*if (!this.names.containsKey(s.id)) + { + //throw new RuntimeException("Shouldn't get in here: " + s.id); // No: e.g., buildActionReturn, may refer to "ahead" state before that state is built + getStateChanName(s); // HACK FIXME + } + return this.imedNames.get(s.id);* / + return getStateChanName(s) + "_"; + }*/ + + @Override + protected String makeSTStateName(EState s) + { + /*RPCoreEState rps = (RPCoreEState) s; + String name = s.id == this.graph.init.id // Includes single (nested) state endpoint kinds (i.e, Init, not End) + ? "Init_" + s.id // FIXME: factor out (makeInitStateName) + : (s.isTerminal() + ? //makeEndStateName(this.apigen.proto.getSimpleName(), this.variant) + "End" + (rps.hasNested() ? "_" + s.id : "") + : //this.apigen.proto.getSimpleName() + "_" + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(this.actual) + "_" + "State" + + this.counter++); + return name;*/ + throw new RuntimeException("[rp-core] Shouldn't get in here: " + s); + } + + /*public static String makeEndStateName(GProtocolName simpname, RPRoleVariant r) + { + return //simpname + "_" + ParamCoreSTEndpointApiGenerator.getGeneratedActualRoleName(r) + "_" + + RPCoreSTApiGenConstants.GO_SCHAN_END_TYPE; + }*/ + + // Not variants -- just indexed roles (in EFSM actions) -- cf. ParamCoreSTEndpointApiGenerator#getGeneratedRoleVariantName + public static String getGeneratedIndexedRoleName(RPIndexedRole r) + { + //return r.toString().replaceAll("\\[", "_").replaceAll("\\]", "_").replaceAll("\\.", "_"); + if (r.intervals.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: " + r); + } + RPInterval g = r.intervals.iterator().next(); + return r.getName() + "_" + RPCoreSTApiGenerator.getGeneratedNameLabel(g.start) + + (g.start.equals(g.end) ? "" : "to" + RPCoreSTApiGenerator.getGeneratedNameLabel(g.end)); + } + + // Expressions to be used in code -- cf. RPCoreSTApiGenerator.getGeneratedNameLabel + public String generateIndexExpr(RPIndexExpr e) + { + if (e instanceof RPIndexInt) + { + return e.toGoString(); + } + else if (e instanceof RPIndexIntPair) + { + return e.toGoString(); + } + else if (e instanceof RPIndexVar) + { + String sEp = RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + "." + RPCoreSTApiGenConstants.GO_SCHAN_ENDPOINT; + if (e instanceof RPForeachVar + || this.fvars.stream().anyMatch(p -> p.toString().equals(e.toString()))) // FIXME HACK -- foreach var occurrences inside foreach body are RPIndexVars + { + if (this.apigen.job.parForeach) + { + return sEp + ".Params[" + RPCoreSTApiGenConstants.GO_IO_METHOD_RECEIVER + ".Thread][\"" + e.toGoString() + "\"]"; + } + else + { + return sEp + ".Params[\"" + e.toGoString() + "\"]"; + } + } + else + { + return sEp + //+ "." + RPCoreSTApiGenConstants.GO_ENDPOINT_PARAMS + "[\"" + e + "\"]"; + + "." + e.toGoString(); + } + } + else if (e instanceof RPBinIndexExpr) + { + RPBinIndexExpr b = (RPBinIndexExpr) e; + // TODO: factor out + switch (this.apigen.mode) + { + case Int: return "(" + generateIndexExpr(b.left) + b.op.toString() + generateIndexExpr(b.right) + ")"; + case IntPair: + { + String op; + switch (b.op) + { + case Add: op = "Plus"; break; + case Subt: op = "Sub"; break; + case Mult: + default: throw new RuntimeException("[rp-core] Shouldn't get in here: " + e); + } + return "(" + generateIndexExpr(b.left) + "." + op + "(" + generateIndexExpr(b.right) + "))"; + } + default: throw new RuntimeException("Shouldn't get in here: " + this.apigen.mode); + } + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + e); + } + } + + /*public String makeExtNameImport(DataType t) + { + String extName = getExtName(t); + return extName.matches("(\\[\\])*(int|string|byte)") + ? "" + : "import \"" + getExtSource(t) + "\"\n"; + }*/ + + + + + protected boolean isDelegType(PayloadElemType t) + { + //return this.dtds.stream().filter(x -> x.getDeclName().equals(t)).findAny().get() instanceof RPCoreDelegDecl; // FIXME: make a map + // "Old style", when deleg state chan types were directly imported by user as regular Go types + return t.isGDelegationType(); // CHECKME: distinguish RPCoreGDelegationType? + } + + // Cf. getExtName + protected String getPayloadElemTypeName(PayloadElemType pet) + { + if (pet instanceof RPCoreGDelegationType) + { + //return ((RPCoreSTStateChanApiBuilder) api).getExtName((DataType) pet); + RPCoreGDelegationType gdt = (RPCoreGDelegationType) pet; + String name; + + GProtocolName root = gdt.getRoot(); + GProtocolName state = gdt.getState(); + RPRoleVariant v = gdt.getVariant(); + RPCoreAstFactory af = new RPCoreAstFactory(); + + // Based on RPCoreCommandLine.paramCoreParseAndCheckWF // FIXME: integrate? (e.g., process all protocols, not just target main -- then won't need to separately run CL first on delegated proto) + GProtocolDecl gpd = (GProtocolDecl) this.job.getContext().getMainModule() + .getProtocolDecl(root.getSimpleName()); // FIXME: delegated protocol may not be in main module + try + { + RPCoreGType gt = new RPCoreGProtocolDeclTranslator(this.job, af).translate(gpd); + //RPCoreLType lt = gt.project(af, v, smt2t); + + /* // FIXME: currently cannot determine state chan name of target state in delegated protocol because of decoupled state numbering + // If we rebuild the target endpoint graph here, the state numbering won't match + RPCoreEGraphBuilder builder = new RPCoreEGraphBuilder(job); + EGraph g = builder.build(this.L0.get(r).get(ranges));*/ + } + catch (RPCoreSyntaxException e) + { + throw new RuntimeException("Shouldn't get in here: ", e); + } + + // FIXME: hardcoded to Init because of above FIXME + if (!root.equals(state)) + { + throw new RuntimeException("[rp-core] TODO: delegation of non-initial state of target protocol: " + state); + } + name = "Init"; + + return "*" + getDelegatedChanPackageName(gdt) + "." + name; + } + else if (pet instanceof DataType) + { + return getExtName((DataType) pet); + } + else + { + throw new RuntimeException("[rp-core] TODO: " + pet); + } + } + + protected static String getDelegatedChanPackageName(RPCoreGDelegationType gdt) + { + GProtocolName proto = gdt.getGlobalProtocol(); + RPRoleVariant variant = gdt.getVariant(); + return RPCoreSTApiGenerator.getEndpointKindTypeName(proto.getSimpleName(), variant); // N.B. doesn't use proto + } + + + /*protected String getExtName(AbstractName n) + { + if (n instanceof DataType) + { + DataType t = (DataType) n; + return this.dtds.stream().filter(x -> x.getDeclName().equals(t)).findAny().get().extName; + } + else if (n instanceof MessageSigName) + { + MessageSigName msn = (MessageSigName) n; + return this.msnds.stream().filter(x -> x.getDeclName().equals(msn)).findAny().get().extName; + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + n); + } + } + + protected String getExtSource(AbstractName n) + { + if (n instanceof DataType) + { + DataType t = (DataType) n; + return this.dtds.stream().filter(x -> x.getDeclName().equals(t)).findAny().get().extSource; // FIXME: make a map + } + else if (n instanceof MessageSigName) + { + MessageSigName msn = (MessageSigName) n; + return this.msnds.stream().filter(x -> x.getDeclName().equals(msn)).findAny().get().extSource; + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + n); + } + }*/ + + protected String getExtName(DataType t) + { + return this.dtds.stream().filter(x -> x.getDeclName().equals(t)).findAny().get().extName; + } + + protected String getExtSource(DataType t) + { + return this.dtds.stream().filter(x -> x.getDeclName().equals(t)).findAny().get().extSource; // FIXME: make a map + } + + protected String getExtName(MessageSigName n) + { + return this.msnds.stream().filter(x -> x.getDeclName().equals(n)).findAny().get().extName; + } + + protected String getExtSource(MessageSigName n) + { + return this.msnds.stream().filter(x -> x.getDeclName().equals(n)).findAny().get().extSource; + } + + + + + // FIXME: make a ParamCoreEState + protected enum RPCoreEStateKind { CROSS_SEND, CROSS_RECEIVE, DOT_SEND, DOT_RECEIVE, MULTICHOICES_RECEIVE, TERMINAL } + + protected static RPCoreEStateKind getStateKind(EState s) + { + List as = s.getActions(); + if (as.isEmpty()) + { + return RPCoreEStateKind.TERMINAL; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreECrossSend)) + { + return RPCoreEStateKind.CROSS_SEND; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreECrossReceive)) + { + return RPCoreEStateKind.CROSS_RECEIVE; + } + /*else if (as.stream().allMatch(a -> a instanceof RPCoreEDotSend)) // FIXME: CFSMs should have only !^1, ! and ? + { + return ParamCoreEStateKind.DOT_SEND; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreEDotReceive)) + { + return ParamCoreEStateKind.DOT_RECEIVE; + } + else if (as.stream().allMatch(a -> a instanceof RPCoreEMultiChoicesReceive)) + { + return ParamCoreEStateKind.MULTICHOICES_RECEIVE; + }*/ + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + s); + } + } + + + + + + + + + + + + /*@Override + public String getPackage() + { + //throw new RuntimeException("[rp-core] TODO:"); + return this.gpn.getSimpleName().toString(); + }*/ + + /*public String getActualRoleName() + { + return this.apigen.self.toString(); + }*/ + + /*protected RPRoleVariant getSelf() + { + return (RPRoleVariant) this.getSelf(); + }*/ +} + diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/main/RPCoreException.java b/scribble-go/src/main/java/org/scribble/ext/go/core/main/RPCoreException.java new file mode 100644 index 000000000..f84fd9fda --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/main/RPCoreException.java @@ -0,0 +1,51 @@ +package org.scribble.ext.go.core.main; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.main.ScribbleException; + +//public class AssrtException extends Exception +public class RPCoreException extends ScribbleException +{ + + /** + * + */ + private static final long serialVersionUID = 1L; + + public RPCoreException() + { + // TODO Auto-generated constructor stub + } + + public RPCoreException(String arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + public RPCoreException(Throwable arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + public RPCoreException(String arg0, Throwable arg1) + { + super(arg0, arg1); + // TODO Auto-generated constructor stub + } + + public RPCoreException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + // TODO Auto-generated constructor stub + } + + public RPCoreException(CommonTree blame, String arg0) + { + super(blame, arg0); + // TODO Auto-generated constructor stub + } + +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/main/RPCoreMainContext.java b/scribble-go/src/main/java/org/scribble/ext/go/core/main/RPCoreMainContext.java new file mode 100644 index 000000000..3ccb05793 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/main/RPCoreMainContext.java @@ -0,0 +1,73 @@ +package org.scribble.ext.go.core.main; + +import java.nio.file.Path; + +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.RPAstFactoryImpl; +import org.scribble.ext.go.core.model.endpoint.RPCoreEModelFactory; +import org.scribble.ext.go.core.model.endpoint.RPCoreEModelFactoryImpl; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.parser.scribble.RPAntlrToScribParser; +import org.scribble.ext.go.parser.scribble.RPScribbleAntlrWrapper; +import org.scribble.main.MainContext; +import org.scribble.main.ScribbleException; +import org.scribble.main.resource.ResourceLocator; +import org.scribble.parser.scribble.ScribbleAntlrWrapper; +import org.scribble.util.ScribParserException; + +public class RPCoreMainContext extends MainContext +{ + protected final boolean selectApi; + protected final boolean noCopy; + protected final boolean parForeach; + + // Load main module from file system + public RPCoreMainContext(boolean debug, ResourceLocator locator, Path mainpath, boolean useOldWF, boolean noLiveness, boolean minEfsm, + boolean fair, boolean noLocalChoiceSubjectCheck, boolean noAcceptCorrelationCheck, boolean noValidation, boolean noCopy, boolean selectApi, boolean parForeach) + throws ScribParserException, ScribbleException + { + super(debug, locator, mainpath, useOldWF, noLiveness, minEfsm, fair, noLocalChoiceSubjectCheck, noAcceptCorrelationCheck, noValidation); + this.noCopy = noCopy; + this.selectApi = selectApi; + this.parForeach = parForeach; + } + + @Override + public GoJob newJob() // FIXME: make RPCoreJob? + { + return new GoJob(this.debug, this.getParsedModules(), this.main, this.useOldWF, this.noLiveness, this.minEfsm, this.fair, + this.noLocalChoiceSubjectCheck, this.noAcceptCorrelationCheck, this.noValidation, + this.af, this.ef, this.sf, this.noCopy, this.selectApi, this.parForeach); + } + + @Override + protected ScribbleAntlrWrapper newAntlrParser() + { + return new RPScribbleAntlrWrapper(); + } + + @Override + protected RPAntlrToScribParser newScribParser() + { + return new RPAntlrToScribParser(); + } + + @Override + protected RPAstFactory newAstFactory() + { + return new RPAstFactoryImpl(); + } + + @Override + protected RPCoreEModelFactory newEModelFactory() + { + return new RPCoreEModelFactoryImpl(); // HACK FIXME + } + + /*@Override + protected SModelFactory newSModelFactory() + { + //return new ParamSModelFactoryImpl(); + return new ParamCoreSModelFactoryImpl(); // HACK FIXME + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEGraphBuilder.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEGraphBuilder.java new file mode 100644 index 000000000..7c9e2e9b3 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEGraphBuilder.java @@ -0,0 +1,227 @@ +package org.scribble.ext.go.core.model.endpoint; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.scribble.ext.go.core.ast.RPCoreForeach; +import org.scribble.ext.go.core.ast.RPCoreRecVar; +import org.scribble.ext.go.core.ast.local.RPCoreLActionKind; +import org.scribble.ext.go.core.ast.local.RPCoreLChoice; +import org.scribble.ext.go.core.ast.local.RPCoreLCont; +import org.scribble.ext.go.core.ast.local.RPCoreLEnd; +import org.scribble.ext.go.core.ast.local.RPCoreLForeach; +import org.scribble.ext.go.core.ast.local.RPCoreLRec; +import org.scribble.ext.go.core.ast.local.RPCoreLType; +import org.scribble.ext.go.core.type.RPAnnotatedInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.model.endpoint.EGraph; +import org.scribble.model.endpoint.EGraphBuilderUtil; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.type.Message; +import org.scribble.type.MessageSig; +import org.scribble.type.Payload; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.RecVar; + +public class RPCoreEGraphBuilder +{ + + private final GoJob job; + private final RPCoreEModelFactory ef; + private final EGraphBuilderUtil util; // Not using any features for unguarded choice/recursion/continue (recursion manually tracked here) + + public RPCoreEGraphBuilder(GoJob job) + { + this.job = job; + this.ef = (RPCoreEModelFactory) job.ef; + this.util = new EGraphBuilderUtil(job.ef); + } + + /*private Pair makeRPCoreEState(RPCoreLType lt) + { + RPCoreEState s; + RPCoreLType seq; + if (lt instanceof RPCoreLForeach) + { + RPCoreLForeach fe = (RPCoreLForeach) lt; + s = this.ef.newRPCoreEState(Collections.emptySet(), fe.var, + new RPInterval(fe.start, fe.end), (RPCoreEState) build(((RPCoreLForeach) lt).body).init); + if (fe.seq instanceof RPCoreForeach) // FIXME: consecutive foreach ("tau" action) + { + throw new RuntimeException("[rp-core] TODO: " + lt); + } + seq = fe.seq; + } + else + { + s = this.ef.newRPCoreEState(Collections.emptySet(), null, null, null); + seq = lt; + } + return new Pair<>(s, seq); + }*/ + + public EGraph build(RPCoreLType lt) + { + /*Pair p = makeRPCoreEState(lt); // Currently always a top-level rec + this.util.init(p.left); + build(p.right, this.util.getEntry(), this.util.getExit(), new HashMap<>());*/ + this.util.init(this.ef.newEState(Collections.emptySet())); // RPCoreEState + build(lt, (RPCoreEState) this.util.getEntry(), + (RPCoreEState) this.util.getExit(), new HashMap<>()); // lt is always a top-level rec + EGraph foo = this.util.finalise(); + return foo; + } + + // s1 is "current state", which may be mutably modified by foreach (and rec -- GraphBuilerUtil#addEntryLabel done by LRecursionDel) + private void build(RPCoreLType lt, RPCoreEState s1, RPCoreEState s2, Map recs) + { + if (lt instanceof RPCoreLForeach) + { + RPCoreLForeach fe = (RPCoreLForeach) lt; + RPCoreEState s = (RPCoreEState) s1; // FIXME: modify method sig + if (fe.ivals.size() > 1) + { + throw new RuntimeException("[rp-core] TODO: " + fe.ivals); + } + RPAnnotatedInterval iv = fe.ivals.stream().findFirst().get(); + s.setParam(iv.var); + s.setInterval(new RPInterval(iv.start, iv.end)); + RPCoreEGraphBuilder nested = new RPCoreEGraphBuilder(this.job); + s.setNested((RPCoreEState) nested.build(fe.body).init); + if (fe.seq instanceof RPCoreForeach) // FIXME: consecutive foreach ("tau" action) + { + throw new RuntimeException("[rp-core] TODO: " + lt); + } + else if (!(fe.seq instanceof RPCoreLEnd)) + { + build(fe.seq, s1, s2, recs); + } + } + else if (lt instanceof RPCoreLChoice) + { + /*if (lt instanceof RPCoreLMultiChoices) + { + RPCoreLMultiChoices lc = (RPCoreLMultiChoices) lt; + List> mids = lc.cases.keySet().stream().map(x -> x.op).collect(Collectors.toList()); + List pays = lc.cases.keySet().stream().map(x -> x.pay).collect(Collectors.toList()); + buildMultiChoicesEdgeAndContinuation(s1, s2, recs, lc.role, lc.getKind(), mids, pays, lc.getContinuation()); + // N.B. this directly constructs a single continuation for the multichoices-receiver + // cf. multichoices sender side, standard cross-send with separate (but identical) continuations -- could also build single contination for sender by introducing explicit multichoices-send constructor + } + else*/ + { + RPCoreLChoice lc = (RPCoreLChoice) lt; + RPIndexExpr offset = //(lc instanceof RPCoreLDotChoice) ? ((RPCoreLDotChoice) lc).offset : + null; + lc.cases.entrySet().forEach(e -> + buildEdgeAndContinuation(s1, s2, recs, lc.role, lc.getKind(), e.getKey(), e.getValue(), offset) + ); + } + } + else if (lt instanceof RPCoreLRec) + { + RPCoreLRec lr = (RPCoreLRec) lt; + Map tmp = new HashMap<>(recs); + tmp.put(lr.recvar, s1); + build(lr.body, s1, s2, tmp); + } + else if (lt instanceof RPCoreLCont) + { + // skip + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + lt); + } + } + + // CHECKME: offset redundant? + private void buildEdgeAndContinuation(RPCoreEState s1, RPCoreEState s2, Map recs, + RPIndexedRole r, RPCoreLActionKind k, //RPCoreMessage a, + Message a, + RPCoreLType cont, RPIndexExpr offset) + { + EAction ea = toEAction(r, k, a, offset); + if (cont instanceof RPCoreLEnd || cont instanceof RPCoreLCont) + { + this.util.addEdge(s1, ea, s2); + } + else if (cont instanceof RPCoreRecVar) + { + EState s = recs.get(((RPCoreRecVar) cont).recvar); + this.util.addEdge(s1, ea, s); + } + else + { + RPCoreEState s = this.ef.newEState(Collections.emptySet()); + this.util.addEdge(s1, ea, s); + build(cont, s, s2, recs); + } + } + + /*// FIXME: factor out with above + private void buildMultiChoicesEdgeAndContinuation(EState s1, EState s2, Map recs, + RPIndexedRole r, RPCoreLActionKind k, List> mids, List pays, RPCoreLType cont) + { + EAction ea = ((RPCoreEModelFactory) this.util.ef).newParamCoreEMultiChoicesReceive(r, mids, pays); + if (cont instanceof RPCoreLEnd) + { + this.util.addEdge(s1, ea, s2); + } + else if (cont instanceof RPCoreRecVar) + { + EState s = recs.get(((RPCoreRecVar) cont).recvar); + this.util.addEdge(s1, ea, s); + } + else + { + EState s = this.util.ef.newEState(Collections.emptySet()); + this.util.addEdge(s1, ea, s); + build(cont, s, s2, recs); + } + }*/ + + private EAction toEAction(RPIndexedRole r, RPCoreLActionKind k, //RPCoreMessage a, + Message a, + RPIndexExpr offset) + { + RPCoreEModelFactory ef = (RPCoreEModelFactory) this.util.ef; // FIXME: factor out + + // Cf. LSendDel#leaveEGraphBuilding + MessageId mid = a.getId(); + Payload pay = (a instanceof MessageSig) // Hacky? + ? ((MessageSig) a).payload + : Payload.EMPTY_PAYLOAD; + + if (k.equals(RPCoreLActionKind.CROSS_SEND)) + { + return ef.newParamCoreECrossSend(r, mid, pay); + + } + else if (k.equals(RPCoreLActionKind.CROSS_RECEIVE)) + { + return ef.newParamCoreECrossReceive(r, mid, pay); + } + /*else if (k.equals(RPCoreLActionKind.DOT_SEND)) + { + return ef.newParamCoreEDotSend(r, offset, mid, pay); + } + else if (k.equals(RPCoreLActionKind.DOT_RECEIVE)) + { + return ef.newParamCoreEDotReceive(r, offset, mid, pay); + } + else if (k.equals(ParamCoreLActionKind.MULTICHOICES_RECEIVE)) + { + return ef.newParamCoreEMultiChoicesReceive(r, mid, pay); + }*/ + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + k); + } + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEModelFactory.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEModelFactory.java new file mode 100644 index 000000000..753794785 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEModelFactory.java @@ -0,0 +1,33 @@ +package org.scribble.ext.go.core.model.endpoint; + +import java.util.List; +import java.util.Set; + +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossSend; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEDotReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEDotSend; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEMultiChoicesReceive; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.model.endpoint.EModelFactory; +import org.scribble.type.Payload; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.RecVar; + +public interface RPCoreEModelFactory extends EModelFactory +{ + @Override + RPCoreEState newEState(Set labs); + + RPCoreEState newRPCoreEState(Set labs, RPForeachVar param, RPInterval interval, RPCoreEState nested); + + RPCoreECrossSend newParamCoreECrossSend(RPIndexedRole peer, MessageId mid, Payload payload); + RPCoreECrossReceive newParamCoreECrossReceive(RPIndexedRole peer, MessageId mid, Payload payload); + RPCoreEDotSend newParamCoreEDotSend(RPIndexedRole peer, RPIndexExpr offset, MessageId mid, Payload payload); + RPCoreEDotReceive newParamCoreEDotReceive(RPIndexedRole peer, RPIndexExpr offset, MessageId mid, Payload payload); + RPCoreEMultiChoicesReceive newParamCoreEMultiChoicesReceive(RPIndexedRole peer,//MessageId mid, Payload payload) + List> mids, List pays); +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEModelFactoryImpl.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEModelFactoryImpl.java new file mode 100644 index 000000000..82ce05bb4 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEModelFactoryImpl.java @@ -0,0 +1,82 @@ +package org.scribble.ext.go.core.model.endpoint; + +import java.util.List; +import java.util.Set; + +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossSend; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEDotReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEDotSend; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEMultiChoicesReceive; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.model.endpoint.EModelFactoryImpl; +import org.scribble.model.endpoint.actions.EReceive; +import org.scribble.model.endpoint.actions.ESend; +import org.scribble.type.Payload; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.RecVar; +import org.scribble.type.name.Role; + +public class RPCoreEModelFactoryImpl extends EModelFactoryImpl implements RPCoreEModelFactory +{ + + @Override + public RPCoreEState newEState(Set labs) + { + //throw new RuntimeException("[rp-core] Shouldn't get in here: "); // No: needed by e.g., EGraphBuilderUtil#init + return new RPCoreEState(labs); + } + + @Override + public RPCoreEState newRPCoreEState(Set labs, RPForeachVar param, RPInterval interval, RPCoreEState nested) + { + return new RPCoreEState(labs, param, interval, nested); + } + + + @Override + public ESend newESend(Role peer, MessageId mid, Payload payload) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: "); + } + + @Override + public EReceive newEReceive(Role peer, MessageId mid, Payload payload) + { + throw new RuntimeException("[rp-core] Shouldn't get in here: "); + } + + @Override + public RPCoreECrossSend newParamCoreECrossSend(RPIndexedRole peer, MessageId mid, Payload payload) + { + return new RPCoreECrossSend(this, peer, mid, payload); + } + + @Override + public RPCoreECrossReceive newParamCoreECrossReceive(RPIndexedRole peer, MessageId mid, Payload payload) + { + return new RPCoreECrossReceive(this, peer, mid, payload); + } + + @Override + public RPCoreEDotSend newParamCoreEDotSend(RPIndexedRole peer, RPIndexExpr offset, MessageId mid, Payload payload) + { + return new RPCoreEDotSend(this, peer, offset, mid, payload); + } + + @Override + public RPCoreEDotReceive newParamCoreEDotReceive(RPIndexedRole peer, RPIndexExpr offset, MessageId mid, Payload payload) + { + return new RPCoreEDotReceive(this, peer, offset, mid, payload); + } + + @Override + public RPCoreEMultiChoicesReceive newParamCoreEMultiChoicesReceive(RPIndexedRole peer,//MessageId mid, Payload payload) + List> mids, List pays) + { + return new RPCoreEMultiChoicesReceive(this, peer, mids, pays); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEState.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEState.java new file mode 100644 index 000000000..eb1e4f21e --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/RPCoreEState.java @@ -0,0 +1,217 @@ +package org.scribble.ext.go.core.model.endpoint; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.core.model.endpoint.action.RPCoreEAction; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossReceive; +import org.scribble.ext.go.core.model.endpoint.action.RPCoreECrossSend; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.model.MState; +import org.scribble.model.endpoint.EModelFactory; +import org.scribble.model.endpoint.EState; +import org.scribble.model.endpoint.actions.EAction; +import org.scribble.model.endpoint.actions.EReceive; +import org.scribble.model.endpoint.actions.ESend; +import org.scribble.type.name.RecVar; + +// Cf. AssrtEState +public class RPCoreEState extends EState +{ + + // Mutable -- not used in hashCode/equals (state ID only) -- cf. EState#hashCode/equals (and mutable label set) + private RPForeachVar param; + private RPInterval interval; + private RPCoreEState nested; // null if no nested FSM (then above also null) + + protected RPCoreEState(Set labs) + { + this(labs, null, null, null); + } + + protected RPCoreEState(Set labs, RPForeachVar param, RPInterval interval, RPCoreEState nested) + { + super(labs); + this.param = param; + this.interval = interval; + this.nested = nested; + } + + @Override + protected RPCoreEState cloneNode(EModelFactory ef, Set labs) + { + return ((RPCoreEModelFactory) ef).newRPCoreEState(labs, this.param, this.interval, this.nested); + } + + public boolean hasNested() + { + return this.nested != null; + } + + // Mutable getters/setters -- cf. super label set + + public RPForeachVar getParam() + { + return this.param; + } + + public void setParam(RPForeachVar param) + { + this.param = param; + } + + public RPInterval getInterval() + { + return this.interval; + } + + public void setInterval(RPInterval interval) + { + this.interval = interval; + } + + public RPCoreEState getNested() + { + return this.nested; + } + + public void setNested(RPCoreEState nested) + { + this.nested = nested; + } + + @Override + protected String getNodeLabel() + { + String labs = this.labs.toString(); + return "label=\"" + this.id + ": " + labs.substring(1, labs.length() - 1) // From super.getNodeLabel + + (hasNested() ? this.param + ":" + this.interval + "; " + this.nested.id : "") + + "\""; // FIXME: would be more convenient for this method to return only the label body + } + + @Override + public RPCoreEState getSuccessor(EAction a) + { + return (RPCoreEState) super.getSuccessor(a); + } + + @Override + public int hashCode() + { + int hash = 4817; + hash = 31 * hash + super.hashCode(); + // N.B. use state ID only -- following super pattern -- to allow, e.g., mutable label set + /*if (hasNested()) + { + hash = 31 * hash + this.param.hashCode(); + hash = 31 * hash + this.interval.hashCode(); + hash = 31 * hash + this.nested.hashCode(); + }*/ + return hash; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPCoreEState)) + { + return false; + } + //RPCoreEState them = (RPCoreEState) o; + return super.equals(o); // Checks canEquals + /*&& hasNested() // No: use state ID only + ? (them.hasNested() && this.param.equals(them.param) && this.interval.equals(them.interval) && this.nested.equals(them.nested)) + : !them.hasNested();*/ + } + + @Override + protected boolean canEquals(MState s) + { + return s instanceof RPCoreEState; + } + + // FIXME: make not static -- otherwise choosing statics (cf. MState) by overloading, error prone + public static Set getReachableStates(RPCoreEState start) + { + Set res = MState.getReachableStates(start).stream() + .map(s -> (RPCoreEState) s).collect(Collectors.toSet()); + + //System.out.println("ccc: " + start.id + ",, " + res); + + Set nested = res.stream() + .flatMap(s -> s.hasNested() ? Stream.concat(Stream.of(s.nested), getReachableStates(s.nested).stream()) : Stream.of()).collect(Collectors.toSet()); + res.addAll(nested); + if (start.hasNested()) // N.B. start itself is not considered reachable -- correct? + { + res.add(start.nested); + res.addAll(getReachableStates(start.nested)); + } + return res; + } + + // FIXME: make not static -- otherwise choosing statics (cf. MState) by overloading, error prone + // Note: returns "syntactic" results, e.g., foreachvars directly returned unqualified + // cf. RPCoreGForeach#getIndexedRoles + public static Set getReachableActions(RPCoreEModelFactory ef, RPCoreEState start) + { + Set rs = getReachableStates(start); + rs.add(start); + Set tmp = rs.stream() + .flatMap(s -> s.getAllActions().stream().map(a -> (RPCoreEAction) a)).collect(Collectors.toSet()); + + if (start.hasNested()) + { + Set tmp2 = new HashSet<>(); + for (RPCoreEAction a : tmp) + { + if (a.getPeer().intervals.stream().flatMap(d -> d.getIndexVars().stream()).anyMatch(x -> x.toString().equals(start.param.toString()))) + { + Set blah = new HashSet<>(); + for (RPInterval d : a.getPeer().intervals) + { + // FIXME: current assuming if any I occurrence, then interval is be [I,I] + if (d.getIndexVars().stream().anyMatch(x -> x.toString().equals(start.param.toString()))) + { + blah.add(start.interval); + } + else + { + blah.add(d); + } + } + RPIndexedRole b = new RPIndexedRole(a.getPeer().getName().toString(), blah); + + if (a instanceof RPCoreECrossSend) + { + tmp2.add(ef.newParamCoreECrossSend(b, ((ESend) a).mid, ((ESend) a).payload)); + } + else if (a instanceof RPCoreECrossReceive) + { + tmp2.add(ef.newParamCoreECrossReceive(b, ((EReceive) a).mid, ((EReceive) a).payload)); + } + else + { + throw new RuntimeException("[rp-core] Shouldn't get in here: " + a); + } + } + else + { + tmp2.add(a); + } + } + tmp = tmp2; + } + + //System.out.println("bbb: " + start.id + ",, " + rs + ",, " + tmp); + + return tmp; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEAction.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEAction.java new file mode 100644 index 000000000..e8f692765 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEAction.java @@ -0,0 +1,9 @@ +package org.scribble.ext.go.core.model.endpoint.action; + +import org.scribble.ext.go.core.type.RPIndexedRole; + +public interface RPCoreEAction +{ + + RPIndexedRole getPeer(); // N.B. *not* ParamActualRole +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreECrossReceive.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreECrossReceive.java new file mode 100644 index 000000000..c35aa7f7b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreECrossReceive.java @@ -0,0 +1,65 @@ +package org.scribble.ext.go.core.model.endpoint.action; + +import org.scribble.ext.go.core.model.endpoint.RPCoreEModelFactory; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.model.endpoint.actions.EReceive; +import org.scribble.model.global.SModelFactory; +import org.scribble.model.global.actions.SReceive; +import org.scribble.type.Payload; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.Role; + +public class RPCoreECrossReceive extends EReceive implements RPCoreEAction +{ + + public RPCoreECrossReceive(RPCoreEModelFactory ef, RPIndexedRole peer, MessageId mid, Payload payload) + { + super(ef, peer, mid, payload); + } + + @Override + public RPIndexedRole getPeer() + { + return (RPIndexedRole) this.peer; + } + + @Override + public RPCoreECrossSend toDual(Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public SReceive toGlobal(SModelFactory sf, Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public int hashCode() + { + int hash = 6763; + hash = 31 * hash + super.hashCode(); + return hash; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPCoreECrossReceive)) + { + return false; + } + return super.equals(o); // Does canEquals + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPCoreECrossReceive; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreECrossSend.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreECrossSend.java new file mode 100644 index 000000000..db205c659 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreECrossSend.java @@ -0,0 +1,65 @@ +package org.scribble.ext.go.core.model.endpoint.action; + +import org.scribble.ext.go.core.model.endpoint.RPCoreEModelFactory; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.model.endpoint.actions.ESend; +import org.scribble.model.global.SModelFactory; +import org.scribble.model.global.actions.SSend; +import org.scribble.type.Payload; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.Role; + +public class RPCoreECrossSend extends ESend implements RPCoreEAction +{ + + public RPCoreECrossSend(RPCoreEModelFactory ef, RPIndexedRole peer, MessageId mid, Payload payload) + { + super(ef, peer, mid, payload); + } + + @Override + public RPIndexedRole getPeer() + { + return (RPIndexedRole) this.peer; + } + + @Override + public RPCoreECrossReceive toDual(Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public SSend toGlobal(SModelFactory sf, Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public int hashCode() + { + int hash = 6779; + hash = 31 * hash + super.hashCode(); + return hash; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPCoreECrossSend)) + { + return false; + } + return super.equals(o); // Does canEquals + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPCoreECrossSend; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEDotReceive.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEDotReceive.java new file mode 100644 index 000000000..472bc4855 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEDotReceive.java @@ -0,0 +1,96 @@ +package org.scribble.ext.go.core.model.endpoint.action; + +import org.scribble.ext.go.core.model.endpoint.RPCoreEModelFactory; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.model.endpoint.actions.EReceive; +import org.scribble.model.global.SModelFactory; +import org.scribble.model.global.actions.SReceive; +import org.scribble.type.Payload; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.Role; + +public class RPCoreEDotReceive extends EReceive implements RPCoreEAction +{ + public final RPIndexExpr offset; + + public RPCoreEDotReceive(RPCoreEModelFactory ef, RPIndexedRole peer, RPIndexExpr offset, MessageId mid, Payload payload) + { + super(ef, peer, mid, payload); + this.offset = offset; + } + + @Override + public RPIndexedRole getPeer() + { + return (RPIndexedRole) this.peer; + } + + @Override + public RPCoreEDotSend toDual(Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public SReceive toGlobal(SModelFactory sf, Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public String toString() + { + RPIndexedRole peer = getPeer(); + RPInterval g = peer.intervals.iterator().next(); + return peer.getName() + "[" + this.offset + ":" + g.start + ".." + g.end + "]" + + getCommSymbol() + this.mid + this.payload; + } + + @Override + public String toStringWithMessageIdHack() + { + String m = this.mid.isMessageSigName() ? "^" + this.mid : this.mid.toString(); // HACK + RPIndexedRole peer = getPeer(); + RPInterval g = peer.intervals.iterator().next(); + return peer.getName() + "[" + this.offset + ":" + g.start + ".." + g.end + "]" + + getCommSymbol() + m + this.payload; + } + + @Override + protected String getCommSymbol() + { + return "?="; + } + + @Override + public int hashCode() + { + int hash = 7213; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.offset.hashCode(); + return hash; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPCoreEDotReceive)) + { + return false; + } + return super.equals(o) // Does canEquals + && this.offset.equals(((RPCoreEDotSend) o).offset); + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPCoreEDotReceive; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEDotSend.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEDotSend.java new file mode 100644 index 000000000..92efdf23a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEDotSend.java @@ -0,0 +1,97 @@ +package org.scribble.ext.go.core.model.endpoint.action; + +import org.scribble.ext.go.core.model.endpoint.RPCoreEModelFactory; +import org.scribble.ext.go.core.type.RPInterval; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.model.endpoint.actions.ESend; +import org.scribble.model.global.SModelFactory; +import org.scribble.model.global.actions.SSend; +import org.scribble.type.Payload; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.Role; + +public class RPCoreEDotSend extends ESend implements RPCoreEAction +{ + public final RPIndexExpr offset; + + // ParamRole range is original peer absolute range -- local id plus offset will be inside this range + public RPCoreEDotSend(RPCoreEModelFactory ef, RPIndexedRole peer, RPIndexExpr offset, MessageId mid, Payload payload) + { + super(ef, peer, mid, payload); + this.offset = offset; + } + + @Override + public RPIndexedRole getPeer() + { + return (RPIndexedRole) this.peer; + } + + @Override + public RPCoreEDotReceive toDual(Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public SSend toGlobal(SModelFactory sf, Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public String toString() + { + RPIndexedRole peer = getPeer(); + RPInterval g = peer.intervals.iterator().next(); + return peer.getName() + "[" + this.offset + ":" + g.start + ".." + g.end + "]" + + getCommSymbol() + this.mid + this.payload; + } + + @Override + public String toStringWithMessageIdHack() + { + String m = this.mid.isMessageSigName() ? "^" + this.mid : this.mid.toString(); // HACK + RPIndexedRole peer = getPeer(); + RPInterval g = peer.intervals.iterator().next(); + return peer.getName() + "[" + this.offset + ":" + g.start + ".." + g.end + "]" + + getCommSymbol() + m + this.payload; + } + + @Override + protected String getCommSymbol() + { + return "!="; + } + + @Override + public int hashCode() + { + int hash = 7211; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.offset.hashCode(); + return hash; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPCoreEDotSend)) + { + return false; + } + return super.equals(o) // Does canEquals + && this.offset.equals(((RPCoreEDotSend) o).offset); + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPCoreEDotSend; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEMultiChoicesReceive.java b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEMultiChoicesReceive.java new file mode 100644 index 000000000..32a9dea9c --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/model/endpoint/action/RPCoreEMultiChoicesReceive.java @@ -0,0 +1,101 @@ +package org.scribble.ext.go.core.model.endpoint.action; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import org.scribble.ext.go.core.model.endpoint.RPCoreEModelFactory; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.model.endpoint.actions.EReceive; +import org.scribble.model.global.SModelFactory; +import org.scribble.model.global.actions.SReceive; +import org.scribble.type.Payload; +import org.scribble.type.name.MessageId; +import org.scribble.type.name.Role; + +public class RPCoreEMultiChoicesReceive extends EReceive implements RPCoreEAction +{ + public final List> mids; + public final List pays; // mids.size() == pays.size() + + public RPCoreEMultiChoicesReceive(RPCoreEModelFactory ef, RPIndexedRole peer, List> mids, List pays) + { + super(ef, peer, null, null); // null OK? + this.mids = Collections.unmodifiableList(mids); + this.pays = Collections.unmodifiableList(pays); + } + + @Override + public RPIndexedRole getPeer() + { + return (RPIndexedRole) this.peer; + } + + @Override + public RPCoreECrossSend toDual(Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public SReceive toGlobal(SModelFactory sf, Role self) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this); + } + + @Override + public String toString() + { + Iterator pays = this.pays.iterator(); + String ms = "{" + this.mids.stream().map(m -> m.toString() + pays.next().toString()).collect(Collectors.joining(", ")) + "}"; + return this.peer + getCommSymbol() + ms; + } + + @Override + public String toStringWithMessageIdHack() + { + Iterator pays = this.pays.iterator(); + String ms = "{" + this.mids.stream().map(m -> (m.isMessageSigName() ? "^" + m : m.toString()) + + pays.next().toString()).collect(Collectors.joining(", ")) + "}"; + return this.obj + getCommSymbol() + ms; + } + + @Override + protected String getCommSymbol() + { + return "?*"; + } + + @Override + public int hashCode() + { + int hash = 7219; + hash = 31 * hash + this.obj.hashCode(); + hash = 31 * hash + this.mids.hashCode(); // N.B. excluding this.mid, this.payload + hash = 31 * hash + this.pays.hashCode(); + return hash; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPCoreEMultiChoicesReceive)) + { + return false; + } + RPCoreEMultiChoicesReceive them = (RPCoreEMultiChoicesReceive) o; + return them.canEqual(this) && // N.B. don't call super: this.mid, this.pay == null + this.obj.equals(them.obj) && this.mids.equals(them.mids) && this.pays.equals(them.pays); + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPCoreEMultiChoicesReceive; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPAnnotatedInterval.java b/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPAnnotatedInterval.java new file mode 100644 index 000000000..0f0453f5f --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPAnnotatedInterval.java @@ -0,0 +1,58 @@ +package org.scribble.ext.go.core.type; + +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; + +public class RPAnnotatedInterval extends RPInterval +{ + public final RPForeachVar var; // FIXME: generally deprecate RPForeachVar for RPIndexVar? + + public RPAnnotatedInterval(RPForeachVar var, RPIndexExpr start, RPIndexExpr end) + { + super(start, end); + this.var = var; + } + + @Override + public RPInterval minimise(int self) + { + return new RPAnnotatedInterval(var, this.start.minimise(self), this.end.minimise(self)); + } + + @Override + public String toString() + { + return "[" + this.var + ":" + this.start + ((this.start == this.end) ? "" : "," + this.end) + "]"; + } + + @Override + public int hashCode() + { + int hash = 3119; + hash = 31 * hash + this.var.hashCode(); + hash = 31 * hash + super.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPAnnotatedInterval)) + { + return false; + } + RPAnnotatedInterval them = (RPAnnotatedInterval) obj; + return super.equals(them) // Does canEqual + && this.var.equals(them.var); + } + + @Override + public boolean canEqual(RPInterval o) + { + return o instanceof RPAnnotatedInterval; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPIndexedRole.java b/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPIndexedRole.java new file mode 100644 index 000000000..a5f28f6f1 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPIndexedRole.java @@ -0,0 +1,124 @@ +package org.scribble.ext.go.core.type; + +import java.util.Collections; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.type.name.Role; + +// FIXME: make distinct kind? i.e., don't extend Role? -- yes: ParamRole is not a Role (Role should actually be a ParamRole in that sense) +public class RPIndexedRole extends Role +{ + /** + * + */ + private static final long serialVersionUID = 1L; + + //public final ParamRange range; + public final Set intervals; // size >= 1 -- size == 1 for parsed syntax + // FIXME: this set was meant for multidim nat intervals, but multidim should be factored into the RPInterval itself + // No, above is wrong -- this set is actually for multiple intervals, but currently only non-singleton at local level (i.e, variants) + + public RPIndexedRole(String name, Set intervals) + { + super(name); + /*if (intervals.size() != 1) + // FIXME: this set was meant for multidim nat intervals, but multidim should be factored into the RPInterval itself + // No: above is true for parsed globals, but Set needed for variants (subclass of this) + { + throw new RuntimeException("TODO: " + intervals); + }*/ + this.intervals = Collections.unmodifiableSet(intervals); + } + + // FIXME: rename + public RPIndexedRole minimise(int self) + { + Set ivals = this.intervals.stream().map(x -> x.minimise(self)).collect(Collectors.toSet()); + Optional o = ivals.stream().filter(x -> x.isSingleton()).findFirst(); + if (o.isPresent()) // FIXME: more general interval "merge"? + { + ivals = Stream.of(o.get()).collect(Collectors.toSet()); + } + return new RPIndexedRole(this.getLastElement(), ivals); + } + + // FIXME: currently just a syntactic singleton check on a single interval -- false negatives possible in general case (multiple intervals) + public boolean isSingleton() + { + /*if (this.intervals.size() != 1) + { + return false; + } + RPInterval ival = this.intervals.stream().findFirst().get(); + return ival.isSingleton();*/ + return this.intervals.stream().anyMatch(x -> x.isSingleton()); + } + + public Set getIndexVars() + { + return this.intervals.stream() + .flatMap(d -> Stream.of(d.start.getVars(), d.end.getVars()).flatMap(vs -> vs.stream())) + .collect(Collectors.toSet()); + } + + public RPInterval getParsedRange() + { + if (this.intervals.size() > 1) + { + throw new RuntimeException("[param-core] Shouldn't get in here: " + this.intervals); + } + return this.intervals.iterator().next(); + } + + // FIXME + public Role getName() + { + return new Role(this.getLastElement()); + } + + @Override + public String toString() + { + String rs = this.intervals.stream().map(Object::toString).collect(Collectors.joining(", ")); + if (this.intervals.size() > 1) + { + rs = "{" + rs + "}"; + } + return super.toString() + rs; + } + + @Override + public int hashCode() + { + int hash = 7121; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.intervals.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPIndexedRole)) + { + return false; + } + RPIndexedRole them = (RPIndexedRole) obj; + return super.equals(them) // Does canEqual + && this.intervals.equals(them.intervals); + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPIndexedRole; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPInterval.java b/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPInterval.java new file mode 100644 index 000000000..8f0eac9ae --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPInterval.java @@ -0,0 +1,89 @@ +package org.scribble.ext.go.core.type; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexVar; + +public class RPInterval +{ + /*public final ParamRoleParam start; + public final ParamRoleParam end; // Inclusive*/ + + public final RPIndexExpr start; + public final RPIndexExpr end; + + //public ParamRange(ParamRoleParam start, ParamRoleParam end) + public RPInterval(RPIndexExpr start, RPIndexExpr end) + { + this.start = start; + this.end = end; + } + + // FIXME: rename + public RPInterval minimise(int self) + { + return new RPInterval(this.start.minimise(self), this.end.minimise(self)); + } + + public Set getIndexVals() + { + return Stream.of(this.start, this.end).flatMap(p -> p.getVals().stream()).collect(Collectors.toSet()); + } + + //public Set getActualParams() // Hack + public Set getIndexVars() + { + //return Stream.of(this.start, this.end).filter(p -> !p.isConstant()).collect(Collectors.toSet()); + return Stream.of(this.start, this.end).flatMap(p -> p.getVars().stream()).collect(Collectors.toSet()); + } + + // FIXME: cf. equals -- this is to avoid awkwardness of RPInterval and RPAnnotatedInterval + // Althoug, also cf. "contains" -- currently "syntactic equality", generalise? + public boolean isSame(RPInterval i) + { + return this.start.equals(i.start) && this.end.equals(i.end); + } + + public boolean isSingleton() + { + return this.start.equals(this.end); + } + + @Override + public String toString() + { + return "[" + this.start + ((this.start.equals(this.end)) ? "" : "," + this.end) + "]"; + } + + @Override + public int hashCode() + { + int hash = 7151; + hash = 31 * hash + this.start.hashCode(); + hash = 31 * hash + this.end.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPInterval)) + { + return false; + } + RPInterval them = (RPInterval) obj; + return them.canEqual(this) && this.start.equals(them.start) && this.end.equals(them.end); + } + + public boolean canEqual(RPInterval o) + { + return o instanceof RPInterval; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPRoleVariant.java b/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPRoleVariant.java new file mode 100644 index 000000000..2b9b6c08d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/type/RPRoleVariant.java @@ -0,0 +1,98 @@ +package org.scribble.ext.go.core.type; + +import java.util.Collections; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.type.index.RPIndexVar; + +public class RPRoleVariant extends RPIndexedRole +{ + /** + * + */ + private static final long serialVersionUID = 1L; + + public final Set cointervals; + + public RPRoleVariant(String name, Set ranges, Set coranges) + { + super(name, ranges); + this.cointervals = Collections.unmodifiableSet(coranges); + } + + // self is irrelevant -- variants don't contain self + @Override + public RPRoleVariant minimise(int self) + { + Set ivals = this.intervals.stream().map(x -> x.minimise(self)).collect(Collectors.toSet()); + Optional o = ivals.stream().filter(x -> x.isSingleton()).findFirst(); + if (o.isPresent()) // FIXME: more general interval "merge"? + { + ivals = Stream.of(o.get()).collect(Collectors.toSet()); + return new RPRoleVariant(this.getLastElement(), ivals, Collections.emptySet()); + } + Set coivals = this.cointervals.stream().map(x -> x.minimise(self)).collect(Collectors.toSet()); + return new RPRoleVariant(this.getLastElement(), ivals, coivals); + } + + /*@Override + public boolean isSingleton() + { + return super.isSingleton(); + }*/ + + @Override + public Set getIndexVars() + { + Set ivars = super.getIndexVars(); + ivars.addAll(this.cointervals.stream() + .flatMap(d -> Stream.of(d.start.getVars(), d.end.getVars()).flatMap(vs -> vs.stream())) + .collect(Collectors.toSet())); + return ivars; + } + + @Override + public String toString() + { + // Duplicated from super to make rs1 braces mandatory + String rs1 = "{" + this.intervals.stream().map(Object::toString).collect(Collectors.joining(", ")) + "}"; + String rs2 = this.cointervals.isEmpty() + ? "" + : "{" + this.cointervals.stream().map(Object::toString).collect(Collectors.joining(", ")) + "}"; + return super.getLastElement() + rs1 + rs2; + } + + @Override + public int hashCode() + { + int hash = 7193; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.cointervals.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (!(obj instanceof RPRoleVariant)) + { + return false; + } + RPRoleVariant them = (RPRoleVariant) obj; + return super.equals(them) // Does canEqual + && this.cointervals.equals(them.cointervals); + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPRoleVariant; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/type/name/RPCoreGDelegationType.java b/scribble-go/src/main/java/org/scribble/ext/go/core/type/name/RPCoreGDelegationType.java new file mode 100644 index 000000000..ab43d18eb --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/type/name/RPCoreGDelegationType.java @@ -0,0 +1,81 @@ +package org.scribble.ext.go.core.type.name; + +import org.scribble.ext.go.core.type.RPRoleVariant; +import org.scribble.type.name.GDelegationType; +import org.scribble.type.name.GProtocolName; + +public class RPCoreGDelegationType extends GDelegationType +{ + private static final long serialVersionUID = 1L; + + protected GProtocolName state; // Cf. RPGDelegationElem + + // super.proto used for root + public RPCoreGDelegationType(GProtocolName root, GProtocolName state, RPRoleVariant v) + { + super(root, v); + this.state = state; + } + + public GProtocolName getRoot() + { + return getGlobalProtocol(); + } + + public GProtocolName getState() + { + return this.state; + } + + public RPRoleVariant getVariant() + { + return (RPRoleVariant) this.role; + } + + @Override + public String toString() + { + return this.proto + ":" + this.state + "@" + this.role; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPCoreGDelegationType)) + { + return false; + } + RPCoreGDelegationType them = (RPCoreGDelegationType) o; + return them.canEqual(this) && super.equals(o) && this.state.equals(them.state); + } + + public boolean canEqual(Object o) + { + return o instanceof RPCoreGDelegationType; + } + + @Override + public int hashCode() + { + int hash = 6673; + hash = 31 * super.hashCode(); + hash = 31 * this.state.hashCode(); + return hash; + } + + /*private void writeObject(java.io.ObjectOutputStream out) throws IOException + { + out.writeObject(this.proto); + out.writeObject(this.role); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException + { + this.proto = (GProtocolName) in.readObject(); + this.role = (Role) in.readObject(); + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/core/visit/RPCoreIndexVarCollector.java b/scribble-go/src/main/java/org/scribble/ext/go/core/visit/RPCoreIndexVarCollector.java new file mode 100644 index 000000000..11a688b38 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/core/visit/RPCoreIndexVarCollector.java @@ -0,0 +1,91 @@ +package org.scribble.ext.go.core.visit; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.scribble.ast.ScribNode; +import org.scribble.del.ScribDel; +import org.scribble.ext.go.ast.RPDel; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.main.Job; +import org.scribble.main.ScribbleException; +import org.scribble.visit.NoEnvInlinedProtocolVisitor; + +// FIXME: move out of Core to main RP -- currently not actually used (due to RPCoreType), but eventually should be used on locals +// Currently done for globals (e.g., RPGMessageTransferDel), but should be on locals +// Duplicated from EGraphBuilder +public class RPCoreIndexVarCollector extends NoEnvInlinedProtocolVisitor +{ + private final Set ivars = new HashSet<>(); + + public RPCoreIndexVarCollector(Job job) + { + super(job); + } + + public void clear() + { + this.ivars.clear(); + } + + public void addIndexVars(Collection ivars) + { + this.ivars.addAll(ivars); + } + + public Set getIndexVars() + { + return new HashSet<>(this.ivars); + } + + /*// Override visitInlinedProtocol -- not visit, or else enter/exit is lost + @Override + public ScribNode visitInlinedProtocol(ScribNode parent, ScribNode child) throws ScribbleException + { + if (child instanceof LInteractionSeq) + { + return visitOverrideForLInteractionSeq((LProtocolBlock) parent, (LInteractionSeq) child); + } + else if (child instanceof LChoice) + { + return visitOverrideForLChoice((LInteractionSeq) parent, (LChoice) child); + } + else + { + return super.visitInlinedProtocol(parent, child); + } + } + + protected LInteractionSeq visitOverrideForLInteractionSeq(LProtocolBlock parent, LInteractionSeq child) throws ScribbleException + { + return ((LInteractionSeqDel) child.del()).visitForFsmConversion(this, child); + } + + protected LChoice visitOverrideForLChoice(LInteractionSeq parent, LChoice child) + { + return ((LChoiceDel) child.del()).visitForFsmConversion(this, child); + }*/ + + @Override + protected final void inlinedEnter(ScribNode parent, ScribNode child) throws ScribbleException + { + super.inlinedEnter(parent, child); + ScribDel del = child.del(); + if (del instanceof RPDel) + { + ((RPDel) child.del()).enterIndexVarCollection(parent, child, this); + } + } + + @Override + protected ScribNode inlinedLeave(ScribNode parent, ScribNode child, ScribNode visited) throws ScribbleException + { + ScribDel del = visited.del(); + if (del instanceof RPDel) + { + visited = ((RPDel) visited.del()).leaveIndexVarCollection(parent, child, this, visited); + } + return super.inlinedLeave(parent, child, visited); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/del/RPForeachDel.java b/scribble-go/src/main/java/org/scribble/ext/go/del/RPForeachDel.java new file mode 100644 index 000000000..b059f7a50 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/del/RPForeachDel.java @@ -0,0 +1,112 @@ +package org.scribble.ext.go.del; + +import org.scribble.ast.ScribNode; +import org.scribble.del.CompoundInteractionNodeDel; +import org.scribble.ext.go.ast.RPDel; +import org.scribble.ext.go.ast.RPForeach; +import org.scribble.main.ScribbleException; +import org.scribble.visit.InlinedProtocolUnfolder; +import org.scribble.visit.env.UnfoldingEnv; + +// Based on ChoiceDecl +public class RPForeachDel extends CompoundInteractionNodeDel implements RPDel +{ + /*// Role names not disambiguated? + @Override + public void enterDisambiguation(ScribNode parent, ScribNode child, NameDisambiguator disamb) throws ScribbleException + { + Recursion rec = (Recursion) child; + RecVar rv = rec.recvar.toName(); + //disamb.addRecVar(rv); + disamb.pushRecVar(rv); + } + + @Override + public ScribNode leaveDisambiguation(ScribNode parent, ScribNode child, NameDisambiguator disamb, ScribNode visited) throws ScribbleException + { + RecVar rv = ((Recursion) child).recvar.toName(); // visited may be already name mangled // Not any more (refactored to inlining) + disamb.popRecVar(rv); + return rec; + }*/ + + /*@Override // No special inlining behaviour for Foreach -- just visitChildren + public void enterProtocolInlining(ScribNode parent, ScribNode child, ProtocolDefInliner inliner) throws ScribbleException + { + super.enterProtocolInlining(parent, child, inliner); + RPForeach rec = (RPForeach) child; + inliner.pushRecVar(rec.recvar.toName()); + } + + @Override + public ScribNode leaveProtocolInlining(ScribNode parent, ScribNode child, ProtocolDefInliner inliner, ScribNode visited) throws ScribbleException + { + //Recursion rec = (Recursion) visited; + RecVar origRV = ((Recursion) child).recvar.toName(); // visited may be already name mangled + inliner.popRecVar(origRV); + return super.leaveProtocolInlining(parent, child, inliner, visited); + }*/ + + /*// Anything special needed? + @Override + public void enterInlinedProtocolUnfolding(ScribNode parent, ScribNode child, InlinedProtocolUnfolder unf) throws ScribbleException + { + super.enterInlinedProtocolUnfolding(parent, child, unf); + Recursion lr = (Recursion) child; + RecVar recvar = lr.recvar.toName(); + unf.setRecVar(unf.job.af, recvar, lr); // Cloned on use (on continue) + + UnfoldingEnv env = unf.peekEnv().enterContext(); + env = env.pushChoiceParent(); // Above is already a copy, but fine + unf.pushEnv(env); + }*/ + + @Override + public RPForeach leaveInlinedProtocolUnfolding(ScribNode parent, ScribNode child, InlinedProtocolUnfolder unf, ScribNode visited) throws ScribbleException + { + RPForeach fe = (RPForeach) visited; + UnfoldingEnv merged = unf.popEnv().mergeContext((UnfoldingEnv) fe.block.del().env()); // Merge child into current... + unf.pushEnv(merged); + return (RPForeach) super.leaveInlinedProtocolUnfolding(parent, child, unf, fe); // ...super merges current into parent + + /*Choice cho = (Choice) visited; + List benvs = + cho.getBlocks().stream().map(b -> (UnfoldingEnv) b.del().env()).collect(Collectors.toList()); + UnfoldingEnv merged = unf.popEnv().mergeContexts(benvs); + unf.pushEnv(merged); + return (Choice) super.leaveInlinedProtocolUnfolding(parent, child, unf, visited); // Done merge of children here, super does merge into parent*/ + } + + /*@Override + public ScribNode leaveIndexVarCollection(ScribNode parent, ScribNode child, RPCoreIndexVarCollector coll, ScribNode visited) throws ScribbleException + { + ... // cf. RPCoreGForeach#getIndexedRoles + Set d = Stream.of(new RPInterval(this.start, this.end)).collect(Collectors.toSet()); + Set var = Stream.of(new RPInterval(this.var, this.var)).collect(Collectors.toSet()); + Set irs = this.body.getIndexedRoles() + .stream().map( + ir -> ir.intervals.equals(var) + ? new RPIndexedRole(ir.getName().toString(), d) + : ir + ).collect(Collectors.toSet()); + return irs; + }*/ + + /*// Needed? -- how about Recursion? + @Override + public void enterExplicitCorrelationCheck(ScribNode parent, ScribNode child, ExplicitCorrelationChecker checker) throws ScribbleException + { + ExplicitCorrelationEnv env = checker.peekEnv().enterContext(); + checker.pushEnv(env); + } + + @Override + public Choice leaveExplicitCorrelationCheck(ScribNode parent, ScribNode child, ExplicitCorrelationChecker checker, ScribNode visited) throws ScribbleException + { + Choice cho = (Choice) visited; + List benvs = + cho.getBlocks().stream().map((b) -> (ExplicitCorrelationEnv) b.del().env()).collect(Collectors.toList()); + ExplicitCorrelationEnv merged = checker.popEnv().mergeContexts(benvs); + checker.pushEnv(merged); + return (Choice) super.leaveExplicitCorrelationCheck(parent, child, checker, visited); // Done merge of children here, super does merge into parent + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGChoiceDel.java b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGChoiceDel.java new file mode 100644 index 000000000..e8a69e835 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGChoiceDel.java @@ -0,0 +1,45 @@ +package org.scribble.ext.go.del.global; + +import java.util.List; +import java.util.stream.Collectors; + +import org.scribble.ast.ScribNode; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDelBase; +import org.scribble.del.global.GChoiceDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.RPDel; +import org.scribble.ext.go.ast.global.RPGChoice; +import org.scribble.ext.go.core.visit.RPCoreIndexVarCollector; +import org.scribble.main.ScribbleException; +import org.scribble.visit.ProtocolDefInliner; +import org.scribble.visit.env.InlineProtocolEnv; + +public class RPGChoiceDel extends GChoiceDel implements RPDel +{ + @Override + public ScribNode leaveProtocolInlining(ScribNode parent, ScribNode child, ProtocolDefInliner inl, ScribNode visited) throws ScribbleException + { + RPGChoice gc = (RPGChoice) visited; + List blocks = gc.getBlocks().stream() + .map(b -> (GProtocolBlock) ((InlineProtocolEnv) b.del().env()).getTranslation()).collect(Collectors.toList()); + RoleNode subj = gc.subj.clone(inl.job.af); + + RPGChoice inlined = ((RPAstFactory) inl.job.af).ParamGChoice(gc.getSource(), subj, gc.expr, blocks); + + inl.pushEnv(inl.popEnv().setTranslation(inlined)); + + //return (GChoice) super.leaveProtocolInlining(parent, child, inl, gc); + return ScribDelBase.popAndSetVisitorEnv(this, inl, visited); + } + + // FIXME: not really needed for global? -- should be local + @Override + public ScribNode leaveIndexVarCollection(ScribNode parent, ScribNode child, RPCoreIndexVarCollector coll, ScribNode visited) throws ScribbleException + { + RPGChoice c = (RPGChoice) visited; + coll.addIndexVars(c.expr.getVars()); // FIXME: subject should be PRIndexedRole, currently index expr is separate from RoleNode + return visited; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGDelegationElemDel.java b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGDelegationElemDel.java new file mode 100644 index 000000000..21e7e251c --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGDelegationElemDel.java @@ -0,0 +1,60 @@ +/** + * Copyright 2008 The Scribble Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.scribble.ext.go.del.global; + +import org.scribble.ast.ProtocolDecl; +import org.scribble.ast.context.ModuleContext; +import org.scribble.ast.global.GDelegationElem; +import org.scribble.ast.name.qualified.GProtocolNameNode; +import org.scribble.del.global.GDelegationElemDel; +import org.scribble.ext.go.ast.global.RPGDelegationElem; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.Global; +import org.scribble.type.name.GProtocolName; +import org.scribble.type.name.Role; +import org.scribble.visit.wf.NameDisambiguator; + +public class RPGDelegationElemDel extends GDelegationElemDel +{ + public RPGDelegationElemDel() + { + + } + + // Duplicated from super + @Override + public RPGDelegationElem visitForNameDisambiguation(NameDisambiguator disamb, GDelegationElem de) throws ScribbleException + { + ModuleContext mc = disamb.getModuleContext(); + GProtocolName rootfullname = (GProtocolName) mc.getVisibleProtocolDeclFullName(de.proto.toName()); + + Role rn = de.role.toName(); + ProtocolDecl gpd = disamb.job.getContext().getModule(rootfullname.getPrefix()).getProtocolDecl(rootfullname.getSimpleName()); + if (!gpd.header.roledecls.getRoles().contains(rn)) + { + String tmp = rn.toString(); // FIXME HACK (currently rely on checking valid variant later) + if (tmp.indexOf("_") == -1) + { + throw new ScribbleException(de.role.getSource(), "Invalid delegation role: " + de); + } + } + + RPGDelegationElem rpde = (RPGDelegationElem) de; + GProtocolName statefullname = (GProtocolName) mc.getVisibleProtocolDeclFullName(rpde.state.toName()); + GProtocolNameNode root = (GProtocolNameNode) disamb.job.af.QualifiedNameNode(rpde.proto.getSource(), rootfullname.getKind(), rootfullname.getElements()); // Not keeping original namenode del + GProtocolNameNode state = (GProtocolNameNode) disamb.job.af.QualifiedNameNode(rpde.state.getSource(), statefullname.getKind(), statefullname.getElements()); // Not keeping original namenode del + + return (RPGDelegationElem) rpde.reconstruct(root, state, de.role); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGForeachDel.java b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGForeachDel.java new file mode 100644 index 000000000..afad74c6f --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGForeachDel.java @@ -0,0 +1,30 @@ +package org.scribble.ext.go.del.global; + +import java.util.List; +import java.util.stream.Collectors; + +import org.scribble.ast.ScribNode; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDelBase; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.global.RPGForeach; +import org.scribble.ext.go.del.RPForeachDel; +import org.scribble.main.ScribbleException; +import org.scribble.visit.ProtocolDefInliner; +import org.scribble.visit.env.InlineProtocolEnv; + +public class RPGForeachDel extends RPForeachDel +{ + @Override + public ScribNode leaveProtocolInlining(ScribNode parent, ScribNode child, ProtocolDefInliner inlr, ScribNode visited) throws ScribbleException + { + RPGForeach fe = (RPGForeach) visited; + List subjs = fe.subjs.stream().map(r -> r.clone(inlr.job.af)).collect(Collectors.toList()); + GProtocolBlock block = (GProtocolBlock) ((InlineProtocolEnv) fe.block.del().env()).getTranslation(); + RPGForeach inlined = ((RPAstFactory) inlr.job.af).RPGForeach(fe.getSource(), subjs, fe.params, fe.starts, fe.ends, block); + inlr.pushEnv(inlr.popEnv().setTranslation(inlined)); + //return (GChoice) super.leaveProtocolInlining(parent, child, inl, gc); + return ScribDelBase.popAndSetVisitorEnv(this, inlr, visited); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGMessageTransferDel.java b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGMessageTransferDel.java new file mode 100644 index 000000000..d8e6a945b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGMessageTransferDel.java @@ -0,0 +1,47 @@ +package org.scribble.ext.go.del.global; + +import java.util.List; + +import org.scribble.ast.ScribNode; +import org.scribble.ast.global.GMessageTransfer; +import org.scribble.del.global.GMessageTransferDel; +import org.scribble.ext.go.ast.RPDel; +import org.scribble.ext.go.ast.global.RPGMessageTransfer; +import org.scribble.ext.go.core.visit.RPCoreIndexVarCollector; +import org.scribble.main.ScribbleException; +import org.scribble.type.name.Role; +import org.scribble.visit.wf.NameDisambiguator; + +public class RPGMessageTransferDel extends GMessageTransferDel implements RPDel +{ + public RPGMessageTransferDel() + { + + } + + @Override + public ScribNode leaveDisambiguation(ScribNode parent, ScribNode child, NameDisambiguator disamb, ScribNode visited) throws ScribbleException + { + GMessageTransfer gmt = (GMessageTransfer) visited; + Role src = gmt.src.toName(); + List dests = gmt.getDestinationRoles(); + if (dests.contains(src)) + { + // FIXME TODO + //throw new ScribbleException(gmt.getSource(), "[TODO] Self connections not supported: " + gmt); // Would currently be subsumed by unconnected check + } + return gmt; + } + + // FIXME: not needed for global -- should be local + @Override + public ScribNode leaveIndexVarCollection(ScribNode parent, ScribNode child, RPCoreIndexVarCollector coll, ScribNode visited) throws ScribbleException + { + RPGMessageTransfer mt = (RPGMessageTransfer) visited; + coll.addIndexVars(mt.srcRangeStart.getVars()); + coll.addIndexVars(mt.srcRangeEnd.getVars()); + coll.addIndexVars(mt.destRangeStart.getVars()); + coll.addIndexVars(mt.destRangeEnd.getVars()); + return visited; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGMultiChoicesDel.java b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGMultiChoicesDel.java new file mode 100644 index 000000000..aa1fe682a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/del/global/RPGMultiChoicesDel.java @@ -0,0 +1,35 @@ +package org.scribble.ext.go.del.global; + +import java.util.List; +import java.util.stream.Collectors; + +import org.scribble.ast.ScribNode; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.del.ScribDelBase; +import org.scribble.del.global.GChoiceDel; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.global.RPGMultiChoices; +import org.scribble.main.ScribbleException; +import org.scribble.visit.ProtocolDefInliner; +import org.scribble.visit.env.InlineProtocolEnv; + +public class RPGMultiChoicesDel extends GChoiceDel +{ + @Override + public ScribNode leaveProtocolInlining(ScribNode parent, ScribNode child, ProtocolDefInliner inl, ScribNode visited) throws ScribbleException + { + RPGMultiChoices gc = (RPGMultiChoices) visited; + List blocks = gc.getBlocks().stream() + .map(b -> (GProtocolBlock) ((InlineProtocolEnv) b.del().env()).getTranslation()).collect(Collectors.toList()); + RoleNode subj = gc.subj.clone(inl.job.af); + + RPGMultiChoices inlined = ((RPAstFactory) inl.job.af).ParamGMultiChoices(gc.getSource(), subj, + gc.var, gc.start, gc.end, blocks); + + inl.pushEnv(inl.popEnv().setTranslation(inlined)); + + //return (GChoice) super.leaveProtocolInlining(parent, child, inl, gc); + return ScribDelBase.popAndSetVisitorEnv(this, inl, visited); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/main/GoJob.java b/scribble-go/src/main/java/org/scribble/ext/go/main/GoJob.java new file mode 100644 index 000000000..925ab8c93 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/main/GoJob.java @@ -0,0 +1,72 @@ +package org.scribble.ext.go.main; + +import java.util.Map; + +import org.scribble.ast.AstFactory; +import org.scribble.ast.Module; +import org.scribble.main.Job; +import org.scribble.model.endpoint.EModelFactory; +import org.scribble.model.global.SModelFactory; +import org.scribble.type.name.ModuleName; + +public class GoJob extends Job +{ + public final boolean selectApi; + public final boolean noCopy; + public final boolean parForeach; + + public GoJob(boolean debug, Map parsed, ModuleName main, + boolean useOldWF, boolean noLiveness, boolean minEfsm, boolean fair, boolean noLocalChoiceSubjectCheck, + boolean noAcceptCorrelationCheck, boolean noValidation, + AstFactory af, EModelFactory ef, SModelFactory sf, boolean noCopy, boolean selectApi, boolean parForeach) + { + super(debug, parsed, main, useOldWF, noLiveness, minEfsm, fair, noLocalChoiceSubjectCheck, noAcceptCorrelationCheck, noValidation, af, ef, sf); + this.noCopy = noCopy; + this.selectApi = selectApi; + this.parForeach = parForeach; + } + + /*// FIXME: move to MainContext::newJob? + @Override + public ParamEGraphBuilderUtil newEGraphBuilderUtil() + { + return new ParamEGraphBuilderUtil((ParamEModelFactory) this.ef); + } + + @Override + public void runContextBuildingPasses() throws ScribbleException + { + runVisitorPassOnAllModules(ModuleContextBuilder.class); + + runVisitorPassOnAllModules(ParamNameDisambiguator.class); // FIXME: factor out overriding pattern? + + runVisitorPassOnAllModules(ProtocolDeclContextBuilder.class); + runVisitorPassOnAllModules(DelegationProtocolRefChecker.class); + runVisitorPassOnAllModules(RoleCollector.class); + runVisitorPassOnAllModules(ProtocolDefInliner.class); + } + + @Override + public void runUnfoldingPass() throws ScribbleException + { + //runVisitorPassOnAllModules(ParamInlinedProtocolUnfolder.class); // FIXME: skipping for now + } + + @Override + protected void runProjectionUnfoldingPass() throws ScribbleException + { + //runVisitorPassOnProjectedModules(ParamInlinedProtocolUnfolder.class); // FIXME + } + + @Override + public void runWellFormednessPasses() throws ScribbleException + { + super.runWellFormednessPasses(); + + // Additional + if (!this.noValidation) + { + runVisitorPassOnAllModules(ParamAnnotationChecker.class); + } + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/main/GoMainContext.java b/scribble-go/src/main/java/org/scribble/ext/go/main/GoMainContext.java new file mode 100644 index 000000000..3b1982bd7 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/main/GoMainContext.java @@ -0,0 +1,27 @@ +package org.scribble.ext.go.main; + +import java.nio.file.Path; + +import org.scribble.main.MainContext; +import org.scribble.main.ScribbleException; +import org.scribble.main.resource.ResourceLocator; +import org.scribble.util.ScribParserException; + +public class GoMainContext extends MainContext +{ + // Load main module from file system + public GoMainContext(boolean debug, ResourceLocator locator, Path mainpath, boolean useOldWF, boolean noLiveness, boolean minEfsm, + boolean fair, boolean noLocalChoiceSubjectCheck, boolean noAcceptCorrelationCheck, boolean noValidation) + throws ScribParserException, ScribbleException + { + super(debug, locator, mainpath, useOldWF, noLiveness, minEfsm, fair, noLocalChoiceSubjectCheck, noAcceptCorrelationCheck, noValidation); + } + + @Override + public GoJob newJob() + { + return new GoJob(this.debug, this.getParsedModules(), this.main, this.useOldWF, this.noLiveness, this.minEfsm, this.fair, + this.noLocalChoiceSubjectCheck, this.noAcceptCorrelationCheck, this.noValidation, + this.af, this.ef, this.sf, false, false, false); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/RPAntlrToScribParser.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/RPAntlrToScribParser.java new file mode 100644 index 000000000..11e1f9024 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/RPAntlrToScribParser.java @@ -0,0 +1,80 @@ +package org.scribble.ext.go.parser.scribble; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.ScribNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.parser.scribble.ast.RPAntlrPayloadElemList; +import org.scribble.ext.go.parser.scribble.ast.RPCoreAntlrModule; +import org.scribble.ext.go.parser.scribble.ast.global.RPAntlrGChoice; +import org.scribble.ext.go.parser.scribble.ast.global.RPAntlrGCrossMessageTransfer; +import org.scribble.ext.go.parser.scribble.ast.global.RPAntlrGDotMessageTransfer; +import org.scribble.ext.go.parser.scribble.ast.global.RPAntlrGProtocolDecl; +import org.scribble.ext.go.parser.scribble.ast.global.RPAntlrGProtocolHeader; +import org.scribble.ext.go.parser.scribble.ast.global.RPCoreAntlrGForeach; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.ScribbleAntlrConstants; +import org.scribble.util.ScribParserException; + +public class RPAntlrToScribParser extends AntlrToScribParser +{ + // FIXME: refactor constants following ScribbleAntlrConstants/AntlrToScribParserUtil? -- cannot extend existing node type enum though + public static final String PARAM_ROLEDECL_NODE_TYPE = "PARAM_ROLEDECL"; + public static final String PARAM_GLOBALCROSSMESSAGETRANSFER_NODE_TYPE = "PARAM_GLOBALCROSSMESSAGETRANSFER"; + public static final String PARAM_GLOBALDOTMESSAGETRANSFER_NODE_TYPE = "PARAM_GLOBALDOTMESSAGETRANSFER"; + public static final String PARAM_GLOBALCHOICE_NODE_TYPE = "PARAM_GLOBALCHOICE"; + /*public static final String PARAM_GLOBALMULTICHOICES_NODE_TYPE = "PARAM_GLOBALMULTICHOICES"; + public static final String PARAM_GLOBALMULTICHOICESTRANSFER_NODE_TYPE = "PARAM_GLOBALMULTICHOICESTRANSFER";*/ + public static final String PARAM_DELEGDECL_NODE_TYPE = "PARAM_DELEGDECL"; + public static final String PARAM_GLOBALFOREACH = "PARAM_GLOBALFOREACH"; + + public static final String PARAM_DELEGATION = "PARAM_DELEGATION"; + + public static final String PARAM_GLOBALPROTOCOLHEADER = "PARAM_GLOBALPROTOCOLHEADER"; + + public RPAntlrToScribParser() + { + + } + + @Override + public ScribNode parse(CommonTree ct, AstFactory af) throws ScribParserException + { + AntlrToScribParser.checkForAntlrErrors(ct); + + RPAstFactory aaf = (RPAstFactory) af; + String type = ct.getToken().getText(); // Duplicated from ScribParserUtil.getAntlrNodeType // FIXME: factor out with ParamAntlrPayloadElemList.parsePayloadElem + switch (type) + { + // "Overrides" + case ScribbleAntlrConstants.MODULE_NODE_TYPE: + return RPCoreAntlrModule.parseModule(this, ct, af); + case ScribbleAntlrConstants.PAYLOAD_NODE_TYPE: + return RPAntlrPayloadElemList.parsePayloadElemList(this, ct, af); + /*case ScribbleAntlrConstants.GLOBALPROTOCOLDECL_NODE_TYPE: + return RPAntlrGProtocolDecl.parseGPrototocolDecl(this, ct, af);*/ + + + // "Extensions" + //case PARAM_ROLEDECL_NODE_TYPE: return RPAntlrRoleDecl.parseParamRoleDecl(this, ct, aaf); + case PARAM_GLOBALCROSSMESSAGETRANSFER_NODE_TYPE: + return RPAntlrGCrossMessageTransfer.parseParamGCrossMessageTransfer(this, ct, aaf); + case PARAM_GLOBALDOTMESSAGETRANSFER_NODE_TYPE: + return RPAntlrGDotMessageTransfer.parseParamGDotMessageTransfer(this, ct, aaf); + case PARAM_GLOBALCHOICE_NODE_TYPE: + return RPAntlrGChoice.parseParamGChoice(this, ct, aaf); + /*case PARAM_GLOBALMULTICHOICES_NODE_TYPE: + return RPAntlrGMultiChoices.parseParamGMultiChoices(this, ct, aaf); + case PARAM_GLOBALMULTICHOICESTRANSFER_NODE_TYPE: + return RPAntlrGMultiChoicesTransfer.parseParamGMultiChoicesTransfer(this, ct, aaf);*/ + case PARAM_GLOBALFOREACH: + return RPCoreAntlrGForeach.parseRPGForeach(this, ct, aaf); + /*case PARAM_DELEGDECL_NODE_TYPE: // FIXME: deprecate + return RPCoreAntlrDelegDecl.parseDelegDecl(this, ct, aaf);*/ + case PARAM_GLOBALPROTOCOLHEADER: + return RPAntlrGProtocolHeader.parseGProtocolHeader(this, ct, aaf); + + default: return super.parse(ct, af); + } + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/RPScribbleAntlrWrapper.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/RPScribbleAntlrWrapper.java new file mode 100644 index 000000000..d3689a35b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/RPScribbleAntlrWrapper.java @@ -0,0 +1,26 @@ +package org.scribble.ext.go.parser.scribble; + +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.Lexer; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.CommonTree; +import org.scribble.parser.antlr.ParamScribbleLexer; +import org.scribble.parser.antlr.ParamScribbleParser; +import org.scribble.parser.scribble.ScribbleAntlrWrapper; + +public class RPScribbleAntlrWrapper extends ScribbleAntlrWrapper +{ + + @Override + protected Lexer getScribbleLexer(ANTLRStringStream ass) + { + return new ParamScribbleLexer(ass); + } + + @Override + protected CommonTree runScribbleParser(CommonTokenStream cts) throws RecognitionException + { + return (CommonTree) new ParamScribbleParser(cts).module().getTree(); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPAntlrPayloadElemList.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPAntlrPayloadElemList.java new file mode 100644 index 000000000..98185602a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPAntlrPayloadElemList.java @@ -0,0 +1,71 @@ +/** + * Copyright 2008 The Scribble Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.scribble.ext.go.parser.scribble.ast; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.PayloadElem; +import org.scribble.ast.PayloadElemList; +import org.scribble.ast.name.qualified.GProtocolNameNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.AntlrToScribParserUtil; +import org.scribble.parser.scribble.ast.AntlrPayloadElemList; +import org.scribble.parser.scribble.ast.name.AntlrQualifiedName; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; + +// Duplicated from AntlrPayloadElemList +public class RPAntlrPayloadElemList +{ + // Cf. AntlrNonRoleArgList + public static PayloadElemList parsePayloadElemList(AntlrToScribParser parser, CommonTree ct, AstFactory af) + { + List> pes = getPayloadElements(ct).stream().map(pe -> parsePayloadElem(pe, af)).collect(Collectors.toList()); + return af.PayloadElemList(ct, pes); + } + + //private static PayloadElem parsePayloadElem(CommonTree ct) + public static PayloadElem parsePayloadElem(CommonTree ct, AstFactory af) + { + String type = ct.getToken().getText(); // FIXME from AntlrToScribParser#getAntlrNodeType + switch (type) + { + case "PARAM_DELEGATION": + { + // Duplicated from AntlrPayloadElemList.parsePayloadElem + RoleNode rn = AntlrSimpleName.toRoleNode((CommonTree) ct.getChild(0), af); // FIXME: factor out constants + GProtocolNameNode root = AntlrQualifiedName.toGProtocolNameNode((CommonTree) ct.getChild(1), af); + CommonTree tmp = (CommonTree) ct.getChild(2); + GProtocolNameNode state = (tmp != null) + ? AntlrQualifiedName.toGProtocolNameNode(tmp, af) + : root; + return ((RPAstFactory) af).RPGDelegationElem(ct, root, state, rn); + } + + default: return AntlrPayloadElemList.parsePayloadElem(ct, af); + } + } + + public static final List getPayloadElements(CommonTree ct) + { + return (ct.getChildCount() == 0) + ? Collections.emptyList() + : AntlrToScribParserUtil.toCommonTreeList(ct.getChildren()); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPAntlrRoleDecl.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPAntlrRoleDecl.java new file mode 100644 index 000000000..6e7b7c2dc --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPAntlrRoleDecl.java @@ -0,0 +1,51 @@ +package org.scribble.ext.go.parser.scribble.ast; + +import java.util.List; +import java.util.stream.Collectors; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.RoleDecl; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.parser.scribble.AntlrToScribParser; + +@Deprecated +public class RPAntlrRoleDecl +{ + // Same as original + public static final int NAME_CHILD_INDEX = 0; + + public static final int PARAM_CHILDREN_START_INDEX = 1; + + public static RoleDecl parseParamRoleDecl(AntlrToScribParser parser, CommonTree root, RPAstFactory af) + { + /*RoleNode name = AntlrSimpleName.toRoleNode(getNameChild(root), af); + /*List params = getParamChildren(root) + .stream().map(p -> ParamAntlrSimpleName.toParamRoleParamNode(p, af)).collect(Collectors.toList());* / + List params = getParamChildren(root) + .stream().map(p -> RPIndexFactory.ParamIntVar(p.getText())).collect(Collectors.toList()); + return af.ParamRoleDecl(root, name, params);*/ + return null; + } + + public static CommonTree getNameChild(CommonTree root) + { + return (CommonTree) root.getChild(NAME_CHILD_INDEX); + } + + // FIXME: deprecate + public static List getParamChildren(CommonTree root) + { + List children = root.getChildren(); + return children.subList(PARAM_CHILDREN_START_INDEX, children.size()).stream().map(c -> (CommonTree) c).collect(Collectors.toList()); + } + + /*public static int getStartIndex(CommonTree root) + { + return Integer.parseInt(root.getChild(START_CHILD_INDEX).getText()); + } + + public static int getEndIndex(CommonTree root) + { + return Integer.parseInt(root.getChild(END_CHILD_INDEX).getText()); + }*/ +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPCoreAntlrDelegDecl.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPCoreAntlrDelegDecl.java new file mode 100644 index 000000000..fdeb05e47 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPCoreAntlrDelegDecl.java @@ -0,0 +1,33 @@ +package org.scribble.ext.go.parser.scribble.ast; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.name.qualified.DataTypeNode; +import org.scribble.ext.go.core.ast.RPCoreDelegDecl; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.ast.AntlrDataTypeDecl; +import org.scribble.parser.scribble.ast.AntlrExtIdentifier; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; + +// FIXME: should be RPDelegDecl (not Core, a "full" AST (Antlr) node) +// Duplicated from AntlrDataTypeDecl +public class RPCoreAntlrDelegDecl +{ + public static final int SCHEMA_CHILD_INDEX = 0; + public static final int EXTNAME_CHILD_INDEX = 1; + public static final int SOURCE_CHILD_INDEX = 2; + public static final int ALIAS_CHILD_INDEX = 3; + + public static RPCoreDelegDecl parseDelegDecl(AntlrToScribParser parser, CommonTree ct, AstFactory af) + { + CommonTree tmp1 = AntlrDataTypeDecl.getSchemaChild(ct); + String schema = AntlrSimpleName.getName(tmp1); + CommonTree tmp2 = AntlrDataTypeDecl.getExtNameChild(ct); + String extName = AntlrExtIdentifier.getName(tmp2); + CommonTree tmp3 = AntlrDataTypeDecl.getSourceChild(ct); + String source = AntlrExtIdentifier.getName(tmp3); + DataTypeNode alias = AntlrSimpleName.toDataTypeNameNode(AntlrDataTypeDecl.getAliasChild(ct), af); // FIXME: EMTPY_ALIAS? + //return ((RPAstFactory) af).ParamCoreDelegDecl(ct, schema, extName, source, alias); + throw new RuntimeException("Shouldn't get here: " + ct); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPCoreAntlrModule.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPCoreAntlrModule.java new file mode 100644 index 000000000..3bae965ec --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/RPCoreAntlrModule.java @@ -0,0 +1,82 @@ +package org.scribble.ext.go.parser.scribble.ast; + +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.ImportDecl; +import org.scribble.ast.Module; +import org.scribble.ast.ModuleDecl; +import org.scribble.ast.NonProtocolDecl; +import org.scribble.ast.ProtocolDecl; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.AntlrToScribParserUtil; +import org.scribble.parser.scribble.ScribbleAntlrConstants; +import org.scribble.parser.scribble.ast.AntlrModule; +import org.scribble.util.ScribParserException; + +public class RPCoreAntlrModule +{ + // Duplicated from AntlrModule + public static Module parseModule(AntlrToScribParser parser, CommonTree ct, AstFactory af) throws ScribParserException + { + ModuleDecl md = (ModuleDecl) parser.parse(AntlrModule.getModuleDeclChild(ct), af); + List> ids = new LinkedList<>(); + List> ptds = new LinkedList<>(); + List> pds = new LinkedList<>(); + for (CommonTree id : getImportDeclChildren(ct)) + { + ImportDecl tmp = (ImportDecl) parser.parse(id, af); + ids.add(tmp); + } + for (CommonTree ptd : getDataTypeDeclChildren(ct)) + { + NonProtocolDecl tmp = (NonProtocolDecl) parser.parse(ptd, af); + ptds.add(tmp); + } + for (CommonTree pd : getProtocolDeclChildren(ct)) + { + ProtocolDecl tmp = (ProtocolDecl) parser.parse(pd, af); + pds.add(tmp); + } + return af.Module(ct, md, ids, ptds, pds); + } + + // FIXME: like this because AntlrNodeType is not conveniently extendable -- need to bypass AntlrToScribParserUtil#getAntlrNodeType + private static final Set IMPORTDECLS = Stream.of(ScribbleAntlrConstants.IMPORTMODULE_NODE_TYPE, + ScribbleAntlrConstants.IMPORTMEMBER_NODE_TYPE).collect(Collectors.toSet()); + private static final Set NONPROTOCOLDECLS = Stream.of(ScribbleAntlrConstants.PAYLOADTYPEDECL_NODE_TYPE, + ScribbleAntlrConstants.MESSAGESIGNATUREDECL_NODE_TYPE, "PARAM_DELEGDECL").collect(Collectors.toSet()); // FIXME: factor out constant + private static final Set PROTOCOLDECLS = Stream.of(ScribbleAntlrConstants.GLOBALPROTOCOLDECL_NODE_TYPE, + ScribbleAntlrConstants.LOCALPROTOCOLDECL_NODE_TYPE).collect(Collectors.toSet()); + + public static List getImportDeclChildren(CommonTree ct) + { + //return filterChildren(ct, AntlrNodeType.IMPORTMODULE, AntlrNodeType.IMPORTMEMBER); + List children = AntlrToScribParserUtil.toCommonTreeList(ct.getChildren()); + return children.subList(1, children.size()).stream() + .filter(c -> IMPORTDECLS.contains(c.getToken().getText())) + .collect(Collectors.toList()); + } + + public static List getDataTypeDeclChildren(CommonTree ct) + { + List children = AntlrToScribParserUtil.toCommonTreeList(ct.getChildren()); + return children.subList(1, children.size()).stream() + .filter(c -> NONPROTOCOLDECLS.contains(c.getToken().getText())) + .collect(Collectors.toList()); + } + + public static List getProtocolDeclChildren(CommonTree ct) + { + //return filterChildren(ct, AntlrNodeType.GLOBALPROTOCOLDECL, AntlrNodeType.LOCALPROTOCOLDECL); + List children = AntlrToScribParserUtil.toCommonTreeList(ct.getChildren()); + return children.subList(1, children.size()).stream() + .filter(c -> PROTOCOLDECLS.contains(c.getToken().getText())) + .collect(Collectors.toList()); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGChoice.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGChoice.java new file mode 100644 index 000000000..218fbd03c --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGChoice.java @@ -0,0 +1,52 @@ +package org.scribble.ext.go.parser.scribble.ast.global; + +import java.util.LinkedList; +import java.util.List; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.global.RPGChoice; +import org.scribble.ext.go.parser.scribble.ast.index.RPAntlrIndexExpr; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.AntlrToScribParserUtil; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; +import org.scribble.util.ScribParserException; + +public class RPAntlrGChoice +{ + public static final int SUBJECT_CHILD_INDEX = 0; + + public static final int BLOCK_CHILDREN_START_INDEX = 2; + public static final int INDEX_EXPR_CHILD_INDEX = 1; + + public static RPGChoice parseParamGChoice(AntlrToScribParser parser, CommonTree root, RPAstFactory af) throws ScribParserException + { + RoleNode subj = AntlrSimpleName.toRoleNode(getSubjectChild(root), af); + List blocks = new LinkedList<>(); + RPIndexExpr expr = RPAntlrIndexExpr.parseParamIndexExpr(getIndexExprChild(root), af); + for (CommonTree b : getBlockChildren(root)) + { + blocks.add((GProtocolBlock) parser.parse(b, af)); + } + return af.ParamGChoice(root, subj, expr, blocks); + } + + public static CommonTree getSubjectChild(CommonTree ct) + { + return (CommonTree) ct.getChild(SUBJECT_CHILD_INDEX); + } + + public static CommonTree getIndexExprChild(CommonTree ct) + { + return (CommonTree) ct.getChild(INDEX_EXPR_CHILD_INDEX); + } + + public static List getBlockChildren(CommonTree ct) + { + List children = ct.getChildren(); + return AntlrToScribParserUtil.toCommonTreeList(children.subList(BLOCK_CHILDREN_START_INDEX, children.size())); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGCrossMessageTransfer.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGCrossMessageTransfer.java new file mode 100644 index 000000000..dd59c791c --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGCrossMessageTransfer.java @@ -0,0 +1,81 @@ +package org.scribble.ext.go.parser.scribble.ast.global; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.MessageNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.global.RPGCrossMessageTransfer; +import org.scribble.ext.go.parser.scribble.ast.index.RPAntlrIndexExpr; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.ast.global.AntlrGMessageTransfer; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; +import org.scribble.util.ScribParserException; + +public class RPAntlrGCrossMessageTransfer +{ + // Same as original + public static final int MESSAGE_CHILD_INDEX = 0; + public static final int SOURCE_NAME_CHILD_INDEX = 1; + public static final int DESTINATION_NAME_CHILD_INDEX = 2; + + // New + public static final int SOURCE_INDEXINTERVAL_CHILD_INDEX = 3; + public static final int DESTINATION_INDEXINTERVAL_CHILD_INDEX = 4; + + public static RPGCrossMessageTransfer + parseParamGCrossMessageTransfer(AntlrToScribParser parser, CommonTree root, RPAstFactory af) throws ScribParserException + { + MessageNode msg = AntlrGMessageTransfer.parseMessage(parser, getMessageChild(root), af); + RoleNode srcName = AntlrSimpleName.toRoleNode(getSourceNameChild(root), af); + RoleNode destName = AntlrSimpleName.toRoleNode(getDestinationNameChild(root), af); + + CommonTree srcIndexInterval = getSourceIndexIntervalChild(root); + CommonTree destIndexInterval = getDestinationIndexIntervalChild(root); + RPIndexExpr srcStart = RPAntlrIndexExpr.parseParamIndexExpr(getParamIndexedRoleStartChild(srcIndexInterval), af); + RPIndexExpr srcEnd = RPAntlrIndexExpr.parseParamIndexExpr(getParamIndexedRoleEndChild(srcIndexInterval), af); + RPIndexExpr destStart = RPAntlrIndexExpr.parseParamIndexExpr(getParamIndexedRoleStartChild(destIndexInterval), af); + RPIndexExpr destEnd = RPAntlrIndexExpr.parseParamIndexExpr(getParamIndexedRoleEndChild(destIndexInterval), af); + return af.ParamGCrossMessageTransfer(root, srcName, msg, destName, srcStart, srcEnd, destStart, destEnd); + } + + public static CommonTree getMessageChild(CommonTree root) + { + return (CommonTree) root.getChild(MESSAGE_CHILD_INDEX); + } + + public static CommonTree getSourceNameChild(CommonTree root) + { + return (CommonTree) root.getChild(SOURCE_NAME_CHILD_INDEX); + } + + public static CommonTree getDestinationNameChild(CommonTree root) + { + return (CommonTree) root.getChild(DESTINATION_NAME_CHILD_INDEX); + } + + public static CommonTree getSourceIndexIntervalChild(CommonTree root) + { + return (CommonTree) root.getChild(SOURCE_INDEXINTERVAL_CHILD_INDEX); + } + + public static CommonTree getDestinationIndexIntervalChild(CommonTree root) + { + return (CommonTree) root.getChild(DESTINATION_INDEXINTERVAL_CHILD_INDEX); + } + + + // "ParamIndexedRole" -- factor out? + public static final int PARAMINDEXEDROLE_START_CHILD_INDEX = 0; + public static final int PARAMINDEXEDROLE_END_CHILD_INDEX = 1; + + public static CommonTree getParamIndexedRoleStartChild(CommonTree root) + { + return (CommonTree) root.getChild(PARAMINDEXEDROLE_START_CHILD_INDEX); + } + + public static CommonTree getParamIndexedRoleEndChild(CommonTree root) + { + return (CommonTree) root.getChild(PARAMINDEXEDROLE_END_CHILD_INDEX); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGDotMessageTransfer.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGDotMessageTransfer.java new file mode 100644 index 000000000..a19769ae4 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGDotMessageTransfer.java @@ -0,0 +1,80 @@ +package org.scribble.ext.go.parser.scribble.ast.global; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.MessageNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.global.RPGDotMessageTransfer; +import org.scribble.ext.go.parser.scribble.ast.index.RPAntlrIndexExpr; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.ast.global.AntlrGMessageTransfer; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; +import org.scribble.util.ScribParserException; + +// Duplicated from ParamAntlrGCrossMessageTransfer +public class RPAntlrGDotMessageTransfer +{ + // Same as original + public static final int MESSAGE_CHILD_INDEX = 0; + public static final int SOURCE_CHILD_INDEX = 1; + public static final int DESTINATION_CHILD_INDEX = 2; + + // New + public static final int SOURCE_START_CHILD_INDEX = 3; + public static final int SOURCE_END_CHILD_INDEX = 4; + public static final int DEST_START_CHILD_INDEX = 5; + public static final int DEST_END_CHILD_INDEX = 6; + + public static RPGDotMessageTransfer + parseParamGDotMessageTransfer(AntlrToScribParser parser, CommonTree root, RPAstFactory af) throws ScribParserException + { + RoleNode src = AntlrSimpleName.toRoleNode(getSourceChild(root), af); + MessageNode msg = AntlrGMessageTransfer.parseMessage(parser, getMessageChild(root), af); + RoleNode dest = AntlrSimpleName.toRoleNode(getDestChild(root), af); + /*ParamRoleParamNode sourceStart = ParamAntlrSimpleName.toParamRoleParamNode(getSourceRangeStartChild(root), af); + ParamRoleParamNode sourceEnd = ParamAntlrSimpleName.toParamRoleParamNode(getSourceRangeEndChild(root), af); + ParamRoleParamNode destStart = ParamAntlrSimpleName.toParamRoleParamNode(getDestRangeStartChild(root), af); + ParamRoleParamNode destEnd = ParamAntlrSimpleName.toParamRoleParamNode(getDestRangeEndChild(root), af);*/ + RPIndexExpr sourceStart = RPAntlrIndexExpr.parseParamIndexExpr(getSourceRangeStartChild(root), af); + RPIndexExpr sourceEnd = RPAntlrIndexExpr.parseParamIndexExpr(getSourceRangeEndChild(root), af); + RPIndexExpr destStart = RPAntlrIndexExpr.parseParamIndexExpr(getDestRangeStartChild(root), af); + RPIndexExpr destEnd = RPAntlrIndexExpr.parseParamIndexExpr(getDestRangeEndChild(root), af); + return af.ParamGDotMessageTransfer(root, src, msg, dest, sourceStart, sourceEnd, destStart, destEnd); + } + + public static CommonTree getMessageChild(CommonTree root) + { + return (CommonTree) root.getChild(MESSAGE_CHILD_INDEX); + } + + public static CommonTree getSourceChild(CommonTree root) + { + return (CommonTree) root.getChild(SOURCE_CHILD_INDEX); + } + + public static CommonTree getDestChild(CommonTree root) + { + return (CommonTree) root.getChild(DESTINATION_CHILD_INDEX); + } + + public static CommonTree getSourceRangeStartChild(CommonTree root) + { + return (CommonTree) root.getChild(SOURCE_START_CHILD_INDEX); + } + + public static CommonTree getSourceRangeEndChild(CommonTree root) + { + return (CommonTree) root.getChild(SOURCE_END_CHILD_INDEX); + } + + public static CommonTree getDestRangeStartChild(CommonTree root) + { + return (CommonTree) root.getChild(DEST_START_CHILD_INDEX); + } + + public static CommonTree getDestRangeEndChild(CommonTree root) + { + return (CommonTree) root.getChild(DEST_END_CHILD_INDEX); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGMultiChoices.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGMultiChoices.java new file mode 100644 index 000000000..4b0cb4df1 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGMultiChoices.java @@ -0,0 +1,68 @@ +package org.scribble.ext.go.parser.scribble.ast.global; + +import java.util.LinkedList; +import java.util.List; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.global.GChoice; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.parser.scribble.ast.index.RPAntlrIndexExpr; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.AntlrToScribParserUtil; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; +import org.scribble.util.ScribParserException; + +public class RPAntlrGMultiChoices +{ + public static final int SUBJECT_CHILD_INDEX = 0; + + public static final int BLOCK_CHILDREN_START_INDEX = 4; + + public static final int INDEX_VAR_CHILD_INDEX = 1; + public static final int START_INDEX_EXPR_CHILD_INDEX = 2; + public static final int END_INDEX_EXPR_CHILD_INDEX = 3; + + public static GChoice parseParamGMultiChoices(AntlrToScribParser parser, CommonTree root, RPAstFactory af) throws ScribParserException + { + RoleNode subj = AntlrSimpleName.toRoleNode(getSubjectChild(root), af); + List blocks = new LinkedList<>(); + RPIndexVar var = (RPIndexVar) RPAntlrIndexExpr.parseParamIndexExpr(getIndexVarChild(root), af); + RPIndexExpr start = RPAntlrIndexExpr.parseParamIndexExpr(getStartIndexExprChild(root), af); + RPIndexExpr end = RPAntlrIndexExpr.parseParamIndexExpr(getEndIndexExprChild(root), af); + for (CommonTree b : getBlockChildren(root)) + { + blocks.add((GProtocolBlock) parser.parse(b, af)); + } + return af.ParamGMultiChoices(root, subj, var, start, end, blocks); + } + + public static CommonTree getSubjectChild(CommonTree ct) + { + return (CommonTree) ct.getChild(SUBJECT_CHILD_INDEX); + } + + public static CommonTree getIndexVarChild(CommonTree ct) + { + return (CommonTree) ct.getChild(INDEX_VAR_CHILD_INDEX); + } + + public static CommonTree getStartIndexExprChild(CommonTree ct) + { + return (CommonTree) ct.getChild(START_INDEX_EXPR_CHILD_INDEX); + } + + public static CommonTree getEndIndexExprChild(CommonTree ct) + { + return (CommonTree) ct.getChild(END_INDEX_EXPR_CHILD_INDEX); + } + + public static List getBlockChildren(CommonTree ct) + { + List children = ct.getChildren(); + return AntlrToScribParserUtil.toCommonTreeList(children.subList(BLOCK_CHILDREN_START_INDEX, children.size())); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGMultiChoicesTransfer.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGMultiChoicesTransfer.java new file mode 100644 index 000000000..2ed90a4e7 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGMultiChoicesTransfer.java @@ -0,0 +1,69 @@ +package org.scribble.ext.go.parser.scribble.ast.global; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.MessageNode; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.global.RPGMultiChoicesTransfer; +import org.scribble.ext.go.parser.scribble.ast.index.RPAntlrIndexExpr; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexVar; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.ast.global.AntlrGMessageTransfer; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; +import org.scribble.util.ScribParserException; + +public class RPAntlrGMultiChoicesTransfer +{ + // Same as original + public static final int MESSAGE_CHILD_INDEX = 0; + public static final int SOURCE_CHILD_INDEX = 1; + public static final int DESTINATION_CHILD_INDEX = 2; + + // New + public static final int INDEX_VAR_CHILD_INDEX = 3; + public static final int DEST_START_CHILD_INDEX = 4; + public static final int DEST_END_CHILD_INDEX = 5; + + public static RPGMultiChoicesTransfer + parseParamGMultiChoicesTransfer(AntlrToScribParser parser, CommonTree root, RPAstFactory af) throws ScribParserException + { + RoleNode src = AntlrSimpleName.toRoleNode(getSourceChild(root), af); + MessageNode msg = AntlrGMessageTransfer.parseMessage(parser, getMessageChild(root), af); + RoleNode dest = AntlrSimpleName.toRoleNode(getDestChild(root), af); + RPIndexVar var = (RPIndexVar) RPAntlrIndexExpr.parseParamIndexExpr(getIndexVarChild(root), af); + RPIndexExpr destStart = RPAntlrIndexExpr.parseParamIndexExpr(getDestRangeStartChild(root), af); + RPIndexExpr destEnd = RPAntlrIndexExpr.parseParamIndexExpr(getDestRangeEndChild(root), af); + return af.ParamGMultiChoicesTransfer(root, src, msg, dest, var, destStart, destEnd); + } + + public static CommonTree getMessageChild(CommonTree root) + { + return (CommonTree) root.getChild(MESSAGE_CHILD_INDEX); + } + + public static CommonTree getSourceChild(CommonTree root) + { + return (CommonTree) root.getChild(SOURCE_CHILD_INDEX); + } + + public static CommonTree getDestChild(CommonTree root) + { + return (CommonTree) root.getChild(DESTINATION_CHILD_INDEX); + } + + public static CommonTree getIndexVarChild(CommonTree root) + { + return (CommonTree) root.getChild(INDEX_VAR_CHILD_INDEX); + } + + public static CommonTree getDestRangeStartChild(CommonTree root) + { + return (CommonTree) root.getChild(DEST_START_CHILD_INDEX); + } + + public static CommonTree getDestRangeEndChild(CommonTree root) + { + return (CommonTree) root.getChild(DEST_END_CHILD_INDEX); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGProtocolDecl.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGProtocolDecl.java new file mode 100644 index 000000000..fa2900435 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGProtocolDecl.java @@ -0,0 +1,60 @@ +/** + * Copyright 2008 The Scribble Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.scribble.ext.go.parser.scribble.ast.global; + +import java.util.LinkedList; +import java.util.List; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ast.global.GProtocolDef; +import org.scribble.ast.global.GProtocolHeader; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.ast.global.AntlrGProtocolDecl; +import org.scribble.util.ScribParserException; + +@Deprecated +public class RPAntlrGProtocolDecl +{ + public static final String NO_MODS = "PARAM_NOMODS"; + + public static final int ANNOT_CHILD_INDEX = 3; + + public static GProtocolDecl parseGPrototocolDecl(AntlrToScribParser parser, CommonTree ct, AstFactory af) throws ScribParserException + { + GProtocolHeader header = (GProtocolHeader) parser.parse(AntlrGProtocolDecl.getHeaderChild(ct), af); + GProtocolDef def = (GProtocolDef) parser.parse(AntlrGProtocolDecl.getBodyChild(ct), af); + List modifiers = new LinkedList<>(); + if (RPAntlrGProtocolDecl.hasModifiersChild(ct)) + { + for (CommonTree mod : AntlrGProtocolDecl.getModifierChildren(ct)) + { + switch (mod.getText()) + { + case "aux": modifiers.add(GProtocolDecl.Modifiers.AUX); break; + case "explicit": modifiers.add(GProtocolDecl.Modifiers.EXPLICIT); break; + default: throw new RuntimeException("TODO: " + mod); + } + } + } + return null;//((RPAstFactory) af).RPGProtocolDecl(ct, modifiers, header, def); + } + + public static boolean hasModifiersChild(CommonTree ct) + { + return ct.getChildCount() > AntlrGProtocolDecl.MODIFIERS_CHILD_INDEX + && !ct.getChild(AntlrGProtocolDecl.MODIFIERS_CHILD_INDEX).getText().equals(NO_MODS); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGProtocolHeader.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGProtocolHeader.java new file mode 100644 index 000000000..8d3d65356 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPAntlrGProtocolHeader.java @@ -0,0 +1,70 @@ +/** + * Copyright 2008 The Scribble Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.scribble.ext.go.parser.scribble.ast.global; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ast.NonRoleParamDeclList; +import org.scribble.ast.RoleDeclList; +import org.scribble.ast.global.GProtocolHeader; +import org.scribble.ast.name.qualified.GProtocolNameNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.ast.AntlrExtIdentifier; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; +import org.scribble.util.ScribParserException; + +public class RPAntlrGProtocolHeader +{ + public static final int ANNOT_CHILD_INDEX = 3; + + public static final int NAME_CHILD_INDEX = 0; + public static final int PARAMETERDECLLIST_CHILD_INDEX = 1; + public static final int ROLEDECLLIST_CHILD_INDEX = 2; + + public static GProtocolHeader parseGProtocolHeader(AntlrToScribParser parser, CommonTree ct, AstFactory af) throws ScribParserException + { + GProtocolNameNode name = AntlrSimpleName.toGProtocolNameNode(getNameChild(ct), af); + RoleDeclList rdl = (RoleDeclList) parser.parse(getRoleDeclListChild(ct), af); + NonRoleParamDeclList pdl = (NonRoleParamDeclList) parser.parse(getParamDeclListChild(ct), af); + String annot = AntlrExtIdentifier.getName(getAnnotChild(ct)); + return ((RPAstFactory) af).RPGProtocolHeader(ct, name, rdl, pdl, annot); + } + + public static CommonTree getNameChild(CommonTree ct) + { + return (CommonTree) ct.getChild(NAME_CHILD_INDEX); + } + + public static CommonTree getRoleDeclListChild(CommonTree ct) + { + return (CommonTree) ct.getChild(ROLEDECLLIST_CHILD_INDEX); + } + + public static CommonTree getParamDeclListChild(CommonTree ct) + { + return (CommonTree) ct.getChild(PARAMETERDECLLIST_CHILD_INDEX); + } + + /*public static boolean hasAnnotChild(CommonTree ct) + { + return ct.getChildCount() == 4; + }*/ + + public static CommonTree getAnnotChild(CommonTree ct) + { + return (CommonTree) ct.getChild(ANNOT_CHILD_INDEX); + } +} + diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPCoreAntlrGForeach.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPCoreAntlrGForeach.java new file mode 100644 index 000000000..874d290df --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/global/RPCoreAntlrGForeach.java @@ -0,0 +1,87 @@ +package org.scribble.ext.go.parser.scribble.ast.global; + +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.global.GProtocolBlock; +import org.scribble.ast.name.simple.RoleNode; +import org.scribble.ext.go.ast.RPAstFactory; +import org.scribble.ext.go.ast.global.RPGForeach; +import org.scribble.ext.go.parser.scribble.ast.index.RPAntlrIndexExpr; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.parser.scribble.AntlrToScribParser; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; +import org.scribble.util.ScribParserException; + +public class RPCoreAntlrGForeach +{ + //public static final int SUBJECT_CHILD_INDEX = 0; + public static final int BLOCK_CHILD_INDEX = 0; + public static final int FOREACHINTERVAL_CHILDREN_START_INDEX = 1; + + public static RPGForeach parseRPGForeach(AntlrToScribParser parser, CommonTree root, RPAstFactory af) throws ScribParserException + { + //RoleNode subj = AntlrSimpleName.toRoleNode(getSubjectChild(root), af); + GProtocolBlock block = (GProtocolBlock) parser.parse(getBlockChild(root), af); + + List subjs = new LinkedList<>(); + List vars = new LinkedList<>(); + List starts = new LinkedList<>(); + List ends = new LinkedList<>(); + for (CommonTree fi : getForeachIntevalChildren(root)) + { + subjs.add(AntlrSimpleName.toRoleNode(getForeachIntervalSubjectChild(fi), af)); + vars.add((RPForeachVar) RPAntlrIndexExpr.parseRPForeachVar(getForeachIntervalIndexVarChild(fi), af)); + starts.add(RPAntlrIndexExpr.parseParamIndexExpr(getForeachIntervalStartIndexExprChild(fi), af)); + ends.add(RPAntlrIndexExpr.parseParamIndexExpr(getForeachIntervalEndIndexExprChild(fi), af)); + } + return af.RPGForeach(root, subjs, vars, starts, ends, block); + } + + /*public static CommonTree getSubjectChild(CommonTree ct) + { + return (CommonTree) ct.getChild(SUBJECT_CHILD_INDEX); + }*/ + + public static CommonTree getBlockChild(CommonTree ct) + { + return (CommonTree) ct.getChild(BLOCK_CHILD_INDEX); + } + + public static List getForeachIntevalChildren(CommonTree ct) + { + List children = ct.getChildren(); + return children.subList(FOREACHINTERVAL_CHILDREN_START_INDEX, children.size()).stream() + .map(c -> (CommonTree) c).collect(Collectors.toList()); + } + + + // PARAM_FOREACHINTERVAL -- factor out? + public static final int SUBJECT_CHILD_INDEX = 0; + public static final int INDEX_VAR_CHILD_INDEX = 1; + public static final int START_INDEX_EXPR_CHILD_INDEX = 2; + public static final int END_INDEX_EXPR_CHILD_INDEX = 3; + + public static CommonTree getForeachIntervalSubjectChild(CommonTree ct) + { + return (CommonTree) ct.getChild(SUBJECT_CHILD_INDEX); + } + + public static CommonTree getForeachIntervalIndexVarChild(CommonTree ct) + { + return (CommonTree) ct.getChild(INDEX_VAR_CHILD_INDEX); + } + + public static CommonTree getForeachIntervalStartIndexExprChild(CommonTree ct) + { + return (CommonTree) ct.getChild(START_INDEX_EXPR_CHILD_INDEX); + } + + public static CommonTree getForeachIntervalEndIndexExprChild(CommonTree ct) + { + return (CommonTree) ct.getChild(END_INDEX_EXPR_CHILD_INDEX); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/index/RPAntlrIndexExpr.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/index/RPAntlrIndexExpr.java new file mode 100644 index 000000000..227dbdf66 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/index/RPAntlrIndexExpr.java @@ -0,0 +1,71 @@ +package org.scribble.ext.go.parser.scribble.ast.index; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ext.go.type.index.RPBinIndexExpr; +import org.scribble.ext.go.type.index.RPForeachVar; +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.index.RPIndexFactory; + +public class RPAntlrIndexExpr +{ + public static RPIndexExpr parseParamIndexExpr(CommonTree ct, AstFactory af) + { + String type = ct.getToken().getText(); // Duplicated from ScribParserUtil.getAntlrNodeType + switch (type) + { + case "PARAM_BININDEXEXPR": // FIXME: factor out + { + RPIndexExpr left = parseParamIndexExpr((CommonTree) ct.getChild(0), af); + if (ct.getChildCount() < 3) + { + return left; + } + RPIndexExpr right = parseParamIndexExpr((CommonTree) ct.getChild(2), af); + RPBinIndexExpr.Op op; + switch (ct.getChild(1).getText()) + { + case "+": op = RPBinIndexExpr.Op.Add; break; + case "-": op = RPBinIndexExpr.Op.Subt; break; + case "*": op = RPBinIndexExpr.Op.Mult; break; + default: throw new RuntimeException("[param] Shouldn't get in here: " + ct); + } + return RPIndexFactory.ParamBinIndexExpr(op, left, right); + } + case "PARAM_PAIR": // FIXME + { + RPIndexExpr left = parseParamIndexExpr((CommonTree) ct.getChild(0), af); + if (ct.getChildCount() < 2) + { + return left; + } + RPIndexExpr right = parseParamIndexExpr((CommonTree) ct.getChild(1), af); + return RPIndexFactory.RPIndexPair(left, right); + } + default: + { + return isInteger(type) + ? RPIndexFactory.ParamIntVal(Integer.parseInt(type)) + : RPIndexFactory.ParamIndexVar(type); + } + } + } + + public static RPForeachVar parseRPForeachVar(CommonTree ct, AstFactory af) + { + // Duplicated from above + String type = ct.getToken().getText(); // Parsed as simplename + return RPIndexFactory.RPForeachVar(type); + } + + private static boolean isInteger(String s) + { + // return Arrays.stream(s.getBytes()).stream().allMatch(c -> // Character.digit((char) c,radix) < 0); // no Byte stream + if (s.isEmpty()) return false; + for (int i = 0; i < s.length(); i++) + { + if (Character.digit(s.charAt(i), 10) < 0) return false; + } + return true; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/name/ParamAntlrSimpleName.java b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/name/ParamAntlrSimpleName.java new file mode 100644 index 000000000..f0df63710 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/parser/scribble/ast/name/ParamAntlrSimpleName.java @@ -0,0 +1,16 @@ +package org.scribble.ext.go.parser.scribble.ast.name; + +import org.antlr.runtime.tree.CommonTree; +import org.scribble.ast.AstFactory; +import org.scribble.ext.go.ast.name.simple.RPIndexedRoleNode; +import org.scribble.ext.go.type.kind.RPIndexedRoleKind; +import org.scribble.parser.scribble.ast.name.AntlrSimpleName; + +@Deprecated +public class ParamAntlrSimpleName +{ + public static RPIndexedRoleNode toParamRoleParamNode(CommonTree ct, AstFactory af) + { + return (RPIndexedRoleNode) af.SimpleNameNode(ct, RPIndexedRoleKind.KIND, AntlrSimpleName.getName(ct)); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotExpr.java b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotExpr.java new file mode 100644 index 000000000..245f110e6 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotExpr.java @@ -0,0 +1,164 @@ +package org.scribble.ext.go.type.annot; + +import java.util.Set; + +import org.scribble.ext.go.type.annot.RPBinAnnotExpr.Op; +import org.scribble.ext.go.util.Smt2Translator; +import org.scribble.util.Pair; + +public abstract class RPAnnotExpr +{ + public boolean isConstant() + { + return false; + } + + public abstract String toGoString(); // As basic Go expressions, but not (necessarily) actual code generation "ouput" + // N.B. "value" expressions -- though may also be used for, e.g., names (e.g., RPCoreSTApiGenerator.getGeneratedNameLabel) + + public abstract Set getVals(); // TODO: factor out a "value" interface + public abstract Set getVars(); // N.B. doesn't include foreach params + + public abstract String toSmt2Formula(Smt2Translator smt2t); // Cf. toString -- but can be useful to separate, for debugging (and printing) + // FIXME: inconsistency with toString + // TODO: factor out Smt2 translation interface + + // N.B. "syntactic" comparison + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPAnnotExpr)) + { + return false; + } + return ((RPAnnotExpr) o).canEqual(this); + } + + protected abstract boolean canEqual(Object o); + + // In case subclasses do super + @Override + public int hashCode() + { + return 5869; + } + + // TODO: parse properly using ANTLR, cf. Assrt + public static RPAnnotExpr parse(String annot) + { + //for (String t = annot.trim(); !t.equals(""); ) + { + RPAnnotExpr left; + RPAnnotExpr right; + String t = annot.trim(); + Pair next = nextToken(t); + t = t.substring(next.right, t.length()).trim(); + left = parseEle(next.left); + Pair op = nextToken(t); + t = t.substring(op.right, t.length()).trim(); + next = nextToken(t); + right = parseEle(next.left); + switch (op.left) + { + case "<": return RPAnnotFactory.ParamBinAnnotExpr(Op.Lt, left, right); + case "<=": return RPAnnotFactory.ParamBinAnnotExpr(Op.Lte, left, right); + case ">": return RPAnnotFactory.ParamBinAnnotExpr(Op.Gt, left, right); + case ">=": return RPAnnotFactory.ParamBinAnnotExpr(Op.Gte, left, right); + default: throw new RuntimeException("Shouldn't get in here: " + annot); + } + } + } + + private static RPAnnotExpr parseEle(String e) + { + if (e.startsWith("(")) + { + int comma = e.indexOf(","); + RPAnnotExpr l = parseEle(e.substring(1, comma)); + RPAnnotExpr r = parseEle(e.substring(comma+1, e.length()-1)); + return RPAnnotFactory.RPAnnotPair(l, r); + } + else + { + try + { + return RPAnnotFactory.ParamIntVal(Integer.parseInt(e)); + } + catch (NumberFormatException x) + { + return RPAnnotFactory.ParamIndexVar(e); + } + } + } + + private static Pair nextToken(String t) + { + for (int i = 0; i < t.length(); i++) + { + char c = t.charAt(i); + if (c == ' ') + { + + } + else if (c == '(') + { + //int comma = t.indexOf(',', i+1); + int j = t.indexOf(')', i+1) + 1; + return new Pair<>(t.substring(i, j), j); + } + else if (c >= '0' && c <= '9') + { + int j = i; + while (j < t.length() && c >= '0' && c <= '9') + { + j++; + if (j == t.length()) + { + break; + } + c = t.charAt(j); + } + return new Pair<>(t.substring(i, j), j); + } + else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + { + int j = i; + while (j < t.length() && (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + { + j++; + if (j == t.length()) + { + break; + } + c = t.charAt(j); + } + return new Pair<>(t.substring(i, j), j); + } + else if (c == '<') + { + if (i+1 < t.length() && t.charAt(i+1) == '=') + { + return new Pair<>(t.substring(i, i+2), i+2); + } + return new Pair<>(t.substring(i, i+1), i+1); + } + else if (c == '>') + { + if (i+1 < t.length() && t.charAt(i+1) == '=') + { + return new Pair<>(t.substring(i, i+2), i+2); + } + return new Pair<>(t.substring(i, i+1), i+1); + } + else + { + throw new RuntimeException("TODO: " + t); + } + } + throw new RuntimeException("TODO: " + t); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotFactory.java b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotFactory.java new file mode 100644 index 000000000..a3813490a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotFactory.java @@ -0,0 +1,34 @@ +package org.scribble.ext.go.type.annot; + +// Used directly by source ast parsing -- cf. scrib-assrt, AssrtAntlrToFormulaParser +// Would correspond to a "types factory" -- cf. AST factory +public class RPAnnotFactory +{ + + public static RPBinAnnotExpr ParamBinAnnotExpr(RPBinAnnotExpr.Op op, RPAnnotExpr left, RPAnnotExpr right) + { + return new RPBinAnnotExpr(op, left, right); + } + + public static RPAnnotInt ParamIntVal(int i) + { + return new RPAnnotInt(i); + } + + public static RPAnnotVar ParamIndexVar(String text) + { + /*// Check here? Or in API gen + char c = text.charAt(0); + if (c < 'A' || c > 'Z') + { + throw new RuntimeException("[param] Annot variables must be uppercase for Go accessibility: " + text); + // FIXME: return proper parsing error -- refactor as param API gen errors + }*/ + return new RPAnnotVar(text); + } + + public static RPAnnotIntPair RPAnnotPair(RPAnnotExpr left, RPAnnotExpr right) + { + return new RPAnnotIntPair(left, right); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotInt.java b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotInt.java new file mode 100644 index 000000000..3c57dc28b --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotInt.java @@ -0,0 +1,85 @@ +package org.scribble.ext.go.type.annot; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.util.Smt2Translator; + +// Integer literal +public class RPAnnotInt extends RPAnnotExpr implements RPAnnotVal +{ + public final int val; + + protected RPAnnotInt(int i) + { + this.val = i; + } + + @Override + public boolean isConstant() + { + return true; + } + + @Override + public String toGoString() + { + return toString(); + } + + @Override + public String toSmt2Formula(Smt2Translator smt2t) + { + return Integer.toString(this.val); + } + + @Override + public Set getVals() + { + return Stream.of(this).collect(Collectors.toSet()); + } + + @Override + public Set getVars() + { + return Collections.emptySet(); + } + + @Override + public String toString() + { + return Integer.toString(this.val); + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPAnnotInt)) + { + return false; + } + return super.equals(this) // Does canEqual + && this.val == ((RPAnnotInt) o).val; + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPAnnotInt; + } + + @Override + public int hashCode() + { + int hash = 5897; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.val; + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotIntPair.java b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotIntPair.java new file mode 100644 index 000000000..646a41a76 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotIntPair.java @@ -0,0 +1,97 @@ +package org.scribble.ext.go.type.annot; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.util.Smt2Translator; + + +// Currently only considered as a value +public class RPAnnotIntPair extends RPAnnotExpr implements RPAnnotVal +{ + public final RPAnnotExpr left; + public final RPAnnotExpr right; + + protected RPAnnotIntPair(RPAnnotExpr left, RPAnnotExpr right) + { + //if (!isUnaryExpr(left) || !isUnaryExpr(right)) + if (!(left instanceof RPAnnotInt) || !(right instanceof RPAnnotInt)) + { + throw new RuntimeException("TODO: (" + left + ", " + right + ")"); + } + this.left = left; + this.right = right; + } + + /*private static boolean isUnaryExpr(RPAnnotExpr e) + { + return (e instanceof RPAnnotInt) || (e instanceof RPAnnotVar); + }*/ + + @Override + public String toGoString() + { + return "(session2.XY(" + this.left.toGoString() + ", " + this.right.toGoString() + "))"; + } + + @Override + public String toSmt2Formula(Smt2Translator smt2t) + { + String left = this.left.toSmt2Formula(smt2t); + String right = this.right.toSmt2Formula(smt2t); + return "(mk-pair " + left + " " + right + ")"; + } + + @Override + public Set getVals() + { + return Stream.of(this).collect(Collectors.toSet()); + } + + @Override + public Set getVars() + { + //return Stream.of(this.left.getVars(), this.right.getVars()).flatMap(x -> x.stream()).collect(Collectors.toSet()); + return Collections.emptySet(); // Currently only considered as a value + } + + @Override + public String toString() + { + return "(" + this.left.toString() + ", " + this.right.toString() + ")"; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPAnnotIntPair)) + { + return false; + } + RPAnnotIntPair f = (RPAnnotIntPair) o; + return super.equals(this) // Does canEqual + && this.left.equals(f.left) && this.right.equals(f.right); + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPAnnotIntPair; + } + + @Override + public int hashCode() + { + int hash = 6311; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.left.hashCode(); + hash = 31 * hash + this.right.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotVal.java b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotVal.java new file mode 100644 index 000000000..3339c0b4e --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotVal.java @@ -0,0 +1,6 @@ +package org.scribble.ext.go.type.annot; + +public interface RPAnnotVal +{ + //public boolean gtEq(RPAnnotVal them); +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotVar.java b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotVar.java new file mode 100644 index 000000000..dffd0e594 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPAnnotVar.java @@ -0,0 +1,85 @@ +package org.scribble.ext.go.type.annot; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.scribble.ext.go.util.Smt2Translator; + +// Variable occurrence +public class RPAnnotVar extends RPAnnotExpr // FIXME: extend AbstractName? cf. Role -- e.g., for compatibility with NameCollector +{ + public final String name; + + protected RPAnnotVar(String name) + { + this.name = name; + } + + @Override + public String toGoString() + { + return toString(); + } + + @Override + public String toSmt2Formula(Smt2Translator smt2t) + { + /*if (this.name.startsWith("_dum")) // FIXME + { + throw new RuntimeException("[assrt] Use squash first: " + this); + }*/ + //return "(" + this.name + ")"; + return this.name; + } + + @Override + public Set getVals() + { + return Collections.emptySet(); + } + + @Override + public Set getVars() + { + Set vars = new HashSet<>(); + vars.add(this); // FIXME: currently may also be a role + return vars; + } + + @Override + public String toString() + { + return this.name; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPAnnotVar)) + { + return false; + } + return super.equals(this) // Does canEqual + && this.name.equals(((RPAnnotVar) o).name); + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPAnnotVar; + } + + @Override + public int hashCode() + { + int hash = 5903; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.name.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPBinAnnotExpr.java b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPBinAnnotExpr.java new file mode 100644 index 000000000..1102b7546 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/annot/RPBinAnnotExpr.java @@ -0,0 +1,125 @@ +package org.scribble.ext.go.type.annot; + +import java.util.HashSet; +import java.util.Set; + +import org.scribble.ext.go.util.Smt2Translator; + + +// Binary arithmetic +public class RPBinAnnotExpr extends RPAnnotExpr +{ + public enum Op + { + Gt, + Gte, + Lt, + Lte; + + @Override + public String toString() + { + switch (this) + { + case Gt: return ">"; + case Gte: return ">="; + case Lt: return "<"; + case Lte: return "<="; + default: throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + } + } + + public final Op op; + public final RPAnnotExpr left; + public final RPAnnotExpr right; + + protected RPBinAnnotExpr(Op op, RPAnnotExpr left, RPAnnotExpr right) + { + this.left = left; + this.right = right; + this.op = op; + } + + @Override + public String toGoString() + { + //throw new RuntimeException("[param-core] TODO: " + this); + return toString(); + } + + @Override + public String toSmt2Formula(Smt2Translator smt2t) + { + String left = this.left.toSmt2Formula(smt2t); + String right = this.right.toSmt2Formula(smt2t); + String op; + switch(this.op) + { + case Gt: op = smt2t.getGtOp(); break; + case Gte: op = smt2t.getGteOp(); break; + case Lt: op = smt2t.getLtOp(); break; + case Lte: op = smt2t.getLteOp(); break; + //case Mult: op = "*"; break; + default: throw new RuntimeException("[param] Shouldn't get in here: " + this.op); + } + return "(" + op + " " + left + " " + right + ")"; + } + + @Override + public Set getVals() + { + Set vals = new HashSet<>(this.left.getVals()); + vals.addAll(this.right.getVals()); + return vals; + } + + @Override + public Set getVars() + { + Set vars = new HashSet<>(this.left.getVars()); + vars.addAll(this.right.getVars()); + return vars; + } + + @Override + public String toString() + { + return "(" + this.left.toString() + this.op + this.right.toString() + ")"; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPBinAnnotExpr)) + { + return false; + } + RPBinAnnotExpr f = (RPBinAnnotExpr) o; + return super.equals(this) // Does canEqual + && this.op.equals(f.op) && this.left.equals(f.left) && this.right.equals(f.right); + // Storing left/right as a Set could give commutativity in equals, but not associativity + // Better to keep "syntactic" equality, and do via additional routines for, e.g., normal forms + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPBinAnnotExpr; + } + + @Override + public int hashCode() + { + int hash = 5879; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.op.hashCode(); + hash = 31 * hash + this.left.hashCode(); + hash = 31 * hash + this.right.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPBinIndexExpr.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPBinIndexExpr.java new file mode 100644 index 000000000..b4dc002f4 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPBinIndexExpr.java @@ -0,0 +1,214 @@ +package org.scribble.ext.go.type.index; + +import java.util.HashSet; +import java.util.Set; + +import org.scribble.ext.go.util.Smt2Translator; + + +// Binary arithmetic +public class RPBinIndexExpr extends RPIndexExpr +{ + public enum Op + { + Add, + Subt, + Mult; + + @Override + public String toString() + { + switch (this) + { + case Add: return "+"; + case Subt: return "-"; + case Mult: //return "*"; + default: throw new RuntimeException("[param] Shouldn't get in here: " + this); + } + } + } + + public final Op op; + public final RPIndexExpr left; + public final RPIndexExpr right; + + protected RPBinIndexExpr(Op op, RPIndexExpr left, RPIndexExpr right) + { + this.left = left; + this.right = right; + this.op = op; + } + + @Override + public RPIndexExpr minimise(int self) + { + // FIXME: consider associativity for "maximal" reduction (or normal forms) + RPIndexExpr left = this.left.minimise(self); + RPIndexExpr right = this.right.minimise(self); + if (right instanceof RPIndexInt) + { + int y = ((RPIndexInt) right).val; + if (left instanceof RPIndexInt) + { + int x = ((RPIndexInt) left).val; + switch (this.op) + { + case Add: return RPIndexFactory.ParamIntVal(x + y); + case Mult: return RPIndexFactory.ParamIntVal(x * y); + case Subt: return RPIndexFactory.ParamIntVal(x - y); + default: throw new RuntimeException("Shouldn't get in here: " + this); + } + } + else + { + if (y < 0) + { + if (this.op == Op.Add) + { + return RPIndexFactory.ParamBinIndexExpr(Op.Subt, left, RPIndexFactory.ParamIntVal(-y)); + } + else if (this.op == Op.Subt) + { + return RPIndexFactory.ParamBinIndexExpr(Op.Add, left, RPIndexFactory.ParamIntVal(-y)); + } + } + } + } + else + { + if (left instanceof RPIndexInt) + { + int x = ((RPIndexInt) left).val; + if (x < 0 && this.op == Op.Add) + { + return RPIndexFactory.ParamBinIndexExpr(Op.Subt, right, RPIndexFactory.ParamIntVal(-x)); + } + } + else + { + if (right instanceof RPIndexIntPair) + { + RPIndexIntPair y = ((RPIndexIntPair) right); + if (left instanceof RPIndexIntPair) + { + RPIndexIntPair x = ((RPIndexIntPair) left); + switch (this.op) + { + case Add: return RPIndexFactory.RPIndexPair(RPIndexFactory.ParamIntVal(((RPIndexInt) x.left).val + ((RPIndexInt) y.left).val), + RPIndexFactory.ParamIntVal(((RPIndexInt) x.right).val + ((RPIndexInt) y.right).val)); + case Subt: return RPIndexFactory.RPIndexPair(RPIndexFactory.ParamIntVal(((RPIndexInt) x.left).val - ((RPIndexInt) y.left).val), + RPIndexFactory.ParamIntVal(((RPIndexInt) x.right).val - ((RPIndexInt) y.right).val)); + case Mult: //return RPIndexFactory.ParamIntVal(x * y); + default: throw new RuntimeException("Shouldn't get in here: " + this); + } + } + else + { + /*if (y < 0) // TODO + { + if (this.op == Op.Add) + { + return RPIndexFactory.ParamBinIndexExpr(Op.Subt, left, RPIndexFactory.ParamIntVal(-y)); + } + else if (this.op == Op.Subt) + { + return RPIndexFactory.ParamBinIndexExpr(Op.Add, left, RPIndexFactory.ParamIntVal(-y)); + } + }*/ + } + } + else + { + /*if (left instanceof RPIndexPair) // TODO + { + int x = ((RPIndexInt) left).val; + if (x < 0 && this.op == Op.Add) + { + return RPIndexFactory.ParamBinIndexExpr(Op.Subt, right, RPIndexFactory.ParamIntVal(-x)); + }*/ + } + } + } + return RPIndexFactory.ParamBinIndexExpr(this.op, left, right); + } + + @Override + public String toGoString() + { + //throw new RuntimeException("[param-core] TODO: " + this); + return toString(); + } + + @Override + public String toSmt2Formula(Smt2Translator smt2t) + { + String left = this.left.toSmt2Formula(smt2t); + String right = this.right.toSmt2Formula(smt2t); + String op; + switch(this.op) + { + case Add: op = smt2t.getPlusOp(); break; + case Subt: op = smt2t.getSubOp(); break; + //case Mult: op = "*"; break; + default: throw new RuntimeException("[param] Shouldn't get in here: " + this.op); + } + return "(" + op + " " + left + " " + right + ")"; + } + + @Override + public Set getVals() + { + Set vals = new HashSet<>(this.left.getVals()); + vals.addAll(this.right.getVals()); + return vals; + } + + @Override + public Set getVars() + { + Set vars = new HashSet<>(this.left.getVars()); + vars.addAll(this.right.getVars()); + return vars; + } + + @Override + public String toString() + { + return "(" + this.left.toString() + this.op + this.right.toString() + ")"; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPBinIndexExpr)) + { + return false; + } + RPBinIndexExpr f = (RPBinIndexExpr) o; + return super.equals(this) // Does canEqual + && this.op.equals(f.op) && this.left.equals(f.left) && this.right.equals(f.right); + // Storing left/right as a Set could give commutativity in equals, but not associativity + // Better to keep "syntactic" equality, and do via additional routines for, e.g., normal forms + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPBinIndexExpr; + } + + @Override + public int hashCode() + { + int hash = 5879; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.op.hashCode(); + hash = 31 * hash + this.left.hashCode(); + hash = 31 * hash + this.right.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPForeachVar.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPForeachVar.java new file mode 100644 index 000000000..52d6e3a02 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPForeachVar.java @@ -0,0 +1,50 @@ +package org.scribble.ext.go.type.index; + +// Foreach index variable occurrence -- hacky? -- CHECKME: why distinguish from RPIndexVar? +// Currently only used for parsing foreach param decls -- occurrences of vars inside foreach not disambiguated between endpoint-vars and foreach-vars +// (Currently no actual RPIndexExprNode ast -- so no name disambiguation) + +// FIXME: @Deprecated -- causes problems with checking equality between var occurrences, etc. -- or use same equals/hash for both?... +public class RPForeachVar extends RPIndexVar +{ + protected RPForeachVar(String name) + { + super(name); + } + + /*@Override + public Set getVars() + { + return Collections.emptySet(); // No: still treat foreach vars as vars here -- scope managmenet should be handled by, e.g., RPCoreLForeach + }*/ + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPForeachVar)) + { + return false; + } + return super.equals(this) // Does canEqual + && this.name.equals(((RPForeachVar) o).name); + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPForeachVar; + } + + @Override + public int hashCode() + { + int hash = 2243; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.name.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexExpr.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexExpr.java new file mode 100644 index 000000000..5e6a9205a --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexExpr.java @@ -0,0 +1,49 @@ +package org.scribble.ext.go.type.index; + +import java.util.Set; + +import org.scribble.ext.go.util.Smt2Translator; + +public abstract class RPIndexExpr +{ + public boolean isConstant() + { + return false; + } + + public abstract RPIndexExpr minimise(int self); + + public abstract String toGoString(); // As basic Go expressions, but not (necessarily) actual code generation "ouput" + // N.B. "value" expressions -- though may also be used for, e.g., names (e.g., RPCoreSTApiGenerator.getGeneratedNameLabel) + + public abstract Set getVals(); // TODO: factor out a "value" interface + public abstract Set getVars(); // N.B. doesn't include foreach params + + public abstract String toSmt2Formula(Smt2Translator smt2t); // Cf. toString -- but can be useful to separate, for debugging (and printing) + // FIXME: inconsistency with toString + // TODO: factor out Smt2 translation interface + + // N.B. "syntactic" comparison + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPIndexExpr)) + { + return false; + } + return ((RPIndexExpr) o).canEqual(this); + } + + protected abstract boolean canEqual(Object o); + + // In case subclasses do super + @Override + public int hashCode() + { + return 5869; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexFactory.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexFactory.java new file mode 100644 index 000000000..fdb37042e --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexFactory.java @@ -0,0 +1,44 @@ +package org.scribble.ext.go.type.index; + +// Used directly by source ast parsing -- cf. scrib-assrt, AssrtAntlrToFormulaParser +// Would correspond to a "types factory" -- cf. AST factory +public class RPIndexFactory +{ + + public static RPBinIndexExpr ParamBinIndexExpr(RPBinIndexExpr.Op op, RPIndexExpr left, RPIndexExpr right) + { + return new RPBinIndexExpr(op, left, right); + } + + public static RPIndexInt ParamIntVal(int i) + { + return new RPIndexInt(i); + } + + public static RPIndexVar ParamIndexVar(String text) + { + /*// Check here? Or in API gen + char c = text.charAt(0); + if (c < 'A' || c > 'Z') + { + throw new RuntimeException("[param] Index variables must be uppercase for Go accessibility: " + text); + // FIXME: return proper parsing error -- refactor as param API gen errors + }*/ + return new RPIndexVar(text); + } + + public static RPForeachVar RPForeachVar(String text) + { + return new RPForeachVar(text); + } + + public static RPIndexSelf RPIndexSelf() + { + return RPIndexSelf.SELF; + } + + public static RPIndexIntPair RPIndexPair(RPIndexExpr left, RPIndexExpr right) + { + return new RPIndexIntPair(left, right); + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexInt.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexInt.java new file mode 100644 index 000000000..99ed5620f --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexInt.java @@ -0,0 +1,97 @@ +package org.scribble.ext.go.type.index; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.util.Smt2Translator; + +// Integer literal +public class RPIndexInt extends RPIndexExpr implements RPIndexVal +{ + public final int val; + + protected RPIndexInt(int i) + { + this.val = i; + } + + @Override + public boolean gtEq(RPIndexVal them) + { + return this.val >= ((RPIndexInt) them).val; + } + + @Override + public RPIndexExpr minimise(int self) + { + return this; + } + + @Override + public boolean isConstant() + { + return true; + } + + @Override + public String toGoString() + { + return toString(); + } + + @Override + public String toSmt2Formula(Smt2Translator smt2t) + { + return Integer.toString(this.val); + } + + @Override + public Set getVals() + { + return Stream.of(this).collect(Collectors.toSet()); + } + + @Override + public Set getVars() + { + return Collections.emptySet(); + } + + @Override + public String toString() + { + return Integer.toString(this.val); + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPIndexInt)) + { + return false; + } + return super.equals(this) // Does canEqual + && this.val == ((RPIndexInt) o).val; + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPIndexInt; + } + + @Override + public int hashCode() + { + int hash = 5897; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.val; + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexIntPair.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexIntPair.java new file mode 100644 index 000000000..624cf3d19 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexIntPair.java @@ -0,0 +1,110 @@ +package org.scribble.ext.go.type.index; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.scribble.ext.go.util.Smt2Translator; + + +// Currently only considered as a value +public class RPIndexIntPair extends RPIndexExpr implements RPIndexVal +{ + public final RPIndexExpr left; + public final RPIndexExpr right; + + protected RPIndexIntPair(RPIndexExpr left, RPIndexExpr right) + { + //if (!isUnaryExpr(left) || !isUnaryExpr(right)) + if (!(left instanceof RPIndexInt) || !(right instanceof RPIndexInt)) + { + throw new RuntimeException("TODO: (" + left + ", " + right + ")"); + } + this.left = left; + this.right = right; + } + + /*private static boolean isUnaryExpr(RPIndexExpr e) + { + return (e instanceof RPIndexInt) || (e instanceof RPIndexVar); + }*/ + + @Override + public boolean gtEq(RPIndexVal them) + { + RPIndexIntPair p = (RPIndexIntPair) them; + return ((RPIndexInt) this.left).val >= ((RPIndexInt) p.left).val && ((RPIndexInt) this.right).val >= ((RPIndexInt) p.right).val; + } + + @Override + public RPIndexExpr minimise(int self) + { + return RPIndexFactory.RPIndexPair(this.left.minimise(self), this.right.minimise(self)); + } + + @Override + public String toGoString() + { + return "(session2.XY(" + this.left.toGoString() + ", " + this.right.toGoString() + "))"; + } + + @Override + public String toSmt2Formula(Smt2Translator smt2t) + { + String left = this.left.toSmt2Formula(smt2t); + String right = this.right.toSmt2Formula(smt2t); + return "(mk-pair " + left + " " + right + ")"; + } + + @Override + public Set getVals() + { + return Stream.of(this).collect(Collectors.toSet()); + } + + @Override + public Set getVars() + { + //return Stream.of(this.left.getVars(), this.right.getVars()).flatMap(x -> x.stream()).collect(Collectors.toSet()); + return Collections.emptySet(); // Currently only considered as a value + } + + @Override + public String toString() + { + return "(" + this.left.toString() + ", " + this.right.toString() + ")"; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPIndexIntPair)) + { + return false; + } + RPIndexIntPair f = (RPIndexIntPair) o; + return super.equals(this) // Does canEqual + && this.left.equals(f.left) && this.right.equals(f.right); + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPIndexIntPair; + } + + @Override + public int hashCode() + { + int hash = 6311; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.left.hashCode(); + hash = 31 * hash + this.right.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexSelf.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexSelf.java new file mode 100644 index 000000000..d6347a0cf --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexSelf.java @@ -0,0 +1,54 @@ +package org.scribble.ext.go.type.index; + +// Does not occur in RPRoleVariant, only RPIndexedRole +public class RPIndexSelf extends RPIndexVar +{ + public static final RPIndexSelf SELF = new RPIndexSelf(); + + private RPIndexSelf() + { + super("self"); + } + + @Override + public RPIndexExpr minimise(int self) + { + // FIXME: factor out constant + return (self < 1) ? this : RPIndexFactory.ParamIntVal(self); + } + + @Override + public String toString() + { + return this.name; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPIndexSelf)) + { + return false; + } + return super.equals(this); + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPIndexSelf; + } + + @Override + public int hashCode() + { + int hash = 2099; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.name.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexVal.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexVal.java new file mode 100644 index 000000000..1699e7d96 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexVal.java @@ -0,0 +1,6 @@ +package org.scribble.ext.go.type.index; + +public interface RPIndexVal +{ + public boolean gtEq(RPIndexVal them); +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexVar.java b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexVar.java new file mode 100644 index 000000000..24d280e11 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/index/RPIndexVar.java @@ -0,0 +1,96 @@ +package org.scribble.ext.go.type.index; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.scribble.ext.go.util.Smt2Translator; + +// Variable occurrence +public class RPIndexVar extends RPIndexExpr // FIXME: extend AbstractName? cf. Role -- e.g., for compatibility with NameCollector +{ + public final String name; + + protected RPIndexVar(String name) + { + this.name = name; + } + + @Override + public RPIndexExpr minimise(int self) + { + return this; + } + + /*public RPRoleParam toRoleParam() + { + return new RPRoleParam(this.name); + }*/ + + @Override + public String toGoString() + { + return toString(); + } + + @Override + public String toSmt2Formula(Smt2Translator smt2t) + { + /*if (this.name.startsWith("_dum")) // FIXME + { + throw new RuntimeException("[assrt] Use squash first: " + this); + }*/ + //return "(" + this.name + ")"; + return this.name; + } + + @Override + public Set getVals() + { + return Collections.emptySet(); + } + + @Override + public Set getVars() + { + Set vars = new HashSet<>(); + vars.add(this); // FIXME: currently may also be a role + return vars; + } + + @Override + public String toString() + { + return this.name; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPIndexVar)) + { + return false; + } + return super.equals(this) // Does canEqual + && this.name.equals(((RPIndexVar) o).name); + } + + @Override + protected boolean canEqual(Object o) + { + return o instanceof RPIndexVar; + } + + @Override + public int hashCode() + { + int hash = 5903; + hash = 31 * hash + super.hashCode(); + hash = 31 * hash + this.name.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/kind/RPIndexedRoleKind.java b/scribble-go/src/main/java/org/scribble/ext/go/type/kind/RPIndexedRoleKind.java new file mode 100644 index 000000000..c748b175d --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/kind/RPIndexedRoleKind.java @@ -0,0 +1,43 @@ +package org.scribble.ext.go.type.kind; + +import java.io.Serializable; + +import org.scribble.type.kind.AbstractKind; + +public class RPIndexedRoleKind extends AbstractKind implements Serializable +{ + private static final long serialVersionUID = 1L; + + public static final RPIndexedRoleKind KIND = new RPIndexedRoleKind(); + + protected RPIndexedRoleKind() + { + + } + + @Override + public int hashCode() + { + return super.hashCode(); + } + + @Override + public boolean equals(Object o) + { + if (o == this) + { + return true; + } + if (!(o instanceof RPIndexedRoleKind)) + { + return false; + } + return ((RPIndexedRoleKind) o).canEqual(this); + } + + @Override + public boolean canEqual(Object o) + { + return o instanceof RPIndexedRoleKind; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/type/name/RPIndexedRole.java b/scribble-go/src/main/java/org/scribble/ext/go/type/name/RPIndexedRole.java new file mode 100644 index 000000000..a412b7e7c --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/type/name/RPIndexedRole.java @@ -0,0 +1,65 @@ +package org.scribble.ext.go.type.name; + +import org.scribble.ext.go.type.index.RPIndexExpr; +import org.scribble.ext.go.type.kind.RPIndexedRoleKind; +import org.scribble.type.name.AbstractName; + +// Currently used for both "actual params" and int literals -- cf. ParamRoleParamRoleNode, and isConstant +@Deprecated // Not currently used -- FIXME: name clash with org.scribble.ext.go.core.type.RPIndexedRole +public class RPIndexedRole extends AbstractName +{ + public final RPIndexExpr start; + public final RPIndexExpr end; + + private static final long serialVersionUID = 1L; + + protected RPIndexedRole(RPIndexExpr start, RPIndexExpr end) + { + super(RPIndexedRoleKind.KIND); + this.start = start; + this.end = end; + } + + public RPIndexedRole(String text, RPIndexExpr start, RPIndexExpr end) + { + super(RPIndexedRoleKind.KIND, text); + this.start = start; + this.end = end; + } + + public boolean isSingleton() + { + return this.start.equals(this.end); + } + + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof RPIndexedRole)) + { + return false; + } + RPIndexedRole them = (RPIndexedRole) o; + return super.equals(o) // Does canEqual + && this.start.equals(them.start) && this.end.equals(them.end); + } + + public boolean canEqual(Object o) + { + return o instanceof RPIndexedRole; + } + + @Override + public int hashCode() + { + int hash = 7187; + hash = 31*hash + super.hashCode(); + hash = 31*hash + this.start.hashCode(); + hash = 31*hash + this.end.hashCode(); + return hash; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/util/IntPairSmt2Translator.java b/scribble-go/src/main/java/org/scribble/ext/go/util/IntPairSmt2Translator.java new file mode 100644 index 000000000..208950778 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/util/IntPairSmt2Translator.java @@ -0,0 +1,66 @@ +package org.scribble.ext.go.util; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.main.GoJob; + +public class IntPairSmt2Translator extends Smt2Translator +{ + public IntPairSmt2Translator(GoJob job, GProtocolDecl global) + { + super(job, global); //Sort.Pair); + } + + @Override + public String getSort() + { + return "(Pair Int Int)"; + } + + @Override + public String getZeroValue() + { + return "(mk-pair 0 0)"; + } + + @Override + public String getDefaultBaseValue() + { + return "(mk-pair 1 1)"; + } + + @Override + public String getLtOp() + { + return "pair_lt"; + } + + @Override + public String getLteOp() + { + return "pair_lte"; + } + + @Override + public String getGtOp() + { + return "pair_gt"; + } + + @Override + public String getGteOp() + { + return "pair_gte"; + } + + @Override + public String getPlusOp() + { + return "pair_plus"; + } + + @Override + public String getSubOp() + { + return "pair_sub"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/util/IntSmt2Translator.java b/scribble-go/src/main/java/org/scribble/ext/go/util/IntSmt2Translator.java new file mode 100644 index 000000000..380f3e2f7 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/util/IntSmt2Translator.java @@ -0,0 +1,66 @@ +package org.scribble.ext.go.util; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.main.GoJob; + +public class IntSmt2Translator extends Smt2Translator +{ + public IntSmt2Translator(GoJob job, GProtocolDecl global) + { + super(job, global); //Sort.Int); + } + + @Override + public String getSort() + { + return "Int"; + } + + @Override + public String getZeroValue() + { + return "0"; + } + + @Override + public String getDefaultBaseValue() + { + return "1"; + } + + @Override + public String getLtOp() + { + return "<"; + } + + @Override + public String getLteOp() + { + return "<="; + } + + @Override + public String getGtOp() + { + return ">"; + } + + @Override + public String getGteOp() + { + return ">="; + } + + @Override + public String getPlusOp() + { + return "+"; + } + + @Override + public String getSubOp() + { + return "-"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/util/RecursiveFunctionalInterface.java b/scribble-go/src/main/java/org/scribble/ext/go/util/RecursiveFunctionalInterface.java new file mode 100644 index 000000000..790289cec --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/util/RecursiveFunctionalInterface.java @@ -0,0 +1,7 @@ +package org.scribble.ext.go.util; + +// Duplicated from org.scribble.ext.assrt.util +public class RecursiveFunctionalInterface // F should be a functional interface +{ + public F func; +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/util/Smt2Translator.java b/scribble-go/src/main/java/org/scribble/ext/go/util/Smt2Translator.java new file mode 100644 index 000000000..82212fe24 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/util/Smt2Translator.java @@ -0,0 +1,130 @@ +package org.scribble.ext.go.util; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.main.GoJob; + +public abstract class Smt2Translator +{ + public final GoJob job; + public final GProtocolDecl global; + + /*enum Sort { Int, Pair } + + private final Sort sort;*/ + + public Smt2Translator(GoJob job, GProtocolDecl global) + { + this.job = job; + this.global = global; + //this.sort = sort; + } + + public abstract String getSort(); + public abstract String getLtOp(); + public abstract String getLteOp(); + public abstract String getGtOp(); + public abstract String getGteOp(); + public abstract String getPlusOp(); + public abstract String getSubOp(); + + public abstract String getZeroValue(); + public abstract String getDefaultBaseValue(); + + //public String makeVarDecl(RPIndexVar v) + public String makeVarDecl(String v) + { + return "(" + v//.toSmt2Formula() + + " " + getSort() + ")"; // Factor out + } + + //public String makeExists(List vars, String body) + public String makeExists(List vars, String body) + { + return "(exists " + + "(" + vars.stream().map(x -> makeVarDecl(x)).collect(Collectors.joining(" ")) + ")" + + " " + body + ")"; + } + + //public String makeForall(List vars, String body) + public String makeForall(List vars, String body) + { + // TODO: factor out with above + return "(forall " + + "(" + vars.stream().map(x -> makeVarDecl(x)).collect(Collectors.joining(" ")) + ")" + + " " + body + ")"; + } + + public String makeLt(String x, String y) + { + return "(" + getLtOp() + " " + x + " " + y + ")"; + } + + public String makeLte(String x, String y) + { + return "(" + getLteOp() + " " + x + " " + y + ")"; + } + + public String makeGt(String x, String y) + { + return "(" + getGtOp() + " " + x + " " + y + ")"; + } + + public String makeGte(String x, String y) + { + return "(" + getGteOp() + " " + x + " " + y + ")"; + } + + public String makePlus(String x, String y) + { + return "(" + getPlusOp() + " " + x + " " + y + ")"; + } + + public String makeSub(String x, String y) + { + return "(" + getSubOp() + " " + x + " " + y + ")"; + } + + public String makeEq(String x, String y) + { + return "(= " + x + " " + y + ")"; + } + + public String makeAnd(String... cs) // OK because cs last parameter + { + return makeAnd(Arrays.asList(cs)); + } + + public String makeAnd(List cs) + { + return "(and " + cs.stream().collect(Collectors.joining(" ")) + ")"; + } + + public String makeImplies(String left, String right) + { + return "(implies " + left + " " + right + ")"; + } + + public String makeOr(String... cs) + { + return makeOr(Arrays.asList(cs)); + } + + public String makeOr(List cs) + { + return "(or " + cs.stream().collect(Collectors.joining(" ")) + ")"; + } + + public String makeNot(String c) + { + return "(not " + c + ")"; + } + + public String makeAssert(String body) + { + return "(assert " + body + ")"; + } +} diff --git a/scribble-go/src/main/java/org/scribble/ext/go/util/Z3Wrapper.java b/scribble-go/src/main/java/org/scribble/ext/go/util/Z3Wrapper.java new file mode 100644 index 000000000..e7852aeb3 --- /dev/null +++ b/scribble-go/src/main/java/org/scribble/ext/go/util/Z3Wrapper.java @@ -0,0 +1,97 @@ +package org.scribble.ext.go.util; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Set; + +import org.scribble.ast.ProtocolDecl; +import org.scribble.ast.global.GProtocolDecl; +import org.scribble.ext.go.core.ast.global.RPCoreGType; +import org.scribble.ext.go.core.type.RPIndexedRole; +import org.scribble.ext.go.main.GoJob; +import org.scribble.ext.go.type.index.RPIndexIntPair; +import org.scribble.main.ScribbleException; +import org.scribble.type.kind.Global; +import org.scribble.util.ScribUtil; + +// "Native" Z3 -- not Z3 Java API +public class Z3Wrapper +{ + + public static Smt2Translator getSmt2Translator(GoJob job, GProtocolDecl gpd, RPCoreGType gt) + { + Set irs = gt.getIndexedRoles(); + if (irs.isEmpty() || // FIXME: hardcoded default + irs.stream().allMatch(x -> x.intervals.stream().allMatch(y -> y.getIndexVals().stream().noneMatch(z -> z instanceof RPIndexIntPair)))) + { + return new IntSmt2Translator(job, gpd); + } + else if (irs.stream().allMatch(x -> x.intervals.stream().allMatch(y -> y.getIndexVals().stream().allMatch(z -> z instanceof RPIndexIntPair)))) + { + return new IntPairSmt2Translator(job, gpd); + } + else + { + throw new RuntimeException("Shouldn't get in here: " + irs); + } + } + + // Based on CommandLine::runDot, JobContext::runAut, etc + public static boolean checkSat(GoJob job, ProtocolDecl gpd, String smt2) //throws ScribbleException + { + //String tmpName = gpd.header.name + "_" + ".smt2.tmp"; + File tmp = null; //= new File(tmpName); + /*if (tmp.exists()) // Factor out with CommandLine.runDot (file exists check) // Now redundant, using createTempFile + { + throw new RuntimeException("Cannot overwrite: " + tmp.getAbsolutePath()); + }*/ + smt2 = "(declare-datatypes (T1 T2) ((Pair (mk-pair (fst T1) (snd T2)))))\n" + + "(define-fun pair_max ((p!1 (Pair Int Int))) Int (ite (< (fst p!1) (snd p!1)) (snd p!1) (fst p!1) ) )\n" + + "(define-fun pair_min ((p!1 (Pair Int Int))) Int (ite (< (fst p!1) (snd p!1)) (fst p!1) (snd p!1)))\n" + + "(define-fun twopair_max ((p!1 (Pair Int Int)) (p!2 (Pair Int Int))) Int (ite (< (pair_max p!1) (pair_max p!2)) (pair_max p!2) (pair_max p!1)))\n" + + "(define-fun twopair_min ((p!1 (Pair Int Int)) (p!2 (Pair Int Int))) Int (ite (< (pair_min p!1) (pair_min p!2)) (pair_min p!1) (pair_min p!2)))\n" + + "(define-fun pair_lte ((p!1 (Pair Int Int)) (p!2 (Pair Int Int))) Bool (and (<= (fst p!1) (fst p!2)) (<= (snd p!1) (snd p!2)) ))\n" + + "(define-fun pair_lt ((p!1 (Pair Int Int)) (p!2 (Pair Int Int))) Bool (and (pair_lte p!1 p!2) (not (= p!1 p!2))))\n" + + "(define-fun pair_gte ((p!1 (Pair Int Int)) (p!2 (Pair Int Int))) Bool (pair_lte p!2 p!1))\n" + + "(define-fun pair_gt ((p!1 (Pair Int Int)) (p!2 (Pair Int Int))) Bool (pair_lt p!2 p!1))\n" + + "(define-fun pair_plus ((p!1 (Pair Int Int)) (p!2 (Pair Int Int))) (Pair Int Int) (mk-pair (+ (fst p!1) (fst p!2)) (+ (snd p!1) (snd p!2))))\n" + + "(define-fun pair_sub ((p!1 (Pair Int Int)) (p!2 (Pair Int Int))) (Pair Int Int) (mk-pair (- (fst p!1) (fst p!2)) (- (snd p!1) (snd p!2))))\n" + + smt2; + smt2 = smt2 + "\n(check-sat)\n(exit)"; + try + { + tmp = File.createTempFile(gpd.header.name.toString(), ".smt2.tmp"); + ScribUtil.writeToFile(tmp, smt2); + String[] res = ScribUtil.runProcess("z3", tmp.getAbsolutePath());//, "-T:60"); + String trim = res[0].trim(); + if (trim.equals("sat")) // FIXME: factor out + { + return true; + } + else if (trim.equals("unsat")) + { + return false; + } + else + { + throw new RuntimeException("[assrt] Z3 error: " + Arrays.toString(res)); + } + } + catch (IOException x) + { + throw new RuntimeException(x); + } + catch (ScribbleException e) + { + throw new RuntimeException(e); + } + finally + { + if (tmp != null) + { + tmp.delete(); + } + } + } +} diff --git a/scribble-go/src/test/scrib/param/cgo18/AllToAll.scr b/scribble-go/src/test/scrib/param/cgo18/AllToAll.scr new file mode 100644 index 000000000..1e75b1a45 --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/AllToAll.scr @@ -0,0 +1,8 @@ +module param.cgo18.AllToAll; + +type "int" from "runtime" as int; + +global protocol P(role A(N, M), role B(N, M)) +{ + Msg(int) from A[1..N] to B[1..M]; +} diff --git a/scribble-go/src/test/scrib/param/cgo18/AllToOne.scr b/scribble-go/src/test/scrib/param/cgo18/AllToOne.scr new file mode 100644 index 000000000..32fc62b74 --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/AllToOne.scr @@ -0,0 +1,8 @@ +module param.cgo18.AllToOne; + +type "int" from "runtime" as int; + +global protocol P(role A(N), role B(N)) +{ + Msg(int) from A[1..N] to B[1..1]; +} diff --git a/scribble-go/src/test/scrib/param/cgo18/Auction.scr b/scribble-go/src/test/scrib/param/cgo18/Auction.scr new file mode 100644 index 000000000..917a8f4ec --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/Auction.scr @@ -0,0 +1,94 @@ +//Raymond@HZHL3 ~/code/eclipse/scribble/github.com/rhu1-go/scribble-java +//$ bin/scribblec-param.sh -ip scribble-go/src/test/scrib/ -d scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/cgo18/Auction.scr -param Proto1 + +module param.cgo18.Auction; + + +type "int" from "..." as int; + + +//* +global protocol Proto1(role A(n), role B(n)) +{ + bid(int) from B[1..n] to A[1..1]; + + do X(A, B); +} + +// mu X +aux global protocol X(role A, role B) +{ + choice at A[1] + { + highestBidSoFar(int) from A[1..1] to B[1..n]; + + choices at B[i:1..n] + { + bid(int) from B[i] to A[1..1]; + do X(A, B); + } + or + { + skip(int) from B[i] to A[1..1]; + do X(A, B); + } + } + or + { + winner() from A[1..1] to B[1..n]; + } +} +//*/ + + + + + + + + +/* +// mu X +aux global protocol X(role A, role B(n)) +{ + choice at A[1] + { + highestbid(int) from A[1..1] to B[1..n]; + + /* // If "directly" corresponding to formalism + wigglychoice at B[i:1..n] + { + bid(int) wigglyarrow B[i] to A[1..1]; + } + or + { + skip(int) wigglyarrow B[i] to A[1..1]; + }*/ + + // Version to implement + /*foreach (i: 1..n) + { + choice at B[i]* / + choices at B[i:1..n] + { + bid(int) from B[i] to A[1..1]; + do X(A, B); + } + or + { + skip(int) from B[i] to A[1..1]; + do X(A, B); + } + //} + + // "Traditional MPST" solution + //bidOrSkip(int) from B[1..n] to A[1..1]; + + //do X(A, B); + } + or + { + winner() from A[1..1] to B[1..n]; + } +} +//*/ diff --git a/scribble-go/src/test/scrib/param/cgo18/Htcat.scr b/scribble-go/src/test/scrib/param/cgo18/Htcat.scr new file mode 100644 index 000000000..841475a1d --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/Htcat.scr @@ -0,0 +1,46 @@ +//Raymond@HZHL3 ~/code/eclipse/scribble/github.com/rhu1-go/scribble-java +//$ bin/scribblec-go.sh -ip scribble-go/src/test/scrib/ -d +//scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/cgo18/Htcat.scr -param Proto1 + +module param.cgo18.Htcat; + + +type "cat" from "..." as cat; +type "int" from "..." as int; +type "frag" from "..." as frag; +type "err" from "..." as err; + + +global protocol Htcat(role M(n), role W(n)) +{ + get(cat) from M[1..1] to W[1..n]; + + do HtcatProto(M, W); +} + +aux global protocol HtcatProto(role M, role W) +{ + choice at M[1] + { + cont() from M[1..1] to W[1..n]; + + choices at W[i:1..n] + { + register(frag) from W[i] to M[1..1]; + do HtcatProto(M, W); + } or + { + cancel(err) from W[i] to M[1..1]; + do HtcatProto(M, W); + } or + { + lastFragment(int) from W[i] to M[1..1]; + do HtcatProto(M, W); + } + + } or + { + stop() from M[1..1] to W[1..n]; + } +} + diff --git a/scribble-go/src/test/scrib/param/cgo18/OneToAll.scr b/scribble-go/src/test/scrib/param/cgo18/OneToAll.scr new file mode 100644 index 000000000..ac0320ea9 --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/OneToAll.scr @@ -0,0 +1,8 @@ +module param.cgo18.OneToAll; + +type "int" from "runtime" as int; + +global protocol P(role A(N), role B(N)) +{ + Msg(int) from A[1..1] to B[1..N]; +} diff --git a/scribble-go/src/test/scrib/param/cgo18/OneToOne.scr b/scribble-go/src/test/scrib/param/cgo18/OneToOne.scr new file mode 100644 index 000000000..bee95bd3c --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/OneToOne.scr @@ -0,0 +1,8 @@ +module param.cgo18.OneToOne; + +type "int" from "runtime" as int; + +global protocol P(role A, role B) +{ + Msg(int) from A[1..1] to B[1..1]; +} diff --git a/scribble-go/src/test/scrib/param/cgo18/Reduce.scr b/scribble-go/src/test/scrib/param/cgo18/Reduce.scr new file mode 100644 index 000000000..ff05405d1 --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/Reduce.scr @@ -0,0 +1,43 @@ +//Raymond@HZHL3 ~/code/eclipse/scribble/github.com/rhu1-go/scribble-java +//$ bin/scribblec-param.sh -ip scribble-go/src/test/scrib/ -d scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/cgo18/SumEuler.scr -param Proto1 + +module param.cgo18.Reduce; + + +type "int" from "..." as int; +type "int[]" from "..." as intarray; + + +//* +global protocol Reduce( role M(N) + , role W(N) + , role R(N) + ) +{ + /* // ?? + M --> W[0][1..n] : <[] int> + forall (i < log n), + forall (j < i), + W[i][j*2] --> W[i+1][j] . W[i][j*2+1] --> W[i+1][j] + W[log n][0] --> M + */ + + distrib(intarray) from M[1..1] to W[1..8*N]; + + // These ranges seem to fail + redl1(intarray) from W[1 .. N] to R[1..1]; + redl1(intarray) from W[ N +1..2*N] to R[2..2]; + redl1(intarray) from W[(2*N)+1..3*N] to R[3..3]; + redl1(intarray) from W[(3*N)+1..4*N] to R[4..4]; + redl1(intarray) from W[(4*N)+1..5*N] to R[5..5]; + redl1(intarray) from W[(5*N)+1..6*N] to R[6..6]; + redl1(intarray) from W[(6*N)+1..7*N] to R[7..7]; + redl1(intarray) from W[(7*N)+1..8*N] to R[8..8]; + + /* Can we simplify this? */ + redl2(intarray) dot R[5..8] to R[1..4]; + redl3(intarray) dot R[3..4] to R[1..2]; + redl4(intarray) dot R[2..2] to R[1..1]; + gather(intarray) dot R[1..1] to M[1..1]; +} +//*/ diff --git a/scribble-go/src/test/scrib/param/cgo18/Ring.scr b/scribble-go/src/test/scrib/param/cgo18/Ring.scr new file mode 100644 index 000000000..f8de7a20c --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/Ring.scr @@ -0,0 +1,110 @@ +//Raymond@HZHL3 ~/code/eclipse/scribble/github.com/rhu1-go/scribble-java +//$ bin/scribblec-param.sh -ip scribble-go/src/test/scrib/ -d scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/cgo18/Ring.scr -param Proto1 + +module param.cgo18.Ring; + + +type "int" from "..." as int; + + +global protocol Proto1(role B(k)) +{ + choice at B[1] + { + m1(int) dot B[1..k] to B[2..k+1]; + m1(int) dot B[k+1..k+1] to B[1..1]; + //m1(int) from B[k+1..k+1] to B[1..1]; // Equivalent to above line + + do Proto1(B); + } + or + { + m2(int) dot B[1..k] to B[2..k+1]; + m2(int) dot B[k+1..k+1] to B[1..1]; + //m2(int) from B[k+1..k+1] to B[1..1]; // Equivalent to above line + } +} + + + +/* +global protocol Proto2(role B(k)) +{ + m1(int) dot B[1..k] to B[2..k+1]; + m1(int) dot B[k+1..k+1] to B[1..1]; + m1(int) dot B[1..k] to B[2..k+1]; + m1(int) dot B[k+1..k+1] to B[1..1]; + //... + m1(int) dot B[1..k] to B[2..k+1]; + m1(int) dot B[k+1..k+1] to B[1..1]; +} + + +global protocol Proto3(role B(k)) +{ + choice at B[1] + { + m1(int) from B[1..1] to B[2..k+1]; + m1(int) dot B[1..k] to B[2..k+1]; + m1(int) dot B[k+1..k+1] to B[1..1]; + + do Proto3(B); + } + or + { + m2(int) from B[1..1] to B[2..k+1]; + m2(int) dot B[1..k] to B[2..k+1]; + m2(int) dot B[k+1..k+1] to B[1..1]; + } +} +//*/ + + +/* +global protocol Proto4(role B(k)) +{ + choices at B[i:1..k+1] + { + m1(int) from B[i] to B[i+1]; // Projection at dest? + m1(int) dot B[k+1..k+1] to B[1..1]; + + do Proto4(B); + } + or + { + m2(int) from B[i] to B[i+1]; + m2(int) dot B[k+1..k+1] to B[1..1]; + } +} +//*/ + + + +/* +global protocol Proto1(role B(k)) // FIXME: role param WF -- params only for root protos? +{ + choice at B[1] // FIXME: role index WF? + { + //m1(int) dot B[1..k-1] to B[2..k]; // FIXME: k>2 global invariant // FIXME: range-sensitive role enabling -- a Scribble-specific issue, choice subjs + //m1(int) dot B[k..k] to B[1..1]; + + //m1(int) dot B[1..k] to B[2..k+1]; + //m1(int) dot B[k+1..k+1] to B[1..1]; + + m1(int) from B[1..1] to B[2..k+1]; + m1(int) dot B[1..k] to B[2..k+1]; + m1(int) dot B[k+1..k+1] to B[1..1]; + + do Proto1(B); // FIXME: role params? or disallow role permuting? + } + or + { + //m2(int) dot B[1..k-1] to B[2..k]; + //m2(int) dot B[k..k] to B[1..1]; + + m2(int) from B[1..1] to B[2..k+1]; + m2(int) dot B[1..k] to B[2..k+1]; + m2(int) dot B[k+1..k+1] to B[1..1]; + } +} +//*/ diff --git a/scribble-go/src/test/scrib/param/cgo18/ScatterGather.scr b/scribble-go/src/test/scrib/param/cgo18/ScatterGather.scr new file mode 100644 index 000000000..ddfd1c2ea --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/ScatterGather.scr @@ -0,0 +1,18 @@ +//Raymond@HZHL3 ~/code/eclipse/scribble/github.com/rhu1-go/scribble-java +//$ bin/scribblec-param.sh -ip scribble-go/src/test/scrib/ -d scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/cgo18/ScatterGather.scr -param Proto1 -param-fsm B + +module param.cgo18.ScatterGather; + + +type "int" from "..." as int; + + +//* +global protocol Proto1(role A(k), role B(k)) +{ + scatter(int) from A[1..1] to B[1..k]; + gather(int) from B[1..k] to A[1..1]; +} +//*/ + + diff --git a/scribble-go/src/test/scrib/param/cgo18/SpectralNorm.scr b/scribble-go/src/test/scrib/param/cgo18/SpectralNorm.scr new file mode 100644 index 000000000..5e5d8b383 --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/SpectralNorm.scr @@ -0,0 +1,21 @@ +//Raymond@HZHL3 ~/code/eclipse/scribble/github.com/rhu1-go/scribble-java +//$ bin/scribblec-param.sh -ip scribble-go/src/test/scrib/ -d scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/cgo18/SpectralNorm.scr -param Proto1 + +module param.cgo18.SpectralNorm; + + +type "int" from "..." as int; +type "..." from "..." as vec; + + +//* +global protocol Proto1(role M(n), role W(n)) +{ + Data(int, int) from M[1..1] to W[1..n]; + Data(vec) from M[1..1] to W[1..n]; + Data(vec) from W[1..n] to M[1..1]; // here master-workers compute x + Data(vec) from M[1..1] to W[1..n]; + Data(vec) from W[1..n] to M[1..1]; // here master-workers compute v + do Proto1(M, W); +} +//*/ diff --git a/scribble-go/src/test/scrib/param/cgo18/SumEuler.scr b/scribble-go/src/test/scrib/param/cgo18/SumEuler.scr new file mode 100644 index 000000000..6532bdde3 --- /dev/null +++ b/scribble-go/src/test/scrib/param/cgo18/SumEuler.scr @@ -0,0 +1,17 @@ +//Raymond@HZHL3 ~/code/eclipse/scribble/github.com/rhu1-go/scribble-java +//$ bin/scribblec-param.sh -ip scribble-go/src/test/scrib/ -d scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/cgo18/SumEuler.scr -param Proto1 + +module param.cgo18.SumEuler; + + +type "int" from "..." as int; +type "int[]" from "..." as intarray; + + +//* // cf. ScatterGather.scr +global protocol Proto1(role M(n), role W(n)) +{ + 1(intarray) from M[1..1] to W[1..n]; + 2(int) from W[1..n] to M[1..1]; +} +//*/ diff --git a/scribble-go/src/test/scrib/param/tmp/ParamTest.scr b/scribble-go/src/test/scrib/param/tmp/ParamTest.scr new file mode 100644 index 000000000..be8bf837f --- /dev/null +++ b/scribble-go/src/test/scrib/param/tmp/ParamTest.scr @@ -0,0 +1,1212 @@ +//Raymond@HZHL3 ~/code/eclipse/scribble/github.com/rhu1-go/scribble-java +//$ bin/scribblec-param.sh -ip scribble-go/src/test/scrib/ -d scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/tmp/ParamTest.scr -V -param Proto1 +//$ bin/scribblec-param.sh -ip scribble-go/src/test/scrib/ scribble-go/src/test/scrib/param/tmp/ParamTest.scr -V -param Proto1 github.com/rhu1-go/scribble-java/src/test/scrib/param/tmp/ParamTest -param-api S + +// http://sandbox.kidstrythisathome.com/erdos/ + + +module param.tmp.ParamTest; + + +global protocol Proto1(role A, role B) @"K>=(1,1)" +{ + Foo() from A[(1,1)] to B[K]; +} + + +/* +global protocol Proto1(role A, role B, role C) +{ + Foo() from A[1] to C[1]; + Foo() from A[1] to B[1]; + Foo() from A[1] to B[1,K]; + Foo() from A[1] to B[2,K]; // Testing "domain" clauses, here 2 <= K, put outside neg of neg Phi for family check + //Foo() from B[1] to B[2,K]; +} +/*/ + + +/* +global protocol Proto1(role A, role B) +{ + foreach B[I:1,K] + { + Foo() from A[1] to B[I]; + } +} +//*/ + + +/* +sig "message.Parse" from "github.com/nickng/scribble-go-examples/20_webcrawler/message" as Parse; +sig "message.Index" from "github.com/nickng/scribble-go-examples/20_webcrawler/message" as Index; +sig "message.URL" from "github.com/nickng/scribble-go-examples/20_webcrawler/message" as URL; + +global protocol Proto1(role Downloader, role Parser, role Indexer, role Master) { + foreach Downloader[I:1,N], Parser[J:1,N] { + Parse from Downloader[I] to Parser[J]; + } + Index from Parser[1,N] to Indexer[1]; + URL from Indexer[1] to Master[1]; +} +//*/ + + +/* +global protocol Proto1(role P, role Q) +{ + Play(Game@A) from Q[1] to P[1,K]; +} + +global protocol Game(role A, role B, role C) +{ + Foo() from A[1] to B[1]; + Bar() from A[1] to C[1]; +} +//*/ + + +/* +global protocol Proto1(role A, role B) +{ + foreach B[I:1,K] + { + choice at A[1] + { + Foo() from A[1] to B[I]; + } + or + { + Bar() from A[1] to B[I]; + } + } +} +//*/ + + +/* +sig "message.QuoteReq" from "github.com/nickng/scribble-go-examples/11_quote-request/message" as QuoteReq; +type "message.Quote" from "github.com/nickng/scribble-go-examples/11_quote-request/message" as Quote; + +global protocol Proto1(role Buyer, role Supplier, role Manufacturer) { + // (1) Buyer requests quote from Suppliers. + QuoteReq from Buyer[1] to Supplier[1,S]; + do Negotiate(Buyer, Supplier, Manufacturer); +} + +aux global protocol Negotiate(role Buyer, role Supplier, role Manufacturer) { + // (2) All Suppliers forward quote request to their Manufacturers. + /*foreach Supplier[I:1,S] { + foreach Manufacturer[J:1,M] { + QuoteReq from Supplier[I] to Manufacturer[J]; + Reply(Quote) from Manufacturer[J] to Supplier[I]; + } + }* / + QuoteReq from Supplier[1,S] to Manufacturer[1,M]; + Reply(Quote) from Manufacturer[1,M] to Supplier[1,S]; + // (3) Suppliers build quote for the Buyer, + // which is then sent back to the Buyer. + Reply(Quote) from Supplier[1,S] to Buyer[1]; + do MakeDeal(Buyer, Supplier, Manufacturer); +} + +aux global protocol MakeDeal(role Buyer, role Supplier, role Manufacturer) { + choice at Buyer[1] { + // (4a) Either the Buyer agrees to the quote and place order. + Order(Quote) from Buyer[1] to Supplier[1,S]; + End() from Supplier[1] to Manufacturer[1,M]; + End() from Supplier[1,S] to Manufacturer[1,M]; + } or { + // (4b) Or the Buyer modify the quote and send back to Suppliers. + Modify(Quote) from Buyer[1] to Supplier[1,S]; + Wait() from Supplier[1] to Manufacturer[1,M]; + Wait() from Supplier[1,S] to Manufacturer[1,M]; + + do UpdatedQuoteRequest(Buyer, Supplier, Manufacturer); + } +} + +aux global protocol UpdatedQuoteRequest(role Buyer, role Supplier, role Manufacturer) { + // (5) Supplier received updated quote + foreach Supplier[I:1,S] { + choice at Supplier[I] { + // (5a) Either Supplier respond by agreeing to it and sending a confirmation + Confirm() from Supplier[I] to Buyer[1]; + End() from Supplier[I] to Manufacturer[1,M]; + } or { + // (5b) Or Supplier modify it and sending it back to Buyer. + // Buyer goes back to (4) + Modify(Quote) from Supplier[I] to Buyer[1]; + NoOp() from Supplier[I] to Manufacturer[1,M]; + //do MakeDeal(Buyer, Supplier, Manufacturer); // No: recursion out of foreach + } or { + // (5c) Or Supplier reject updated quote. + Reject() from Supplier[I] to Buyer[1]; + End() from Supplier[I] to Manufacturer[1,M]; + } or { + // (5d) Or Supplier renegotiate with the Manufacturers + // going back to (3) + Renegotiate() from Supplier[I] to Buyer[1]; + Renegotiate() from Supplier[I] to Manufacturer[1,M]; + //do Negotiate(Buyer, Supplier, Manufacturer); // No: recursion out of foreach + } + } +} +//*/ + + +/* +global protocol Proto1(role A, role B) +{ + Foo() from A[(1,1)] to B[K]; + //Foo() from A[1] to B[1]; +} +//*/ + + +/* +global protocol Proto1(role A, role B) +{ + Foo() from A[K] to B[K]; // FIXME: 1d or 2d? +} +//*/ + + +/* +//foreach { A , B , C }{ i:k 11 ..k wh } do ( A [ i ]→ C [ i ] :Val.B [ i ]→ C [ i ] :Val.cont ) ;end +global protocol Proto1(role A, role B, role C) +{ + foreach A[IA:(1,1),K], B[IB:(1,1),K], C[IC:(1,1),K] + { + Foo() from A[IA] to C[IC]; + Bar() from B[IB] to C[IC]; + } +} +//*/ + + +/* +//foreach W { i1 :k 11 ..k wh -(1,0) , i2 :k 11 +(1,0)..k wh } do ( W [ i 1 ]→ W [ i 2 ] .cont ) ; +//foreach W { i1 :k w1 ..k wh , i2 :k 11 ..k 1h } do ( W [ i 1 ]→ W [ i 2 ] .cont ) ; +//foreach W { i1 :k 11 ..k 1h -(0,1) , i2 :k 11 +(0,1)..k 1h } do ( W [ i 1 ]→ W [ i 2 ] .cont ) ;W [ k 1h ]→ W [ k 11 ] .end +global protocol Proto1(role W, role M) +{ + foreach W[I1:(1,1),K-(1,0)], W[I2:(1,1)+(1,0),K] { + Foo() from W[I1] to W[I2]; + } + /*Bar() from W[(1,1),Kwh] to M[1]; + foreach W[I1:(W,1),K], W[I2:(1,1),(1,H)] { + Foo() from W[I1] to W[I2]; + } + Bar() from W[(1,1),K] to M[1]; + /*foreach W[I1:(1,1),(1,H)-(0,1)], W[I2:(1,1)+(0,1),(1,H)] { + Foo() from W[I1] to W[I2]; + }* / +} +//*/ + + +/* +global protocol Proto1(role W) +{ + foreach W[I2:1,K-2], W[I1:2,K-1], W[I:3,K] + { + Foo() from W[I2] to W[I]; + Foo() from W[I1] to W[I]; + } +} + +/* +W{[1,(K-2)], [3,K]}{[I1]}, +W{[I1], [3,K]}{[1,(K-2)]}, +W{[I1]}{[1,(K-2)], [3,K]}, +W{[3,K]}{[1,(K-2)], [I1]}, +W{[1,(K-2)], [I1], [3,K]}, +W{[1,(K-2)], [I1]}{[3,K]}, +W{[1,(K-2)]}{[I1], [3,K]} +*/ +//*/ + + + +/* +global protocol Proto1(role A, role B) +{ + foreach A[I:1,N], B[J:1,N] { + Foo() from A[I] to B[J]; + } +} +//*/ + + +/* +global protocol Proto1(role A, role B) +{ + foreach Manufacturer[J:1,M] { + QuoteReq from Supplier[1,S] to Manufacturer[J]; + Quote from Manufacturer[J] to Supplier[1,S]; + } +} +//*/ + + + + + +/* +global protocol Proto1(role A, role B) +{ + Foo() from A[1] to B[1,K]; +} +*/ + + +/* +global protocol Proto1(role F, role S, role M) +{ + Head() from F[1] to S[1]; + Res() from S[1] to F[1]; + Meta() from F[1] to M[1]; + + Job() from M[1] to F[1,K]; + // Send jobs. + foreach F[I:1,K] + { + Get() from F[I] to S[1]; + Res() from S[1] to F[I]; + } + Data() from F[1,K] to M[1]; + } +//*/ + +/*Projection onto S{[1]}: mu param_tmp_ParamTest_Proto1___F__S__M_.F[1]?Head().F[1]!Res().foreach {F}{I:1..K} do F[I]?Get().F[I]!Res().cont ; end + +[rp-core] Built endpoint graph for S{[1]}: +digraph G { +compound = true; +"14" [ label="14: " ]; +"14" -> "16" [ label="F[1]?Head()" ]; +"16" [ label="16: " ]; +"16" -> "17" [ label="F[1]!Res()" ]; +"17" [ label="17: I:[1,K]; 10" ]; +} + +digraph G { +compound = true; +"10" [ label="10: " ]; +"10" -> "12" [ label="F[I]?Get()" ]; +"12" [ label="12: " ]; +"12" -> "13" [ label="F[I]!Res()" ]; +"13" [ label="13: " ]; +}*/ + + + +/* +global protocol Proto1(role A, role B) +{ + foreach A[I:1,KA] + { + foreach B[J:1,KB] + { + Foo() from A[I] to B[J]; + } + } +} +//*/ + + + + +/* +sig "http.HeadReq" from "github.com/rhu1/scribble-go-examples/9_pget/http" as Head; +sig "http.GetReq" from "github.com/rhu1/scribble-go-examples/9_pget/http" as Get; +sig "http.Response" from "github.com/rhu1/scribble-go-examples/9_pget/http" as Res; + +sig "msg.Meta" from "github.com/rhu1/scribble-go-examples/9_pget/msg" as Meta; +sig "msg.Job" from "github.com/rhu1/scribble-go-examples/9_pget/msg" as Job; +sig "msg.Data" from "github.com/rhu1/scribble-go-examples/9_pget/msg" as Data; +sig "msg.Done" from "github.com/rhu1/scribble-go-examples/9_pget/msg" as Done; + +global protocol Proto1(role M, role F, role S) { + // Get metadata (size) + Head from F[1] to S[1]; + Res from S[1] to F[1]; + Meta from F[1] to M[1]; + + // Send jobs. + Job from M[1] to F[1,K]; + Get from F[1,K] to S[1]; + Res from S[1] to F[1,K]; + Data from F[1,K] to M[1]; + + Foo(Sync@A) from F[1,K] to M[1]; +} + +aux global protocol Sync(role A, role B) { + Done from A[1] to B[1]; +} +//*/ + + + +/* +global protocol Proto1(role A, role B) +{ + Foo(Proto1a@C) from A[1] to B[1]; +} + +aux global protocol Proto1a(role C, role D) +{ + Bar() from C[1] to D[1]; +} +//*/ + + +/* +global protocol Proto1(role B) { + foreach B[I:2,K-1] { + Foo() from B[I+1] to B[1]; // FIXME: projection + } +} +//*/ + + +/* +global protocol Proto1(role B) { + foreach B[I:1,K], B[J:K,K+K] { // FIXME TODO foreach interval constraint + Foo() from B[I] to B[J]; + } +} +//*/ + + +/* +global protocol Proto1(role A, role B) { + foreach B[I:1,K] { + Foo() from A[1] to B[2]; // OK? FIXME projection -- have to consider if 2 is inside 1,K? + //Foo() from A[I] to B[I]; // FIXME TODO + } +} +//*/ + + +/* +global protocol Proto1(role A, role B) { + choice at A[1] + { + Foo() from A[1] to B[1]; + } + or + { + Bar() from A[1] to B[2]; + } +} +//*/ + + + +/* +global protocol Proto1(role A, role B) { + foreach B[I:1,K-1] { + Foo() from A[1] to B[I]; + //Foo() from A[1] to B[I+1]; // Bad if uncommented + //Foo() from B[I+1] to A[1]; // Bad if uncommented + } +} +//*/ + + +/* +global protocol Proto1(role B) { + foreach B[I:1,K] { + Foo() from B[I] to B[I]; // Bad + } +} +//*/ + + +/* +global protocol Proto1(role B) { + foreach B[I:1,K], B[J:1,K] { + Foo() from B[I] to B[J]; // Bad + } +} +//*/ + + +/* +global protocol Proto1(role B) { + foreach B[I:1,K-1], B[J:2,K] { + Foo() from B[I] to B[J]; // OK + } +} +//*/ + + +/* +global protocol Proto1(role B) { + foreach B[I:1,K], B[J:2,K+1] { // Bad + Foo() from B[I] to B[J]; + } +} +//*/ + + +/* +global protocol Proto1(role B) { + Foo() from B[1,2] to B[1,K]; // Bad + Foo() from B[1,2] to B[J,J+1]; // Bad +} +//*/ + + +/* +type "int" from "builtin" as int; +type "string" from "builtin" as string; +sig "msgsig.Request" from "github.com/nickng/httpget/msgsig" as Request; +sig "msgsig.Response" from "github.com/nickng/httpget/msgsig" as Response; + +global protocol Proto1(role M, role F, role S) { + URL(int) from M[1] to F[1,N]; + + foreach F[I:1,N] { + Request from F[I] to S[1]; + Response from S[1] to F[I]; + //tmp() from S[1] to M[1]; // FIXME: projection + } + + Done(string) from F[1,N] to M[1]; +} +//*/ + + + + +/* +- keep P + coP for "actual roles" -- needed for API gen -- ParamRole => ParamRoleName? cf. ParamRole ("actual") +- keep constraint for each "actual role" -- needed for API "selection" check +- index exprs +- WF G -- proto sig param decls +- examples + + +- how does prev pabble treat "actual roles"? e.g., pipeline +- how does prev pabble do projection wrt. arbitrary role ranges? + + +vs. pabble +- projection (distribution) +- type generation vs. code generation (related to above, heavyweight code generation needed because not fully projected) + +message passing +- abstract transport -- shared mem, TCP -- integrated +- domain flexibility -- parallel algs, Web services -- shared parameterised abstraction, concrete transport independence + + +// encode "multi-choices" by local role(thread) forking/joining? for dynamic join/leave use param-value dependency? (run-time checked?) + +// statechan interfaces -- use Go's structural typing, individual action funs -- combine with select-branch style +*/ + + +// Add a scribble version and time/date to API output header + + +// paramterisation subsumes multicast + + +/* +type "int" from "..." as int; +type "string" from "..." as string; +type "TwoBuyer.Address" from "scrib/twobuyer/TwoBuyer/TwoBuyer/types.go" as Address; +type "TwoBuyer.Date" from "scrib/twobuyer/TwoBuyer/TwoBuyer/types.go" as Date; + +sig "..." + from "..." + as Data; + +global protocol Proto1(role A, role B) { + foreach A[I:1,K], B[J:2,KK] + { + Data from A[I,I] to B[J,J]; + } +} +//*/ + + + +/*global protocol ScatterGather(role M, role S) { + (int) from M[1,1] to S[1,N]; +}*/ + + +/* +global protocol Proto1(role A(n)) +{ + /*a() from A[n-1..n-1] to A[n..n]; + b() from A[n-2..n-2] to A[n..n]; + do Proto1(A(n-1)); // FIXME? * / + + a() dot A[1..1] to A[n..n]; +} +//*/ + + + +/* +global protocol Proto1(role A(n, m), role B(n, m)) +{ + 1() from A[1..n] to B[1..m]; // (a) All-to-all, (unary) mult. choices +} + +global protocol Proto2(role A(n), role B(n)) +{ + 1() dot A[1..n] to B[1..n]; // (b) ones-to-ones, (unary) multi. choices +} +//*/ + + + + + + + + + + + + + + + +/*global protocol Proto3(role A(n), role B(n)) +{ + choices at A[i:1..n] + { + 1() dot A[1..n] to B[1..n]; // TODO (b) ones-to-ones, multi. choices + } + or + { + 2() dot A[1..n] to B[1..n]; + } +}*/ + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + choice at A[1] + { + //0() from A[1..n] to B[1..n]; // FIXME when unary-choice -- or OK? + //0() dot A[1..n] to B[1..n]; // FIXME when unary-choice -- or OK? + 0() from A[1..n] to B[1..n]; + } + or + { + 1() from A[1..n] to B[1..n]; + } +} +//*/ + + +/* +global protocol Proto1(role A(n,m), role B(n,m)) +{ + 0() dot A[1..n] to B[(m*2)+1..(m*2)+n]; +} +*/ + + +/* +global protocol Proto1(role A(n), role B(n), role S(n)) +{ + title(string) from A[1..1] to S[1..1]; + quote(int) from S[1..1] to A[1..1]; + quote(int) from S[1..1] to B[1..n]; + share(int) from A[1..1] to B[1..n]; + choice at B[1] + { + ok(Address) from B[1..1] to S[1..1]; + (Date) from S[1..1] to B[1..1]; + choice at B[1] + { + ok() from B[1..1] to B[2..n]; + } + or + { + quit() from B[1..1] to B[2..n]; + } + } + or + { + quit() from B[1..1] to S[1..1]; + choice at B[1] + { + ok() from B[1..1] to B[2..n]; + } + or + { + quit() from B[1..1] to B[2..n]; + } + } +} +*/ + +/* +global protocol Proto1(role A(n, m), role B(n, m)) +{ + 1() from A[1..1] to B[n..n]; // Testing actual role "naming" + 2() from A[1..1] to B[m..m]; +} +//*/ + + +/* +global protocol Proto1(role A(n), role B(n)) // Testing API gen +{ + 1() from A[1..1] to B[1..n]; + 2() from B[1..n] to B[1..1]; +} +//*/ + +/* +global protocol P1(role A(N), role B(N)) +{ + Msg(int) from A[1..(N-1)] to B[1..1]; +} + +global protocol P2(role A(N), role B(N)) +{ + Msg(int) from A[N..(N+N)] to B[1..1]; +} +//*/ + + +/*global protocol Proto1(role A(k), role B(k)) +{ + 1() from A[1..1] to B[k+k..(k+k)+k]; +}*/ + +/*global protocol Proto1(role A(n, m), role B(n, m)) +{ + //1() from A[1..m] to B[m+1..n]; + 1() from A[1..m] to B[m+1..(m+1)+n]; +} +//*/ + +/* +global protocol Proto1(role A(n), role B(n)) +{ + choices at A[i:1..n] + { + 1() from A[i] to B[1..1]; + 3() from B[1..1] to A[1..n]; + } + or + { + 2() from A[i] to B[1..1]; + 3() from B[1..1] to A[1..n]; + } +} +//*/ + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + choices at A[i:1..n] + { + 1() from A[i] to B[1..i]; // FIXME: bad "i" + //1() from A[j] to B[1..1]; // FIXME: bad "i" + } +} +//*/ + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + 1() dot A[1..n] to B[1+1..n+1]; +} +//*/ + + +/* +global protocol Proto1(role A(n)) +{ + 1() dot A[1..n] to A[2..n+1]; + 2() dot A[3..n+3] to A[4..n+4]; +} +//*/ + + +/* +global protocol Proto1(role A(n)) +{ + choice at A[1] + { + 1() dot A[1..n] to A[2..n+1]; + } + or + { + 2() dot A[1..n] to A[2..n+1]; + //2() dot A[2..n+1] to A[1..n]; // Bad: non-directed + } + + + /*choices at A[i:1..n] + { + 1() from A[i] to B[1..1]; + //1() from B[1..1] to A[i]; // Not allowed + }* / +} +//*/ + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + choices at A[i:1..n] + { + //1(int) from A[i+1] to B[1..1]; // Allow? + + //1(int) from A[i] to B[i+1]; // Allow? // Key point of foreach? relative indexing -- how to derive actual roles? + // A[i:1..n] ->* B[i+1:1..n]: 1() . end ? + // for (i:1..n) ( A[i] ->* B[i+1]: 1() . end ) + } +} +//*/ + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + /*choices at A[i:1..n] + { + 1() from A[i] to B[1..1]; + }* / + + /*choice at A[1] + { + 1() from A[1..1] to B[1..1]; + }* / + + 1() from A[1..n] to B[1..1]; // Above and this are equivalent for n=1 +} +//*/ + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + choices at A[i:1..n] + { + 1() from A[i] to B[1..2]; + + //3() from A[1..n] to B[1..2]; + } + or + { + 2() from A[i] to B[1..2]; + //2() from A[1..1] to B[1..2]; + + //3() from A[1..n] to B[1..2]; // OK + //3() from A[1..1] to B[1..2]; // Bad + } + + //3() from A[1..n] to B[1..2]; // FIXME: support this for param-core multi-choices? +} +//*/ + + + + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + //choice at A[i:1..n] + choice at A[1] + { + 1() from A[1..1] to B[1..2]; // OK + + //1() from A[1..2] to B[1..2]; // Bad + //1() from A[1..n] to B[1..2]; // Bad + } + or + { + 2() from A[1..1] to B[1..2]; + } +} +//*/ + + + + +/*// A=Auctioneer, B=Bidder +global protocol Auction(role A(n), role B(n)) +{ + bid(int) from B[1..n] to A; // A[1..1] + + do X(A, B); +} + +// mu X +aux global protocol X(role A, role B(n)) +{ + choice at A + { + highestbid(int) from A to B[1..n]; + + specialchoice at B[i:1..n] + { + bid(int) specialarrow B[i] to A; + } + or + { + skip(int) specialarrow B[i] to A; + } + + + for (i: 1..n) + { + choice at B[i] + { + bid(int) from B[i] to A; + } + or + { + skip(int) from B[i] to A; + } + } + //bidOrSkip(int) from B[1..n] to A; + + do X(A, B); + } + or + { + winner() from A to B[1..n]; + } +} +//*/ + + + /*choice at B[1..n] + { + bid() fromto A; + } + or + { + skip() from B[1..n] to A; + }*/ + + + + + + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + /*bid() from B[1..n] to A[1..1]; + + ... + + bidorskip(x:int) from B[1..n] to A[1..1]; + + choice at A[1] + { + highestbid() from A[1..1] to B[1..n]; + do Proto1(A, B); + } + or + { + + win() from A[1..1] to B[1..n]; + }*/ + + + /*do MyBiddingSubproto(A, B); + do MyBiddingSubproto(A, C); + do MyBiddingSubproto(A, D); + ... + + + for (i 1 .. N) + { + do MyBiddingSubproto(A, B[i]); + }* / + + choice at B[1..n] + { + bid() from B[1..n] to A[1..1]; + } + or + { + skip() from B[1..n] to A[1..1]; + } + + bidorskip(x:int) from B[1..n] to A[1..1]; + + G +} + + + +/* +global protocol Proto1(role A(n, m), role B(n, m)) +{ + 1() from A[1..1] to B[1..m*n]; +} +//*/ + + +/* +global protocol Proto1(role A(n, m)) +//global protocol Proto1(role A(n, m), role B(n, m)) +{ + //1() from A[1..n-1] to A[2..2]; // Currently bad range interval under n>=1 + + //1() from A[1..n+1] to A[2..2]; // Bad, overlapping for n>=1 + + //1() from A[1..n+m] to B[1..1]; // OK + + //1() from A[1..n+m] to A[1..1]; // Bad, overlapping + + 1() from A[1..1] to A[n..n+1]; // Bad + //1() from A[1..1] to A[n+1..n+2]; // OK +} +//*/ + + +/* +//global protocol Proto1(role A(n, m)) +global protocol Proto1(role A(n, m), role B(n, m)) +{ + //1() dot A[1..n] to A[1..n]; // Bad -- ruled out by self-comm + + //1() dot A[1..n] to A[2..n+1]; // OK + + //1() dot A[1..n] to A[1+1..n+2]; // Bad + + //1() dot A[1..1+n] to A[m..m+n]; // Bad + //1() dot A[1..1+n] to A[2..2+n]; // OK + + //1() dot A[1..1+n] to B[1..1+m]; // Bad + //1() dot A[1..1+n] to B[m..m+n]; // OK +} +//*/ + +/* +global protocol Proto1(role A, role B) +{ + choice at A[1] + { + 1() from A[1..1] to B[1..2]; + } + or + { + 2() from A[1..1] to B[1..2]; + } +} +//*/ + +/* +global protocol Proto1(role A, role B) +{ + choice at A[1] + { + 1() from A[1..1] to B[1..1]; + 1() from A[1..1] to B[2..2]; // Bad, non-directed choice + } + or + { + 2() from A[1..1] to B[2..2]; + 2() from A[1..1] to B[1..1]; + } +} +//*/ + +/* +global protocol Proto1(role A, role B) +{ + choice at A[1] + { + 1() from A[2..2] to B[1..1]; // FIXME: role-enabling -- Scribble detail, also proto sig param decls + } +} +//*/ + +/* +global protocol Proto1(role A) +{ + //1() from A[1..1] to A[2..2]; // OK + //1() from A[1..1] to A[1..1]; // Bad + 1() from A[1..1] to A[1..2]; // FIXME: should be bad +} +//*/ + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + 1() from A[1..1] to B[1..n]; + 2() from B[1..n] to A[1..1]; + //do Proto1(A, B); // OK + do Proto1(B, A); // OK because same "param knowledge"? -- cf. computed roles +} +//*/ + +/* +global protocol Proto1(role A(n), role B(n, m), role C(m) +{ + 1() from A[1..1] to B[1..n]; + 2() from B[1..n] to A[1..1]; + + 3() from B[1..1] to C[1..m]; + 4() from C[1..m] to B[1..1]; + + do Proto1(C, B, A); // Bad because different "param knowledge"? + //do Proto1(B, A, C); // Also bad +} +//*/ + + + + + + + + + + + + + + +/* +global protocol Proto1(role A(n), role B(n)) +{ + choice at A[1] + { + 1(int) from A[1..1] to B[1..n]; + } + or + { + //2(int) from A[1..1] to B[1..n-1]; + 2(int) from A[1..1] to B[1..n]; + } +} +//*/ + +/*/ +global protocol Proto1(role A(m,n), role B(m,n)) +{ + 1() from A[1..1] to B[1..n]; + 2() from B[1..n-1] to A[1..1]; +} +//*/ + +/* +global protocol Proto1(role A(n), role B(n)) +{ + 1() from A[2..n] to B[2..n]; + //1() dot A[1..n] to B[1..n]; +} +//*/ + + + + + + + + + + + + + + + + + + + + + + + + + +/* +global protocol Proto1(role A, role B(n)) +{ + 1() from A[1..1] to B[1..n]; + 2() from B[1..n] to A[1..1]; +} +//*/ + + +/* +global protocol Proto1(role A, role B(n)) // n = 1 gives 2 roles; n > 1 gives 3 roles +{ + 1() from A[1..1] to B[1..n]; + 2() from B[1..1] to A[1..1]; +} +//*/ + + +/* +global protocol Proto1(role A, role B(n,m)) +{ + 1() from A[1..1] to B[1..n]; + 2() from B[1..m] to A[1..1]; +} +//*/ + + +/* +global protocol Proto1(role A(n), role B(m)) +{ + 1() from A[1..n] to B[1..m]; + 2() from B[1..m] to A[1..n]; +} +//*/ + + +/* +global protocol Proto1(role A, role B(n)) +{ + 1() from A[1..1] to B[1..n]; + 2() from B[2..n] to A[1..1]; +} +//*/ + + +/* +global protocol Proto1(role A, role B(n,m)) +{ + 1() from A[1..1] to B[1..n]; + 2() from B[2..m] to A[1..1]; +} +//*/ + + +/* +global protocol Proto1(role A, role B) +{ + choice at A + { + 1() from A[1..1] to B[1..2]; + 2() from B[1..1] to A[1..1]; + } + or + { + 3() from A[1..1] to B[1..2]; + 4() from B[2..2] to A[1..1]; + } +} +//*/ diff --git a/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/AntlrDataTypeDecl.java b/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/AntlrDataTypeDecl.java index eb9e80cdd..ee97f1456 100644 --- a/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/AntlrDataTypeDecl.java +++ b/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/AntlrDataTypeDecl.java @@ -33,7 +33,7 @@ public static DataTypeDecl parseDataTypeDecl(AntlrToScribParser parser, CommonTr String schema = AntlrSimpleName.getName(tmp1); CommonTree tmp2 = getExtNameChild(ct); String extName = AntlrExtIdentifier.getName(tmp2); - CommonTree tmp3 = getExtNameChild(ct); + CommonTree tmp3 = getSourceChild(ct); String source = AntlrExtIdentifier.getName(tmp3); DataTypeNode alias = AntlrSimpleName.toDataTypeNameNode(getAliasChild(ct), af); // FIXME: EMTPY_ALIAS? return af.DataTypeDecl(ct, schema, extName, source, alias); diff --git a/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/AntlrModule.java b/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/AntlrModule.java index 471e9b9a6..874037093 100644 --- a/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/AntlrModule.java +++ b/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/AntlrModule.java @@ -83,6 +83,6 @@ private static List filterChildren(CommonTree ct, AntlrNodeType... t List tmp = Arrays.asList(types); List children = AntlrToScribParserUtil.toCommonTreeList(ct.getChildren()); return children.subList(1, children.size()).stream() - .filter((c) -> tmp.contains(AntlrToScribParserUtil.getAntlrNodeType(c))).collect(Collectors.toList()); + .filter(c -> tmp.contains(AntlrToScribParserUtil.getAntlrNodeType(c))).collect(Collectors.toList()); } } diff --git a/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/global/AntlrGProtocolDecl.java b/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/global/AntlrGProtocolDecl.java index 263dd03d3..372a249bd 100644 --- a/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/global/AntlrGProtocolDecl.java +++ b/scribble-parser/src/main/java/org/scribble/parser/scribble/ast/global/AntlrGProtocolDecl.java @@ -43,7 +43,7 @@ public static GProtocolDecl parseGPrototocolDecl(AntlrToScribParser parser, Comm }*/ if (hasModifiersChild(ct)) { - for (CommonTree mod :getModifierChildren(ct)) + for (CommonTree mod : getModifierChildren(ct)) { switch (mod.getText()) { @@ -75,7 +75,7 @@ public static List getModifierChildren(CommonTree ct) { //return (CommonTree) ct.getChild(MODIFIERS_CHILD_INDEX); return ((List) ((CommonTree) ct.getChild(MODIFIERS_CHILD_INDEX)).getChildren()).stream() - .map((c) -> (CommonTree) c).collect(Collectors.toList()); + .map(c -> (CommonTree) c).collect(Collectors.toList()); } /*public static boolean isExplicitConnections(CommonTree ct)