• R/O
  • SSH

YSLib: Commit

The YSLib project - main repository


Commit MetaInfo

Revisión187738900a17fd7873917f3f1eb0a8721a8b5dd3 (tree)
Tiempo2022-09-23 21:46:50
AutorFrankHB <frankhb1989@gmai...>
CommiterFrankHB

Log Message

更新主分支版本: build 956 rev 10 。

Cambiar Resumen

    Diferencia incremental

    diff -r 5acfef664815 -r 187738900a17 YFramework/include/Helper/Initialization.h
    --- a/YFramework/include/Helper/Initialization.h Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/include/Helper/Initialization.h Fri Sep 23 20:46:50 2022 +0800
    @@ -1,5 +1,5 @@
    11 /*
    2- © 2009-2016, 2019-2020 FrankHB.
    2+ © 2009-2016, 2019-2020, 2022 FrankHB.
    33
    44 This file is part of the YSLib project, and may only be used,
    55 modified, and distributed under the terms of the YSLib project
    @@ -11,13 +11,13 @@
    1111 /*! \file Initialization.h
    1212 \ingroup Helper
    1313 \brief 框架初始化。
    14-\version r893
    14+\version r896
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since 早于 build 132
    1717 \par 创建时间:
    1818 2009-10-21 23:15:08 +0800
    1919 \par 修改时间:
    20- 2020-10-05 09:19 +0800
    20+ 2022-09-23 01:05 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -156,7 +156,7 @@
    156156
    157157 /*!
    158158 \brief 取值类型根节点。
    159-\pre 断言:已初始化。
    159+\exception GeneralEvent 异常中立:由 FetchEnvironmnet 抛出。
    160160 \since build 688
    161161 */
    162162 YF_API ValueNode&
    @@ -172,6 +172,7 @@
    172172
    173173 /*!
    174174 \brief 取 MIME 类型名和文件扩展名双向映射对象。
    175+\exception GeneralEvent 异常中立:由 FetchEnvironmnet 抛出。
    175176 \since build 450
    176177 */
    177178 YF_API MIMEBiMapping&
    diff -r 5acfef664815 -r 187738900a17 YFramework/include/NPL/Configuration.h
    --- a/YFramework/include/NPL/Configuration.h Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/include/NPL/Configuration.h Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Configuration.h
    1212 \ingroup NPL
    1313 \brief 配置设置。
    14-\version r445
    14+\version r468
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 334
    1717 \par 创建时间:
    1818 2012-08-27 15:15:08 +0800
    1919 \par 修改时间:
    20- 2022-09-10 02:11 +0800
    20+ 2022-09-23 01:04 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -30,7 +30,8 @@
    3030
    3131 #include "YModules.h"
    3232 #include YFM_NPL_NPLA1 // for YSLib::default_allocator, byte, ValueNode,
    33-// NoContainer, ystdex::exclude_self_params_t;
    33+// TermNode, ContextState, GlobalState, shared_ptr, Environment, std::istream,
    34+// string_view, ystdex::exclude_self_params_t, NoContainer;
    3435
    3536 namespace NPL
    3637 {
    @@ -40,12 +41,30 @@
    4041 {
    4142
    4243 /*!
    43-\brief 加载 NPLA1 翻译单元。
    44-\throw LoggedEvent 警告:被加载配置中的实体转换失败。
    45-\since build 955
    44+\brief 节点加载器。
    45+\since build 956
    4646 */
    47-YF_API YB_ATTR_nodiscard ValueNode
    48-LoadNode(const TermNode&);
    47+class YF_API NodeLoader
    48+{
    49+private:
    50+ mutable ContextState cs;
    51+
    52+public:
    53+ NodeLoader(const GlobalState&);
    54+
    55+ YB_ATTR_nodiscard YB_PURE ValueNode
    56+ LoadNode(const TermNode&) const;
    57+ template<typename _type,
    58+ yimpl(typename = ystdex::exclude_self_t<TermNode, _type>)>
    59+ YB_ATTR_nodiscard YB_PURE inline ValueNode
    60+ LoadNode(_type&& obj) const
    61+ {
    62+ return LoadNode(cs.Global.get().ReadFrom(GlobalState::LoadOptionTag<
    63+ GlobalState::NoSourceInformation>(), yforward(obj), cs));
    64+ }
    65+
    66+ DefGetter(const ynothrow, ContextState&, Context, cs)
    67+};
    4968
    5069 } // namespace A1;
    5170
    diff -r 5acfef664815 -r 187738900a17 YFramework/include/NPL/Dependency.h
    --- a/YFramework/include/NPL/Dependency.h Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/include/NPL/Dependency.h Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Dependency.h
    1212 \ingroup NPL
    1313 \brief 依赖管理。
    14-\version r640
    14+\version r646
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 623
    1717 \par 创建时间:
    1818 2015-08-09 22:12:37 +0800
    1919 \par 修改时间:
    20- 2022-09-14 01:32 +0800
    20+ 2022-09-22 20:16 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -29,8 +29,7 @@
    2929 #define NPL_INC_Dependency_h_
    3030
    3131 #include "YModules.h"
    32-#include YFM_NPL_NPLA1 // for string, vector, GlobalState, YSLib::unique_ptr;
    33-#include <istream> // for std::istream;
    32+#include YFM_NPL_NPLA1 // for string, vector, std::istream, YSLib::unique_ptr;
    3433 #include <ystdex/scope_guard.hpp> // for ystdex::guard;
    3534
    3635 namespace NPL
    @@ -185,13 +184,14 @@
    185184 \brief 加载输入/输出模块。
    186185 \pre 断言:第二参数非空。
    187186 \note 第二参数指定基础环境。
    187+\since build 956
    188188
    189189 加载输入/输出库操作。
    190190 派生实现依赖模块:
    191191 字符串模块 std.strings 。
    192192 */
    193193 YF_API void
    194-LoadModule_std_io(ContextState&, const shared_ptr<Environment>&);
    194+LoadModule_std_io(ContextState&);
    195195
    196196 /*!
    197197 \brief 加载系统模块。
    @@ -208,6 +208,7 @@
    208208 \brief 加载模块管理模块。
    209209 \pre 断言:第二参数非空。
    210210 \note 第二参数指定基础环境。
    211+\since build 956
    211212
    212213 加载模块管理操作。
    213214 派生实现依赖模块:
    @@ -217,7 +218,7 @@
    217218 系统模块 std.system 。
    218219 */
    219220 YF_API void
    220-LoadModule_std_modules(ContextState&, const shared_ptr<Environment>&);
    221+LoadModule_std_modules(ContextState&);
    221222 //@}
    222223
    223224 /*!
    diff -r 5acfef664815 -r 187738900a17 YFramework/include/NPL/NPLA.h
    --- a/YFramework/include/NPL/NPLA.h Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/include/NPL/NPLA.h Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA.h
    1212 \ingroup NPL
    1313 \brief NPLA 公共接口。
    14-\version r9807
    14+\version r9835
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 663
    1717 \par 创建时间:
    1818 2016-01-07 10:32:34 +0800
    1919 \par 修改时间:
    20- 2022-09-05 08:44 +0800
    20+ 2022-09-17 02:28 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -208,27 +208,6 @@
    208208
    209209
    210210 /*!
    211-\brief 解析 NPLA 项节点字符串。
    212-\since build 852
    213-
    214-以 string 类型访问节点,若失败则结果为空串。
    215-*/
    216-YB_ATTR_nodiscard YF_API YB_PURE string
    217-ParseNPLATermString(const TermNode&);
    218-
    219-
    220-/*!
    221-\brief 映射 NPLA 叶节点。
    222-\return 创建的新节点。
    223-\sa ParseNPLANodeString
    224-\since build 674
    225-
    226-创建新节点。若参数为空则返回值为空串的新节点;否则值以 ParseNPLANodeString 取得。
    227-*/
    228-YB_ATTR_nodiscard YF_API YB_PURE ValueNode
    229-MapNPLALeafNode(const TermNode&);
    230-
    231-/*!
    232211 \brief 变换 NPLA 语法节点为语法分析树的叶节点。
    233212 \return 变换得到的节点。
    234213 \note 可选参数指定结果名称。
    @@ -2207,6 +2186,14 @@
    22072186 Environment(BindingMap&& m)
    22082187 : Bindings(std::move(m))
    22092188 {}
    2189+ //! \since build 956
    2190+ Environment(const BindingMap& m, allocator_type a)
    2191+ : Bindings(m, a)
    2192+ {}
    2193+ //! \since build 956
    2194+ Environment(BindingMap&& m, allocator_type a)
    2195+ : Bindings(std::move(m), a)
    2196+ {}
    22102197 //@}
    22112198 /*!
    22122199 \brief 构造:使用父环境。
    @@ -3325,6 +3312,10 @@
    33253312
    33263313 //! \brief 设置参数指定的父环境弱引用。
    33273314 //@{
    3315+//! \since build 956
    3316+inline PDefH(void, AssignWeakParent, ValueObject& parent,
    3317+ TermNode::allocator_type a, EnvironmentReference r_env)
    3318+ ImplExpr(AssignParent(parent, a, std::move(r_env)))
    33283319 inline PDefH(void, AssignWeakParent, ValueObject& parent,
    33293320 TermNode::allocator_type a, ContextNode& ctx)
    33303321 ImplExpr(AssignParent(parent, a, ctx.WeakenRecord()))
    diff -r 5acfef664815 -r 187738900a17 YFramework/include/NPL/NPLA1.h
    --- a/YFramework/include/NPL/NPLA1.h Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/include/NPL/NPLA1.h Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA1.h
    1212 \ingroup NPL
    1313 \brief NPLA1 公共接口。
    14-\version r10005
    14+\version r10057
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 472
    1717 \par 创建时间:
    1818 2014-02-02 17:58:24 +0800
    1919 \par 修改时间:
    20- 2022-09-14 02:53 +0800
    20+ 2022-09-22 20:16 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -50,7 +50,8 @@
    5050 #include <ystdex/algorithm.hpp> // for ystdex::fast_any_of, ystdex::split;
    5151 #include <ystdex/cast.hpp> // for ystdex::polymorphic_downcast;
    5252 #include <ystdex/scope_guard.hpp> // for ystdex::guard;
    53-#include <iosfwd> // for std::ostream;
    53+#include <iosfwd> // for std::ostream, std::streambuf;
    54+#include <istream> // for std::istream;
    5455
    5556 namespace NPL
    5657 {
    @@ -452,7 +453,7 @@
    452453 支持重规约。异步重规约由 ContextNode 支持。
    453454 此处约定的迭代中对节点的具体结构分类默认也适用于其它 NPLA1 实现 API ;
    454455 例外情况应单独指定明确的顺序。
    455- 例外情况包括输入节点不是表达式语义结构(而是 AST )的 API ,如 TransformNode 。
    456+ 例外情况包括输入节点不是表达式语义结构(而是 AST )的 API 。
    456457 规约结果由以下规则确定:
    457458 对异步规约,返回 Reduction::Partial ;
    458459 否则,对枝节点,返回被调用的规约遍的求值结果;
    @@ -745,43 +746,6 @@
    745746
    746747
    747748 /*!
    748-\brief 插入 NPLA1 子节点。
    749-\note 插入后按名称排序顺序。
    750-\since build 852
    751-
    752-第一参数指定的变换结果插入第二参数指定的容器。
    753-若映射操作返回节点名称为空则根据当前容器内子节点数量加前缀 $ 命名以避免重复。
    754-*/
    755-YF_API void
    756-InsertChild(ValueNode&&, ValueNode::Container&);
    757-
    758-/*!
    759-\brief 变换 NPLA1 节点 S 表达式抽象语法树为 NPLA1 语义结构。
    760-\exception std::bad_function_call 第三至五参数为空。
    761-\return 变换后的新节点(及子节点)。
    762-\sa InsertChild
    763-\sa MapNPLALeafNode
    764-\sa ParseNPLATermString
    765-\since build 897
    766-
    767-第一参数指定源节点,其余参数指定部分变换规则。
    768-当被调用的第三参数不修改传入的节点参数时变换不修改源节点。
    769-过程如下:
    770-若源节点为叶节点,直接返回使用 MapNPLALeafNode 创建映射的节点。
    771-若源节点只有一个子节点,直接返回这个子节点的变换结果。
    772-否则,使用 ParseNPLATermString 从第一个子节点取作为变换结果名称的字符串。
    773- 若名称非空则忽略第一个子节点,只变换剩余子节点。
    774- 当剩余一个子节点(即源节点有两个子节点)时,直接递归变换这个节点并返回。
    775- 若变换后的结果名称非空,则作为结果的值;否则,结果作为容器内单一的值。
    776- 否则,新建节点容器,遍历并变换剩余的节点插入其中,返回以之构造的节点。
    777- 调用 InsertChild 插入映射的结果到容器。
    778-子节点的映射操作使用递归 TransformNode 调用。
    779-*/
    780-YF_API ValueNode
    781-TransformNode(const TermNode&);
    782-
    783-
    784-/*!
    785749 \ingroup functors
    786750 \brief 中缀分隔符变换器。
    787751 \since build 881
    @@ -2172,16 +2136,26 @@
    21722136 /*!
    21732137 \sa ListTermPreprocess
    21742138 \sa SetupDefaultInterpretation
    2139+ \since build 566
    21752140 */
    21762141 //@{
    2177- /*!
    2178- \brief 构造:使用默认解释、指定的存储资源和默认的叶节点词素转换器。
    2179- \sa ParseLeaf
    2180- */
    2181- GlobalState(pmr::memory_resource& = NPL::Deref(pmr::new_delete_resource()));
    2142+ //! \sa ParseLeaf
    2143+ //@{
    2144+ //! \brief 构造:使用默认解释、指定的分配器和默认的叶节点词素转换器。
    2145+ GlobalState(TermNode::allocator_type a = {});
    2146+ //! \brief 构造:使用默认解释、指定的存储资源和默认的叶节点词素转换器。
    2147+ GlobalState(pmr::memory_resource& rsrc)
    2148+ : GlobalState(TermNode::allocator_type(&rsrc))
    2149+ {}
    2150+ //@}
    2151+ //! \brief 构造:使用默认解释、指定的分配器和叶节点词素转换器。
    2152+ GlobalState(Tokenizer, SourcedTokenizer, TermNode::allocator_type a = {});
    21822153 //! \brief 构造:使用默认解释、指定的存储资源和叶节点词素转换器。
    2183- GlobalState(Tokenizer, SourcedTokenizer,
    2184- pmr::memory_resource& = NPL::Deref(pmr::new_delete_resource()));
    2154+ GlobalState(Tokenizer leaf_conv,
    2155+ SourcedTokenizer sourced_leaf_conv, pmr::memory_resource& rsrc)
    2156+ : GlobalState(std::move(leaf_conv), std::move(sourced_leaf_conv),
    2157+ TermNode::allocator_type(&rsrc))
    2158+ {}
    21852159 //@}
    21862160
    21872161 /*!
    diff -r 5acfef664815 -r 187738900a17 YFramework/include/YSLib/UI/Loader.h
    --- a/YFramework/include/YSLib/UI/Loader.h Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/include/YSLib/UI/Loader.h Fri Sep 23 20:46:50 2022 +0800
    @@ -1,5 +1,5 @@
    11 /*
    2- © 2013-2016, 2019-2020 FrankHB.
    2+ © 2013-2016, 2019-2020, 2022 FrankHB.
    33
    44 This file is part of the YSLib project, and may only be used,
    55 modified, and distributed under the terms of the YSLib project
    @@ -11,13 +11,13 @@
    1111 /*! \file Loader.h
    1212 \ingroup UI
    1313 \brief 动态 GUI 加载。
    14-\version r676
    14+\version r684
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 433
    1717 \par 创建时间:
    1818 2013-08-01 20:37:16 +0800
    1919 \par 修改时间:
    20- 2020-04-07 00:20 +0800
    20+ 2022-09-22 23:33 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -32,6 +32,7 @@
    3232 #include YFM_YSLib_UI_YUIContainer
    3333 #include YFM_YSLib_Core_ValueNode
    3434 #include <ystdex/cast.hpp> // for ystdex::polymorphic_downcast;
    35+#include <ystdex/function.hpp> // for ystdex::unchecked_function;
    3536
    3637 namespace YSLib
    3738 {
    @@ -236,6 +237,8 @@
    236237 class YF_API WidgetLoader
    237238 {
    238239 public:
    240+ //! \since build 956
    241+ ystdex::unchecked_function<ValueNode(string_view)> Convert;
    239242 GWidgetRegister<> Default{};
    240243 GWidgetRegister<const Rect&> Bounds{};
    241244 //! \since build 495
    @@ -243,6 +246,11 @@
    243246 //! \since build 555
    244247 GWidgetInserterRegister<IWidget&, const ZOrder&> InsertZOrdered{};
    245248
    249+ //! \since build 956
    250+ WidgetLoader(ystdex::unchecked_function<ValueNode(string_view)> conv)
    251+ : Convert(std::move(conv))
    252+ {}
    253+
    246254 //! \since build 888
    247255 //@{
    248256 //! \exception std::out_of_range 异常中立:找不到内部类型节点。
    diff -r 5acfef664815 -r 187738900a17 YFramework/source/Helper/Environment.cpp
    --- a/YFramework/source/Helper/Environment.cpp Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/source/Helper/Environment.cpp Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Environment.cpp
    1212 \ingroup Helper
    1313 \brief 环境。
    14-\version r2001
    14+\version r2004
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 379
    1717 \par 创建时间:
    1818 2013-02-08 01:27:29 +0800
    1919 \par 修改时间:
    20- 2022-09-14 01:34 +0800
    20+ 2022-09-22 00:20 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -59,8 +59,8 @@
    5959 #endif
    6060
    6161 Environment::Environment(Application& app)
    62- : Root(app.get_allocator()), DefaultOutputStream(string(
    63- app.get_allocator())), Global(*app.get_allocator().resource())
    62+ : Root(app.get_allocator()), DefaultOutputStream(
    63+ string(app.get_allocator())), Global(app.get_allocator())
    6464 {
    6565 #if !YF_Hosted
    6666 // NOTE: This only effects freestanding implementations now, which may need
    @@ -153,6 +153,7 @@
    153153 # endif
    154154 );
    155155 NPL::A1::Forms::LoadStandardContext(Main);
    156+ Main.GetRecordRef().Frozen = true;
    156157 }, yfsig, " NPLA1 Failure ",
    157158 " An unexpected error occurs \n"
    158159 " during the initializaiton.\n");
    diff -r 5acfef664815 -r 187738900a17 YFramework/source/Helper/Initialization.cpp
    --- a/YFramework/source/Helper/Initialization.cpp Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/source/Helper/Initialization.cpp Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Initialization.cpp
    1212 \ingroup Helper
    1313 \brief 框架初始化。
    14-\version r3959
    14+\version r3970
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since 早于 build 132
    1717 \par 创建时间:
    1818 2009-10-21 23:15:08 +0800
    1919 \par 修改时间:
    20- 2022-01-31 20:02 +0800
    20+ 2022-09-23 01:04 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -41,8 +41,7 @@
    4141 // platform_ex::WCSToUTF8, platform_ex::UTF8ToWCS;
    4242 #endif
    4343 #include YFM_CHRLib_MappingEx // for CHRLib::cp113_lkp;
    44-#include YFM_NPL_Configuration // for NPL::Configuration, NPL::Session,
    45-// A1::LoadNode;
    44+#include YFM_NPL_Configuration // for NPL::Configuration, A1::NodeLoader;
    4645 #include YFM_YSLib_Service_TextFile // for Text::BOM_UTF_8, Text::CheckBOM;
    4746 #include <ystdex/string.hpp> // for ystdex::write_literal, ystdex::sfmt;
    4847 #include <cerrno> // for errno;
    @@ -410,10 +409,10 @@
    410409 yunused(disp);
    411410 if(show_info)
    412411 YTraceDe(Notice, "Found %s '%s'.", Nonnull(disp), path);
    413- // XXX: Race condition may cause failure, though file would not be
    414- // corrupted now.
    412+ // XXX: Race condition may cause failure, though file would not be corrupted
    413+ // now.
    415414 // XXX: Exception thrown here would be caught by %TryInvoke in the call to
    416- // %LoadNPLA1FileVec or %LoadNPLA1File, so there is no need to attatch the
    415+ // %LoadNPLA1FileVec or %LoadNPLA1File, so there is no need to attach the
    417416 // additional filename information here.
    418417 if(SharedInputMappedFileStream sifs{path})
    419418 {
    @@ -831,9 +830,8 @@
    831830 return make_unique<Drawing::FontCache>();
    832831 }, [](ValueNode& node, unique_ptr<Drawing::FontCache>& locked)
    833832 -> Drawing::FontCache&{
    834- InitializeSystemFontCache(*locked,
    835- AccessChild<string>(node, "FontFile"),
    836- AccessChild<string>(node, "FontDirectory"));
    833+ InitializeSystemFontCache(*locked, AccessChild<string>(node,
    834+ "FontFile"), AccessChild<string>(node, "FontDirectory"));
    837835 return *locked.get();
    838836 });
    839837 }
    @@ -846,10 +844,8 @@
    846844 }, [](ValueNode& node, MIMEBiMapping& locked) -> MIMEBiMapping&{
    847845 AddMIMEItems(locked, LoadNPLA1File("MIME database", (AccessChild<string>
    848846 (node, "DataDirectory") + "MIMEExtMap.txt").c_str(), []{
    849- NPL::Session sess{};
    850-
    851- return A1::LoadNode(
    852- SContext::Analyze(sess, sess.Process(TU_MIME)));
    847+ return
    848+ A1::NodeLoader(FetchEnvironment().Global).LoadNode(TU_MIME);
    853849 }, true));
    854850 return locked;
    855851 });
    diff -r 5acfef664815 -r 187738900a17 YFramework/source/NPL/Configuration.cpp
    --- a/YFramework/source/NPL/Configuration.cpp Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/source/NPL/Configuration.cpp Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Configuration.cpp
    1212 \ingroup NPL
    1313 \brief 配置设置。
    14-\version r981
    14+\version r1048
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 334
    1717 \par 创建时间:
    1818 2012-08-27 15:15:06 +0800
    1919 \par 修改时间:
    20- 2022-09-10 02:11 +0800
    20+ 2022-09-23 02:20 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -26,25 +26,94 @@
    2626
    2727
    2828 #include "NPL/YModules.h"
    29-#include YFM_NPL_Configuration // for PrintNode, LiteralizeEscapeNodeLiteral;
    30-#include YFM_NPL_SContext // for Session, SContext::Analyze;
    31-#include <iterator> // for std::istreambuf_iterator;
    29+#include YFM_NPL_Configuration // for ystdex::value_or, AccessPtr, string,
    30+// ystdex::quote, YSLib::AsNode, Deliteralize, PrintNode,
    31+// LiteralizeEscapeNodeLiteral;
    32+#include YFM_NPL_NPLA1Forms // for A1, Forms, RegisterStrict;
    33+#include YFM_NPL_Dependency // for LoadGroundContext;
    3234 #include <ystdex/ios.hpp> // for ystdex::rethrow_badstate,
    3335 // std::ios_base::failbit;
    3436
    3537 namespace NPL
    3638 {
    3739
    40+//! \since build 956
    41+namespace
    42+{
    43+
    44+YB_ATTR_nodiscard YB_PURE inline string
    45+ParseNPLATermName(const TermNode& term)
    46+{
    47+ if(const auto p = AccessPtr<string>(term))
    48+ return ystdex::quote(*p);
    49+ return ystdex::value_or(AccessPtr<TokenValue>(term));
    50+}
    51+
    52+YB_ATTR_nodiscard YB_PURE ValueNode
    53+TransformNode(const TermNode& term)
    54+{
    55+ auto s(term.size());
    56+ const ValueNode::allocator_type a(term.get_allocator());
    57+
    58+ if(s == 0)
    59+ return YSLib::AsNode(a, string(),
    60+ string(Deliteralize(ystdex::value_or(AccessPtr<string>(term)))));
    61+
    62+ auto i(term.begin());
    63+
    64+ if(s == 1)
    65+ return TransformNode(*i);
    66+
    67+ const auto& name(ParseNPLATermName(*i));
    68+
    69+ if(!name.empty())
    70+ yunseq(++i, --s);
    71+ if(s == 1)
    72+ {
    73+ auto&& nd(TransformNode(*i));
    74+
    75+ if(nd.GetName().empty())
    76+ return YSLib::AsNode(a, name, std::move(nd.Value));
    77+
    78+ ValueNode::Container node_con(a);
    79+
    80+ node_con.insert(std::move(nd));
    81+ return {ValueNode::Container(std::move(node_con), a), name};
    82+ }
    83+
    84+ ValueNode::Container node_con(a);
    85+
    86+ std::for_each(i, term.end(), [&](const TermNode& tm){
    87+ auto&& node(TransformNode(tm));
    88+
    89+ node_con.insert(node.GetName().empty() ? YSLib::AsNode(
    90+ node.get_allocator(), '$' + MakeIndex(node_con.size()),
    91+ std::move(node.Value)) : std::move(node));
    92+ });
    93+ return {std::allocator_arg, a, std::move(node_con), name};
    94+}
    95+
    96+} // unnamed namespace;
    97+
    3898 namespace A1
    3999 {
    40100
    101+NodeLoader::NodeLoader(const GlobalState& global)
    102+ : cs(global)
    103+{}
    104+
    41105 ValueNode
    42-LoadNode(const TermNode& tree)
    106+NodeLoader::LoadNode(const TermNode& tree) const
    43107 {
    44- TryRet(A1::TransformNode(tree))
    45- CatchThrow(bad_any_cast& e, LoggedEvent(YSLib::sfmt(
    46- "Bad NPLA1 tree found: cast failed from [%s] to [%s] .", e.from(),
    47- e.to()), YSLib::Warning))
    108+ TryRet(TransformNode(tree))
    109+ CatchThrow(bad_any_cast& e, LoggedEvent(YSLib::sfmt("Bad NPLA1 tree found:"
    110+ " cast failed from [%s] to [%s] .", e.from(), e.to()), YSLib::Warning))
    111+ catch(std::exception& e)
    112+ {
    113+ YTraceDe(YSLib::Err, "Bad NPLA1 tree found: [%s]%s",
    114+ typeid(e).name(), e.what());
    115+ throw;
    116+ }
    48117 }
    49118
    50119 } // namespace A1;
    @@ -59,13 +128,8 @@
    59128 std::istream&
    60129 operator>>(std::istream& is, Configuration& conf)
    61130 {
    62- using sb_it_t = std::istreambuf_iterator<char>;
    63- // TODO: Validate for S-expression?
    64- const auto a(conf.get_allocator());
    65- Session sess(a);
    66-
    67- TryExpr(conf.root = A1::LoadNode(SContext::Analyze(std::allocator_arg, a,
    68- sess, sess.Process(sb_it_t(is), sb_it_t{}))))
    131+ TryExpr(conf.root
    132+ = A1::NodeLoader(A1::GlobalState(conf.get_allocator())).LoadNode(is))
    69133 CatchExpr(..., ystdex::rethrow_badstate(is, std::ios_base::failbit))
    70134 return is;
    71135 }
    diff -r 5acfef664815 -r 187738900a17 YFramework/source/NPL/Dependency.cpp
    --- a/YFramework/source/NPL/Dependency.cpp Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/source/NPL/Dependency.cpp Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Dependency.cpp
    1212 \ingroup NPL
    1313 \brief 依赖管理。
    14-\version r7359
    14+\version r7396
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 623
    1717 \par 创建时间:
    1818 2015-08-09 22:14:45 +0800
    1919 \par 修改时间:
    20- 2022-09-14 01:45 +0800
    20+ 2022-09-17 23:01 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -1401,10 +1401,9 @@
    14011401 LoadStandardDerived(ContextState& cs)
    14021402 {
    14031403 #if NPL_Impl_NPLA1_Native_Forms
    1404- auto& renv(cs.GetRecordRef());
    1405-
    1406- RegisterUnary<Strict, const TokenValue>(renv, "ensigil", Ensigil);
    1407- RegisterForm(renv, "$binds1?", [](TermNode& term, ContextNode& ctx){
    1404+ // XXX: Using %cs instead of 'renv' is occasionally more efficient.
    1405+ RegisterUnary<Strict, const TokenValue>(cs, "ensigil", Ensigil);
    1406+ RegisterForm(cs, "$binds1?", [](TermNode& term, ContextNode& ctx){
    14081407 RetainN(term, 2);
    14091408
    14101409 auto i(term.begin());
    @@ -1466,13 +1465,11 @@
    14661465 void
    14671466 Load(ContextState& cs)
    14681467 {
    1469- auto& renv(cs.GetRecordRef());
    1470-
    1471-// LoadObjects(renv);
    1468+// LoadObjects(cs.GetRecordRef());
    14721469 Primitive::Load(cs);
    14731470 Derived::Load(cs);
    14741471 // NOTE: Prevent the ground environment from modification.
    1475- renv.Frozen = true;
    1472+ cs.GetRecordRef().Frozen = true;
    14761473 }
    14771474
    14781475 } // namespace Ground;
    @@ -2047,11 +2044,8 @@
    20472044 }
    20482045
    20492046 void
    2050-LoadModule_std_io(ContextState& cs,
    2051- const shared_ptr<Environment>& p_ground)
    2047+LoadModule_std_io(ContextState& cs)
    20522048 {
    2053- YAssertNonnull(p_ground);
    2054-
    20552049 auto& renv(cs.GetRecordRef());
    20562050
    20572051 RegisterUnary<Strict, const string>(renv, "readable-file?",
    @@ -2142,9 +2136,8 @@
    21422136 YAssert(false, "Invalid state found.");
    21432137 }
    21442138 ThrowInvalidSyntaxError("Syntax error in get-module.");
    2145- }, std::placeholders::_2, EnvironmentReference(p_ground)));
    2139+ }, std::placeholders::_2, cs.WeakenRecord()));
    21462140 #else
    2147- yunused(p_ground);
    21482141 cs.ShareCurrentSource("<lib:std.io-1>");
    21492142 A1::Perform(cs, R"NPL(
    21502143 $defl! get-module (&filename .&opt)
    @@ -2225,11 +2218,8 @@
    22252218 }
    22262219
    22272220 void
    2228-LoadModule_std_modules(ContextState& cs,
    2229- const shared_ptr<Environment>& p_ground)
    2221+LoadModule_std_modules(ContextState& cs)
    22302222 {
    2231- YAssertNonnull(p_ground);
    2232-
    22332223 #if NPL_Impl_NPLA1_Native_Forms
    22342224 using namespace std::placeholders;
    22352225 using YSLib::to_std_string;
    @@ -2287,14 +2277,14 @@
    22872277 ystdex::emplace_hint_in_place(registry, pr.first, req,
    22882278 std::piecewise_construct, NPL::tuple<>(),
    22892279 NPL::forward_as_tuple([&]{
    2290- return CreateEnvironmentWithParent(term.get_allocator(),
    2291- r_ground);
    2280+ return
    2281+ CreateEnvironmentWithParent(term.get_allocator(), r_ground);
    22922282 }()))->second.second);
    22932283 return ReductionStatus::Clean;
    22942284 }
    22952285 throw NPLException("Requirement '" + to_std_string(req)
    22962286 + "' is already registered.");
    2297- }, EnvironmentReference(p_ground)));
    2287+ }, cs.WeakenRecord()));
    22982288 RegisterUnary<Strict, const string>(renv, "unregister-requirement!",
    22992289 trivial_swap, [&](const string& req){
    23002290 CheckRequirement(req);
    @@ -2380,9 +2370,8 @@
    23802370 ThrowInvalidSyntaxError("Syntax error in require.");
    23812371 }
    23822372 return reduce_to_res(pr.first->second.first);
    2383- }, _2, EnvironmentReference(p_ground)));
    2373+ }, _2, cs.WeakenRecord()));
    23842374 #else
    2385- yunused(p_ground);
    23862375 context.ShareCurrentSource("<lib:std.modules>");
    23872376 // XXX: Thread-safety is not respected currently.
    23882377 context.Perform(R"NPL(
    @@ -2677,26 +2666,18 @@
    26772666 LoadStandardContext(ContextState& cs)
    26782667 {
    26792668 LoadGroundContext(cs);
    2680-
    2681- const auto pfx("std.");
    2682- string mod(pfx, cs.get_allocator());
    2683- const auto load_std_module(
    2684- [&](string_view module_name, void(&load_module)(ContextState&)){
    2685- // XXX: Using allocator of the state or %std::string are both a bit less
    2686- // efficient.
    2687- mod += module_name;
    2688- LoadModuleChecked(cs, mod, load_module, cs);
    2689- mod.resize(ystdex::string_length(pfx));
    2690- });
    2691- const auto p_ground(cs.ShareRecord());
    2692-
    2693- load_std_module("continuations", LoadModule_std_continuations),
    2694- load_std_module("promises", LoadModule_std_promises);
    2695- load_std_module("math", LoadModule_std_math),
    2696- load_std_module("strings", LoadModule_std_strings);
    2697- LoadModuleChecked(cs, "std.io", LoadModule_std_io, cs, p_ground);
    2698- load_std_module("system", LoadModule_std_system);
    2699- LoadModuleChecked(cs, "std.modules", LoadModule_std_modules, cs, p_ground);
    2669+ // XXX: A lambda-expression is OK and the generated code can be equally
    2670+ // efficient, but not succinct as using macro in the invocation sites.
    2671+#define NPL_Impl_LoadStd(_name) \
    2672+ LoadModuleChecked(cs, "std." #_name, LoadModule_std_##_name, cs)
    2673+ NPL_Impl_LoadStd(continuations),
    2674+ NPL_Impl_LoadStd(promises);
    2675+ NPL_Impl_LoadStd(math),
    2676+ NPL_Impl_LoadStd(strings);
    2677+ NPL_Impl_LoadStd(io);
    2678+ NPL_Impl_LoadStd(system);
    2679+ NPL_Impl_LoadStd(modules);
    2680+#undef NPL_Impl_LoadStd
    27002681 }
    27012682
    27022683 } // namespace Forms;
    diff -r 5acfef664815 -r 187738900a17 YFramework/source/NPL/NPLA.cpp
    --- a/YFramework/source/NPL/NPLA.cpp Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/source/NPL/NPLA.cpp Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA.cpp
    1212 \ingroup NPL
    1313 \brief NPLA 公共接口。
    14-\version r4202
    14+\version r4213
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 663
    1717 \par 创建时间:
    1818 2016-01-07 10:32:45 +0800
    1919 \par 修改时间:
    20- 2022-08-21 23:32 +0800
    20+ 2022-09-23 01:05 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -137,19 +137,6 @@
    137137 }
    138138
    139139
    140-string
    141-ParseNPLATermString(const TermNode& term)
    142-{
    143- return ystdex::value_or(AccessPtr<string>(term));
    144-}
    145-
    146-ValueNode
    147-MapNPLALeafNode(const TermNode& term)
    148-{
    149- return YSLib::AsNode(ValueNode::allocator_type(term.get_allocator()),
    150- string(), string(Deliteralize(ParseNPLATermString(term))));
    151-}
    152-
    153140 TermNode
    154141 TransformToSyntaxNode(ValueNode&& node)
    155142 {
    diff -r 5acfef664815 -r 187738900a17 YFramework/source/NPL/NPLA1.cpp
    --- a/YFramework/source/NPL/NPLA1.cpp Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/source/NPL/NPLA1.cpp Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA1.cpp
    1212 \ingroup NPL
    1313 \brief NPLA1 公共接口。
    14-\version r23927
    14+\version r23965
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 472
    1717 \par 创建时间:
    1818 2014-02-02 18:02:47 +0800
    1919 \par 修改时间:
    20- 2022-09-14 02:53 +0800
    20+ 2022-09-21 23:46 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -1930,51 +1930,6 @@
    19301930
    19311931
    19321932 void
    1933-InsertChild(ValueNode&& node, ValueNode::Container& con)
    1934-{
    1935- con.insert(node.GetName().empty() ? YSLib::AsNode(node.get_allocator(),
    1936- '$' + MakeIndex(con.size()), std::move(node.Value)) : std::move(node));
    1937-}
    1938-
    1939-ValueNode
    1940-TransformNode(const TermNode& term)
    1941-{
    1942- auto s(term.size());
    1943-
    1944- if(s == 0)
    1945- return MapNPLALeafNode(term);
    1946-
    1947- auto i(term.begin());
    1948-
    1949- if(s == 1)
    1950- return TransformNode(*i);
    1951-
    1952- const auto& name(ParseNPLATermString(*i));
    1953-
    1954- if(!name.empty())
    1955- yunseq(++i, --s);
    1956- if(s == 1)
    1957- {
    1958- auto&& nd(TransformNode(*i));
    1959-
    1960- if(nd.GetName().empty())
    1961- return YSLib::AsNode(ValueNode::allocator_type(
    1962- term.get_allocator()), name, std::move(nd.Value));
    1963- return
    1964- {ValueNode::Container({std::move(nd)}, term.get_allocator()), name};
    1965- }
    1966-
    1967- ValueNode::Container node_con;
    1968-
    1969- std::for_each(i, term.end(), [&](const TermNode& tm){
    1970- InsertChild(TransformNode(tm), node_con);
    1971- });
    1972- return
    1973- {std::allocator_arg, term.get_allocator(), std::move(node_con), name};
    1974-}
    1975-
    1976-
    1977-void
    19781933 ParseLeaf(TermNode& term, string_view id)
    19791934 {
    19801935 YAssertNonnull(id.data());
    @@ -2746,7 +2701,7 @@
    27462701 }
    27472702
    27482703
    2749-GlobalState::GlobalState(pmr::memory_resource& rsrc)
    2704+GlobalState::GlobalState(TermNode::allocator_type a)
    27502705 : GlobalState([this](const GParsedValue<ByteParser>& str){
    27512706 TermNode term(Allocator);
    27522707 const auto id(YSLib::make_string_view(str));
    @@ -2763,11 +2718,11 @@
    27632718 ParseLeafWithSourceInformation(term, id, cs.CurrentSource,
    27642719 val.first);
    27652720 return term;
    2766- }, rsrc)
    2721+ }, a)
    27672722 {}
    27682723 GlobalState::GlobalState(Tokenizer leaf_conv,
    2769- SourcedTokenizer sourced_leaf_conv, pmr::memory_resource& rsrc)
    2770- : Allocator(&rsrc), Preprocess(SeparatorPass(Allocator)),
    2724+ SourcedTokenizer sourced_leaf_conv, TermNode::allocator_type a)
    2725+ : Allocator(a), Preprocess(SeparatorPass(Allocator)),
    27712726 ConvertLeaf(std::move(leaf_conv)),
    27722727 ConvertLeafSourced(std::move(sourced_leaf_conv))
    27732728 {
    diff -r 5acfef664815 -r 187738900a17 YFramework/source/YSLib/UI/Loader.cpp
    --- a/YFramework/source/YSLib/UI/Loader.cpp Wed Sep 14 04:23:05 2022 +0800
    +++ b/YFramework/source/YSLib/UI/Loader.cpp Fri Sep 23 20:46:50 2022 +0800
    @@ -1,5 +1,5 @@
    11 /*
    2- © 2013-2016, 2018-2021 FrankHB.
    2+ © 2013-2016, 2018-2022 FrankHB.
    33
    44 This file is part of the YSLib project, and may only be used,
    55 modified, and distributed under the terms of the YSLib project
    @@ -11,13 +11,13 @@
    1111 /*! \file Loader.cpp
    1212 \ingroup UI
    1313 \brief 动态 GUI 加载。
    14-\version r383
    14+\version r395
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 433
    1717 \par 创建时间:
    1818 2013-08-01 20:39:49 +0800
    1919 \par 修改时间:
    20- 2021-12-24 23:56 +0800
    20+ 2022-09-22 23:36 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -26,11 +26,10 @@
    2626
    2727
    2828 #include "YSLib/UI/YModules.h"
    29-#include "NPL/YModules.h"
    30-#include YFM_YSLib_UI_Loader // for to_std_string, istringtream;
    29+#include YFM_YSLib_UI_Loader // for to_std_string, istringtream,
    30+// std::allocator_arg, shared_ptr;
    3131 #include <sstream> // for complete istringtream;
    32-#include YFM_YSLib_UI_YPanel
    33-#include YFM_NPL_Configuration // for NPL, Session, A1::LoadNode;
    32+#include <limits> // for std::numeric_limits;
    3433
    3534 namespace YSLib
    3635 {
    @@ -53,6 +52,7 @@
    5352 catch(std::exception& e)
    5453 {
    5554 YTraceDe(Warning, "Error: %s", e.what());
    55+ YTraceDe(Informative, "The string is: '%s'.", str.c_str());
    5656 throw std::invalid_argument("Parse 'Rect' failed: bad state.");
    5757 }
    5858 YTraceDe(Debug, "ParseRect: %s.", to_string(res).c_str());
    @@ -96,11 +96,7 @@
    9696 ValueNode
    9797 WidgetLoader::LoadUILayout(string_view sv) const
    9898 {
    99- using namespace NPL;
    100- Session sess{};
    101-
    102- return TransformUILayout(
    103- A1::LoadNode(SContext::Analyze(sess, sess.Process(sv))));
    99+ return TransformUILayout(Convert(sv));
    104100 }
    105101
    106102 ValueNode
    @@ -137,8 +133,7 @@
    137133 const auto
    138134 r(std::stoul(to_std_string(*p_z)));
    139135
    140- // TODO: Do not use magic number.
    141- if(r < 0x100)
    136+ if(r <= std::numeric_limits<ZOrder>::max())
    142137 z = r;
    143138 }
    144139 CatchIgnore(std::invalid_argument&)
    diff -r 5acfef664815 -r 187738900a17 YSTest/source/Shells.cpp
    --- a/YSTest/source/Shells.cpp Wed Sep 14 04:23:05 2022 +0800
    +++ b/YSTest/source/Shells.cpp Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Shells.cpp
    1212 \ingroup YReader
    1313 \brief Shell 框架逻辑。
    14-\version r6556
    14+\version r6565
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since 早于 build 132
    1717 \par 创建时间:
    1818 2010-03-06 21:38:16 +0800
    1919 \par 修改时间:
    20- 2022-09-14 03:06 +0800
    20+ 2022-09-23 00:37 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -25,11 +25,13 @@
    2525 */
    2626
    2727
    28-#include "Shells.h" // for std::throw_with_nested;
    28+#include "Shells.h" // for std::throw_with_nested, make_shared,
    29+// FetchEnvironment;
    2930 #include "ShlExplorer.h"
    3031 #include "ShlReader.h"
    31-#include <ytest/timing.hpp>
    32-#include YFM_NPL_Dependency // for NPL, A1::Forms::InvokeIn;
    32+#include <ytest/timing.hpp> // for ytest::timing::once;
    33+#include YFM_NPL_Configuration // for NPL::A1::NodeLoader, ystdex::trivial_swap,
    34+// std::bind, string_view, std::placeholders::_1;
    3335 #include YFM_Helper_Environment // for complete Environment;
    3436
    3537 namespace YReader
    @@ -126,7 +128,10 @@
    126128 WidgetLoader&
    127129 FetchWidgetLoader()
    128130 {
    129- static WidgetLoader wgt_ldr;
    131+ static const NPL::A1::NodeLoader loader(FetchEnvironment().Global);
    132+ static WidgetLoader wgt_ldr(decltype(WidgetLoader::Convert)(
    133+ ystdex::trivial_swap, std::bind(&NPL::A1::NodeLoader::LoadNode<
    134+ string_view>, &loader, std::placeholders::_1)));
    130135 static const struct Init
    131136 {
    132137 Init()
    diff -r 5acfef664815 -r 187738900a17 doc/ChangeLog.V0.9.txt
    --- a/doc/ChangeLog.V0.9.txt Wed Sep 14 04:23:05 2022 +0800
    +++ b/doc/ChangeLog.V0.9.txt Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file ChangeLog.V0.9.txt
    1212 \ingroup Documentation
    1313 \brief 版本更新历史记录 - V0.9 。
    14-\version r11547
    14+\version r11673
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 800
    1717 \par 创建时间:
    1818 2020-10-12 17:19:23 +0800
    1919 \par 修改时间:
    20- 2022-09-14 04:19 +0800
    20+ 2022-09-23 18:50 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -32,6 +32,133 @@
    3232
    3333 $now
    3434 (
    35+ / %YFramework $=
    36+ (
    37+ / %YSLib $=
    38+ (
    39+ / %UI.Loader $=
    40+ (
    41+ + "tracing of the string value with level %Informative after \
    42+ the warning message on failure" @ "function %ParseRect",
    43+ / @ "class %WidgetLoader" $=
    44+ (
    45+ / DLDI "avoided the use of magic number"
    46+ @ "function %TransformUILayout",
    47+ (
    48+ + "data member %Convert";
    49+ + "constructor",
    50+ / DLI "simplified function %LoadUILayout" ^ "%Convert"
    51+ ~ "%NPL"
    52+ )
    53+ ),
    54+ ),
    55+ / "parameter type 'const shared_ptr<Shell>&'" @ "function %Activate"
    56+ @ %Core.YApplication -> 'shared_ptr<Shell>'
    57+ ),
    58+ / "parameter type 'const shared_ptr<Shell>&'" @ "function %NowShellTo"
    59+ @ %Helper.ShellHelper -> 'shared_ptr<Shell>',
    60+ // As in %YSLib.Core.YApplication.
    61+ / %NPL $=
    62+ (
    63+ / %Dependency $=
    64+ (
    65+ (
    66+ / @ "functions %(LoadModule_std_io, LoadModule_std_modules)" $=
    67+ (
    68+ / DLI "simplified" !^ "2nd argument";
    69+ - $revert(b942) "2nd parameter"
    70+ );
    71+ / $forced $revert(b942) DLI
    72+ "simplified function %LoadStandardContext",
    73+ ),
    74+ / DLI "several target" @ "function %LoadGroundContext" ^ 'cs'
    75+ ~ 'renv',
    76+ // Only in a few cases it would be more efficient.
    77+ / DLDI ^ 'ynothrow' @ "applicative 'remove-file'"
    78+ @ "function %LoadModule_std_system",
    79+ - DLDI "inclusion <istream>" @ "header"
    80+ $dep_from "NPLA1 inclusion of <istream>"
    81+ ),
    82+ / %Configuration $=
    83+ (
    84+ + "class %NodeLoader";
    85+ // This is like %A1::LoadNode, except that the supported \
    86+ values are already converted by %NPL::A1::ParseLeaf, \
    87+ so both supported format of the keys and non-key leaf \
    88+ values are different. See %Documentation.YFramework.
    89+ / DLI "simplified function %operator>>" ^ "%NodeLoader",
    90+ // This is a breaking change on the key format as above.
    91+ - "function %LoadNode" $dep_from ("%FetchMIMEBiMapping"
    92+ @ %Helper.Initialization, %Yeader.Shells)
    93+ ),
    94+ / %NPLA1 $=
    95+ (
    96+ / @ "constructos %GlobalState" $=
    97+ (
    98+ + "2 overloads with allocator parameter";
    99+ / "default argument" @ "'pmr::memory_resource&' parameter"
    100+ -> ("default argument '{}'" @ "allocator parameter")
    101+ ),
    102+ * DLDI "missing inclusion <istream>" @ "header" $since b758
    103+ $dep_to "NPLA1 inclusion of <istream>",
    104+ // This was needed for %(std::istream, streambuf). It was \
    105+ fixed for %std::streambuf but not %std::istream by the \
    106+ inclusion of <iosfwd> since b901 because the complete \
    107+ type %std::istream was used since b891. This bug was \
    108+ not shown due to the inclusion of <istream> in \
    109+ %YBase.YStandardEx.String, but this should not been \
    110+ relied on.
    111+ - "functions %(TransformNode; InsertChild)"
    112+ $dep_from ("%A1::LoadNode" @ %Configuration)
    113+ ),
    114+ / @ %NPLA $=
    115+ (
    116+ + "overload %AssignWeakParent with %EnvironmentReference \
    117+ parameter",
    118+ + "2 constructor with %allocator_type parameter"
    119+ @ "class %Environment",
    120+ (
    121+ - "function %ParseNPLATermString";
    122+ - "function %MapNPLALeafNode"
    123+ $dep_from ("%TranformNode" @ %NPLA1)
    124+ )
    125+ )
    126+ ),
    127+ / %Helper $=
    128+ (
    129+ / @ "constructor %Environment" @ %Environment $=
    130+ (
    131+ / "froze the current environment after the call to \
    132+ %NPL::A1::Forms::LoadStandardContext",
    133+ / DLI "simplified"
    134+ $dep_from ("constructors %GlobalState" @ %NPL.NPLA1)
    135+ ),
    136+ / %Initialization $=
    137+ (
    138+ * DD "wrong precondition" @ "Doxygen comment"
    139+ @ "function %FetchRoot" $since b550
    140+ $= (/ "'\pre' command" -> "'exception' command"),
    141+ / @ "function %FetchMIMEBiMapping" $=
    142+ (
    143+ / "simplified"
    144+ ^ $dep_from ("%NodeLoader" @ %NPL.Configuration);
    145+ // This changes the precondition and it is not fully \
    146+ compatible to the old version. This also a \
    147+ breaking change, see %NPL::A1::NodeLoader.
    148+ + DD "'\exception' command" @ "Doxygen comment"
    149+ )
    150+ )
    151+ )
    152+ ),
    153+ / $forced DLDI "function %FetchWidgetLoader" @ %YReader.Shells
    154+ $dep_from ("constructor %WidgetLoader" @ %YFramework.UI.Loader)
    155+ ^ $dep_from ("%NodeLoader" @ %YFramework.NPL.Configuration)
    156+ // This is a breaking change as %NPL::A1::NoadLoader. See also \
    157+ %Documentation.Test.
    158+),
    159+
    160+b955
    161+(
    35162 * "missing refinement on Clang++ version" @ "#pragma directive"
    36163 @ "member function %monotonic_buffer_resource::do_allocate"
    37164 @ %YBase.YStandardEx.MemoryResource $since b948,
    diff -r 5acfef664815 -r 187738900a17 doc/NPL.txt
    --- a/doc/NPL.txt Wed Sep 14 04:23:05 2022 +0800
    +++ b/doc/NPL.txt Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPL.txt
    1212 \ingroup Documentation
    1313 \brief NPL 规范和实现规格说明。
    14-\version r29695
    14+\version r29760
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 304
    1717 \par 创建时间:
    1818 2012-04-25 10:34:20 +0800
    1919 \par 修改时间:
    20- 2022-09-14 01:23 +0800
    20+ 2022-09-23 01:05 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -340,7 +340,7 @@
    340340 无限制的特例要求指定更多的附加规则,而违反这个要求。
    341341 **原理**
    342342 在语言设计上,这类似 [RnRK] 的设计原则 G1 :
    343-G1a 对象状态(object status) :语言操作一等对象(@4.1);
    343+G1a 对象状态(object status) :语言操作一等对象(@4.1) ;
    344344 G1b 可扩展性(extensibility) :用户定义的设施能重现内建特性的能力(capability) 。
    345345 以上原则在 NPL 中略有变化。关于 G1a 的改变,详见一等实体(@4.2) 。
    346346 同 [RnRK] ,被 G1b 重现能力的特性是内建的(built-in) 。这不同于如 [RnRK] G2 指定的基本的(primitive) 特性。
    @@ -992,7 +992,7 @@
    992992 使整体设计直接违反 @1.5.2.2 ;
    993993 要求局部所有权以和全局默认机制的不一致的方式表达,造成接口抽象泄漏(@1.5.3.4)(这首先来放弃局域性(@1.5.2.4) 和需求的冲突)。
    994994 此外,即便使用时不要求区分对象的局部所有权关系,全局的分配释放机制也比局部的机制有更大的实现复杂性和约束。为实现对内部有限的资源的有效管理,局部所有权在实现中仍是必要的。
    995-在使用全局所有者如全局的垃圾回收(GC, garbage collection) 的实现中,这种必要性被隐藏在全局所有者内部实现,语言的整体设计不会更简单。
    995+在使用全局所有者如全局的垃圾回收(GC, garbage collection) 的实现中,这种必要性被隐藏在全局所有者内部实现,语言的整体设计不会更简单(@1.5.3.2) 。
    996996 使用全局所有者的资源管理假定启发式(heuristic) 策略以节约现实中无法接受的非预期性开销。这仍无法保证总是对不同的场景同样有效,以至于存在以下问题:
    997997 设计至少违反 @1.5.2.1 和 @1.5.3.2 之一;
    998998 在不引入支持用户配置策略的扩充设计时,违反 @1.5.2.1 总是无法避免的;
    @@ -1662,7 +1662,7 @@
    16621662 过程实体(@4.5.2) 决定函数表达式(@4.5.2) 关联的上下文。
    16631663 本节以外其它具体规则由派生实现定义。
    16641664 **注释**
    1665-参数化的子项可在语法上被表示为一个洞(hole) 。
    1665+参数化的子项可在(元语言的)语法上被表示为一个洞(hole) 。
    16661666
    16671667 @4.6.1 求值环境:
    16681668 求值环境(evaluation environment) 是在求值(@4.1) 时可访问的隐式上下文,提供可通过名称解析(@4.3.3) 访问的变量的绑定(@4.1) 。
    @@ -1829,6 +1829,15 @@
    18291829 但这不足以涵盖一般的形式定义;特别地,调用(@4.5.2.2) 是仅仅关于过程这类实体的互操作,而种类适合一般实体的静态类型。例如,在不考虑进一步地实现时,多变多态(@4.2.3.5.5) 的类型不需要限定过程(函数)。
    18301830 种类也可扩展到特定的计算作用的作用系统(effect system) 上,此处从略。
    18311831
    1832+@4.7.10 一等类型:
    1833+一等对象(@4.2) 的类型是一等类型(first-class type) 。
    1834+非一等类型的居留(@4.7.6) 不在乎对象语言中可表达,即对象语言中无法构造这些类型的值。
    1835+非一等类型仅用于构造其它类型(可能是一等类型)和类型检查等依赖类型的推理。
    1836+**注释**
    1837+一个典型的非一等类型的例子是 ISO C 、ISO C++ 和 .NET 等支持的类型 void 。
    1838+在语义的角度上,void 可视为依赖翻译阶段(@2.4.1) 把求值时得到 void 居留的表示替换为语义错误的单元类型,但这种居留在对象语言中始终不可取得。
    1839+若不限制翻译阶段,可通过在传递(@4.4.6.5) 时始终限制正常控制(@4.8) 的值实现类似的效果,例如不考虑类型消除时 ISO C++ 中在复制或转移构造函数始终抛出异常的类类型。
    1840+
    18321841 @4.8 程序的控制执行条件(execution condition) :
    18331842 和过程的调用(@4.5.2.2) 类似,程序的控制状态(@4.1) 决定求值使用的续延。
    18341843 更一般地,规约规则指定语言的实现决定程序行为时使用的(对程序不保证可见的)续延,这种在实现中对应的控制状态称为控制执行条件。
    @@ -2004,6 +2013,10 @@
    20042013 宿主语言实现在宿主语言的尾上下文可能支持宿主 TCO(@5.10.4.2) 而使递归调用满足嵌套调用安全,但这并不是语言提供的保证,不应在可移植的实现中依赖。
    20052014 非嵌套调用安全的情形在过程嵌套调用深度过大时,可因为宿主语言的存储资源消耗导致的宿主语言实现的未定义行为,典型地包括实现中的栈溢出(stack overflow) 。
    20062015
    2016+@5.4.3 并发访问:
    2017+当前所有 NPLA1 实现中都没有显式的并发访问控制。
    2018+一般地,为避免并发访问引起的宿主语言的未定义行为,需要通过本机实现(@5.3.4) 在外部使用不同的资源实例或附加适当的同步。
    2019+
    20072020 @5.5 一等对象类型:
    20082021 除类型映射(@5.3.1) ,NPLA 约定能作为一等对象的类型支持的抽象的类型,作为实现的做小要求的一部分。
    20092022 以下章节扩充 NPLA 的其它类型,这些类型中的一部分可能作为一等对象。
    @@ -4283,7 +4296,8 @@
    42834296
    42844297 @6.15.1 NPLA1 应用实例:
    42854298 在对象语言(@7) 外,NPLA1 的实现也被用于其它应用。
    4286-NPLA1 当前加入特定的序列化和反序列化作为配置文件,参见 NPL::Configuration 。
    4299+NPLA1 当前加入特定的序列化和反序列化作为配置文件,参见模块 NPL::Configuration :
    4300+A1::NodeLoader 加载(@1.2.4) NPLA1 翻译单元(另见 @6.1.6.3 )。
    42874301 NPLA1 的上述配置文件加入特定的匹配和初始化机制作为 YSLib::UI::Loader([Documenatation::YSLib @@6.15.9]) 在运行时读取用户界面布局和配置的脚本。
    42884302 NPLA1 用于 MIME 类型和文件名映射([Documentation::YSLib @@4.5.3]) 的实现,上述配置文件对应的外部配置格式。
    42894303 注意这些应用不直接使用 NPLA1 的语义,其中使用的 TermNode 类型中名称直接表示上下文(@4.6) 中的实体名称。
    @@ -4623,15 +4637,7 @@
    46234637 @7.5 NPLA1 节点处理 API :
    46244638 NPLA1 提供了对节点作为树形数据结构和整体处理的处理 API 。
    46254639
    4626-@7.5.1 直接节点操作:
    4627-以下 API 主要用于兼容历史实现。
    4628-A1::InsertChild 插入 NPLA1 子节点。
    4629-A1::TransformNode 变换 NPLA1 节点 S 表达式抽象语法树为 NPLA1 语义结构。
    4630-通过 ValueNode 变换实现解释,参数指定映射例程,结果是变换的序列语义结构。
    4631-复合表达式中的经过节点到字符串的映射例程被解释为序列语义结构的名称,余下的项一一映射为子节点。
    4632-A1::LoadNode 加载(@1.2.4) NPLA1 翻译单元(另见 @6.1.6.3 )。
    4633-
    4634-@7.5.2 中缀变换:
    4640+@7.5.1 中缀变换:
    46354641 NPLA1 提供符合特定谓词指定的过滤条件的中缀分隔项替换为特定名称表达式(@4.5.1) 指定的前缀操作形式的列表。
    46364642 这些中缀变换作为预处理操作,可识别和接受 NPL-GA 语法外的记号,即转换扩展的 NPL-GA 文法输入为严格的 NPL-GA 语法(@3.4.4) 要求的源语言。
    46374643 这些操作以函数对象类型 SeparatorTransformer 提供。
    @@ -4640,7 +4646,7 @@
    46404646 变换结果可被进一步规约。
    46414647 另见异步规约实现(@7.9.2) 。
    46424648
    4643-@7.5.3 叶节点分析 :
    4649+@7.5.2 叶节点分析 :
    46444650 叶节点(@6.2.1) 分析 API 作为标记器(@7.8) 的实现转换词素到包含记号的项,包括:
    46454651 函数 A1::ParseLeaf
    46464652 函数 A1::ParseLeafWithSourceInformation
    @@ -5118,7 +5124,7 @@
    51185124 类 A1::GlobalState 提供全局状态,可直接作为 REPL 原型。
    51195125 其中,数据成员 EvaluateLeaf 、EvaluateList 、EvaluateLiteral 是全局公共遍(@7.4.3) ,分别为叶遍、列表遍和字面量求值遍。
    51205126 A1::GlobalState 以 ContextNode::EvaluateList(@6.11.3.1) 为第二参数调用 A1::SetupDefaultInterpretation 初始化,之后默认解释配置 ContextNode 具有以下能在 A1::ReduceOnce(@7.4.4) 运行的规约算法:
    5121-A1::GlobalState 使用 @7.5.3 的 API 实现标记器。
    5127+A1::GlobalState 使用 @7.5.2 的 API 实现标记器。
    51225128 若项是具有一个子项的列表节点,则规约为这个子项;
    51235129 若项是具有多个子项的列表节点,依次调用 NPL::ReduceHeadEmptyList(@6.10.7.1) 、A1::ReduceFirst(@7.4.6) 和 A1::ReduceCombined(@7.6.4.2) 规约列表项;
    51245130 否则调用 A1::ReduceLeafToken(@7.6.4) 规约叶节点。
    @@ -5212,7 +5218,7 @@
    52125218 @7.9.2 异步规约 API 支持:
    52135219 部分 NPLA1 API 提供同步和异步的不同实现。一些 API 明确支持异步规约。
    52145220 启用异步规约的实现定义为实现选项(@7.1) NPL_Impl_NPLA1_Enable_Thunked 。
    5215-此外,启用分隔符中缀变换(@7.5.2) 的异步的实现定义为实现选项 NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass ,使用单独的异步实现保证嵌套调用安全(@6.1.4.1) 。
    5221+此外,启用分隔符中缀变换(@7.5.1) 的异步的实现定义为实现选项 NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass ,使用单独的异步实现保证嵌套调用安全(@6.1.4.1) 。
    52165222 NPL::NPLA1Forms(@8.1) 等同时支持同步和异步规约的 API 可基于这些 API 实现。
    52175223
    52185224 @7.9.2.1 异步规约基本支持:
    @@ -5681,7 +5687,7 @@
    56815687 当前实现显式包含保证嵌套调用安全(@5.4.2) 机制的异步调用 API 包括:
    56825688 NPL::SContext 中的递归遍历 API(@6.1.6.4) ;
    56835689 环境数据结构(@6.11.1) 的可重入 API ;
    5684-中缀变换(@7.5.2) ;
    5690+中缀变换(@7.5.1) ;
    56855691 递归绑定支持 API(@7.7.4) 。
    56865692 例外参见:
    56875693 NPLA 安全保证例外(@6.1.4) 。
    @@ -6008,23 +6014,26 @@
    60086014
    60096015 @8.5.2 对象语言加载 API
    60106016 函数 Forms::LoadGroundContext 提供 SHBuild 初始 REPL 环境(包含的上下文称为基础上下文(ground context) ),其中支持:
    6011-使用 A1::SeparatorTransformer(@7.5.2) 启用预处理的分号和逗号转换,分别为有序和无序列表求值的语法糖。
    6012-上述语法糖实现为 REPL 对象内部的无状态的预处理器求值遍,仅包含中缀变换(@7.5.2) ,不需要向环境中添加名称。
    6017+使用 A1::SeparatorTransformer(@7.5.1) 启用预处理的分号和逗号转换,分别为有序和无序列表求值的语法糖。
    6018+上述语法糖实现为 REPL 对象内部的无状态的预处理器求值遍,仅包含中缀变换(@7.5.1) ,不需要向环境中添加名称。
    60136019 变换后仍然具有 WHNF(@4.4.5.1) 形式,其中第一个子项是一个合并子右值,具有以下性质:
    60146020 对之后的子项构成的序列有序或无序列表求值;
    60156021 若存在操作数,有序求值保证最后一项是尾上下文(实现同 @8.4.9 );
    60166022 不保证是真合并子(@4.5.3.2) 。
    60176023 在对象语言中的对应接口参见 NPLA1 参考实现环境(@10) 。
    6018-模块 NPL::Dependency 还提供其它一些接口,调用函数 Forms::LoadGroundContext 初始化上下文后继续调用,初始化特定操作的环境:
    6019-函数 Forms::LoadModule_std_continuations 提供一等续延(@4.5.3.3) 相关操作(@12.1) ;
    6020-函数 Forms::LoadModule_std_promises 提供延迟求值等操作(@12.2) ;
    6021-函数 Forms::LoadModule_std_math 提供数学功能相关操作(@12.3) ;
    6022-函数 Forms::LoadModule_std_strings 提供字符串操作(@12.4) ;
    6023-函数 Forms::LoadModule_std_io 提供输入/输出操作(@12.5) ;
    6024-函数 Forms::LoadModule_std_modules 提供模块管理操作(@12.7) ;
    6025-函数 Forms::LoadModule_std_system 提供系统操作(@12.6) ;
    6026-函数 Forms::LoadModule_SHBuild 提供其它一些供 SHBuild 间接调用的操作(@13.1.1) 。
    6027-函数 Forms::LoadStandardContext 调用 Forms::LoadGroundContext 并加载基础上下文中提供的库模块(@10.2) ;另见 NPLA1 参考实现扩展环境(@12) 。
    6024+模块 NPL::Dependency 还提供其它一些函数。
    6025+调用函数 Forms::LoadGroundContext 初始化上下文后继续调用。这蕴含调用以下函数初始化特定操作的环境:
    6026+Forms::LoadModule_std_continuations 提供一等续延(@4.5.3.3) 相关操作(@12.1) ;
    6027+Forms::LoadModule_std_promises 提供延迟求值等操作(@12.2) ;
    6028+Forms::LoadModule_std_math 提供数学功能相关操作(@12.3) ;
    6029+Forms::LoadModule_std_strings 提供字符串操作(@12.4) ;
    6030+Forms::LoadModule_std_io 提供输入/输出操作(@12.5) ;
    6031+Forms::LoadModule_std_modules 提供模块管理操作(@12.7) ;
    6032+Forms::LoadModule_std_system 提供系统操作(@12.6) ;
    6033+Forms::LoadModule_SHBuild 提供其它一些供 SHBuild 间接调用的操作(@13.1.1) 。
    6034+Forms::LoadStandardContext 调用 Forms::LoadGroundContext 并加载基础上下文中提供的库模块(@10.2) ;另见 NPLA1 参考实现扩展环境(@12) 。
    6035+当前实现中,以下情形可能修改共享的资源,因此需要附加宿主实现机制以避免宿主语言的未定义行为:
    6036+Forms::LoadModule_std_modules 可修改保存在环境对象(@5.7.1) 中的共享资源。
    60286037
    60296038 @8.6 实现注记:
    60306039 本节指定当前实现的一些非公开接口性质。
    @@ -6118,7 +6127,7 @@
    61186127 **注释**
    61196128 klisp 的 equal? 直接使用自动机实现,在比较操作中没有对应的续延。NPLA1 支持互操作(@5.3) 允许相等的子对象以异步规约实现,不能使用这种方式而排除续延。
    61206129 klisp 的 $vau 不具有应保证被求值的实际参数,不需要异步调用(@6.11.3) ,没有 eval-vau-parent 对应的续延。
    6121-import-bindings 和 Forms::Provide 使用的 provide-let-return 共用部分本机实现。
    6130+import-bindings 和 Forms::Provide 使用的 provide-let-return 共用部分本机实现(@5.3.4) 。
    61226131 klisp 的 call/cc 直接捕获当前续延而不进行其它操作。控制作用(@4.1) 对续延的调用在本机函数 kcall_cont 实现,并被 apply-continuation 的本机实现调用,其中可调用本机函数 do_interception ,但没有指派具体的续延名称。
    61236132 和 klisp 不同,Forms::Call1CC 需检查一次续延调用的约束,在不修改宿主类型 A1::Continuation(@7.4.2) 时,不能单独把控制作用的实现放在调用处,而是和 Scheme 这样直接把续延具现为过程的方式,在内部的 A1::ContextHandler(@7.4.2) 中指定其实现。
    61246133 这样的实现方式在捕获时单独指定不同的特性(包括续延名称)而不是在其它位置(如应用或扩展续延)时指定信息,同时不需要修改 A1::Continuation 的实现。这些信息原则上是可选的,减少 A1::Continuation 的实现意味着减小实现开销(但 TCO 实现当前仍然无法避免类似的开销)。
    @@ -6149,7 +6158,7 @@
    61496158
    61506159 @9.1.1 外部环境(@1.2.4) :
    61516160 基于 @5.2 约定,由 @2.7.1 ,NPLA 的实现不假定存在多线程执行环境。
    6152-但是,宿主语言可支持多线程环境执行,在没有适当同步下可引起宿主语言的未定义行为(@5.4) 。
    6161+但是,宿主语言可支持多线程环境执行,可引起宿主语言的未定义行为(@5.4.3) 。
    61536162 作为 NPLA 的派生,NPLA1 对象语言程序也具有相同的性质,除非另行指定需要和外部环境交互的特定操作,不需要假定 NPLA1 引入存在多线程执行环境。
    61546163
    61556164 @9.1.2 附加元数据(extra metadata) :
    @@ -6262,7 +6271,7 @@
    62626271 <boolean> :布尔值(@4.1),即取值为 #t 或 #f 的集合,是 NPLA 类型映射(@5.3.1) 指定的用于条件判断的单一值的类型。
    62636272 推论:<boolean> 对应的宿主类型是 bool 。
    62646273 <test> :类似 <object> ,通常预期为 <boolean> ,作为条件。
    6265-和 Scheme 类似但和 Kenerl 不同,非 #t 的值在决定分支时视同 #f ,以允许在 <boolean> 外自然扩展的逻辑代数操作。
    6274+和 Scheme 类似但和 Kernel 不同,非 #t 的值在决定分支时视同 #f ,以允许在 <boolean> 外自然扩展的逻辑代数操作。
    62666275 和 Common Lisp 不同,不使用空列表(或符号 nil )代替 #f ,以避免需要特设的规则以特定的其它类型的值(如 Common Lisp 的符号 t )表示逻辑真(这在逻辑非操作中不可避免)。
    62676276 <combiner> :合并子。
    62686277 <applicative> :应用子(@4.5.3.2) 。
    @@ -6566,7 +6575,7 @@
    65666575
    65676576 @9.7.1 求值算法:
    65686577 除非另行指定,NPLA1 对象语言的求值总是使用规范求值算法(@7.8.2) 。
    6569-在 REPL(@7.8) 中输入求值算法接受的语法形式之前,求值可使用基于中缀变换(@7.5.2) 识别的 ; 和 , 分隔符,分别表示对被分隔的序列参数进行有序和无序列表求值(替换后合并子功能对应参考实现环境中函数 $sequence(@11.4.1) 和 list%(@11.3.5) 求值后的合并子)。
    6578+在 REPL(@7.8) 中输入求值算法接受的语法形式之前,求值可使用基于中缀变换(@7.5.1) 识别的 ; 和 , 分隔符,分别表示对被分隔的序列参数进行有序和无序列表求值(替换后合并子功能对应参考实现环境中函数 $sequence(@11.4.1) 和 list%(@11.3.5) 求值后的合并子)。
    65706579 其中,分隔符 , 优先组合。
    65716580 对分隔符的处理使用和组合顺序相反的两遍分别对 ; 和 , 遍历替换,实现参见 @8.5 。
    65726581 由此引起的其它语法差异参见绑定构造(@9.7.3) 。
    @@ -7623,6 +7632,16 @@
    76237632 未指定值可等于 #inert(@9.3.1.3) 或其它值,但满足忽略值时不引起可观察行为(@4.1.3) 的改变(这排除了引入 volatile 类型或非平凡析构的宿主值)。
    76247633 若操作(@10.3.1) 在 Kernel 或 klisp 中存在结果是 #inert 的对应的操作,且未指定作为函数值的结果,则返回等于 #inert 的右值。
    76257634 操作中隐式分配的和按接口约定转移所有权给操作实现的资源不存在资源泄漏(@5.6.4) 。这包括抛出异常(@9.5.2) 时,操作的实现提供基本异常安全保证(basic exception safety) 。
    7635+**原理**
    7636+#inert(@4.7) 是单元类型的值。但是,未指定值并不依赖单元类型的性质,而只是需要一种可在对象语言中判断是否为实现(如 [RnRK] 的 inert? ),而避免使用特设的规则。
    7637+取而代之,一些语言或运行时支持非一等的特设返回类型:void(@4.7.10) ,在对象语言中无法构造其值。这种特性引起一些实用上的困难而被考虑改进,替换成一等类型,如:
    7638+https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0146r1.html
    7639+https://github.com/dotnet/csharplang/discussions/1603
    7640+即便被改进,这通常只是单元类型,而不够清晰地反映未指定的意图。
    7641+未指定值蕴含的不确定性在对象语言中难以建模,因此直接作为内建的支持特性能使语言的设计更简单(@1.5.3.2) 。
    7642+未指定值的未指定性在接口意义上仍然不是一等实体,因为当前不提供如 inert? 这样的谓词(提供 inert? 也仅仅是判断值是否为 #inert 而不是任意的未指定值)。
    7643+相对 inert? ,这类谓词可能是有用的,例如元语言可能需要判断未指定性质以简化其派生实现。但这类需求和实现细节相关,且当前缺乏实例显示在对象语言中无条件提供的必要性。更重要的是,若要求提供这种谓词,限制派生实现在未指定值的类型上维持开放类型(@5.3.1) 设计。
    7644+未指定值作为内建特性时,用户也无法直接提供这类谓词的派生(而不符合可扩展性(@1.5.5.1) )。在需要这类谓词时,派生语言设计可能视具体实现需要满足的条件补充。
    76267645
    76277646 @10.9.2 操作符合性:
    76287647 除非另行指定,以下关于操作实现的行为未指定。
    @@ -7669,8 +7688,8 @@
    76697688 除操作外,特定名称的对象以变量的形式在库中初始化,直接提供具有预设目的的可编程特性。
    76707689
    76717690 @10.9.4 操作实现注记:
    7672-通过派生实现的操作不依赖非真合并子(@9.9.5) ,因此以合并子实现操作时,其中不使用分隔符(@9.7.1) ,也不需要实现在初始化(@10.1.1) 时支持中缀变换(@7.5.2) 。
    7673-但是,不同操作之间的定义可能使用分隔符。因为不需依赖 $sequence(@11.4.1) ,这种实现也更简单。
    7691+通过派生实现的操作不依赖非真合并子(@9.9.5) ,因此以合并子实现操作时,其中不使用分隔符(@9.7.1) ,也不需要实现在初始化(@10.1.1) 时支持中缀变换(@7.5.1) 。
    7692+但是,不同操作之间的定义可能使用分隔符。因为不需依赖 $sequence(@11.4.1) ,这种实现也更简单(@1.5.3.2) 。
    76747693 除非另行指定,当前实现中,操作引发错误对象(@9.5.2) 以抛出异常实现(@10.6.4) ,涉及具体的异常类型未指定。
    76757694 **注释**
    76767695 这允许引起错误处理(@10.6.4) 的使用引发错误对象的派生实现。
    @@ -7971,10 +7990,12 @@
    79717990 若省略 <alternative> 且 <test> 求值为 #f ,则结果未指定(@10.9) 。
    79727991 **注释**
    79737992 对 <test> 的处理的主要原理和 Kernel 的 $and 不要求尾上下文的表达式求值检查类型一致。
    7974-若需要检查类型避免误用,可以派生提供其它函数;相反的派生无法利用更简单的实现。
    7993+若需要检查类型避免误用,可以派生提供其它函数;相反的派生无法利用更简单(@1.5.3.2) 的实现。
    79757994 **原理**
    79767995 和 R7RS 类似,但和 Racket 及 Kernel 不同,省略 <alternative> 被支持。
    79777996 这避免用户必须引入 #inert 等具体的值实现相同隐式效果而违反关注点分离原则(@1.5.2.4) 。
    7997+必要时(如派生结果等效 #inert 的操作(@10.9.1) ),#inert 的值仍可被显式使用,但这在接口意义上通常是不必要的。
    7998+另见关于 #inert 的原理(@10.9.1) 。
    79787999 和 [RnRK] 中的相关讨论结论不同,是否省略 <alternative> 的形式应是一致的。这是因为:
    79798000 NPLA1 不假设作为基本控制操作的 $if 的作用(仅要 <consequent> 或 <alternative> 求值的结果,或仅为了副作用);
    79808001 $if 不假设用户对 <consequent> 和 <alternative> 顺序选择性偏好,以避免限制用户选择否定谓词简化 <test> ,从而支持 @1.5.2.1 。
    @@ -8960,8 +8981,10 @@
    89608981 同时保存创建的环境,以避免因程序没有保存环境引用而无效化(@9.8.6) ,使访问变量绑定的程序具有未定义行为;
    89618982 结果是加载结果(同 std.io 模块中的 load(@12.5) )而不是 #inert 。
    89628983 **注释**
    8963-当前实现依赖可用的 std.strings(@12.4) 、std.io(@12.5) 和 std.system(@12.6) 环境。
    8984+当前派生实现依赖可用的 std.strings(@12.4) 、std.io(@12.5) 和 std.system(@12.6) 环境。
    89648985 通过不经过本模块的操作、重复字符串模板的重复项、符号链接和字符串大小写不敏感的文件名等可能绕过本模块的注册机制而重复加载同一个外部文件。本模块的操作不对这些情形进行任何检查。
    8986+当前使用 Forms::LoadModule_std_modules(@8.5.2) 实现,不对并发访问进行控制。
    8987+需注意外部环境(@9.1.1) 中不受到控制的并发访问可能引起宿主语言未定义行为(@5.4.3) 。
    89658988
    89668989 @13 SHBuild 实现环境:
    89678990 SHBuild 实现环境是派生 NPLA1 参考实现扩展环境(@12) 的用于 SHBuild 和外部脚本的构建的初始环境。
    diff -r 5acfef664815 -r 187738900a17 doc/Test.txt
    --- a/doc/Test.txt Wed Sep 14 04:23:05 2022 +0800
    +++ b/doc/Test.txt Fri Sep 23 20:46:50 2022 +0800
    @@ -1,5 +1,5 @@
    11 /*
    2- © 2015-2018, 2020-2021 FrankHB.
    2+ © 2015-2018, 2020-2022 FrankHB.
    33
    44 This file is part of the YSLib project, and may only be used,
    55 modified, and distributed under the terms of the YSLib project
    @@ -11,13 +11,13 @@
    1111 /*! \file Test.txt
    1212 \ingroup Documentation
    1313 \brief 测试项目说明。
    14-\version r357
    14+\version r362
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 597
    1717 \par 创建时间:
    1818 2015-05-09 13:10:21 +0800
    1919 \par 修改时间:
    20- 2021-10-22 18:05 +0800
    20+ 2022-09-23 02:03 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -243,6 +243,11 @@
    243243 @4.1.3.7 build 885 起:
    244244 MinGW64 平台支持同上(@4.1.3.6) 。
    245245
    246+@4.1.3.8 build 956 起:
    247+支持格式变更同 [Documentation::YFramework @@5.2.10] 。
    248+**注释**
    249+书签中的路径使用字符串字面量作为键,不受变更影响。
    250+
    246251 @5 测试注记:
    247252 以下注记仅适用提交版本([Documentation::ProjectRules @@3.2.1.2]) ,对已提交的版本为测试记录,未提交的版本为测试计划。
    248253 示例测试项目 YSTest 包含 @3 和 @4 提到的测试。
    diff -r 5acfef664815 -r 187738900a17 doc/YFramework.txt
    --- a/doc/YFramework.txt Wed Sep 14 04:23:05 2022 +0800
    +++ b/doc/YFramework.txt Fri Sep 23 20:46:50 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file YFramework.txt
    1212 \ingroup Documentation
    1313 \brief YFramework 设计和实现说明。
    14-\version r1602
    14+\version r1625
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since 早于 build 132
    1717 \par 创建时间:
    1818 2009-12-02 05:14:30 +0800
    1919 \par 修改时间:
    20- 2022-07-09 12:12 +0800
    20+ 2022-09-23 11:24 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -699,6 +699,7 @@
    699699 除 @2.8.2 外,当前取得单态状态的接口包括:
    700700 FetchRoot :取值类型根节点;
    701701 FetchDefaultFontCache :取默认字体缓存。
    702+FetchMIMEBiMapping :取 MIME 数据映射。
    702703
    703704 @2.8.5 多线程同步:
    704705 特定于平台,Helper 可能提供的多线程同步接口。
    @@ -967,6 +968,17 @@
    967968 @5.2.9 build 710 起:
    968969 Linux 框架公共配置文件路径修改为以程序映像所在的目录下的 yconf.txt 的绝对路径(不再是依赖初始化时当前工作目录的相对路径)。
    969970
    971+@5.2.10 build 956 起:
    972+配置节点的叶节点的值被 NPL::ParseLeaf([Documentation::NPL @@7.5.2]) 处理,因此:
    973+ 配置的键(子节点中第一个叶节点)支持 NPLA1 代码字面量和字符串字面量,不再支持数值和其它构成字面量的词素。
    974+ 配置的非键的值(除键的叶节点)区分不同的字面量,不再支持非字符串字面量的值。
    975+以上不被支持的值在转换为内部表示时,被视为空值。
    976+对符号,空值转换为键的 "$"(兼容处理 YSLib::ValueNode([Documentation.YSLib @@3.16]) 的函数 YSLib::IsPrefixedIndex );对字符串,空值转换为空字符串。
    977+**注释**
    978+构成符号的词素仍被键支持。
    979+字符串字面量仍被非键的配置值。
    980+这不影响默认生成的配置,因为这些配置中的键都使用符号,非键的值都使用字符串字面量。
    981+
    970982 @5.3 附加配置:
    971983 附加配置是可选的。
    972984 build 654 起,Win32 平台支持环境变量 YF_DEBUG_OUTPUT 设置值为 1 时初始化默认日志记录跟踪发送到调试器。
    @@ -977,6 +989,21 @@
    977989 初始化模块 Adaptor::Image 中的 YSLib::Drawing::ImageCodec 对象。
    978990 非框架初始化的内部实现也可能使用类似框架初始化的实现(@2.8.4) 。
    979991
    992+@5.5 其它外部数据文件:
    993+其它外部数据文件可能使用类似配置文件(@5.2) 的方式访问。
    994+当外部数据文件不可用时,可使用内置的默认值。
    995+
    996+@5.5.1 build 450 起:
    997+外部文件 MIMEExtMap.txt 提供 MIME 数据。
    998+使用的格式同 yconf.txt(@5.2.2) 。
    999+**注释**
    1000+解析 MIME 数据的函数 FetchMIMEBiMapping 在初始化模块(@2.8.4) 一并提供,但当前这不依赖框架初始化。
    1001+
    1002+@5.5.2 build 956 起:
    1003+外部文件 MIMEExtMap.txt 支持格式变更同 @5.2.10 。
    1004+**注释**
    1005+解析 MIME 数据的函数 FetchMIMEBiMapping 依赖框架初始化。
    1006+
    9801007 */
    9811008 ////
    9821009
    Show on old repository browser