diff --git a/AlgebraicDataflowArchitectureModel/models/GroupChat.model b/AlgebraicDataflowArchitectureModel/models/GroupChat.model new file mode 100644 index 0000000..d8b0c42 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/GroupChat.model @@ -0,0 +1,27 @@ +channel Signup { + out accounts(adb:Map, signUp(aid:Str)) = insert(adb, aid, {"notifications": nil}) +} + +channel HasRead(aid:Str) { + out accounts.{aid}.notifications(ntMap:Map, hasRead(gid:Str)) = delete(ntMap, gid) +} + +channel CreateGroup { + out groups(gdb:Map, createGroup(gid:Str)) = insert(gdb, gid, {"members": nil, "messages": nil}) +} + +channel AddGroupMember(gid:Str) { + out groups.{gid}.members(memList:List, addGroupMember(aid:Str)) = append(memList, aid) +} + +channel PostMessage(gid:Str) { + out groups.{gid}.messages(mesList:List, postMessage(message:Str)) = append(mesList, message) +} + +channel Notify(gid:Str) { + in groups.{gid}.messages(prevMesList, notify(id)) = mesList + for EachMember(mno:Int) { + ref groups.{gid}.members.{mno}(id:Str, notify(id)) + out accounts.{id}.notifications(prevNtMap:Map, notify(id)) = insert(prevNtMap, gid, true) + } +} diff --git a/AlgebraicDataflowArchitectureModel/models/OnlineBattleGame2.model b/AlgebraicDataflowArchitectureModel/models/OnlineBattleGame2.model index 4012b23..a5a6f57 100644 --- a/AlgebraicDataflowArchitectureModel/models/OnlineBattleGame2.model +++ b/AlgebraicDataflowArchitectureModel/models/OnlineBattleGame2.model @@ -3,7 +3,7 @@ } channel ChangeName(aid:Str) { - out accounts.{aid}.name(prev_name:Str, changeName(name)) = name + out accounts.{aid}.name(prevName:Str, changeName(name)) = name } channel CreateRoom { @@ -15,19 +15,19 @@ } channel Battle(rid:Str) { - out rooms.{rid}.battle(prev_result, battle(result:Bool)) = result + out rooms.{rid}.battle(prevState, battle(state:Bool)) = state } channel RoomName(rid:Str, mno:Int) { - in rooms.{rid}.members.{mno}.id(prev_mid:Str, sync(mid, name)) = mid - in accounts.{mid}.name(prev_name:Str, sync(mid, name)) = name - out rooms.{rid}.members.{mno}.name(prev_name:Str, sync(mid, name)) = name + in rooms.{rid}.members.{mno}.id(prevMid:Str, nameSync(mid, name)) = mid + in accounts.{mid}.name(prevName:Str, nameSync(mid, name)) = name + out rooms.{rid}.members.{mno}.name(prevName:Str, nameSync(mid, name)) = name } channel RoomResult(rid:Str) { - in rooms.{rid}.battle(prev_result, sync2(result, mid)) = result - sub RoomResult2(mno:Int) { - in rooms.{rid}.members.{mno}.id(prev_mid:Str, sync2(result, mid)) = mid - out accounts.{mid}.point(prev_point:Int, sunc2(result, mid)) = if(result, prev_point + 1, prev_point) + in rooms.{rid}.battle(prevState, pointSync(hasWon, mid)) = hasWon + for EachMember(mno:Int) { + in rooms.{rid}.members.{mno}.id(prevMid:Str, pointSync(hasWon, mid)) = mid + out accounts.{mid}.point(prevPoint:Int, pointSync(hasWon, mid)) = if(hasWon, prevPoint + 1, prevPoint) } } diff --git a/AlgebraicDataflowArchitectureModel/models/Twitter.model b/AlgebraicDataflowArchitectureModel/models/Twitter.model index fe64776..0b2cd2a 100644 --- a/AlgebraicDataflowArchitectureModel/models/Twitter.model +++ b/AlgebraicDataflowArchitectureModel/models/Twitter.model @@ -1,5 +1,5 @@ channel SignUp { - out accounts(acDB:Map, signup(myId:Str, name:Str)) = insert(acDB, myId, {"name": name, "tweets": nil, "followees": nil, "timeline": nil}) + out accounts(acDB:Map, signup(id:Str, name:Str)) = insert(acDB, id, {"name": name, "tweets": nil, "followees": nil, "timeline": nil}) } channel Tweet(id:Str) { @@ -12,7 +12,7 @@ channel Timeline(myId:Str) { in accounts.{myId}.tweets(t1:List, m) = m.myTweets - sub C2(no:Int) { + for EachFollowee(no:Int) { in accounts.{myId}.followees.{no}(id:Str, m) = m.flw.{no}.id in accounts.{m.flw.{no}.id}.tweets(t2:List, m) = m.flw.{no}.tweets } diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index 60f5a55..671e934 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -46,7 +46,7 @@ public static final String IN = "in"; public static final String OUT = "out"; public static final String REF = "ref"; - public static final String SUB_CHANNEL = "sub"; + public static final String SUB_CHANNEL = "for"; public static final String NATIVE = "native"; public static final String LEFT_CURLY_BRACKET = "{"; public static final String RIGHT_CURLY_BRACKET = "}"; diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java index 264c6fc..a1f0302 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java @@ -39,7 +39,7 @@ private Map dependingParameters = new HashMap<>(); private Set outputResources = new HashSet<>(); private Set childEvents = new HashSet<>(); - private Map> channelSelectorToInputResourcePathParam = new HashMap<>(); + private Map> channelSelectorToInputOrReferenceResourcePathParam = new HashMap<>(); private Map> channelSelectorToOutputResourcePathParam = new HashMap<>(); /** @@ -92,7 +92,7 @@ List channelSelectors = channel.getAllSelectors(); for (Selector sel: channelSelectors) { if (inputResPath != null) { - Integer paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(inputResPath); + Integer paramIdx = channelSelectorToInputOrReferenceResourcePathParam.get(sel).get(inputResPath); if (paramIdx != null) { Resource ancestor = inputResource; int idx = inputResPath.getPathParams().size(); @@ -140,10 +140,21 @@ for (ResourcePath resPath: channel.getInputResources()) { int paramIdx = resPath.getPathParams().indexOf(sel.getExpression()); if (paramIdx >= 0) { - Map pathToIdx = channelSelectorToInputResourcePathParam.get(sel); + Map pathToIdx = channelSelectorToInputOrReferenceResourcePathParam.get(sel); if (pathToIdx == null) { pathToIdx = new HashMap<>(); - channelSelectorToInputResourcePathParam.put(sel, pathToIdx); + channelSelectorToInputOrReferenceResourcePathParam.put(sel, pathToIdx); + } + pathToIdx.put(resPath, paramIdx); + } + } + for (ResourcePath resPath: channel.getReferenceResources()) { + int paramIdx = resPath.getPathParams().indexOf(sel.getExpression()); + if (paramIdx >= 0) { + Map pathToIdx = channelSelectorToInputOrReferenceResourcePathParam.get(sel); + if (pathToIdx == null) { + pathToIdx = new HashMap<>(); + channelSelectorToInputOrReferenceResourcePathParam.put(sel, pathToIdx); } pathToIdx.put(resPath, paramIdx); } @@ -399,21 +410,23 @@ } Expression parentEventMessage = (Expression) unifiedMessage.clone(); for (Channel childChannel: channel.getChildren()) { - // Search the deepest input side resource path in each child channel that matches the channel parameters. - ChannelMember in = null; - for (ChannelMember cm: ((DataTransferChannel) childChannel).getInputChannelMembers()) { + // Search the deepest input or reference side resource path in each child channel that matches the channel parameters. + ChannelMember inOrRef = null; + Set channelMembers = new HashSet<>(((DataTransferChannel) childChannel).getInputChannelMembers()); + channelMembers.addAll(((DataTransferChannel) childChannel).getReferenceChannelMembers()); + for (ChannelMember cm: channelMembers) { if (!cm.isOutside()) { ResourcePath resPath = cm.getResource(); if (resPath.getPathParams().containsAll(childChannel.getAllSelectorVariables())) { - in = cm; + inOrRef = cm; break; } } } - if (in != null) { + if (inOrRef != null) { // Collect events for all resources under this event's input resource that matches the deepest input side resource path. - for (Resource res: baseResource.getDescendants(in.getResource().getResourceHierarchy())) { - Event childEvent = new Event((DataTransferChannel) childChannel, in.getResource(), res); + for (Resource res: baseResource.getDescendants(inOrRef.getResource().getResourceHierarchy())) { + Event childEvent = new Event((DataTransferChannel) childChannel, inOrRef.getResource(), res); childEvent.setMessage(parentEventMessage); messageConstraint = childEvent.constructMessageAndDesdendantEvents(resourceStateValueProvider, substitutedPositionsInMessageFromChannels, true); if (messageConstraint != null) { @@ -475,7 +488,7 @@ ResourceIdentifier resId = ResourceIdentifier.createFrom(resPath); for (Map.Entry chParamEnt: channelSelectorAndValues) { Selector sel = chParamEnt.getKey(); - Map inputPathParamEnt = channelSelectorToInputResourcePathParam.get(sel); + Map inputPathParamEnt = channelSelectorToInputOrReferenceResourcePathParam.get(sel); if (inputPathParamEnt != null) { Integer paramIdx = inputPathParamEnt.get(resPath); if (paramIdx != null) { @@ -506,8 +519,8 @@ ResourceIdentifier resId = ResourceIdentifier.createFrom(inputResPath); for (Map.Entry chParamEnt: channelSelectorAndValues) { Selector sel = chParamEnt.getKey(); - if (channelSelectorToInputResourcePathParam.get(sel) != null) { - Integer paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(inputResPath); + if (channelSelectorToInputOrReferenceResourcePathParam.get(sel) != null) { + Integer paramIdx = channelSelectorToInputOrReferenceResourcePathParam.get(sel).get(inputResPath); if (paramIdx != null) { resId.setPathParam(paramIdx, chParamEnt.getValue()); }