stanford-oval/wikipedia huggingface dataset:
Modula-3
基础性语法和语义 > 语句 > With语句

Modula-3的WITH语句，无关于Modula-2的同名语句，它有如下形式：WITH id = e DO S END，这里的id是一个标识符，e是一个表达式，而S是一个语句。WITH语句声明了具有作用域S的id，作为变量e的别名，或作为值e的只读名字。表达式e在进入WITH语句的时候被求值一次。一个单一的WITH语句可以包含多个绑定，它们顺序的求值，就是说WITH id_1 = e_1, id_2 = e_2, ...，等价于WITH id_1 = e_1 DO WITH id_2 = e_2 DO ....。
WITH语句可类比于某种过程调用P(e)，这里的P被声明为：
PROCEDURE P(mode id: typeof e) =
BEGIN
    S
END P
这里的算符typeof只是个示意，它不在语言规定之中；如果e是可写的指定式，则mode是VAR，否则mode是READONLY。在WITH语句和调用P(e)之间唯一的区别为，出现在WITH语句内的自由变量、RETURN和EXIT，是在WITH语句所在的上下文中解释的，而非在新增加的P的上下文中。
Modula-3语言报告使用WITH语句定义其他语句，比如，INC和DEC语句分别有如下形式：INC(v, n)和DEC(v, n)，这里的v指示一个序数类型的变量，而n是可选的一个整数取值表达式，如果省略n则缺省为1，这两个语句分别等价于WITH x = v DO x := VAL(ORD(x) + n, T) END和WITH x = v DO x := VAL(ORD(x) - n, T) END，这里的T是v的类型，而x代表不出现在n中的变量。
基础性语法和语义 > 例外

例外声明有如下形式：EXCEPTION id(T)，这里的id是一个标识符，而T是除了开放数组之外的一个类型，它声明了id是具有实际参数类型T的例外。如果省略了(T)，这个例外不接受实际参数。例外声明只允许出现在接口和模块的最外层作用域之中。所有的声明的例外都是各不相同的。
RAISE语句有两种形式，没有实际参数的形式：RAISE e，这里的e是不接受实际参数的一个例外，它的结果是发起例外e；具有实际参数的形式：RAISE e(x)，这里的e是接受实际参数的一个例外，而x是可赋值给e的实际参数类型的一个表达式，它的结果是引发具有配对实际参数x的例外e。
Modula-3的例外处理，基于了TRY-EXCEPT语句。采用类似的块系统的有Delphi、Python、Scala和Visual Basic.NET。 TRY-EXCEPT语句有如下形式：
TRY
    Body
EXCEPT 
    id_1 (v_1) => Handler_1
  | ... 
  | id_n (v_n) => Handler_n
    ELSE Handler_0 
END
这里的Body和每个Handler都是语句，每个id指名一个例外，而每个v_i是一个标识符。ELSE Handler_0和每个(v_i)都是可选的。每个(v_i)声明一个变量，其类型是例外id_i的实际参数类型，而它的作用域是Handler_i。如果(v_i)缺席，形式id_1, ..., id_n => Handler，是id_1 => Handler; ...; id_n => Handler的简写。
TRY子句执行Body。如果结果是正常的，则忽略EXCEPT等子句。如果Body引发任何列出的例外id_i，则执行Handler_i。在处理具有配对实际参数x的例外id_i的时候，v_i在执行Handler_i之前被初始化为x。如果Body引发任何其他例外，并且ELSE Handler_0存在，则执行它。在这两种情况的任何之一下，TRY-EXCEPT语句的结果是选出的处理器的结果。如果Body引发未列出的例外，而ELSE Handler_0缺席，则TRY-EXCEPT语句的结果是Body引发的例外。
Modula-3还提供TRY-FINALLY语句，它有如下形式：TRY S_1 FINALLY S_2 END，它执行语句S_1接着执行语句S_2。如果S_1的结果是正常的，则TRY语句的结果等价于S_1; S_2。如果S_1的结果是例外，并且S_2的结果是正常，则在S_2执行之后，重新发起来自S_1的例外。如果二者的结果都是例外，则TRY语句的结果是来自S_2的例外。
在Modula-3中，EXIT和RETURN语句的语义，分别被定义为发起叫做exit-exception和return-exception的例外。exit-exception不接受实际参数，return-exception接受任意类型的实际参数，程序不能显式的命名这些例外。语句LOOP S END，非正式的等价于：
TRY
    S; S; S; ...
EXCEPT 
    exit-exception => (*skip*)
END
基础性语法和语义 > 过程 > 过程类型

一个过程要么是NIL，要么是有如下构成的三元组：
过程体，它是一个语句。
签名，它有如下形式(formal_1; ...; formal_n): R RAISES S，这里的每个formal_i是形式参数，R是结果类型，S是RAISES集合（这个过程可以引发的例外的集合）。
环境，它是在解释过程体中变量名字方面有关的作用域。
形式参数有如下形式：Mode Name: Type := Default，这里的：
Mode是参数模态，它可以是VALUE、VAR或READONLY。如果省略了Mode，它缺省为VALUE。
Name是命名这个形式参数的标识符。形式参数名字必须是各不相同的。
Type是这个形式参数的类型。
Default是一个常量表达式，它是这个形式参数的缺省值。如果Mode是VAR，则:= Default必须省略，否则:= Default和: Type中任何一个都可以省略，但不能二者都省略。如果省略了Type，它采用Default的类型。如果二者都存在，Default的值必须是Type的一个成员。
形式Mode v_1, ..., v_n: Type := Default，是Mode v_1: Type := Default; ...; Mode v_n: Type := Default的简写。
VAR形式参数绑定到对应的实际参数所指示的变量上，也就是说它是别名。对于VAR形式参数，实际参数必须是可写的指定式，它的类型同于形式参数的类型，或者在VAR数组形式参数的情况下，它可赋值给这个形式参数。
VALUE形式参数绑定到具有未用的位置的一个变量上，并且它被初始化为实际参数对应的值。对于VALUE或READONLY形式参数，实际参数是可赋值给形式参数类型的任何表达式，并且放开了针对赋值局部过程的禁止。
READONLY形式参数，如果实际参数是指定式并且有与形式参数相同的类型，或者是可赋值给形式参数的类型的一个数组类型，则被当作VAR形式参数对待，它的只读语义体现在指定这个指定式为只读的，否则被当作VALUE形式参数对待。
在签名中，如果省略了: R，则这个过程是真正（proper）过程，否则为函数过程；如果省略了RAISES S，则假定它为RAISES {}。一个过程发起未包括在RAISES集合中的一个例外，是一个必查的运行时间错误，如果语言实现将这个运行时间错误映射成一个例外，则这个例外隐含的包括在所有的RAISES子句中。
基础性语法和语义 > 过程 > 过程声明

有两种形式的过程声明：只允许出现在接口中的PROCEDURE id sig，和只允许出现在模块中的PROCEDURE id sig = B id，这里的id是一个标识符，sig是过程签名，而B是一个块。在一个模块的最外层作用域内声明的过程是顶层过程，其他过程是局部过程。局部过程可以作为形式参数传递但不能被赋值，因为在栈实现下，局部过程在包含它的栈桢被弹出后会成为无效的。
过程类型声明有如下形式：TYPE T = PROCEDURE sig，这里的sig是签名规定。一个过程P是过程类型T的一个成员，或称为是它的一个值的条件为，它是NIL，或者它的签名被T的签名所含盖（cover）。这里的签名sig_A含盖签名sig_B的条件是：
它们有相同数目的形式参数，并且对应的形式参数有相同的类型和模态。
它们有相同的结果类型，或者都没有结果类型。
sig_A的RAISES集合包含sig_B的RAISES集合。
过程常量是声明为过程的一个标识符。过程变量是声明为具有过程类型的一个变量。例如：
PROCEDURE P(txt: TEXT := "P") = 
BEGIN
    IO.Put(txt)
END P;
VAR q: PROCEDURE(txt: TEXT := "Q") := P;
声明了过程常量P和过程变量q。两个过程如果有一致的闭包，就是说它们涉及相同的过程体和环境，则二者相等即有相同的值。形式参数名字和缺省值，影响一个过程的类型即签名，而非这个过程的值。将一个过程常量赋值给一个过程变量，改变这个它的值，而非它的类型。比如上例中有：P = q为TRUE。缺省的形式参数的解释，由一个过程的类型来确定，而非这个过程的值。比如上例子中：P()打印P，而q()打印Q。
基础性语法和语义 > 过程 > 过程调用

过程调用有如下形式：P(Bindings)，这里的P是一个过程取值的表达式，而Bindings是关键字或位置绑定的一个列表。关键字绑定有如下形式：name := actual，这里的actual是一个表达式，而name是一个标识符。位置绑定有如下形式：actual，这里的actual是一个表达式。当关键字和位置绑定混合在一个调用中的时候，位置绑定必须前导于关键字绑定。如果绑定列表为空，圆括号仍然是需要的。
绑定列表要如下这样重写，来适合P的类型签名：首先，每个位置绑定actual，若为Bindings中的第i个绑定，则通过补充上第i个形式参数的名字，转换成关键字绑定增加到关键字绑定列表中。其次，对于有缺省值并且在第一步之后没有被绑定的每个形式参数，将它的形式参数的名字name和它的缺省值default，形成关键字绑定name := default增加到关键字绑定列表。重写成的关键字绑定列表必须只绑定形式参数，并且必须只绑定每个形式参数正好一次。
执行过程调用，需要求值过程取值表达式P和它的实际参数，绑定形式参数，并执行过程体。P和它的实际参数的求值次序是未定义的。调用一个未定义或NIL过程，是一个必查的运行时间错误。调用具有过程体B的真正过程，在绑定了实际参数之后等价于：
TRY
    B
EXCEPT
    return-exception => (*skip*)
END
而调用具有过程体B的函数过程等价于：
TRY
    B; (错误：没有返回值)
EXCEPT
    return-exception (v) => (结果成为v)
END
基础性语法和语义 > 递归定义

对于常量、类型或过程声明N = E、变量声明N: E、例外声明N(E)或揭示N = E，如果N出现在E的任何部份展开之中，则它是递归的。对于省略了类型的变量声明N := I，如果N出现在I的类型E的任何部份展开中，则它是递归的。允许这种声明的条件，是N在E的任何部份展开中所有的出现为如下三者之一：在类型构造子REF或PROCEDURE的某个出现之内，在类型构造子OBJECT的一个字段或方法类型之内，或者在一个过程体之内。下面是合法的递归声明的例子：
TYPE 
    RealList = REF RECORD
        val: REAL;
        link: RealList
    END;
    ListNode = OBJECT
        link: ListNode
    END;
    IntList = ListNode OBJECT
        val: INTEGER
    END;
    T = PROCEDURE(n: INTEGER; p: T);
EXCEPTION E(PROCEDURE() RAISES {E});
PROCEDURE P(b: BOOLEAN) =
BEGIN
    IF b THEN P(NOT b) END 
END P;
特征性技术

Modula-3的设计者认为Modula-2最成功的特征，是提供了在模块之间的显式接口，故而接口在Modula-3中保留而在本质上没有变化。到模块的接口，是披露了模块公开部份的声明搜集，而未声明于接口中的模块中的东西是私有的。模块导入它所依赖的接口，而导出它所实现的接口（在Modula-3中可以是多个接口）。
在现代编程语言的实现下，一个抽象类型的值，被表示一个对象，它的操作由叫做对象的方法的过程值的一个套件来实现。一个新的对象类型，可以定义为现存类型的子类型，在这种情况下新类型拥有旧类型的所有方法，并且可能还有新的方法（继承）。新类型可以为旧方法提供新的实现（覆盖）。对象类型和Modula-2的不透明类型（英语：）的组合，产生了一个新事物：部份不透明（partially opaque）类型，这里的一个对象的一些字段在一个作用域内是可见的，而其他的是隐藏的。
泛型模块是一种模板，在其中一些导入的接口被当作形式参数，它们在实例化泛型的时候要绑定到实际接口。不同的泛型实例是独立编译的，源代码程序被重复使用，而编译后的代码对不同实例通常是不同的。为保持简单性，在Modula-3中泛型被限制在模块层面，泛型的过程和类型不孤立存在，并且泛型形式参数必须都是完全的接口。
将计算分解入并发进程（或线程）中是关注点分离的基本方法。Modula-2提供的线程很弱，本质上相当于协程。Modula-3采用了霍尔的监视器，它是并发编程的更坚实基础。Modula-2+（英语：）在设计中加入了简化的Mesa同步原语，它足够成功而在实质上没有改变的结合入了Modula-3。
一个语言特征是不安全的，如果它的滥用可以破坏运行时系统，使得程序的进一步运行不忠实于语言的语义，不安全特征的一个例子，是没有边界检查的数组赋值。一个安全的程序的一个错误，可以导致计算中止，并给出运行时间错误信息或给出错误解答，但它不会导致计算分崩离析。Modula-3在这个领域里跟从Cedar，接受只在显式的标记为不安全的模块中才允许的少量不安全特征。
特征性技术 > 模块化

接口中的声明，除了任何变量初始化必须是常量，和过程声明必须只能指定签名而不能有过程体之外，同于在块中的声明。接口有如下形式：
INTERFACE id;
    Imports;
    Decls
END id.
这里的id是命名这个接口的标识符，Imports是一序列的导入语句，而Decls是一序列的声明。在Decls中的名字和可见的导入的名字必须是各不相同的。两个或更多个接口形成导入环是静态错误。典型的接口定义，通常为每个接口定义一个数据结构（记录或对象）以及任何的支持过程。
模块除了实体名字的可见性之外，就像是一个块。一个实体在一个块中是可见的，如果它被声明在这个块中，或在某个包围的块中；而一个实体在一个模块中是可见的，如果它被声明在这个模块中，或在这个模块所导入或导出的一个接口中。模块有如下形式：
MODULE id EXPORTS Interfaces;
    Imports;
Block id.
这里的id是命名这个模块的一个标识符，Interfaces是这个模块导出的那些接口的不同名字的一个列表，Imports是一序列的导入语句，而Block是一个块，它是模块体。名字id必须重复于终结模块体的END之后。EXPORTS Interfaces可以省略，在这种情况下Interfaces缺省为id，即模块将缺省导出相同名称的接口。Modula-3中的导出EXPORTS，与Modula-2中的导出EXPORT无关，它在概念上对应于Modula-2的“实现”。
如果模块M导出了接口I，则在I中声明的所有名字在M中是不加以限定而可见的。一个模块M导出一个接口I，可以重新声明在这个接口中声明的一个或多个过程，为其提供过程体。在M中的签名，必须被在I中的签名所含盖。要确定在对这个过程的调用中的关键字绑定的解释，在M内使用M中的签名，在其他地方使用I中的签名。除了重新声明导出的过程之外，在Block的顶层中声明的名字，可见的导入的名字，和在导出的接口中声明的名字必须是各不相同的。
一个程序的模块和接口的名字叫做全局名字。查找全局名字的方法是依赖于实现的，比如通过文件系统查找路径。一个模块或接口X导入一个接口I，从而使得在I中声明的实体和揭示在X中可见，但不包括I所导入的那些。一个模块M使用了接口I，如果M导入或导出了I，或者M使用了导入I的一个接口。Modula-3中所有的编译单元，要么是接口要么是模块。任何编译单元都可以使用IMPORT语句从其他接口导入标识符。与其他语言的包含功能不同，任何标识符都可以追踪到它的起源位置。
IMPORT语句有如下的典型使用形式：IMPORT I，它导入全局名字为I的接口，并给它一个同样的局部名字，从而使用点表示法访问接口中的实体（类似于访问记录中的字段）。比如接口中的主要类型按惯例命名为T，则使用它时采用的限定形式为I.T。如果导入接口的名字与模块内的其他实体的名字发生冲突，则可以使用IMPORT I AS X这样的形式给与它不同的局部名字。
IMPORT语句还有如下的另一种形式：FROM I IMPORT N，它为在接口I中声明为N的实体，介入一个局部名字N，比如：FROM IO IMPORT Put，并且不加限定的使用它，比如：Put("Hello World\n")。局部绑定优先于全局绑定，例如：IMPORT I AS J, J AS I; FROM I IMPORT N，为全局名字为J.N的实体介入了局部名字N。非法使用相同的局部名字两次是静态错误。
一个程序是模块和接口的搜集，包含了任何它的模块或接口所导入或导出的所有接口，并且在其中没有重复定义的过程、模块或接口。执行一个程序的效果是执行它的所有模块的模块体。模块的执行次序受到初始化规则的约束：如果模块M依赖于模块N并且N不依赖于M，则N的模块体将先于M的模块体执行。这里的模块M依赖于模块N，如果M使用了N导出的一个接口，或者M所依赖的一个模块依赖于N。
其模块体最后执行的模块叫做主模块。在初始化规则不能唯一的确定它的情况下，语言实现提供了指定这个主模块的方法，即主模块是导出Main的模块，它的内容是依赖于实现的。程序执行在主模块终止的时候终止，即使并发的控制线程仍在执行。
下面是接口与模块的一个规范性的例子，是有隐藏表示的一个公开堆栈：
INTERFACE Stack;
    TYPE T <: REFANY;
    PROCEDURE Create(): T;
    PROCEDURE Push(VAR s: T; x: REAL);
    PROCEDURE Pop(VAR s: T): REAL;
END Stack.
MODULE Stack;
    REVEAL T = BRANDED OBJECT
        item: REAL;
        link: T
    END;
    PROCEDURE Create(): T = 
    BEGIN 
        RETURN NIL 
    END Create;
    PROCEDURE Push(VAR s: T; x: REAL) =
    BEGIN 
        s := NEW(T, item := x, link := s)
    END Push;
    PROCEDURE Pop(VAR s: T): REAL =
        VAR res: REAL;
    BEGIN 
        res := s.item;
        s := s.link;
        RETURN res
    END Pop;
BEGIN
END Stack.
如果多于一个模块需要此堆栈的表示，则应当把它转移到私有接口中，从而在需要它的任何地方的都可以导入它：
INTERFACE Stack;
    (* ... 同上 ... *)
END Stack.

INTERFACE StackRep;
    IMPORT Stack;   
    REVEAL Stack.T = BRANDED OBJECT
        item: REAL;
        link: Stack.T
    END
END StackRep.
MODULE Stack;
    IMPORT StackRep;
    (* Push、Pop和Create同上 *)
BEGIN
END Stack.
特征性技术 > 对象类型

一个对象要么是NIL，要么是到有配对的方法套件的一个数据记录的引用，方法套件是接受这个对象作为第一个实际参数的那些过程的一个记录。这个数据记录可以包含经由对象类型的子类型介入的增加字段，这个套件可以包含经由子类型介入的增加方法。对象赋值是引用赋值。要复制一个对象的数据记录到另一个对象，这些字段必须单独的赋值。
Modula-3意图保持采用对象这个最简单的术语，而非在其他面向对象语言中对应的术语类。对象类型声明采用如下形式：
TYPE T = ST OBJECT
        Fields
    METHODS
        Methods
    OVERRIDES
        Overrides
    END
这里的ST是可选的超类型，如果省略则缺省为ROOT，Fields是完全如同记录类型那样的字段声明的一个列表，Methods是方法声明的一个列表，而Overrides是方法覆盖的一个列表。在字段和方法声明中介入的名字，必须相互不同，并且不同于在覆盖声明中的名字。T的字段构成自ST的字段和随后的新声明的字段。T的方法构成自经过OVERRIDES中的覆盖修改的ST的方法，和随后的METHODS中声明的方法。T有着同ST一样的引用类。
关键字OBJECT可选的可以前导上BRANDED或BRANDED b来给对象加铭牌，使之唯一而避免结构等价，这里的b是文本常量。其含义同于非对象的引用类型，b被省略时，系统自动生成唯一性的一个字符串。
方法声明有如下形式：m sig := proc，这里的m是个标识符，sig是过程签名，而proc是顶层过程常量。方法声明指定了T的方法m有签名sig和值proc。如果省略了:= proc假定它为:= NIL。如果proc非空，它的第一个形式参数必须是缺省的模态VALUE，并有着T的某个超类型的类型（包括且经常是T自身），并且去除了第一个形式参数结果就是sig所含盖的签名。
方法覆盖（override）有如下形式：m := proc，这里的m是超类型ST的方法的名字，而proc是顶层过程常量。方法覆盖指定了T的方法m是proc，并非指定ST.m。如果proc非空，它的第一个形式参数必须是缺省的模态VALUE，并有着T的某个超类型的类型（包括且经常是T自身），去除了proc第一个形式参数结果就是ST的m方法所含盖的签名。举例说明：
TYPE 
    Super = OBJECT
        a: INTEGER;
    METHODS
        p()
    END;
    Sub = Super OBJECT
        b: INTEGER
    END;
PROCEDURE ProcSuper(self: Super) = ... ; 
PROCEDURE ProcSub(self: Sub) = ... ;
这里的过程ProcSuper和ProcSub是类型Super和Sub的对象的p方法的候选值。例如：
| --- | --- |
 TYPE T1 = Sub OBJECT     OVERRIDES         p := ProcSub     END :  TYPE T2 = Super OBJECT     OVERRIDES         p := ProcSuper     END 
声明了具有Sub数据记录和预期一个Sub的p方法的一个类型。T1是Sub的有效的子类型。: 声明了具有Super数据记录和预期一个Super的p方法的一个类型。T2是Super的有效的子类型。
 TYPE T3 = Sub OBJECT     OVERRIDES         p := ProcSuper     END :  TYPE T4 = Super OBJECT     OVERRIDES         p := ProcSub     END 
声明了具有Sub数据记录和预期一个Super的p方法的一个类型。因为所有Sub都是Super，这个方法不挑剔要放入的对象。: 尝试声明具有Super数据记录和预期一个Sub的p方法的一个类型，因为不是所有Super都是Sub，这个方法很挑剔要放入的对象。T4的声明是个静态错误。
如果T是对象类型或到记录的引用，NEW(T)操作有如下形式：NEW(T, Bindings)，这里的Bindings是用来初始化新字段的关键字绑定的一个列表，不允许位置绑定。每个绑定f := v将字段f初始化为值v。如果T是对象类型，则Bindings还可以包括形如m := P的方法覆盖，这里的m是T的一个方法而P是一个顶层过程常量。NEW(T, m := P)是NEW(T OBJECT OVERRIDES m := P END)的语法糖。
如果o是一个对象，则o.f指示在o的数据记录中名为f的数据字段。o.f是可写的指定式，它的类型是这个字段的所声明的类型。如果m是o方法之一，以o.m(Bindings)形式的过程调用，指示执行o的m方法，这等价于：(o的m方法) (o, Bindings)。
如果T是对象类型而m是T的方法的名字之一，则T.m指示T的m方法。它的过程类型的第一个实际参数有类型T，而第一个实际参数对应的形式参数名字是未指定的，因此在调用T.m时，第一个实际参数必须按位置来指定，不能用关键字。这种表示法便于子类型方法调用它的某个超类型的对应方法。
在子类型中的字段或方法遮盖（mask）了在超类型中的任何同名的字段或方法。要访问被遮盖的字段，使用类型运算NARROW(x, T)来将子类型变量当作超类型的成员，这里的T必须是对象类型或有跟踪的引用类型，而x必须可赋值给T。NARROW(x, T): T在检查了x是T一个成员之后返回x，如果检查失败则发生运行时间错误。
下面的例子展示了在声明新方法和覆盖现存方法之间的不同，首先声明如下：
TYPE
    Super = OBJECT 
    METHODS
        m() := ProcSuper
    END;
    SubOverridden = Super OBJECT
    OVERRIDES
        m := ProcSub
    END;
    SubExtended = Super OBJECT
    METHODS
        m() := ProcSub
    END;
VAR
    a := NEW(Super); 
    b := NEW(SubOverridden);
    c := NEW(SubExtended);
然后可以用a.m()激活ProcSuper(a)，用b.m()激活ProcSub(b)，用c.m()激活ProcSub(c)，如此调用在覆盖和扩展之间没有区别。但是扩展的c的方法套件有两个方法，而覆盖的b的方法套件只有一个方法，这可以通过使用NARROW(x, T)将子类型的变量b和c视为超类型Super的成员来披露：NARROW(b, Super).m()激活ProcSub(b)，NARROW(c, Super).m()激活ProcSuper(c)。
对象不能解引用（英语：），因为在语言实现中，一个对象变量的静态类型不确定它的数据记录的类型。对象类型确定了关乎数据记录字段和方法套件的超类型链的前缀的那些类型。
特征性技术 > 对象类型 > 实现

下面是语言设计者提出的对象的一种可能实现的梗概，一个对象可以表示为它的数据记录的第一个字的地址。前面的字存储一个对象头部，它包含一个唯一于对象类型的类型代码。这些类型代码是小型整数，对每个对象类型和每个有跟踪的引用类型都有一个代码。在对象头部之前的字，存储到这个对象的方法套件的一个引用。如果这个对象没有方法，这个字可以省略。这还允许对象共享方法套件，这是常见情况。如果o是一个对象，d是它的数据字段之一，而m是它的方法之一，则在这种表示下：
| 0 | 1 | 2 |
| --- | --- | --- |
| o.d | 是 | Mem[o + d] |
| o.m | 是 | Mem[Mem[o – 2] + m] |
| TYPECODE(o) | 是 | Mem[o – 1] |
这里假定了字段和方法以自然方式表示为偏移量。进一步的问题是如何高效的测试一个对象o是否有着类型T，这是NARROW()和TYPECASE语句所需要的。NARROW()的最简单实现，是维护一个以类型代码为索引的数组st，st[tc]是其类型代码为tc的对象类型的超类型的类型代码，如果它没有超类型则为NIL。要测试o是否是一个T，使用一个循环来计算T的类型代码是否出现在如下序列之中：
TYPECODE(o), st[TYPECODE(o)], st[st[TYPECODE(o)]], ... NIL
这个序列可以称为o的类型的超类型路径，而它的长度可称为o的类型的深度。利用上每个类型的深度都是编译时间确定的，因此可以同相应的类型代码一起存储的事实，可以有更快速的NARROW()实现。如果T的类型代码，出现在类型U的超类型路径上，它就该在位置depth(U) - depth(T)上。如果每个类型的超类型路径都是顺序数组，这意味着NARROW()可以用恒定时间实现。因为超类型路径通常不太长，这是一个有吸引力的策略。在不常见的对象类型有非常长的超类型链的情况下，只有这个链的直到某个极大长度的一个前缀，会被顺序的存储。在运行时间，这个深度差如果超出这个链的顺序存储的长度，实现必须回退到链表。
特征性技术 > 不透明类型及其披露

不透明（英语：）（opaque）类型声明有如下形式：TYPE T <: U，这里的T是标识符，而U是指示一个引用类型的表达式。它将名字T介入为不透明类型，并披露了U是T的超类型。
Modula-3的揭示（revelation）机制，将关于一个不透明类型的信息，介入到一个作用域之内，不同于其他声明，揭示不介入新的名字。不同的作用域，可以披露（reveal）关于一个不透明类型的不同的信息。例如，某个不透明类型，在一个作用域内知晓为REFANY的子类型，在其他的作用域内可以知晓为ROOT的子类型。
不透明类型名字所指示的实际类型叫做具体类型。T的具体类型，必须披露于程序的其他地方。在对象声明中，如果ST被声明为不透明类型，则只在知晓ST的具体类型为对象类型的作用域内，T的声明是合法的。如果T被声明为不透明类型，则只在完全知晓T的具体类型，或者知晓它为对象类型的作用域内，NEW(T)是合法的。
揭示分为两种：部份的和完全的，一个程序可以包含一个不透明类型的任意多个部份揭示，但必须包含唯一的一个完全揭示。
部份揭示有如下形式：REVEAL T <: V，这里的V是类型表达式（可能就是个名字），而T是被声明为不透明类型的一个标识符（可能有限定）。它披露了V是T的超类型。在任何作用域内，对一个不透明类型披露的超类型，必须是在子类型关系下是线性有序的。就是说，如果披露了T <: U1和T <: U2，则必须也要披露要么U1 <: U2要么U2 <: U1。REVEAL T <: T是合法的非递归声明。
完全揭示有如下形式：REVEAL T = V，这里的V是类型表达式（不能就是个名字），它的最外层类型构造子，是有铭牌的一个引用或对象类型，而T是被声明为不透明类型的一个标识符（可能有限定）。这个揭示指定了V是T的具体类型。在任何作用域内，披露为T的超类型的任何类型，都必须是V的超类型，否则是一个静态错误。不同的不透明类型有不同的具体类型，因为V包含了一个铭牌并且在程序中所有的铭牌都是独一的。REVEAL I.T = I.T BRANDED OBJECT ... END是非法的递归声明。
揭示只允许用在接口和模块的最外层作用域内。在接口中的揭示可以被导入到任何需要它的作用域之内。揭示提供了向客户隐藏实现细节的，在概念上简单清晰却非常强力的机制，例如：
INTERFACE I; 
    TYPE T <: ROOT;
    PROCEDURE P(x: T): T;
END I.

INTERFACE IRep;
    IMPORT I;
    REVEAL I.T = MUTEX BRANDED OBJECT
        count: INTEGER
    END;
END IRep.

INTERFACE IClass;
    IMPORT I;
    REVEAL I.T <: MUTEX;
END IClass.
导入I的编译单元见到的I.T是ROOT的不透明子类型，因而被限制为可以分配类型I.T的对象，把它们传递给I.P，或声明I.T的子类型。导入IRep的编译单元见到的I.T是具体类型，它是有扩展的count字段的MUTEX的子类型。导入IClass的编译单元见到的I.T是MUTEX的不透明子类型，因而可以锁定类型I.T的对象。
特征性技术 > 泛型

在泛型接口或模块中，某些导入的接口名字被当作形式参数，它们在泛型被实例化的时候要绑定到实际接口上。泛型接口及其实例有如下左侧的形式，并等价于右侧定义的普通接口：
| --- | --- |
 GENERIC INTERFACE G(F_1, ..., F_n); Body END G. INTERFACE I = G(A_1, ..., A_n) END I. :  INTERFACE I;     IMPORT A_1 AS F_1, ..., A_n AS F_n; Body END I. 
这里的G是命名这个泛型接口的一个标识符，F_1, ..., F_n是叫做G的形式导入的标识符的一个列表，而Body同在非泛型接口中一样，是一序列导入和随后的一序列声明。这里的I是这个实例的名字，而A_1, ..., A_n是G的形式导入要绑定的实际接口的一个列表。
泛型模块及其实例有如下左侧的形式，并等价于右侧定义的普通模块：
| --- | --- |
 GENERIC MODULE G(F_1, ..., F_n); Body END G. MODULE I EXPORTS E = G(A_1, ..., A_n) END I. :  MODULE I EXPORTS E;     IMPORT A_1 AS F_1, ..., A_n AS F_n; Body END I. 
这里的G是命名这个泛型模块的一个标识符，F_1, ..., F_n是叫做G的形式导入的标识符的一个列表，而Body同在非泛型模块中一样，是一序列的导入和随后的一个块。这里的I是这个实例的名字，E是由M导出的接口的一个列表，而A_1, ..., A_n是G的形式导入要绑定的实际接口的一个列表。EXPORTS E可以省略，在这种情况下它缺省为EXPORTS I。泛型模块自身没有导出，它们只在被实例化时提供。
泛型接口及其对应的泛型模块（与C++模板一样）可以轻松定义和使用抽象数据类型，但粒度在模块级别，裸露的类型INTEGER或REAL不能使用，相比之下，它们在C++模板中可以使用。例如，可以定义泛型堆栈：
GENERIC INTERFACE Stack(Elem);
    (* 这里的Elem.T不是开放数组类型 *)
    TYPE T <: REFANY;
    PROCEDURE Create(): T;
    PROCEDURE Push(VAR s: T; x: Elem.T);
    PROCEDURE Pop(VAR s: T): Elem.T;
END Stack.
GENERIC MODULE Stack(Elem);
    REVEAL T = BRANDED OBJECT
        n: INTEGER;
        a: REF ARRAY OF Elem.T
    END;
    PROCEDURE Create(): T =
    BEGIN
        RETURN NEW(T, n := 0, a := NIL)  
    END Create;
    PROCEDURE Push(VAR s: T; x: Elem.T) =
    BEGIN
        IF s.a = NIL THEN 
            s.a := NEW(REF ARRAY OF Elem.T, 5)
        ELSIF s.n > LAST(s.a^) THEN
            WITH temp = NEW(REF ARRAY OF Elem.T, 2 * NUMBER(s.a^)) DO
                FOR i := 0 TO LAST(s.a^) DO
                    temp[i] := s.a[i] 
                END;
                s.a := temp
            END
        END;
        s.a[s.n] := x;
        INC(s.n)
    END Push;
    PROCEDURE Pop(VAR s: T): Elem.T =
    BEGIN
        DEC(s.n);
        RETURN s.a[s.n]  
    END Pop;
BEGIN
END Stack.
然后使用接口例如IntegerElem，对其进行实例化，只要这个接口定义了泛型模块所需的属性即可：
INTERFACE IntegerElem;
    TYPE T = INTEGER;
END IntegerElem.

INTERFACE IntStack = Stack(IntegerElem) END IntStack.
MODULE IntStack = Stack(IntegerElem) END IntStack.
特征性技术 > 面向对象

Modula-3下的面向对象编程，经常采用部份不透明类型，它通过如下惯用法来声明：Type T <: Public; Public = OBJECT ... END，这里的不透明类型T，支持在随后定义的对象类型中的字段和方法，而不会披露T的确切结构，也不披露T可能支持的其他方法。
下面的例子，定义一个接口Person，具有按习惯约定命名的两个类型，导出类型T，和公开对象类型Public，这里声明了T是Public的不透明子类型，Public具有两个方法getAge()和init()；随后是Person接口的完全实现：
INTERFACE Person;
    TYPE T <: Public;
        Public = OBJECT 
        METHODS
            getAge(): INTEGER;
            init(name: TEXT; age: INTEGER): T;
        END;
END Person.
MODULE Person;
    REVEAL T = Public BRANDED OBJECT 
        name: TEXT;
        age: INTEGER;
    OVERRIDES
        getAge := Age;
        init := Init;
    END;
    PROCEDURE Age(self: T): INTEGER =
    BEGIN
        RETURN self.age;
    END Age;
    PROCEDURE Init(self: T; name: TEXT; age: INTEGER): T =
    BEGIN
        self.name := name;
        self.age := age;
        RETURN self;
    END Init;
BEGIN
END Person.
要建立一个新的Person.T对象，要使用内建操作NEW()，并调用方法init()：
VAR jim := NEW(Person.T).init("Jim", 25);
下面是整数堆栈的例子：
INTERFACE IntegerStack;
    TYPE
        T <: Public OBJECT;
        Public = OBJECT
        METHODS
            init(): T;
            push(x: INTEGER);
            pop(): INTEGER;
        END;
END IntegerStack.
MODULE IntegerStack;
    REVEAL T = Public BRANDED OBJECT
        n: INTEGER;
        a: REF ARRAY OF INTEGER;
    OVERRIDES
        init := Init;
	    push := Push;
	    pop := Pop;
    END;
    PROCEDURE Init(self: T): T =
    BEGIN
        self.n := 0;
        self.a := NIL;
        RETURN self
    END Init;
    PROCEDURE Push(self: T; x: INTEGER) =
    BEGIN
        IF self.a = NIL THEN 
            self.a := NEW(REF ARRAY OF INTEGER, 5)
        ELSIF self.n > LAST(self.a^) THEN
            WITH temp = NEW(REF ARRAY OF INTEGER, 2 * NUMBER(self.a^)) DO
                FOR i := 0 TO LAST(self.a^) DO
                    temp[i] := self.a[i] 
                END;
                self.a := temp
            END
        END;
        self.a[self.n] := x;
        INC(self.n)
    END Push;
    PROCEDURE Pop(self: T): INTEGER =
    BEGIN
        DEC(self.n);
        RETURN self.a[self.n]  
    END Pop;
BEGIN
END IntegerStack.
创建新堆栈在这里的部份不透明类型实现下为：VAR myStack := NEW(IntegerStack.T).init()，在上述的不透明类型实现下为：VAR myStack := IntStack.Create()。而压入一个数在这里的部份不透明类型实现下为：myStack.push(8)，在上述的不透明类型实现下为：IntStack.Push(myStack, 8)。
特征性技术 > 多线程

语言支持多线程和在线程间的同步。在运行时库（m3core）中有一个必要接口叫做Thread，它支持采用分叉会合模型的多线程应用。这里还预定义不透明类型MUTEX被用来同步多个线程，并保护共享数据免于具有可能损害或竞争条件的同时访问。MUTEX是一个对象，因此可以从它派生其他对象。
LOCK语句有如下形式：LOCK mu DO S END，这里的S是一个语句，而mu是一个表达式，它等价于：
WITH m = mu DO
    Thread.Acquire(m);
    TRY S FINALLY Thread.Release(m) END
END
这里的m表示不出现在S中的一个变量。LOCK语句介入一个互斥锁要锁定的块，并暗含着在代码执行轨迹离开这个块时的解锁它。
特征性技术 > 不安全标记

某些功能被认为是不安全的，编译器无法再保证结果是一致性的（例如，当与C编程语言交接时）。在INTERFACE或MODULE前面加上前缀关键字UNSAFE，可用于告诉编译器启用语言的某些不安全的低级功能。例如，在UNSAFE模块中，使用LOOPHOLE()将整数的诸位元复制成浮点REAL数，使用DISPOSE()释放无跟踪的内存。
一个接口是内在安全的，如果在安全模块中使用这个接口，无法产生不核查的运行时间错误。如果导出一个安全接口的所有的模块都是安全的，编译器保证这个接口的内在安全性。如果导出一个安全接口的任何模块是不安全的，就要编程者而非编译器，去做这种保证了。安全接口导入不安全接口，或安全模块导入或导出不安全接口，都是静态错误。导入不安全接口的编译单元本身必定也是不安全的。
对其他编程语言的影响

尽管Modula-3没有获得主流地位，DEC-SRC M3发行的某些部份做到了。可能最有影响的一部份是网络对象库，它形成了Java包括了网络协议的最初的远程方法调用（RMI）实现的基础。在Sun从通用对象请求代理架构（CORBA）标准转移到基于IIOP的协议的时候才被放弃。Java关于远程对象的垃圾收集的文档仍提及了Modula-3网络对象为其先驱性工作 。
Python从Modula-3借鉴了模块系统、例外系统和关键字参数，Python的类机制受到C++和Modula-3的启发。Nim利用了Modula-3的某些方面比如有跟踪和无跟踪的指针。
圣域2：堕落天使

| 圣域2：堕落天使 |
| --- | --- |

官方译名: 中国大陆：
常用译名: 中国大陆：神圣纪事2：堕落天使
类型: 动作角色扮演
平台: Microsoft Windows、PlayStation 3、Xbox 360
开发商: Ascaron
发行商: 全球：cdv Software Entertainment、Deep Silver 中国大陆：星空娱动 臺灣：新世代
设计师: Bob Bates （制作人）
音乐: Dynamedion Blind Guardian（主题音乐） Pedro Macedo Camacho（追加音乐）
系列: 圣域系列
模式: 单人、单人
发行日:  2008年11月7日 Microsoft Windows版欧洲：2008年11月7日 北美：2008年11月11日 中国大陆：2009年1月15日 臺灣：2009年3月3日PlayStation 3、Xbox 360版北美：2009年5月12日 欧洲：2009年6月5日  
《圣域2：堕落天使》（英语：）是圣域系列的第二部作品。它是《圣域》的前传，剧情发生在《圣域》的2000年前。该游戏采用了新引擎，采用正确透视的3D渲染，同时保留旧作中的视角。游戏设计师鲍勃·盖茨参与了制作，力量金属乐队Blind Guardian(盲目守护者\盲卫士)演唱了主题曲并制作了一个视频。
Windows版在2008年年末发行，游戏主机版则迟至2009年才发行。一个名为《冰与血》的资料片于10月2日放出，只面向欧洲电脑玩家发行。
现在Ascaron公司已被合并，星空娱动已倒闭。
参考资料

↑  cdv Software Entertainment （页面存档备份，存于） cdvusa.com
↑  Blind Guardian Rocks Out in Sacred 2 Archive.is的存檔，存档日期2012-07-17 1up.com
↑  MobyGames, ,   [2008-12-28], （原始内容存档于2009-02-20）
↑  Broomhall, John, , Develop Magazine (59), November 2008: 57  [2010-09-25], （原始内容存档于2011-07-22）  引文格式1维护：日期与年 (link)
↑  Sacred 2: Fallen Angel Tech Info 的存檔，存档日期2009-07-06. uk.gamespot.com
↑  - Sacred 2 Gone Gold for US xbox360.ign.com
↑  Sacred 2 Gone Gold for EU psu.com
↑  Sacred 2: Fallen Angel Goes Gold for the Xbox 360 （页面存档备份，存于） gammingexcellence.com
内马

| 内马 |
| --- | --- |
城市

坐标：16°37′N 7°15′W﻿ / ﻿16.62°N 7.25°W﻿ / 16.62; -7.25
国家:  毛里塔尼亚
地区: 东胡德省
内马（法语：）位于毛里塔尼亚东南部的撒哈拉沙漠中，是东胡德省的首府，人口约5-6万。
内马临近马里，是毛里塔尼亚东南部的贸易中心，和首都努瓦克肖特有“希望之路”相连。毛里塔尼亚航空公司计划开辟内马与努瓦克肖特、阿比让和拉斯帕尔马斯之间的航班。
内森尼尔·查尔斯·罗斯柴尔德

| 内森尼尔·查尔斯·罗斯柴尔德 |
| --- | --- |
出生: (1877-05-09)1877年5月9日 英国
逝世: 1923年10月12日（1923-10-12） 英国
国籍:  英国
内森尼尔·查尔斯·罗斯柴尔德（英語：，1877年5月9日—1923年10月12日）经常被简称为查尔斯·罗斯柴尔德，是一名英国银行家、昆虫学家，他是罗斯柴尔德家族创始人迈耶·阿姆谢尔·罗斯柴尔德的玄孙。
生平

内森尼尔·查尔斯·罗斯柴尔德于1877年5月9日出生于英国，他是内森·迈耶·罗斯柴尔德和艾玛·路易丝·冯·罗斯柴尔德的第三个孩子，内森尼尔·查尔斯·罗斯柴尔德的中学就读于哈罗公学，在这里他发现他因为他的宗教信仰受到欺负。后来他进入了罗斯柴尔德家族的家族企业N M 罗斯柴尔德与儿子们银行（英語：）工作，虽然他真正的兴趣爱好是生物学和其它自然科学，他每天早上都去N M 罗斯柴尔德与儿子们银行上班，从来没有一天没去过。
他对罗斯柴尔德家族经营的黄金精炼厂很感兴趣，他还自己发明了一些黄金冶炼设备，他一直都是从科学的角度去研究黄金，他还担任过联盟保险公司的董事长。
内森尼尔·查尔斯·罗斯柴尔德与他那个喜欢研究动物学的哥哥莱昂内尔·沃尔特·罗斯柴尔德相似，他把很多精力放在了昆虫学上，他对跳蚤的收藏目前被存放在大英博物馆中。1901年他在非洲的苏丹进行科学考察的时候发现了东方肥跳蚤（ Xenopsylla cheopis）并在1903年将自己对其的研究成果发表出来。
内森尼尔·查尔斯·罗斯柴尔德被看成是英国的自然保护区的先锋，1899年他建立了位于剑桥郡威肯村的威肯芬自然保护区，1910年他建立了位于剑桥郡伍德沃尔登村的伍德沃尔登自然保护区。
1907年2月6日，内森尼尔·查尔斯·罗斯柴尔德和罗兹卡·厄斗·冯·魏泽姆斯特恩结婚。
由于长期遭受脑炎的痛苦，1923年10月12日，内森尼尔·查尔斯·罗斯柴尔德用自杀结束了自己的生命。
家庭与世系表 > 家庭

内森尼尔·查尔斯·罗斯柴尔德和罗兹卡·厄斗·冯·魏泽姆斯特恩有4个孩子，3个女儿，1个儿子。
米里亚姆·路易莎·罗斯柴尔德（女儿，1908年-2005年）
伊丽莎白·夏洛特·罗斯柴尔德（女儿，1909年-1988年）
内森尼尔·迈耶·维克多·罗斯柴尔德（儿子，1910年-1990年）
凯瑟琳·安妮·潘诺尼卡·德·科尼斯瓦特（女儿，1913年-1988年）
家庭与世系表 > 世系表

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|  |  迈耶·阿姆谢尔·罗斯柴尔德 |  迈耶·阿姆谢尔·罗斯柴尔德 |   |  古特·斯纳帕 |  古特·斯纳帕 |   |   |   |   |   |   |
|  |   |   |   |   |  |  |  |  |  |  |  |
|  |  |  |   |  |  |  |  |  |  |  |  |
|  |   |   |   |   |  |  |  |  |  |  |  |
|  |  内森·迈耶·罗斯柴尔德 |  内森·迈耶·罗斯柴尔德 |   |  卡尔·迈耶·冯·罗斯柴尔德 |  卡尔·迈耶·冯·罗斯柴尔德 |   |   |   |   |   |   |
|  |   |  |  |   |  |  |  |  |  |  |  |
|  |   |   |   |   |   |   |   |   |  |  |  |
|  |  莱昂内尔·内森·德·罗斯柴尔德 |  莱昂内尔·内森·德·罗斯柴尔德 |   |  夏洛特·冯·罗斯柴尔德 |  夏洛特·冯·罗斯柴尔德 |   |  迈耶·卡尔·冯·罗斯柴尔德 |  迈耶·卡尔·冯·罗斯柴尔德 |   |   |   |
|  |   |  |  |   |  |  |   |  |  |  |  |
|  |   |   |   |   |   |  |   |  |  |  |  |
|  |  内森·迈耶·罗斯柴尔德 |  内森·迈耶·罗斯柴尔德 |  |  |  |  |  艾玛·路易丝·冯·罗斯柴尔德 |  艾玛·路易丝·冯·罗斯柴尔德 |   |   |   |
|  |   |  |  |  |  |  |   |  |  |  |  |
|  |   |   |   |   |   |   |   |  |  |  |  |
|  |  内森尼尔·查尔斯·罗斯柴尔德 |  内森尼尔·查尔斯·罗斯柴尔德 |   |  罗兹卡·厄斗·冯·魏泽姆斯特恩 |  罗兹卡·厄斗·冯·魏泽姆斯特恩 |   |   |   |   |   |   |
|  |   |   |   |   |  |  |  |  |  |  |  |
|  |  |  |   |  |  |  |  |  |  |  |  |
:  
|  |  米里亚姆·路易莎·罗斯柴尔德 |  米里亚姆·路易莎·罗斯柴尔德 |   |  伊丽莎白·夏洛特·罗斯柴尔德 |  伊丽莎白·夏洛特·罗斯柴尔德 |   |  内森尼尔·迈耶·维克多·罗斯柴尔德 |  内森尼尔·迈耶·维克多·罗斯柴尔德 |   |  凯瑟琳·安妮·潘诺尼卡·德·科尼斯瓦特 |  凯瑟琳·安妮·潘诺尼卡·德·科尼斯瓦特 |
儀親王

和碩儀親王（满语：，穆麟德轉寫：Hošoi yongso cin wang），清朝世袭親王。乾隆四十四年（1779年），乾隆帝第八子永璇封郡王（後進親王），封號儀，死後諡號慎，未得世袭罔替，每次襲封需遞降一級，一共传了七代七位。
儀親王

1779年—1832年：儀慎親王永璇 初封郡王，1797年進親王，諡號慎
1832年—1834年：儀順郡王綿志 永璇一子，降爵為郡王，諡號順
1834年—1893年：郡王銜貝勒奕絪 綿志四子，降爵為貝勒，1884年加郡王銜
追封：貝子載桓 奕絪一子，降爵為貝子
1894年—1901年：貝勒銜貝子毓崐 載桓孫，溥頤一子，降爵為貝子，追加貝勒銜，無嗣
1902年—1916年：奉恩鎮國公毓岐 載桓孫，溥頤五子，降爵為奉恩鎮國公
1917年—？：奉恩鎮國公恆鉞 毓岐一子
儀親王 > 綿志支系

1799年—1832年：貝勒綿志 永璇一子，初封不入八分輔國公，1802年進貝子，1809年進貝勒，1813年加郡王銜，1815年除郡王銜，1819年復郡王銜，1820年除郡王銜，1823年復郡王銜，1832年襲儀郡王
儀親王 > 奕績支系

追封：不入八分輔國公奕績 綿志三子，1813年追封，無嗣
儀親王 > 奕絪支系

1831年—1834年：奉恩輔國公奕絪 綿志四子，1834年襲貝勒