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

Commit ee22481

Browse files
perostOpenModelica-Hudson
authored andcommitted
[NF] Branch selection of if-expressions.
Belonging to [master]: - #2342 - OpenModelica/OpenModelica-testsuite#914
1 parent 180e008 commit ee22481

File tree

2 files changed

+88
-56
lines changed

2 files changed

+88
-56
lines changed

Compiler/NFFrontEnd/NFTypeCheck.mo

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2056,51 +2056,6 @@ algorithm
20562056
end match;
20572057
end getRangeTypeEnum;
20582058

2059-
function checkIfExpression
2060-
input Expression condExp;
2061-
input Type condType;
2062-
input Variability condVar;
2063-
input Expression thenExp;
2064-
input Type thenType;
2065-
input Variability thenVar;
2066-
input Expression elseExp;
2067-
input Type elseType;
2068-
input Variability elseVar;
2069-
input SourceInfo info;
2070-
output Expression outExp;
2071-
output Type outType;
2072-
output Variability outVar;
2073-
protected
2074-
Expression ec, e1, e2;
2075-
String s1, s2, s3, s4;
2076-
MatchKind ty_match;
2077-
algorithm
2078-
(ec, _, ty_match) := matchTypes(condType, Type.BOOLEAN(), condExp);
2079-
2080-
// The condition must be a boolean.
2081-
if isIncompatibleMatch(ty_match) then
2082-
s1 := Expression.toString(condExp);
2083-
s2 := Type.toString(condType);
2084-
Error.addSourceMessageAndFail(Error.IF_CONDITION_TYPE_ERROR, {s1, s2}, info);
2085-
end if;
2086-
2087-
(e1, e2, outType, ty_match) :=
2088-
matchExpressions(thenExp, thenType, elseExp, elseType);
2089-
2090-
// The types of the branches must be compatible.
2091-
if isIncompatibleMatch(ty_match) then
2092-
s1 := Expression.toString(thenExp);
2093-
s2 := Expression.toString(elseExp);
2094-
s3 := Type.toString(thenType);
2095-
s4 := Type.toString(elseType);
2096-
Error.addSourceMessageAndFail(Error.TYPE_MISMATCH_IF_EXP,
2097-
{"", s1, s3, s2, s4}, info);
2098-
end if;
2099-
2100-
outExp := Expression.IF(ec, e1, e2);
2101-
outVar := Prefixes.variabilityMax(thenVar, elseVar);
2102-
end checkIfExpression;
2103-
21042059
function matchBinding
21052060
input output Binding binding;
21062061
input Type componentType;

Compiler/NFFrontEnd/NFTyping.mo

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,9 +1017,11 @@ function typeExp
10171017
"Types an untyped expression, returning the typed expression itself along with
10181018
its type and variability. The default behaviour is to replace any constants
10191019
found with their bound values (giving an error if they have none), but this
1020-
can be turned off with the replaceConstants parameter. Note that replaceConstants
1021-
is not propagated when typing subexpressions, because this is so far only
1022-
used when we need the whole expression to be kept as a cref (like connectors)."
1020+
can be turned off with the replaceConstants parameter.
1021+
1022+
NOTE: replaceConstants is not propagated when typing subexpressions, because
1023+
this is so far only used when we need the whole expression to be kept
1024+
as a cref (like connectors)."
10231025
input output Expression exp;
10241026
input ExpOrigin.Type origin;
10251027
input SourceInfo info;
@@ -1128,14 +1130,7 @@ algorithm
11281130
then
11291131
(exp, ty, variability);
11301132

1131-
case Expression.IF()
1132-
algorithm
1133-
next_origin := intBitOr(origin, ExpOrigin.SUBEXPRESSION);
1134-
(e1, ty1, var1) := typeExp(exp.condition, next_origin, info);
1135-
(e2, ty2, var2) := typeExp(exp.trueBranch, next_origin, info);
1136-
(e3, ty3, var3) := typeExp(exp.falseBranch, next_origin, info);
1137-
then
1138-
TypeCheck.checkIfExpression(e1, ty1, var1, e2, ty2, var2, e3, ty3, var3, info);
1133+
case Expression.IF() then typeIfExpression(exp, origin, info);
11391134

11401135
case Expression.CALL()
11411136
algorithm
@@ -1892,6 +1887,88 @@ function evaluateEnd
18921887
end match;
18931888
end evaluateEnd;
18941889

1890+
function typeIfExpression
1891+
input output Expression ifExp;
1892+
input ExpOrigin.Type origin;
1893+
input SourceInfo info;
1894+
output Type ty;
1895+
output Variability var;
1896+
protected
1897+
Expression cond, tb, fb, tb2, fb2;
1898+
ExpOrigin.Type next_origin;
1899+
Type cond_ty, tb_ty, fb_ty;
1900+
Variability cond_var, tb_var, fb_var;
1901+
MatchKind ty_match;
1902+
algorithm
1903+
Expression.IF(condition = cond, trueBranch = tb, falseBranch = fb) := ifExp;
1904+
next_origin := intBitOr(origin, ExpOrigin.SUBEXPRESSION);
1905+
1906+
(cond, cond_ty, cond_var) := typeExp(cond, next_origin, info);
1907+
1908+
// The condition must be a scalar boolean.
1909+
(cond, _, ty_match) := TypeCheck.matchTypes(cond_ty, Type.BOOLEAN(), cond);
1910+
1911+
if TypeCheck.isIncompatibleMatch(ty_match) then
1912+
Error.addSourceMessage(Error.IF_CONDITION_TYPE_ERROR,
1913+
{Expression.toString(cond), Type.toString(cond_ty)}, info);
1914+
fail();
1915+
end if;
1916+
1917+
if cond_var <= Variability.STRUCTURAL_PARAMETER then
1918+
// If the condition is constant, always do branch selection.
1919+
if evaluateCondition(cond, info) then
1920+
(ifExp, ty, var) := typeExp(tb, next_origin, info);
1921+
else
1922+
(ifExp, ty, var) := typeExp(fb, next_origin, info);
1923+
end if;
1924+
else
1925+
// Otherwise type both of the branches.
1926+
(tb, tb_ty, tb_var) := typeExp(tb, next_origin, info);
1927+
(fb, fb_ty, fb_var) := typeExp(fb, next_origin, info);
1928+
1929+
(tb2, fb2, ty, ty_match) := TypeCheck.matchExpressions(tb, tb_ty, fb, fb_ty);
1930+
1931+
if TypeCheck.isIncompatibleMatch(ty_match) then
1932+
if cond_var <= Variability.PARAMETER then
1933+
// If the branches have different types but the condition is a parameter
1934+
// expression, do branch selection.
1935+
(ifExp, ty, var) := if evaluateCondition(cond, info) then (tb, tb_ty, tb_var) else (fb, fb_ty, fb_var);
1936+
else
1937+
// Otherwise give an type mismatch error.
1938+
Error.addSourceMessage(Error.TYPE_MISMATCH_IF_EXP,
1939+
{"", Expression.toString(tb), Type.toString(tb_ty),
1940+
Expression.toString(fb), Type.toString(fb_ty)}, info);
1941+
fail();
1942+
end if;
1943+
else
1944+
// If the types match, return a typed if-expression.
1945+
ifExp := Expression.IF(cond, tb2, fb2);
1946+
var := Prefixes.variabilityMax(cond_var, Prefixes.variabilityMax(tb_var, fb_var));
1947+
end if;
1948+
end if;
1949+
end typeIfExpression;
1950+
1951+
function evaluateCondition
1952+
input Expression condExp;
1953+
input SourceInfo info;
1954+
output Boolean condBool;
1955+
protected
1956+
Expression cond_exp;
1957+
algorithm
1958+
cond_exp := Ceval.evalExp(condExp, Ceval.EvalTarget.GENERIC(info));
1959+
cond_exp := SimplifyExp.simplifyExp(cond_exp);
1960+
1961+
condBool := match cond_exp
1962+
case Expression.BOOLEAN() then cond_exp.value;
1963+
else
1964+
algorithm
1965+
Error.assertion(false, getInstanceName() + " failed to evaluate condition `" +
1966+
Expression.toString(condExp) + "`", info);
1967+
then
1968+
fail();
1969+
end match;
1970+
end evaluateCondition;
1971+
18951972
function typeSections
18961973
input InstNode classNode;
18971974
input ExpOrigin.Type origin;

0 commit comments

Comments
 (0)