基本介紹
- 外文名:
- 特點:
歷史發展,語法,語言功能,模組化,安全與不安全,泛型,可追溯性,動態編程,面向對象,異常,多執行緒,
歷史發展
語法
語言的語法一個常見例子是Hello world程式。
MODULE Main;
IMPORT IO;
BEGIN
IO.Put("Hello World\n")
END Main.
Modula-3中的所有程式都至少有一個模組檔案,而大多數程式還包含一個客戶端用來訪問模組數據的接口檔案。 像其他語言一樣,Modula-3程式必須導出一個主模組,它可以是一個名為Main.m3的檔案,也可以是一個檔案可以調用EXPORT來導出主模組。
MODULE Foo EXPORTS Main
建議模組檔案名稱稱與實際模組名稱相同,但編譯器只會在不同的情況下提醒您。
語法中的其他約定包括命名接口T的導出類型,因為類型通常由它們的全名來限定,所以在名為Foo的模組內的類型T將被命名為Foo.T. 這有助於可讀性。 另一個類似的約定是在上面的OOP示例中命名公共對象Public。
語言功能
模組化
首先,所有編譯單元都是INTERFACE或實現MODULE,具有一種或另一種風格。一個接口編譯單元,從關鍵字INTERFACE開始,定義常量,類型,變數,例外和過程。實現模組以關鍵字MODULE開頭,提供實際代碼以及實現接口所需的任何其他常量,類型或變數。默認情況下,實現模組將實現相同名稱的接口,但是模組可以明確地將EXPORT輸出到不具有相同名稱的模組。例如,主程式為Main接口導出一個實現模組。
MODULE HelloWorld EXPORTS Main;
IMPORT IO;
BEGIN IO.Put("Hello World\n")
END HelloWorld.
任何編譯單元都可以導入其他接口,但禁止循環導入。 這可以通過從執行MODULE執行導入來解決。 使用FROM模組IMPORT Item [,Item] *語法可以導入導入模組中的實體,而不僅僅是模組名稱:
MODULE HelloWorld EXPORTS Main;
FROM IO IMPORT Put;
BEGIN
Put("Hello World\n")
END HelloWorld.
通常,只導入接口,並使用'點'符號訪問接口內的項目(類似於訪問記錄中的欄位)。一個典型的用法是為每個接口定義一個數據結構(記錄或對象)以及任何支持過程。在這裡主類型將得到名稱'T',並且使用MyModule.T 中的一個。
如果導入的模組與模組內的其他實體之間發生名稱衝突,則保留字AS可用於IMPORT CollidingModule AS X;
安全與不安全
某些功能被認為是不安全的,編譯器不能再保證結果是一致的(例如,與C程式語言接口時)。前綴INTERFACE或MODULE前面的關鍵字UNSAFE可用於告訴編譯器啟用該語言的某些低級功能。例如,一個不安全的操作是繞過使用LOOPHOLE的類型系統將一個整數的位複製到一個浮點實數。
導入不安全模組的接口本身不安全。 安全接口可能由不安全的實現模組導出。這是連線到外部庫時的典型用法,其中構建了兩個接口(一個不安全,另一個安全)。
泛型
通用接口及其相應的通用模組,在INTERFACE或MODULE關鍵字前加上GENERIC,並將其他接口作為形式參數。 因此(像C ++模板一樣)可以很容易地定義和使用抽象數據類型,但與C ++不同的是,粒度在模組級別。 接口作為實際參數傳遞給通用接口和實現模組,編譯器將生成具體模組。
例如,可以定義GenericStack,然後使用IntegerElem或RealElem等接口或甚至與對象的接口對其進行實例化,只要這些接口中的每一個都定義了通用模組所需的屬性即可。
注意:裸類型INTEGER或REAL不能使用,因為它們不是模組,泛型系統基於使用模組作為參數。相比之下,在C ++模板中,將使用裸類型。
檔案: IntegerElem.i3
INTERFACE IntegerElem;
CONST Name = "Integer";
TYPE T = INTEGER; PROCEDURE Format(x: T):
TEXT;
PROCEDURE Scan(txt: TEXT; VAR x: T):
BOOLEAN;
END IntegerElem.
檔案:GenericStack.ig
GENERIC INTERFACE GenericStack(Element);
(* Here Element.T is the type to be stored in the generic stack. *)
TYPE
T = Public OBJECT;
Public = OBJECT
METHODS
init(): TStack;
format(): TEXT;
isEmpty(): BOOLEAN;
count(): INTEGER;
push(elm: Element.T);
pop(VAR elem: Element.T): BOOLEAN;
END;
END GenericStack.
檔案:GenericStack.mg
GENERIC MODULE GenericStack(Element);
< ... generic implementation details... >
PROCEDURE Format(self: T):
TEXT = VAR
str: TEXT;
BEGIN
str := Element.Name & "Stack{";
FOR k := 0 TO self.n -1
DO
IF k > 0 THEN str := str & ", ";
END;
str := str & Element.Format(self.arr[k]);
END;
str := str & "};";
RETURN str;
END Format;
< ... more generic implementation details... >
END GenericStack.
檔案:IntegerStack.i3
INTERFACE IntegerStack = GenericStack(IntegerElem)
END IntegerStack.
檔案:IntegerStack.m3
MODULE IntegerStack = GenericStack(IntegerElem)
END IntegerStack.
可追溯性
任何標識符都可以追溯到它的起源地點,而不像其他語言的“包含”特徵。 編譯單元必須使用IMPORT語句從其他編譯單元導入標識符。 即使枚舉也使用與訪問記錄欄位時使用的'點'符號相同的符號。
INTERFACE A;
TYPE Color = {
Black, Brown, Red, Orange, Yellow, Green, Blue, Violet, Gray, White};
END A;
MODULE B;
IMPORT A;
FROM A IMPORT Color;VAR aColor: A.Color;
(* Uses the module name as a prefix *) theColor: Color;
(* Does not have the module name as a prefix *)
anotherColor: A.Color;BEGIN aColor := A.Color.Brown;
theColor := Color.Red;
anotherColor := Color.Orange;
(* Can't simply use Orange *)
END B.
動態編程
Modula-3支持在運行時分配數據。有兩種記憶體可以分配TRACED和UNTRACED,不同之處在於垃圾收集器是否可以看到它。NEW()用於分配這兩類記憶體中的任何一個的數據。在UNSAFE模組中,DISPOSE可用於釋放未交叉的記憶體。
面向對象
面向對象編程技術可用於Modula-3,但不需要使用它們。Modula-3(模組,泛型)中提供的許多其他功能通常可代替面向對象。
對象支持有意保留其最簡單的條款。OBJECT聲明引入了一個對象類型(在其他面向對象的語言中稱“類”),儘管對象類型是引用類型,但與Modula-3中的RECORD不同 (類似於C中的結構)。按照慣例,導出的類型通常被命名為T,並創建一個單獨的“公共”類型來公開方法和數據。 例如:
INTERFACE Person;
TYPE T <: Public;
Public = OBJECT METHODS getAge(): INTEGER;
init(name: TEXT;
age: INTEGER): T;
END;
END Person.
異常
異常處理基於TRY ... EXCEPT塊系統,它變得很常見。除了Delphi,Python ,Scala和Visual Basic.NET之外,其他語言中尚未採用的一個特性是[EXCEL]構造定義了一種switch語句形式,每種語言都有 作為它自己的EXCEPT子句中的一個例子可能的例外。Modula-3還支持LOOP ... EXIT ... END結構,該結構循環直到出現EXIT,這個結構等同於TRY ... EXCEPT子句中的簡單循環。
多執行緒
該語言支持使用多執行緒,以及執行緒之間的同步。運行時庫(m3core)中有一個名為Thread的標準模組,它支持使用多執行緒應用程式。實際上,Modula-3運行時可能會使用單獨的執行緒來執行垃圾收集等內部任務。
內置數據結構MUTEX用於同步多個執行緒,並保護數據結構免受可能的損壞或競爭條件的同時訪問。LOCK和相應的UNLOCK語句鎖定和解鎖MUTEX。MUTEX是一個對象,因此可以從中派生出其他對象。
例如,在libm3庫的I / O部分,讀寫器(Rd.T和Wr.T)從MUTEX派生,並且在訪問或修改任何內部數據(如緩衝區)之前鎖定自己。