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

Commit

Permalink
[NF] Move general evaluation to separate phase.
Browse files Browse the repository at this point in the history
- Added new module NFEvalConstants which evaluates constants and
  structural parameters after the flattening, instead of doing it during
  the typing which causes lots of issues.
- Moved the construction of the function tree to after the evaluation
  and simplification phases, to avoid collecting functions that have
  been optimized out.
- Fixed Ceval.evalCref so that subscripts are applied correctly.
- Fixed EvalFunction so that it fails if an assertion is triggered,
  instead of returning the current value of the outputs.
- Improved subscripting of if-expressions by subscripting the branches
  instead of the whole expression.
- Added check that terminate is not used in a function context,
  and removed the handling of terminate in EvalFunction.

Belonging to [master]:
  - #2690
  - OpenModelica/OpenModelica-testsuite#1043
  • Loading branch information
perost authored and OpenModelica-Hudson committed Oct 3, 2018
1 parent 6f85ead commit 5468d69
Show file tree
Hide file tree
Showing 26 changed files with 1,640 additions and 336 deletions.
69 changes: 69 additions & 0 deletions Compiler/NFFrontEnd/NFBinding.mo
Expand Up @@ -91,6 +91,7 @@ uniontype Binding
bindings constructed from the record fields) that should be discarded
during flattening."
Expression bindingExp;
list<InstNode> parents;
end CEVAL_BINDING;


Expand Down Expand Up @@ -316,10 +317,16 @@ public
case RAW_BINDING() then binding.parents;
case UNTYPED_BINDING() then binding.parents;
case TYPED_BINDING() then binding.parents;
case CEVAL_BINDING() then binding.parents;
else {};
end match;
end parents;

function parentCount
input Binding binding;
output Integer count = listLength(parents(binding));
end parentCount;

function addParent
input InstNode parent;
input output Binding binding;
Expand Down Expand Up @@ -349,6 +356,12 @@ public
then
();

case CEVAL_BINDING()
algorithm
binding.parents := parent :: binding.parents;
then
();

else ();
end match;
end addParent;
Expand Down Expand Up @@ -467,6 +480,62 @@ public
fail();
end match;
end toDAEExp;

function mapExp
input output Binding binding;
input MapFunc mapFn;

partial function MapFunc
input output Expression exp;
end MapFunc;
protected
Expression e1, e2;
algorithm
() := match binding
case UNTYPED_BINDING(bindingExp = e1)
algorithm
e2 := mapFn(e1);

if not referenceEq(e1, e2) then
binding.bindingExp := e2;
end if;
then
();

case TYPED_BINDING(bindingExp = e1)
algorithm
e2 := mapFn(e1);

if not referenceEq(e1, e2) then
binding.bindingExp := e2;
end if;
then
();

case FLAT_BINDING(bindingExp = e1)
algorithm
e2 := mapFn(e1);

if not referenceEq(e1, e2) then
binding.bindingExp := e2;
end if;
then
();

case CEVAL_BINDING(bindingExp = e1)
algorithm
e2 := mapFn(e1);

if not referenceEq(e1, e2) then
binding.bindingExp := e2;
end if;
then
();

else ();
end match;
end mapExp;

end Binding;

annotation(__OpenModelica_Interface="frontend");
Expand Down
55 changes: 28 additions & 27 deletions Compiler/NFFrontEnd/NFBuiltinFuncs.mo
Expand Up @@ -58,6 +58,7 @@ import NFComponentRef.Origin;
import NFModifier.Modifier;
import Sections = NFSections;
import NFFunction.SlotEvalStatus;
import NFFunction.FunctionStatus;

protected
import MetaModelica.Dangerous.*;
Expand Down Expand Up @@ -129,7 +130,7 @@ constant InstNode INTEGER_DUMMY_NODE = NFInstNode.CLASS_NODE("Integer",
constant Function INTEGER_FUNCTION = Function.FUNCTION(Path.IDENT("Integer"),
INTEGER_DUMMY_NODE, {ENUM_PARAM}, {}, {}, {
Slot.SLOT("e", SlotType.POSITIONAL, NONE(), NONE(), 1, SlotEvalStatus.NOT_EVALUATED)
}, Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {}, Pointer.createImmutable(true), Pointer.createImmutable(0));
}, Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {}, Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant InstNode INTEGER_NODE = InstNode.CLASS_NODE("IntegerFunc",
DUMMY_ELEMENT, Visibility.PUBLIC,
Expand All @@ -155,15 +156,15 @@ constant Function STRING_REAL = Function.FUNCTION(Path.IDENT("String"),
Slot.SLOT("minimumLength", SlotType.NAMED, SOME(Expression.INTEGER(0)), NONE(), 3, SlotEvalStatus.NOT_EVALUATED),
Slot.SLOT("leftJustified", SlotType.NAMED, SOME(Expression.BOOLEAN(true)), NONE(), 4, SlotEvalStatus.NOT_EVALUATED)
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// String(r, format="-0.6g")
constant Function STRING_REAL_FORMAT = Function.FUNCTION(Path.IDENT("String"),
STRING_DUMMY_NODE, {REAL_PARAM, STRING_PARAM}, {STRING_PARAM}, {}, {
Slot.SLOT("r", SlotType.POSITIONAL, NONE(), NONE(), 1, SlotEvalStatus.NOT_EVALUATED),
Slot.SLOT("format", SlotType.NAMED, NONE(), NONE(), 2, SlotEvalStatus.NOT_EVALUATED)
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// String(i, minimumLength=0, leftJustified=true)
constant Function STRING_INT = Function.FUNCTION(Path.IDENT("String"),
Expand All @@ -172,7 +173,7 @@ constant Function STRING_INT = Function.FUNCTION(Path.IDENT("String"),
Slot.SLOT("minimumLength", SlotType.NAMED, SOME(Expression.INTEGER(0)), NONE(), 2, SlotEvalStatus.NOT_EVALUATED),
Slot.SLOT("leftJustified", SlotType.NAMED, SOME(Expression.BOOLEAN(true)), NONE(), 3, SlotEvalStatus.NOT_EVALUATED)
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// String(b, minimumLength=0, leftJustified=true)
constant Function STRING_BOOL = Function.FUNCTION(Path.IDENT("String"),
Expand All @@ -181,7 +182,7 @@ constant Function STRING_BOOL = Function.FUNCTION(Path.IDENT("String"),
Slot.SLOT("minimumLength", SlotType.NAMED, SOME(Expression.INTEGER(0)), NONE(), 2, SlotEvalStatus.NOT_EVALUATED),
Slot.SLOT("leftJustified", SlotType.NAMED, SOME(Expression.BOOLEAN(true)), NONE(), 3, SlotEvalStatus.NOT_EVALUATED)
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// String(e, minimumLength=0, leftJustified=true)
constant Function STRING_ENUM = Function.FUNCTION(Path.IDENT("String"),
Expand All @@ -190,7 +191,7 @@ constant Function STRING_ENUM = Function.FUNCTION(Path.IDENT("String"),
Slot.SLOT("minimumLength", SlotType.NAMED, SOME(Expression.INTEGER(0)), NONE(), 2, SlotEvalStatus.NOT_EVALUATED),
Slot.SLOT("leftJustified", SlotType.NAMED, SOME(Expression.BOOLEAN(true)), NONE(), 3, SlotEvalStatus.NOT_EVALUATED)
}, Type.STRING(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant InstNode STRING_NODE = InstNode.CLASS_NODE("String",
DUMMY_ELEMENT, Visibility.PUBLIC,
Expand All @@ -215,72 +216,72 @@ constant ComponentRef STRING_CREF =
constant Function ABS_REAL = Function.FUNCTION(Path.IDENT("abs"),
InstNode.EMPTY_NODE(), {REAL_PARAM, REAL_PARAM}, {REAL_PARAM}, {}, {},
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function MAX_INT = Function.FUNCTION(Path.IDENT("max"),
InstNode.EMPTY_NODE(), {INT_PARAM, INT_PARAM}, {INT_PARAM}, {}, {},
Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function MAX_REAL = Function.FUNCTION(Path.IDENT("max"),
InstNode.EMPTY_NODE(), {REAL_PARAM, REAL_PARAM}, {REAL_PARAM}, {}, {},
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function DIV_INT = Function.FUNCTION(Path.IDENT("div"),
InstNode.EMPTY_NODE(), {INT_PARAM, INT_PARAM}, {INT_PARAM}, {}, {},
Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function FLOOR = Function.FUNCTION(Path.IDENT("floor"),
InstNode.EMPTY_NODE(), {REAL_PARAM}, {REAL_PARAM}, {}, {},
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function INTEGER_REAL = Function.FUNCTION(Path.IDENT("integer"),
InstNode.EMPTY_NODE(), {REAL_PARAM}, {INT_PARAM}, {}, {},
Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function INTEGER_ENUM = Function.FUNCTION(Path.IDENT("Integer"),
InstNode.EMPTY_NODE(), {ENUM_PARAM}, {INT_PARAM}, {}, {},
Type.INTEGER(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function POSITIVE_MAX_REAL = Function.FUNCTION(Path.IDENT("$OMC$PositiveMax"),
InstNode.EMPTY_NODE(), {REAL_PARAM, REAL_PARAM}, {REAL_PARAM}, {}, {},
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function IN_STREAM = Function.FUNCTION(Path.IDENT("inStream"),
InstNode.EMPTY_NODE(), {REAL_PARAM}, {REAL_PARAM}, {}, {},
Type.REAL(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function PROMOTE = Function.FUNCTION(Path.IDENT("promote"),
InstNode.EMPTY_NODE(), {}, {}, {}, {},
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function CAT = Function.FUNCTION(Path.IDENT("cat"),
InstNode.EMPTY_NODE(), {}, {}, {}, {},
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function ARRAY_FUNC = Function.FUNCTION(Path.IDENT("array"),
InstNode.EMPTY_NODE(), {}, {}, {}, {},
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function FILL_FUNC = Function.FUNCTION(Path.IDENT("fill"),
InstNode.EMPTY_NODE(), {}, {}, {}, {},
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

constant Function SMOOTH = Function.FUNCTION(Path.IDENT("smooth"),
InstNode.EMPTY_NODE(), {}, {}, {}, {},
Type.UNKNOWN(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));


constant Component CLOCK_COMPONENT = Component.TYPED_COMPONENT(NFInstNode.EMPTY_NODE(),
Expand All @@ -297,52 +298,52 @@ constant InstNode CLOCK_DUMMY_NODE = NFInstNode.CLASS_NODE("Clock",
// Clock() - inferred clock
constant Function CLOCK_INFERED = Function.FUNCTION(Path.IDENT("Clock"),
CLOCK_DUMMY_NODE, {}, {CLOCK_PARAM}, {}, {}, Type.CLOCK(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// Clock(intervalCounter) - clock with Integer interval
constant Function CLOCK_INT = Function.FUNCTION(Path.IDENT("Clock"),
CLOCK_DUMMY_NODE, {INT_PARAM}, {CLOCK_PARAM}, {}, {
Slot.SLOT("intervalCounter", SlotType.POSITIONAL, NONE(), NONE(), 1, SlotEvalStatus.NOT_EVALUATED)
}, Type.CLOCK(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// Clock(intervalCounter, resolution) - clock with Integer interval
constant Function CLOCK_INT_RESOLUTION = Function.FUNCTION(Path.IDENT("Clock"),
CLOCK_DUMMY_NODE, {INT_PARAM, INT_PARAM}, {CLOCK_PARAM}, {}, {
Slot.SLOT("intervalCounter", SlotType.POSITIONAL, NONE(), NONE(), 1, SlotEvalStatus.NOT_EVALUATED),
Slot.SLOT("resolution", SlotType.NAMED, SOME(Expression.INTEGER(1)), NONE(), 2, SlotEvalStatus.NOT_EVALUATED)
}, Type.CLOCK(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// Clock(interval) - clock with Real interval
constant Function CLOCK_REAL = Function.FUNCTION(Path.IDENT("Clock"),
CLOCK_DUMMY_NODE, {REAL_PARAM}, {CLOCK_PARAM}, {}, {
Slot.SLOT("interval", SlotType.POSITIONAL, NONE(), NONE(), 1, SlotEvalStatus.NOT_EVALUATED)
}, Type.CLOCK(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// Clock(condition) - Boolean clock, triggered by zero-crossing events
constant Function CLOCK_BOOL = Function.FUNCTION(Path.IDENT("Clock"),
CLOCK_DUMMY_NODE, {BOOL_PARAM}, {CLOCK_PARAM}, {}, {
Slot.SLOT("condition", SlotType.POSITIONAL, NONE(), NONE(), 1, SlotEvalStatus.NOT_EVALUATED)
}, Type.CLOCK(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// Clock(condition, startInterval) - Boolean clock, triggered by zero-crossing events
constant Function CLOCK_BOOL_INTERVAL = Function.FUNCTION(Path.IDENT("Clock"),
CLOCK_DUMMY_NODE, {BOOL_PARAM, REAL_PARAM}, {CLOCK_PARAM}, {}, {
Slot.SLOT("condition", SlotType.POSITIONAL, NONE(), NONE(), 1, SlotEvalStatus.NOT_EVALUATED),
Slot.SLOT("startInterval", SlotType.NAMED, SOME(Expression.REAL(0.0)), NONE(), 2, SlotEvalStatus.NOT_EVALUATED)
}, Type.CLOCK(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));

// Clock(c, solverMethod) - Solver clock
constant Function CLOCK_SOLVER = Function.FUNCTION(Path.IDENT("Clock"),
CLOCK_DUMMY_NODE, {CLOCK_PARAM, STRING_PARAM}, {CLOCK_PARAM}, {}, {
Slot.SLOT("condition", SlotType.POSITIONAL, NONE(), NONE(), 1, SlotEvalStatus.NOT_EVALUATED),
Slot.SLOT("solverMethod", SlotType.NAMED, NONE(), NONE(), 2, SlotEvalStatus.NOT_EVALUATED)
}, Type.CLOCK(), DAE.FUNCTION_ATTRIBUTES_BUILTIN, {},
Pointer.createImmutable(true), Pointer.createImmutable(0));
Pointer.createImmutable(FunctionStatus.BUILTIN), Pointer.createImmutable(0));


constant InstNode CLOCK_NODE = InstNode.CLASS_NODE("Clock",
Expand Down
22 changes: 13 additions & 9 deletions Compiler/NFFrontEnd/NFCall.mo
Expand Up @@ -262,12 +262,8 @@ uniontype Call
case UNTYPED_CALL()
algorithm
fnl := Function.typeRefCache(call.ref);
// Don't evaluate constants or structural parameters for external functions,
// the code generation can't handle it in some cases (see bug #4904).
// TODO: Remove this when #4904 is fixed.
is_external := if listEmpty(fnl) then false else Function.isExternal(listHead(fnl));
then
typeArgs(call, not is_external, origin, info);
typeArgs(call, origin, info);

else
algorithm
Expand Down Expand Up @@ -862,17 +858,26 @@ protected
list<Dimension> dims = {};
list<tuple<InstNode, Expression>> iters = {};
ExpOrigin.Type next_origin;
Boolean is_structural;
algorithm
(call, ty, variability) := match call
// This is always a call to the function array()/$array(). See instIteratorCall.
// Other mapping function calls are already wrapped by array() at this point.
case UNTYPED_MAP_CALL()
algorithm
variability := Variability.CONSTANT;
// The size of the expression must be known unless we're in a function.
is_structural := ExpOrigin.flagNotSet(origin, ExpOrigin.FUNCTION);

for i in call.iters loop
(iter, range) := i;
(range, iter_ty, iter_var) := Typing.typeIterator(iter, range, origin, structural = false);
(range, iter_ty, iter_var) := Typing.typeIterator(iter, range, origin, is_structural);

if is_structural then
range := Ceval.evalExp(range, Ceval.EvalTarget.RANGE(info));
iter_ty := Expression.typeOf(range);
end if;

dims := listAppend(Type.arrayDims(iter_ty), dims);
variability := Variability.variabilityMax(variability, iter_var);
iters := (iter, range) :: iters;
Expand All @@ -896,7 +901,6 @@ protected

function typeArgs
input output Call call;
input Boolean replaceConstants;
input ExpOrigin.Type origin;
input SourceInfo info;
algorithm
Expand All @@ -913,7 +917,7 @@ protected
algorithm
typedArgs := {};
for arg in call.arguments loop
(arg, arg_ty, arg_var) := Typing.typeExp(arg, origin, info, replaceConstants = replaceConstants);
(arg, arg_ty, arg_var) := Typing.typeExp(arg, origin, info);
typedArgs := (arg, arg_ty, arg_var) :: typedArgs;
end for;

Expand All @@ -922,7 +926,7 @@ protected
typedNamedArgs := {};
for narg in call.named_args loop
(name,arg) := narg;
(arg, arg_ty, arg_var) := Typing.typeExp(arg, origin, info, replaceConstants = replaceConstants);
(arg, arg_ty, arg_var) := Typing.typeExp(arg, origin, info);
typedNamedArgs := (name, arg, arg_ty, arg_var) :: typedNamedArgs;
end for;

Expand Down

0 comments on commit 5468d69

Please sign in to comment.