gpt4 book ai didi

.net - 我可以构建尾调用递归优化表达式吗?

转载 作者:行者123 更新时间:2023-12-04 00:25:27 24 4
gpt4 key购买 nike

我尝试构建尾递归 Expression在 .NET 4.0 中。

我可以构建它,但是,尽管指定了 tailCall = true,但编译后的方法并未进行尾调用优化。 ,生成的 IL 没有 tail.前缀指令。

请告诉我如何构建尾调用优化递归 Expression ?

构建表达式如下。

using System;
using System.Linq.Expressions;

namespace ConsoleApplication2
{
public delegate int RecursiveFunc(RecursiveFunc function, int acc, int n);

internal class Program
{
private static void Main()
{
var funcParam = Expression.Parameter(typeof (RecursiveFunc));
var accParam = Expression.Parameter(typeof (int));
var nParam = Expression.Parameter(typeof (int));
var constZero = Expression.Constant(0, typeof (int));

var accumExpr = Expression.Add(accParam, nParam);
var decrimentExpr = Expression.Decrement(nParam);

var invokeExpr = Expression.Invoke(funcParam, funcParam,
accumExpr, decrimentExpr);

var testExpr = Expression.Equal(nParam, constZero);
var condExpr = Expression.Condition(testExpr, accParam,
invokeExpr);

var lambda = Expression.Lambda<RecursiveFunc>(condExpr,
"TailCall", true, new[] {funcParam, accParam, nParam});

var sumParam = Expression.Parameter(typeof (RecursiveFunc),
"Sum");

var method = lambda.Compile();

var ans = method(method, 0, 100);
Console.WriteLine(ans);
}
}
}

这个 lambda 表达式生成的 IL 在下面
.method public static int32 EvaluateTarget (
class [ConsoleApplication2]ConsoleApplication2.RecursiveFunc '',
int32 '',
int32 ''
) cil managed
{
// Method begins at RVA 0x2050
// Code size 25 (0x19)
.maxstack 7

IL_0000: ldarg.2
IL_0001: ldc.i4.0
IL_0002: ceq
IL_0004: brfalse IL_000b

IL_0009: ldarg.1
IL_000a: ret

IL_000b: ldarg.0
IL_000c: ldarg.0
IL_000d: ldarg.1
IL_000e: ldarg.2
IL_000f: add
IL_0010: ldarg.2
IL_0011: ldc.i4.1
IL_0012: sub
IL_0013: callvirt instance int32
[ConsoleApplication2]ConsoleApplication2.RecursiveFunc::Invoke(class
[ConsoleApplication2]ConsoleApplication2.RecursiveFunc, int32, int32)
IL_0018: ret
} // end of method AutoGeneratedType::EvaluateTarget

最佳答案

以下工作解决:

using System;
using System.Linq.Expressions;
using System.Reflection.Emit;

namespace ConsoleApplication2
{
public delegate int RecursiveFunc(RecursiveFunc doCall, RecursiveFunc function, int acc, int n);

internal class Program
{
private static void Main()
{
DynamicMethod dm = new DynamicMethod("DoInvokeWithTailCall", typeof(int), new Type[] { typeof(RecursiveFunc), typeof(RecursiveFunc), typeof(int), typeof(int) }, typeof(Program).Module);
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Ldarg_3);
il.Emit(OpCodes.Tailcall);
il.EmitCall(OpCodes.Callvirt, typeof(RecursiveFunc).GetMethod("Invoke"), null);
il.Emit(OpCodes.Ret);
RecursiveFunc doCall = (RecursiveFunc)dm.CreateDelegate(typeof(RecursiveFunc));

var doCallParam = Expression.Parameter(typeof(RecursiveFunc));
var funcParam = Expression.Parameter(typeof(RecursiveFunc));
var accParam = Expression.Parameter(typeof(int));
var nParam = Expression.Parameter(typeof(int));
var constZero = Expression.Constant(0, typeof(int));

var accumExpr = Expression.Add(accParam, nParam);
var decrimentExpr = Expression.Decrement(nParam);

//var invokeExpr = Expression.Invoke(funcParam, funcParam, funcParam, accumExpr, decrimentExpr);
var invokeExpr = Expression.Call(dm, doCallParam, funcParam, accumExpr, decrimentExpr);

var testExpr = Expression.Equal(nParam, constZero);
var condExpr = Expression.Condition(testExpr, accParam,
invokeExpr);

var lambda = Expression.Lambda<RecursiveFunc>(condExpr,
"TailCall", true, new[] { doCallParam, funcParam, accParam, nParam });

var method = lambda.Compile();

var ans = method(doCall, method, 0, 100);
Console.WriteLine(ans);
}
}
}

关于.net - 我可以构建尾调用递归优化表达式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7903074/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com