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

Commit

Permalink
[NF] Initial support for functional arguments.
Browse files Browse the repository at this point in the history
  • Loading branch information
perost authored and OpenModelica-Hudson committed Nov 5, 2018
1 parent c6038ff commit fbe0a66
Show file tree
Hide file tree
Showing 9 changed files with 367 additions and 50 deletions.
2 changes: 1 addition & 1 deletion Compiler/NFFrontEnd/NFCall.mo
Expand Up @@ -211,7 +211,7 @@ uniontype Call
if isRecordConstructor(ty_call) then
outExp := toRecordExpression(ty_call, ty);
else
if Function.hasUnboxArgs(InstNode.definition(ComponentRef.node(cref))) then
if Function.hasUnboxArgs(Call.typedFunction(ty_call)) then
outExp := Expression.CALL(Call.unboxArgs(ty_call));
else
outExp := Expression.CALL(ty_call);
Expand Down
3 changes: 2 additions & 1 deletion Compiler/NFFrontEnd/NFComponentRef.mo
Expand Up @@ -275,7 +275,8 @@ public
output Variability var;
algorithm
var := match cref
case CREF() then Component.variability(InstNode.component(cref.node));
case CREF(node = InstNode.COMPONENT_NODE())
then Component.variability(InstNode.component(cref.node));
else Variability.CONTINUOUS;
end match;
end nodeVariability;
Expand Down
21 changes: 20 additions & 1 deletion Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -3961,13 +3961,32 @@ public
end match;
end makeMinValue;

function box
input Expression exp;
output Expression boxedExp;
algorithm
boxedExp := match exp
case Expression.BOX() then exp;
else Expression.BOX(exp);
end match;
end box;

function unbox
input Expression boxedExp;
output Expression exp;
algorithm
exp := match boxedExp
local
Type ty;

case Expression.BOX() then boxedExp.exp;
else boxedExp;

else
algorithm
ty := Expression.typeOf(boxedExp);
then
if Type.isBoxed(ty) then Expression.UNBOX(boxedExp, Type.unbox(ty)) else boxedExp;

end match;
end unbox;

Expand Down
24 changes: 18 additions & 6 deletions Compiler/NFFrontEnd/NFFlatten.mo
Expand Up @@ -1477,12 +1477,21 @@ function collectExpFuncs_traverse
input output FunctionTree funcs;
algorithm
() := match exp
local
Function fn;

case Expression.CALL()
algorithm
funcs := flattenFunction(Call.typedFunction(exp.call), funcs);
then
();

case Expression.CREF(ty = Type.FUNCTION(fn = fn))
algorithm
funcs := flattenFunction(fn, funcs);
then
();

else ();
end match;
end collectExpFuncs_traverse;
Expand All @@ -1493,14 +1502,17 @@ function flattenFunction
algorithm
if not Function.isCollected(fn) then
Function.collect(fn);
funcs := FunctionTree.add(funcs, Function.name(fn), fn);
funcs := collectClassFunctions(fn.node, funcs);

for fn_der in fn.derivatives loop
for der_fn in Function.getCachedFuncs(fn_der.derivativeFn) loop
funcs := flattenFunction(der_fn, funcs);
if not InstNode.isPartial(fn.node) then
funcs := FunctionTree.add(funcs, Function.name(fn), fn);
funcs := collectClassFunctions(fn.node, funcs);

for fn_der in fn.derivatives loop
for der_fn in Function.getCachedFuncs(fn_der.derivativeFn) loop
funcs := flattenFunction(der_fn, funcs);
end for;
end for;
end for;
end if;
end if;
end flattenFunction;

Expand Down
104 changes: 91 additions & 13 deletions Compiler/NFFrontEnd/NFFunction.mo
Expand Up @@ -73,6 +73,7 @@ import Algorithm = NFAlgorithm;
import OperatorOverloading = NFOperatorOverloading;
import MetaModelica.Dangerous.listReverseInPlace;
import Array;
import ElementSource;


public
Expand Down Expand Up @@ -297,6 +298,7 @@ uniontype Function
LookupState state;
Absyn.Path functionPath;
ComponentRef prefix;
Boolean is_class;
algorithm
try
// Make sure the name is a path.
Expand All @@ -307,7 +309,10 @@ uniontype Function
end try;

(functionRef, found_scope) := Lookup.lookupFunctionName(functionName, scope, info);
prefix := ComponentRef.fromNodeList(InstNode.scopeList(InstNode.classScope(found_scope), includeRoot = true));
// If we found a function class we include the root in the prefix, but if we
// instead found a component (i.e. a functional parameter) we don't.
is_class := InstNode.isClass(ComponentRef.node(functionRef));
prefix := ComponentRef.fromNodeList(InstNode.scopeList(InstNode.classScope(found_scope), includeRoot = is_class));
functionRef := ComponentRef.append(functionRef, prefix);
end lookupFunction;

Expand Down Expand Up @@ -518,6 +523,13 @@ uniontype Function
output Absyn.Path path = fn.path;
end name;

function setName
input Absyn.Path name;
input output Function fn;
algorithm
fn.path := name;
end setName;

function nameConsiderBuiltin "Handles the DAE.mo structure where builtin calls are replaced by their simpler name"
input Function fn;
output Absyn.Path path;
Expand Down Expand Up @@ -607,6 +619,22 @@ uniontype Function
str := Absyn.pathString(fn.path) + "(" + str + ")";
end callString;

function typeString
"Constructs a string representing the type of the function, on the form
function_name<function>(input types) => output type"
input Function fn;
output String str;
algorithm
str := List.toString(fn.inputs, paramTypeString,
Absyn.pathString(name(fn)) + "<function>",
"(", ", ", ") => " + Type.toString(fn.returnType), true);
end typeString;

function paramTypeString
input InstNode param;
output String str = Type.toString(InstNode.getType(param));
end paramTypeString;

function instance
input Function fn;
output InstNode node = fn.node;
Expand Down Expand Up @@ -1190,10 +1218,14 @@ uniontype Function
algorithm
if not isTyped(fn) then
// Type all the components in the function.
Typing.typeClassType(node, NFBinding.EMPTY_BINDING, ExpOrigin.FUNCTION);
Typing.typeClassType(node, NFBinding.EMPTY_BINDING, ExpOrigin.FUNCTION, node);
Typing.typeComponents(node, ExpOrigin.FUNCTION);

// Type the binding of the inputs only. This is done because they are
if InstNode.isPartial(node) then
ClassTree.applyComponents(Class.classTree(InstNode.getClass(node)), boxFunctionParameter);
end if;

// Type the bindings of the inputs only. This is done because they are
// needed when type checking a function call. The outputs are not needed
// for that and can contain recursive calls to the function, so we leave
// them for later.
Expand Down Expand Up @@ -1231,6 +1263,16 @@ uniontype Function
end for;
end typeFunctionBody;

function boxFunctionParameter
input InstNode component;
protected
Component comp;
algorithm
comp := InstNode.component(component);
comp := Component.setType(Type.box(Component.getType(comp)), comp);
InstNode.updateComponent(comp, component);
end boxFunctionParameter;

function isBuiltin
input Function fn;
output Boolean isBuiltin = isBuiltinAttr(fn.attributes);
Expand Down Expand Up @@ -1346,6 +1388,18 @@ uniontype Function
output Boolean isPointer = fn.attributes.isFunctionPointer;
end isFunctionPointer;

function setFunctionPointer
input Boolean isPointer;
input output Function fn;
protected
DAE.FunctionAttributes attr = fn.attributes;
algorithm
attr.isFunctionPointer := isPointer;
fn.attributes := attr;
// The whole function should just be this, but it doesn't compile yet.
//fn.attributes.isFunctionPointer := isPointer;
end setFunctionPointer;

function isExternal
input Function fn;
output Boolean isExternal = not InstNode.isEmpty(fn.node) and
Expand Down Expand Up @@ -1391,7 +1445,8 @@ uniontype Function
ty := makeDAEType(fn);
defs := def :: list(FunctionDerivative.toDAE(fn_der) for fn_der in fn.derivatives);
daeFn := DAE.FUNCTION(fn.path, defs, ty, vis, par, impr, ity,
DAE.emptyElementSource, SCode.getElementComment(InstNode.definition(fn.node)));
ElementSource.createElementSource(InstNode.info(fn.node)),
SCode.getElementComment(InstNode.definition(fn.node)));
end toDAE;

function makeDAEType
Expand Down Expand Up @@ -1426,10 +1481,22 @@ uniontype Function
end getBody;

function hasUnboxArgs
"Returns true if the function has the __OpenModelica_UnboxArguments annotation, otherwise false."
input Function fn;
output Boolean res;
algorithm
res := match fn.attributes
case DAE.FunctionAttributes.FUNCTION_ATTRIBUTES(
isBuiltin = DAE.FunctionBuiltin.FUNCTION_BUILTIN(unboxArgs = res)) then res;
else false;
end match;
end hasUnboxArgs;

function hasUnboxArgsAnnotation
input SCode.Element def;
output Boolean res =
SCode.hasBooleanNamedAnnotationInClass(def, "__OpenModelica_UnboxArguments");
end hasUnboxArgs;
end hasUnboxArgsAnnotation;

function hasOptionalArgument
input SCode.Element component;
Expand Down Expand Up @@ -1490,6 +1557,11 @@ uniontype Function
end if;
end mapExpParameter;

function isPartial
input Function fn;
output Boolean isPartial = InstNode.isPartial(fn.node);
end isPartial;

protected
function collectParams
"Sorts all the function parameters as inputs, outputs and locals."
Expand Down Expand Up @@ -1661,17 +1733,19 @@ protected
array<InstNode> params;
SCode.Restriction res;
SCode.FunctionRestriction fres;
Boolean is_partial;
algorithm
def := InstNode.definition(node);
res := SCode.getClassRestriction(def);

Error.assertion(SCode.isFunctionRestriction(res), getInstanceName() + " got non-function restriction", sourceInfo());

SCode.Restriction.R_FUNCTION(functionRestriction = fres) := res;
is_partial := SCode.isPartial(def);

attr := matchcontinue fres
local
Boolean is_impure, is_om_pure, has_out_params;
Boolean is_impure, is_om_pure, has_out_params, has_unbox_args;
String name;
list<String> in_params, out_params;
DAE.InlineType inline_ty;
Expand All @@ -1685,9 +1759,10 @@ protected
name := SCode.isBuiltinFunction(def, in_params, out_params);
inline_ty := InstUtil.classIsInlineFunc(def);
is_impure := is_impure or hasImpure(def);
has_unbox_args := hasUnboxArgsAnnotation(def);
then
DAE.FUNCTION_ATTRIBUTES(inline_ty, hasOMPure(def), is_impure, false,
DAE.FUNCTION_BUILTIN(SOME(name), hasUnboxArgs(def)), DAE.FP_NON_PARALLEL());
DAE.FUNCTION_ATTRIBUTES(inline_ty, hasOMPure(def), is_impure, is_partial,
DAE.FUNCTION_BUILTIN(SOME(name), has_unbox_args), DAE.FP_NON_PARALLEL());

// Parallel function: there are some builtin functions.
case SCode.FunctionRestriction.FR_PARALLEL_FUNCTION()
Expand All @@ -1696,21 +1771,22 @@ protected
out_params := list(InstNode.name(o) for o in outputs);
name := SCode.isBuiltinFunction(def, in_params, out_params);
inline_ty := InstUtil.classIsInlineFunc(def);
has_unbox_args := hasUnboxArgsAnnotation(def);
then
DAE.FUNCTION_ATTRIBUTES(inline_ty, hasOMPure(def), false, false,
DAE.FUNCTION_BUILTIN(SOME(name), hasUnboxArgs(def)), DAE.FP_PARALLEL_FUNCTION());
DAE.FUNCTION_ATTRIBUTES(inline_ty, hasOMPure(def), false, is_partial,
DAE.FUNCTION_BUILTIN(SOME(name), has_unbox_args), DAE.FP_PARALLEL_FUNCTION());

// Parallel function: non-builtin.
case SCode.FunctionRestriction.FR_PARALLEL_FUNCTION()
algorithm
inline_ty := InstUtil.classIsInlineFunc(def);
then
DAE.FUNCTION_ATTRIBUTES(inline_ty, hasOMPure(def), false, false,
DAE.FUNCTION_ATTRIBUTES(inline_ty, hasOMPure(def), false, is_partial,
getBuiltin(def), DAE.FP_PARALLEL_FUNCTION());

// Kernel functions: never builtin and never inlined.
case SCode.FunctionRestriction.FR_KERNEL_FUNCTION()
then DAE.FUNCTION_ATTRIBUTES(DAE.NO_INLINE(), true, false, false,
then DAE.FUNCTION_ATTRIBUTES(DAE.NO_INLINE(), true, false, is_partial,
DAE.FUNCTION_NOT_BUILTIN(), DAE.FP_KERNEL_FUNCTION());

// Normal function.
Expand All @@ -1724,7 +1800,7 @@ protected
not listEmpty(outputs)) or
SCode.hasBooleanNamedAnnotationInClass(def, "__ModelicaAssociation_Impure");
then
DAE.FUNCTION_ATTRIBUTES(inline_ty, hasOMPure(def), is_impure, false,
DAE.FUNCTION_ATTRIBUTES(inline_ty, hasOMPure(def), is_impure, is_partial,
getBuiltin(def), DAE.FP_NON_PARALLEL());

end matchcontinue;
Expand Down Expand Up @@ -1771,6 +1847,8 @@ protected
case Type.POLYMORPHIC() then true;
case Type.ARRAY() then isValidParamType(ty.elementType);
case Type.COMPLEX() then isValidParamState(ty.cls);
case Type.FUNCTION() then true;
case Type.METABOXED() then isValidParamType(ty.ty);
else false;
end match;
end isValidParamType;
Expand Down
10 changes: 10 additions & 0 deletions Compiler/NFFrontEnd/NFInstNode.mo
Expand Up @@ -1444,6 +1444,16 @@ uniontype InstNode
else false;
end match;
end isBuiltin;

function isPartial
input InstNode node;
output Boolean isPartial;
algorithm
isPartial := match node
case CLASS_NODE() then SCode.isPartial(node.definition);
else false;
end match;
end isPartial;
end InstNode;

annotation(__OpenModelica_Interface="frontend");
Expand Down

0 comments on commit fbe0a66

Please sign in to comment.