diff --git a/AlgebraicDataflowArchitectureModel/models/Twitter.model b/AlgebraicDataflowArchitectureModel/models/Twitter.model new file mode 100644 index 0000000..98d391b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Twitter.model @@ -0,0 +1,53 @@ +channel a_Tweet { + out a_user_timeline(l:List, a_tweet(t:Str)) == cons(t, l) + out a_user_timeline(l, e) == l +} + +channel a_Follow { + out a_follows(f:List, a_follow(u:Int)) == cons(u, f) + out a_follows(f, e) == f +} + +channel a_Home { + in a_user_timeline(la1, update_a(f2, la2, lb2, lc2)) == la2 + in b_user_timeline(lb1, update_a(f2, la2, lb2, lc2)) == lb2 + in c_user_timeline(lc1, update_a(f2, la2, lb2, lc2)) == lc2 + in a_follows(f, update_a(f2, la2, lb2, lc2)) == f2 + out a_home_timeline(t:List, update_a(f2, la2, lb2, lc2)) == merge(la2, if(contains(f2,2), merge(lb2, if(contains(f2,3), lc2, nil)), if(contains(f2,3), lc2, nil))) +} + +channel b_Tweet { + out b_user_timeline(l:List, b_tweet(t:Str)) == cons(t, l) + out b_user_timeline(l, e) == l +} + +channel b_Follow { + out b_follows(f:List, b_follow(u:Int)) == cons(u, f) + out b_follows(f, e) == f +} + +channel b_Home { + in a_user_timeline(la1, update_b(f2, la2, lb2, lc2)) == la2 + in b_user_timeline(lb1, update_b(f2, la2, lb2, lc2)) == lb2 + in c_user_timeline(lc1, update_b(f2, la2, lb2, lc2)) == lc2 + in b_follows(f, update_b(f2, la2, lb2, lc2)) == f2 + out b_home_timeline(t:List, update_b(f2, la2, lb2, lc2)) == merge(lb2, if(contains(f2,1), merge(la2, if(contains(f2,3), lc2, nil)), if(contains(f2,3), lc2, nil))) +} + +channel c_Tweet { + out c_user_timeline(l:List, c_tweet(t:Str)) == cons(t, l) + out c_user_timeline(l, e) == l +} + +channel c_Follow { + out c_follows(f:List, c_follow(u:Int)) == cons(u, f) + out c_follows(f, e) == f +} + +channel c_Home { + in a_user_timeline(la1, update_c(f2, la2, lb2, lc2)) == la2 + in b_user_timeline(lb1, update_c(f2, la2, lb2, lc2)) == lb2 + in c_user_timeline(lc1, update_c(f2, la2, lb2, lc2)) == lc2 + in c_follows(f, update_c(f2, la2, lb2, lc2)) == f2 + out c_home_timeline(t:List, update_c(f2, la2, lb2, lc2)) == merge(lc2, if(contains(f2,1), merge(la2, if(contains(f2,2), lb2, nil)), if(contains(f2,2), lb2, nil))) +} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java index 74acd2b..878c8e2 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java @@ -18,6 +18,7 @@ import models.algebra.Symbol; import models.algebra.Term; import models.algebra.Type; +import models.algebra.Variable; import models.dataConstraintModel.ChannelGenerator; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; @@ -152,18 +153,33 @@ for (ChannelGenerator cg : model.getIOChannelGenerators()) { for (ChannelMember cm : cg.getChannelMembers()) { if (cm.getIdentifierTemplate().getResourceName().equals(type.getTypeName().toLowerCase())) { - if (cm.getStateTransition().getMessageExpression().getClass() == Term.class) { + Expression message = cm.getStateTransition().getMessageExpression(); + if (message.getClass() == Term.class) { ArrayList params = new ArrayList<>(); - params.add(new VariableDeclaration(cm.getIdentifierTemplate().getResourceStateType(), - cm.getIdentifierTemplate().getResourceName())); + for (Variable var: message.getVariables().values()) { + params.add(new VariableDeclaration(var.getType(), var.getName())); + } MethodDeclaration input = new MethodDeclaration( ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), false, typeVoid, params); type.addMethod(input); - String str; - str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); - input = new MethodDeclaration(str, false, typeVoid, params); - mainType.addMethod(input); + String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); + input = getMethod(mainType, str); + if (input == null) { + input = new MethodDeclaration(str, false, typeVoid, params); + mainType.addMethod(input); + } else { + // Add type to a parameter without type. + for (VariableDeclaration param: input.getParameters()) { + if (param.getType() == null) { + for (VariableDeclaration p: params) { + if (param.getName().equals(p.getName()) && p.getType() != null) { + param.setType(p.getType()); + } + } + } + } + } } } } @@ -337,6 +353,13 @@ } } + private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().equals(methodName)) return m; + } + return null; + } + static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { @Override public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java index b612a08..5d55493 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java @@ -18,6 +18,7 @@ import models.algebra.Term; import models.algebra.UnificationFailed; import models.algebra.ValueUndefined; +import models.algebra.Variable; import models.dataConstraintModel.ChannelGenerator; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.IdentifierTemplate; @@ -170,7 +171,13 @@ if (mainType != null) { MethodDeclaration mainInput = getMethod(mainType, input.getName()); if (mainInput != null) { - mainInput.addStatement("this." + resourceName + "." + input.getName() + "(" + resourceName + ");"); + String args = ""; + String delimitar = ""; + for (Variable var: message.getVariables().values()) { + args += delimitar + var.getName(); + delimitar = ", "; + } + mainInput.addStatement("this." + resourceName + "." + input.getName() + "(" + args + ");"); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java index 36b376d..9fad21e 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java @@ -19,6 +19,7 @@ import models.algebra.Symbol; import models.algebra.Term; import models.algebra.Type; +import models.algebra.Variable; import models.dataConstraintModel.ChannelGenerator; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; @@ -117,12 +118,15 @@ for (ChannelGenerator cg : model.getIOChannelGenerators()) { for (ChannelMember cm : cg.getChannelMembers()) { if (cm.getIdentifierTemplate().getResourceName().equals(type.getTypeName().toLowerCase())) { - if (cm.getStateTransition().getMessageExpression().getClass() == Term.class) { + Expression message = cm.getStateTransition().getMessageExpression(); + if (message.getClass() == Term.class) { ArrayList params = new ArrayList<>(); - String paramName = cm.getIdentifierTemplate().getResourceName(); - VariableDeclaration param = new VariableDeclaration(cm.getIdentifierTemplate().getResourceStateType(), paramName); - param.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); - params.add(param); + for (Variable var: message.getVariables().values()) { + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); + params.add(param); + } MethodDeclaration input = new MethodDeclaration( ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), false, typeVoid, params); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index fff1ccc..762169e 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -20,6 +20,7 @@ public static final Type typeDouble = new Type("Double", "double"); public static final Type typeList = new Type("List", "ArrayList", "List"); public static final Type typeBoolean = new Type("Bool", "boolean"); + public static final Type typeString = new Type("Str", "String"); public static final Symbol add = new Symbol(Parser.ADD, 2, Symbol.Type.INFIX); public static final Symbol mul = new Symbol(Parser.MUL, 2, Symbol.Type.INFIX);; public static final Symbol sub = new Symbol(Parser.SUB, 2, Symbol.Type.INFIX); @@ -28,8 +29,10 @@ public static final Symbol cons = new Symbol("cons", 2, Symbol.Type.PREFIX, "add", Symbol.Type.METHOD_WITH_SIDE_EFFECT, new int[] {1, 0}); public static final Symbol head = new Symbol("head", 1, Symbol.Type.PREFIX, "get(0)", Symbol.Type.METHOD); public static final Symbol body = new Symbol("tail", 1, Symbol.Type.PREFIX, "($x)->$x.subString(1, $x.size())", Symbol.Type.LAMBDA); - public static final Symbol cond = new Symbol("if", 3, Symbol.Type.PREFIX, "($x,$y,$z)->$x ? $y : $z", Symbol.Type.LAMBDA); + public static final Symbol contains = new Symbol("contains", 2, Symbol.Type.PREFIX, "contains", Symbol.Type.METHOD); + public static final Symbol cond = new Symbol("if", 3, Symbol.Type.PREFIX, "($x,$y,$z)->($x ? $y : $z)", Symbol.Type.LAMBDA); public static final Symbol eq = new Symbol("eq", 2, Symbol.Type.PREFIX, "==", Symbol.Type.INFIX); + public static final Symbol neq = new Symbol("neq", 2, Symbol.Type.PREFIX, "!=", Symbol.Type.INFIX); public static final Symbol gt = new Symbol("gt", 2, Symbol.Type.PREFIX, ">", Symbol.Type.INFIX); public static final Symbol lt = new Symbol("lt", 2, Symbol.Type.PREFIX, "<", Symbol.Type.INFIX); @@ -53,6 +56,7 @@ addType(typeDouble); addType(typeList); addType(typeBoolean); + addType(typeString); symbols = new HashMap<>(); addSymbol(add); addSymbol(mul); @@ -62,8 +66,10 @@ addSymbol(cons); addSymbol(head); addSymbol(body); + addSymbol(contains); addSymbol(cond); addSymbol(eq); + addSymbol(neq); addSymbol(gt); addSymbol(lt); } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java index a04eefb..8ebc0a6 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java @@ -155,12 +155,7 @@ Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetIdentifier, targetIdentifier); if (unifiedMessage == null) { // for IOChannel - Expression nextOutputStateAccessor = stateAccessor.getNextStateAccessorFor(targetIdentifier, targetIdentifier); unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); - HashMap messageVars = unifiedMessage.getVariables(); - for (Variable var: messageVars.values()) { - unifiedMessage = ((Term) unifiedMessage).substitute(var, nextOutputStateAccessor); - } } return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); }