diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index 2510f5a..3bdb1dd 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Stack; @@ -472,7 +473,54 @@ public static final Symbol remove = new Symbol("remove", 2, Symbol.Type.PREFIX, "remove", Symbol.Type.METHOD_WITH_SIDE_EFFECT); // Don't calculate here (Calculated in simulator). public static final Symbol head = new Symbol("head", 1, Symbol.Type.PREFIX, "($x)->$x.get(0)", Symbol.Type.LAMBDA); public static final Symbol tail = new Symbol("tail", 1, Symbol.Type.PREFIX, "($x)->$x.subList(1, $x.size())", Symbol.Type.LAMBDA); - public static final Symbol length = new Symbol("length", 1, Symbol.Type.PREFIX, "($x)->$x.size()", Symbol.Type.LAMBDA); + public static final Symbol length = new Symbol("length", 1, Symbol.Type.PREFIX, "($x)->$x.size()", Symbol.Type.LAMBDA, new Symbol.ICalculator() { + @Override + public Expression calculate(List args) { + if (args.get(0).getClass() == Constant.class && ((Constant) args.get(0)).getSymbol().equals(nil)) { + return new Constant("0", typeInt); + } + if (args.get(0) instanceof Term) { + Term term = (Term) args.get(0); + Type type = term.getType(); + if (typeList.isAncestorOf(type)) { + int len = 0; + while (term.getSymbol().equals(DataConstraintModel.append)) { + len++; + term = (Term) term.getChild(0); + } + if (term instanceof ListTerm) { + len += ((ListTerm) term).getChildren().size(); + return new Constant(Integer.toString(len), typeInt); + } + } else if (typeMap.isAncestorOf(type)) { + HashSet keySet = new HashSet<>(); + while (term.getSymbol().equals(DataConstraintModel.insert)) { + if (term.getChild(1).getClass() == Constant.class) { + keySet.add((String) ((Constant) term.getChild(1)).getValue()); + } + term = (Term) term.getChild(0); + } + if (term instanceof MapTerm) { + keySet.addAll(((MapTerm) term).keySet()); + return new Constant(Integer.toString(keySet.size()), typeInt); + } + } else if (typeJson.isAncestorOf(type)) { + HashSet keySet = new HashSet<>(); + while (term.getSymbol().equals(DataConstraintModel.addMember)) { + if (term.getChild(1).getClass() == Constant.class) { + keySet.add((String) ((Constant) term.getChild(1)).getValue()); + } + term = (Term) term.getChild(0); + } + if (term instanceof JsonTerm) { + keySet.addAll(((JsonTerm) term).keySet()); + return new Constant(Integer.toString(keySet.size()), typeInt); + } + } + } + return null; + } + }); public static final Symbol get = new Symbol("get", 2, Symbol.Type.PREFIX, "get", Symbol.Type.METHOD, new Symbol.ICalculator() { @Override public Expression calculate(List args) {