﻿/*
	© 2012-2016 FrankHB.

	This file is part of the YSLib project, and may only be used,
	modified, and distributed under the terms of the YSLib project
	license, LICENSE.TXT.  By continuing to use, modify, or distribute
	this file you indicate that you have read the license and
	understand and accept it fully.
*/

/*!	\file NPL.txt
\ingroup Documentation
\brief NPL 规格说明。
\version r862
\author FrankHB <frankhb1989@gmail.com>
\since build 304
\par 创建时间:
	2012-04-25 10:34:20 +0800
\par 修改时间:
	2016-05-26 18:46 +0800
\par 文本编码:
	UTF-8
\par 模块名称:
	Documentation::NPL
*/


/*

@0 体例和适用范围：
引用标记参见 [Documentation::CommonRules @@0.1] 。
项目范围参见 [Documentation::ProjectRules @@1] 。
本文档适用于 NPL 及实现(@2.1.2) 。
编码细节和其它规范参见 [Documentation::Designation] 。

@1 整体设计：

@1.1 设计的基本原理、表达形式和抽象：
设计的出发点：构建一个可用计算机实现的语言。
原始目的：在以标准 C++ 环境（宿主实现）的程序框架中嵌入配置和脚本操作。
扩展目的：渐进地向独立的计算机软件系统演进，探究能适用于各个领域并以计算机实现的通用语言。
本文描述基于此出发点的 NPL(Name Protocoling Language) 及其参考实现。

@1.2 理论背景、工具和依据：
基本内容参见 [Documentation::CommonRules @@2.1] 。

@1.2.1 组织概念模型：
略。

@1.2.3 设计意义：
参见 [Documentation::Designation @@2.2.3] 。

@1.3 构建原则：
基本内容参见 [Documentation::CommonRules @@2.2] 。
其它参见 [Documentation::Designation @@2.3] 。

@1.4 领域设计原则：

@1.4.1 原则性描述：
关于设计和实现的哲学。

@1.4.1.1 本体论：
语义的存在体现本质。

@1.4.1.2 价值观：

@1.4.1.2.1 变化的自由：
在明确需求的前提下，尽可能保证对现状按需进行改变的可行性和便利性。
适用于一般需求。
对计算机软件：尽量避免不必要地损失可修改性，便于保障按需引入或除去接口(@2.1.2) 及其实现的自由。
在满足需求的前提下，修改应尽可能少地有碍于其它的接口。

@1.4.1.2.2 避免不必要付出代价：
尽可能减少影响需求实现的成本。
适用于一般需求。
对计算机软件：不为不需要的特性付出代价（现代 C++ 的 no overhead 原则）。

@1.4.1.2.3 最小接口原则：
在确定的范围内尽可能少地提供必须的接口，以避免影响接口适应需求的能力，同时减少复杂性。
适用于一般设计。
对需要在计算机上实现的人工语言设计：设计语言不应该进行功能的堆砌，而应该尽可能减少弱点和限制，使剩下的功能显得必要（参照 Scheme ）。

@1.4.1.3 形而上学：

@1.4.1.3.1
语言设计独立于语言实现(@2.2) 。
适用于计算机语言设计。

@1.4.1.3.2
语言实现包括库设计。
适用于可复用实现的计算机语言设计。

@1.4.1.4 方法论：

@1.4.1.4.1 避免不成熟的优化：
参照 D.E.Knuth ： “ Premature optimization is the root of all evil. ”。
适用于一般需求。
适时收缩理论长度以照顾可操作性（注意断言一个优化过早自身可能就是一个过早的优化）；
主动适应需求变更（不同时明确全部的具体需求，只限定需求范围：能使用计算机实现部分语义的任务）。

@1.4.2 阶段性目标：
确定系属分类。
确定实现方法。
必要的自然语言描述。
基础语义设计。
领域特定语言演化。

@1.4.3 语义方法：
形式语义方法：指称语义、公理语义、操作语义。
非确定语义：经验语义，不需要使用自然语言解释的部分。

@2 基本概念和约定：
描述中可能涉及上下文相关的略称参见 @2.3 。

@2.1 通用约定：
关于“语言”补充的基本概念和约定，使用元语言语法 <相关范畴/上下文> 。
除非有其它说明，适用于任意上下文。

@2.1.1 [<自指><名词>] ：
实体(entity) ：任意被自然语言表达的目标；不需要通过自然语言先验定义；参见经验语义。
语义(semantics) ：参见经验语义。
经验(experience) ：参见哲学或一般等价的经验语义。
范畴(category) ：参见范畴论。
态射(morphism) ：参见范畴论。
归纳(induction) ：一种态射，可操作性参见经验语义。
方法学(methodology) ：一个归纳经验得到的范畴；参见哲学或一般等价的经验语义。
方法(method) ：方法学的一个子范畴；可操作性参见经验语义。
概念(concept) ：参见形式逻辑学。
上下文(context) ：一种概念范畴适用的态射；参见经验语义。

@2.1.2 [<非自指>] ：
形式(form) ：参见经验语义和数学。
<概念> 内涵：参见形式逻辑学。
<概念> 外延：参见形式逻辑学。
<概念> 定义(definition) ：确定概念内涵和外延的方法；参见任意一种形式逻辑学。
集合(set) ：参见 NBG 集合论。
序列(sequence) ：有序集合。
类(class) ：参见 NBG 集合论和范畴论。
真类(proper class) ：参见 NBG 集合论和范畴论。
<动词> 抽象(abstracting) ：通过经验语义定义概念范畴或集合的方法。
<名词> 抽象(abstraction) ：<动词>抽象的结果。
<动词> 封装(encapsulating) ：从某一个范畴中抽象一个子范畴的方法。
<名词> 封装(encapsulation) ：<动词>封装的结果。
接口(interface) ：一种封装，参见软件工程学。
实现(implementation) ：一种封装，参见软件工程学。
重用(reusing) ：参见经验语义和软件工程学。
不变量(invariable) ：满足某种等价关系（自反、传递、对称的二元关系）的实体。参见数学和契约式程序设计。
状态(state) ：可以和其它实体关联的、可在某个上下文中保持变化或不变的实体。同一状态总是保持变化或保持不变。状态变化的含义参见经验语义、数学或另行约定。
可变状态(mutable state) ：在某个上下文中可能映射到若干其它状态的状态。
不可变状态(immutable state) ：不是可变状态的状态。
<动词> 派生(deriving) ：基于重用的操作。
<名词> 派生(derivation) ：<动词>派生的结果。
<语言> 接口(<language>interface) ：和表达语义有关的语言的可见的特征。
<语言> 实现(<language>implementation)：对语言表达语义的表达。
<语言> 人类接口(human interface) ：语义仅对人类有意义（内容改变时可以导致语义的差异性），不提供为涉及作为图灵机实现的语言接口。
<语言> 机器接口(machine interface) ：对机器（或特定语言实现的特定部分）有意义的语言接口。注意不同语言实现组成部分可以不同。例如，对 C 预处理器而言， C 源代码中的空白符是机器接口，而对翻译器来说则不是。就源代码而言，机器接口总是人类接口的子集。
语言特性(language feature) ：作为功能提供的人类接口。

@2.2 领域约定：
适用于上下文 <NPL> 。
广义实体： <通用约定> 实体。语言抽象的目标，不另行定义（意义最终取决于自然语言）。
名称(name) ：一种特殊的广义实体，用于指称另一个广义实体。
实体(entity) ：非名称的广义实体。
规则(rule) ：用于确定行为或其它规则的描述。
约束(constraint) ：可被形式表达，用于限制和明确行为的规则。不一定使用形式表达。
违反(violation) ：对约束指定的条件的不满足。
语言实现(language implementation) ：语言提供的接口的实现，是语言的表现形式，可以是具体语言实现或抽象语言实现之一。
具体语言实现(concreate language implementation) ：能最终完全表达为可预测的物理现象一一对应的表达可计算性的实现（如机器指令），一般应为程序。
抽象语言实现(abstract language implementation) ：非具体语言实现的语言实现。形式意义的标准定义的语言属于此类。
派生语言实现(derived language implementation) ：派生已有实现的部分或全部得到的语言实现。以下简作“派生实现”。
实现环境(environment of implementation) ：对应特定语言实现的特定不变状态（对机器来说可以是配置项，对人来说不确定，所以一般忽略）的集合。
行为(behavior) ：语言实现的外部表现。基于可操作性考虑，一般仅约束机器实现。
翻译(traslation) ：不同语言之间的变换，可作为语言实现的形式。
解释(interpretation) ：通过直接执行表现行为的具体语言实现的形式。
文法(grammar) ：描述语言的可形式化的规则。
语法(syntax)：描述语言的字面(literal) 结构而不考虑解释(interpretation) 或含义(meaning) 的规则、原理和过程。
语义(semantics)：语法以外的文法，可以约束含义的表达。
代码(code)：任意有限的语言的实例片段。
伪代码(pseudo code)：抽象语言实现的语言的代码。注意习惯上和具体语言实现代码完全一致的代码可以不作为伪代码考虑。
程序(program) ：具体语言实现接受的以代码表示的输入，或被变换后对应的输出。
元语言(metalanguage) ：描述其它语言的语言。
对象语言(object language)：被元语言操作或实现的语言。
元编程(metaprograming) ：使用元语言编程。
反射(reflection) ：元语言和对象语言相同的元编程。
具现(reification) ：在对象语言中以数据模型作为关联实体以表示程序的语义。
诊断消息(diagnostic message) ：用于和用户交互的提示性信息。
未定义的(undefined) ：可能导致违反约束但不保证具有诊断消息的。表示置于规则下的行为等不可预测。
未指定的(unspecified) ：在各个实现中可能存在的。不应假定不同实现具有完全一致的特性。
由实现定义的(implementation-defined) ：取决于各个具体语言实现的，要求有文档说明。
由派生实现定义的(derived-implementation-defined) ：取决于各个具体派生实现的，要求除存在默认定义或被派生实现的部分有明确的文档说明。
语言特性(language feature) ：语言提供的功能接口，可以是具体语言特性或抽象语言特性之一。
具体语言特性(concrete language feature) ：完全没有派生语言实现定义的语言特性。
抽象语言特性(abstract language feature) ：非具体语言特性的语言特性。
过时的(obsolesence) ：不应继续使用的（接口/特性）。
废弃的(deprecated) ：过时的但因为兼容性等原因，暂时保留的、一般可提供替代的接口或特性。

@2.3 略称：
仅在不致混淆时使用。
实现(implementation) ：语言实现。
环境(environment) ：实现环境。
派生实现(derived implementation) ：派生语言实现。

@2.4 NPL 实现模型：
NPL 是抽象的语言，没有具体语言实现(@2.2) ，但一些直接影响实现表现形式的规则被本节限定。
NPL 具体实现进行抽象解释(abstraction interpret) ，其目标不一定是程序(@2.2) 。

@2.4.1 实现的执行阶段(phase of execution) ：
一个 NPL 的完整实现应保证行为能符合以下的阶段（具体阶段不要求和实际实现中的一一对应，但应保证顺序一致）：
分析(analysis) 阶段：处理代码，取得适当的中间表示(intemediate representation) ；
代码生成：生成可被其它阶段执行的代码，称为目标代码；
运行：运行目标代码。
其中分析阶段是任意实现必要的，包含：
词法分析：必要时转换字符编码；转义并提取记号；
语法分析：检验语法正确性(@2.5) ；
语义分析：检验语义正确性(@2.5) 。
运行之前的阶段总称为翻译(translation) ，包含各个翻译阶段(phase of translation) 。
对有宿主语言支持的嵌入实现(embedded implementation) 或目标不是程序的情况，代码生成及之后的阶段不是必须的。
嵌入实现的宿主语言可直接运行语义分析的结果（中间表示）。
在语义不变的前提下，允许实现一次或多次翻译部分代码产生部分中间结果并复用。
其它可能的阶段由派生实现定义，但应满足所有阶段具有确定的全序关系，且不改变上述指定的阶段的顺序。符合这些条件的附加阶段称为扩展阶段。

@2.4.2 并发实现(concurrent implementation) ：
一个实现中顺序执行以上执行阶段的控制流称为一个执行线程(thread of execution) ，简称线程(thread) 。
一个实现在整个执行过程中可以有一个或多个线程被执行。是否支持多线程执行（多线程翻译和/或多线程运行）由派生实现定义。

@2.4.3 阶段不变量约束：
若某些状态在某个执行阶段 k 被唯一确定为不可变状态，且在之后的状态下是不变量，则此状态称为满足 k 阶段不变量约束的。

@2.5 正确性：
正确性规则包含语法正确性和语义正确性。
当正确性规则被发现违反时，实现进入异常执行状态。
异常执行的实现是否存在未定义行为由派生实现定义。

@2.6 实现行为：
实现的行为由具有非特定存储的抽象机描述。
若语义规则明确可以行为被忽略，则被忽略之后的实现行为与之前等价。
允许派生实现定义附加的等价性。
实现可能向用户以派生实现定义的方式输出诊断消息(diagnostic message) 。

@2.7 简单实现模型约定：

@2.7.1 嵌入宿主语言实现：
一个派生实现使用外部语言 L 简单实现模型 NPL-EMA ，若满足：
以 L 为宿主语言的嵌入实现，不包含扩展执行阶段(@2.4.1) ；
单一实现不支持多线程执行(@2.4.2) ，但允许多个实现同时在宿主中多线程执行。

@3 文法：
本章约定基本的 NPL 文法(@2.2) 规则中，包括语法及对应的基础词法。对应的语义单独列为一章(@4) 。
多态文法规则：派生实现可完全不提供本章明确定义的词法和语法构造的支持，仅当提供同构的替代文法且符合语义规则。

@3.1 基本概念：
字符(character) ：组成语言代码的最小实体。
基本翻译单元(basic transation unit) ：任意连续字符的有限序列（可以是空序列）。
翻译单元(translation unit) ：基本翻译单元的集合，之间满足由派生实现定义的规则。

@3.2 字符集和字符串：
字符集(character set) ：对一个实现而言不变的字符的有限集合。
基本字符集(basic character set) ：实现环境必须支持的字符集。具体由派生实现定义。
字符串(character string) ：字符集上的序列。
其它同 ISO/IEC 14882:2011 对 character 和 character set 的有关定义。

@3.3 词法规则(lexical rules) ：
约定元语言语法 <x> 表示词法元素 x ， ::= 表示定义， | 表示析取。
名称约定为在 NPL 中符合语法(@3.4) 约束的若干记号(@3.3.1) 的集合，一般可实现为可表达的字符串。

@3.3.1 基本词法构造：
<token> ::= <literal> | <$punctuator> | <$identifier>
记号(token) ：代码中非空白符分隔的字符序列。
字面量(literal) ：一种记号，参见 @3.3.3 。
标点(punctuator) ：由派生实现定义的特定字符序列的集合，起分隔其它记号的作用，具有一定语义功能。
标识符(identifier) ：除字面量和标点以外的记号。
可以保证 ISO/IEC 14882:2011 的 identifier 的定义，或在上述标识符中插入字符 $ 构造得到的标识符属于 NPL 标识符。

@3.3.2 转义序列和字符序列：
<char-escape-content-seq> ::= <$single-escape-char> | <$escape-prefix-char><$escape-content-seq>
<char-seq> ::= <$literal-char> | \<char-escape-seq>

@3.3.3 字面量：
<literal-content> ::= <char-seq> | <literal-char-seq><literal-data>
<code-literal> ::= '<literal-content>'
<data-literal> ::= "<literal-content>"
<string-literal> ::= <code-literal> | <data-literal>
<literal> ::= <string-literal> | <$derived-impldef-literal>
代码字面量(code literal) ：以 ' 作为起始和结束字符的记号。
数据字面量(data literal) ：以 " 作为起始和结束字符的记号。
字符串字面量(string literal) ：代码字面量或数据字面量。
字面量：字符串字面量或其它由派生实现定义的记号。

@3.3.4 词法分析规则：
输入翻译单元，输出记号序列。
输出规则（按优先顺序）：
断行连接：反斜杠之后紧接换行符的双字符序列视为续行符，会被删除；
反斜杠转义：连续两个反斜杠被替换为一个反斜杠；
引号转义：反斜杠之后紧接单引号或双引号时，反斜杠会被删除；
字面量：未被转义的单引号或双引号后进入字面量解析状态，无视以下规则，直接逐字节输出原始输入，直至遇到对应的另一个引号。
窄字符空白符替换：单字节空格、水平/垂直制表符、换行符被替换为单一空格；回车符会被忽略；
原始输出：其它字符序列逐字节输出。

@3.4 语法 ：
本节指定 NPL 作为对象语言(@2.2) 的语法(@2.2) 。
约定元语言(@2.2) 的语法 x 表示语法元素 x ， ::= 表示定义， | 表示析取。

@3.4.1 基本语法构造：

@3.4.2 表达式(expression) ：
expression ::= atomic-expression | composite-expression | list-expression
表达式是受表达式语法约束的记号序列。
其中构成分别称为原子表达式(atomic expression) 、复合表达式(composite expression) 和列表表达式(list expression) 。
构成表达式的表达式是前者的子表达式(subexpression) 。

@3.4.2.1 原子表达式：
atomic-expression ::= token
原子表达式不能被表示为其它表达式的语法构成形式的复合。

@3.4.2.2 复合表达式：
composite-expression ::= token expression | expression token
符合表达式是原子表达式和表达式的复合。
同一个表达式可能被按原子表达式出现的位置以不同的方式规约为复合表达式。允许的规约复合表达式的方式由派生实现定义。

@3.4.2.3 列表表达式：
list-expression ::= <left-list-bound> expression <right-list-bound>
<left-list-bound> ::= ( | <extended-left-list-bound>
<right-list-bound> ::= ) | <extended-right-list-bound>
列表表达式是使用 <left-list-bound> 和 <right-list-bound> 作为边界的表达式。
<left-list-bound> 和 <right-list-bound> 是不同的标点。
边界为 ( 和 ) 的表达式是基本列表表达式。其它可能的边界由派生实现定义，构成扩展列表表达式。

@3.4.4 语法形式(syntactic form) ：
语法形式是词法上满足特定形式(@2.1.2) 的语法构造。
除非派生实现另行指定，语法形式总是表达式。

@3.4.5 语句(statement) ：
以派生实现定义的标点结尾的表达式称为语句。
语句语法的分组(grouping) 规则以及是否隐式地作为列表表达式求值由派生实现定义。

@3.4.6 简单文法约定：
一个派生实现使用简单文法 NPL-GA ，若满足：
翻译单元同基本翻译单元(@3.1) ；
字面量同字符串字面量(@3.3.3) ；
只支持左原子表达式构成复合表达式(@3.4.2.2) ；
只支持基本列表表达式(@3.4.2.3) ；
标点为单个字符(@3.1) ；
不支持语句(@3.4.3) 。

@4 语义：
NPL 的语义规则(@2.2) 构成演绎系统(deductive system) ，通过对翻译单元(@3.1) 中的表达式(@3.4.2) 的求值(@4.1) 表达。
除非派生实现另行约定，仅使用表达式指定语义，系统的规约(@4.1) 规则即表达式的求值规则(@4.4) 。

@4.1 基本概念：
范围(range) ：一个连续区间。此处“连续”的概念由派生实现定义，默认参照数学的形式定义。
声明(declaration) ：引入单一名称的表达式。
声明区域(declarative region) ：对某一个声明及其引入的名称，通过声明区域规则(@4.3.1) 决定，可由词法分析实现(@5.3) 确定的关于这个名称有效的代码片段的最大位置范围。
有效名称(valid name) ：可以唯一确定指称的实体的名称。
有效命名实体(valid named entity) ：有效名称指称的实体。
名称隐藏(name hiding) ：若同一个名称在同一个位置属于超过一个声明区域，则应能通过名称隐藏规则(@4.3.2) 确定唯一有效的声明以指定有效名称和对应的有效命名实体，此时有效名称隐藏其它声明区域声明的名称，有效命名实体隐藏可以使用被隐藏名称指称的实体。
作用域(scope) ：声明区域的子集，满足其中指定的名称是有效名称。
生存期(lifetime) ：逻辑上关于可用性的连续区间的抽象，是一个闭集。
对象(object) ：表示可被逻辑上表达为连续存储的状态的集合且能明确生存期开始和终止的实体。
变量(variable) ：通过声明引入的实体。注意不一定表示可变状态。
常量(constant) ：满足某种不变量的约束以和不可变状态关联的实体。具体由派生实现定义。注意不和变量对立（表示不可变状态的变量可能是常量）。
表示(representation) ：表现演绎实例、具体实现及其中一部分实体（如某个值）的状态。
值(value) ：表达式关联的不可变状态。
副作用(side effect) ：对表达式的值以外的表示的改变。
规约(reduction) ：根据规约规则的演绎，包括表达式之间的等价变换(transformation) 即以作用相等的表达式替代另一个表达式，以及此过程中实现环境的交互。
作用(effect) ：具体实现规约表达式的结果，包括值的计算和副作用的产生。
抽象求值(abstract evaluation) ：对表达式的不取得作用的规约。
具体求值(concrete evaluation) ：对表达式的取得作用的规约。
求值(evaluation) ：抽象求值或具体求值。

@4.1.1 附加约定：
状态不变由实现定义的等价关系(@2.1.2) 决定。

@4.2 基本语义规则：
所有不需要诊断消息的规则由派生实现定义。
以下规则不产生未定义行为。

@4.3 名称规则：
名称(@2.2) 和能标识特定含义、符合名称词法约束(@3.3) 的表达式(@3.4.2) 一一对应。
具体的外延由派生实现定义。
表示名称的表达式不同于名称，但在无歧义时，语言中可直接以名称代指表达式和对应的词法元素。

@4.3.1 声明区域规则：
对引入名称 n 的声明 D ，对应的声明区域始于紧接 n 的位置，终于满足以下条件的记号“)”（若存在）或翻译单元末尾（不存在满足条件的记号“)”）：
记号“)”和与之匹配的记号“(”构成的表达式包含 D ；
此记号之前不存在满足上一个条件的其它的记号“)”。

@4.3.2 可见(visible) 名称：
名称隐藏规则：若声明 D 是表达式 E 的子集，且不存在 D 的子集声明同一个名称，则 D 声明了有效名称，隐藏了 E 中其它同名的名称。
在声明区域中，没有被隐藏的名称是可见(visible) 的。有效名称实质蕴含可见名称。

@4.3.3 名称解析(name resoultion) ：
名称解析是通过名称确定名称指定的实体的过程。
名称解析包括名称验证(name verification) 和名称查找(name lookup) 。
不保证名称解析总是成功。
名称验证确定可见名称(@4.3.2) 的基础上确定名称是否有效。
名称查找是从已知有效名称确定唯一指称的实体的过程，仅在名称验证成功后进行。
不同名称经过名称查找的结果可能等效。等效的有效名称视为同一的，规则由派生实现定义。
以上约定以外的具体规则以及失败的行为由派生实现定义。

@4.3.4 命名空间(namespace) ：
命名空间是实体(@2.2) 。命名空间可以由名称指称。
是否实现命名空间为程序中可由用户指定可变的实体及在求值(@4.1) 时可访问的对应数据结构（求值环境），由派生实现定义。

@4.3.4.1 指称(denotation) ：
总是没有名称指称的命名空间是匿名命名空间(anonymous namespace) 。
没有有效名称指称的命名空间是未命名命名空间(unnamed namespace) 。
注意匿名命名空间和未命名命名空间不同。前者可能是一个系统的默认约定，一般整体唯一存在（如全局(global) 命名空间）；后者只是对某些接口隐藏，可以有多个。
NPL 定义一个抽象的匿名命名空间，称为根命名空间。未命名命名空间的支持由派生实现定义。
NPL 约定一个在实现中的有效名称总是指称一个命名空间。有效名称指称的命名空间的同一性和有效名称的同一性(@4.3.3) 对应。

@4.3.4.2 成员(member) ：
除了用于指称的名称外，一个命名空间可以和若干其它名称关联。
通过派生实现定义的对命名空间的操作可以取得的名称是这个命名空间的成员。
若无歧义，命名空间的成员指称的实体也称为这个命名空间的成员。
命名空间直接包含成员，称为直接成员。
除了根命名空间和其它派生实现定义外，命名空间可以作为另一个命名空间的成员，此时命名空间内的成员（若存在）是包含其的命名空间的间接成员。
命名空间对成员的直接包含和间接包含总称为包含，是反自反的、反对称的、传递的二元关系。

@4.3.4.3 简单名称(simple name) 和限定名称(qualified name) ：
命名空间的直接成员(@4.3.4.2) 的标识符在这个命名空间中是有效名称，称为简单名称。
命名空间及其成员按包含关系依次枚举标识符组成的序列是一个名称，称为在这个命名空间中的限定名称。
根命名空间的限定名称称为全限定名称(fully qualified name) 。
限定名称的语法（如标识符之间的分隔符等）由派生实现定义。

@4.4 求值规则：
求值应满足以下基本规则：
值替换规则：表达式的值的计算通过已知的子表达式的值替换决定。
除非派生实现另行约定，子表达式的值仅由求值得到，此时递归蕴含规则(@4.4.4) 中的求值依赖规则是这个规则的推论。

@4.4.1 求值顺序(evaluation order) ：
先序(sequenced before) 关系是两个求值之间存在的一种偏序关系(partial order) ，对实现中求值之间的顺序提供约束。
后序(sequenced after) 是先序的逆关系。
非决定性有序(indeterminately sequenced) 是先序或后序的并集。
无序(unsequenced) 是非决定性有序在求值二元关系全集上的补集。
非决定性求值规则：除非派生实现另行约定，递归蕴含规则(@4.4.4) 约定外的任意表达式的求值之间无序。
非决定性求值规则允许在语言中表达并发实现(@2.4.2) 。

@4.4.2 求值性质：
两个具体求值等价，当且仅当两者的作用相等。
两个求值等价，当且仅当作为具体求值时等价，或其中每个求值的变换实质蕴含另一个。
没有副作用的求值是纯的(pure) （仅有值的计算或抽象求值）。
值为被求值的表达式自身的具体求值或不包含变换为存在不等价求值的表达式的抽象求值为恒等(identity) 求值。
恒等的纯求值是空求值(empty evaluation) 。
作用是空集的表达式求值是空作用求值(null effect evaluation) 。推论：空作用求值是空求值。
语法形式(@3.4.4) 固定且求值总是空求值的表达式是空表达式(empty expression) ，这仅由派生实现可选提供。

@4.4.3 规范形式(normal form) ：
规范形式是由派生实现定义的表示(@4.1) ，被一组规约规则确定，通过有限的规约步骤后得到，满足之后任意的规约和空求值等价(@4.4.2) 。
表达式在得到规范形式后求值终止。
若表达式规约总是能得到规范形式（求值总是能在有限规约步骤后终止），则具有强规范化(strong normalization) 性质。
除非派生实现另行约定，不保证强规范化性质。

@4.4.4 递归蕴含规则：
除非派生实现另行约定，表达式和子表达式之间的求值满足以下递归蕴含规则：
求值依赖规则：表达式被求值实质蕴含子表达式(@3.4.2) 被求值。
顺序依赖规则：子表达式求值先序(@4.4.1) 于所在的表达式求值。
平凡求值规则：指定一个表达式是平凡求值(@4.4.2) 实质蕴含其子表达式的求值被指定为平凡求值。

@4.4.5 可选求值规则：
应满足的本节上述约定的最小求值规则和语义外的具体求值规则和语义由派生实现定义。
派生实现的求值可满足以下节指定语义，此时应满足其中约定的规则。

@4.6 λ 完备语义和对应语法：
作为通用语言，求值规则表达的系统可具有和无类型 λ 演算(untyped lambda calculus) 对应的形式和计算能力。
基于此语义的派生实现应允许以下几种互不相交的表达式集合，且保证满足在派生实现定义的项上的强规范化（即保证求值能终止）。

@4.6.1 名称表达式(name expression) ：
名称表达式是表示变量的 λ 项。
原子表达式(@3.4.2.1) 的由派生实现定义的非空子集是名称表达式。其它作为名称表达式的表达式语法形式(@3.4.4) 由派生实现定义。
名称表达式不被进一步规约，其求值是替换规则(@4.4) 的平凡形式。

@4.6.2 函数(function) ：
特定的由派生实现定义的表达式对应 λ 抽象，称为函数表达式，简称函数。
λ 抽象可以捕获(capture) 若干有效名称及对应的实体，即这些名称可在函数中使用。
被捕获的名称指称的实体是函数的形式参数(formal parameter, parameter) 。
表达式外被捕获的名称指称的实体是实际参数(actual argument, argument) 。
实际参数和形式参数一一对应。
派生实现应在仅有名称表达式不同的两个函数之间定义等价规则，以满足 λ 演算的 α-转换(alpha-conversion) 规则。
除非派生实现另行约定，函数表达式不需要被进一步规约，此时其求值是替换规则(@4.4) 的平凡形式。

@4.6.2.1 过程(procedual) ：
过程是 λ 抽象具现(@2.2) 的实体。函数表达式的求值结果和过程实体以派生实现定义的方式关联。
具体实现中的过程可能为子例程(subroutine)、协程(subroutine) 、续延(continuation) 等形式的一种或多种，由派生实现指定。
注意过程不一定具有可被对象语言(@2.2) 直接表达的一等(first-class) 函数而在元语言(@2.2) 中可能是，如无限制续延(undelimited continuation) 。

@4.6.3 函数应用：
形如 E1 E2 的表达式 E ，当且仅当 E1 是函数时， E 是函数应用表达式，简称函数应用。
函数应用符合 λ 演算的 β-规约(beta-reduction) 规则，是替换规则(@4.4) 的非平凡形式。
派生实现应指定函数应用规约(@4.1) 的结果是规范形式(@4.6.2)，它对应的值称为函数值。

@4.7 表达式关联实体：

@4.7.1 上下文(context) ：
上下文是表达式关联的状态的特定集合（注意不是 @2.1.1 约定的自指概念），包含以下小节约定的类别。
确定上下文的状态或对可变上下文的修改称为对上下文的访问(access) 。
过程实体(@4.6.2) 决定函数表达式(@4.6.2) 关联的上下文。
其它具体规则由派生实现定义。

@4.7.1.1 显式上下文(explicit context) ：
可通过名称表达式(@4.1.5) 访问的上下文。

@4.7.1.2 隐式上下文(implicit context) ：
除显式上下文外的上下文。

@4.7.2 类型(type) ：
上下文中和表达式直接关联或间接关联的元素，满足某个执行阶段的不变量约束(@2.4.3) 。
和表达式直接关联的类型满足起始阶段不变量约束，称为静态类型(static type) 。
和表达式的值(@4.1) 关联的类型满足运行阶段(@2.4.1) 的不变量约束，称为动态类型(dynamic type) 。
其它可能存在类型或实现执行阶段的扩展由派生实现定义。
称为类型的具体实体和之间的关联由派生实现的类型系统(type system) 规则指定。

@5 语言实现：
当前维护的派生语言为 NPLA ，是 NPL 的抽象语言实现，约定以下附加规则。
NPLA 的参考实现 NPLA1 是具体语言实现，约定特定于当前参考实现的附加规则和实现。

@5.1 NPLA 领域语义支持：
位(bit) ：表示二进制存储的最小单位，具有 0 和 1 两种状态。
字节(byte) ：基本字符集中一个字符需要的最少的存储空间，是若干位的有序集合。
八元组(octet) ： 8 个位的有序集合。

@5.2 NPLA 约定：
使用宿主语言为 ISO C++11 的简单实现模型 NPL-EMA(@2.7.1) 。
使用语法 NPL-GA(@3.4.5) 。
名称仅被实现为字符串。
动态类型同静态类型。
规范形式(@4.4.3) 是特定类型的 C++ 对象。
名称解析失败(@4.3.3) 可能被忽略而不终止(@4.4.3) 实现演绎。
不提供命名空间(@4.3.4) 实现的可变实体。
过程实现为子例程(@4.6.2.1) 。
一字节占用的位和宿主环境一致（至少占用 8 个二进制位）。

@5.3 NPLA 公共实现：
词法分析参见 @3.3.4 和参考实现 NPL::Lexical 。
语法分析参考实现 NPL::SContext 。
派生实现可能检查更多语法规则。
抽象语法树以 ValueNode 类型表示。
之后的若干阶段(@2.4.1) 中得到规范形式的中间表示和规范形式始终作为单一的树，其节点以 ValueNode 类型表示。
名称以 string 类型表示。
以上类型都在 namespace NPL 中声明，从 namespace YSLib 引入。
关于 YSLib::ValueNode， 参见 [Documentation::YSLib @@3.16] 。

@5.4 NPLA1 约定：
仅使用宿主语言的类型和值作为状态。类型等价性由 C++ 定义。值等价性由宿主实现的 == 表达式的结果定义。
当前不特别约定类型系统，所有类型都是同宿主类型的空字符结尾的字符串（ C++ NTCTS ）。
附加规则：
当前仅支持标识符(@3.3.1) 作为名称。以 $ 起始的名称保留给宿主交互使用，含有 __ 的名称保留给 NPL 实现。违反保留名称规定的程序可能会造成未指定的运行时错误。
函数的求值结果被宿主实现以 ValueNode 表示为 string 类型或 ValueNode 类型的节点。

@5.5 NPLA1 解释实现：
NPL::TransformNPLA1 通过 ValueNode 变换实现解释，参数指定映射例程，结果为 NPL 序列语义结构。
复合表达式中的经过节点到字符串的映射例程被解释为序列语义结构的名称，余下的项一一映射为子节点。
变体 NPL::TransformNPLA1Sequence 使用 NodeSequence 代替 ValueNode::Container 作为结果中子节点的容器，其它行为和 NPL::TransformNPLA1 相同。

@5.6 NPLA1 应用实例：
NPLA1 当前加入特定的序列化和反序列化作为配置文件，参见 NPL::Configuration 。
NPLA1 的上述配置文件加入特定的匹配和初始化机制作为 YSLib::UI::Loader([Documenatation::YSLib @@5.6.8]) 在运行时读取用户界面布局和配置的脚本。
NPLA1 用于 MIME 类型和文件名映射([Documentation::YSLib @@4.6.3]) 的实现，上述配置文件对应的外部配置格式。

@5.7 NPLA 其它实现应用实例：
NPL::SXML 命名空间提供的 API 部分支持以 NPLA 分析 SXML 及构造 NPLA 表示的节点并转换为 XML 输出。
NPL 自定义分析器被用于 NPL::DecomposeMakefileDepList 实现解析 GCC 输出的兼容 GNU make 包含依赖字符串。

@5.8 兼容性：
除非在此另行约定， YSLib 中的 NPL 实现保持兼容。
影响向前兼容的变更：
b449 增加对多个未命名节点（叶节点或首个子节点未能解析为名称的分支节点）作为非名称子节点时的反序列化支持。多个值会被以 $ 前缀接序号（从 0 起始）命名。之前的版本中读取的节点名称为空串，值被覆盖为第一个节点值。

@6 编码风格导引：
仅叙述之前章节未涉及的内容。
参见 [Documentation::CommonRules @@5] 。

@7 一般实现导引：

@7.1 程序实现：
程序是语言的派生。实现程序即在语言的基础上指定派生规则。

*/
////

