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

Commit 05a951b

Browse files
sjoelundOpenModelica-Hudson
authored andcommitted
Handle tail recursion in CevalFunction
This fixes ticket:4838 Belonging to [master]: - #2300 - OpenModelica/OpenModelica-testsuite#889
1 parent 748b75a commit 05a951b

File tree

6 files changed

+70
-20
lines changed

6 files changed

+70
-20
lines changed

Compiler/FrontEnd/CevalFunction.mo

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,12 +1031,16 @@ algorithm
10311031
FCore.Graph env;
10321032
DAE.Exp lhs, rhs, condition;
10331033
DAE.ComponentRef lhs_cref;
1034-
Values.Value rhs_val;
1034+
Values.Value rhs_val, v;
10351035
list<DAE.Exp> exps;
10361036
list<Values.Value> vals;
10371037
list<DAE.Statement> statements;
10381038
Absyn.Path path;
1039+
DAE.Type returnType;
10391040
LoopControl loop_ctrl;
1041+
DAE.TailCall tailCall;
1042+
String var;
1043+
list<String> vars;
10401044

10411045
case (DAE.STMT_ASSIGN(exp1 = lhs, exp = rhs), cache, env)
10421046
equation
@@ -1100,12 +1104,29 @@ algorithm
11001104
then
11011105
(cache, inEnv, NEXT());
11021106
// Special case for print, and other known calls for now; evaluated even when there is no ST
1103-
case (DAE.STMT_NORETCALL(exp = rhs as DAE.CALL(path = path, expLst = exps)), _, _)
1107+
case (DAE.STMT_NORETCALL(exp = rhs as DAE.CALL(path = path, expLst = exps, attr=DAE.CALL_ATTR(ty=returnType, tailCall=tailCall))), _, _)
11041108
algorithm
11051109
(cache, vals) := cevalExpList(exps, inCache, inEnv);
1106-
(cache, _) := cevalExp(rhs, cache, inEnv);
1110+
(cache, v) := cevalExp(rhs, cache, inEnv);
1111+
(cache, env, outLoopControl) := match tailCall
1112+
case DAE.NO_TAIL() then (cache, inEnv, NEXT());
1113+
// Handle tail recursion; same as a assigning all outputs followed by a return
1114+
case DAE.TAIL(outVars={}) then (cache, inEnv, RETURN());
1115+
case DAE.TAIL(outVars={var})
1116+
algorithm
1117+
(cache, env) := assignVariable(ComponentReference.makeUntypedCrefIdent(var), v, cache, inEnv);
1118+
then (cache, env, RETURN());
1119+
case DAE.TAIL(outVars=vars)
1120+
algorithm
1121+
Values.TUPLE(vals) := v;
1122+
for val in vals loop
1123+
var::vars := vars;
1124+
(cache, env) := assignVariable(ComponentReference.makeUntypedCrefIdent(var), val, cache, inEnv);
1125+
end for;
1126+
then (cache, env, RETURN());
1127+
end match;
11071128
then
1108-
(cache, inEnv, NEXT());
1129+
(cache, env, NEXT());
11091130

11101131
case (DAE.STMT_RETURN(), _, _)
11111132
then

Compiler/FrontEnd/DAE.mo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,7 @@ public uniontype TailCall
15341534
end NO_TAIL;
15351535
record TAIL
15361536
list<String> vars;
1537+
list<String> outVars;
15371538
end TAIL;
15381539
end TailCall;
15391540

Compiler/FrontEnd/DAEDump.mo

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,8 +1462,15 @@ algorithm
14621462
();
14631463

14641464
case (DAE.STMT_NORETCALL(exp = e1),i)
1465-
equation
1465+
algorithm
14661466
indent(i);
1467+
_ := match e1
1468+
case DAE.CALL(attr=DAE.CALL_ATTR(tailCall=DAE.TAIL()))
1469+
algorithm
1470+
Print.printBuf("return ");
1471+
then ();
1472+
else ();
1473+
end match;
14671474
ExpressionDump.printExp(e1);
14681475
Print.printBuf(";\n");
14691476
then
@@ -1716,8 +1723,12 @@ algorithm
17161723
case (DAE.STMT_NORETCALL(exp = e),i)
17171724
equation
17181725
s1 = indentStr(i);
1719-
s2 = ExpressionDump.printExpStr(e);
1720-
str = stringAppendList({s1,s2,";\n"});
1726+
s2 = match e
1727+
case DAE.CALL(attr=DAE.CALL_ATTR(tailCall=DAE.TAIL())) then "return ";
1728+
else "";
1729+
end match;
1730+
s3 = ExpressionDump.printExpStr(e);
1731+
str = stringAppendList({s1,s2,s3,";\n"});
17211732
then
17221733
str;
17231734

Compiler/FrontEnd/InstUtil.mo

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7551,13 +7551,13 @@ protected function optimizeStatementTail2
75517551
output DAE.Exp orhs;
75527552
algorithm
75537553
true:=valueEq(lhsVars,outvars);
7554-
(orhs,true) := optimizeStatementTail3(path,rhs,invars,source);
7554+
(orhs,true) := optimizeStatementTail3(path,rhs,invars,lhsVars,source);
75557555
end optimizeStatementTail2;
75567556

75577557
protected function optimizeStatementTail3
75587558
input Absyn.Path path;
75597559
input DAE.Exp rhs;
7560-
input list<String> vars;
7560+
input list<String> vars, lhsVars;
75617561
input DAE.ElementSource source;
75627562
output DAE.Exp orhs;
75637563
output Boolean isTailRecursive;
@@ -7585,18 +7585,18 @@ algorithm
75857585
if Flags.isSet(Flags.TAIL) then
75867586
Error.addSourceMessage(Error.COMPILER_NOTIFICATION,{str},ElementSource.getElementSourceFileInfo(source));
75877587
end if;
7588-
attr.tailCall = DAE.TAIL(vars);
7588+
attr.tailCall = DAE.TAIL(vars,lhsVars);
75897589
call.attr = attr;
75907590
then (call,true);
75917591
case (_,DAE.IFEXP(e1,e2,e3),_,_)
75927592
equation
7593-
(e2,b1) = optimizeStatementTail3(path,e2,vars,source);
7594-
(e3,b2) = optimizeStatementTail3(path,e3,vars,source);
7593+
(e2,b1) = optimizeStatementTail3(path,e2,vars,lhsVars,source);
7594+
(e3,b2) = optimizeStatementTail3(path,e3,vars,lhsVars,source);
75957595
true = b1 or b2;
75967596
then (DAE.IFEXP(e1,e2,e3),true);
75977597
case (_,DAE.MATCHEXPRESSION(matchType as DAE.MATCH(_) /*TODO:matchcontinue*/,inputs,aliases,localDecls,cases,et),_,_)
75987598
equation
7599-
cases = optimizeStatementTailMatchCases(path,cases,false,{},vars,source);
7599+
cases = optimizeStatementTailMatchCases(path,cases,false,{},vars,lhsVars,source);
76007600
then (DAE.MATCHEXPRESSION(matchType,inputs,aliases,localDecls,cases,et),true);
76017601
else (rhs,false);
76027602
end matchcontinue;
@@ -7607,7 +7607,7 @@ protected function optimizeStatementTailMatchCases
76077607
input list<DAE.MatchCase> inCases;
76087608
input Boolean changed;
76097609
input list<DAE.MatchCase> inAcc;
7610-
input list<String> vars;
7610+
input list<String> vars, lhsVars;
76117611
input DAE.ElementSource source;
76127612
output list<DAE.MatchCase> ocases;
76137613
algorithm
@@ -7627,18 +7627,18 @@ algorithm
76277627
case (_,{},true,acc,_,_) then listReverse(acc);
76287628
case (_,DAE.CASE(patterns,patternGuard,localDecls,body,SOME(exp),resultInfo,jump,info)::cases,_,acc,_,_)
76297629
equation
7630-
(exp,true) = optimizeStatementTail3(path,exp,vars,source);
7630+
(exp,true) = optimizeStatementTail3(path,exp,vars,lhsVars,source);
76317631
case_ = DAE.CASE(patterns,patternGuard,localDecls,body,SOME(exp),resultInfo,jump,info);
7632-
then optimizeStatementTailMatchCases(path,cases,true,case_::acc,vars,source);
7632+
then optimizeStatementTailMatchCases(path,cases,true,case_::acc,vars,lhsVars,source);
76337633
case (_,DAE.CASE(patterns,patternGuard,localDecls,body,SOME(DAE.TUPLE({})),resultInfo,jump,info)::cases,_,acc,_,_)
76347634
equation
76357635
DAE.STMT_NORETCALL(exp,sourceStmt) = List.last(body);
7636-
(exp,true) = optimizeStatementTail3(path,exp,vars,source);
7636+
(exp,true) = optimizeStatementTail3(path,exp,vars,lhsVars,source);
76377637
body = List.set(body,listLength(body),DAE.STMT_NORETCALL(exp,sourceStmt));
76387638
case_ = DAE.CASE(patterns,patternGuard,localDecls,body,SOME(DAE.TUPLE({})),resultInfo,jump,info);
7639-
then optimizeStatementTailMatchCases(path,cases,true,case_::acc,vars,source);
7639+
then optimizeStatementTailMatchCases(path,cases,true,case_::acc,vars,lhsVars,source);
76407640
case (_,case_::cases,_,acc,_,_)
7641-
then optimizeStatementTailMatchCases(path,cases,changed,case_::acc,vars,source);
7641+
then optimizeStatementTailMatchCases(path,cases,changed,case_::acc,vars,lhsVars,source);
76427642
end matchcontinue;
76437643
end optimizeStatementTailMatchCases;
76447644

Compiler/Template/DAEDumpTV.mo

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,20 @@ package DAE
13911391
end SUM;
13921392

13931393
end Exp;
1394+
1395+
uniontype CallAttributes
1396+
record CALL_ATTR
1397+
TailCall tailCall "Input variables of the function if the call is tail-recursive";
1398+
end CALL_ATTR;
1399+
end CallAttributes;
1400+
1401+
uniontype TailCall
1402+
record NO_TAIL
1403+
end NO_TAIL;
1404+
record TAIL
1405+
end TAIL;
1406+
end TailCall;
1407+
13941408
end DAE;
13951409

13961410
package SCodeDump

Compiler/Template/DAEDumpTpl.tpl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,8 +698,11 @@ template dumpNoRetCall(DAE.Exp call_exp, DAE.ElementSource src)
698698
::=
699699
let call_str = dumpExp(call_exp)
700700
let src_str = dumpSource(src)
701+
let tail_str = match call_exp
702+
case CALL(attr=CALL_ATTR(tailCall=TAIL(__))) then "return "
703+
else ""
701704
<<
702-
<%call_str%><%src_str%>;
705+
<%tail_str%><%call_str%><%src_str%>;
703706
>>
704707
end dumpNoRetCall;
705708

0 commit comments

Comments
 (0)