From 96a1c7828d444ced575ad57198a12548dc1ab020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=96stlund?= Date: Mon, 19 Oct 2015 11:29:41 +0200 Subject: [PATCH 1/2] Fix inst of Annex60 (and maybe Buildings). - Type convert record values when when evaluating modifier values, to make sure they are of the correct types. - Better check for duplicate modifiers, gets rid of some "duplicate modifier" errors. - Better merging of record modifiers, gets rid of even more "duplicate modifier" errors. - Some cleanup. --- Compiler/FrontEnd/Inst.mo | 133 ++------ Compiler/FrontEnd/Mod.mo | 550 ++++++++++++++++++-------------- Compiler/FrontEnd/ValuesUtil.mo | 41 +++ Compiler/Util/Error.mo | 2 +- 4 files changed, 384 insertions(+), 342 deletions(-) diff --git a/Compiler/FrontEnd/Inst.mo b/Compiler/FrontEnd/Inst.mo index 5358dbe733d..8e5ce5a487a 100644 --- a/Compiler/FrontEnd/Inst.mo +++ b/Compiler/FrontEnd/Inst.mo @@ -4199,61 +4199,23 @@ protected function updateComponentsInEnv input list crefs; input ClassInf.State ci_state; input Boolean impl; - output FCore.Cache outCache; - output FCore.Graph outEnv; - output InnerOuter.InstHierarchy outIH; + output FCore.Cache outCache = cache; + output FCore.Graph outEnv = env; + output InnerOuter.InstHierarchy outIH = inIH; algorithm - (outCache,outEnv,outIH) := matchcontinue(cache, env, inIH, pre, mod, crefs, ci_state, impl) + ErrorExt.setCheckpoint("updateComponentsInEnv__"); - // case (_, _, _, _, _, _, _, _) then (cache,env,inIH); - - // do NOT fail and do not display any errors from this function as it tries to type and evaluate dependent things but not with enough information - case (_, _, _, _, _, _, _, _) - equation - ErrorExt.setCheckpoint("updateComponentsInEnv__"); - (outCache,outEnv,outIH) = updateComponentsInEnv_dispatch(cache, env, inIH, pre, mod, crefs, ci_state, impl); - ErrorExt.rollBack("updateComponentsInEnv__") "roll back any errors"; - then - (outCache,outEnv,outIH); + // do NOT fail and do not display any errors from this function as it tries + // to type and evaluate dependent things but not with enough information + try + (outCache, outEnv, outIH) := + updateComponentsInEnv2(cache, env, inIH, pre, mod, crefs, ci_state, impl); + else + end try; - // do NOT fail and do not display any errors from this function as it tries to type and evaluate dependent things but not with enough information - else - equation - ErrorExt.rollBack("updateComponentsInEnv__") "roll back any errors"; - then - (cache,env,inIH); - end matchcontinue; + ErrorExt.rollBack("updateComponentsInEnv__") "roll back any errors"; end updateComponentsInEnv; -protected function updateComponentsInEnv_dispatch -"author: PA - This function is the second pass of component instantiation, when a - component can be instantiated fully and the type of the component can be - determined. The type is added/updated to the environment such that other - components can use it when they are instantiated." - input FCore.Cache cache; - input FCore.Graph env; - input InnerOuter.InstHierarchy inIH; - input Prefix.Prefix pre; - input DAE.Mod mod; - input list crefs; - input ClassInf.State ci_state; - input Boolean impl; - output FCore.Cache outCache; - output FCore.Graph outEnv; - output InnerOuter.InstHierarchy outIH; -protected - String myTick, crefsStr; -algorithm - //myTick := intString(tick()); - //crefsStr := stringDelimitList(List.map(crefs, Dump.printComponentRefStr),","); - //fprintln(Flags.DEBUG,"start update comps " + myTick + " # " + crefsStr); - (outCache,outEnv,outIH,_):= - updateComponentsInEnv2(cache,env,inIH,pre,mod,crefs,ci_state,impl,NONE(),NONE()); - //fprintln(Flags.DEBUG,"finished update comps" + myTick); - //print("outEnv:");print(FGraph.printGraphStr(outEnv));print("\n"); -end updateComponentsInEnv_dispatch; - protected function getUpdatedCompsHashTable "Routine to lazily create the hashtable as it usually unused" input Option optHT; @@ -5552,59 +5514,28 @@ protected function updateComponentsInEnv2 input list crefs; input ClassInf.State ci_state; input Boolean impl; - input Option inUpdatedComps; - input Option currentCref; - output FCore.Cache outCache; - output FCore.Graph outEnv; - output InnerOuter.InstHierarchy outIH; - output Option outUpdatedComps; + input Option inUpdatedComps = NONE(); + input Option currentCref = NONE(); + output FCore.Cache outCache = inCache; + output FCore.Graph outEnv = inEnv; + output InnerOuter.InstHierarchy outIH = inIH; + output Option outUpdatedComps = inUpdatedComps; +protected + String name; + DAE.Binding binding; algorithm - (outCache,outEnv,outIH,outUpdatedComps) := - matchcontinue (inCache,inEnv,inIH,pre,mod,crefs,ci_state,impl,inUpdatedComps,currentCref) - local - FCore.Graph env_1,env_2; - DAE.Mod mods; - Absyn.ComponentRef cr; - list rest; - InstanceHierarchy ih; - String n; - DAE.Binding binding; - Option updatedComps; - FCore.Cache cache; - FCore.Graph env; - - // This case catches when we want to update an already typed and bound var. - case (cache,env,ih,_,mods,(Absyn.CREF_IDENT(name = n, subscripts = {}) :: rest),_,_,updatedComps,_) - equation - // (_,DAE.TYPES_VAR(binding = binding),_,_,_,_) = Lookup.lookupIdent(cache, env, n); - (_,DAE.TYPES_VAR(binding = binding),_,_,_,_) = Lookup.lookupIdentLocal(cache, env, n); - true = DAEUtil.isBound(binding); - (cache,env_2,ih,updatedComps) = updateComponentsInEnv2(cache, env, ih, - pre, mods, rest, ci_state, impl, updatedComps, currentCref); - then - (cache,env_2,ih,updatedComps); - - case (cache,env,ih,_,mods,(cr :: rest),_,_,updatedComps,_) /* Implicit instantiation */ - equation - //ErrorExt.setCheckpoint(); - // this line below "updateComponentInEnv" can not fail so no need to catch that checkpoint(error). - //print(" Updating component: " + Absyn.printComponentRefStr(cr) + " mods: " + Mod.printModStr(mods)+ "\n"); - (cache,env_1,ih,updatedComps) = updateComponentInEnv(cache, env, ih, pre, mods, cr, ci_state, impl, updatedComps, currentCref); - //ErrorExt.rollBack(); - (cache,env_2,ih,updatedComps) = updateComponentsInEnv2(cache, env_1, ih, - pre, mods, rest, ci_state, impl, updatedComps, currentCref); - then - (cache,env_2,ih,updatedComps); - - case (cache,env,ih,_,_,{},_,_,updatedComps,_) - then (cache,env,ih,updatedComps); - + for cr in crefs loop + try + Absyn.CREF_IDENT(name = name, subscripts = {}) := cr; + (_, DAE.TYPES_VAR(binding = binding), _, _, _, _) := + Lookup.lookupIdentLocal(outCache, outEnv, name); + true := DAEUtil.isBound(binding); else - equation - true = Flags.isSet(Flags.FAILTRACE); - Debug.trace("-updateComponentsInEnv failed\n"); - then fail(); - end matchcontinue; + (outCache, outEnv, outIH, outUpdatedComps) := + updateComponentInEnv(outCache, outEnv, outIH, pre, mod, cr, ci_state, + impl, outUpdatedComps, currentCref); + end try; + end for; end updateComponentsInEnv2; protected function makeFullyQualified2 diff --git a/Compiler/FrontEnd/Mod.mo b/Compiler/FrontEnd/Mod.mo index 95ccf64e067..24deea13272 100644 --- a/Compiler/FrontEnd/Mod.mo +++ b/Compiler/FrontEnd/Mod.mo @@ -427,6 +427,11 @@ algorithm try (_, v) := Ceval.ceval(inCache, inEnv, inExp, false, NONE(), msg, 0); + + if ValuesUtil.isRecord(v) then + v := ValuesUtil.typeConvertRecord(v, Expression.typeof(inExp)); + end if; + outValue := SOME(v); else // Fail if ceval gave an error. Except if the expression contains a @@ -923,7 +928,7 @@ algorithm then SCode.NAMEMOD(id, SCode.MOD(fp, ep, submods1, binding, info2)); - // The first modifier has no binding, use the binding from the second. + // Both modifiers have bindings, print error. case (SCode.NAMEMOD(mod = mod1), SCode.NAMEMOD(mod = mod2), _, _) equation info1 = SCode.getModifierInfo(mod1); @@ -1096,9 +1101,8 @@ algorithm equation mod1 = lookupCompModification2(subs, n); mod2 = lookupComplexCompModification(eqMod,n,f,e); - mod = checkDuplicateModifications(mod1,mod2,n); then - mod; + checkDuplicateModifications(mod1,mod2,n); else DAE.NOMOD(); end match; @@ -1256,7 +1260,6 @@ protected DAE.Type ty; DAE.EqMod eq_mod; SourceInfo info; - algorithm try SOME(DAE.TYPED( @@ -1287,9 +1290,9 @@ print error of duplicate modifications, if not, the one modification having a va input String n; output DAE.Mod outMod; algorithm - outMod := matchcontinue(mod1, mod2) + outMod := match(mod1, mod2) local - String s1,s2,s,n2; + list submods; case (DAE.NOMOD(), _) then mod2; case (_, DAE.NOMOD()) then mod1; @@ -1300,27 +1303,55 @@ algorithm case (DAE.MOD(), DAE.REDECL()) then mergeRedeclareWithBinding(mod2, mod1); - // if they are equal, ignoring prefix, return the second one! - case (_, _) - equation - true = modEqual(mod1, mod2); + case (DAE.MOD(eqModOption = NONE()), DAE.MOD()) + algorithm + submods := checkDuplicateModifications2(mod1.subModLst, mod2.subModLst, n); then - mod2; + DAE.MOD(mod2.finalPrefix, mod2.eachPrefix, submods, mod2.eqModOption); - // print error message - else - equation - s1 = printModStr(mod1); - s2 = printModStr(mod2); - s = s1 + " and " + s2; - n2 = "component " + n; - Error.addMessage(Error.DUPLICATE_MODIFICATIONS,{s,n2}); + case (DAE.MOD(), DAE.MOD(eqModOption = NONE())) + algorithm + submods := checkDuplicateModifications2(mod1.subModLst, mod2.subModLst, n); + then + DAE.MOD(mod1.finalPrefix, mod1.eachPrefix, submods, mod1.eqModOption); + + case (DAE.MOD(), DAE.MOD()) + algorithm + Error.addMultiSourceMessage(Error.DUPLICATE_MODIFICATIONS, {n, ""}, + {getModInfo(mod1), getModInfo(mod2)}); then mod2; - end matchcontinue; + end match; end checkDuplicateModifications; +protected function checkDuplicateModifications2 + input list inSubMods1; + input list inSubMods2; + input String inName; + output list outSubMods; +protected + list submods = inSubMods2; + Option osubmod; + DAE.SubMod submod; + SourceInfo info1, info2; +algorithm + for s in inSubMods1 loop + (submods, osubmod) := + List.deleteMemberOnTrue(subModName(s), submods, isSubModNamed); + + if isSome(osubmod) then + SOME(submod) := osubmod; + + info1 := subModInfo(s); + info2 := subModInfo(submod); + Error.addMultiSourceMessage(Error.MULTIPLE_MODIFIER, {inName}, {info1, info2}); + end if; + end for; + + outSubMods := listAppend(inSubMods1, inSubMods2); +end checkDuplicateModifications2; + protected function mergeRedeclareWithBinding "Merges two modifiers where the first is a redeclare and the second a binding modifier. This is to handle the case where an extended record redeclares a @@ -1336,11 +1367,13 @@ algorithm outMod := match(outMod, inBinding) local SCode.Element el; + DAE.Mod mod; - case (DAE.REDECL(tplSCodeElementModLst = {(el, DAE.NOMOD())}), + case (DAE.REDECL(tplSCodeElementModLst = {(el, mod)}), DAE.MOD(subModLst = {}, eqModOption = SOME(_))) algorithm - outMod.tplSCodeElementModLst := {(el, inBinding)}; + mod := merge(inBinding, mod, FGraph.emptyGraph, Prefix.NOPRE()); + outMod.tplSCodeElementModLst := {(el, mod)}; then outMod; @@ -1603,252 +1636,226 @@ algorithm end matchcontinue; end indexEqmod; -public function merge " -A mid step for merging two modifiers. -It validates that the merging is allowed(considering final modifier)." - input DAE.Mod inModOuter "the outer mod which should overwrite the inner mod"; - input DAE.Mod inModInner "the inner mod"; +public function merge + "Merges two modifiers, where the outer modifier overrides the inner one." + input DAE.Mod inModOuter "The outer mod which should override the inner mod."; + input DAE.Mod inModInner "The inner mod."; input FCore.Graph inEnv; input Prefix.Prefix inPrefix; output DAE.Mod outMod; algorithm - outMod:= matchcontinue (inModOuter,inModInner,inEnv,inPrefix) + outMod := matchcontinue(inModOuter, inModInner) local - DAE.Mod m; - String s1, s2, s3, s4; - Option p; - list> elsmods1, elsmods2; - SCode.Final fp1, fp2; - SCode.Each ep1, ep2; - SCode.Program els1, els2; + String s1, s2, s3, s4; - case (DAE.NOMOD(),DAE.NOMOD(),_,_) then DAE.NOMOD(); - case (DAE.NOMOD(),m,_,_) then m; - case (m,DAE.NOMOD(),_,_) then m; - // That's a NOMOD() if I ever saw one... - case (m,DAE.MOD(subModLst={},eqModOption=NONE()),_,_) then m; - case (DAE.MOD(subModLst={},eqModOption=NONE()),m,_,_) then m; + // If either modifier is empty, return the other one. + case (DAE.NOMOD(), _) then inModInner; + case (_, DAE.NOMOD()) then inModOuter; + case (DAE.MOD(subModLst = {}, eqModOption = NONE()), _) then inModInner; + case (_, DAE.MOD(subModLst = {}, eqModOption = NONE())) then inModOuter; - case(_,_,_,_) - equation - //true = merge2(inModInner); - then - doMerge(inModOuter,inModInner,inEnv,inPrefix); + case (_, _) then doMerge(inModOuter, inModInner, inEnv, inPrefix); - case(_,_,_,_) - equation - true = modSubsetOrEqualOrNonOverlap(inModOuter,inModInner); - m = doMerge(inModOuter,inModInner,inEnv,inPrefix); - then - m; - - // two exactly the same mod, return just one! (used when it is REDECL or a submod is REDECL) - case(DAE.REDECL(fp1, ep1, elsmods1),DAE.REDECL(fp2, ep2, elsmods2),_,_) - equation - true = SCode.eachEqual(ep1, ep2); - true = SCode.finalEqual(fp1, fp2); - els1 = List.map(elsmods1, Util.tuple21); - els2 = List.map(elsmods2, Util.tuple21); - true = List.fold(List.threadMap(els1, els2, SCode.elementEqual), boolAnd, true); + // Two identical redeclares, return one of them. + case (DAE.REDECL(), DAE.REDECL()) + algorithm + true := SCode.eachEqual(inModOuter.eachPrefix, inModInner.eachPrefix); + true := SCode.finalEqual(inModOuter.finalPrefix, inModInner.finalPrefix); + List.threadMapAllValue( + list(Util.tuple21(e) for e in inModInner.tplSCodeElementModLst), + list(Util.tuple21(e) for e in inModOuter.tplSCodeElementModLst), + SCode.elementEqual, true); then inModOuter; else - equation - false = merge2(inModInner); - false = modSubsetOrEqualOrNonOverlap(inModOuter,inModInner); - p = FGraph.getScopePath(inEnv); - s1 = PrefixUtil.printPrefixStrIgnoreNoPre(inPrefix); - s2 = Absyn.optPathString(p); - s3 = printModStr(inModOuter); - s4 = printModStr(inModInner); - Error.addMessage(Error.FINAL_OVERRIDE, {s1,s2,s3,s4}); - // keep this for debugging via gdb. - // _ = merge(inModOuter,inModInner,inEnv,inPrefix); + algorithm + false := merge2(inModInner); + false := modSubsetOrEqualOrNonOverlap(inModOuter, inModInner); + s1 := PrefixUtil.printPrefixStrIgnoreNoPre(inPrefix); + s2 := Absyn.optPathString(FGraph.getScopePath(inEnv)); + s3 := printModStr(inModOuter); + s4 := printModStr(inModInner); + Error.addMessage(Error.FINAL_OVERRIDE, {s1, s2, s3, s4}); then fail(); end matchcontinue; end merge; -public function merge2 " -This function validates that the inner modifier is not final. -Helper function for merge" +public function merge2 + "This function validates that the inner modifier is not final. + Helper function for merge" input DAE.Mod inMod1; output Boolean outMod; algorithm - outMod:= matchcontinue (inMod1) - local - case (DAE.REDECL(tplSCodeElementModLst = - {(SCode.COMPONENT(prefixes=SCode.PREFIXES(finalPrefix=SCode.FINAL())),_)})) - then false; - case(DAE.MOD(finalPrefix = SCode.FINAL())) - then false; - else true; - end matchcontinue; + outMod:= match (inMod1) + case (DAE.REDECL(tplSCodeElementModLst = + {(SCode.COMPONENT(prefixes=SCode.PREFIXES(finalPrefix=SCode.FINAL())),_)})) + then false; + + case (DAE.MOD(finalPrefix = SCode.FINAL())) then false; + else true; + end match; end merge2; -// - Merging -protected function doMerge "This function merges two modifications into one. - The first argument is the *outer* modification that - should take precedence over the *inner* modification." - input DAE.Mod inModOuter "the outer mod which should overwrite the inner mod"; - input DAE.Mod inModInner "the inner mod"; - input FCore.Graph inEnv3; - input Prefix.Prefix inPrefix4; - output DAE.Mod outMod; +protected function doMerge + "Merges two DAE.Mod into one. The first argument is the outer modification + that should take precedence over the inner modification." + input DAE.Mod inModOuter "The outer mod which should overwrite the inner mod."; + input DAE.Mod inModInner "The inner mod."; + input FCore.Graph inEnv; + input Prefix.Prefix inPrefix; + output DAE.Mod outMod = inModOuter; algorithm - outMod := match (inModOuter,inModInner,inEnv3,inPrefix4) + outMod := match (outMod, inModInner) local - DAE.Mod m,m1_1,m2_1,m_2,mod,mods,mm1,mm2,mm3,mm4,cm,icm,emod1,emod2,emod; - SCode.Visibility vis; - SCode.Final finalPrefix,f,f1,f2; - SCode.Replaceable r; - SCode.Redeclare redecl; - Absyn.InnerOuter io; - String id1,id2; - SCode.Attributes attr1, attr2, attr; - Absyn.TypeSpec tp; - SCode.Mod m1,m2,sm,cm1,cm2; - SCode.Comment comment,comment2; - Option ann; - FCore.Graph env; - Prefix.Prefix pre; - list> els; - list subs,subs1,subs2; - Option ass,ass1,ass2; - SCode.Each each1,each2; - Option cond; - SourceInfo info, info1, info2; - SCode.Element celm,elementOne,el; - SCode.ClassDef cdef; - SCode.Encapsulated ep; - SCode.Partial pp; - SCode.Restriction res1, res2, res; - SCode.Prefixes pf1, pf2, pf; + SCode.Element el1, el2; + SCode.Mod smod1, smod2, smod; + DAE.Mod emod1, emod2, emod, dmod1, dmod2, dmod; + SCode.Restriction res; + SourceInfo info; + DAE.EqMod eqmod; + list vals; + Values.Value val; + list names; + String name; + list submods; + DAE.SubMod submod; - /* - case (inModOuter,inModInner,_,_) - equation - print("Merging: " + printModStr(inModOuter) + " with " + printModStr(inModInner) + "\n"); + // Redeclaring the same component. + case (DAE.REDECL(tplSCodeElementModLst = {(el1 as SCode.COMPONENT(), emod1)}), + DAE.REDECL(tplSCodeElementModLst = {(el2 as SCode.COMPONENT(), emod2)})) + algorithm + true := el1.name == el2.name; + smod1 := SCodeUtil.getConstrainedByModifiers(el1.prefixes); + smod1 := SCode.mergeModifiers(el1.modifications, smod1); + dmod1 := elabUntypedMod(smod1, inEnv, inPrefix, COMPONENT(el1.name)); + + smod2 := SCodeUtil.getConstrainedByModifiers(el2.prefixes); + smod2 := SCode.mergeModifiers(el2.modifications, smod2); + dmod2 := elabUntypedMod(smod2, inEnv, inPrefix, COMPONENT(el2.name)); + + dmod := merge(dmod1, dmod2, inEnv, inPrefix); + emod := merge(emod1, emod2, inEnv, inPrefix); + // If we have a constraining class we don't need the mod. + el1.modifications := unelabMod(dmod); + + el1.prefixes := SCode.propagatePrefixes(el2.prefixes, el1.prefixes); + el1.attributes := SCode.propagateAttributes(el2.attributes, el1.attributes); + outMod.tplSCodeElementModLst := {(el1, emod)}; then - fail();*/ + outMod; + + // Redeclaring the same class. + case (DAE.REDECL(tplSCodeElementModLst = {(el1 as SCode.CLASS(), emod1)}), + DAE.REDECL(tplSCodeElementModLst = {(el2 as SCode.CLASS(), emod2)})) + algorithm + true := el1.name == el2.name; + smod1 := SCodeUtil.getConstrainedByModifiers(el1.prefixes); + dmod1 := elabUntypedMod(smod1, inEnv, inPrefix, COMPONENT(el1.name)); + emod1 := merge(emod1, dmod1, inEnv, inPrefix); + + smod2 := SCodeUtil.getConstrainedByModifiers(el2.prefixes); + dmod2 := elabUntypedMod(smod2, inEnv, inPrefix, COMPONENT(el2.name)); + emod2 := merge(emod2, dmod2, inEnv, inPrefix); + + emod := merge(emod1, emod2, inEnv, inPrefix); + el1.prefixes := SCode.propagatePrefixes(el2.prefixes, el2.prefixes); + (res, info) := SCode.checkSameRestriction( + el1.restriction, el2.restriction, el1.info, el2.info); + el1.restriction := res; + el1.info := info; + + outMod.tplSCodeElementModLst := {(el1, emod)}; + then + outMod; + + case (DAE.REDECL(tplSCodeElementModLst = {(el1, emod)}), + DAE.MOD()) + algorithm + emod := merge(emod, inModInner, inEnv, inPrefix); + outMod.tplSCodeElementModLst := {(el1, emod)}; + then + outMod; + + case (DAE.MOD(), + DAE.REDECL(tplSCodeElementModLst = {(el2, emod)})) + algorithm + emod := merge(inModOuter, emod, inEnv, inPrefix); + then + DAE.REDECL(inModInner.finalPrefix, inModInner.eachPrefix, {(el2, emod)}); + + // The outer modifier has a record binding, while the inner consists of submodifiers. + case (DAE.MOD(eqModOption = SOME(eqmod as DAE.TYPED(modifierAsValue = + SOME(val as Values.RECORD()))), subModLst = {}), + DAE.MOD(eqModOption = NONE(), subModLst = submods as _ :: _)) + algorithm + names := val.comp; + vals := {}; + + for v in val.orderd loop + name :: names := names; + + // If the record component doesn't have a binding, use the value + // from the submodifier instead. + if ValuesUtil.isEmpty(v) then + try + (submods, SOME(submod)) := List.deleteMemberOnTrue(name, submods, isSubModNamed); + v := subModValue(submod); + else + end try; + end if; + + vals := v :: vals; + end for; + + val.orderd := listReverse(vals); + eqmod.modifierAsValue := SOME(val); + outMod.eqModOption := SOME(eqmod); + // Remove all submodifier bindings, they have been merged into the + // record binding. + outMod.subModLst := stripSubModBindings(inModInner.subModLst); + then + outMod; + + // The outer modifier consists of submodifiers, while the inner has a record binding. + case (DAE.MOD(eqModOption = NONE(), subModLst = submods as _ :: _), + DAE.MOD(eqModOption = SOME(eqmod as DAE.TYPED(modifierAsValue = + SOME(val as Values.RECORD()))), subModLst = {})) + algorithm + names := val.comp; + vals := {}; + + for v in val.orderd loop + name :: names := names; - case (m,DAE.NOMOD(),_,_) then m; - - // redeclaring same component - case (DAE.REDECL(finalPrefix = f1,eachPrefix = each1, tplSCodeElementModLst = - {(SCode.COMPONENT( - name = id1, - prefixes = pf1, - attributes = attr1, - typeSpec = tp, - modifications = m1, - comment=comment, - condition=cond, - info=info1), - emod1)}), - DAE.REDECL(tplSCodeElementModLst = - {(SCode.COMPONENT( - name = id2, - prefixes = pf2, - attributes = attr2), - emod2)}),env,pre) - equation - true = stringEq(id1, id2); - m1 = SCode.mergeModifiers(m1, SCodeUtil.getConstrainedByModifiers(pf1)); - m2 = SCode.mergeModifiers(m1, SCodeUtil.getConstrainedByModifiers(pf2)); - m1_1 = elabUntypedMod(m1, env, pre, COMPONENT(id1)); - m2_1 = elabUntypedMod(m2, env, pre, COMPONENT(id2)); - m_2 = merge(m1_1, m2_1, env, pre); - // if we have a constraint class we don't need the mod - sm = unelabMod(m_2); - emod = merge(emod1, emod2, env, pre); - pf = SCode.propagatePrefixes(pf2, pf1); - attr = SCode.propagateAttributes(attr2, attr1); - then - DAE.REDECL(f1,each1, - {(SCode.COMPONENT(id1, - pf, - attr, - tp, - sm, - comment,cond,info1),emod)}); - - // Redeclaring same class. - case (DAE.REDECL(finalPrefix = f1, eachPrefix = each1, tplSCodeElementModLst = - {(SCode.CLASS(name = id1, - prefixes = pf1, - restriction = res1, - classDef = cdef, - cmt = comment, - info = info1), - m1_1)}), - DAE.REDECL(tplSCodeElementModLst = - {(SCode.CLASS(name = id2, - prefixes = pf2, - restriction = res2, - encapsulatedPrefix = ep, - partialPrefix = pp, - info = info2), - m2_1)}), env, pre) - equation - true = stringEq(id1, id2); - m1_1 = merge(m1_1, elabUntypedMod(SCodeUtil.getConstrainedByModifiers(pf1), env, pre, COMPONENT(id1)), env, pre); - m2_1 = merge(m2_1, elabUntypedMod(SCodeUtil.getConstrainedByModifiers(pf2), env, pre, COMPONENT(id2)), env, pre); - m = merge(m1_1, m2_1, env, pre); - pf = SCode.propagatePrefixes(pf2, pf1); - (res, info) = SCode.checkSameRestriction(res1, res2, info1, info2); - then - DAE.REDECL(f1, each1, {(SCode.CLASS(id1, pf, ep, pp, res, cdef, comment, info), m)}); - - // luc_pop : this shoud return the first mod because it have been merged in merge_subs - case (DAE.REDECL(finalPrefix = f1,eachPrefix = each1, - tplSCodeElementModLst = {(celm as SCode.COMPONENT(),cm)}), - icm as DAE.MOD(),env,pre) - equation - cm = merge(cm,icm,env,pre); - then - DAE.REDECL(f1,each1,{(celm,cm)}); - - case ((icm as DAE.MOD()), - DAE.REDECL( - finalPrefix = f1, - eachPrefix = each1, - tplSCodeElementModLst = ({( (celm as SCode.COMPONENT()),cm)})),env,pre) - equation - cm = merge(icm,cm,env,pre); - then - DAE.REDECL(f1,each1,{(celm,cm)}); - - case (DAE.MOD(finalPrefix = finalPrefix,eachPrefix = each1,subModLst = subs1,eqModOption = ass1), - DAE.MOD(subModLst = subs2,eqModOption = ass2),env,pre) - equation - subs = mergeSubs(subs1, subs2, env, pre); - ass = mergeEq(ass1, ass2); - mm2 = DAE.MOD(finalPrefix,each1,subs,ass); - then - mm2; - - // Case when we have a modifier on a redeclared class - // This is of current date BZ:2008-03-04 not completly working. - // see testcase mofiles/Modification14.mo - case (mm1 as DAE.MOD(), - DAE.REDECL( - finalPrefix = finalPrefix,eachPrefix = each1, - tplSCodeElementModLst = ( {((elementOne as SCode.CLASS()),mm3)})), - env,pre) - equation - mm4 = merge(mm1,mm3,env,pre); - then - DAE.REDECL(finalPrefix,each1,{(elementOne,mm4)}); - - case (DAE.REDECL(finalPrefix = finalPrefix,eachPrefix = each1, tplSCodeElementModLst = ({((elementOne as SCode.CLASS()),mm3)})), - mm1 as DAE.MOD(),env,pre) - equation - mm4 = merge(mm3,mm1,env,pre); - then - DAE.REDECL(finalPrefix,each1,{(elementOne,mm4)}); + // For each component in the record, check if we have a submodifier + // for it. In that case, use the value from the submodifier instead. + try + (submods, SOME(submod)) := List.deleteMemberOnTrue(name, submods, isSubModNamed); + v := subModValue(submod); + else + end try; + + vals := v :: vals; + end for; + + val.orderd := listReverse(vals); + eqmod.modifierAsValue := SOME(val); + outMod.eqModOption := SOME(eqmod); + // Remove all submodifier bindings, they have been merged into the + // record binding. + outMod.subModLst := stripSubModBindings(outMod.subModLst); + then + outMod; + + case (DAE.MOD(), DAE.MOD()) + algorithm + outMod.subModLst := mergeSubs(outMod.subModLst, inModInner.subModLst, inEnv, inPrefix); + outMod.eqModOption := mergeEq(outMod.eqModOption, inModInner.eqModOption); + then + outMod; end match; end doMerge; @@ -3302,9 +3309,12 @@ algorithm outInfo := match(inMod) local SourceInfo info; + DAE.Mod mod; case DAE.MOD(eqModOption = SOME(DAE.TYPED(info = info))) then info; case DAE.MOD(eqModOption = SOME(DAE.UNTYPED(info = info))) then info; + case DAE.REDECL(tplSCodeElementModLst = (_, mod) :: _) then getModInfo(mod); + else Absyn.dummyInfo; end match; end getModInfo; @@ -3352,5 +3362,65 @@ algorithm end matchcontinue; end getClassModifier; +protected function subModValue + input DAE.SubMod inSubMod; + output Values.Value outValue; +algorithm + DAE.NAMEMOD(mod = DAE.MOD(eqModOption = SOME(DAE.TYPED(modifierAsValue = SOME(outValue))))) + := inSubMod; +end subModValue; + +protected function subModName + input DAE.SubMod inSubMod; + output DAE.Ident outName; +algorithm + DAE.NAMEMOD(ident = outName) := inSubMod; +end subModName; + +protected function subModInfo + input DAE.SubMod inSubMod; + output SourceInfo outInfo; +protected + DAE.Mod mod; +algorithm + DAE.NAMEMOD(mod = mod) := inSubMod; + outInfo := getModInfo(mod); +end subModInfo; + +protected function setEqMod + input Option inEqMod; + input DAE.Mod inMod; + output DAE.Mod outMod = inMod; +algorithm + outMod := match outMod + case DAE.MOD() + algorithm + outMod.eqModOption := inEqMod; + then + outMod; + + else outMod; + end match; +end setEqMod; + +protected function stripSubModBindings + input list inSubMods; + output list outSubMods = {}; +protected + DAE.Ident id; + DAE.Mod mod; +algorithm + for submod in inSubMods loop + DAE.NAMEMOD(id, mod) := submod; + mod := setEqMod(NONE(), mod); + + if not isEmptyMod(mod) then + outSubMods := DAE.NAMEMOD(id, mod) :: outSubMods; + end if; + end for; + + outSubMods := listReverse(outSubMods); +end stripSubModBindings; + annotation(__OpenModelica_Interface="frontend"); end Mod; diff --git a/Compiler/FrontEnd/ValuesUtil.mo b/Compiler/FrontEnd/ValuesUtil.mo index fe52de541b9..ba34ed6e94c 100644 --- a/Compiler/FrontEnd/ValuesUtil.mo +++ b/Compiler/FrontEnd/ValuesUtil.mo @@ -2574,5 +2574,46 @@ algorithm end for; end liftValueList; +public function isEmpty + input Values.Value inValue; + output Boolean outIsEmpty; +algorithm + outIsEmpty := match inValue + case Values.EMPTY() then true; + else false; + end match; +end isEmpty; + +public function typeConvertRecord + "Converts the component values of a record to the correct types." + input Values.Value inValue; + input DAE.Type inType; + output Values.Value outValue = inValue; +algorithm + outValue := match (outValue, inType) + local + DAE.Type ty; + + case (Values.RECORD(), DAE.T_COMPLEX()) + algorithm + outValue.orderd := list(typeConvertRecord(val, Types.getVarType(var)) + threaded for val in outValue.orderd, var in inType.varLst); + then + outValue; + + case (Values.INTEGER(), DAE.T_REAL()) + then Values.REAL(intReal(outValue.integer)); + + case (Values.ARRAY(), DAE.T_ARRAY()) + algorithm + ty := Expression.unliftArray(inType); + outValue.valueLst := list(typeConvertRecord(v, ty) for v in outValue.valueLst); + then + outValue; + + else outValue; + end match; +end typeConvertRecord; + annotation(__OpenModelica_Interface="frontend"); end ValuesUtil; diff --git a/Compiler/Util/Error.mo b/Compiler/Util/Error.mo index f66e3bfc256..cf0a59d99da 100644 --- a/Compiler/Util/Error.mo +++ b/Compiler/Util/Error.mo @@ -716,7 +716,7 @@ public constant Message DERIVATIVE_NON_REAL = MESSAGE(514, TRANSLATION(), ERROR( public constant Message UNUSED_MODIFIER = MESSAGE(515, TRANSLATION(), ERROR(), Util.gettext("In modifier %s.")); public constant Message MULTIPLE_MODIFIER = MESSAGE(516, TRANSLATION(), ERROR(), - Util.gettext("Multiple modifiers in same scope for element %s, %s.")); + Util.gettext("Multiple modifiers in same scope for element %s.")); public constant Message INCONSISTENT_UNITS = MESSAGE(517, TRANSLATION(), WARNING(), Util.gettext("The system of units is inconsistent in term %s with the units %s and %s respectively.")); public constant Message CONSISTENT_UNITS = MESSAGE(518, TRANSLATION(), NOTIFICATION(), From a6932e46ddd6e075aa15ac49186aa3518801ea68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BCdiger=20Franke?= Date: Mon, 19 Oct 2015 18:37:47 +0200 Subject: [PATCH 2/2] remove remaining use of boost::multi_array (#3522) --- .../cpp/Include/Core/Math/ArraySlice.h | 20 ++++++++++++------- SimulationRuntime/cpp/Include/Core/Modelica.h | 5 ----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/SimulationRuntime/cpp/Include/Core/Math/ArraySlice.h b/SimulationRuntime/cpp/Include/Core/Math/ArraySlice.h index 884881cfce4..c4bbd0236b5 100644 --- a/SimulationRuntime/cpp/Include/Core/Math/ArraySlice.h +++ b/SimulationRuntime/cpp/Include/Core/Math/ArraySlice.h @@ -101,7 +101,8 @@ class ArraySliceConst: public BaseArray { , _baseArray(baseArray) , _isets(slice.size()) , _idxs(slice.size()) - , _baseIdx(slice.size()) { + , _baseIdx(slice.size()) + , _tmp_data(NULL) { if (baseArray.getNumDims() != slice.size()) throw ModelicaSimulationError(MODEL_ARRAY_FUNCTION, @@ -136,6 +137,11 @@ class ArraySliceConst: public BaseArray { } } + virtual ~ArraySliceConst() { + if (_tmp_data != NULL) + delete [] _tmp_data; + } + virtual const T& operator()(const vector &idx) const { return _baseArray(baseIdx(idx.size(), &idx[0])); } @@ -176,11 +182,11 @@ class ArraySliceConst: public BaseArray { } virtual const T* getData() const { - if (_tmp_data.num_elements() == 0) + if (_tmp_data == NULL) // allocate on first use - _tmp_data.resize(boost::extents[getNumElems()]); - getDataDim(_idxs.size(), _tmp_data.data()); - return _tmp_data.data(); + _tmp_data = new T [getNumElems()]; + getDataDim(_idxs.size(), _tmp_data); + return _tmp_data; } virtual size_t getNumElems() const { @@ -217,7 +223,7 @@ class ArraySliceConst: public BaseArray { vector< vector > _idxs; // created index sets per dimension vector _dims; // dimensions of array slice mutable vector _baseIdx; // idx into underlying array - mutable boost::multi_array _tmp_data; // storage for const T* getData() + mutable T *_tmp_data; // storage for const T* getData() /** * returns idx vector to access an element @@ -347,4 +353,4 @@ class ArraySlice: public ArraySliceConst { return processed; } }; -/** @} */ // end of math \ No newline at end of file +/** @} */ // end of math diff --git a/SimulationRuntime/cpp/Include/Core/Modelica.h b/SimulationRuntime/cpp/Include/Core/Modelica.h index f1419190bb3..a11492a3721 100644 --- a/SimulationRuntime/cpp/Include/Core/Modelica.h +++ b/SimulationRuntime/cpp/Include/Core/Modelica.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -48,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -75,10 +73,7 @@ using std::map; using std::pair; using std::make_pair; using namespace boost::assign; -using boost::multi_array; using namespace boost::algorithm; -using boost::const_multi_array_ref; -using boost::multi_array_ref; using boost::unordered_map; using boost::lexical_cast; using boost::numeric_cast;