From e293f5ae65e65fc915c09e9c1c133b823c9cbf16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=96stlund?= Date: Wed, 27 May 2020 19:08:39 +0200 Subject: [PATCH] [NF] Flat Modelica improvements. - Simplify away subscripts when devectorizing calls if possible. - Recheck whether a subscript is a slice or not after modifying the contained expression via e.g. Subscript.map. - Only dump 'input' prefix for top-level components. - Dump type attributes for components in e.g. functions. - Dump 'public' for public elements, otherwise everything will be private after the first private element. - Fix dumping of array dimensions which was using normal toString. - Change more dump functions to use IOStream. --- OMCompiler/Compiler/NFFrontEnd/NFCall.mo | 6 +- OMCompiler/Compiler/NFFrontEnd/NFComponent.mo | 108 +++++++++++++++--- .../Compiler/NFFrontEnd/NFComponentRef.mo | 2 +- OMCompiler/Compiler/NFFrontEnd/NFDimension.mo | 45 ++++++++ .../Compiler/NFFrontEnd/NFEvalFunction.mo | 2 +- OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo | 2 + OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo | 1 + OMCompiler/Compiler/NFFrontEnd/NFModifier.mo | 65 +++++++++-- .../Compiler/NFFrontEnd/NFSimplifyExp.mo | 3 +- OMCompiler/Compiler/NFFrontEnd/NFSubscript.mo | 76 ++++++++++-- OMCompiler/Compiler/NFFrontEnd/NFType.mo | 10 +- OMCompiler/Compiler/NFFrontEnd/NFVariable.mo | 33 +----- 12 files changed, 278 insertions(+), 75 deletions(-) diff --git a/OMCompiler/Compiler/NFFrontEnd/NFCall.mo b/OMCompiler/Compiler/NFFrontEnd/NFCall.mo index 72c3411e7fc..e1e6af8c7d5 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFCall.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFCall.mo @@ -42,8 +42,10 @@ import Type = NFType; import Record = NFRecord; protected +import Binding = NFBinding; import BuiltinCall = NFBuiltinCall; import Ceval = NFCeval; +import Component = NFComponent; import ComponentRef = NFComponentRef; import Config; import Dimension = NFDimension; @@ -54,9 +56,7 @@ import Inst = NFInst; import List; import Lookup = NFLookup; import MetaModelica.Dangerous.listReverseInPlace; -import Binding = NFBinding; import Class = NFClass; -import Component = NFComponent; import NFFunction.Function; import NFFunction.FunctionMatchKind; import NFFunction.MatchedFunction; @@ -68,6 +68,7 @@ import NFTyping.ExpOrigin; import Operator = NFOperator; import Prefixes = NFPrefixes; import SCodeUtil; +import SimplifyExp = NFSimplifyExp; import Subscript = NFSubscript; import TypeCheck = NFTypeCheck; import Typing = NFTyping; @@ -1427,6 +1428,7 @@ protected exp := Expression.replaceIterator(exp, iter_node, iter_exp); end for; + exp := SimplifyExp.simplify(exp); Expression.CALL(call = outCall) := exp; end devectorizeCall; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo b/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo index 7018b6b5b1d..5e9572980e0 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo @@ -50,6 +50,7 @@ import Prefixes = NFPrefixes; import SCodeUtil; import Restriction = NFRestriction; import Component = NFComponent; +import IOStream; public constant Attributes DEFAULT_ATTR = @@ -155,14 +156,22 @@ public Prefixes.unparseDirection(attr.direction); end toString; - function toFlatString + function toFlatStream input Attributes attr; input Type ty; - output String str; + input output IOStream.IOStream s; + input Boolean isTopLevel = true; algorithm - str := Prefixes.unparseVariability(attr.variability, ty) + - Prefixes.unparseDirection(attr.direction); - end toFlatString; + if attr.isFinal then + s := IOStream.append(s, "final "); + end if; + + s := IOStream.append(s, Prefixes.unparseVariability(attr.variability, ty)); + + if isTopLevel then + s := IOStream.append(s, Prefixes.unparseDirection(attr.direction)); + end if; + end toFlatStream; end Attributes; record COMPONENT_DEF @@ -851,23 +860,92 @@ public end match; end toString; - function toFlatString + function toFlatStream input String name; input Component component; - output String str; + input output IOStream.IOStream s; + protected + list> ty_attrs; algorithm - str := match component - local - SCode.Element def; - + () := match component case TYPED_COMPONENT() - then Attributes.toFlatString(component.attributes, component.ty) + - Type.toFlatString(component.ty) + " '" + name + "'" + - Binding.toFlatString(component.binding, " = "); + algorithm + s := Attributes.toFlatStream(component.attributes, component.ty, s); + s := IOStream.append(s, Type.toFlatString(component.ty)); + s := IOStream.append(s, " '"); + s := IOStream.append(s, name); + s := IOStream.append(s, "'"); + + ty_attrs := list((Modifier.name(a), Modifier.binding(a)) for a in + Class.getTypeAttributes(InstNode.getClass(component.classInst))); + s := typeAttrsToFlatStream(ty_attrs, component.ty, s); + + s := IOStream.append(s, Binding.toFlatString(component.binding, " = ")); + then + (); case TYPE_ATTRIBUTE() - then name + Modifier.toFlatString(component.modifier, printName = false); + algorithm + s := IOStream.append(s, name); + s := IOStream.append(s, Modifier.toFlatString(component.modifier, printName = false)); + then + (); end match; + end toFlatStream; + + function typeAttrsToFlatStream + input list> typeAttrs; + input Type componentType; + input output IOStream.IOStream s; + protected + Integer var_dims, binding_dims; + list> ty_attrs = typeAttrs; + String name; + Binding binding; + Expression bind_exp; + algorithm + if listEmpty(ty_attrs) then + return; + end if; + + s := IOStream.append(s, "("); + var_dims := Type.dimensionCount(componentType); + + while true loop + (name, binding) := listHead(ty_attrs); + bind_exp := Expression.getBindingExp(Binding.getExp(binding)); + binding_dims := Type.dimensionCount(Expression.typeOf(bind_exp)); + + if var_dims > binding_dims then + s := IOStream.append(s, "each "); + end if; + + s := IOStream.append(s, name); + s := IOStream.append(s, " = "); + s := IOStream.append(s, Binding.toFlatString(binding)); + + ty_attrs := listRest(ty_attrs); + if listEmpty(ty_attrs) then + break; + else + s := IOStream.append(s, ", "); + end if; + end while; + + s := IOStream.append(s, ")"); + end typeAttrsToFlatStream; + + function toFlatString + input String name; + input Component component; + output String str; + protected + IOStream.IOStream s; + algorithm + s := IOStream.create(name, IOStream.IOStreamType.LIST()); + s := toFlatStream(name, component, s); + str := IOStream.string(s); + IOStream.delete(s); end toFlatString; function setDimensions diff --git a/OMCompiler/Compiler/NFFrontEnd/NFComponentRef.mo b/OMCompiler/Compiler/NFFrontEnd/NFComponentRef.mo index f67928c0138..e161dc13a23 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFComponentRef.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFComponentRef.mo @@ -857,7 +857,7 @@ public case CREF(origin = Origin.CREF) algorithm - subs := list(Subscript.simplify(s) for s in cref.subscripts); + subs := Subscript.simplifyList(cref.subscripts, Type.arrayDims(cref.ty)); then CREF(cref.node, subs, cref.ty, cref.origin, simplifySubscripts(cref.restCref)); diff --git a/OMCompiler/Compiler/NFFrontEnd/NFDimension.mo b/OMCompiler/Compiler/NFFrontEnd/NFDimension.mo index f278db91347..6025452d7c1 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFDimension.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFDimension.mo @@ -286,6 +286,20 @@ public end if; end toStringList; + function toFlatString + input Dimension dim; + output String str; + algorithm + str := match dim + case INTEGER() then String(dim.size); + case BOOLEAN() then "Boolean"; + case ENUM() then Type.toFlatString(dim.enumType); + case EXP() then Expression.toFlatString(dim.exp); + case UNKNOWN() then ":"; + case UNTYPED() then Expression.toFlatString(dim.dimension); + end match; + end toFlatString; + function endExp "Returns an expression for the last index in a dimension." input Dimension dim; @@ -325,6 +339,37 @@ public end match; end sizeExp; + function expIsLowerBound + "Returns true if the expression represents the lower bound of a dimension." + input Expression exp; + output Boolean isStart; + algorithm + isStart := match exp + case Expression.INTEGER() then exp.value == 1; + case Expression.BOOLEAN() then exp.value == false; + case Expression.ENUM_LITERAL() then exp.index == 1; + else false; + end match; + end expIsLowerBound; + + function expIsUpperBound + "Returns true if the expression represents the upper bound of the given dimension." + input Expression exp; + input Dimension dim; + output Boolean isEnd; + algorithm + isEnd := match (exp, dim) + local + Type ty; + + case (Expression.INTEGER(), INTEGER()) then exp.value == dim.size; + case (Expression.BOOLEAN(), _) then exp.value == true; + case (Expression.ENUM_LITERAL(), ENUM(enumType = ty as Type.ENUMERATION())) + then exp.index == listLength(ty.literals); + else false; + end match; + end expIsUpperBound; + function variability input Dimension dim; output Variability var; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFEvalFunction.mo b/OMCompiler/Compiler/NFFrontEnd/NFEvalFunction.mo index afcb94ed0c7..a3294999f49 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFEvalFunction.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFEvalFunction.mo @@ -495,7 +495,7 @@ algorithm case Statement.FOR() algorithm // Make a mutable expression with a placeholder value. - iter_exp := Expression.makeMutable(Expression.EMPTY(Type.UNKNOWN())); + iter_exp := Expression.makeMutable(Expression.EMPTY(InstNode.getType(stmt.iterator))); // Replace the iterator with the expression in the body of the for loop. stmt.body := list( Statement.mapExp(s, function Expression.replaceIterator( diff --git a/OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo b/OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo index ecbf9a520ca..d639153a6bc 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFFlatModel.mo @@ -201,6 +201,8 @@ public s := IOStream.append(s, ";\n"); end for; + s := IOStream.append(s, "public\n"); + if not listEmpty(flat_model.initialEquations) then s := IOStream.append(s, "initial equation\n"); s := Equation.toFlatStreamList(flat_model.initialEquations, " ", s); diff --git a/OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo b/OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo index d872ca76244..f3ff03f1238 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo @@ -1366,6 +1366,7 @@ uniontype InstNode input output IOStream.IOStream s; algorithm s := match node + case COMPONENT_NODE() then Component.toFlatStream(node.name, Pointer.access(node.component), s); case CLASS_NODE() then Class.toFlatStream(Pointer.access(node.cls), node, s); else IOStream.append(s, toFlatString(node)); end match; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFModifier.mo b/OMCompiler/Compiler/NFFrontEnd/NFModifier.mo index d3edd1ea910..1b7778a23db 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFModifier.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFModifier.mo @@ -52,6 +52,7 @@ protected import Error; import List; import SCodeUtil; +import IOStream; constant Modifier EMPTY_MOD = NOMOD(); @@ -540,33 +541,73 @@ public end match; end toString; - function toFlatString + function toFlatStreamList + input list modifiers; + input output IOStream.IOStream s; + input String delimiter = ", "; + protected + list mods = modifiers; + algorithm + if listEmpty(mods) then + return; + end if; + + while true loop + s := toFlatStream(listHead(mods), s); + mods := listRest(mods); + + if listEmpty(mods) then + break; + else + s := IOStream.append(s, delimiter); + end if; + end while; + end toFlatStreamList; + + function toFlatStream input Modifier mod; + input output IOStream.IOStream s; input Boolean printName = true; - output String string; + protected + list submods; + String subs_str, binding_str, binding_sep; algorithm - string := match mod - local - list submods; - String subs_str, binding_str, binding_sep; - + () := match mod case MODIFIER() algorithm + if printName then + s := IOStream.append(s, mod.name); + end if; + submods := ModTable.listValues(mod.subModifiers); if not listEmpty(submods) then - subs_str := "(" + stringDelimitList(list(toFlatString(s) for s in submods), ", ") + ")"; + s := IOStream.append(s, "("); + s := toFlatStreamList(submods, s); + s := IOStream.append(s, ")"); binding_sep := " = "; else - subs_str := ""; binding_sep := if printName then " = " else "= "; end if; - binding_str := Binding.toFlatString(mod.binding, binding_sep); + s := IOStream.append(s, Binding.toFlatString(mod.binding, binding_sep)); then - if printName then mod.name + subs_str + binding_str else subs_str + binding_str; + (); - else ""; + else (); end match; + end toFlatStream; + + function toFlatString + input Modifier mod; + input Boolean printName = true; + output String str; + protected + IOStream.IOStream s; + algorithm + s := IOStream.create(getInstanceName(), IOStream.IOStreamType.LIST()); + s := toFlatStream(mod, s, printName); + str := IOStream.string(s); + IOStream.delete(s); end toFlatString; protected diff --git a/OMCompiler/Compiler/NFFrontEnd/NFSimplifyExp.mo b/OMCompiler/Compiler/NFFrontEnd/NFSimplifyExp.mo index cde6f8c0750..812a3319d76 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFSimplifyExp.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFSimplifyExp.mo @@ -718,7 +718,8 @@ protected algorithm Expression.SUBSCRIPTED_EXP(e, subs, ty) := subscriptedExp; subscriptedExp := simplify(e); - subscriptedExp := Expression.applySubscripts(list(Subscript.simplify(s) for s in subs), subscriptedExp); + subs := Subscript.simplifyList(subs, Type.arrayDims(Expression.typeOf(e))); + subscriptedExp := Expression.applySubscripts(subs, subscriptedExp); end simplifySubscriptedExp; function simplifyTupleElement diff --git a/OMCompiler/Compiler/NFFrontEnd/NFSubscript.mo b/OMCompiler/Compiler/NFFrontEnd/NFSubscript.mo index 36412e06d93..088334c3d7e 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFSubscript.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFSubscript.mo @@ -86,6 +86,13 @@ public end match; end fromExp; + function fromTypedExp + input Expression exp; + output Subscript subscript; + algorithm + subscript := if Type.isArray(Expression.typeOf(exp)) then SLICE(exp) else INDEX(exp); + end fromTypedExp; + function toExp input Subscript subscript; output Expression exp; @@ -384,13 +391,13 @@ public algorithm e2 := Expression.map(e1, func); then - if referenceEq(e1, e2) then subscript else INDEX(e2); + if referenceEq(e1, e2) then subscript else fromTypedExp(e2); case SLICE(slice = e1) algorithm e2 := Expression.map(e1, func); then - if referenceEq(e1, e2) then subscript else SLICE(e2); + if referenceEq(e1, e2) then subscript else fromTypedExp(e2); else subscript; end match; @@ -419,13 +426,13 @@ public algorithm e2 := func(e1); then - if referenceEq(e1, e2) then subscript else INDEX(e2); + if referenceEq(e1, e2) then subscript else fromTypedExp(e2); case SLICE(slice = e1) algorithm e2 := func(e1); then - if referenceEq(e1, e2) then subscript else SLICE(e2); + if referenceEq(e1, e2) then subscript else fromTypedExp(e2); else subscript; end match; @@ -475,13 +482,13 @@ public algorithm (exp, arg) := Expression.mapFold(subscript.index, func, arg); then - if referenceEq(subscript.index, exp) then subscript else INDEX(exp); + if referenceEq(subscript.index, exp) then subscript else fromTypedExp(exp); case SLICE() algorithm (exp, arg) := Expression.mapFold(subscript.slice, func, arg); then - if referenceEq(subscript.slice, exp) then subscript else SLICE(exp); + if referenceEq(subscript.slice, exp) then subscript else fromTypedExp(exp); else subscript; end match; @@ -512,13 +519,13 @@ public algorithm (exp, arg) := func(subscript.index, arg); then - if referenceEq(subscript.index, exp) then subscript else INDEX(exp); + if referenceEq(subscript.index, exp) then subscript else fromTypedExp(exp); case SLICE() algorithm (exp, arg) := func(subscript.slice, arg); then - if referenceEq(subscript.slice, exp) then subscript else SLICE(exp); + if referenceEq(subscript.slice, exp) then subscript else fromTypedExp(exp); else subscript; end match; @@ -614,15 +621,66 @@ public function simplify input Subscript subscript; + input Dimension dimension; output Subscript outSubscript; algorithm outSubscript := match subscript case INDEX() then INDEX(SimplifyExp.simplify(subscript.index)); - case SLICE() then SLICE(SimplifyExp.simplify(subscript.slice)); + case SLICE() then simplifySlice(subscript.slice, dimension); else subscript; end match; end simplify; + function simplifySlice + input Expression slice; + input Dimension dimension; + output Subscript outSubscript; + protected + Expression exp; + algorithm + exp := SimplifyExp.simplify(slice); + + outSubscript := match exp + // If the slice is equivalent to 1:size(dim), replace it with : + case Expression.RANGE() + guard (isNone(exp.step) or Expression.isOne(Util.getOption(exp.step))) and + Dimension.expIsLowerBound(exp.start) and + Dimension.expIsUpperBound(exp.stop, dimension) + then WHOLE(); + + // Otherwise return a new slice with the simplified expression. + else SLICE(exp); + end match; + end simplifySlice; + + function simplifyList + input list subscripts; + input list dimensions; + output list outSubscripts = {}; + protected + Dimension d; + list rest_d = dimensions; + algorithm + if listEmpty(dimensions) then + // If the type of the subscript owner isn't known, for example when dealing + // with expandable connector elements, treat the dimensions as unknown. + outSubscripts := list(simplify(s, Dimension.UNKNOWN()) for s in subscripts); + else + rest_d := List.lastN(dimensions, listLength(subscripts)); + + for s in subscripts loop + d :: rest_d := rest_d; + outSubscripts := simplify(s, d) :: outSubscripts; + end for; + + while not listEmpty(outSubscripts) and isWhole(listHead(outSubscripts)) loop + outSubscripts := listRest(outSubscripts); + end while; + + outSubscripts := listReverseInPlace(outSubscripts); + end if; + end simplifyList; + function toDimension "Returns a dimension representing the size of the given subscript." input Subscript subscript; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFType.mo b/OMCompiler/Compiler/NFFrontEnd/NFType.mo index 108525cb23f..f94af9eb0d7 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFType.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFType.mo @@ -835,8 +835,8 @@ public case Type.CLOCK() then "Clock"; case Type.ENUMERATION() then "'" + AbsynUtil.pathString(ty.typePath) + "'"; case Type.ENUMERATION_ANY() then "enumeration(:)"; - case Type.ARRAY() then toString(ty.elementType) + "[" + stringDelimitList(List.map(ty.dimensions, Dimension.toString), ", ") + "]"; - case Type.TUPLE() then "(" + stringDelimitList(List.map(ty.types, toString), ", ") + ")"; + case Type.ARRAY() then toFlatString(ty.elementType) + "[" + stringDelimitList(List.map(ty.dimensions, Dimension.toFlatString), ", ") + "]"; + case Type.TUPLE() then "(" + stringDelimitList(List.map(ty.types, toFlatString), ", ") + ")"; case Type.NORETCALL() then "()"; case Type.UNKNOWN() then "unknown()"; case Type.COMPLEX() then "'" + AbsynUtil.pathString(InstNode.scopePath(ty.cls)) + "'"; @@ -889,13 +889,13 @@ public s := IOStream.append(s, ty.name); s := IOStream.append(s, "'\n"); - s := IOStream.append(s, "input "); + s := IOStream.append(s, " input "); s := IOStream.append(s, toString(ty.ty)); s := IOStream.append(s, " exp;\n"); index := 1; for sub in ty.subs loop - s := IOStream.append(s, "input "); + s := IOStream.append(s, " input "); s := IOStream.append(s, toString(sub)); s := IOStream.append(s, " s"); s := IOStream.append(s, String(index)); @@ -903,7 +903,7 @@ public index := index + 1; end for; - s := IOStream.append(s, "output "); + s := IOStream.append(s, " output "); s := IOStream.append(s, toString(ty.subscriptedTy)); s := IOStream.append(s, " result = exp["); s := IOStream.append(s, diff --git a/OMCompiler/Compiler/NFFrontEnd/NFVariable.mo b/OMCompiler/Compiler/NFFrontEnd/NFVariable.mo index 4f274b5738b..43ba10509f8 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFVariable.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFVariable.mo @@ -213,40 +213,15 @@ public if var.visibility == Visibility.PROTECTED then s := IOStream.append(s, "protected "); + else + s := IOStream.append(s, "public "); end if; - s := IOStream.append(s, Component.Attributes.toFlatString(var.attributes, var.ty)); + s := Component.Attributes.toFlatStream(var.attributes, var.ty, s, ComponentRef.isSimple(var.name)); s := IOStream.append(s, Type.toFlatString(var.ty)); s := IOStream.append(s, " "); s := IOStream.append(s, ComponentRef.toFlatString(var.name)); - - if not listEmpty(var.typeAttributes) then - s := IOStream.append(s, "("); - - first := true; - var_dims := Type.dimensionCount(var.ty); - - for a in var.typeAttributes loop - if first then - first := false; - else - s := IOStream.append(s, ", "); - end if; - - b := Util.tuple22(a); - binding_dims := Type.dimensionCount(Expression.typeOf(Expression.getBindingExp(Binding.getExp(b)))); - - if var_dims > binding_dims then - s := IOStream.append(s, "each "); - end if; - - s := IOStream.append(s, Util.tuple21(a)); - s := IOStream.append(s, " = "); - s := IOStream.append(s, Binding.toFlatString(b)); - end for; - - s := IOStream.append(s, ")"); - end if; + s := Component.typeAttrsToFlatStream(var.typeAttributes, var.ty, s); if Binding.isBound(var.binding) then s := IOStream.append(s, " = ");