diff --git a/Compiler/NFFrontEnd/NFBinding.mo b/Compiler/NFFrontEnd/NFBinding.mo index cae6af768c..59a4568789 100644 --- a/Compiler/NFFrontEnd/NFBinding.mo +++ b/Compiler/NFFrontEnd/NFBinding.mo @@ -36,35 +36,35 @@ public import SCode; import Type = NFType; import NFPrefixes.Variability; + import BindingOrigin = NFBindingOrigin; protected import Dump; import Binding = NFBinding; public + type Origin = enumeration(COMPONENT, EXTENDS, CLASS); + record UNBOUND end UNBOUND; record RAW_BINDING Absyn.Exp bindingExp; InstNode scope; - Integer originLevel; - SourceInfo info; + BindingOrigin origin; end RAW_BINDING; record UNTYPED_BINDING Expression bindingExp; Boolean isProcessing; InstNode scope; - Integer originLevel; - SourceInfo info; + BindingOrigin origin; end UNTYPED_BINDING; record TYPED_BINDING Expression bindingExp; Type bindingType; Variability variability; - Integer originLevel; - SourceInfo info; + BindingOrigin origin; end TYPED_BINDING; record FLAT_BINDING @@ -78,6 +78,7 @@ public input Integer level; input InstNode scope; input SourceInfo info; + input BindingOrigin.ElementType ty = NFBindingOrigin.ElementType.COMPONENT; output Binding binding; algorithm binding := match bindingExp @@ -85,7 +86,7 @@ public Absyn.Exp exp; case SOME(exp) - then RAW_BINDING(exp, scope, if eachPrefix then -level else level, info); + then RAW_BINDING(exp, scope, BindingOrigin.create(eachPrefix, level, ty, info)); else UNBOUND(); end match; @@ -168,12 +169,23 @@ public algorithm info := match binding case UNBOUND() then Absyn.dummyInfo; - case RAW_BINDING() then binding.info; - case UNTYPED_BINDING() then binding.info; - case TYPED_BINDING() then binding.info; + case RAW_BINDING() then binding.origin.info; + case UNTYPED_BINDING() then binding.origin.info; + case TYPED_BINDING() then binding.origin.info; end match; end getInfo; + function getOrigin + input Binding binding; + output BindingOrigin origin; + algorithm + origin := match binding + case RAW_BINDING() then binding.origin; + case UNTYPED_BINDING() then binding.origin; + case TYPED_BINDING() then binding.origin; + end match; + end getOrigin; + function getType input Binding binding; output Type ty; @@ -186,9 +198,9 @@ public output Boolean isEach; algorithm isEach := match binding - case RAW_BINDING() then binding.originLevel < 0; - case UNTYPED_BINDING() then binding.originLevel < 0; - case TYPED_BINDING() then binding.originLevel < 0; + case RAW_BINDING() then BindingOrigin.isEach(binding.origin); + case UNTYPED_BINDING() then BindingOrigin.isEach(binding.origin); + case TYPED_BINDING() then BindingOrigin.isEach(binding.origin); else false; end match; end isEach; diff --git a/Compiler/NFFrontEnd/NFBindingOrigin.mo b/Compiler/NFFrontEnd/NFBindingOrigin.mo new file mode 100644 index 0000000000..13903f5e87 --- /dev/null +++ b/Compiler/NFFrontEnd/NFBindingOrigin.mo @@ -0,0 +1,82 @@ +/* + * This file is part of OpenModelica. + * + * Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC), + * c/o Linköpings universitet, Department of Computer and Information Science, + * SE-58183 Linköping, Sweden. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR + * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, + * ACCORDING TO RECIPIENTS CHOICE. + * + * The OpenModelica software and the Open Source Modelica + * Consortium (OSMC) Public License (OSMC-PL) are obtained + * from OSMC, either from the above address, + * from the URLs: http://www.ida.liu.se/projects/OpenModelica or + * http://www.openmodelica.org, and in the OpenModelica distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH + * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. + * + * See the full OSMC Public License conditions for more details. + * + */ + +encapsulated uniontype NFBindingOrigin + import NFModifier.ModifierScope; + +protected + import BindingOrigin = NFBindingOrigin; + +public + type ElementType = enumeration(COMPONENT, EXTENDS, CLASS); + + record ORIGIN + Integer level; + ElementType ty; + SourceInfo info; + end ORIGIN; + + function create + input Boolean eachPrefix; + input Integer level; + input ElementType ty; + input SourceInfo info; + output BindingOrigin origin; + algorithm + origin := ORIGIN(if eachPrefix then -level else level, ty, info); + end create; + + function level + input BindingOrigin origin; + output Integer level = origin.level; + end level; + + function isEach + input BindingOrigin origin; + output Boolean isEach = origin.level < 0; + end isEach; + + function info + input BindingOrigin origin; + output SourceInfo info = origin.info; + end info; + + function isFromClass + input BindingOrigin origin; + output Boolean fromClass; + protected + ElementType ty = origin.ty; + algorithm + fromClass := ty == ElementType.CLASS; + end isFromClass; + + annotation(__OpenModelica_Interface="frontend"); +end NFBindingOrigin; diff --git a/Compiler/NFFrontEnd/NFBuiltin.mo b/Compiler/NFFrontEnd/NFBuiltin.mo index 7b812075ba..025d42735f 100644 --- a/Compiler/NFFrontEnd/NFBuiltin.mo +++ b/Compiler/NFFrontEnd/NFBuiltin.mo @@ -44,6 +44,7 @@ public import Absyn; import SCode; import Binding = NFBinding; +import BindingOrigin = NFBindingOrigin; import NFClass.Class; import NFClassTree; import NFComponent.Component; @@ -196,40 +197,35 @@ constant Binding STATESELECT_NEVER_BINDING = Expression.ENUM_LITERAL(STATESELECT_TYPE, "never", 1), STATESELECT_TYPE, Variability.CONSTANT, - -1, - Absyn.dummyInfo); + BindingOrigin.ORIGIN(-1, NFBindingOrigin.ElementType.CLASS, Absyn.dummyInfo)); constant Binding STATESELECT_AVOID_BINDING = Binding.TYPED_BINDING( Expression.ENUM_LITERAL(STATESELECT_TYPE, "avoid", 2), STATESELECT_TYPE, Variability.CONSTANT, - -1, - Absyn.dummyInfo); + BindingOrigin.ORIGIN(-1, NFBindingOrigin.ElementType.CLASS, Absyn.dummyInfo)); constant Binding STATESELECT_DEFAULT_BINDING = Binding.TYPED_BINDING( Expression.ENUM_LITERAL(STATESELECT_TYPE, "default", 3), STATESELECT_TYPE, Variability, - -1, - Absyn.dummyInfo); + BindingOrigin.ORIGIN(-1, NFBindingOrigin.ElementType.CLASS, Absyn.dummyInfo)); constant Binding STATESELECT_PREFER_BINDING = Binding.TYPED_BINDING( Expression.ENUM_LITERAL(STATESELECT_TYPE, "prefer", 4), STATESELECT_TYPE, Variability.CONSTANT, - -1, - Absyn.dummyInfo); + BindingOrigin.ORIGIN(-1, NFBindingOrigin.ElementType.CLASS, Absyn.dummyInfo)); constant Binding STATESELECT_ALWAYS_BINDING = Binding.TYPED_BINDING( Expression.ENUM_LITERAL(STATESELECT_TYPE, "always", 5), STATESELECT_TYPE, Variability.CONSTANT, - -1, - Absyn.dummyInfo); + BindingOrigin.ORIGIN(-1, NFBindingOrigin.ElementType.CLASS, Absyn.dummyInfo)); constant InstNode STATESELECT_NEVER = InstNode.COMPONENT_NODE("never", diff --git a/Compiler/NFFrontEnd/NFCeval.mo b/Compiler/NFFrontEnd/NFCeval.mo index d5e437506c..b8c14a974a 100644 --- a/Compiler/NFFrontEnd/NFCeval.mo +++ b/Compiler/NFFrontEnd/NFCeval.mo @@ -59,8 +59,7 @@ uniontype EvalTarget end DIMENSION; record ATTRIBUTE - Expression exp; - SourceInfo info; + Binding binding; end ATTRIBUTE; record RANGE @@ -102,7 +101,7 @@ uniontype EvalTarget algorithm info := match target case DIMENSION() then target.info; - case ATTRIBUTE() then target.info; + case ATTRIBUTE() then Binding.getInfo(target.binding); case RANGE() then target.info; case CONDITION() then target.info; end match; diff --git a/Compiler/NFFrontEnd/NFExpressionIterator.mo b/Compiler/NFFrontEnd/NFExpressionIterator.mo index c236502980..6ea8b54d0c 100644 --- a/Compiler/NFFrontEnd/NFExpressionIterator.mo +++ b/Compiler/NFFrontEnd/NFExpressionIterator.mo @@ -33,6 +33,7 @@ encapsulated uniontype NFExpressionIterator protected import ExpressionIterator = NFExpressionIterator; import ComponentRef = NFComponentRef; + import BindingOrigin = NFBindingOrigin; public import Expression = NFExpression; @@ -103,8 +104,8 @@ public algorithm iterator := match binding case Binding.TYPED_BINDING() - then if binding.originLevel > 0 then - fromExp(binding.bindingExp) else EACH_ITERATOR(binding.bindingExp); + then if BindingOrigin.isEach(binding.origin) or BindingOrigin.isFromClass(binding.origin) then + EACH_ITERATOR(binding.bindingExp) else fromExp(binding.bindingExp); case Binding.FLAT_BINDING() then SCALAR_ITERATOR(binding.bindingExp); diff --git a/Compiler/NFFrontEnd/NFFlatten.mo b/Compiler/NFFrontEnd/NFFlatten.mo index b86a056b58..d9ca914ff5 100644 --- a/Compiler/NFFrontEnd/NFFlatten.mo +++ b/Compiler/NFFrontEnd/NFFlatten.mo @@ -77,6 +77,7 @@ import ComplexType = NFComplexType; import NFInstNode.CachedData; import NFPrefixes.Variability; import Variable = NFVariable; +import BindingOrigin = NFBindingOrigin; public type FunctionTree = FunctionTreeImpl.Tree; @@ -335,13 +336,16 @@ algorithm () := match binding local list subs; + Integer binding_level; case Binding.UNBOUND() then (); case Binding.TYPED_BINDING() algorithm - if binding.originLevel > 0 then - subs := List.flatten(ComponentRef.subscriptsN(prefix, InstNode.level(component) - binding.originLevel)); + binding_level := BindingOrigin.level(binding.origin); + + if binding_level > 0 then + subs := List.flatten(ComponentRef.subscriptsN(prefix, InstNode.level(component) - binding_level)); binding.bindingExp := Expression.subscript(binding.bindingExp, subs); end if; then diff --git a/Compiler/NFFrontEnd/NFInst.mo b/Compiler/NFFrontEnd/NFInst.mo index 9ee0543f39..73bf324ef7 100644 --- a/Compiler/NFFrontEnd/NFInst.mo +++ b/Compiler/NFFrontEnd/NFInst.mo @@ -92,6 +92,7 @@ import ComplexType = NFComplexType; import Package = NFPackage; import NFFunction.Function; import FlatModel = NFFlatModel; +import BindingOrigin = NFBindingOrigin; type EquationScope = enumeration(NORMAL, INITIAL, WHEN); @@ -1464,9 +1465,9 @@ algorithm case Binding.RAW_BINDING() algorithm - bind_exp := instExp(binding.bindingExp, binding.scope, binding.info); + bind_exp := instExp(binding.bindingExp, binding.scope, BindingOrigin.info(binding.origin)); then - Binding.UNTYPED_BINDING(bind_exp, false, binding.scope, binding.originLevel, binding.info); + Binding.UNTYPED_BINDING(bind_exp, false, binding.scope, binding.origin); else binding; end match; diff --git a/Compiler/NFFrontEnd/NFModifier.mo b/Compiler/NFFrontEnd/NFModifier.mo index 674a490fa0..890b780c33 100644 --- a/Compiler/NFFrontEnd/NFModifier.mo +++ b/Compiler/NFFrontEnd/NFModifier.mo @@ -116,15 +116,17 @@ uniontype ModifierScope end match; end toString; - function isClass + function toElementType input ModifierScope scope; - output Boolean isClass; + output ElementType origin; + import NFBindingOrigin.ElementType; algorithm - isClass := match scope - case CLASS() then true; - else false; + origin := match scope + case COMPONENT() then ElementType.COMPONENT; + case CLASS() then ElementType.CLASS; + case EXTENDS() then ElementType.EXTENDS; end match; - end isClass; + end toElementType; end ModifierScope; uniontype Modifier @@ -169,8 +171,9 @@ public case SCode.MOD() algorithm - is_each := SCode.eachBool(mod.eachPrefix) or ModifierScope.isClass(modScope); - binding := Binding.fromAbsyn(mod.binding, is_each, level, scope, mod.info); + is_each := SCode.eachBool(mod.eachPrefix); + binding := Binding.fromAbsyn(mod.binding, is_each, level, + scope, mod.info, ModifierScope.toElementType(modScope)); lvl := if is_each then level + 1 else level; submod_lst := list((m.ident, createSubMod(m, modScope, lvl, scope)) for m in mod.subModLst); submod_table := ModTable.fromList(submod_lst, diff --git a/Compiler/NFFrontEnd/NFTypeCheck.mo b/Compiler/NFFrontEnd/NFTypeCheck.mo index af73315b5b..4bb0c58f84 100644 --- a/Compiler/NFFrontEnd/NFTypeCheck.mo +++ b/Compiler/NFFrontEnd/NFTypeCheck.mo @@ -61,6 +61,7 @@ import DAEUtil; import Prefixes = NFPrefixes; import Restriction = NFRestriction; import ComplexType = NFComplexType; +import BindingOrigin = NFBindingOrigin; public type MatchKind = enumeration( @@ -2426,15 +2427,17 @@ algorithm Type ty, comp_ty; InstNode parent; list dims; + Integer binding_level; case Binding.TYPED_BINDING() algorithm comp_ty := componentType; + binding_level := BindingOrigin.level(binding.origin); - if binding.originLevel >= 0 then + if binding_level >= 0 then parent := component; - for i in 1:InstNode.level(component) - binding.originLevel loop + for i in 1:InstNode.level(component) - binding_level loop parent := InstNode.parent(component); dims := Type.arrayDims(InstNode.getType(parent)); comp_ty := Type.liftArrayLeftList(comp_ty, dims); @@ -2446,10 +2449,10 @@ algorithm if not isCompatibleMatch(ty_match) then Error.addSourceMessage(Error.VARIABLE_BINDING_TYPE_MISMATCH, {name, Binding.toString(binding), Type.toString(comp_ty), - Type.toString(binding.bindingType)}, binding.info); + Type.toString(binding.bindingType)}, Binding.getInfo(binding)); fail(); elseif isCastMatch(ty_match) then - binding := Binding.TYPED_BINDING(exp, ty, binding.variability, binding.originLevel, binding.info); + binding := Binding.TYPED_BINDING(exp, ty, binding.variability, binding.origin); end if; then (); diff --git a/Compiler/NFFrontEnd/NFTyping.mo b/Compiler/NFFrontEnd/NFTyping.mo index e2cd73a1e0..5659557409 100644 --- a/Compiler/NFFrontEnd/NFTyping.mo +++ b/Compiler/NFFrontEnd/NFTyping.mo @@ -83,6 +83,7 @@ import Package = NFPackage; import NFFunction.Function; import NFInstNode.CachedData; import Direction = NFPrefixes.Direction; +import BindingOrigin = NFBindingOrigin; uniontype TypingError record NO_ERROR end NO_ERROR; @@ -499,7 +500,7 @@ algorithm case Binding.UNTYPED_BINDING() algorithm prop_dims := InstNode.countDimensions(InstNode.parent(component), - InstNode.level(component) - binding.originLevel); + InstNode.level(component) - BindingOrigin.level(binding.origin)); dim := typeExpDim(binding.bindingExp, index + prop_dims, intBitOr(origin, ExpOrigin.DIMENSION), info); then @@ -509,7 +510,7 @@ algorithm case Binding.TYPED_BINDING() algorithm prop_dims := InstNode.countDimensions(InstNode.parent(component), - InstNode.level(component) - binding.originLevel); + InstNode.level(component) - BindingOrigin.level(binding.origin)); dim := nthDimensionBoundsChecked(binding.bindingType, index + prop_dims); then dim; @@ -653,12 +654,14 @@ algorithm Expression exp; Type ty; Variability var; + SourceInfo info; case Binding.UNTYPED_BINDING(bindingExp = exp) algorithm - (exp, ty, var) := typeExp(exp, origin, binding.info); + info := Binding.getInfo(binding); + (exp, ty, var) := typeExp(exp, origin, info); then - Binding.TYPED_BINDING(exp, ty, var, binding.originLevel, binding.info); + Binding.TYPED_BINDING(exp, ty, var, binding.origin); case Binding.TYPED_BINDING() then binding; case Binding.UNBOUND() then binding; @@ -684,8 +687,9 @@ algorithm SourceInfo info; MatchKind mk; - case Binding.UNTYPED_BINDING(bindingExp = exp, info = info) + case Binding.UNTYPED_BINDING(bindingExp = exp) algorithm + info := Binding.getInfo(condition); (exp, ty, var) := typeExp(exp, intBitOr(origin, ExpOrigin.CONDITION), info); (exp, _, mk) := TypeCheck.matchTypes(ty, Type.BOOLEAN(), exp); @@ -752,8 +756,8 @@ function typeTypeAttribute protected String name; Binding binding; + BindingOrigin binding_origin; Type expected_ty, comp_ty; - list dims; algorithm () := match attribute // Normal modifier with no submodifiers. @@ -761,11 +765,13 @@ algorithm algorithm // Use the given function to get the expected type of the attribute. expected_ty := attrTyFn(name, ty, Modifier.info(attribute)); + binding_origin := Binding.getOrigin(binding); // Add the component's dimensions to the expected type, unless the // binding is declared 'each'. - if not Binding.isEach(binding) then + if not (BindingOrigin.isEach(binding_origin) or BindingOrigin.isFromClass(binding_origin)) then comp_ty := InstNode.getType(component); + if Type.isArray(comp_ty) then expected_ty := Type.ARRAY(expected_ty, Type.arrayDims(comp_ty)); end if; @@ -780,7 +786,7 @@ algorithm Error.addSourceMessage(Error.HIGHER_VARIABILITY_BINDING, {name, Prefixes.variabilityString(Variability.PARAMETER), "'" + Binding.toString(binding) + "'", Prefixes.variabilityString(Binding.variability(binding))}, - Binding.getInfo(binding)); + BindingOrigin.info(binding_origin)); fail(); end if; @@ -818,10 +824,10 @@ algorithm case Binding.TYPED_BINDING() algorithm - exp := Ceval.evalExp(binding.bindingExp, Ceval.EvalTarget.ATTRIBUTE(binding.bindingExp, binding.info)); + exp := Ceval.evalExp(binding.bindingExp, Ceval.EvalTarget.ATTRIBUTE(binding)); exp := SimplifyExp.simplifyExp(exp); then - Binding.TYPED_BINDING(exp, binding.bindingType, binding.variability, binding.originLevel, binding.info); + Binding.TYPED_BINDING(exp, binding.bindingType, binding.variability, binding.origin); else algorithm diff --git a/Compiler/boot/LoadCompilerSources.mos b/Compiler/boot/LoadCompilerSources.mos index c7c92564e2..eac60e7198 100644 --- a/Compiler/boot/LoadCompilerSources.mos +++ b/Compiler/boot/LoadCompilerSources.mos @@ -89,6 +89,7 @@ if true then /* Suppress output */ // "NFFrontEnd"; "../NFFrontEnd/NFBinding.mo", + "../NFFrontEnd/NFBindingOrigin.mo", "../NFFrontEnd/NFBuiltin.mo", "../NFFrontEnd/NFBuiltinFuncs.mo", "../NFFrontEnd/NFCall.mo",