Skip to content

Commit

Permalink
[NF] Initial partial function application support.
Browse files Browse the repository at this point in the history
- Implemented handling of partial function applications.
- Changed TypeMatch.matchExpressions to handle type checking/casting by
  itself instead of relying on matchTypes, since matchTypes assumes a
  strict actual/expected relation between the types which is not the
  case for matchExpressions. This could e.g. lead to inconsistent
  boxing/unboxing of expressions depending on which side of a binary
  expression a boxed expression appeared on.
- Replaced all usage of intBitOr/intBitAnd for ExpOrigin flags with
  ExpOrigin.setFlag/flagSet.

Belonging to [master]:
  - OpenModelica/OMCompiler#2797
  - OpenModelica/OpenModelica-testsuite#1080
  • Loading branch information
perost authored and OpenModelica-Hudson committed Nov 23, 2018
1 parent 0fa8007 commit 17cf378
Show file tree
Hide file tree
Showing 10 changed files with 568 additions and 171 deletions.
22 changes: 11 additions & 11 deletions Compiler/NFFrontEnd/NFBuiltinCall.mo
Expand Up @@ -531,7 +531,7 @@ protected
end if;

// pre/change may not be used in a function context.
if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
{ComponentRef.toString(fn_ref)}, info);
end if;
Expand Down Expand Up @@ -570,7 +570,7 @@ protected
Type ety;
algorithm
// der may not be used in a function context.
if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessage(Error.EXP_INVALID_IN_FUNCTION, {"der"}, info);
fail();
end if;
Expand Down Expand Up @@ -659,7 +659,7 @@ protected
CallAttributes ca;
algorithm
// edge may not be used in a function context.
if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessage(Error.EXP_INVALID_IN_FUNCTION, {"edge"}, info);
fail();
end if;
Expand Down Expand Up @@ -950,7 +950,7 @@ protected
{fn} := Function.typeRefCache(fnRef);
ty := Type.liftArrayLeftList(fillType, dims);

if evaluated and intBitAnd(origin, ExpOrigin.FUNCTION) == 0 then
if evaluated and ExpOrigin.flagNotSet(origin, ExpOrigin.FUNCTION) then
callExp := Ceval.evalBuiltinFill(ty_args);
else
callExp := Expression.CALL(Call.makeTypedCall(NFBuiltinFuncs.FILL_FUNC, ty_args, variability, ty));
Expand Down Expand Up @@ -1286,7 +1286,7 @@ protected
{Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector) => Integer"}, info);
end if;

if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
{ComponentRef.toString(fn_ref)}, info);
end if;
Expand Down Expand Up @@ -1334,7 +1334,7 @@ protected
{Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector, Connector)"}, info);
end if;

if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
{ComponentRef.toString(fn_ref)}, info);
end if;
Expand Down Expand Up @@ -1373,7 +1373,7 @@ protected
{Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector)"}, info);
end if;

if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
{ComponentRef.toString(fn_ref)}, info);
end if;
Expand Down Expand Up @@ -1421,7 +1421,7 @@ protected
{Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector, Integer = 0)"}, info);
end if;

if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
{ComponentRef.toString(fn_ref)}, info);
end if;
Expand Down Expand Up @@ -1471,7 +1471,7 @@ protected
{Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector)"}, info);
end if;

if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
{ComponentRef.toString(fn_ref)}, info);
end if;
Expand Down Expand Up @@ -1506,7 +1506,7 @@ protected
{Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector)"}, info);
end if;

if intBitAnd(origin, ExpOrigin.FUNCTION) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FUNCTION) then
Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
{ComponentRef.toString(fn_ref)}, info);
end if;
Expand Down Expand Up @@ -1588,7 +1588,7 @@ protected
end if;

{arg} := args;
(arg, ty, variability) := Typing.typeExp(arg, intBitOr(origin, ExpOrigin.NOEVENT), info);
(arg, ty, variability) := Typing.typeExp(arg, ExpOrigin.setFlag(origin, ExpOrigin.NOEVENT), info);

{fn} := Function.typeRefCache(fn_ref);
callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, variability, ty));
Expand Down
3 changes: 3 additions & 0 deletions Compiler/NFFrontEnd/NFCall.mo
Expand Up @@ -1054,10 +1054,13 @@ protected
list<TypedArg> typedArgs;
list<TypedNamedArg> typedNamedArgs;
String name;
ExpOrigin.Type next_origin;

case UNTYPED_CALL()
algorithm
typedArgs := {};
next_origin := ExpOrigin.setFlag(origin, ExpOrigin.SUBEXPRESSION);

for arg in call.arguments loop
(arg, arg_ty, arg_var) := Typing.typeExp(arg, origin, info);
typedArgs := (arg, arg_ty, arg_var) :: typedArgs;
Expand Down
83 changes: 71 additions & 12 deletions Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -48,6 +48,7 @@ protected
import TypeCheck = NFTypeCheck;
import ValuesUtil;
import MetaModelica.Dangerous.listReverseInPlace;
import Types;

public
import Absyn.Path;
Expand Down Expand Up @@ -306,6 +307,13 @@ public
ClockKind clk "Clock kinds";
end CLKCONST;

record PARTIAL_FUNCTION_APPLICATION
ComponentRef fn;
list<Expression> args;
list<String> argNames;
Type ty;
end PARTIAL_FUNCTION_APPLICATION;

function isArray
input Expression exp;
output Boolean isArray;
Expand Down Expand Up @@ -631,6 +639,17 @@ public
then
comp;

case PARTIAL_FUNCTION_APPLICATION()
algorithm
PARTIAL_FUNCTION_APPLICATION(fn = cr, args = expl) := exp2;
comp := ComponentRef.compare(exp1.fn, cr);

if comp == 0 then
comp := compareList(exp1.args, expl);
end if;
then
comp;

else
algorithm
Error.assertion(false, getInstanceName() + " got unknown expression.", sourceInfo());
Expand Down Expand Up @@ -712,10 +731,11 @@ public
case UNBOX() then exp.ty;
case SUBSCRIPTED_EXP() then exp.ty;
case TUPLE_ELEMENT() then exp.ty;
case RECORD_ELEMENT() then exp.ty;
case RECORD_ELEMENT() then exp.ty;
case BOX() then Type.METABOXED(typeOf(exp.exp));
case MUTABLE() then typeOf(Mutable.access(exp.exp));
case EMPTY() then exp.ty;
case PARTIAL_FUNCTION_APPLICATION() then exp.ty;
else Type.UNKNOWN();
end match;
end typeOf;
Expand All @@ -742,7 +762,8 @@ public
case UNBOX() algorithm exp.ty := ty; then ();
case SUBSCRIPTED_EXP() algorithm exp.ty := ty; then ();
case TUPLE_ELEMENT() algorithm exp.ty := ty; then ();
case RECORD_ELEMENT() algorithm exp.ty := ty; then ();
case RECORD_ELEMENT() algorithm exp.ty := ty; then ();
case PARTIAL_FUNCTION_APPLICATION() algorithm exp.ty := ty; then ();
else ();
end match;
end setType;
Expand Down Expand Up @@ -1376,6 +1397,9 @@ public
case RECORD_ELEMENT() then toString(exp.recordExp) + "[field: " + exp.fieldName + "]";
case MUTABLE() then toString(Mutable.access(exp.exp));
case EMPTY() then "#EMPTY#";
case PARTIAL_FUNCTION_APPLICATION()
then "function " + ComponentRef.toString(exp.fn) + "(" + stringDelimitList(
list(n + " = " + Expression.toString(a) threaded for a in exp.args, n in exp.argNames), ", ") + ")";

else anyString(exp);
end match;
Expand Down Expand Up @@ -1457,7 +1481,7 @@ public
Boolean swap;
DAE.Exp dae1, dae2;
list<String> names;
ClockKind clk;
Function.Function fn;

case INTEGER() then DAE.ICONST(exp.value);
case REAL() then DAE.RCONST(exp.value);
Expand All @@ -1466,8 +1490,8 @@ public
case ENUM_LITERAL(ty = ty as Type.ENUMERATION())
then DAE.ENUM_LITERAL(Absyn.suffixPath(ty.typePath, exp.name), exp.index);

case CLKCONST(clk)
then DAE.CLKCONST(ClockKind.toDAE(clk));
case CLKCONST()
then DAE.CLKCONST(ClockKind.toDAE(exp.clk));

case CREF()
then DAE.CREF(ComponentRef.toDAE(exp.cref), Type.toDAE(exp.ty));
Expand Down Expand Up @@ -1541,6 +1565,15 @@ public
case RECORD_ELEMENT()
then DAE.RSUB(toDAE(exp.recordExp), exp.index, exp.fieldName, Type.toDAE(exp.ty));

case PARTIAL_FUNCTION_APPLICATION()
algorithm
fn :: _ := Function.Function.typeRefCache(exp.fn);
then
DAE.PARTEVALFUNCTION(Function.Function.nameConsiderBuiltin(fn),
list(toDAE(arg) for arg in exp.args),
Type.toDAE(exp.ty),
Type.toDAE(Type.FUNCTION(fn, NFType.FunctionType.FUNCTIONAL_VARIABLE)));

else
algorithm
Error.assertion(false, getInstanceName() + " got unknown expression '" + toString(exp) + "'", sourceInfo());
Expand Down Expand Up @@ -1771,6 +1804,12 @@ public
then
exp;

case PARTIAL_FUNCTION_APPLICATION()
algorithm
exp.args := list(map(e, func) for e in exp.args);
then
exp;

else exp;
end match;

Expand Down Expand Up @@ -2103,6 +2142,12 @@ public
then
exp;

case PARTIAL_FUNCTION_APPLICATION()
algorithm
exp.args := list(func(e) for e in exp.args);
then
exp;

else exp;
end match;
end mapShallow;
Expand Down Expand Up @@ -2395,6 +2440,7 @@ public
case RECORD_ELEMENT() then fold(exp.recordExp, func, arg);
case BOX() then fold(exp.exp, func, arg);
case MUTABLE() then fold(Mutable.access(exp.exp), func, arg);
case PARTIAL_FUNCTION_APPLICATION() then foldList(exp.args, func, arg);
else arg;
end match;

Expand Down Expand Up @@ -2651,6 +2697,7 @@ public
case RECORD_ELEMENT() algorithm apply(exp.recordExp, func); then ();
case BOX() algorithm apply(exp.exp, func); then ();
case MUTABLE() algorithm apply(Mutable.access(exp.exp), func); then ();
case PARTIAL_FUNCTION_APPLICATION() algorithm applyList(exp.args, func); then ();
else ();
end match;

Expand Down Expand Up @@ -2978,6 +3025,13 @@ public
then
exp;

case PARTIAL_FUNCTION_APPLICATION()
algorithm
(expl, arg) := List.map1Fold(exp.args, mapFold, func, arg);
exp.args := expl;
then
exp;

else exp;
end match;

Expand Down Expand Up @@ -3297,6 +3351,13 @@ public
then
exp;

case PARTIAL_FUNCTION_APPLICATION()
algorithm
(expl, arg) := List.mapFold(exp.args, func, arg);
exp.args := expl;
then
exp;

else exp;
end match;
end mapFoldShallow;
Expand Down Expand Up @@ -3597,12 +3658,9 @@ public
case SUBSCRIPTED_EXP()
then contains(exp.exp, func) or Subscript.listContainsExp(exp.subscripts, func);

case TUPLE_ELEMENT()
then contains(exp.tupleExp, func);

case RECORD_ELEMENT()
then contains(exp.recordExp, func);

case TUPLE_ELEMENT() then contains(exp.tupleExp, func);
case RECORD_ELEMENT() then contains(exp.recordExp, func);
case PARTIAL_FUNCTION_APPLICATION() then listContains(exp.args, func);
case BOX() then contains(exp.exp, func);
else false;
end match;
Expand Down Expand Up @@ -3778,7 +3836,7 @@ public
input ExpOrigin.Type origin;
output Boolean iter;
algorithm
if intBitAnd(origin, ExpOrigin.FOR) > 0 then
if ExpOrigin.flagSet(origin, ExpOrigin.FOR) then
iter := contains(exp, isIterator);
else
iter := false;
Expand Down Expand Up @@ -4270,6 +4328,7 @@ public
case TUPLE_ELEMENT() then variability(exp.tupleExp);
case RECORD_ELEMENT() then variability(exp.recordExp);
case BOX() then variability(exp.exp);
case PARTIAL_FUNCTION_APPLICATION() then Variability.CONTINUOUS;
else
algorithm
Error.assertion(false, getInstanceName() + " got unknown expression.", sourceInfo());
Expand Down
8 changes: 8 additions & 0 deletions Compiler/NFFrontEnd/NFFlatten.mo
Expand Up @@ -1498,6 +1498,14 @@ algorithm
then
();

case Expression.PARTIAL_FUNCTION_APPLICATION()
algorithm
for f in Function.getRefCache(exp.fn) loop
funcs := flattenFunction(f, funcs);
end for;
then
();

else ();
end match;
end collectExpFuncs_traverse;
Expand Down

0 comments on commit 17cf378

Please sign in to comment.