in TRMC, still apply normal TCE

This commit is contained in:
Folkert 2023-06-24 19:45:44 +02:00
parent 9d10389c2b
commit ae47cc5171
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
3 changed files with 121 additions and 9 deletions

View file

@ -603,6 +603,7 @@ fn trmc_candidates_help<'a>(
#[derive(Clone)]
pub(crate) struct TrmcEnv<'a> {
lambda_name: LambdaName<'a>,
/// Current hole to fill
hole_symbol: Symbol,
/// Pointer to the first constructor ("the head of the list")
@ -672,6 +673,18 @@ impl<'a> TrmcEnv<'a> {
}
}
fn is_tail_recursive_call(
lambda_name: LambdaName,
symbol: Symbol,
expr: &Expr<'a>,
next: &Stmt<'a>,
) -> Option<Call<'a>> {
match next {
Stmt::Ret(s) if *s == symbol => Self::is_recursive_expr(expr, lambda_name),
_ => None,
}
}
fn ptr_write(
env: &mut Env<'a, '_>,
ptr: Symbol,
@ -747,6 +760,7 @@ impl<'a> TrmcEnv<'a> {
let trmc_calls = trmc_calls.confirmed().map(|s| (s, None)).collect();
let mut this = Self {
lambda_name: proc.name,
hole_symbol,
head_symbol,
joinpoint_id,
@ -821,6 +835,20 @@ impl<'a> TrmcEnv<'a> {
return self.walk_stmt(env, next);
}
if let Some(call) =
Self::is_tail_recursive_call(self.lambda_name, *symbol, expr, next)
{
// turn the call into a jump. Just re-use the existing hole
let mut arguments = Vec::new_in(arena);
arguments.extend(call.arguments);
arguments.push(self.hole_symbol);
arguments.push(self.head_symbol);
let jump = Stmt::Jump(self.joinpoint_id, arguments.into_bump_slice());
return jump;
}
if let Some(cons_info) = Self::is_terminal_constructor(stmt) {
// figure out which TRMC call to use here. We pick the first one that works
let opt_recursive_call = cons_info.arguments.iter().find_map(|arg| {