Skip to content

Commit 291aef2

Browse files
committed
[NF] Record improvements.
- Fix evaluation of record field crefs so that getting the binding from the parent's parent (and so on) works properly. - When determining the default argument for a function parameter of record type, try to create an argument from the record's fields if the parameter itself does not have a binding.
1 parent d5ae327 commit 291aef2

File tree

7 files changed

+112
-12
lines changed

7 files changed

+112
-12
lines changed

OMCompiler/Compiler/NFFrontEnd/NFCeval.mo

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -644,19 +644,43 @@ algorithm
644644

645645
// A record field without an explicit binding, evaluate the parent's binding
646646
// if it has one and fetch the binding from it instead.
647-
case (_, ComponentRef.CREF(restCref = rest_cr as ComponentRef.CREF(ty = ty)))
648-
guard Type.isRecord(Type.arrayElementType(ty))
647+
case (_, _)
649648
algorithm
650-
exp := evalCref(rest_cr, Expression.EMPTY(ty), target);
651-
exp := Expression.bindingExpMap(exp, function makeComponentBinding2(name = InstNode.name(node)));
649+
exp := makeRecordFieldBindingFromParent(cref, target);
652650
then
653651
Binding.CEVAL_BINDING(exp);
654652

655653
else NFBinding.EMPTY_BINDING;
656654
end matchcontinue;
657655
end makeComponentBinding;
658656

659-
function makeComponentBinding2
657+
function makeRecordFieldBindingFromParent
658+
input ComponentRef cref;
659+
input EvalTarget target;
660+
output Expression exp;
661+
protected
662+
ComponentRef parent_cr;
663+
Type parent_ty;
664+
algorithm
665+
parent_cr := ComponentRef.rest(cref);
666+
parent_ty := ComponentRef.nodeType(parent_cr);
667+
true := Type.isRecord(Type.arrayElementType(parent_ty));
668+
669+
try
670+
// Pass an EMPTY expression here as the default expression instead of the
671+
// cref. Otherwise evalCref might attempt to make a binding for the parent
672+
// from its children, which would create an evaluation loop.
673+
exp := evalCref(parent_cr, Expression.EMPTY(parent_ty), target);
674+
else
675+
// If the parent didn't have a binding, try the parent's parent.
676+
exp := makeRecordFieldBindingFromParent(parent_cr, target);
677+
end try;
678+
679+
exp := Expression.bindingExpMap(exp,
680+
function lookupRecordFieldInExp(name = ComponentRef.firstName(cref)));
681+
end makeRecordFieldBindingFromParent;
682+
683+
function lookupRecordFieldInExp
660684
input Expression exp;
661685
input String name;
662686
output Expression result;
@@ -669,7 +693,7 @@ algorithm
669693

670694
case Expression.RECORD() then Expression.recordElement(name, exp);
671695

672-
// An empty array of records will still be empty, only the type needs to be changed.
696+
// An empty array of records will still be empty, but the type needs to be changed.
673697
case Expression.ARRAY(elements = {})
674698
algorithm
675699
exp.ty := Type.lookupRecordFieldType(name, exp.ty);
@@ -682,16 +706,16 @@ algorithm
682706
// element of the array so we only need to do lookup once.
683707
case Expression.ARRAY(ty = Type.ARRAY(dimensions = dim :: _))
684708
algorithm
685-
expl := list(makeComponentBinding2(e, name) for e in exp.elements);
709+
expl := list(lookupRecordFieldInExp(e, name) for e in exp.elements);
686710
ty := Type.liftArrayLeft(Expression.typeOf(listHead(expl)), dim);
687711
then
688712
Expression.makeArray(ty, expl, literal = true);
689713

690714
case Expression.SUBSCRIPTED_EXP()
691-
then Expression.SUBSCRIPTED_EXP(makeComponentBinding2(exp.exp, name), exp.subscripts, exp.ty);
715+
then Expression.SUBSCRIPTED_EXP(lookupRecordFieldInExp(exp.exp, name), exp.subscripts, exp.ty);
692716

693717
end match;
694-
end makeComponentBinding2;
718+
end lookupRecordFieldInExp;
695719

696720
function makeRecordBindingExp
697721
input InstNode typeNode;

OMCompiler/Compiler/NFFrontEnd/NFClass.mo

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,23 @@ uniontype Class
694694
end if;
695695
end hasOperator;
696696

697+
function makeRecordExp
698+
input InstNode clsNode;
699+
output Expression exp;
700+
protected
701+
Class cls;
702+
Type ty;
703+
InstNode ty_node;
704+
array<InstNode> fields;
705+
list<Expression> args;
706+
algorithm
707+
cls := InstNode.getClass(clsNode);
708+
ty as Type.COMPLEX(complexTy = ComplexType.RECORD(ty_node)) := getType(cls, clsNode);
709+
fields := ClassTree.getComponents(classTree(cls));
710+
args := list(Binding.getExp(Component.getImplicitBinding(InstNode.component(f))) for f in fields);
711+
exp := Expression.makeRecord(InstNode.scopePath(ty_node), ty, args);
712+
end makeRecordExp;
713+
697714
function toFlatStream
698715
input Class cls;
699716
input InstNode clsNode;

OMCompiler/Compiler/NFFrontEnd/NFComponent.mo

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,31 @@ uniontype Component
453453
end match;
454454
end getBinding;
455455

456+
function getImplicitBinding
457+
"Returns the component's binding. If the component does not have a binding
458+
and is a record instance it will try to create a binding from the
459+
component's children."
460+
input Component component;
461+
output Binding binding;
462+
protected
463+
InstNode cls_node;
464+
Expression record_exp;
465+
algorithm
466+
binding := getBinding(component);
467+
468+
if Binding.isUnbound(binding) then
469+
cls_node := classInstance(component);
470+
471+
if InstNode.isRecord(cls_node) then
472+
try
473+
record_exp := Class.makeRecordExp(cls_node);
474+
binding := Binding.FLAT_BINDING(record_exp, Expression.variability(record_exp));
475+
else
476+
end try;
477+
end if;
478+
end if;
479+
end getImplicitBinding;
480+
456481
function setBinding
457482
input Binding binding;
458483
input output Component component;

OMCompiler/Compiler/NFFrontEnd/NFFunction.mo

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ import Array;
7777
import ElementSource;
7878
import SCodeUtil;
7979
import IOStream;
80+
import ComplexType = NFComplexType;
8081

8182
public
8283
type NamedArg = tuple<String, Expression>;
@@ -1969,7 +1970,7 @@ protected
19691970
algorithm
19701971
try
19711972
comp := InstNode.component(component);
1972-
default := Binding.typedExp(Component.getBinding(comp));
1973+
default := Binding.typedExp(Component.getImplicitBinding(comp));
19731974
name := InstNode.name(component);
19741975

19751976
// Remove $in_ for OM input output arguments.

testsuite/flattening/modelica/scodeinst/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,9 @@ RecordBinding4.mo \
712712
RecordBinding5.mo \
713713
RecordBinding6.mo \
714714
RecordBinding7.mo \
715+
RecordBinding8.mo \
715716
RecordConstructor1.mo \
717+
RecordConstructor2.mo \
716718
RecordExtends1.mo \
717719
RecordExtends2.mo \
718720
RecordUnknownDim1.mo \
@@ -882,7 +884,6 @@ OCGTests.mos \
882884
# test that currently fail. Move up when fixed.
883885
# Run make testfailing
884886
FAILINGTESTFILES=\
885-
RecordConstructor2.mo \
886887
FinalParameter1.mo \
887888
FinalParameter2.mo \
888889
FinalParameter3.mo \
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// name: RecordBinding8
2+
// keywords:
3+
// status: correct
4+
// cflags: -d=newInst
5+
//
6+
7+
record R1
8+
Real x = 1.0;
9+
end R1;
10+
11+
record R2
12+
R1 r1;
13+
end R2;
14+
15+
function f
16+
input R2 r2;
17+
output Real x = r2.r1.x;
18+
end f;
19+
20+
model RecordBinding8
21+
Real x;
22+
equation
23+
x = f();
24+
end RecordBinding8;
25+
26+
// Result:
27+
// class RecordBinding8
28+
// Real x;
29+
// equation
30+
// x = 1.0;
31+
// end RecordBinding8;
32+
// endResult

testsuite/flattening/modelica/scodeinst/RecordConstructor2.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ end RecordConstructor2;
2929
// Real r.x;
3030
// constant Real r.y = 1.0;
3131
// algorithm
32-
// r := R(time);
32+
// r := R(time, 1.0);
3333
// end RecordConstructor2;
3434
// endResult

0 commit comments

Comments
 (0)