Skip to content

Commit

Permalink
Improve handling of conditional components (#7608)
Browse files Browse the repository at this point in the history
- Try to delete conditional components earlier during typing instead of
  during flattening if possible, to avoid type mismatch issues inside of
  deleted components.
- Change Expression.makeExpArray to take the element type as argument
  instead of deducing it from the list of expressions, to make it safe
  to use for empty arrays.
  • Loading branch information
perost committed Jun 24, 2021
1 parent 5234deb commit b2341d1
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 26 deletions.
3 changes: 2 additions & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFCeval.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2858,7 +2858,8 @@ protected
Type ty;
algorithm
expl := Expression.arrayScalarElements(arg);
result := Expression.makeExpArray(expl, isLiteral = true);
result := Expression.makeExpArray(expl,
Type.arrayElementType(Expression.typeOf(arg)), isLiteral = true);
end evalBuiltinVector;

function evalBuiltinZeros
Expand Down
1 change: 1 addition & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFComponent.mo
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,7 @@ public
count := match component
case UNTYPED_COMPONENT() then arrayLength(component.dimensions);
case TYPED_COMPONENT() then listLength(Type.arrayDims(component.ty));
case DELETED_COMPONENT() then dimensionCount(component.component);
else 0;
end match;
end dimensionCount;
Expand Down
4 changes: 3 additions & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFComponentRef.mo
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,9 @@ public
InstNode node;

case CREF(node = node, origin = Origin.CREF)
then InstNode.isComponent(node) and Component.isDeleted(InstNode.component(node));
then (InstNode.isComponent(node) and Component.isDeleted(InstNode.component(node))) or
isDeleted(cref.restCref);

else false;
end match;
end isDeleted;
Expand Down
8 changes: 5 additions & 3 deletions OMCompiler/Compiler/NFFrontEnd/NFExpression.mo
Original file line number Diff line number Diff line change
Expand Up @@ -933,13 +933,13 @@ public

function makeExpArray
input list<Expression> elements;
input Type elementType;
input Boolean isLiteral = false;
output Expression exp;
protected
Type ty;
algorithm
ty := typeOf(listHead(elements));
ty := Type.liftArrayLeft(ty, Dimension.fromInteger(listLength(elements)));
ty := Type.liftArrayLeft(elementType, Dimension.fromInteger(listLength(elements)));
exp := makeArray(ty, elements, isLiteral);
end makeExpArray;

Expand Down Expand Up @@ -4893,6 +4893,7 @@ public
Integer dim_size_int;
Expression sub_exp;
list<Expression> rest_subs, expl;
Type ty;
algorithm
if listEmpty(dimSizes) then
outExp := Expression.map(exp, mapSplitExpressions3);
Expand All @@ -4909,7 +4910,8 @@ public
expl := outExp :: expl;
end for;

outExp := Expression.makeExpArray(expl, isLiteral = true);
ty := Expression.typeOf(if listEmpty(expl) then exp else listHead(expl));
outExp := Expression.makeExpArray(expl, ty, isLiteral = true);
end if;
end mapSplitExpressions2;

Expand Down
4 changes: 3 additions & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFSimplifyExp.mo
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ function simplifyVector
protected
list<Expression> expl;
Boolean is_literal;
Type ty;
algorithm
expl := Expression.arrayScalarElements(arg);
is_literal := Expression.isLiteral(arg);
Expand All @@ -347,7 +348,8 @@ algorithm
end if;

if is_literal or List.all(expl, Expression.isScalar) then
exp := Expression.makeExpArray(expl);
ty := Type.arrayElementType(Expression.typeOf(arg));
exp := Expression.makeExpArray(expl, ty);
else
exp := Expression.CALL(call);
end if;
Expand Down
73 changes: 53 additions & 20 deletions OMCompiler/Compiler/NFFrontEnd/NFTyping.mo
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,9 @@ function typeComponent
output Type ty;
protected
InstNode node = InstNode.resolveOuter(component);
Component c = InstNode.component(node);
Component c = InstNode.component(node), c_typed;
Expression cond;
Boolean is_deleted;
algorithm
ty := match c
// An untyped component, type it.
Expand All @@ -375,20 +377,35 @@ algorithm
// Construct the type of the component and update the node with it.
ty := typeClassType(c.classInst, c.binding, context, component);
ty := Type.liftArrayLeftList(ty, arrayList(c.dimensions));
InstNode.updateComponent(Component.setType(ty, c), node);

// Check that flow/stream variables are Real.
checkComponentStreamAttribute(c.attributes.connectorType, ty, component);
if Binding.isBound(c.condition) then
c.condition := typeComponentCondition(c.condition, context, evaluate = true);
is_deleted := Expression.isFalse(Binding.getExp(c.condition));
else
is_deleted := false;
end if;

c_typed := Component.setType(ty, c);

// Type the component's children.
typeComponents(c.classInst, context);
if is_deleted then
InstNode.updateComponent(Component.DELETED_COMPONENT(c_typed), node);
else
InstNode.updateComponent(c_typed, node);

// Check that flow/stream variables are Real.
checkComponentStreamAttribute(c.attributes.connectorType, ty, component);

// Type the component's children.
typeComponents(c.classInst, context);
end if;
then
ty;

// A component that has already been typed, skip it.
case Component.TYPED_COMPONENT() then c.ty;
case Component.ITERATOR() then c.ty;
case Component.ENUM_LITERAL(literal = Expression.ENUM_LITERAL(ty = ty)) then ty;
case Component.DELETED_COMPONENT() then Component.getType(c.component);

// Any other type of component shouldn't show up here.
else
Expand Down Expand Up @@ -863,10 +880,6 @@ algorithm

c.binding := binding;

if Binding.isBound(c.condition) then
c.condition := typeComponentCondition(c.condition, context);
end if;

InstNode.updateComponent(c, node);

if typeChildren then
Expand All @@ -885,11 +898,6 @@ algorithm
checkComponentBindingVariability(InstNode.name(component), c, c.binding, context);
end if;

if Binding.isBound(c.condition) then
c.condition := typeComponentCondition(c.condition, context);
InstNode.updateComponent(c, node);
end if;

if typeChildren then
typeBindings(c.classInst, component, context);
end if;
Expand Down Expand Up @@ -926,6 +934,8 @@ algorithm
then
();

case Component.DELETED_COMPONENT() then ();

else
algorithm
Error.assertion(false, getInstanceName() + " got invalid node " + InstNode.name(node), sourceInfo());
Expand Down Expand Up @@ -1024,6 +1034,7 @@ end checkBindingEach;
function typeComponentCondition
input output Binding condition;
input InstContext.Type context;
input Boolean evaluate = false;
algorithm
condition := match condition
local
Expand All @@ -1032,6 +1043,7 @@ algorithm
Variability var;
SourceInfo info;
MatchKind mk;
NFBinding.EvalState eval_state;

case Binding.UNTYPED_BINDING(bindingExp = exp)
algorithm
Expand All @@ -1050,9 +1062,22 @@ algorithm
{Expression.toString(exp)}, info);
fail();
end if;

eval_state := NFBinding.EvalState.NOT_EVALUATED;

if evaluate then
ErrorExt.setCheckpoint(getInstanceName());
try
exp := Ceval.evalExp(exp, Ceval.EvalTarget.CONDITION(info));
exp := simplifyDimExp(exp);
eval_state := NFBinding.EvalState.EVALUATED;
else
end try;
ErrorExt.rollBack(getInstanceName());
end if;
then
Binding.TYPED_BINDING(exp, ty, var, NFBinding.EachType.NOT_EACH,
Mutable.create(NFBinding.EvalState.NOT_EVALUATED), false, condition.source, info);
Mutable.create(eval_state), false, condition.source, info);

end match;
end typeComponentCondition;
Expand Down Expand Up @@ -2692,6 +2717,8 @@ algorithm
then
();

case Component.DELETED_COMPONENT() then ();

else
algorithm
Error.assertion(false, getInstanceName() + " got uninstantiated component " + InstNode.name(component), sourceInfo());
Expand Down Expand Up @@ -2787,6 +2814,7 @@ protected
InstContext.Type next_context;
SourceInfo info;
list<Equation> eql;
Boolean lhs_deleted, rhs_deleted;
algorithm
info := ElementSource.getInfo(source);

Expand All @@ -2800,13 +2828,14 @@ algorithm
end if;

next_context := InstContext.set(context, NFInstContext.CONNECT);
(lhs, lhs_ty) := typeConnector(lhsConn, next_context, info);
(rhs, rhs_ty) := typeConnector(rhsConn, next_context, info);
(lhs, lhs_ty, lhs_deleted) := typeConnector(lhsConn, next_context, info);
(rhs, rhs_ty, rhs_deleted) := typeConnector(rhsConn, next_context, info);

// Check that the connectors have matching types, but only if they're not expandable.
// Expandable connectors can only be type checked after they've been augmented during
// the connection handling.
if not (Type.isExpandableConnector(lhs_ty) or Type.isExpandableConnector(rhs_ty)) then
if not (lhs_deleted or rhs_deleted) and
not (Type.isExpandableConnector(lhs_ty) or Type.isExpandableConnector(rhs_ty)) then
(lhs, rhs, _, mk) := TypeCheck.matchExpressions(lhs, lhs_ty, rhs, rhs_ty, allowUnknown = true);

if TypeCheck.isIncompatibleMatch(mk) then
Expand All @@ -2825,14 +2854,16 @@ function typeConnector
input InstContext.Type context;
input SourceInfo info;
output Type ty;
output Boolean deleted;
algorithm
(connExp, ty, _) := typeExp(connExp, context, info);
checkConnector(connExp, info);
deleted := checkConnector(connExp, info);
end typeConnector;

function checkConnector
input Expression connExp;
input SourceInfo info;
output Boolean deleted;
protected
ComponentRef cr;
list<Subscript> subs;
Expand Down Expand Up @@ -2860,6 +2891,8 @@ algorithm
end if;
end for;
end if;

deleted := ComponentRef.isDeleted(cr);
then
();

Expand Down

0 comments on commit b2341d1

Please sign in to comment.