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

Commit

Permalink
Error message improvements.
Browse files Browse the repository at this point in the history
- Add division by zero error message in NFCeval.evalBinaryDiv.
- Improve the error message for using == and <> on Reals.

Belonging to [master]:
  - #2878
  - OpenModelica/OpenModelica-testsuite#1105
  • Loading branch information
perost authored and OpenModelica-Hudson committed Jan 15, 2019
1 parent 1f99d4a commit 1f8adde
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 22 deletions.
3 changes: 1 addition & 2 deletions Compiler/FrontEnd/OperatorOverloading.mo
Expand Up @@ -2057,8 +2057,7 @@ algorithm
verifyOp(op);
opString = ExpressionDump.relopSymbol(op);
stmtString = ExpressionDump.printExpStr(e1) + opString + ExpressionDump.printExpStr(e2);
pre_str = PrefixUtil.printPrefixStr3(pre);
Error.addSourceMessage(Error.WARNING_RELATION_ON_REAL, {pre_str,stmtString,opString}, inInfo);
Error.addSourceMessage(Error.WARNING_RELATION_ON_REAL, {stmtString,opString}, inInfo);
then
();
else ();
Expand Down
34 changes: 29 additions & 5 deletions Compiler/NFFrontEnd/NFCeval.mo
Expand Up @@ -50,6 +50,7 @@ import NFClassTree.ClassTree;
import ComplexType = NFComplexType;
import Subscript = NFSubscript;
import NFTyping.TypingError;
import DAE;

protected
import NFFunction.Function;
Expand All @@ -61,6 +62,7 @@ import MetaModelica.Dangerous.*;
import NFClass.Class;
import TypeCheck = NFTypeCheck;
import ExpandExp = NFExpandExp;
import ElementSource;

public
uniontype EvalTarget
Expand All @@ -87,6 +89,10 @@ uniontype EvalTarget
SourceInfo info;
end GENERIC;

record STATEMENT
DAE.ElementSource source;
end STATEMENT;

record IGNORE_ERRORS end IGNORE_ERRORS;

function isRange
Expand All @@ -109,6 +115,7 @@ uniontype EvalTarget
case RANGE() then true;
case CONDITION() then true;
case GENERIC() then true;
case STATEMENT() then true;
else false;
end match;
end hasInfo;
Expand All @@ -123,6 +130,7 @@ uniontype EvalTarget
case RANGE() then target.info;
case CONDITION() then target.info;
case GENERIC() then target.info;
case STATEMENT() then ElementSource.getInfo(target.source);
else Absyn.dummyInfo;
end match;
end getInfo;
Expand Down Expand Up @@ -196,7 +204,7 @@ algorithm
exp1 := evalExp(exp.exp1, target);
exp2 := evalExp(exp.exp2, target);
then
evalBinaryOp(exp1, exp.operator, exp2);
evalBinaryOp(exp1, exp.operator, exp2, target);

case Expression.UNARY()
algorithm
Expand Down Expand Up @@ -738,13 +746,14 @@ function evalBinaryOp
input Expression exp1;
input Operator op;
input Expression exp2;
input EvalTarget target = EvalTarget.IGNORE_ERRORS();
output Expression exp;
algorithm
exp := match op.op
case Op.ADD then evalBinaryAdd(exp1, exp2);
case Op.SUB then evalBinarySub(exp1, exp2);
case Op.MUL then evalBinaryMul(exp1, exp2);
case Op.DIV then evalBinaryDiv(exp1, exp2);
case Op.DIV then evalBinaryDiv(exp1, exp2, target);
case Op.POW then evalBinaryPow(exp1, exp2);
case Op.ADD_SCALAR_ARRAY then evalBinaryScalarArray(exp1, exp2, evalBinaryAdd);
case Op.ADD_ARRAY_SCALAR then evalBinaryArrayScalar(exp1, exp2, evalBinaryAdd);
Expand All @@ -756,8 +765,10 @@ algorithm
case Op.MUL_MATRIX_VECTOR then evalBinaryMulMatrixVector(exp1, exp2);
case Op.SCALAR_PRODUCT then evalBinaryScalarProduct(exp1, exp2);
case Op.MATRIX_PRODUCT then evalBinaryMatrixProduct(exp1, exp2);
case Op.DIV_SCALAR_ARRAY then evalBinaryScalarArray(exp1, exp2, evalBinaryDiv);
case Op.DIV_ARRAY_SCALAR then evalBinaryArrayScalar(exp1, exp2, evalBinaryDiv);
case Op.DIV_SCALAR_ARRAY
then evalBinaryScalarArray(exp1, exp2, function evalBinaryDiv(target = target));
case Op.DIV_ARRAY_SCALAR
then evalBinaryArrayScalar(exp1, exp2, function evalBinaryDiv(target = target));
case Op.POW_SCALAR_ARRAY then evalBinaryScalarArray(exp1, exp2, evalBinaryPow);
case Op.POW_ARRAY_SCALAR then evalBinaryArrayScalar(exp1, exp2, evalBinaryPow);
case Op.POW_MATRIX then evalBinaryPowMatrix(exp1, exp2);
Expand Down Expand Up @@ -857,16 +868,29 @@ end evalBinaryMul;
function evalBinaryDiv
input Expression exp1;
input Expression exp2;
input EvalTarget target;
output Expression exp;
algorithm
exp := match (exp1, exp2)
case (_, Expression.REAL(0.0))
algorithm
if EvalTarget.hasInfo(target) then
Error.addSourceMessage(Error.DIVISION_BY_ZERO,
{Expression.toString(exp1), Expression.toString(exp2)}, EvalTarget.getInfo(target));
fail();
else
exp := Expression.BINARY(exp1, Operator.makeDiv(Type.REAL()), exp2);
end if;
then
exp;

case (Expression.REAL(), Expression.REAL())
then Expression.REAL(exp1.value / exp2.value);

case (Expression.ARRAY(), Expression.ARRAY())
guard listLength(exp1.elements) == listLength(exp2.elements)
then Expression.makeArray(exp1.ty,
list(evalBinaryDiv(e1, e2) threaded for e1 in exp1.elements, e2 in exp2.elements),
list(evalBinaryDiv(e1, e2, target) threaded for e1 in exp1.elements, e2 in exp2.elements),
literal = true);

else
Expand Down
32 changes: 19 additions & 13 deletions Compiler/NFFrontEnd/NFEvalFunction.mo
Expand Up @@ -56,6 +56,7 @@ import NFTyping.ExpOrigin;
import SCode;
import NFPrefixes.Variability;
import EvalFunctionExt = NFEvalFunctionExt;
import NFCeval.EvalTarget;

encapsulated package ReplTree
import BaseAvlTree;
Expand Down Expand Up @@ -163,7 +164,7 @@ algorithm

if lang == "builtin" then
// Functions defined as 'external "builtin"', delegate to Ceval.
result := Ceval.evalBuiltinCall(fn, args, NFCeval.EvalTarget.IGNORE_ERRORS());
result := Ceval.evalBuiltinCall(fn, args, EvalTarget.IGNORE_ERRORS());
elseif isKnownExternalFunc(name, ann) then
// External functions that we know how to evaluate without generating code.
// TODO: Move this to EvalFunctionExt and unify evaluateKnownExternal and
Expand Down Expand Up @@ -491,11 +492,11 @@ algorithm
// adrpo: we really need some error handling here to detect which statement cannot be evaluated
// try
ctrl := match stmt
case Statement.ASSIGNMENT() then evaluateAssignment(stmt.lhs, stmt.rhs);
case Statement.ASSIGNMENT() then evaluateAssignment(stmt.lhs, stmt.rhs, stmt.source);
case Statement.FOR() then evaluateFor(stmt.iterator, stmt.range, stmt.body, stmt.source);
case Statement.IF() then evaluateIf(stmt.branches);
case Statement.IF() then evaluateIf(stmt.branches, stmt.source);
case Statement.ASSERT() then evaluateAssert(stmt.condition, stmt);
case Statement.NORETCALL() then evaluateNoRetCall(stmt.exp);
case Statement.NORETCALL() then evaluateNoRetCall(stmt.exp, stmt.source);
case Statement.WHILE() then evaluateWhile(stmt.condition, stmt.body, stmt.source);
case Statement.RETURN() then FlowControl.RETURN;
case Statement.BREAK() then FlowControl.BREAK;
Expand All @@ -515,9 +516,10 @@ end evaluateStatement;
function evaluateAssignment
input Expression lhsExp;
input Expression rhsExp;
input DAE.ElementSource source;
output FlowControl ctrl = FlowControl.NEXT;
algorithm
assignVariable(lhsExp, Ceval.evalExp(rhsExp));
assignVariable(lhsExp, Ceval.evalExp(rhsExp, EvalTarget.STATEMENT(source)));
end evaluateAssignment;

public
Expand Down Expand Up @@ -715,7 +717,7 @@ protected
list<Statement> body = forBody;
Integer i = 0, limit = Flags.getConfigInt(Flags.EVAL_LOOP_LIMIT);
algorithm
range_exp := Ceval.evalExp(Util.getOption(range));
range_exp := Ceval.evalExp(Util.getOption(range), EvalTarget.STATEMENT(source));
range_iter := RangeIterator.fromExp(range_exp);

if RangeIterator.hasNext(range_iter) then
Expand Down Expand Up @@ -748,6 +750,7 @@ end evaluateFor;

function evaluateIf
input list<tuple<Expression, list<Statement>>> branches;
input DAE.ElementSource source;
output FlowControl ctrl;
protected
Expression cond;
Expand All @@ -756,7 +759,7 @@ algorithm
for branch in branches loop
(cond, body) := branch;

if Expression.isTrue(Ceval.evalExp(cond)) then
if Expression.isTrue(Ceval.evalExp(cond, EvalTarget.STATEMENT(source))) then
ctrl := evaluateStatements(body);
return;
end if;
Expand All @@ -770,13 +773,14 @@ function evaluateAssert
input Statement assertStmt;
output FlowControl ctrl = FlowControl.NEXT;
protected
Expression msg, lvl;
Expression cond, msg, lvl;
DAE.ElementSource source;
EvalTarget target = EvalTarget.STATEMENT(Statement.source(assertStmt));
algorithm
if Expression.isFalse(Ceval.evalExp(condition)) then
if Expression.isFalse(Ceval.evalExp(condition, target)) then
Statement.ASSERT(message = msg, level = lvl, source = source) := assertStmt;
msg := Ceval.evalExp(msg);
lvl := Ceval.evalExp(lvl);
msg := Ceval.evalExp(msg, target);
lvl := Ceval.evalExp(lvl, target);

() := match (msg, lvl)
case (Expression.STRING(), Expression.ENUM_LITERAL(name = "warning"))
Expand Down Expand Up @@ -804,9 +808,10 @@ end evaluateAssert;

function evaluateNoRetCall
input Expression callExp;
input DAE.ElementSource source;
output FlowControl ctrl = FlowControl.NEXT;
algorithm
Ceval.evalExp(callExp);
Ceval.evalExp(callExp, EvalTarget.STATEMENT(source));
end evaluateNoRetCall;

function evaluateWhile
Expand All @@ -816,8 +821,9 @@ function evaluateWhile
output FlowControl ctrl = FlowControl.NEXT;
protected
Integer i = 0, limit = Flags.getConfigInt(Flags.EVAL_LOOP_LIMIT);
EvalTarget target = EvalTarget.STATEMENT(source);
algorithm
while Expression.isTrue(Ceval.evalExp(condition)) loop
while Expression.isTrue(Ceval.evalExp(condition, target)) loop
ctrl := evaluateStatements(body);

if ctrl <> FlowControl.NEXT then
Expand Down
2 changes: 1 addition & 1 deletion Compiler/NFFrontEnd/NFTypeCheck.mo
Expand Up @@ -1318,7 +1318,7 @@ algorithm
o := operator.op;
if ExpOrigin.flagNotSet(origin, ExpOrigin.FUNCTION) and (o == Op.EQUAL or o == Op.NEQUAL) then
Error.addSourceMessage(Error.WARNING_RELATION_ON_REAL,
{"<NO COMPONENT>", Expression.toString(outExp), Operator.symbol(operator)}, info);
{Expression.toString(outExp), Operator.symbol(operator, "")}, info);
end if;
then
valid;
Expand Down
2 changes: 1 addition & 1 deletion Compiler/Util/Error.mo
Expand Up @@ -831,7 +831,7 @@ public constant Message SETTING_FIXED_ATTRIBUTE = MESSAGE(503, TRANSLATION(), WA
public constant Message FAILED_TO_EVALUATE_FUNCTION = MESSAGE(506, TRANSLATION(), ERROR(),
Util.gettext("Failed to evaluate function: %s."));
public constant Message WARNING_RELATION_ON_REAL = MESSAGE(509, TRANSLATION(), WARNING(),
Util.gettext("In component %s, in relation %s, %s on Real numbers is only allowed inside functions."));
Util.gettext("In relation %s, %s on Real numbers is only allowed inside functions."));
public constant Message OUTER_MODIFICATION = MESSAGE(512, TRANSLATION(), WARNING(),
Util.gettext("Ignoring the modification on outer element: %s."));
public constant Message DERIVATIVE_NON_REAL = MESSAGE(514, TRANSLATION(), ERROR(),
Expand Down

0 comments on commit 1f8adde

Please sign in to comment.