Skip to content
This repository has been archived by the owner on May 18, 2019. It is now read-only.

Commit

Permalink
[NF] Operator overloading support.
Browse files Browse the repository at this point in the history
  -  Initial operator overloading support for the new front-end.

  - Some error messaages and extra checks needs improvments.
  - A few other minor modifications.
    - new type-matching type PLUG_COMAPTIBLE.
      - used when matching is possible on a component basis.
    - use different matching rules for different cases.
      - e.g matchings allowed for assignments are different from matchings allowed for arguments.
      - needs more improvment.
    - Type 'String' calls as special builtin.
    - ...

Belonging to [master]:
  - #2235
  - OpenModelica/OpenModelica-testsuite#860
  • Loading branch information
mahge authored and OpenModelica-Hudson committed Feb 26, 2018
1 parent 983f52f commit f570c07
Show file tree
Hide file tree
Showing 12 changed files with 734 additions and 318 deletions.
8 changes: 4 additions & 4 deletions Compiler/NFFrontEnd/NFBuiltin.mo
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ constant InstNode STRING_NODE = InstNode.CLASS_NODE("String",
Pointer.createImmutable(Class.PARTIAL_BUILTIN(Type.STRING(), NFClassTree.EMPTY,
Modifier.NOMOD(), Restriction.TYPE())),
listArray({ NFInstNode.CachedData.FUNCTION({
NFBuiltinFuncs.STRING_ENUM, NFBuiltinFuncs.STRING_INT,
NFBuiltinFuncs.STRING_BOOL, NFBuiltinFuncs.STRING_REAL,
NFBuiltinFuncs.STRING_REAL_FORMAT
NFBuiltinFuncs.STRING_ENUM, NFBuiltinFuncs.STRING_INT,
NFBuiltinFuncs.STRING_BOOL, NFBuiltinFuncs.STRING_REAL,
NFBuiltinFuncs.STRING_REAL_FORMAT
},
true, false),
true, true),
NFInstNode.CachedData.NO_CACHE(),
NFInstNode.CachedData.NO_CACHE()}
),
Expand Down
169 changes: 112 additions & 57 deletions Compiler/NFFrontEnd/NFCall.mo
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ uniontype Call
record TYPED_CALL
Function fn;
Type ty;
Variability var;
list<Expression> arguments;
CallAttributes attributes;
end TYPED_CALL;
Expand Down Expand Up @@ -367,6 +368,7 @@ uniontype Call
UNTYPED_CALL(ref = cref) := call;

(callExp, ty, variability) := match ComponentRef.firstName(cref)
case "String" then typeStringCall(call, origin, info);
case "cardinality" then typeCardinalityCall(call, origin, info);
case "change" then typeChangeCall(call, origin, info);
case "der" then typeDerCall(call, origin, info);
Expand Down Expand Up @@ -426,6 +428,12 @@ uniontype Call
callExp := Expression.CALL(call);
then
();
case Expression.CALL(call as TYPED_CALL())
algorithm
ty := call.ty;
variability := call.var;
then
();
end match;
end typeCall;

Expand Down Expand Up @@ -517,7 +525,6 @@ uniontype Call
case ComponentRef.CREF(node = fn_node)
algorithm
CachedData.FUNCTION(functions, typed, special) := InstNode.getFuncCache(fn_node);

// Type the function(s) if not already done.
if not typed then
functions := list(Function.typeFunction(f) for f in functions);
Expand Down Expand Up @@ -554,16 +561,14 @@ uniontype Call
case ARG_TYPED_CALL() algorithm

// Match the arguments with the expected ones.
(fn,tyArgs) := matchFunctions(argtycall,info);
(fn,tyArgs) := checkMatchingFunctions(argtycall,info);

args := list(Util.tuple31(a) for a in tyArgs);

variability := Variability.CONSTANT;
for a in tyArgs loop
variability := Prefixes.variabilityMax(variability, Util.tuple33(a));
end for;

// Construct the call expression.
ty := Function.returnType(fn);

if intBitAnd(origin, ExpOrigin.FUNCTION) == 0 then
Expand All @@ -576,7 +581,7 @@ uniontype Call
, Function.inlineBuiltin(fn), DAE.NO_TAIL()
);
then
(TYPED_CALL(fn, ty, args, ca), ty, variability);
(TYPED_CALL(fn, ty, variability, args, ca), ty, variability);

else algorithm
Error.assertion(false, getInstanceName() + " got invalid function call expression", sourceInfo());
Expand Down Expand Up @@ -720,37 +725,28 @@ uniontype Call
end match;
end typeArgs;

function matchFunctions
function checkMatchingFunctions
input Call call;
input SourceInfo info;
output Function outFunc;
output list<TypedArg> args;
protected
list<FunctionMatchKind.MatchedFunction> matchedFunctions, exactMatches;
Boolean typematched, has_cast;
list<Function> allfuncs, matchingFuncs;
list<Function> allfuncs;
InstNode fn_node;
FunctionMatchKind matchKind;
Absyn.Path ov_name;
Integer numerr = Error.getNumErrorMessages();
algorithm
ErrorExt.setCheckpoint("NFCall:matchFunctions");
matchingFuncs := {};
ErrorExt.setCheckpoint("NFCall:checkMatchingFunctions");
matchedFunctions := {};

_ := match call
case ARG_TYPED_CALL(ref = ComponentRef.CREF(node = fn_node)) algorithm
ov_name := ComponentRef.toPath(call.ref);
allfuncs := Function.getCachedFuncs(fn_node);
for fn in allfuncs loop

(args, typematched, matchKind) := matchFunction(fn, call.arguments, call.named_args, info);

if typematched then
matchedFunctions := (fn,args,matchKind)::matchedFunctions;
matchingFuncs := fn::matchingFuncs;
end if;
end for;
matchedFunctions := Function.matchFunctions(allfuncs, call.arguments, call.named_args, info);
then
();
end match;
Expand All @@ -759,9 +755,9 @@ uniontype Call
// implementation details and usually doesn't provide any more info than
// what the "no match found" error gives anyway.
if listLength(allfuncs) > 1 then
ErrorExt.rollBack("NFCall:matchFunctions");
ErrorExt.rollBack("NFCall:checkMatchingFunctions");
else
ErrorExt.delCheckpoint("NFCall:matchFunctions");
ErrorExt.delCheckpoint("NFCall:checkMatchingFunctions");
end if;

if listEmpty(matchedFunctions) then
Expand Down Expand Up @@ -808,15 +804,13 @@ uniontype Call
end if;
return;
else
// TODO: FIX ME: Add proper error message.
print("Ambiguous call: " + toString(call) + "\nCandidates:\n ");
print(candidateFuncListString(matchingFuncs,SOME(ov_name)));
print("\n");
Error.addSourceMessage(Error.AMBIGUOUS_MATCHING_FUNCTIONS_NFINST,
{typedString(call), candidateFuncListString(list(Util.tuple31(fn) for fn in matchedFunctions),SOME(ov_name))}, info);
fail();
end if;
end if;

end matchFunctions;
end checkMatchingFunctions;

function typeOf
input Call call;
Expand All @@ -839,24 +833,6 @@ uniontype Call
end match;
end setType;


protected
function matchFunction
input Function func;
input list<TypedArg> args;
input list<TypedNamedArg> named_args;
input SourceInfo info;
output list<TypedArg> out_args;
output Boolean matched;
output FunctionMatchKind matchKind;
algorithm
(out_args, matched) := Function.fillArgs(args, named_args, func, info);
if matched then
(out_args, matched, matchKind) := Function.matchArgs(func, out_args, info);
end if;
end matchFunction;

public
function arguments
input Call call;
output list<Expression> arguments;
Expand Down Expand Up @@ -1098,9 +1074,10 @@ protected
argument expressions."
input Function func;
input list<Expression> args;
input Variability var = Variability.CONSTANT;
output Call call;
algorithm
call := TYPED_CALL(func, func.returnType, args,
call := TYPED_CALL(func, func.returnType, var, args,
CallAttributes.CALL_ATTR(func.returnType, false, true, false, false,
DAE.NO_INLINE(), DAE.NO_TAIL()));
end makeBuiltinCall;
Expand All @@ -1112,13 +1089,90 @@ protected
input Function func;
input list<Expression> args;
input Type returnType; // you can use func.returnType if the buiting function is defined with the corrrect type.
input Variability var = Variability.CONSTANT; // :( We don't have variability info in the arg expressions.
output Call call;
algorithm
call := TYPED_CALL(func, returnType, args,
call := TYPED_CALL(func, returnType, var, args,
CallAttributes.CALL_ATTR(returnType, false, true, false, false,
DAE.NO_INLINE(), DAE.NO_TAIL()));
end makeBuiltinCall2;

function typeStringCall
input Call call;
input ExpOrigin.Type origin;
input SourceInfo info;
output Expression callExp;
output Type outType;
output Variability var;
protected
Call argtycall;
Function operfn;
list<TypedArg> args;
list<TypedNamedArg> named_args;
Type argty;
Expression exp;
ComponentRef fn_ref;
list<Function> candidates;
Boolean matched;
InstNode recopnode;
FunctionMatchKind matchKind;
list<FunctionMatchKind.MatchedFunction> matchedFunctions, exactMatches;
algorithm
argtycall as ARG_TYPED_CALL(_, args, named_args) := typeNormalCall(call, origin, info);
(exp, argty, _)::_ := args;

candidates := {};
matchedFunctions := {};
if Type.isComplex(Type.arrayElementType(argty)) then
Type.COMPLEX(cls=recopnode) := argty;
ErrorExt.setCheckpoint("NFTypeCheck:operatorOverloadDefined");
try
fn_ref := Function.lookupFunction(Absyn.CREF_IDENT("'String'",{}), recopnode, InstNode.info(recopnode));
ErrorExt.delCheckpoint("NFTypeCheck:operatorOverloadDefined");
else
ErrorExt.rollBack("NFTypeCheck:operatorOverloadDefined");
fail();
end try;

fn_ref := Function.instFuncRef(fn_ref, InstNode.info(recopnode));
candidates := Call.typeCachedFunctions(fn_ref);
for fn in candidates loop
TypeCheck.checkValidOperatorOverload("'String'", fn, recopnode);
end for;

ErrorExt.setCheckpoint("NFCall:typeStringCall");
matchedFunctions := Function.matchFunctions(candidates, args, named_args, info);
ErrorExt.rollBack("NFCall:typeStringCall");

exactMatches := FunctionMatchKind.getExactMatches(matchedFunctions);
if listEmpty(exactMatches) then
Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
{typedString(argtycall), candidateFuncListString(candidates,NONE())}, info);
fail();
end if;

if listLength(exactMatches) == 1 then
(operfn,args,_) ::_ := exactMatches;
outType := Function.returnType(operfn);
callExp := Expression.CALL(Call.TYPED_CALL(operfn, outType, Variability.CONSTANT, list(Util.tuple31(a) for a in args)
, CallAttributes.CALL_ATTR(
outType, false, false, false, false, DAE.NO_INLINE(),DAE.NO_TAIL())
)
);

return;
else
Error.addSourceMessage(Error.AMBIGUOUS_MATCHING_FUNCTIONS_NFINST,
{typedString(call), candidateFuncListString(list(Util.tuple31(fn) for fn in matchedFunctions),NONE())}, info);
fail();
end if;

end if;

(argtycall, outType, var) := matchTypedNormalCall(argtycall, origin, info);
callExp := Expression.CALL(argtycall);
end typeStringCall;

function typeDiscreteCall
"Types a function call that can be typed normally, but which always has
discrete variability regardless of the variability of the arguments."
Expand Down Expand Up @@ -1218,7 +1272,7 @@ protected
end if;

{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, var));
end typePreCall;

function typeChangeCall
Expand Down Expand Up @@ -1281,7 +1335,7 @@ protected
end if;

{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, variability));
end typeDerCall;

function typeDiagonalCall
Expand Down Expand Up @@ -1327,7 +1381,7 @@ protected
end match;

{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, variability));
end typeDiagonalCall;

function typeEdgeCall
Expand Down Expand Up @@ -1464,14 +1518,14 @@ protected
// TODO: Also handle records here.
(arg2, ty, mk) := TypeCheck.matchTypes(ty2, Type.setArrayElementType(ty2, Type.REAL()), arg2, true);

if not TypeCheck.isCompatibleMatch(mk) then
if not TypeCheck.isValidArgumentMatch(mk) then
Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
{"2", ComponentRef.toString(fn_ref), "", Expression.toString(arg2),
Type.toString(ty2), "Real\n Real[:, ...]\n Real record\n Real record[:, ...]"}, info);
end if;

{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg1, arg2}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg1, arg2}, ty, var));
end typeSmoothCall;

function typeFillCall
Expand Down Expand Up @@ -1560,7 +1614,7 @@ protected
if variability <= Variability.PARAMETER and intBitAnd(origin, ExpOrigin.FUNCTION) == 0 then
callExp := Ceval.evalBuiltinCall(fn, ty_args, Ceval.EvalTarget.IGNORE_ERRORS());
else
callExp := Expression.CALL(makeBuiltinCall2(fn, ty_args, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, ty_args, ty, variability));
end if;
end typeFillCall2;

Expand Down Expand Up @@ -1633,7 +1687,7 @@ protected

ty := Type.arrayElementType(ty);
{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, variability));
end typeScalarCall;

function typeVectorCall
Expand Down Expand Up @@ -1691,7 +1745,7 @@ protected

ty := Type.ARRAY(Type.arrayElementType(ty), {Dimension.INTEGER(dim_size)});
{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, variability));
end typeVectorCall;

function typeMatrixCall
Expand Down Expand Up @@ -1751,7 +1805,7 @@ protected

ty := Type.ARRAY(Type.arrayElementType(ty), dims);
{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, variability));
end typeMatrixCall;

function typeSymmetricCall
Expand Down Expand Up @@ -1789,7 +1843,7 @@ protected
end if;

{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, variability));
end typeSymmetricCall;

function typeTransposeCall
Expand Down Expand Up @@ -1836,7 +1890,7 @@ protected
end match;

{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, variability));
end typeTransposeCall;

function typeCardinalityCall
Expand Down Expand Up @@ -1891,7 +1945,7 @@ protected
(arg, ty, variability) := Typing.typeExp(arg, intBitOr(origin, ExpOrigin.NOEVENT), info);

{fn} := typeCachedFunctions(fn_ref);
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty));
callExp := Expression.CALL(makeBuiltinCall2(fn, {arg}, ty, variability));
end typeNoEventCall;

function unboxArgs
Expand All @@ -1906,6 +1960,7 @@ protected
end match;
end unboxArgs;

public
function candidateFuncListString
input list<Function> fns;
input Option<Absyn.Path> overload_name;
Expand Down
Loading

0 comments on commit f570c07

Please sign in to comment.