Compiler construction 使用手写编译器生成字节码时如何处理作用域

Compiler construction 使用手写编译器生成字节码时如何处理作用域,compiler-construction,scope,bytecode,stack-machine,Compiler Construction,Scope,Bytecode,Stack Machine,我已经为一个简单的堆栈机器编写了一个小编译器。它只能通过一些虚拟机黑客来组装和处理范围/功能。也就是说,我让它在字节码本身中定义作用域和作用域内变量定义 我可以得到一些关于如何处理范围的建议吗 我面临的问题主要是,我如何让它知道何时应该和何时不应该用内部变量覆盖外部变量,以及类似的问题。字节码是可变的,我更愿意更改它 其他问题包括如何在返回后将变量保留在外部。所以一个变量仍然有它的值。我可以把它推到堆栈中,但是我可以有很多变量 我认为需要做一些编译器工作来检查这些东西,但我想不出需要做什么来检查

我已经为一个简单的堆栈机器编写了一个小编译器。它只能通过一些虚拟机黑客来组装和处理范围/功能。也就是说,我让它在字节码本身中定义作用域和作用域内变量定义

我可以得到一些关于如何处理范围的建议吗

我面临的问题主要是,我如何让它知道何时应该和何时不应该用内部变量覆盖外部变量,以及类似的问题。字节码是可变的,我更愿意更改它

其他问题包括如何在返回后将变量保留在外部。所以一个变量仍然有它的值。我可以把它推到堆栈中,但是我可以有很多变量

我认为需要做一些编译器工作来检查这些东西,但我想不出需要做什么来检查这些东西。

一种方法是:

相当于:

{
   declare foo_0;
   foo_0 = assignment;
   {
     declare foo_1;

     foo_1 = another_assignment;
     another_use = foo_1;
   }
   use = foo_0;
}
编译时,每个变量维护一个“重命名堆栈”。以及:

  • 每当看到一个声明时,都会生成一个新名称并将其推送到相应变量的重命名堆栈中

  • 当您看到一个赋值/用法时,您将用堆栈顶部的名称替换该名称

  • 当您离开示波器时,您会将其从堆栈中弹出


  • 你说的是闭包吗?差不多,但不是。基本上是如何生成字节码来处理具有作用域的变量,或者更确切地说是其中的示例(可能更有用)。谢谢,这实际上非常有用。我没有想到为每个变量保留一个单独的重命名堆栈。我试图在范围的基础上做这件事。这条路要优雅得多。非常感谢。那么我该如何处理递归语句呢?这是一个一直困扰我的问题。由于作用域而产生的屏蔽可以按照我在编译时解释的方式处理,即通过重命名来避免屏蔽。另一方面,递归调用(甚至是常规调用)应该在运行时处理。i、 e.在调用堆栈中。这真的是一个完全不同的问题。除了这里还涉及到一个堆栈;)
    {
       declare foo_0;
       foo_0 = assignment;
       {
         declare foo_1;
    
         foo_1 = another_assignment;
         another_use = foo_1;
       }
       use = foo_0;
    }