From f4c58e19f46ccb09ba066e9b0cfd3ba94cf5b0e1 Mon Sep 17 00:00:00 2001 From: Kevin Lano Date: Sun, 4 Aug 2024 14:53:38 +0100 Subject: [PATCH] OCL optimisation for energy use --- Attribute.java | 42 ++++++-- BasicExpression.java | 33 +++++- BehaviouralFeature.java | 9 ++ BinaryExpression.java | 160 +++++++++++++++++++++++++++++ ConditionalExpression.java | 15 +++ Constraint.java | 23 +++++ Entity.java | 9 ++ Expression.java | 3 + SetExpression.java | 13 +++ Statement.java | 205 ++++++++++++++++++++++++++++++++++++- UCDArea.java | 12 +++ UmlTool.java | 9 ++ UnaryExpression.java | 77 ++++++++++++++ 13 files changed, 601 insertions(+), 9 deletions(-) diff --git a/Attribute.java b/Attribute.java index 38b73908..ec20233f 100644 --- a/Attribute.java +++ b/Attribute.java @@ -3083,10 +3083,15 @@ public String setOperationJava7(Entity ent, Vector cons, Vector v = type.getValues(); String val = nme + "_x"; + Attribute par = new Attribute(val,type,ModelElement.INTERNAL); par.setElementType(elementType); + BasicExpression attxbe = new BasicExpression(val); + // attxbe.setType(type); + // attxbe.setElementType(elementType); + Vector v1 = new Vector(); v1.add(par); String t = type.getJava7(); // (elementType) @@ -3101,6 +3106,9 @@ public String setOperationJava7(Entity ent, Vector cons, BehaviouralFeature event = new BehaviouralFeature("set" + nme,v1,false,null); + java.util.Map env = new java.util.HashMap(); + env.put(ename, "this"); + String qual = " "; String code = ""; String sync = ""; @@ -3117,24 +3125,41 @@ else if (!instanceScope) } else { code = nme + " = " + val + ";"; } // controller sets static atts, once only + + String precode = ""; + + for (int j = 0; j < cons.size(); j++) + // may be constraints of subclass ent + { Constraint cc = (Constraint) cons.get(j); + + if (cc.isDeltaConstraint(nme) && + cc.dependsUpon(ename,nme)) + { Constraint cc2 = + (Constraint) cc.substituteEq(nme,attxbe); + String cccode = cc2.updateFormJava7(env,true); + + System.out.println(">> Delta constraint " + cc + "\n" + + ">> action for set" + nme + " is: " + cccode); + precode = precode + "\n" + + cccode + "\n"; + } + } + String opheader; opheader = "public" + sync + qual + "void set" + nme + "(" + t + - " " + val + ") { " + code; + " " + val + ") { " + precode + "\n " + code; if (!instanceScope) { opheader = opheader + " }\n\n" + "public" + sync + " void localSet" + nme + "(" + t + - " " + val + ") { "; + " " + val + ") { " + precode; } - BasicExpression attxbe = new BasicExpression(val); Vector contexts = new Vector(); contexts.add(ent); - java.util.Map env = new java.util.HashMap(); - env.put(ename, "this"); - + for (int j = 0; j < cons.size(); j++) // may be constraints of subclass ent { Constraint cc = (Constraint) cons.get(j); @@ -3146,7 +3171,10 @@ else if (!instanceScope) " depends on " + nme + " : " + cc.dependsUpon(ename,nme)); */ - if (cc.isBehavioural() && + if (cc.isDeltaConstraint(nme) && + cc.dependsUpon(ename,nme)) + { } + else if (cc.isBehavioural() && cc.dependsUpon(ename,nme)) { String cccode = cc.updateFormJava7(env,true); diff --git a/BasicExpression.java b/BasicExpression.java index 613f465e..3d23fa39 100644 --- a/BasicExpression.java +++ b/BasicExpression.java @@ -17295,6 +17295,36 @@ public static void main(String[] args) } + public Expression simplifyOCL() + { // Replaces energy-expensive processing by simpler. + + Expression objR = objectRef; + if (objectRef != null) + { objR = objectRef.simplifyOCL(); } + + Expression arrInd = arrayIndex; + if (arrayIndex != null) + { arrInd = arrayIndex.simplifyOCL(); } + + Vector pars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + pars.add(par.simplifyOCL()); + } + } + else + { pars = parameters; } + + BasicExpression res = (BasicExpression) clone(); + res.objectRef = objR; + res.arrayIndex = arrInd; + res.parameters = pars; + return res; + } + + + public Map energyUse(Map res, Vector rUses, Vector oUses) { // Calls to OclType reflection operators and OclDatasource // connect are red flags. @@ -17379,7 +17409,8 @@ public java.util.Map collectionOperatorUses(int level, } return res; - } + } // and in the parameters and object ref + public int syntacticComplexity() { int res = 0; diff --git a/BehaviouralFeature.java b/BehaviouralFeature.java index e49bd5ab..1c5fe3de 100644 --- a/BehaviouralFeature.java +++ b/BehaviouralFeature.java @@ -4239,6 +4239,15 @@ public Vector equivalentsUsedIn() return res; } + public void simplifyOCL() + { if (pre != null) + { pre = pre.simplifyOCL(); } + if (post != null) + { post = post.simplifyOCL(); } + if (activity != null) + { activity = activity.optimiseOCL(); } + } + public Map energyAnalysis(Vector redUses, Vector amberUses) { // Scan the postcondition/activity for energy expensive // expressions/code diff --git a/BinaryExpression.java b/BinaryExpression.java index e3ec4a94..3d36a2b9 100644 --- a/BinaryExpression.java +++ b/BinaryExpression.java @@ -20080,6 +20080,166 @@ public Expression featureAdding2(String var, Vector remainder) return null; } + public Expression simplifyOCL() + { // Double iterations ->select(...)->select(...) + // replaced + + Expression lexpr = left.simplifyOCL(); + Expression rexpr = right.simplifyOCL(); + + + if (operator.equals("|")) + { BinaryExpression arg = (BinaryExpression) left; + Expression domain = arg.getRight(); + if (domain instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) domain; + + if (lbe.operator.equals("->select")) + { System.out.println(">> Inefficient nested select: " + this); + Expression newleft = lbe.getLeft(); + Expression newright = lbe.getRight(); + BasicExpression ref = + (BasicExpression) arg.getLeft(); + Expression newpred = + Expression.simplifyAnd( + newright.addReference(ref, ref.getType()), right); + Expression newdomain = + new BinaryExpression(":", ref, + newleft); + return new BinaryExpression("|", newdomain, newpred); + } + else if (lbe.operator.equals("->reject")) + { System.out.println(">> Inefficient nested select: " + this); + Expression newleft = lbe.getLeft(); + Expression newright = lbe.getRight(); + BasicExpression ref = + (BasicExpression) arg.getLeft(); + Expression newpred = + Expression.simplifyAnd( + Expression.negate(newright.addReference(ref, + ref.getType())), + right); + Expression newdomain = + new BinaryExpression(":", ref, + newleft); + return new BinaryExpression("|", newdomain, newpred); + } + } + } + else if (operator.equals("|R")) + { BinaryExpression arg = (BinaryExpression) left; + Expression domain = arg.getRight(); + if (domain instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) domain; + + if (lbe.operator.equals("->select")) + { System.out.println(">> Inefficient nested select/reject: " + this); + Expression newleft = lbe.getLeft(); + Expression newright = lbe.getRight(); + BasicExpression ref = + (BasicExpression) arg.getLeft(); + Expression newpred = + Expression.simplifyAnd( + newright.addReference(ref, ref.getType()), + Expression.negate(right)); + Expression newdomain = + new BinaryExpression(":", ref, + newleft); + return new BinaryExpression("|", newdomain, newpred); + } + else if (lbe.operator.equals("->reject")) + { System.out.println(">> Inefficient nested reject: " + this); + Expression newleft = lbe.getLeft(); + Expression newright = lbe.getRight(); + BasicExpression ref = + (BasicExpression) arg.getLeft(); + Expression newpred = + Expression.simplifyOr( + newright.addReference(ref, + ref.getType()), + right); + Expression newdomain = + new BinaryExpression(":", ref, + newleft); + return new BinaryExpression("|R", newdomain, newpred); + } + } + } + else if (operator.equals("->select")) + { + if (left instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) left; + if (lbe.operator.equals("->select")) + { System.out.println(">> Inefficient nested select: " + this); + Expression predicate1 = lbe.getRight(); + Expression combinedPred = + new BinaryExpression("&", predicate1, right); + BinaryExpression res = (BinaryExpression) clone(); + res.left = lbe.getLeft(); + res.operator = "->select"; + res.right = combinedPred; + System.out.println(">> Replacing with: " + res); + return res; + } + else if (lbe.operator.equals("->reject")) + { System.out.println(">> Inefficient nested select: " + this); + Expression predicate1 = lbe.getRight(); + Expression pred2 = + Expression.negate(predicate1); + Expression combinedPred = + new BinaryExpression("&", pred2, right); + BinaryExpression res = (BinaryExpression) clone(); + res.left = lbe.getLeft(); + res.operator = "->select"; + res.right = combinedPred; + System.out.println(">> Replacing with: " + res); + return res; + } + } + } + else if (operator.equals("->reject")) + { + if (left instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) left; + if (lbe.operator.equals("->select")) + { System.out.println(">> Inefficient nested select: " + this); + Expression predicate1 = lbe.getRight(); + Expression combinedPred = + new BinaryExpression("&", + Expression.negate(predicate1), right); + BinaryExpression res = (BinaryExpression) clone(); + res.left = lbe.getLeft(); + res.operator = "->select"; + res.right = combinedPred; + System.out.println(">> Replacing with: " + res); + return res; + } + else if (lbe.operator.equals("->reject")) + { System.out.println(">> Inefficient nested select: " + this); + Expression predicate1 = lbe.getRight(); + Expression pred2 = + Expression.negate(predicate1); + pred2.setBrackets(true); + right.setBrackets(true); + Expression combinedPred = + new BinaryExpression("or", pred2, right); + BinaryExpression res = (BinaryExpression) clone(); + res.left = lbe.getLeft(); + res.operator = "->reject"; + res.right = combinedPred; + System.out.println(">> Replacing with: " + res); + return res; + } + } + } + + BinaryExpression res = (BinaryExpression) clone(); + res.left = lexpr; + res.right = rexpr; + return res; + } + + public Map energyUse(Map res, Vector rUses, Vector aUses) { // Double iterations ->select(...)->select(...) // are amber flags. diff --git a/ConditionalExpression.java b/ConditionalExpression.java index a63bf6e0..15549700 100644 --- a/ConditionalExpression.java +++ b/ConditionalExpression.java @@ -144,6 +144,21 @@ public Statement generateDesign(java.util.Map env, boolean local) return new ConditionalStatement(test, ifstat, elsestat); } + public Expression simplifyOCL() + { Expression ifstat = ifExp.simplifyOCL(); + Expression elsestat = elseExp.simplifyOCL(); + + Expression testexpr = test.simplifyOCL(); + + if ((testexpr + "").equals("true")) + { return ifstat; } + + if ((testexpr + "").equals("false")) + { return elsestat; } + + return new ConditionalExpression(testexpr, ifstat, elsestat); + } + public Map energyUse(Map res, Vector rUses, Vector oUses) { test.energyUse(res,rUses,oUses); ifExp.energyUse(res,rUses,oUses); diff --git a/Constraint.java b/Constraint.java index b8138201..402c6a36 100644 --- a/Constraint.java +++ b/Constraint.java @@ -316,6 +316,29 @@ else if (op.equals("&") && beante.left instanceof BinaryExpression) public boolean isBehavioural() { return behavioural; } + public boolean isDeltaConstraint(String nme) + { // nme /= nme@pre or nme@pre /= nme + Expression ante = antecedent(); + + // System.out.println("Antecedent: " + ante); + + if (ante instanceof BinaryExpression) + { BinaryExpression bexpr = (BinaryExpression) ante; + if ("/=".equals(bexpr.getOperator())) + { if (nme.equals(bexpr.getLeft() + "") && + (nme + "@pre").equals(bexpr.getRight() + "")) + { return true; } + if (nme.equals(bexpr.getRight() + "") && + (nme + "@pre").equals(bexpr.getLeft() + "")) + { return true; } + return false; + } + return false; + } + return false; + } + + public String cg(CGSpec cgs) { Expression ante = antecedent(); Expression succ = succedent(); diff --git a/Entity.java b/Entity.java index 3683ebc9..72738f79 100644 --- a/Entity.java +++ b/Entity.java @@ -5540,6 +5540,15 @@ public int sizeof(Vector types, Vector entities) return sze; } + public void simplifyOCL() + { int n = operations.size(); + + for (int i = 0; i < n; i++) + { BehaviouralFeature op = (BehaviouralFeature) operations.get(i); + op.simplifyOCL(); + } + } + public Map energyAnalysis() { Map res = new Map(); res.set("red", 0); diff --git a/Expression.java b/Expression.java index 63041019..96236aed 100644 --- a/Expression.java +++ b/Expression.java @@ -2740,6 +2740,9 @@ public boolean confluenceCheck(Vector iterated, Vector created) abstract public Expression simplify(); + public Expression simplifyOCL() + { return simplify(); } + protected static Expression pruneDuplicates(Vector cnames, Expression e1, Expression e2) diff --git a/SetExpression.java b/SetExpression.java index 7aa6e190..47e8ac6e 100644 --- a/SetExpression.java +++ b/SetExpression.java @@ -1426,6 +1426,19 @@ public Map energyUse(Map res, Vector rUses, Vector aUses) return res; } + public Expression simplifyOCL() + { Vector elems = new Vector(); + for (int i = 0; i < elements.size(); i++) + { Expression elem = (Expression) elements.get(i); + elems.add(elem.simplifyOCL()); + } + + SetExpression res = (SetExpression) clone(); + res.elements = elems; + + return res; + } + public java.util.Map collectionOperatorUses(int level, java.util.Map res) { for (int i = 0; i < elements.size(); i++) diff --git a/Statement.java b/Statement.java index 8f0f2d3c..11296da6 100644 --- a/Statement.java +++ b/Statement.java @@ -265,6 +265,8 @@ public static boolean hasLoopStatement(Statement st) public Vector allVariableNames() { return new Vector(); } // default + public abstract Statement optimiseOCL(); + public abstract Map energyUse(Map uses, Vector rUses, Vector oUses); @@ -2252,6 +2254,13 @@ public Map energyUse(Map uses, return uses; } + public Statement optimiseOCL() + { if (value == null) + { return this; } + Expression newval = value.simplifyOCL(); + return new ReturnStatement(newval); + } + public java.util.Map collectionOperatorUses( int nestingLevel, java.util.Map operatorsAtLevel) @@ -2794,6 +2803,9 @@ public void findClones(java.util.Map clones, String op, String rule) { return; } + public Statement optimiseOCL() + { return this; } + public Map energyUse(Map uses, Vector rUses, Vector oUses) { return uses; } @@ -2989,6 +3001,9 @@ public Map energyUse(Map uses, Vector rUses, Vector oUses) { return uses; } + public Statement optimiseOCL() + { return this; } + public java.util.Map collectionOperatorUses( int nestingLevel, java.util.Map operatorsAtLevel) @@ -3266,6 +3281,11 @@ public void findClones(java.util.Map clones, public Vector allVariableNames() { return callExp.allVariableNames(); } + public Statement optimiseOCL() + { Expression cexp = callExp.simplifyOCL(); + return new InvocationStatement(cexp); + } + public Map energyUse(Map uses, Vector rUses, Vector oUses) { callExp.energyUse(uses, rUses, oUses); @@ -4066,6 +4086,11 @@ public Statement addContainerReference( return new ImplicitInvocationStatement(newExp); } + public Statement optimiseOCL() + { Expression cexp = callExp.simplifyOCL(); + return new ImplicitInvocationStatement(cexp); + } + public String toString() /* B display */ { String res = "execute ( " + callExp + " )"; return res; @@ -4733,6 +4758,40 @@ public Statement addContainerReference(BasicExpression ref, return res; } + public Statement optimiseOCL() + { Expression lv = null; + if (loopVar != null) + { lv = (Expression) loopVar.clone(); } + + Expression lr = null; + if (loopRange != null) + { lr = loopRange.simplifyOCL(); } + + Expression lt = null; + if (loopTest != null) + { lt = loopTest.simplifyOCL(); } + + Statement newbody = body.optimiseOCL(); + + WhileStatement res = new WhileStatement(lt,newbody); + res.setEntity(entity); + res.setLoopKind(loopKind); + res.setLoopRange(lv,lr); + res.setBrackets(brackets); + + Expression inv = null; + if (invariant != null) + { inv = invariant.simplifyOCL(); } + res.setInvariant(inv); + + Expression vv = null; + if (variant != null) + { vv = variant.simplifyOCL(); } + res.setVariant(vv); + + return res; + } + public void setInvariant(Expression inv) { invariant = inv; } @@ -6581,6 +6640,21 @@ public Statement substituteEq(String oldE, Expression newE) return res; } + public Statement optimiseOCL() + { String cio = createsInstanceOf; + String ast = assignsTo; + + CreationStatement res = new CreationStatement(cio,ast); + res.setType(instanceType); + res.setElementType(elementType); + + if (initialExpression != null) + { Expression newExpr = initialExpression.simplifyOCL(); + res.setInitialisation(newExpr); + } + return res; + } + public Statement removeSlicedParameters( BehaviouralFeature bf, Vector fpars) { String cio = createsInstanceOf; @@ -7821,6 +7895,19 @@ public void findMagicNumbers(java.util.Map mgns, String rule, String op) } } + public Statement optimiseOCL() + { Vector newstats = new Vector(); + for (int i = 0; i < statements.size(); i++) + { Statement stat = (Statement) statements.get(i); + Statement newstat = stat.optimiseOCL(); + newstats.add(newstat); + } + SequenceStatement res = new SequenceStatement(newstats); + res.setEntity(entity); + res.setBrackets(brackets); + return res; + } + public Statement dereference(BasicExpression var) { Vector newstats = new Vector(); for (int i = 0; i < statements.size(); i++) @@ -8807,6 +8894,19 @@ public Statement addContainerReference( return cs; } + public Statement optimiseOCL() + { CaseStatement cs = new CaseStatement(); + Vector ss = cases.elements; + for (int i = 0; i < ss.size(); i++) + { Maplet mm = (Maplet) ss.get(i); + Statement cse = (Statement) mm.dest; + Statement stat = cse.optimiseOCL(); + Maplet nn = new Maplet(mm.source,stat); + cs.addCase(nn); + } + return cs; + } + public void addCase(Maplet mm) { cases.add_element(mm); } @@ -9267,6 +9367,14 @@ public Statement substituteEq(String oldE, Expression newE) return new ErrorStatement(null); } + public Statement optimiseOCL() + { if (thrownObject != null) + { Expression tobj = thrownObject.simplifyOCL(); + return new ErrorStatement(tobj); + } + return new ErrorStatement(null); + } + public Map energyUse(Map uses, Vector rUses, Vector aUses) { if (thrownObject != null) { thrownObject.energyUse(uses, rUses, aUses); } @@ -9622,6 +9730,16 @@ public Statement dereference(BasicExpression var) return new AssertStatement(newcond,newmessage); } + public Statement optimiseOCL() + { Expression newcond = condition; + if (condition != null) + { newcond = condition.simplifyOCL(); } + Expression newmessage = message; + if (message != null) + { newmessage = message.simplifyOCL(); } + return new AssertStatement(newcond,newmessage); + } + public Statement addContainerReference(BasicExpression ref, String var, Vector excl) @@ -10027,6 +10145,18 @@ public Object clone() public Statement dereference(BasicExpression var) { return new CatchStatement(caughtObject.dereference(var), action.dereference(var)); } + public Statement optimiseOCL() + { Expression cobj = null; + if (caughtObject != null) + { cobj = caughtObject.simplifyOCL(); } + + Statement cact = null; + if (action != null) + { cact = action.optimiseOCL(); } + + return new CatchStatement(cobj,cact); + } + public void findClones(java.util.Map clones, String rule, String op) { if (action != null) { action.findClones(clones,rule,op); } @@ -10405,7 +10535,6 @@ else if (ends.size() == 1) { catchClauses = ends; endStatement = null; } - } public void setClauses(Vector stats) @@ -10591,6 +10720,26 @@ public Object clone() return res; } + public Statement optimiseOCL() + { Statement s1 = null; + if (body != null) + { s1 = body.optimiseOCL(); } + + TryStatement res = new TryStatement(s1); + + Vector catchClones = new Vector(); + for (int i = 0; i < catchClauses.size(); i++) + { Statement cc = (Statement) catchClauses.get(i); + Statement ccClone = (Statement) cc.optimiseOCL(); + catchClones.add(ccClone); + } + res.setClauses(catchClones); + + if (endStatement != null) + { res.setEndStatement(endStatement.optimiseOCL()); } + return res; + } + public Statement dereference(BasicExpression var) { Statement s1 = null; if (body != null) @@ -11284,6 +11433,19 @@ public Object clone() return res; } // clone the conditions + public Statement optimiseOCL() + { Vector newcases = new Vector(); + for (int i = 0; i < cases.size(); i++) + { IfCase cse = (IfCase) cases.get(i); + IfCase newcse = (IfCase) cse.optimiseOCL(); + newcases.add(newcse); + } + IfStatement res = new IfStatement(); + res.cases = newcases; + res.setEntity(entity); + return res; + } // clone the conditions + public Statement generateDesign(java.util.Map env, boolean local) { Vector newcases = new Vector(); for (int i = 0; i < cases.size(); i++) @@ -12356,6 +12518,15 @@ public Object clone() return res; } + public Statement optimiseOCL() + { Expression newlhs = lhs.simplifyOCL(); + Expression newrhs = rhs.simplifyOCL(); + AssignStatement res = new AssignStatement(newlhs,newrhs); + res.setType(type); + res.setCopyValue(copyValue); + return res; + } + public void findClones(java.util.Map clones, String rule, String op) { if (rhs.syntacticComplexity() < UCDArea.CLONE_LIMIT) { return; } @@ -13065,6 +13236,14 @@ public Object clone() return res; } + public IfCase optimiseOCL() + { Expression newtest = test.simplifyOCL(); + Statement newif = ifPart.optimiseOCL(); + IfCase res = new IfCase(newtest,newif); + res.setEntity(entity); + return res; + } + public IfCase dereference(BasicExpression var) { Expression newtest = (Expression) test.dereference(var); Statement newif = (Statement) ifPart.dereference(var); @@ -13544,6 +13723,25 @@ public Object clone() return new ConditionalStatement(testc, ifc, elsec); } + public Statement optimiseOCL() + { Expression testc = test.simplifyOCL(); + Statement ifc = ifPart.optimiseOCL(); + Statement elsec = null; + if (elsePart != null) + { elsec = elsePart.optimiseOCL(); } + + if ("true".equals(testc + "")) + { return ifc; } + + if ("false".equals(testc + "")) + { if (elsec == null) + { return new InvocationStatement("skip"); } + return elsec; + } + + return new ConditionalStatement(testc, ifc, elsec); + } + public java.util.Map collectionOperatorUses(int lev, java.util.Map uses) @@ -14197,6 +14395,11 @@ public Object clone() return new FinalStatement(ifc); } + public Statement optimiseOCL() + { Statement ifc = body.optimiseOCL(); + return new FinalStatement(ifc); + } + public void findClones(java.util.Map clones, String rule, String op) { body.findClones(clones,rule,op); } diff --git a/UCDArea.java b/UCDArea.java index 3b8c44d3..fb8480ea 100644 --- a/UCDArea.java +++ b/UCDArea.java @@ -3543,6 +3543,18 @@ else if (ent.isTarget()) out.println("*** Estimated maintainability correction cost = " + lowcost + " minutes (" + (lowcost/60.0) + " hours)"); } + public void simplifyOCL() + { for (int j = 0; j < entities.size(); j++) + { Entity ent = (Entity) entities.get(j); + if (ent.isDerived()) { continue; } + + if (ent.isComponent() || ent.isExternal()) + { continue; } + + ent.simplifyOCL(); + } + } + public void energyAnalysis() { java.util.Map clnes = new java.util.HashMap(); energyAnalysis(clnes); diff --git a/UmlTool.java b/UmlTool.java index 1ec90cfb..6884d951 100644 --- a/UmlTool.java +++ b/UmlTool.java @@ -1019,6 +1019,13 @@ public UmlTool() "Reduces depth of code nesting where possible"); qualityMenu.add(reduceNestingop); + JMenuItem simplifyOCLop = + new JMenuItem("Simplify OCL"); + simplifyOCLop.addActionListener(this); + simplifyOCLop.setToolTipText( + "Simplifies OCL expressions where possible"); + qualityMenu.add(simplifyOCLop); + JMenuItem refineMenu = new JMenu("Refinement"); transMenu.add(refineMenu); @@ -2854,6 +2861,8 @@ else if (label.equals("Hoist local declarations")) { this.hoistOperationLocalDecs(); } else if (label.equals("Reduce code nesting")) { this.reduceCodeNesting(); } + else if (label.equals("Simplify OCL")) + { ucdArea.simplifyOCL(); } else if (label.equals("Value Object")) { ucdArea.makeValueObjects(); } else if (label.equals("Singleton")) diff --git a/UnaryExpression.java b/UnaryExpression.java index 427a5a9f..1be38103 100644 --- a/UnaryExpression.java +++ b/UnaryExpression.java @@ -741,6 +741,83 @@ else if (operator.equals("->unionAll") || return res; } + public Expression simplifyOCL() + { Expression arg = + argument.simplifyOCL(); + + if (operator.equals("->any")) + { + if (argument instanceof BinaryExpression) + { BinaryExpression lbe = (BinaryExpression) argument; + + if (lbe.operator.equals("|")) + { // lbe.left | lbe.right + + BinaryExpression res = + new BinaryExpression("|A", lbe.left, lbe.right); + + System.out.println("! Inefficient ->any operation: " + + this + + "\n! Replaced by " + res); + + return res; + } + else if (lbe.operator.equals("->select")) + { // Inefficient col->select(P)->any() expression + // instead use: col->any(P) + + BinaryExpression res = + new BinaryExpression("->any", lbe.left, lbe.right); + + System.out.println("! Inefficient ->any operation: " + + this + + "\n! Replaced by " + res); + + return res; + } + else if (lbe.operator.equals("|R")) + { UnaryExpression notR = + new UnaryExpression("not", lbe.right); + BinaryExpression res = + new BinaryExpression("|A", lbe.left, notR); + + System.out.println("! Inefficient ->any operation: " + + this + + "\n! Replaced by " + res); + + return res; + } + else if (lbe.operator.equals("->reject")) + { UnaryExpression notR = + new UnaryExpression("not", lbe.right); + BinaryExpression res = + new BinaryExpression("->any", lbe.left, notR); + + System.out.println("! Inefficient ->any operation: " + + this + + "\n! Replaced by " + res); + + return res; + } + } + } + else if ("->sort".equals(operator)) + { if (argument.isSorted()) + { // Redundant ->sort operation: + // Argument is already sorted. + + System.out.println("! Redundant ->sort operation: " + + this + + "\n! Argument is already sorted."); + return arg; + } + } + + UnaryExpression res = (UnaryExpression) clone(); + res.argument = arg; + return res; + } + public java.util.Map collectionOperatorUses(int level, java.util.Map res) { // level |-> [x.setAt(i,y), etc]