Skip to content

Commit

Permalink
[NF] Record binding improvements.
Browse files Browse the repository at this point in the history
- Evaluate record constructors to record expressions.
- Split record expressions when flattening a complex component.
- Added dummy node to the definition of the Integer function instead
  of using an empty node, so we can assume each function has a node.

Belonging to [master]:
  - OpenModelica/OMCompiler#2307
  - OpenModelica/OpenModelica-testsuite#891
  • Loading branch information
perost authored and OpenModelica-Hudson committed Mar 23, 2018
1 parent f103a0d commit 63888ab
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 46 deletions.
10 changes: 10 additions & 0 deletions Compiler/NFFrontEnd/NFBinding.mo
Expand Up @@ -156,6 +156,16 @@ public
end match;
end setTypedExp;

function isRecordExp
input Binding binding;
output Boolean isRecordExp;
algorithm
isRecordExp := match binding
case TYPED_BINDING(bindingExp = Expression.RECORD()) then true;
else false;
end match;
end isRecordExp;

function variability
input Binding binding;
output Variability var;
Expand Down
22 changes: 16 additions & 6 deletions Compiler/NFFrontEnd/NFBuiltinFuncs.mo
Expand Up @@ -52,11 +52,16 @@ import Binding = NFBinding;
import Pointer;
import NFPrefixes.Visibility;

// Dummy SCode component, since we usually don't need the definition for anything.
constant SCode.Element DUMMY_ELEMENT = SCode.COMPONENT("dummy",
SCode.defaultPrefixes, SCode.defaultVarAttr,
TypeSpec.TPATH(Path.IDENT("$dummy"), NONE()), SCode.Mod.NOMOD(),
SCode.Comment.COMMENT(NONE(), NONE()), NONE(), Absyn.dummyInfo);
constant SCode.Element DUMMY_ELEMENT = SCode.CLASS(
"$DummyFunction",
SCode.defaultPrefixes,
SCode.Encapsulated.ENCAPSULATED(),
SCode.Partial.NOT_PARTIAL(),
SCode.Restriction.R_FUNCTION(SCode.FunctionRestriction.FR_NORMAL_FUNCTION(false)),
SCode.ClassDef.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
SCode.Comment.COMMENT(NONE(), NONE()),
Absyn.dummyInfo
);

// Default Integer parameter.
constant Component INT_COMPONENT = Component.TYPED_COMPONENT(NFInstNode.EMPTY_NODE(),
Expand Down Expand Up @@ -99,8 +104,13 @@ constant InstNode ENUM_PARAM = InstNode.COMPONENT_NODE("e",
Pointer.createImmutable(ENUM_COMPONENT), 0, InstNode.EMPTY_NODE());

// Integer(e)
constant InstNode INTEGER_NODE = NFInstNode.CLASS_NODE("Integer",
DUMMY_ELEMENT, Visibility.PUBLIC, Pointer.createImmutable(Class.NOT_INSTANTIATED()),
arrayCreate(NFInstNode.NUMBER_OF_CACHES, NFInstNode.CachedData.NO_CACHE()),
InstNode.EMPTY_NODE(), InstNodeType.NORMAL_CLASS());

constant Function INTEGER = Function.FUNCTION(Path.IDENT("Integer"),
InstNode.EMPTY_NODE(), {ENUM_PARAM}, {}, {}, {
INTEGER_NODE, {ENUM_PARAM}, {}, {}, {
Slot.SLOT("e", SlotType.POSITIONAL, NONE(), NONE())
}, Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, Pointer.createImmutable(true));

Expand Down
54 changes: 43 additions & 11 deletions Compiler/NFFrontEnd/NFCall.mo
Expand Up @@ -427,48 +427,57 @@ uniontype Call

public
function typeCall
input output Expression callExp;
input Expression callExp;
input ExpOrigin.Type origin;
input SourceInfo info;
output Type ty;
output Variability variability;
output Expression outExp;
output Type ty;
output Variability variability;
protected
Call call;
list<Expression> args;
algorithm
() := match callExp
outExp := match callExp
case Expression.CALL(UNTYPED_CALL())
algorithm
if(builtinSpecialHandling(callExp.call)) then
(callExp, ty, variability) := typeSpecialBuiltinFunction(callExp.call, origin, info);
(outExp, ty, variability) := typeSpecialBuiltinFunction(callExp.call, origin, info);
else
call := typeMatchNormalCall(callExp.call, origin, info);
callExp := Expression.CALL(call);
ty := getType(call);
variability := getVariability(call);

if isRecordConstructor(call) then
outExp := toRecordExpression(call, ty);
else
outExp := Expression.CALL(call);
end if;
end if;
then
();
outExp;

case Expression.CALL(UNTYPED_MAP_CALL())
algorithm
call := typeMapIteratorCall(callExp.call, origin, info);
callExp := Expression.CALL(call);
ty := getType(call);
variability := getVariability(call);
then
();
Expression.CALL(call);

case Expression.CALL(call as TYPED_CALL())
algorithm
ty := call.ty;
variability := call.var;
then
();
callExp;

case Expression.CALL(call as TYPED_MAP_CALL())
algorithm
ty := call.ty;
variability := call.var;
then
();
callExp;

else
algorithm
Error.assertion(false, getInstanceName() + ": " + Expression.toString(callExp), sourceInfo());
Expand Down Expand Up @@ -2296,6 +2305,29 @@ protected
output String s = stringDelimitList(list(Function.signatureString(fn, true) for fn in fns), "\n ");
end candidateFuncListString;

function isRecordConstructor
input Call call;
output Boolean isConstructor;
algorithm
isConstructor := match call
case UNTYPED_CALL()
then SCode.isRecord(InstNode.definition(ComponentRef.node(call.ref)));
case TYPED_CALL()
then SCode.isRecord(InstNode.definition(call.fn.node));
else false;
end match;
end isRecordConstructor;

function toRecordExpression
input Call call;
input Type ty;
output Expression exp;
algorithm
exp := match call
case TYPED_CALL()
then Expression.RECORD(Function.name(call.fn), ty, call.arguments);
end match;
end toRecordExpression;
end Call;

annotation(__OpenModelica_Interface="frontend");
Expand Down
1 change: 1 addition & 0 deletions Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -764,6 +764,7 @@ public
) + ":" + operandString(exp.stop, exp, false);

case TUPLE() then "(" + stringDelimitList(list(toString(e) for e in exp.elements), ", ") + ")";
case RECORD() then List.toString(exp.elements, toString, Absyn.pathString(exp.path), "(", ", ", ")", true);
case CALL() then Call.toString(exp.call);
case SIZE() then "size(" + toString(exp.exp) +
(
Expand Down
116 changes: 87 additions & 29 deletions Compiler/NFFrontEnd/NFFlatten.mo
Expand Up @@ -125,8 +125,8 @@ algorithm
sections := Sections.EMPTY();
cmt := SCode.getElementComment(InstNode.definition(classInst));

(vars, sections) :=
flattenClass(InstNode.getClass(classInst), ComponentRef.EMPTY(), Visibility.PUBLIC, {}, sections);
(vars, sections) := flattenClass(InstNode.getClass(classInst), ComponentRef.EMPTY(),
Visibility.PUBLIC, NONE(), {}, sections);
vars := listReverseInPlace(vars);

flatModel := match sections
Expand All @@ -152,17 +152,43 @@ function flattenClass
input Class cls;
input ComponentRef prefix;
input Visibility visibility;
input Option<Binding> binding;
input output list<Variable> vars;
input output Sections sections;
protected
ClassTree cls_tree;
array<InstNode> comps;
list<Binding> bindings;
Binding b;
algorithm
() := match cls
case Class.INSTANCED_CLASS(elements = cls_tree as ClassTree.FLAT_TREE())
case Class.INSTANCED_CLASS(elements = ClassTree.FLAT_TREE(components = comps))
algorithm
for c in cls_tree.components loop
(vars, sections) := flattenComponent(c, prefix, visibility, vars, sections);
end for;
if isSome(binding) then
SOME(b) := binding;

if Binding.isBound(b) then
b := flattenBinding(b, ComponentRef.rest(prefix), ComponentRef.node(prefix));
bindings := getRecordBindings(b);

Error.assertion(listLength(bindings) == arrayLength(comps),
getInstanceName() + " got record binding with wrong number of elements for " +
ComponentRef.toString(prefix),
sourceInfo());

for c in comps loop
(vars, sections) := flattenComponent(c, prefix, visibility, SOME(listHead(bindings)), vars, sections);
bindings := listRest(bindings);
end for;
else
for c in comps loop
(vars, sections) := flattenComponent(c, prefix, visibility, binding, vars, sections);
end for;
end if;
else
for c in comps loop
(vars, sections) := flattenComponent(c, prefix, visibility, NONE(), vars, sections);
end for;
end if;

sections := flattenSections(cls.sections, prefix, sections);
then
Expand All @@ -183,6 +209,7 @@ function flattenComponent
input InstNode component;
input ComponentRef prefix;
input Visibility visibility;
input Option<Binding> outerBinding;
input output list<Variable> vars;
input output Sections sections;
protected
Expand Down Expand Up @@ -214,7 +241,7 @@ algorithm

(vars, sections) := match cls
case Class.INSTANCED_BUILTIN()
then flattenSimpleComponent(comp_node, c, vis, cls.attributes, prefix, vars, sections);
then flattenSimpleComponent(comp_node, c, vis, outerBinding, cls.attributes, prefix, vars, sections);
else flattenComplexComponent(comp_node, c, cls, ty, vis, prefix, vars, sections);
end match;
then
Expand All @@ -233,6 +260,7 @@ function flattenSimpleComponent
input InstNode node;
input Component comp;
input Visibility visibility;
input Option<Binding> outerBinding;
input list<Modifier> typeAttrs;
input ComponentRef prefix;
input output list<Variable> vars;
Expand All @@ -252,7 +280,12 @@ algorithm
Component.TYPED_COMPONENT(ty = ty, binding = binding, attributes = comp_attr,
comment = cmt, info = info) := comp;

binding := flattenBinding(binding, prefix, comp_node);
if isSome(outerBinding) then
SOME(binding) := outerBinding;
else
binding := flattenBinding(binding, prefix, comp_node);
end if;

name := ComponentRef.prefixCref(comp_node, ty, {}, prefix);

// If the component is an array component with a binding and at least discrete variability,
Expand Down Expand Up @@ -281,6 +314,26 @@ algorithm
outAttr := (Modifier.name(attr), binding);
end flattenTypeAttribute;

function getRecordBindings
input Binding binding;
output list<Binding> recordBindings;
protected
Expression binding_exp;
list<Expression> expl;
algorithm
binding_exp := Binding.getTypedExp(binding);

recordBindings := match binding_exp
case Expression.RECORD() then list(Binding.FLAT_BINDING(e) for e in binding_exp.elements);
else
algorithm
Error.assertion(false, getInstanceName() + " got non-record binding " +
Expression.toString(binding_exp), sourceInfo());
then
fail();
end match;
end getRecordBindings;

function flattenComplexComponent
input InstNode node;
input Component comp;
Expand All @@ -294,32 +347,36 @@ protected
list<Dimension> dims;
ComponentRef name;
Binding binding;
Option<Binding> opt_binding;
Expression binding_exp;
Equation eq;
list<Expression> bindings;
algorithm
dims := Type.arrayDims(ty);
name := ComponentRef.prefixCref(node, ty, {}, prefix);
binding := Component.getBinding(comp);

// Flatten the class directly if the component is a scalar, otherwise scalarize it.
if listEmpty(dims) then
binding := Component.getBinding(comp);

if Binding.isBound(binding) then
binding_exp := Binding.getTypedExp(binding);

if not Expression.isRecord(binding_exp) then
eq := Equation.EQUALITY(Expression.CREF(ty, name), binding_exp, ty,
ElementSource.createElementSource(InstNode.info(node)));
sections := Sections.prependEquation(eq, sections);
binding := Binding.UNBOUND();
else
// TODO: Split record expressions and pass them to flattenClass.
end if;
// Create an equation if there's a binding on a complex component.
if Binding.isBound(binding) then
binding_exp := Binding.getTypedExp(binding);

if not Expression.isRecord(binding_exp) then
eq := Equation.EQUALITY(Expression.CREF(ty, name), binding_exp, ty,
ElementSource.createElementSource(InstNode.info(node)));
sections := Sections.prependEquation(eq, sections);
opt_binding := SOME(Binding.UNBOUND());
else
opt_binding := SOME(flattenBinding(binding, prefix, node));
end if;
else
opt_binding := NONE();
end if;

(vars, sections) := flattenClass(cls, name, visibility, vars, sections);
// Flatten the class directly if the component is a scalar, otherwise scalarize it.
if listEmpty(dims) then
(vars, sections) := flattenClass(cls, name, visibility, opt_binding, vars, sections);
else
(vars, sections) := flattenArray(cls, dims, name, visibility, vars, sections);
(vars, sections) := flattenArray(cls, dims, name, visibility, opt_binding, vars, sections);
end if;
end flattenComplexComponent;

Expand All @@ -328,6 +385,7 @@ function flattenArray
input list<Dimension> dimensions;
input ComponentRef prefix;
input Visibility visibility;
input Option<Binding> binding;
input output list<Variable> vars;
input output Sections sections;
input list<Subscript> subscripts = {};
Expand All @@ -340,15 +398,15 @@ protected
algorithm
if listEmpty(dimensions) then
sub_pre := ComponentRef.setSubscripts(listReverse(subscripts), prefix);
(vars, sections) := flattenClass(cls, sub_pre, visibility, vars, sections);
(vars, sections) := flattenClass(cls, sub_pre, visibility, binding, vars, sections);
else
dim :: rest_dims := dimensions;
range_iter := RangeIterator.fromDim(dim);

while RangeIterator.hasNext(range_iter) loop
(range_iter, sub_exp) := RangeIterator.next(range_iter);
(vars, sections) := flattenArray(cls, rest_dims, prefix, visibility, vars, sections,
Subscript.INDEX(sub_exp) :: subscripts);
(vars, sections) := flattenArray(cls, rest_dims, prefix, visibility,
binding, vars, sections, Subscript.INDEX(sub_exp) :: subscripts);
end while;
end if;
end flattenArray;
Expand Down

0 comments on commit 63888ab

Please sign in to comment.