跳轉到內容

Oberon/ETH Oberon/Tutorial/編譯器

來自 Wikibooks,開放世界中的開放書籍

這些教程頁面由 André Fischer (afi) 編寫,Hannes Marais 提供編輯協助,託管在 ETHZ,並保留在 ETH 許可 下。相關內容可以在系統中透過 Book.Tool 找到。擴充套件內容也可在 紙質版 上找到。一些教程頁面在 WayBack 存檔 中。

編譯器、構建器和分析器使用者指南

教程目標

[編輯 | 編輯原始碼]

學習使用 Oberon 編譯器及其稱為構建器的前端。

預計時間:30 分鐘。

編譯器的輸入是文字。這些文字方便地在文字檢視器中使用系統編輯器[1]建立。以下命名約定 (廣泛使用) 建議用於儲存源程式的檔案

name.Mod 其中 name 通常對應於模組的名稱 (MODULE name;)。

有關 Oberon 程式語言的介紹,請參閱 有關 Oberon 的文獻。但學習一門新的程式語言的唯一方法是閱讀和編寫該語言的程式。

第一個例子

[編輯 | 編輯原始碼]

第一個程式對於所有程式語言都是一樣的!在 Oberon 中,編寫 hello, world 的程式是

MODULE Hello;
 IMPORT Out;

 PROCEDURE World*;
 BEGIN
  Out.String("hello, world");
  Out.Ln
 END World;

END Hello.

要學習如何使用編譯器,請按照以下步驟操作

  1. 標記 上面的文字並執行 Compiler.Compile *[2]
  2. 觀察 Oberon 日誌中的訊息
    正在編譯 Hello 33
    模組名稱後面的數字是現在儲存在當前目錄中的目標檔案的大小。
  3. 執行 Hello.World 並觀察日誌中的輸出 hello, world。

使用編譯器

[編輯 | 編輯原始碼]

編譯器是 Oberon 系統的重要組成部分。除了核心的一部分,Oberon 系統 3 是用原始的 Oberon 語言實現的。提供的編譯器是 Oberon-2 編譯器。原則上,任何 Oberon-2 編譯器都與系統 3 相容,並且可以使用 Oberon-2 編寫和編譯系統 3 程式。 編譯器可以生成兩種型別的目標檔案:包含目標機器程式碼的經典本地目標檔案,或者預設情況下,瘦二進位制檔案。瘦二進位制檔案是一種新的目標檔案形式,它根本不包含目的碼,而是一個模組內容的行動式描述,這使得這些檔案完全獨立於最終的目標機器 (平臺無關)。目的碼生成是由模組載入器 (取決於底層硬體) 在執行時進行的,並且與載入傳統目標檔案的時間一樣長。

模組 Compiler 只匯出兩個命令,它們在 Compiler.Tool 中的幾個變體中都有文件,並在下面描述。

編譯原始碼(s) - Compiler.Compile

[編輯 | 編輯原始碼]

Compiler.Compile @[\options] 編譯從最近的文字選擇開始的原始碼。

Compiler.Compile *[\options] 編譯標記的檢視器的原始碼。

這兩個第一個命令變體允許直接從文字編輯器編譯模組:不需要先儲存文字。

Compiler.Compile {[\dst=pathName] [\options] {fileName[\options]}}~ | ^ 編譯引數列表中命名的檔案的文字。pathName 指示編譯器將新目標檔案儲存在指定的子目錄中。

options

s - 啟用生成新的 symbol 檔案
e - 啟用生成 extended 符號檔案
u - 如果目標檔案是最新的,則抑制編譯
w - 啟用生成 warning 訊息

編譯一系列模組時,檔名順序必須符合模組匯入層次結構:從底層到頂層;也就是說,模組的客戶端必須在模組本身之後編譯。您可以透過使用 構建器 功能來避免這種情況。請注意,每個檔名後都可以跟選項。

以下選項僅在編譯器必須生成本地目標檔案時才有效。這些檔案跨平臺邊界可移植。因此,這些選項應僅在編寫使用低階模組 SYSTEM 或內建 SIZE 函式的擴充套件時使用。示例:Win.Audio.Mod

N - nable 生成本地目標檔案
a - 抑制為 ASSERT 函式生成程式碼
p - 抑制將本地 pointers 初始化為 NIL
x - 停用 Index 檢查
n - 停用 NIL 檢查
t - 停用 Type 檢查
v - 啟用 Overflow 檢查
c - 停用 Range Checks
r - 抑制生成 ref-info
d - 生成 MacsBug debugger 資訊 (MacOberon)
f - find 對應於所選程式計數器值的文字位置
g - 抑制此次編譯後的 garbage 收集

如果抑制垃圾收集,編譯執行速度更快,但如果使用了太多記憶體或太多檔案,則可能無法完成編譯 (將捕獲)。

指定目標檔案路徑 - Compiler.SetDestPath

[edit | edit source]

Compiler.SetDestPath pathName 指示編譯器將新的目標檔案儲存在指定的子目錄中。

指導載入精簡二進位制檔案

[edit | edit source]

以下命令影響精簡二進位制檔案的載入

OMI.AssertsOn / OMI.AssertsOff 啟用/停用為 ASSERTS 函式生成程式碼。

OMI.ChecksOn / OMI.ChecksOff 啟用/停用索引檢查。

OMI.RefsOn / OMI.RefsOff 啟用/停用生成詳細引用資訊。

這些命令可以方便地放在 Configuration.Text 檔案中。

在執行之前解除安裝模組

[edit | edit source]

如果您對模組進行更改,並在使用(即載入)後重新編譯它,您必須使用 System.Free 命令或使用滑鼠將其解除安裝

當滑鼠焦點位於命令名稱 M.P 上並且按下滑鼠中鍵時,□ ■  左鍵點選會解除安裝包含該命令的模組 M 並載入它的新副本,然後執行該命令。

程式設計師提示和警告: 這在開發和除錯 Oberon 過程時非常有用。這是一個方便的快捷方式來執行 System.Free 命令,但只有在模組 M 沒有客戶端時才會解除安裝它。因此,請記住 System.Free 以及 Builder.Free 提供了額外的可能性。

如果您的更正沒有產生任何影響,請不要感到驚訝:舊的 模組版本仍在控制中!您經常會忘記強制系統使用更新的版本。

以下示例應有助於具體化之前所說的話

MODULE Client;
  IMPORT Hello;

  PROCEDURE MyAction*;
  BEGIN Hello.World
  END MyAction;

END Client.
  1. 選擇模組文字的開頭
  2. 執行 Compiler.Compile @
  3. 執行 Client.MyAction
  4. 執行 System.Free Hello ~
  5. 觀察並解釋日誌訊息:Hello 解除安裝失敗

編譯修改後的示例

[edit | edit source]
MODULE Hello;
  IMPORT Out;

  PROCEDURE World*;
  BEGIN
    Out.String("hello, world");
    Out.Ln
  END World;

END HELLO.
  1. 修改文字 "hello, world"(例如 "Hello Oberon")
  2. 執行 Compiler.Compile *(即重新編譯程式)
  3. 執行 Hello.World 並檢視 Oberon 日誌中如何顯示相同的 "hello, world"。
  4. 強制系統解除安裝模組並使用滑鼠中鍵 + 左鍵點選執行命令 Hello.World 的新版本。

定位和糾正語法錯誤

[edit | edit source]
MODULE Hello;
  IMPORT Out;

  PROCEDURE World*;
  BEGIN
    Out.String("hello, world");
    Out.Ln
  END World;

END HELLO.
  1. 刪除程式中的分號
  2. 將插入符號移動到文字中的另一個位置
  3. 執行 Compiler.Compile *
      然後 Oberon 日誌顯示
     compiling Hello pos nn err 39
  4. 選擇包含錯誤訊息的行,然後單擊 Oberon 日誌選單欄中的 [Locate] 按鈕。這將把插入符號設定在缺少分號的位置。錯誤可以很容易地糾正。

除錯編譯器檢測到的語法錯誤

[edit | edit source]

編譯器檢測到的錯誤在 Oberon 日誌中以以下形式的訊息報告
pos <錯誤位置> err <錯誤編號>

含義:錯誤 <錯誤編號> 發生在源文字中的位置 <錯誤位置>。

以下過程將插入符號放置在源文字中的錯誤位置

  1. 確保源文字出現在檢視器中
  2. 標記檢視器
  3. 在 Oberon 日誌中選擇包含錯誤訊息的行
  4. 單擊選單欄中的 [Locate] 按鈕或
  5. 執行命令 TextDocs.Locate 或
  6. 執行命令 Edit.Locate.

在某些版本中,Oberon 編譯器錯誤編號及其簡短說明列在 OberonErrors.Text 中。在 PlugIn Oberon 中,它執行在各種 MS Windows 系統上,該檔名為 OP2.Errors。在 Oberon 2.3.7 中,類似的列表位於 Oberon.Text 的 Errors 部分[3]

您需要重新編譯模組,直到沒有報告錯誤。但是,可能會發出警告,但它們不被視為錯誤,因此會建立目標檔案。

陷阱檢視器

[edit | edit source]

如果命令執行失敗,執行時錯誤會導致程式異常終止,並且會在文字檢視器 'System.Trap' 中顯示錯誤報告。導致陷阱的錯誤由陷阱程式碼標識,顯示某些系統暫存器的內容,並顯示過程啟用堆疊,從呼叫堆疊頂部的過程開始。所有標量變數和字串以及它們的值也列出。

MODULE Trap;
  VAR arr: ARRAY 3 OF INTEGER;

  PROCEDURE count(n: INTEGER);
  BEGIN arr[n] := n; count(n+1)
  END count;

  PROCEDURE ForceIt*;
  BEGIN count(0)
  END ForceIt;

END Trap.
  1. 選擇模組文字的開頭
  2. 執行 Compiler.Compile @
  3. 執行 Trap.ForceIt 並研究檢視器的內容。

最初,陷阱程式碼在 OberonErrors.Text 的末尾進行了解釋。隨後,當陷阱檢視器被建立或增強時,OberonErrors.Text 中的解釋變得多餘並被刪除。

為了找到失敗的語句,只需顯示源程式並標記其檢視器。然後在陷阱檢視器中選擇包含感興趣過程名稱的行,並使用 "\d" 或 "\f" 選項重新編譯程式。

使用構建器

[edit | edit source]

Builder 為上面描述的 Oberon 編譯器提供了一個方便的前端。它確保模組文字以正確的順序呈現給編譯器,無論引數列表中檔名的順序如何。但是,它不是真正的 make 工具:必須指定所有要編譯的模組。請注意,引數列表必須包含檔名:這些檔名可能與模組名稱不同,但這只是一個約定問題。Builder 模組命令在 Builder.Tool 中有記錄。

編譯源文字 - Builder.Compile

[edit | edit source]

Builder.Compile [\options] * 編譯標記的檢視器的源文字。文字中插入的所有錯誤標記都將被刪除。

Builder.Compile [\options] ({fileName}~ | ^ | *) 編譯引數列表中命名的檔案的文字,自動確定模組的正確編譯順序。必須指定所有要編譯的模組,即它不是真正的 make 工具。選項與 Compiler.Compile 命令的選項相同。

有效處理編譯器檢測到的錯誤

[edit | edit source]

Builder.MarkErrors [^] 當選擇包含編譯器在 Oberon 日誌中寫入的錯誤訊息時,此命令會為該訊息以及所有後續訊息在標記的文字中插入錯誤標記。錯誤標記是一個特殊的(構建器)小工具,它顯示在程式文字中該位置發現的錯誤程式碼的編號。以下錯誤訊息

pos 111 err 4

將在位置 111 處放置 4

Builder.NextError 將插入符號前進到下一個錯誤標記。當到達文字末尾時,搜尋將環繞回到開頭。

Builder.ClearErrors 刪除標記文字中的所有錯誤標記。由 Builder.Compile * 命令自動執行。

解除安裝模組 - Builder.Free

[edit | edit source]

Builder.Free {fileName}~ | ^ 以正確的順序解除安裝引數列表中命名的每個模組。由於檔名必須出現在引數列表中,因此此命令只能釋放源文字可用的模組。要解除安裝其他模組,請使用 System.Free.

插入模組圖示 - Builder.InsertHierarchy

[edit | edit source]

Builder.InsertHierarchy {fileName}~ | ^ 在插入符號處為引數列表中命名的每個模組插入一個圖示。圖示以正確的編譯順序插入。每個圖示都帶有檔名作為標題,並且它的Cmd 屬性值為 "Desktops.OpenDoc '#Caption '". Compiler.Panel 中可以找到此類圖示的示例。

使用分析器

[edit | edit source]

分析器為 Oberon 編譯器提供了一個便捷的補充,用於在語法正確的程式文字中查詢其他潛在錯誤。編譯器錯誤首先報告。不生成目的碼。分析器定位

  • 未匯出的專案(變數/常量/型別/欄位),這些專案已宣告但從未使用過,在初始化 (*) 之前使用過,從未初始化過,以及初始化過但從未使用過。
  • 未匯出的 [型別繫結] 過程,這些過程從未呼叫過。
  • 從未使用的匯入模組。

(*) 對於在不同範圍內宣告的變數,不會產生警告(但是,請參閱選項 \u)。

分析器模組命令在 Analyzer.Tool. 中有記錄。

分析源文字 - Analyzer.Analyze

[編輯 | 編輯原始碼]

Analyzer.Analyze @[\options] 分析從最新文字選擇開始的源文字。

Analyzer.Analyze *[\options] 分析標記檢視器的源文字。

這兩個命令的第一個變體允許直接從文字編輯器分析模組:無需先儲存文字。

Analyzer.Analyze {fileName[\options]}~ | ^ 分析引數列表中命名的檔案的源文字。

Analyzer.Analyze 透過以下形式的訊息警告 Oberon 日誌中可能出現的錯誤

pos <error position> warning <warning number>

請參閱 除錯編譯器檢測到的語法錯誤.

Analyzer.Analyze 還報告模組中語句(賦值、if、while、過程呼叫等)的數量。這對於確定程式的複雜性(而不是行數)很方便。

錯誤標記可以插入源文字中,如 有效處理編譯器檢測到的錯誤 中所述。

可以透過指定一個或多個 選項 獲得更多資訊

i (intermediate) - 定位
- 已經在外部範圍內宣告的專案。
- 對中間專案的使用或賦值,例如在外部範圍內宣告的區域性變數/引數。
s (evaluation sequence) - 定位引數列表中出現函式呼叫的多引數過程的呼叫。引數的求值順序可能會影響這些函式的副作用。
t (type-bound) - 定位
- 型別繫結過程的重新定義。
- 在擴充套件型別中對型別繫結過程的重新定義。
u (used) - 定位在不同範圍內宣告並在設定之前使用的變數。
v (VAR parameter) - 定位用作 VAR 引數的變數,因此不能確保已初始化這些變數。
x (exported) - 定位已宣告但模組本身未使用、在初始化之前使用、從未初始化或已初始化但從未使用的匯出專案。
[ A | B | C | E | N | O | S | T | U ]

A

Analyzer.Analyze
Analyzer.Tool

B

Builder.ClearErrors
Builder.Compile
Builder.Free
Builder.InsertHierarchy
Builder.MarkErrors
Builder.NextError
Builder.Tool

C

Compiler.Compile
Compiler.Panel
Compiler.SetDestPath
Compiler.Tool

E

錯誤標記

N

本地目標檔案

O

OberonErrors.Text

S

精簡二進位制檔案

T

陷阱檢視器

U

解除安裝模組


修訂,afi 1996 年 12 月 10 日
安裝於 1997 年 05 月 30 日


  1. 在 V2(Ceres Oberon)中 Edit.Open <fileName> 。在 ETH Oberon 中 Edit.Open <fileName>ET.Open <fileName> 。在 V5(FPGA Oberon)中 Edit.Open <fileName>
  2. 可以在 ETH Oberon 中使用 MM 執行的命令是深紅色。目標超連結是藍色。非目標超連結是猩紅色。
  3. 郵件列表有一個從 2023-01-07 開始的討論。
華夏公益教科書