Forth/FORTH 中的解析,或“編譯器怎麼了”
要了解 FORTH 語言,我們可以從檢查當您向其輸入命令列時 FORTH 會做什麼開始。以下是“解釋”(“立即執行”)或“編譯”(“稍後執行”)迴圈的正式定義。雖然可能很難看清森林中的樹木,但讓我們簡要描述整個過程,然後重新回顧並更詳細地解釋其意義。
FORTH 透過使其非常統一簡化了人機指令的過程。要向 FORTH 系統發出指令,需要鍵入一系列詞語到計算機中。然後,FORTH 從第一個到最後一個“讀取”這些詞語。為了判斷一個詞語在哪裡結束,另一個詞語從哪裡開始,使用了一個簡單的規則:詞語之間用一個或多個 ASCII 空格字元 (程式碼 32) 分隔。每個詞語都按鍵入的順序進行處理 (或從原始檔中讀取)。
當每個傳入的詞語從輸入流中分離出來時,FORTH 將確定它在“字典”中是否已經存在對它的定義。FORTH 指的是其符號表,它被安排為“字典”結構的一部分。在每個字典條目的名稱欄位中搜索與詞語名稱的匹配項 (從最近定義的詞語開始,到字典中最舊的詞語結束)。如果在字典中找不到該詞語,FORTH 將考慮輸入詞語是否可以被解釋為當前基數中的數字。如果不是,則該輸入對 FORTH 來說不可理解,它將拒絕該輸入,並顯示一條訊息,表明字典中找不到這樣的詞語。
如果找到了定義或輸入是可識別的數字,FORTH 將考慮是否應該立即執行此命令或稍後執行。如果答案是“立即執行”(“解釋”),它將執行與其字典條目關聯的詞語的定義,或將該數字壓入 FORTH 的中央資料交換機,即堆疊。如果答案是“稍後執行”(“編譯”),這通常意味著我們正在將一個新的詞語新增到字典中,使其成為最近定義的詞語。
因此,我們將對輸入詞語或數字的引用作為正在定義的詞語的定義中的下一個條目。它將在稍後按順序執行,但僅在有人請求執行我們正在定義的新詞語時才會執行。
然後,我們重複上述過程來解析輸入流中的下一個詞語。這將持續進行,直到沒有更多輸入。
上述過程有哪些含義?它與其他方法相比如何?(注意:在以下部分中,術語“詞語”和“子例程”可以互換使用,以強調其平行性。)
- 可訪問性
字典中的任何詞語都可以從命令列呼叫。因此,字典中的每個詞語及其包含的應用程式都可以立即單獨測試。只需從命令列呼叫有問題的詞語即可。找到一個錯誤?與傳統的工具鏈不同,您不需要重新編譯應用程式來包含面向除錯的自定義呼叫以檢視內部子例程。只需從命令列呼叫失敗的詞語。失敗?檢視它的定義。按順序鍵入這些詞語到命令列。這些詞語中的任何一個失敗了嗎?重複。可以在不需要採取特殊措施使內部子例程可呼叫的情況下隔離問題。
- 詞彙表。
但這並不意味著每個內部詞語都需要一直對客戶可用,包括那些可能例如刪除其檔案的危險詞語。詞語組可以組織在詞彙表列表中,並且特定的詞彙表列表可以提供給特定的命令列。
- 自然地阻止迴圈定義和思考:詞語必須按合理的自然順序新增到字典中。在構建詞語的定義時,如果呼叫了字典中尚未存在的詞語,則會收到“字典中不存在詞語”的錯誤。因此,必須組織一系列詞語,從僅依賴自身的基石詞語開始,然後是依賴它們的詞語層,然後是依賴它們的詞語。這有助於以邏輯的方式構建字典。
- 簡化和合並工具鏈的編譯和載入部分
傳統的工具鏈具有不同的編譯和載入階段。編譯器將目的碼模組放置到庫中,這些庫稍後以靜態或動態方式載入和連結。只有這樣,才會生成缺少子例程的報告。FORTH 簡化併合並了這些步驟。這就像每個庫模組都被載入並被賦予記憶體中的固定地址。一旦它的地址確定,呼叫它的模組就可以被載入 (字典中的後續詞語)。然後,這些呼叫詞語可以直接指向它們想要呼叫的詞語的入口點的記憶體地址,與傳統連結器的外部引用過程相比。
- 原始碼和目的碼之間的區別消失了。
事實證明,這是其他計算機語言不必要的負擔,畢竟可能不是一個有用的概念。在這門語言中,我們看到了定義一個新詞語的小開銷 (儲存它的名稱,將其附加到字典的其餘部分,以及其他包裝開銷)。將詞語的“原始碼”定義編譯成“目的碼”定義,驚人的是,僅僅是將源文字中找到的每個詞語的名稱從 ASCII 轉換為其入口點的相應記憶體地址。這個過程很容易反轉。編譯結果是刪除原始碼中的人類可讀註釋 (機器在目的碼中不需要它們,它無法讀取它們),並將每個呼叫的詞語的人類可讀名稱轉換為硬體使用的相應數值機器地址。作為充滿錯誤案例、與大腦作鬥爭的巨大位元組的神秘“編譯器”不再存在。只是一些定義明確的查詢。所有其他編譯學術到底有什麼用呢?
- 在這個系統中,**編譯**意味著將 (一個新詞語) 新增到字典的頂部。為此,每個被呼叫的詞語名稱都會從源文字中找到的 ASCII 名稱轉換為其入口點的相應記憶體地址。這個數字將新增到詞語的“目的碼”定義的末尾。