Skip to content

Commit

Permalink
[NF] Function improvements/cleanup.
Browse files Browse the repository at this point in the history
- Refactored handling of builtin functions with special rules into a new
  package NFBuiltinCall.
- Cleaned up NFCall a bit.
- Removed default variability argument from BuiltinCall.makeCall and
  fixed all calls to it to give the actual variability instead of just
  setting it to constant.
- Implemented some basic handling of functional formal parameters.
- Fixed handling of String function so that it doesn't fail without
  error for a non-basic argument without a 'String' overload.

Belonging to [master]:
  - OpenModelica/OMCompiler#2481
  - OpenModelica/OpenModelica-testsuite#966
  • Loading branch information
perost authored and OpenModelica-Hudson committed May 30, 2018
1 parent 6f42885 commit 6609484
Show file tree
Hide file tree
Showing 12 changed files with 2,450 additions and 2,355 deletions.
1,516 changes: 1,516 additions & 0 deletions Compiler/NFFrontEnd/NFBuiltinCall.mo

Large diffs are not rendered by default.

3,001 changes: 735 additions & 2,266 deletions Compiler/NFFrontEnd/NFCall.mo

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions Compiler/NFFrontEnd/NFConnectEquations.mo
Expand Up @@ -61,6 +61,7 @@ import NFClass.Class;
import NFBinding.Binding;
import NFFunction.Function;
import Global;
import BuiltinCall = NFBuiltinCall;

constant Expression EQ_ASSERT_STR =
Expression.STRING("Connected constants/parameters must be equal");
Expand Down Expand Up @@ -209,7 +210,7 @@ algorithm
// Modelica doesn't allow == for Reals, so to keep the flat Modelica
// somewhat valid we use 'abs(lhs - rhs) <= 0' instead.
exp := Expression.BINARY(lhs_exp, Operator.makeSub(ty), rhs_exp);
exp := Expression.CALL(Call.makeBuiltinCall(NFBuiltinFuncs.ABS_REAL, {exp}));
exp := Expression.CALL(BuiltinCall.makeCall(NFBuiltinFuncs.ABS_REAL, {exp}, Expression.variability(exp)));
exp := Expression.RELATION(exp, Operator.makeLessEq(ty), Expression.REAL(0.0));
else
// For any other type, generate assertion for 'lhs == rhs'.
Expand Down Expand Up @@ -295,6 +296,7 @@ algorithm
DAE.ElementSource src, src1, src2;
Expression cref1, cref2, e1, e2;
list<Connector> inside, outside;
Variability var1, var2;

// Unconnected stream connector, do nothing.
case ({Connector.CONNECTOR(face = Face.INSIDE)}) then {};
Expand Down Expand Up @@ -508,7 +510,8 @@ function makeInStreamCall
output Expression inStreamCall;
annotation(__OpenModelica_EarlyInline = true);
algorithm
inStreamCall := Expression.CALL(Call.makeBuiltinCall(NFBuiltinFuncs.IN_STREAM, {streamExp}));
inStreamCall := Expression.CALL(BuiltinCall.makeCall(
NFBuiltinFuncs.IN_STREAM, {streamExp}, Expression.variability(streamExp)));
end makeInStreamCall;

function makePositiveMaxCall
Expand All @@ -532,8 +535,8 @@ algorithm
flow_threshold := flowThreshold;
end if;

positiveMaxCall := Expression.CALL(Call.makeBuiltinCall(NFBuiltinFuncs.POSITIVE_MAX_REAL,
{flowExp, flow_threshold}));
positiveMaxCall := Expression.CALL(BuiltinCall.makeCall(NFBuiltinFuncs.POSITIVE_MAX_REAL,
{flowExp, flow_threshold}, Connector.variability(element)));

setGlobalRoot(Global.isInStream, SOME(true));
end makePositiveMaxCall;
Expand Down
6 changes: 4 additions & 2 deletions Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -36,6 +36,7 @@ protected
import List;

import Builtin = NFBuiltin;
import BuiltinCall = NFBuiltinCall;
import Expression = NFExpression;
import Function = NFFunction;
import RangeIterator = NFRangeIterator;
Expand Down Expand Up @@ -3104,7 +3105,8 @@ public
// An expression with array type, but which is not an array expression.
// Such an expression can't be promoted here, so we create a promote call instead.
case (_, _) guard isArray
then CALL(Call.makeBuiltinCall2(NFBuiltinFuncs.PROMOTE, {exp, INTEGER(dims)}, listHead(types)));
then CALL(BuiltinCall.makeCall2(
NFBuiltinFuncs.PROMOTE, {exp, INTEGER(dims)}, listHead(types), variability(exp)));

// A scalar expression, promote it as many times as the number of types given.
else
Expand Down Expand Up @@ -3262,7 +3264,7 @@ public
algorithm
indexExp := match enumExp
case ENUM_LITERAL() then INTEGER(enumExp.index);
else CALL(Call.makeBuiltinCall(
else CALL(BuiltinCall.makeCall(
NFBuiltinFuncs.INTEGER_ENUM, {enumExp}, variability(enumExp)));
end match;
end enumIndexExp;
Expand Down
43 changes: 41 additions & 2 deletions Compiler/NFFrontEnd/NFFunction.mo
Expand Up @@ -295,7 +295,7 @@ uniontype Function
CachedData cache;
algorithm
// Look up the function.
fn_node := ComponentRef.node(fn_ref);
fn_node := InstNode.classScope(ComponentRef.node(fn_ref));
cache := InstNode.getFuncCache(fn_node);

// Check if a cached instantiation of this function already exists.
Expand Down Expand Up @@ -408,7 +408,7 @@ uniontype Function
protected
CachedData cache;
algorithm
cache := InstNode.getFuncCache(inNode);
cache := InstNode.getFuncCache(InstNode.classScope(inNode));
outFuncs := match cache
case CachedData.FUNCTION() then cache.funcs;
else fail();
Expand Down Expand Up @@ -509,6 +509,11 @@ uniontype Function
str := Absyn.pathString(fn_name) + "(" + input_str + ")" + output_str;
end signatureString;

function candidateFuncListString
input list<Function> fns;
output String s = stringDelimitList(list(Function.signatureString(fn, true) for fn in fns), "\n ");
end candidateFuncListString;

function callString
"Constructs a string representing a call, for use in error messages."
input Function fn;
Expand Down Expand Up @@ -942,6 +947,40 @@ uniontype Function
end match;
end isTyped;

function typeRefCache
"Returns the function(s) referenced by the given cref, and types them if
they are not already typed."
input ComponentRef functionRef;
output list<Function> functions;
protected
InstNode fn_node;
Boolean typed, special;
String name;
algorithm
functions := match functionRef
case ComponentRef.CREF(node = fn_node)
algorithm
fn_node := InstNode.classScope(fn_node);
CachedData.FUNCTION(functions, typed, special) := InstNode.getFuncCache(fn_node);

// Type the function(s) if not already done.
if not typed then
functions := list(typeFunctionSignature(f) for f in functions);
InstNode.setFuncCache(fn_node, CachedData.FUNCTION(functions, true, special));
functions := list(typeFunctionBody(f) for f in functions);
InstNode.setFuncCache(fn_node, CachedData.FUNCTION(functions, true, special));
end if;
then
functions;

else
algorithm
Error.assertion(false, getInstanceName() + " got invalid function call reference", sourceInfo());
then
fail();
end match;
end typeRefCache;

function typeFunction
input output Function fn;
algorithm
Expand Down
154 changes: 101 additions & 53 deletions Compiler/NFFrontEnd/NFInst.mo
Expand Up @@ -1318,7 +1318,7 @@ algorithm
Component inst_comp;
InstNode ty_node;
Class ty;
Boolean use_binding;
Boolean use_binding, in_function;

case SCode.COMPONENT(info = info)
algorithm
Expand All @@ -1340,7 +1340,8 @@ algorithm
// Instantiate the component's attributes, and merge them with the
// attributes of the component's parent (e.g. constant SomeComplexClass c).
attr := instComponentAttributes(component.attributes, component.prefixes);
attr := mergeComponentAttributes(attributes, attr, node);
attr := mergeComponentAttributes(attributes, attr, node,
Class.isFunction(InstNode.getClass(parent)));

// Create the untyped component and update the node with it. We need the
// untyped component in instClass to make sure everything is scoped
Expand Down Expand Up @@ -1495,6 +1496,7 @@ function mergeComponentAttributes
input Component.Attributes outerAttr;
input Component.Attributes innerAttr;
input InstNode node;
input Boolean inFunction;
output Component.Attributes attr;
protected
ConnectorType cty;
Expand All @@ -1513,7 +1515,13 @@ algorithm
cty := Prefixes.mergeConnectorType(outerAttr.connectorType, innerAttr.connectorType, node);
par := Prefixes.mergeParallelism(outerAttr.parallelism, innerAttr.parallelism, node);
var := Prefixes.variabilityMin(outerAttr.variability, innerAttr.variability);
dir := Prefixes.mergeDirection(outerAttr.direction, innerAttr.direction, node);

if inFunction then
dir := innerAttr.direction;
else
dir := Prefixes.mergeDirection(outerAttr.direction, innerAttr.direction, node);
end if;

fin := outerAttr.isFinal or innerAttr.isFinal;
redecl := innerAttr.isRedeclare;
repl := innerAttr.isReplaceable;
Expand Down Expand Up @@ -2140,72 +2148,112 @@ algorithm

crefExp := match cref
case ComponentRef.CREF()
then
match cref.node
case InstNode.COMPONENT_NODE()
then instCrefComponent(cref, cref.node, found_scope, info);
case InstNode.CLASS_NODE()
then if Class.isFunction(InstNode.getClass(cref.node)) then
instCrefFunction(cref, info)
else
instCrefTypename(cref, cref.node, info);
else
algorithm
Error.assertion(false, getInstanceName() + " got invalid instance node", sourceInfo());
then
fail();
end match;

else Expression.CREF(Type.UNKNOWN(), cref);
end match;
end instCref;

function instCrefComponent
input ComponentRef cref;
input InstNode node;
input InstNode scope;
input SourceInfo info;
output Expression crefExp;
protected
Component comp;
ComponentRef prefixed_cref;
algorithm
comp := InstNode.component(node);

crefExp := match comp
case Component.ITERATOR()
algorithm
if InstNode.isComponent(cref.node) then
comp := InstNode.component(cref.node);
checkUnsubscriptableCref(cref, info);
then
Expression.CREF(Type.UNKNOWN(), ComponentRef.makeIterator(node, comp.ty));

crefExp := match comp
case Component.ITERATOR()
algorithm
checkUnsubscriptableCref(cref, cref.subscripts, info);
then
Expression.CREF(Type.UNKNOWN(), ComponentRef.makeIterator(cref.node, comp.ty));
case Component.ENUM_LITERAL()
algorithm
checkUnsubscriptableCref(cref, info);
then
comp.literal;

case Component.ENUM_LITERAL()
algorithm
checkUnsubscriptableCref(cref, cref.subscripts, info);
then
comp.literal;
case Component.TYPE_ATTRIBUTE()
algorithm
Error.addSourceMessage(Error.LOOKUP_VARIABLE_ERROR,
{InstNode.name(node), InstNode.name(InstNode.parent(node))}, info);
then
fail();

case Component.TYPE_ATTRIBUTE()
algorithm
Error.addSourceMessage(Error.LOOKUP_VARIABLE_ERROR,
{Dump.printComponentRefStr(absynCref), InstNode.name(scope)}, info);
then
fail();
else
algorithm
prefixed_cref := ComponentRef.fromNodeList(InstNode.scopeList(scope));
prefixed_cref := if ComponentRef.isEmpty(prefixed_cref) then
cref else ComponentRef.append(cref, prefixed_cref);
then
Expression.CREF(Type.UNKNOWN(), prefixed_cref);

else
algorithm
prefixed_cref := ComponentRef.fromNodeList(InstNode.scopeList(found_scope));
prefixed_cref := if ComponentRef.isEmpty(prefixed_cref) then
cref else ComponentRef.append(cref, prefixed_cref);
then
Expression.CREF(Type.UNKNOWN(), prefixed_cref);
end match;
end instCrefComponent;

end match;
else
checkUnsubscriptableCref(cref, cref.subscripts, info);
ty := InstNode.getType(cref.node);
function instCrefFunction
input ComponentRef cref;
input SourceInfo info;
output Expression crefExp;
protected
ComponentRef fn_ref;
algorithm
fn_ref := Function.instFuncRef(cref, info);
crefExp := Expression.CREF(Type.UNKNOWN(), fn_ref);
end instCrefFunction;

ty := match ty
case Type.BOOLEAN() then Type.ARRAY(ty, {Dimension.BOOLEAN()});
case Type.ENUMERATION() then Type.ARRAY(ty, {Dimension.ENUM(ty)});
else
algorithm
// This should be caught by lookupComponent, only type name classes
// are allowed to be used where a component is expected.
Error.assertion(false, getInstanceName() + " got unknown class node", sourceInfo());
then
fail();
end match;
function instCrefTypename
input ComponentRef cref;
input InstNode node;
input SourceInfo info;
output Expression crefExp;
protected
Type ty;
algorithm
checkUnsubscriptableCref(cref, info);
ty := InstNode.getType(node);

crefExp := Expression.TYPENAME(ty);
end if;
ty := match ty
case Type.BOOLEAN() then Type.ARRAY(ty, {Dimension.BOOLEAN()});
case Type.ENUMERATION() then Type.ARRAY(ty, {Dimension.ENUM(ty)});
else
algorithm
Error.assertion(false, getInstanceName() + " got unknown class node " +
InstNode.name(node), sourceInfo());
then
crefExp;

else Expression.CREF(Type.UNKNOWN(), cref);
fail();
end match;
end instCref;

crefExp := Expression.TYPENAME(ty);
end instCrefTypename;

function checkUnsubscriptableCref
input ComponentRef cref;
input list<Subscript> subscripts;
input SourceInfo info;
algorithm
if not listEmpty(subscripts) then
if ComponentRef.hasSubscripts(cref) then
Error.addSourceMessage(Error.WRONG_NUMBER_OF_SUBSCRIPTS,
{ComponentRef.toString(cref), String(listLength(subscripts)), "0"}, info);
{ComponentRef.toString(cref), String(listLength(ComponentRef.getSubscripts(cref))), "0"}, info);
fail();
end if;
end checkUnsubscriptableCref;
Expand Down

0 comments on commit 6609484

Please sign in to comment.