鸚鵡虛擬機器/多型容器 (PMC)
多型容器 (PMC) - 以前稱為“鸚鵡魔法餅乾” - 是鸚鵡的基本資料型別之一,也是最強大和靈活的資料型別之一。PMC 非常類似於類物件,具有資料儲存和關聯的類方法。PMC 包括所有聚合資料型別,包括陣列、關聯陣列(雜湊)、異常、結構和物件。鸚鵡附帶了一組核心 PMC,但可以為特定程式或語言新增新的 PMC。
PMC 是用我們稱之為“PMC 指令碼”的類似 C 的語言編寫並編譯的。PMC 可以直接內建到鸚鵡中,也可以單獨編寫並在以後載入。在執行時載入的 PMC 稱為“動態 PMC”,簡稱 DYNPMC。
PMC 定義是用類似 C 的語言編寫的,該語言使用名為 pmc2c.pl 的特殊 PMC 編譯器程式轉換為 C 程式碼。轉換為 C 程式碼後,PMC 將包含在鸚鵡構建過程中。
PMC 編譯器 pmc2c.pl 需要執行許多工。它將 PMC 轉換為合法的 C 語法,將函式名插入到相應的表格中,並將有關 PMC 及其方法的資訊匯出到鸚鵡系統的其他部分。
用於編寫 PMC 的指令碼語言基於 C。實際上,它主要是 C,但也包含一些額外的關鍵字和結構。PMC 編譯器將 PMC 檔案轉換為 C 程式碼以進行編譯。所有標準 ANSI C 89 程式碼都可以在 PMC 檔案中使用。在這裡,我們將列出一些新增內容。
PMC 的所有方法和 VTABLE 必須包含在 PMC 類宣告中
pmclass NAME {
}
除了只給出 PMC 的名稱外,您還可以指定單一繼承。
pmclass NAME is SUPERNAME { }
其中 SUPERNAME 是父 PMC 類的名稱。在您的 PMC VTABLE 方法中,您可以使用 SUPER 關鍵字來訪問父類的 VTABLE 方法。
您還可以使用 needs_ext 關鍵字分配一個名為 PMC_EXT 的額外儲存區域。PMC_EXT 是一個額外的結構,可以分配來幫助進行特殊操作,例如在多個直譯器之間共享。如果 PMC 不是自動執行緒安全的,則應新增 PMC_EXT。
| 說明符 | 含義 |
|---|---|
| is SUPERNAME | 指定父類(如果有) |
| need_ext | 需要 PMC_EXT 進行特殊處理 |
| abstract | 該類是抽象的,不能例項化 |
| no_init | PMC 沒有 Parrot 可以呼叫的 init VTABLE 方法。通常,Parrot 在首次建立 PMC 時會呼叫 init 方法。如果您不需要,請使用 no_init。 |
| provides INTERFACE | INTERFACE 是標準介面之一,PMC 可以像該型別的物件一樣使用。介面是“array”、“hash” |
與普通 C 一樣,您可以定義額外的函式來幫助您進行計算。這些函式應該用普通的 C 語言(沒有任何特殊關鍵字或值)編寫,並且應該在 C<pmclass> 定義之外定義。
可以使用 ATTR 關鍵字為 PMC 提供一組自定義資料欄位屬性。ATTR 允許 PMC 擴充套件以包含自定義資料結構,這些資料結構由鸚鵡的記憶體子系統自動管理。以下是一個示例
pmclass Foo {
ATTR INTVAL bar;
ATTR PMC baz;
...
}
屬性儲存在一個自定義資料結構中,可以使用與 PMC 相同名稱的宏(但全部大寫)訪問。
Parrot_Foo_attributes * attrs = PARROT_FOO(SELF); attrs->bar = 7; /* it's an INTVAL */ attrs->baz = pmc_new( ... ) /* It's a PMC */
注意屬性結構的型別名稱是如何 Parrot_、接著是 PMC 的名稱(使用與 pmclass 定義中相同的首字母大小寫)、最後是 _attributes。返回該結構的宏是 PARROT_,接著是 PMC 的名稱(全部大寫)。
VTABLE 介面和 VTABLE 中的特定函式在 Parrot 1.0 版本釋出之前可能會發生變化。
PMC 可以為任意數量的 VTABLE 介面提供定義。任何未定義的介面都將回退到預設實現,該實現會丟擲錯誤。VTABLE 介面必須遵循預定義的格式,嘗試定義不是正常介面之一或不使用與正常介面相同的引數列表和返回值的 VTABLE 介面會導致丟擲錯誤。
所有 VTABLE 和 METHOD 宣告的引數可以是 INTVAL、FLOATVAL、STRING 或 PMC,因為這些是唯一可以從 PIR 程式碼中傳遞的值。VTABLE 介面使用 VTABLE 關鍵字定義,PMC 上的方法可以使用 METHOD 關鍵字定義。
所有 PMC 都擁有標準 API,它是一個所有 PMC 共用的介面。這個標準介面被稱為 **VTABLE**。VTABLE 是一個包含大約 150 個標準函式的列表,這些函式被稱為 “VTABLE 介面”,它們實現了 PMC 的基本、通用行為。所有 PMC 都實現了這些介面,儘管如果一個 PMC 沒有顯式提供這些介面,它可以從父 PMC 類繼承,或者預設丟擲異常。
VTABLE 方法可以透過兩種方式定義:在使用類 C 語言的 PMC 檔案中定義,或者在 PIR 中使用 `:vtable` 函式限定符定義。VTABLE 對應於可以對任何物件執行的一些基本操作,例如算術運算、類操作、型別轉換操作(轉換為 INTVAL、FLOATVAL、STRING 或 PMC)和其他常見操作。無論 VTABLE 方法如何定義,它們都必須具有非常特定的名稱。
VTABLE 函式都有固定的名稱和引數列表。在實現新的 VTABLE 方法時,必須嚴格遵循此規範,否則可能會出現多個編譯錯誤和警告。要檢視所有 vtable 方法及其預期函式簽名的列表,您可以檢視標頭檔案 `include/parrot/vtables.h`。
在 VTABLE 方法內部,可以使用幾個可用的關鍵字。
- SELF
- 當前 PMC
- INTERP
- 鸚鵡直譯器
- SUPER
- 父 PMC 類。
您還可以使用標準的點符號引用當前 PMC 的其他方法或 vtable 方法,例如
SELF.VTABLE_OR_METHOD_NAME()
如果您想將所有或部分處理過程預設到父類(如果您有父類),可以使用 SUPER() 函式來實現。您未實現的任何 vtable 方法都將自動預設到父類(如果有)或預設父類。
除了 VTABLE,PMC 還可以提供一系列名為 **方法** 的自定義介面函式,以提供額外的功能。請注意,方法不像 VTABLE 方法那樣整合到 PIR 運算子或 PASM 操作碼中。方法可以在單個 PMC 的類 C 語言指令碼中編寫,也可以在 PIR 中為使用者定義的 PMC 子類編寫。
方法定義後,可以使用 `PCCINVOKE` 命令在 PMC 檔案中訪問它。
所有 vtable 方法的完整列表位於 附錄 中。
- 內建 PMC 附錄
- http://www.parrotcode.org/docs/pdd/pdd04_datatypes.html
- http://www.parrotcode.org/docs/pdd/pdd17_pmc.html
- http://www.parrotcode.org/docs/pmc2c.html
- http://www.parrotcode.org/docs/pmc.html