Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- First working tail recursion testcase
  - Limited to the last statement being an assignment to a recursive call; but adding if-statements, if-expressions and match-expressions should be a minor addition


git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@9451 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
sjoelund committed Jul 11, 2011
1 parent b21dd74 commit 8dc2c98
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 7 deletions.
10 changes: 10 additions & 0 deletions Compiler/FrontEnd/Expression.mo
Expand Up @@ -7019,5 +7019,15 @@ algorithm
DAE.CREF(componentRef=DAE.CREF_IDENT(ident=name,subscriptLst={})) := exp;
end simpleCrefName;

public function isTailCall
input DAE.Exp exp;
output Boolean isTail;
algorithm
isTail := match exp
case DAE.CALL(attr=DAE.CALL_ATTR(tailCall=DAE.TAIL(vars=_))) then true;
else false;
end match;
end isTailCall;

end Expression;

20 changes: 13 additions & 7 deletions Compiler/FrontEnd/Inst.mo
Expand Up @@ -16469,12 +16469,14 @@ algorithm
equation
name = Expression.simpleCrefName(lhs);
rhs = optimizeStatementTail2(path,rhs,{name},invars,outvars,source);
then fail();
stmt = Util.if_(Expression.isTailCall(rhs),DAE.STMT_NORETCALL(rhs,source),DAE.STMT_ASSIGN(tp,lhs,rhs,source));
then stmt;
case (path,DAE.STMT_TUPLE_ASSIGN(tp,lhsLst,rhs,source),invars,outvars)
equation
lhsNames = Util.listMap(lhsLst,Expression.simpleCrefName);
rhs = optimizeStatementTail2(path,rhs,lhsNames,invars,outvars,source);
then fail();
stmt = Util.if_(Expression.isTailCall(rhs),DAE.STMT_NORETCALL(rhs,source),DAE.STMT_TUPLE_ASSIGN(tp,lhsLst,rhs,source));
then stmt;
else stmt;
end matchcontinue;
end optimizeStatementTail;
Expand Down Expand Up @@ -16503,12 +16505,16 @@ algorithm
local
Absyn.Path path1,path2;
String str;
case (path1,DAE.CALL(path=path2),vars,source)
DAE.InlineType i;
Boolean b1,b2;
DAE.ExpType tp;
list<DAE.Exp> es;
case (path1,DAE.CALL(path=path2,expLst=es,attr=DAE.CALL_ATTR(tp,b1,b2,i,DAE.NO_TAIL())),vars,source)
equation
// str = "Tail recursion of: " +& ExpressionDump.printExpStr(rhs) +& " with input vars: " +& Util.stringDelimitList(vars,",");
// Error.addSourceMessage(Error.COMPILER_NOTIFICATION,{str},DAEUtil.getElementSourceFileInfo(source));
// TODO: Embed input variable names to the function call or whatever...
then fail();
true = Absyn.pathEqual(path1,path2);
str = "Tail recursion of: " +& ExpressionDump.printExpStr(rhs) +& " with input vars: " +& Util.stringDelimitList(vars,",");
Error.addSourceMessage(Error.COMPILER_NOTIFICATION,{str},DAEUtil.getElementSourceFileInfo(source));
then DAE.CALL(path2,es,DAE.CALL_ATTR(tp,b1,b2,i,DAE.TAIL(vars)));
end match;
end optimizeStatementTail3;

Expand Down
19 changes: 19 additions & 0 deletions Compiler/susan_codegen/SimCode/SimCodeC.tpl
Expand Up @@ -2768,6 +2768,7 @@ case FUNCTION(__) then
<%funArgs%>
/* functionBodyRegularFunction: locals */
<%varDecls%>
_tailrecursive:
/* functionBodyRegularFunction: out inits */
<%outVarInits%>
Expand Down Expand Up @@ -5171,6 +5172,15 @@ template daeExpCall(Exp call, Context context, Text &preExp /*BUFP*/,
let argStr = daeExp(s1, context, &preExp, &varDecls)
unboxRecord(argStr, ty, &preExp, &varDecls)

case exp as CALL(attr=attr as CALL_ATTR(tailCall=tail as TAIL(__))) then
let res = <<
/* Tail recursive call <%printExpStr(exp)%> */
<%daeExpTailCall(expLst,tail.vars,context,&preExp,&varDecls)%>goto _tailrecursive;
/* TODO: Make sure any eventual dead code below is never generated */
>>
let &preExp += res
""

case exp as CALL(attr=attr as CALL_ATTR(__)) then
let argStr = (expLst |> exp => '<%daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)%>' ;separator=", ")
let funName = '<%underscorePath(path)%>'
Expand Down Expand Up @@ -5202,6 +5212,15 @@ template daeExpCall(Exp call, Context context, Text &preExp /*BUFP*/,
'<%retVar%>'
end daeExpCall;

template daeExpTailCall(list<DAE.Exp> es, list<String> vs, Context context, Text &preExp, Text &varDecls)
::=
match es
case e::erest then
match vs
case v::vrest then
let exp = daeExp(e,context,&preExp,&varDecls)
'_<%v%> = <%exp%>;<%\n%><%daeExpTailCall(erest, vrest, context, &preExp, &varDecls)%>'
end daeExpTailCall;

template daeExpCallBuiltinPrefix(Boolean builtin)
"Helper to daeExpCall."
Expand Down
16 changes: 16 additions & 0 deletions Compiler/susan_codegen/SimCode/SimCodeTV.mo
Expand Up @@ -1310,6 +1310,14 @@ package DAE
Exp after;
end OP_DERIVE;
end SymbolicOperation;

uniontype TailCall
record NO_TAIL
end NO_TAIL;
record TAIL
list<String> vars;
end TAIL;
end TailCall;
end DAE;


Expand Down Expand Up @@ -1892,6 +1900,14 @@ package Util
replaceable type Type_a subtypeof Any;
end listUnion;

function listThreadTuple
replaceable type Type_b subtypeof Any;
input list<Type_a> inTypeALst;
input list<Type_b> inTypeBLst;
output list<tuple<Type_a, Type_b>> outTplTypeATypeBLst;
replaceable type Type_a subtypeof Any;
end listThreadTuple;

end Util;


Expand Down

0 comments on commit 8dc2c98

Please sign in to comment.