From 6b78d10d0011a3a2c26cec980ef35098e18ae4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=96stlund?= Date: Fri, 5 Dec 2014 17:29:38 +0000 Subject: [PATCH] - Optimized some excessively used functions (crefPrefixOf, crefEqual, expEqual) - Small pattern matching optimization, don't match against RECORD() patterns in switch-optimized match-expressions (the switch already does the matching). git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@23679 f25d12d1-65f4-0310-ae8a-bbce733d8d8e --- Compiler/FrontEnd/ComponentReference.mo | 125 ++---- Compiler/FrontEnd/DAE.mo | 2 +- Compiler/FrontEnd/Expression.mo | 507 +++++++++++++----------- Compiler/FrontEnd/InnerOuter.mo | 35 +- Compiler/FrontEnd/Patternm.mo | 50 ++- 5 files changed, 355 insertions(+), 364 deletions(-) diff --git a/Compiler/FrontEnd/ComponentReference.mo b/Compiler/FrontEnd/ComponentReference.mo index 7741901c7d1..7997e625ec5 100644 --- a/Compiler/FrontEnd/ComponentReference.mo +++ b/Compiler/FrontEnd/ComponentReference.mo @@ -897,80 +897,48 @@ public function crefPrefixOf added also that a.b.c is a prefix of a.b.c[1].*!" input DAE.ComponentRef prefixCref; input DAE.ComponentRef fullCref; - output Boolean outBoolean; + output Boolean outPrefixOf; algorithm - outBoolean := match (prefixCref,fullCref) - local - DAE.ComponentRef cr1,cr2; - Boolean res; - DAE.Ident id1,id2; - list ss1,ss2; - - // first is qualified, second is an unqualified ident, return false! - case (DAE.CREF_QUAL(), DAE.CREF_IDENT()) then false; - + outPrefixOf := match (prefixCref,fullCref) // both are qualified, dive into - case (DAE.CREF_QUAL(ident = id1, subscriptLst = ss1,componentRef = cr1), - DAE.CREF_QUAL(ident = id2, subscriptLst = ss2,componentRef = cr2)) - equation - res = stringEq(id1, id2); - res = if res then Expression.subscriptEqual(ss1, ss2) else false; - res = if res then crefPrefixOf(cr1, cr2) else false; - then - res; + case (DAE.CREF_QUAL(), DAE.CREF_QUAL()) + then prefixCref.ident == fullCref.ident and + Expression.subscriptEqual(prefixCref.subscriptLst, fullCref.subscriptLst) and + crefPrefixOf(prefixCref.componentRef, fullCref.componentRef); // adrpo: 2010-10-07: first is an ID, second is qualified, see if one is prefix of the other // even if the first one DOESN'T HAVE SUBSCRIPTS! - case (DAE.CREF_IDENT(ident = id1,subscriptLst = {}), - DAE.CREF_QUAL(ident = id2)) - then stringEq(id1, id2); + case (DAE.CREF_IDENT(subscriptLst = {}), DAE.CREF_QUAL()) + then prefixCref.ident == fullCref.ident; // first is an ID, second is qualified, see if one is prefix of the other - case (DAE.CREF_IDENT(ident = id1,subscriptLst = ss1), - DAE.CREF_QUAL(ident = id2,subscriptLst = ss2)) - equation - res = if stringEq(id1, id2) then Expression.subscriptEqual(ss1, ss2) else false; - then - res; + case (DAE.CREF_IDENT(), DAE.CREF_QUAL()) + then prefixCref.ident == fullCref.ident and + Expression.subscriptEqual(prefixCref.subscriptLst, fullCref.subscriptLst); // adrpo: 2010-10-07: first is an ID, second is an ID, see if one is prefix of the other // even if the first one DOESN'T HAVE SUBSCRIPTS! - case (DAE.CREF_IDENT(ident = id1,subscriptLst = {}), - DAE.CREF_IDENT(ident = id2)) - then stringEq(id1, id2); + case (DAE.CREF_IDENT(subscriptLst = {}), DAE.CREF_IDENT()) + then stringEq(prefixCref.ident, fullCref.ident); - case (DAE.CREF_IDENT(ident = id1,subscriptLst = ss1), - DAE.CREF_IDENT(ident = id2,subscriptLst = ss2)) - equation - res = if stringEq(id1, id2) then Expression.subscriptEqual(ss1, ss2) else false; - then - res; - - /* adrpo: 2010-10-07. already handled by the cases above! - they might be equal, a.b.c is a prefix of a.b.c - case (cr1,cr2) - equation - true = crefEqualNoStringCompare(cr1, cr2); - then - true;*/ + case (DAE.CREF_IDENT(), DAE.CREF_IDENT()) + then prefixCref.ident == fullCref.ident and + Expression.subscriptEqual(prefixCref.subscriptLst, fullCref.subscriptLst); // they are not a prefix of one-another - else - equation - // print("Expression.crefPrefixOf: " + printComponentRefStr(cr1) + " NOT PREFIX OF " + printComponentRefStr(cr2) + "\n"); - then false; + else false; end match; end crefPrefixOf; public function crefNotPrefixOf "negation of crefPrefixOf" - input DAE.ComponentRef cr1; + input DAE.ComponentRef cr1; input DAE.ComponentRef cr2; output Boolean outBoolean; algorithm outBoolean := matchcontinue(cr1, cr2) // first is qualified, second is an unqualified ident, return false! case (DAE.CREF_QUAL(), DAE.CREF_IDENT()) then true; - else (not crefPrefixOf(cr1,cr2)); + else not crefPrefixOf(cr1, cr2); end matchcontinue; end crefNotPrefixOf; @@ -994,7 +962,7 @@ end crefInLst; public function crefEqualVerySlowStringCompareDoNotUse "Returns true if two component references are equal, - comparing strings in no other solution is found" + comparing strings if no other solution is found" input DAE.ComponentRef inComponentRef1; input DAE.ComponentRef inComponentRef2; output Boolean outBoolean; @@ -1101,49 +1069,28 @@ public function crefEqualNoStringCompare IMPORTANT! do not use this function if you have stringified components, meaning this function will return false for: cref1: QUAL(x, IDENT(x)) != cref2: IDENT(x.y)" - input DAE.ComponentRef cr1; - input DAE.ComponentRef cr2; - output Boolean res; + input DAE.ComponentRef inCref1; + input DAE.ComponentRef inCref2; + output Boolean outEqual; algorithm - res := crefEqualNoStringCompare2(referenceEq(cr1,cr2),cr1,cr2); -end crefEqualNoStringCompare; + if referenceEq(inCref1, inCref2) then + outEqual := true; + return; + end if; -protected function crefEqualNoStringCompare2 -"Returns true if two component references are equal! - IMPORTANT! do not use this function if you have - stringified components, meaning this function will - return false for: cref1: QUAL(x, IDENT(x)) != cref2: IDENT(x.y)" - input Boolean refEq; - input DAE.ComponentRef inComponentRef1; - input DAE.ComponentRef inComponentRef2; - output Boolean res; -algorithm - res := match (refEq,inComponentRef1,inComponentRef2) - local - DAE.Ident n1,n2; - list idx1,idx2; - DAE.ComponentRef cr1,cr2; + outEqual := match(inCref1, inCref2) + case (DAE.CREF_IDENT(), DAE.CREF_IDENT()) + then inCref1.ident == inCref2.ident and + Expression.subscriptEqual(inCref1.subscriptLst, inCref2.subscriptLst); - // check for pointer equality first, if they point to the same thing, they are equal - case (true,_,_) then true; + case (DAE.CREF_QUAL(), DAE.CREF_QUAL()) + then inCref1.ident == inCref2.ident and + crefEqualNoStringCompare(inCref1.componentRef, inCref2.componentRef) and + Expression.subscriptEqual(inCref1.subscriptLst, inCref2.subscriptLst); - // simple identifiers - case (_,DAE.CREF_IDENT(ident = n1,subscriptLst = idx1),DAE.CREF_IDENT(ident = n2,subscriptLst = idx2)) - equation - res = stringEq(n1, n2); - res = if res then Expression.subscriptEqual(idx1, idx2) else false; - then res; - // qualified crefs - case (_,DAE.CREF_QUAL(ident = n1,subscriptLst = idx1,componentRef = cr1),DAE.CREF_QUAL(ident = n2,subscriptLst = idx2,componentRef = cr2)) - equation - res = stringEq(n1, n2); - res = if res then crefEqualNoStringCompare2(referenceEq(cr1,cr2), cr1, cr2) else false; - res = if res then Expression.subscriptEqual(idx1, idx2) else false; - then res; - // the crefs are not equal! else false; end match; -end crefEqualNoStringCompare2; +end crefEqualNoStringCompare; public function crefEqualReturn "author: PA diff --git a/Compiler/FrontEnd/DAE.mo b/Compiler/FrontEnd/DAE.mo index 3f0b4f556bb..5288e883c18 100644 --- a/Compiler/FrontEnd/DAE.mo +++ b/Compiler/FrontEnd/DAE.mo @@ -1517,7 +1517,7 @@ end MatchCase; public uniontype MatchType record MATCHCONTINUE end MATCHCONTINUE; record MATCH - Option> switch "The index of the pattern to switch over, its type and an the value to divide string hashes with"; + Option> switch "The index of the pattern to switch over, its type and the value to divide string hashes with"; end MATCH; end MatchType; diff --git a/Compiler/FrontEnd/Expression.mo b/Compiler/FrontEnd/Expression.mo index d1ec85d35b5..6c332415c12 100644 --- a/Compiler/FrontEnd/Expression.mo +++ b/Compiler/FrontEnd/Expression.mo @@ -7910,300 +7910,323 @@ public function isIntegerOrReal "Returns true if Type is Integer or Real" input DAE.Type tp; output Boolean res; algorithm - res := matchcontinue(tp) - case(DAE.T_REAL()) then true; - case(DAE.T_INTEGER()) then true; + res := match(tp) + case DAE.T_REAL() then true; + case DAE.T_INTEGER() then true; else false; - end matchcontinue; + end match; end isIntegerOrReal; public function expEqual -"Returns true if the two expressions are equal." - input DAE.Exp e1; - input DAE.Exp e2; - output Boolean outBoolean; -algorithm - outBoolean := expEqualWork(e1, e2, referenceEq(e1,e2),true); - // To enable debugging - /*outBoolean := matchcontinue (e1,e2) - local - String s1,s2,s; - case (e1,e2) - then expEqualWork(e1, e2, referenceEq(e1,e2),true); - else - equation - s1 = ExpressionDump.printExpStr(e1); - s2 = ExpressionDump.printExpStr(e2); - s = "Expression.expEqual failed for input: " + s1 + " = " + s2; - Error.addMessage(Error.INTERNAL_ERROR, {s}); - then fail(); - end matchcontinue; - */ -end expEqual; - -protected function expEqualWork -"Returns true if the two expressions are equal." + "Returns true if the two expressions are equal, otherwise false." input DAE.Exp inExp1; input DAE.Exp inExp2; - input Boolean refEq; - input Boolean noFailedSubExpression; - output Boolean outBoolean; -algorithm - outBoolean := match (inExp1,inExp2,refEq,noFailedSubExpression) + output Boolean outEqual; +algorithm + // Return true if the references are the same. + if referenceEq(inExp1, inExp2) then + outEqual := true; + return; + end if; + + // Return false if the expressions are not of the same type. + if valueConstructor(inExp1) <> valueConstructor(inExp2) then + outEqual := false; + return; + end if; + + // Otherwise, check if the expressions are equal or not. + // Since the expressions have already been verified to be of the same type + // above we can match on only one of them to allow the pattern matching to + // optimize this to jump directly to the correct case. + outEqual := match(inExp1) local - Integer i1,i2; - String s1,s2; - Boolean b1,b2,res; - DAE.Exp e11,e12,e21,e22,e1,e2,e13,e23; - Operator op1,op2; - Absyn.Path path1,path2; - list expl1,expl2; - Type tp1,tp2; - Real r1,r2; - Absyn.Path enum1, enum2; - ComponentRef cr1,cr2; - list ae1,ae2; - case (_,_,_,false) then false; - case (_,_,true,_) then true; - case (DAE.ICONST(integer = i1),DAE.ICONST(integer = i2),_,_) then (i1 == i2); - case (DAE.UNARY(DAE.UMINUS(_),exp=DAE.ICONST(integer = i1)),DAE.ICONST(integer = i2),_,_) - equation - i1 = - i1; - then (i1 == i2); - case (DAE.ICONST(integer = i1),DAE.UNARY(DAE.UMINUS(_),exp=DAE.ICONST(integer = i2)),_,_) - equation - i2 = - i2; - then (i1 == i2); - case (DAE.RCONST(real = r1),DAE.RCONST(real = r2),_,_) then (r1 == r2); - case (DAE.UNARY(DAE.UMINUS(_),exp=DAE.RCONST(real = r1)),DAE.RCONST(real = r2),_,_) - equation - r1 = - r1; - then (r1 == r2); - case (DAE.RCONST(real = r1),DAE.UNARY(DAE.UMINUS(_),exp=DAE.RCONST(real = r2)),_,_) - equation - r2 = - r2; - then (r1 == r2); - case (DAE.SCONST(string = s1),DAE.SCONST(string = s2),_,_) then stringEq(s1, s2); - case (DAE.BCONST(bool = b1),DAE.BCONST(bool = b2),_,_) then boolEq(b1, b2); - case (DAE.ENUM_LITERAL(name = enum1), DAE.ENUM_LITERAL(name = enum2),_,_) then Absyn.pathEqual(enum1, enum2); - case (DAE.CREF(componentRef = cr1),DAE.CREF(componentRef = cr2),_,_) then ComponentReference.crefEqual(cr1, cr2); + Integer i; + Real r; + String s; + Boolean b; + Absyn.Path p; + DAE.Exp e, e1, e2; + Option oe; + list expl; + list> mexpl; + DAE.Operator op; + DAE.ComponentRef cr; + DAE.Type ty; - // binary ops - case (DAE.BINARY(exp1 = e11,operator = op1,exp2 = e12),DAE.BINARY(exp1 = e21,operator = op2,exp2 = e22),_,_) - equation - res = operatorEqual(op1, op2); - res = expEqualWork(e11, e21, referenceEq(e11, e21), res); - res = expEqualWork(e12, e22, referenceEq(e12, e22), res); + case DAE.ICONST() + algorithm + DAE.ICONST(integer = i) := inExp2; then - res; + inExp1.integer == i; - // logical binary ops - case (DAE.LBINARY(exp1 = e11,operator = op1,exp2 = e12), - DAE.LBINARY(exp1 = e21,operator = op2,exp2 = e22),_,_) - equation - res = operatorEqual(op1, op2); - res = expEqualWork(e11, e21, referenceEq(e11, e21), res); - res = expEqualWork(e12, e22, referenceEq(e12, e22), res); + case DAE.RCONST() + algorithm + DAE.RCONST(real = r) := inExp2; then - res; + inExp1.real == r; - // unary ops - case (DAE.UNARY(operator = op1,exp = e1),DAE.UNARY(operator = op2,exp = e2),_,_) - equation - res = operatorEqual(op1, op2); - res = expEqualWork(e1, e2, referenceEq(e1, e2), res); + case DAE.SCONST() + algorithm + DAE.SCONST(string = s) := inExp2; then - res; + inExp1.string == s; - // logical unary ops - case (DAE.LUNARY(operator = op1,exp = e1),DAE.LUNARY(operator = op2,exp = e2),_,_) - equation - res = operatorEqual(op1, op2); - res = expEqualWork(e1, e2, referenceEq(e1, e2), res); + case DAE.BCONST() + algorithm + DAE.BCONST(bool = b) := inExp2; then - res; + inExp1.bool == b; - // relational ops - case (DAE.RELATION(exp1 = e11,operator = op1,exp2 = e12),DAE.RELATION(exp1 = e21,operator = op2,exp2 = e22),_,_) - equation - res = operatorEqual(op1, op2); - res = expEqualWork(e11, e21, referenceEq(e11, e21), res); - res = expEqualWork(e12, e22, referenceEq(e12, e22), res); + case DAE.ENUM_LITERAL() + algorithm + DAE.ENUM_LITERAL(name = p) := inExp2; then - res; + Absyn.pathEqual(inExp1.name, p); - // if expressions - case (DAE.IFEXP(expCond = e11,expThen = e12,expElse = e13),DAE.IFEXP(expCond = e21,expThen = e22,expElse = e23),_,_) - equation - res = expEqualWork(e11, e21, referenceEq(e11, e21), true); - res = expEqualWork(e12, e22, referenceEq(e12, e22), res); - res = expEqualWork(e13, e23, referenceEq(e13, e23), res); + case DAE.CREF() + algorithm + DAE.CREF(componentRef = cr) := inExp2; then - res; + ComponentReference.crefEqual(inExp1.componentRef, cr); - // function calls - case (DAE.CALL(path = path1,expLst = expl1),DAE.CALL(path = path2,expLst = expl2),_,_) - equation - res = Absyn.pathEqual(path1, path2); - then expEqualWorkList(expl1, expl2, res); + case DAE.ARRAY() + algorithm + DAE.ARRAY(ty = ty, array = expl) := inExp2; + then + valueEq(inExp1.ty, ty) and expEqualList(inExp1.array, expl); - case (DAE.RECORD(path = path1,exps = expl1),DAE.RECORD(path = path2,exps = expl2),_,_) - equation - res = Absyn.pathEqual(path1, path2); - then expEqualWorkList(expl1, expl2, res); + case DAE.MATRIX() + algorithm + DAE.MATRIX(ty = ty, matrix = mexpl) := inExp2; + then + valueEq(inExp1.ty, ty) and expEqualListList(inExp1.matrix, mexpl); - // partially evaluated functions - case (DAE.PARTEVALFUNCTION(path = path1,expList = expl1),DAE.PARTEVALFUNCTION(path = path2,expList = expl2),_,_) - equation - res = Absyn.pathEqual(path1, path2); - then expEqualWorkList(expl1, expl2, res); + case DAE.BINARY() + algorithm + DAE.BINARY(exp1 = e1, operator = op, exp2 = e2) := inExp2; + then + operatorEqual(inExp1.operator, op) and + expEqual(inExp1.exp1, e1) and + expEqual(inExp1.exp2, e2); - // arrays - case (DAE.ARRAY(ty = tp1,array = expl1),DAE.ARRAY(ty = tp2,array = expl2),_,_) - equation - res = valueEq(tp1, tp2); - then expEqualWorkList(expl1, expl2, res); + case DAE.LBINARY() + algorithm + DAE.LBINARY(exp1 = e1, operator = op, exp2 = e2) := inExp2; + then + operatorEqual(inExp1.operator, op) and + expEqual(inExp1.exp1, e1) and + expEqual(inExp1.exp2, e2); - // matrix - case (e1 as DAE.MATRIX(), e2 as DAE.MATRIX(),_,_) - then valueEq(e1,e2); // TODO! FIXME! should use expEqual on elements + case DAE.UNARY() + algorithm + DAE.UNARY(exp = e, operator = op) := inExp2; + then + operatorEqual(inExp1.operator, op) and + expEqual(inExp1.exp, e); - // ranges [start:stop] - case (DAE.RANGE(start = e11,step = NONE(),stop = e13), - DAE.RANGE(start = e21,step = NONE(),stop = e23),_,_) - equation - res = expEqualWork(e11, e21, referenceEq(e11, e21), true); - res = expEqualWork(e13, e23, referenceEq(e13, e23), res); + case DAE.LUNARY() + algorithm + DAE.LUNARY(exp = e, operator = op) := inExp2; then - res; + operatorEqual(inExp1.operator, op) and + expEqual(inExp1.exp, e); + + case DAE.RELATION() + algorithm + DAE.RELATION(exp1 = e1, operator = op, exp2 = e2) := inExp2; + then + operatorEqual(inExp1.operator, op) and + expEqual(inExp1.exp1, e1) and + expEqual(inExp1.exp2, e2); - // ranges [start:step:stop] - case (DAE.RANGE(start = e11,step = SOME(e12),stop = e13), - DAE.RANGE(start = e21,step = SOME(e22),stop = e23),_,_) - equation - res = expEqualWork(e11, e21, referenceEq(e11, e21), true); - res = expEqualWork(e12, e22, referenceEq(e12, e22), res); - res = expEqualWork(e13, e23, referenceEq(e13, e23), res); + case DAE.IFEXP() + algorithm + DAE.IFEXP(expCond = e, expThen = e1, expElse = e2) := inExp2; then - res; + expEqual(inExp1.expCond, e) and + expEqual(inExp1.expThen, e1) and + expEqual(inExp1.expElse, e2); - // tuples - case (DAE.TUPLE(PR = expl1),DAE.TUPLE(PR = expl2),_,_) - equation - // fails if not all mapped calls return true - then expEqualWorkList(expl1, expl2, true); + case DAE.CALL() + algorithm + DAE.CALL(path = p, expLst = expl) := inExp2; + then + Absyn.pathEqual(inExp1.path, p) and + expEqualList(inExp1.expLst, expl); - // casting - case (DAE.CAST(ty = tp1,exp = e1),DAE.CAST(ty = tp2,exp = e2),_,_) - equation - res = valueEq(tp1, tp2); - then expEqualWork(e1, e2, referenceEq(e1,e2), res); + case DAE.RECORD() + algorithm + DAE.RECORD(path = p, exps = expl) := inExp2; + then + Absyn.pathEqual(inExp1.path, p) and + expEqualList(inExp1.exps, expl); - // array subscripts - case (DAE.ASUB(exp = e1,sub = ae1),DAE.ASUB(exp = e2,sub = ae2),_,_) - equation - res = expEqualWork(e1, e2, referenceEq(e1, e2), true); - then expEqualWorkList(ae1, ae2, res); + case DAE.PARTEVALFUNCTION() + algorithm + DAE.PARTEVALFUNCTION(path = p, expList = expl) := inExp2; + then + Absyn.pathEqual(inExp1.path, p) and + expEqualList(inExp1.expList, expl); - // size(a) - case (DAE.SIZE(exp = e1,sz = NONE()),DAE.SIZE(exp = e2,sz = NONE()),_,_) - then expEqualWork(e1, e2, referenceEq(e1,e2), true); + case DAE.RANGE() + algorithm + DAE.RANGE(start = e1, step = oe, stop = e2) := inExp2; + then + expEqual(inExp1.start, e1) and + expEqual(inExp1.stop, e2) and + expEqualOpt(inExp1.step, oe); - // size(a, dim) - case (DAE.SIZE(exp = e1,sz = SOME(e11)),DAE.SIZE(exp = e2,sz = SOME(e22)),_,_) - equation - res = expEqualWork(e1, e2, referenceEq(e1, e2), true); - res = expEqualWork(e11, e22, referenceEq(e11, e22), res); + case DAE.TUPLE() + algorithm + DAE.TUPLE(PR = expl) := inExp2; then - res; + expEqualList(inExp1.PR, expl); - // metamodeling code - case (DAE.CODE(),DAE.CODE(),_,_) - equation - Debug.trace("exp_equal on CODE not impl.\n"); + case DAE.CAST() + algorithm + DAE.CAST(ty = ty, exp = e) := inExp2; then - false; + valueEq(inExp1.ty, ty) and expEqual(inExp1.exp, e); - case (DAE.REDUCTION(),DAE.REDUCTION(),_,_) - equation - // Reductions contain too much information to compare equality in a sane manner - res = valueEq(inExp1,inExp2); + case DAE.ASUB() + algorithm + DAE.ASUB(exp = e, sub = expl) := inExp2; then - res; + expEqual(inExp1.exp, e) and expEqualList(inExp1.sub, expl); - // end id - /*// everything else failed, try structural equality - case (e1,e2) - equation - equality(e1 = e2); - then true; - case (e1,e2) - equation - failure(equality(e1 = e2)); - then false; - */ - // not equal - case (DAE.LIST(valList = expl1),DAE.LIST(valList = expl2),_,_) - then expEqualWorkList(expl1, expl2, true); + case DAE.SIZE() + algorithm + DAE.SIZE(exp = e, sz = oe) := inExp2; + then + expEqual(inExp1.exp, e) and expEqualOpt(inExp1.sz, oe); - case (DAE.CONS(car = e11,cdr = e12), - DAE.CONS(car = e21,cdr = e22),_,_) - equation - res = expEqualWork(e11, e21, referenceEq(e11, e21), true); - res = expEqualWork(e12, e22, referenceEq(e12, e22), res); + case DAE.REDUCTION() + // Reductions contain too much information to compare in a sane manner. + then valueEq(inExp1, inExp2); + + case DAE.LIST() + algorithm + DAE.LIST(valList = expl) := inExp2; then - res; + expEqualList(inExp1.valList, expl); - case (DAE.META_TUPLE(listExp = expl1),DAE.META_TUPLE(listExp = expl2),_,_) - then expEqualWorkList(expl1, expl2, true); + case DAE.CONS() + algorithm + DAE.CONS(car = e1, cdr = e2) := inExp2; + then + expEqual(inExp1.car, e1) and expEqual(inExp1.cdr, e2); - case (DAE.META_OPTION(exp = NONE()), - DAE.META_OPTION(exp = NONE()),_,_) - then true; + case DAE.META_TUPLE() + algorithm + DAE.META_TUPLE(listExp = expl) := inExp2; + then + expEqualList(inExp1.listExp, expl); - case (DAE.META_OPTION(exp = SOME(e1)), - DAE.META_OPTION(exp = SOME(e2)),_,_) - then expEqualWork(e1, e2, referenceEq(e1, e2), true); + case DAE.META_OPTION() + algorithm + DAE.META_OPTION(exp = oe) := inExp2; + then + expEqualOpt(inExp1.exp, oe); - case (DAE.METARECORDCALL(path = path1,args = expl1),DAE.METARECORDCALL(path = path2,args = expl2),_,_) - equation - res = Absyn.pathEqual(path1, path2); - then expEqualWorkList(expl1, expl2, res); + case DAE.METARECORDCALL() + algorithm + DAE.METARECORDCALL(path = p, args = expl) := inExp2; + then + Absyn.pathEqual(inExp1.path, p) and expEqualList(inExp1.args, expl); - case (e1 as DAE.MATCHEXPRESSION(), - e2 as DAE.MATCHEXPRESSION(),_,_) - then valueEq(e1,e2); + case DAE.MATCHEXPRESSION() + then valueEq(inExp1, inExp2); - case (DAE.BOX(e1),DAE.BOX(e2),_,_) - then expEqualWork(e1, e2, referenceEq(e1, e2), true); + case DAE.BOX() + algorithm + DAE.BOX(exp = e) := inExp2; + then + expEqual(inExp1.exp, e); - case (DAE.UNBOX(exp=e1),DAE.UNBOX(exp=e2),_,_) - then expEqualWork(e1, e2, referenceEq(e1, e2), true); + case DAE.UNBOX() + algorithm + DAE.UNBOX(exp = e) := inExp2; + then + expEqual(inExp1.exp, e); - case (DAE.SHARED_LITERAL(index=i1),DAE.SHARED_LITERAL(index=i2),_,_) then intEq(i1,i2); + case DAE.SHARED_LITERAL() + algorithm + DAE.SHARED_LITERAL(index = i) := inExp2; + then + inExp1.index == i; else false; end match; -end expEqualWork; - -protected function expEqualWorkList -"Returns true if the two expressions are equal." - input list inExp1; - input list inExp2; - input Boolean noFailedSubExpression; - output Boolean outBoolean; +end expEqual; + +protected function expEqualOpt + input Option inExp1; + input Option inExp2; + output Boolean outEqual; +protected + DAE.Exp e1, e2; algorithm - outBoolean := match (inExp1,inExp2,noFailedSubExpression) - local - DAE.Exp e1,e2; - list es1,es2; - case (_,_,false) then false; - case ({},{},_) then true; - case (e1::es1,e2::es2,_) - then expEqualWorkList(es1,es2,expEqualWork(e1,e2,referenceEq(e1,e2),true)); + outEqual := match(inExp1, inExp2) + case (NONE(), NONE()) then true; + case (SOME(e1), SOME(e2)) then expEqual(e1, e2); else false; end match; -end expEqualWorkList; +end expEqualOpt; + +protected function expEqualList + input list inExpl1; + input list inExpl2; + output Boolean outEqual; +protected + DAE.Exp e2; + list rest_expl2 := inExpl2; +algorithm + // Check that the lists have the same length, otherwise they can't be equal. + if listLength(inExpl1) <> listLength(inExpl2) then + outEqual := false; + return; + end if; + + for e1 in inExpl1 loop + e2 :: rest_expl2 := rest_expl2; + + // Return false if the expressions are not equal. + if not expEqual(e1, e2) then + outEqual := false; + return; + end if; + end for; + + outEqual := true; +end expEqualList; + +protected function expEqualListList + input list> inExpl1; + input list> inExpl2; + output Boolean outEqual; +protected + list expl2; + list> rest_expl2 := inExpl2; +algorithm + // Check that the lists have the same length, otherwise they can't be equal. + if listLength(inExpl1) <> listLength(inExpl2) then + outEqual := false; + return; + end if; + + for expl1 in inExpl1 loop + expl2 :: rest_expl2 := rest_expl2; + + // Return false if the expression lists are not equal. + if not expEqualList(expl1, expl2) then + outEqual := false; + return; + end if; + end for; + + outEqual := true; +end expEqualListList; public function expStructuralEqual "Returns true if the two expressions are structural equal. This means @@ -9000,14 +9023,14 @@ algorithm // slices as heads, compare the slice exps and then compare the rest case ((DAE.SLICE(exp = e1) :: xs1),(DAE.SLICE(exp = e2) :: xs2)) - then subscriptEqual(xs1, xs2) and expEqual(e1, e2); + then expEqual(e1, e2) and subscriptEqual(xs1, xs2); // indexes as heads, compare the index exps and then compare the rest case ((DAE.INDEX(exp = e1) :: xs1),(DAE.INDEX(exp = e2) :: xs2)) - then subscriptEqual(xs1, xs2) and expEqual(e1, e2); + then expEqual(e1, e2) and subscriptEqual(xs1, xs2); case ((DAE.WHOLE_NONEXP(exp = e1) :: xs1),(DAE.WHOLE_NONEXP(exp = e2) :: xs2)) - then subscriptEqual(xs1, xs2) and expEqual(e1, e2); + then expEqual(e1, e2) and subscriptEqual(xs1, xs2); // subscripts are not equal, return false else false; diff --git a/Compiler/FrontEnd/InnerOuter.mo b/Compiler/FrontEnd/InnerOuter.mo index 649f6852ca8..704d16c1896 100644 --- a/Compiler/FrontEnd/InnerOuter.mo +++ b/Compiler/FrontEnd/InnerOuter.mo @@ -1741,35 +1741,16 @@ protected function searchForInnerPrefix output DAE.ComponentRef outerCrefPrefix; output DAE.ComponentRef innerCrefPrefix; algorithm - (outerCrefPrefix, innerCrefPrefix) := matchcontinue(fullCref, outerPrefixes) - local - DAE.ComponentRef crOuter, crInner; - OuterPrefixes rest; + for op in outerPrefixes loop + OUTER(outerComponentRef = outerCrefPrefix) := op; - // we haven't found it, fail! - case (_, {}) - then - fail(); + if ComponentReference.crefPrefixOf(outerCrefPrefix, fullCref) then + OUTER(innerComponentRef = innerCrefPrefix) := op; + return; + end if; + end for; - // handle the head that matches - case (_, OUTER(crOuter, crInner)::_) - equation - /* - print("Full: " + ComponentReference.printComponentRefStr(fullCref) + - " outer: " + ComponentReference.printComponentRefStr(crOuter) + - " inner: " + ComponentReference.printComponentRefStr(crInner) + "\n"); - */ - true = ComponentReference.crefPrefixOf(crOuter, fullCref); - then - (crOuter, crInner); - - // handle the rest - case (_, _::rest) - equation - (crOuter, crInner) = searchForInnerPrefix(fullCref, rest); - then - (crOuter, crInner); - end matchcontinue; + fail(); end searchForInnerPrefix; public function printInnerDefStr diff --git a/Compiler/FrontEnd/Patternm.mo b/Compiler/FrontEnd/Patternm.mo index 1cd07e780c9..6f7dcbe9a74 100644 --- a/Compiler/FrontEnd/Patternm.mo +++ b/Compiler/FrontEnd/Patternm.mo @@ -712,7 +712,7 @@ algorithm ht = getUsedLocalCrefs(Flags.isSet(Flags.PATTERNM_SKIP_FILTER_UNUSED_AS_BINDINGS),DAE.MATCHEXPRESSION(DAE.MATCHCONTINUE(),elabExps,inputAliases,matchDecls,elabCases,et),hashSize); (matchDecls,ht) = filterUnusedDecls(matchDecls,ht,{},HashTableStringToPath.emptyHashTableSized(hashSize)); (elabExps,inputAliases,elabCases) = filterUnusedPatterns(elabExps,inputAliases,elabCases) "filterUnusedPatterns() again to filter out the last parts."; - elabMatchTy = optimizeMatchToSwitch(matchTy,elabCases,info); + (elabMatchTy, elabCases) = optimizeMatchToSwitch(matchTy,elabCases,info); exp = DAE.MATCHEXPRESSION(elabMatchTy,elabExps,inputAliases,matchDecls,elabCases,et); then (cache,exp,prop,st); else @@ -737,8 +737,9 @@ protected function optimizeMatchToSwitch input list cases; input SourceInfo info; output DAE.MatchType outType; + output list outCases; algorithm - outType := matchcontinue (matchTy,cases,info) + (outType, outCases) := matchcontinue (matchTy,cases,info) local tuple tpl; list> patternMatrix; @@ -746,7 +747,7 @@ algorithm Integer numNonEmptyColumns; String str; DAE.Type ty; - case (Absyn.MATCHCONTINUE(),_,_) then DAE.MATCHCONTINUE(); + case (Absyn.MATCHCONTINUE(),_,_) then (DAE.MATCHCONTINUE(), cases); case (_,_,_) equation true = listLength(cases) > 2; @@ -756,11 +757,50 @@ algorithm (_,ty,_) = tpl; str = Types.unparseType(ty); Error.assertionOrAddSourceMessage(not Flags.isSet(Flags.PATTERNM_ALL_INFO),Error.MATCH_TO_SWITCH_OPTIMIZATION, {str}, info); - then DAE.MATCH(SOME(tpl)); - else DAE.MATCH(NONE()); + outType = DAE.MATCH(SOME(tpl)); + outCases = optimizeSwitchedMatchCases(outType, cases); + then + (outType, outCases); + + else (DAE.MATCH(NONE()), cases); end matchcontinue; end optimizeMatchToSwitch; +protected function optimizeSwitchedMatchCases + "This function optimizes the cases of a match that has been optimized into a switch." + input DAE.MatchType inMatchType; + input list inCases; + output list outCases; +algorithm + outCases := match(inMatchType) + local + DAE.Pattern pat; + list patl; + + // If we're switching on a uniontype, mark all cases that look like RECORD() + // as singleton, so we can skip doing pattern matching on them (we're + // already switching on their type, we don't need to check the type in the + // case also. + case DAE.MATCH(switch = SOME((_, DAE.T_METATYPE(), _))) + then list( + match c + case DAE.CASE(patterns = {pat as DAE.PAT_CALL(patterns = patl)}) + algorithm + if allPatternsWild(patl) then + pat.knownSingleton := true; + c.patterns := {pat}; + end if; + then + c; + + else c; + end match + for c in inCases); + + else inCases; + end match; +end optimizeSwitchedMatchCases; + protected function removeWildPatternColumnsFromMatrix input list> inPatternMatrix; input list>> inAcc;