C# 嵌套递归函数的编译

C# 嵌套递归函数的编译,c#,.net,language-agnostic,compiler-construction,dynamic-language-runtime,C#,.net,Language Agnostic,Compiler Construction,Dynamic Language Runtime,我正在创建一个玩具动态语言(热衷于javascript),虽然我的实现是在DLR之上,但我认为这个问题的解决方案将是与语言/平台无关的 我在编译递归函数或相邻的相互递归函数方面没有问题。但是编译嵌套的相互递归函数变得更加困难 我用来测试的示例函数如下 void f(int x) { void g(int y) { if((x + y) < 100) { f(x + y); } else { print(x + y); } } g(x); } void f(i

我正在创建一个玩具动态语言(热衷于javascript),虽然我的实现是在DLR之上,但我认为这个问题的解决方案将是与语言/平台无关的

我在编译递归函数或相邻的相互递归函数方面没有问题。但是编译嵌套的相互递归函数变得更加困难

我用来测试的示例函数如下

void f(int x) {
 void g(int y) {
  if((x + y) < 100) {
   f(x + y);
  } else {
   print(x + y);
  }
 }
 g(x);
}
void f(int x){
空g(整数y){
如果((x+y)<100){
f(x+y);
}否则{
打印(x+y);
}
}
g(x);
}

我认为解决这个问题的方法必须非常通用(也许我错了),而不是针对DLR,我假设我必须以某种方式将g的内部定义提出来,在f之前定义它,并且仍然保留闭包上下文。

我知道您正在创建一种动态语言,但我认为相同的原则适用于非动态语言-您仍然有一个符号表,并且您仍然必须通过多个过程处理源代码

如果您在代码生成阶段之前创建语义树,这很容易。对函数的调用指向将包含函数语义定义的对象(节点)。或者它只是一个表示(语义上)调用此函数的节点。由于对函数的调用不需要知道函数包含什么,因此只需指向符号表项的指针就可以了

如果您正在进行优化(尾端递归?),那么您需要先执行两个过程,然后才能分析这种类型的优化。这对于我见过的所有编译器来说都是正常的,因为这个阶段发生在语义/词法分析之后


我想这个图表可以显示我所说的内容(不过它有两种不同输入语言的额外部分)。

闭包通常表示为组合函数指针和参数列表。实际上,第一步是将所有嵌套函数提升到全局范围,并将其环境中的任何绑定变量作为参数。这相当于:

void _f(int x) 
{ 
  closure g = closure(_g,x);       
  call(g,x);  
}

void _g(int x, int y) 
{
  ...;
}

一旦有了“闭包”和“调用”原语,它就可以工作了。在静态语言中,
closure()
只保留相关变量。在动态语言中,
closure()
必须保持整个上下文堆栈可用,以防函数需要它

您试图实现的是一个y组合器


我要说的是,y-combinator不是我想要的,我已经用python编写了自己的y-combinator,我不知道这将如何解决在封闭函数本身的闭包函数中引用封闭函数的问题。