2012-10-03 36 views
1

我已經爲簡單的堆棧機器編寫了一個小型編譯器。它只能通過大量的虛擬機黑客來組裝和處理範圍/功能。那是我在字節碼本身中定義了作用域和範圍變量定義。如何在使用手寫編譯器生成字節碼時處理範圍

我可以得到一些關於如何處理範圍的指示。

我面臨的問題主要是,我如何讓它知道什麼時候以及何時不用覆蓋外部變量的變量以及類似的內容。字節碼是可變的,我寧願改變它。

其他問題包括如何在返回後保留外部變量。所以變量仍然有其價值。我可以將它推入堆棧,但我可能有很多變量。

我認爲有一些編譯工作是爲了檢查這些事情,但我想不出做什麼需要做。

+0

您是否在談論關閉? – delnan

+0

Sorta,但沒有。基本上如何生成字節碼來處理帶有作用域的變量,或者是其中的例子(這可能更有幫助)。 – Chase

回答

2

一種方法是rename variables at compile time to ensure there is no masking.所以:

{ 
    declare foo; 
    foo = assignment; 
    { 
    declare foo; 

    foo = another_assignment; 
    another_use = foo; 
    } 
    use = foo; 
} 

等同於:

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

    foo_1 = another_assignment; 
    another_use = foo_1; 
    } 
    use = foo_0; 
} 

在編譯時,你保持一個 '重命名棧' 每個變量。並且:

  1. 無論何時您看到一個聲明,都會生成一個新名稱並將其推送到相應變量的重命名堆棧。

  2. 當您看到作業/用法時,將名稱替換爲堆棧頂部的任何名稱。

  3. 當您離開作用域時,將其從堆棧中彈出。

+0

謝謝,這實際上非常有幫助。我沒有想到爲每個變量保留一個單獨的重命名堆棧。我試圖在範圍基礎上進行。這種方式更加優雅。謝謝! – Chase

+0

那麼我將如何去處理遞歸語句呢?這是一個讓我煩惱的問題。 – Chase

+1

由於範圍的掩蔽可以按我解釋的方式*在編譯時*處理,即通過重命名來避免掩蔽。另一方面,遞歸調用(甚至是常規調用)應該在運行時處理*。即在調用棧中。它完全是一個完全不同的問題。除此之外還有一個堆棧;) – ArjunShankar

相關問題