diff --git a/AlgebraicDataflowArchitectureModel/models/Accounts.model b/AlgebraicDataflowArchitectureModel/models/Accounts.model index dba68ba..24710ee 100644 --- a/AlgebraicDataflowArchitectureModel/models/Accounts.model +++ b/AlgebraicDataflowArchitectureModel/models/Accounts.model @@ -1,5 +1,5 @@ channel CIO1 { - out accounts(l:Map, signup(id:Int, name:Str)) = append(l, {"name": name}) + out accounts(l:List, signup(name:Str)) = append(l, {"name": name}) } channel CIO2(uid:Int) { diff --git a/AlgebraicDataflowArchitectureModel/models/SimpleUI.model b/AlgebraicDataflowArchitectureModel/models/SimpleUI.model index ac3c51d..9b54346 100644 --- a/AlgebraicDataflowArchitectureModel/models/SimpleUI.model +++ b/AlgebraicDataflowArchitectureModel/models/SimpleUI.model @@ -1,3 +1,9 @@ +init { + screen := {"widgets": {"001": {"type": "button", "text": "OK", "state": 0}, + "002": {"type": "textInput", "text": "", "state": 0}}, + "layout": true} +} + native channel ScreenUpdate { in screen(curSc: Json, update(curSc, nextSc)) = nextSc } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index 2776604..0962ce2 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -783,6 +783,15 @@ return resourceHierarchies.get(hierarchy); } + public ResourceHierarchy getOrPutResourceHierarchy(ResourceHierarchy resourceHierarchy) { + String hierarchy = resourceHierarchy.toString(); + if (resourceHierarchies.get(hierarchy) != null) { + return resourceHierarchies.get(hierarchy); + } + resourceHierarchies.put(hierarchy, resourceHierarchy); + return resourceHierarchy; + } + public List getResourcePaths() { return resourcePaths; } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java index de5b736..91dd47d 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java @@ -21,6 +21,10 @@ return getChild(index); } + public int size() { + return children.size(); + } + @Override public Object clone() { ListTerm newTerm = new ListTerm(); diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index ec5f920..a1184ad 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -15,6 +15,7 @@ import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.JsonAccessor; +import models.dataConstraintModel.JsonTerm; import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; import models.dataConstraintModel.StateTransition; @@ -135,16 +136,21 @@ if (stream.checkNext().equals(RIGHT_CURLY_BRACKET)) return null; boolean isNative = false; - String channelOrInitKeyword = stream.next(); - if (channelOrInitKeyword.equals(NATIVE)) { + String channelOrInitOrNativeKeyword = stream.next(); + if (channelOrInitOrNativeKeyword.equals(NATIVE)) { // A native channel isNative = true; - channelOrInitKeyword = stream.next(); + channelOrInitOrNativeKeyword = stream.next(); } - if (!channelOrInitKeyword.equals(CHANNEL) && !channelOrInitKeyword.equals(SUB_CHANNEL)) { - if (!channelOrInitKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); + if (!channelOrInitOrNativeKeyword.equals(CHANNEL) && !channelOrInitOrNativeKeyword.equals(SUB_CHANNEL)) { + if (!channelOrInitOrNativeKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); parseInit(model); - channelOrInitKeyword = stream.next(); + channelOrInitOrNativeKeyword = stream.next(); + if (channelOrInitOrNativeKeyword.equals(NATIVE)) { + // A native channel + isNative = true; + channelOrInitOrNativeKeyword = stream.next(); + } } if (!stream.hasNext()) throw new ExpectedChannelName(stream.getLine()); @@ -523,21 +529,35 @@ } } +// private Expression parseJsonTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { +// Term jsonTerm = new Constant(DataConstraintModel.nil); +// jsonTerm.setType(DataConstraintModel.typeJson); +// while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { +// String key = stream.next(); +// Constant keyExp = new Constant(key); +// keyExp.setType(DataConstraintModel.typeString); +// if (stream.checkNext() == null || !stream.checkNext().equals(COLON)) throw new ExpectedColon(stream.getLine()); +// String colon = stream.next(); +// Expression value = parseTerm(stream, model); +// Term nextTerm = new Term(DataConstraintModel.addMember); +// nextTerm.addChild(jsonTerm); +// nextTerm.addChild(keyExp); +// nextTerm.addChild(value); +// jsonTerm = nextTerm; +// if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; +// String comma = stream.next(); +// } +// return jsonTerm; +// } + private Expression parseJsonTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { - Term jsonTerm = new Constant(DataConstraintModel.nil); - jsonTerm.setType(DataConstraintModel.typeJson); + JsonTerm jsonTerm = new JsonTerm(); while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { String key = stream.next(); - Constant keyExp = new Constant(key); - keyExp.setType(DataConstraintModel.typeString); if (stream.checkNext() == null || !stream.checkNext().equals(COLON)) throw new ExpectedColon(stream.getLine()); String colon = stream.next(); Expression value = parseTerm(stream, model); - Term nextTerm = new Term(DataConstraintModel.addMember); - nextTerm.addChild(jsonTerm); - nextTerm.addChild(keyExp); - nextTerm.addChild(value); - jsonTerm = nextTerm; + jsonTerm.addMember(key, value); if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; String comma = stream.next(); } @@ -612,6 +632,7 @@ if (stream.checkNext().equals(LEFT_BRACKET)) break; if (stream.checkNext().equals(COLON)) break; } while (stream.next().equals(DOT)); + hierarchy = model.getOrPutResourceHierarchy(hierarchy); return hierarchy; } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java index 23254b8..14e30bb 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java @@ -5,6 +5,7 @@ import java.util.Map; import models.algebra.Constant; +import models.algebra.Expression; import models.algebra.Type; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.ResourceHierarchy; @@ -48,7 +49,12 @@ } } } else { - state = new PrimitiveResourceState((Constant) resourceHierarchy.getInitialValue()); + Expression initValue = resourceHierarchy.getInitialValue(); + if (initValue != null && initValue instanceof Constant) { + state = new PrimitiveResourceState((Constant) resourceHierarchy.getInitialValue()); + } else { + state = new PrimitiveResourceState(null); + } } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index 368b3a6..bb90111 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -49,7 +49,15 @@ for (ResourceHierarchy res: model.getResourceHierarchies()) { if (res.getParent() == null) { // root resource - curState.addResource(new Resource(res)); + Resource resource = new Resource(res); + curState.addResource(resource); + Expression initilValue = res.getInitialValue(); + if (initilValue != null) { + if (initilValue instanceof Term) { + initilValue = ((Term) initilValue).reduce(); + } + curState.updateResourceState(resource.getResourceIdentifier(), initilValue); + } } } for (Channel channel: model.getChannels()) { diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index 4ae4020..5f25bdb 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -13,6 +13,9 @@ import models.algebra.Term; import models.algebra.Type; import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.JsonTerm; +import models.dataConstraintModel.ListTerm; +import models.dataConstraintModel.MapTerm; import models.dataConstraintModel.ResourceHierarchy; import models.dataFlowModel.DataTransferChannel; import simulator.states.CompositeResourceState; @@ -78,6 +81,21 @@ Type resType = resourceIdentifier.getResourceStateType(); if (resType != null && DataConstraintModel.typeList.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof ListTerm) { + ListTerm listValue = (ListTerm) resStateValue; + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier createdResource = null; + for (int i = 0; i < listValue.size(); i++) { + Expression childExp = new Constant(Integer.toString(i), DataConstraintModel.typeInt); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.get(i)); + ((ListResourceState) state).addChildState(childInfo.getKey()); + createdResource = childInfo.getValue(); + } + return createdResource; } else if (resStateValue instanceof Term) { Term listValue = (Term) resStateValue; if (listValue.getSymbol().equals(DataConstraintModel.append)) { @@ -85,10 +103,10 @@ ResourceState state = res.getState(); Expression childExp = null; if (state instanceof ListResourceState) { - childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); + childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size()), DataConstraintModel.typeInt); } else if (state instanceof PrimitiveResourceState && ((PrimitiveResourceState) state).getValue().getSymbol().equals(DataConstraintModel.nil)) { // If the value of state is nil. - childExp = new Constant("0"); + childExp = new Constant("0", DataConstraintModel.typeInt); ResourceState parentState = res.getParent().getState(); ResourceState newState = new ListResourceState(); if (parentState instanceof CompositeResourceState) { @@ -111,6 +129,36 @@ } } else if (resType != null && DataConstraintModel.typeMap.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof JsonTerm) { + JsonTerm mapValue = (JsonTerm) resStateValue; + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier createdResource = null; + for (String key: mapValue.keySet()) { + Expression childExp = new Constant(key, DataConstraintModel.typeString); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + ((MapResourceState) state).addChildState(key, childInfo.getKey()); + createdResource = childInfo.getValue(); + } + return createdResource; + } else if (resStateValue instanceof MapTerm) { + MapTerm mapValue = (MapTerm) resStateValue; + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier createdResource = null; + for (String key: mapValue.keySet()) { + Expression childExp = new Constant(key, DataConstraintModel.typeString); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + ((MapResourceState) state).addChildState(key, childInfo.getKey()); + createdResource = childInfo.getValue(); + } + return createdResource; } else if (resStateValue instanceof Term) { Term mapValue = (Term) resStateValue; if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { @@ -144,6 +192,33 @@ } } else if (resType != null && DataConstraintModel.typeJson.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof JsonTerm) { + JsonTerm jsonValue = (JsonTerm) resStateValue; + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier createdResource = null; + for (String key: jsonValue.keySet()) { + String memberName = key.replace("\"", ""); + ResourceHierarchy childResourceHierarchy = null; + for (ResourceHierarchy childRes: resourceIdentifier.getResourceHierarchy().getChildren()) { + if (childRes.getResourceName().equals(memberName)) { + childResourceHierarchy = childRes; + break; + } + } + if (childResourceHierarchy == null) { + childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName); + } + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); + Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.get(key)); + ResourceState childState = childInfo.getKey(); + if (res.getChildrenMap() != null && res.getChildrenMap().get(memberName) != null) { + res.getChildrenMap().get(memberName).changeState(childState); + } + ((JsonResourceState) state).addChildState(memberName, childState); + createdResource = childInfo.getValue(); + } + return createdResource; } else if (resStateValue instanceof Term) { Term jsonValue = (Term) resStateValue; Resource res = getResource(resourceIdentifier); @@ -200,19 +275,34 @@ } public Map.Entry createResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { - Type resType = null; - if (resStateValue instanceof Term) { - resType = ((Term) resStateValue).getType(); - resStateValue = ((Term) resStateValue).reduce(); - } +// Type resType = null; +// if (resStateValue instanceof Term) { +// resType = ((Term) resStateValue).getType(); +// resStateValue = ((Term) resStateValue).reduce(); +// } + Type resType = resourceIdentifier.getResourceStateType(); if (resType != null) { if (DataConstraintModel.typeList.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof ListTerm) { + ListTerm listValue = (ListTerm) resStateValue; + ListResourceState state = new ListResourceState(); + Map.Entry createInfo = null; + for (int i = 0; i < listValue.size(); i++) { + Expression childExp = new Constant(Integer.toString(i), DataConstraintModel.typeInt); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.get(i)); + state.addChildState(childInfo.getKey()); + createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + return createInfo; } else if (resStateValue instanceof Term) { Term listValue = (Term) resStateValue; if (listValue.getSymbol().equals(DataConstraintModel.append)) { ListResourceState state = new ListResourceState(); - Expression childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); + Expression childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size()), DataConstraintModel.typeInt); ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); @@ -223,6 +313,34 @@ } } else if (DataConstraintModel.typeMap.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof JsonTerm) { + JsonTerm mapValue = (JsonTerm) resStateValue; + MapResourceState state = new MapResourceState(); + Map.Entry createInfo = null; + for (String key: mapValue.keySet()) { + Expression childExp = new Constant(key, DataConstraintModel.typeString); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + state.addChildState(key, childInfo.getKey()); + createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + return createInfo; + } else if (resStateValue instanceof MapTerm) { + MapTerm mapValue = (MapTerm) resStateValue; + MapResourceState state = new MapResourceState(); + Map.Entry createInfo = null; + for (String key: mapValue.keySet()) { + Expression childExp = new Constant(key, DataConstraintModel.typeString); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + state.addChildState(key, childInfo.getKey()); + createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + return createInfo; } else if (resStateValue instanceof Term) { Term mapValue = (Term) resStateValue; if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { @@ -241,6 +359,33 @@ } } else if (DataConstraintModel.typeJson.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof JsonTerm) { + JsonTerm jsonValue = (JsonTerm) resStateValue; + MapResourceState state = new MapResourceState(); + Map.Entry createInfo = null; + for (String key: jsonValue.keySet()) { + String memberName = key.replace("\"", ""); + ResourceHierarchy childResourceHierarchy = null; + for (ResourceHierarchy childRes: resourceIdentifier.getResourceHierarchy().getChildren()) { + if (childRes.getResourceName().equals(memberName)) { + childResourceHierarchy = childRes; + break; + } + } + if (childResourceHierarchy == null) { + childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName); + } + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); + Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.get(key)); + ResourceState childState = childInfo.getKey(); + Resource res = getResource(resourceIdentifier); + if (res != null && res.getChildrenMap() != null && res.getChildrenMap().get(memberName) != null) { + res.getChildrenMap().get(memberName).changeState(childState); + } + state.addChildState(memberName, childState); + createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + return createInfo; } else if (resStateValue instanceof Term) { Term jsonValue = (Term) resStateValue; JsonResourceState state = new JsonResourceState();