鸚鵡虛擬機器/多型容器 (PMCs)
多型容器 (PMCs) - 以前稱為 '鸚鵡魔法餅乾' - 是鸚鵡的基本資料型別之一,也是最強大、最靈活的資料型別之一。PMC 非常類似於類物件,具有資料儲存和關聯的類方法。PMC 包括所有聚合資料型別,包括陣列、關聯陣列(雜湊)、異常、結構和物件。鸚鵡帶有一套核心 PMC,但可以為特定程式或語言新增新的 PMC。
PMC 用我們稱之為“PMC 指令碼”的類 C 語言編寫並編譯。PMC 可以直接內建到鸚鵡中,也可以單獨編寫並在稍後載入。在執行時載入的 PMC 稱為“動態 PMC”,簡稱為 **DYNPMCs**。
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> 定義之外定義。
PMC 可以使用 ATTR 關鍵字獲得一組自定義的資料欄位屬性。ATTR 允許擴充套件 PMC 以包含自定義資料結構,這些資料結構由 Parrot 的記憶體子系統自動管理。以下是一個示例
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 類繼承,或者可以預設丟擲一個異常。
VTABLE 方法可以透過兩種方式之一定義,在 .pmc 中使用類 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 PMC 指令碼中編寫,也可以在 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