• R/O
  • SSH

YSLib: Commit

The YSLib project - main repository


Commit MetaInfo

Revisión04558a9cb7d4cc720b03835c35dfcdb0fcfd4122 (tree)
Tiempo2022-11-28 13:55:23
AutorFrankHB <frankhb1989@gmai...>
CommiterFrankHB

Log Message

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

Cambiar Resumen

    Diferencia incremental

    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YBase/include/ystdex/cache.hpp
    --- a/YBase/include/ystdex/cache.hpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YBase/include/ystdex/cache.hpp Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file cache.hpp
    1212 \ingroup YStandardEx
    1313 \brief 高速缓冲容器模板。
    14-\version r748
    14+\version r751
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 521
    1717 \par 创建时间:
    1818 2013-12-22 20:19:14 +0800
    1919 \par 修改时间:
    20- 2022-03-22 18:11 +0800
    20+ 2022-11-21 07:14 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -33,7 +33,7 @@
    3333 // std::get, std::piecewise_construct, enable_if_t, head_of_t;
    3434 #include <list> // for std::list;
    3535 #include "scope_guard.hpp" // for std::hash, optional_function, std::ref,
    36-// ystdex::unique_guard, ystdex::dismiss;
    36+// ystdex::make_unique_guard, ystdex::dismiss;
    3737 #include <unordered_map> // for std::unordered_map;
    3838 #include <map> // for std::map;
    3939 #include "container.hpp" // for ystdex::begin, ystdex::cbegin,
    @@ -320,7 +320,7 @@
    320320 check_max_used();
    321321
    322322 const auto i(used_list.emplace(yforward(args)...));
    323- auto gd(ystdex::unique_guard([&]() ynothrowv{
    323+ auto gd(ystdex::make_unique_guard([&]() ynothrowv{
    324324 used_list.undo_emplace();
    325325 }));
    326326 const auto pr(used_cache.emplace(i->first, i));
    @@ -344,7 +344,7 @@
    344344 const auto pr(ystdex::search_map_by(
    345345 [&](typename used_cache_type::const_iterator j){
    346346 const auto i(used_list.emplace(yforward(args)...));
    347- auto gd(ystdex::unique_guard([&]() ynothrowv{
    347+ auto gd(ystdex::make_unique_guard([&]() ynothrowv{
    348348 used_list.undo_emplace();
    349349 }));
    350350 const auto r(used_cache.emplace_hint(j, k, i));
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YBase/include/ystdex/scope_guard.hpp
    --- a/YBase/include/ystdex/scope_guard.hpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YBase/include/ystdex/scope_guard.hpp Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file scope_guard.hpp
    1212 \ingroup YStandardEx
    1313 \brief 作用域守卫。
    14-\version r615
    14+\version r655
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 588
    1717 \par 创建时间:
    1818 2015-03-29 00:54:19 +0800
    1919 \par 修改时间:
    20- 2022-02-26 22:50 +0800
    20+ 2022-11-21 08:11 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -40,6 +40,7 @@
    4040 {
    4141
    4242 /*!
    43+\ingroup guards
    4344 \brief 作用域守卫:析构时调用保存的函数对象或引用。
    4445 \note 不可复制,不提供其它状态。
    4546 \since build 605
    @@ -70,21 +71,21 @@
    7071 //@{
    7172 //! \brief 创建作用域守卫。
    7273 //@{
    73-//! \since build 649
    74-template<typename _type, bool _bNoThrow = true, typename... _tParams>
    75-guard<_type>
    76-make_guard(_tParams&&... args) ynoexcept_spec(guard<_type, _bNoThrow>(
    77- guard<_type, _bNoThrow>(yforward(args)...)))
    74+//! \since build 961
    75+template<typename _func, bool _bNoThrow = true, typename... _tParams>
    76+YB_ATTR_nodiscard inline guard<_func, _bNoThrow>
    77+make_guard(_tParams&&... args) ynoexcept_spec(guard<_func, _bNoThrow>(
    78+ guard<_func, _bNoThrow>(yforward(args)...)))
    7879 {
    79- return guard<_type, _bNoThrow>(yforward(args)...);
    80+ return guard<_func, _bNoThrow>(yforward(args)...);
    8081 }
    81-//! \since build 606
    82-template<bool _bNoThrow = true, typename _type>
    83-guard<_type>
    84-make_guard(_type f)
    85- ynoexcept_spec(guard<_type, _bNoThrow>(guard<_type, _bNoThrow>(f)))
    82+//! \since build 961
    83+template<bool _bNoThrow = true, typename _func>
    84+YB_ATTR_nodiscard inline guard<_func, _bNoThrow>
    85+make_guard(_func f)
    86+ ynoexcept_spec(guard<_func, _bNoThrow>(guard<_func, _bNoThrow>(f)))
    8687 {
    87- return guard<_type, _bNoThrow>(f);
    88+ return guard<_func, _bNoThrow>(f);
    8889 }
    8990 //@}
    9091
    @@ -95,29 +96,37 @@
    9596 {};
    9697 //@}
    9798
    98-//! \since build 820
    99+//! \since build 961
    99100 //@{
    100-template<typename _tState = bool, bool _bNoThrow = true, typename _func>
    101-guard<one_shot<decay_t<_func>, void, decay_t<_tState>>, _bNoThrow>
    102-unique_guard(_func&& f, _tState&& s = true) ynoexcept_spec(
    103- guard<one_shot<decay_t<_func>, void, decay_t<_tState>>, _bNoThrow>(
    104- guard<one_shot<decay_t<_func>, void, decay_t<_tState>>,
    105- _bNoThrow>(yforward(f), yforward(s))))
    101+template<typename _func, typename _tCond = bool, bool _bNoThrow = true>
    102+using unique_guard
    103+ = guard<one_shot<decay_t<_func>, void, decay_t<_tCond>>, _bNoThrow>;
    104+
    105+template<typename _type, typename _func, typename _tCond = bool,
    106+ bool _bNoThrow = true>
    107+using unique_state_guard
    108+ = guard<one_shot<decay_t<_func>, _type, decay_t<_tCond>>, _bNoThrow>;
    109+
    110+//! \relates unique_guard
    111+template<typename _tCond = bool, bool _bNoThrow = true, typename _func>
    112+YB_ATTR_nodiscard inline unique_guard<_func, _tCond, _bNoThrow>
    113+make_unique_guard(_func&& f, _tCond&& cond = true)
    114+ ynoexcept_spec(unique_guard<_func, _tCond, _bNoThrow>(
    115+ unique_guard<_func, _tCond, _bNoThrow>(yforward(f), yforward(cond))))
    106116 {
    107- return guard<one_shot<decay_t<_func>, void, decay_t<_tState>>, _bNoThrow>(
    108- yforward(f), yforward(s));
    117+ return unique_guard<_func, _tCond, _bNoThrow>(yforward(f), yforward(cond));
    109118 }
    110119
    111-template<typename _tRes, typename _tState = bool, bool _bNoThrow = true,
    120+//! \relates unique_state_guard
    121+template<typename _type, typename _tCond = bool, bool _bNoThrow = true,
    112122 typename _func>
    113-guard<one_shot<_func, _tRes, decay_t<_tState>>, _bNoThrow>
    114-unique_state_guard(_func&& f, _tRes r = {}, _tState&& s = true) ynoexcept_spec(
    115- guard<one_shot<decay_t<_func>, _tRes, decay_t<_tState>>, _bNoThrow>(
    116- guard<one_shot<decay_t<_func>, _tRes, decay_t<_tState>>, _bNoThrow>(
    117- yforward(f), r, s)))
    123+YB_ATTR_nodiscard inline unique_state_guard<_type, _func, _tCond, _bNoThrow>
    124+make_unique_state_guard(_func&& f, _type r = {}, _tCond&& cond = true)
    125+ ynoexcept_spec(unique_state_guard<_type, _func, _tCond, _bNoThrow>(
    126+ unique_state_guard<_type, _func, _tCond, _bNoThrow>(yforward(f), r, cond)))
    118127 {
    119- return guard<one_shot<decay_t<_func>, _tRes, decay_t<_tState>>, _bNoThrow>(
    120- yforward(f), r, yforward(s));
    128+ return unique_state_guard<_type, _func, _tCond, _bNoThrow>(yforward(f), r,
    129+ yforward(cond));
    121130 }
    122131 //@}
    123132
    @@ -267,6 +276,7 @@
    267276 } // namespace details;
    268277
    269278 /*!
    279+\ingroup guards
    270280 \brief 使用临时状态暂存对象的作用域守卫。
    271281 \since build 569
    272282 \warning 非虚析构。
    @@ -387,6 +397,7 @@
    387397
    388398
    389399 /*!
    400+\ingroup guards
    390401 \brief 使用 ystdex::vswap 调用暂存对象的作用域守卫。
    391402 \since build 569
    392403 \todo 支持分配器。
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YBase/include/ystdex/type_pun.hpp
    --- a/YBase/include/ystdex/type_pun.hpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YBase/include/ystdex/type_pun.hpp Mon Nov 28 12:55:23 2022 +0800
    @@ -1,5 +1,5 @@
    11 /*
    2- © 2014-2016, 2018, 2021 FrankHB.
    2+ © 2014-2016, 2018, 2021-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 type_pun.hpp
    1212 \ingroup YStandardEx
    1313 \brief 共享存储和直接转换。
    14-\version r578
    14+\version r583
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 629
    1717 \par 创建时间:
    1818 2015-09-04 12:16:27 +0800
    1919 \par 修改时间:
    20- 2021-11-22 04:03 +0800
    20+ 2022-11-21 05:57 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -268,7 +268,10 @@
    268268
    269269 //! \since build 716
    270270 //@{
    271-//! \brief 避免严格别名分析限制的缓冲独占所有权指针。
    271+/*!
    272+\ingroup guards
    273+\brief 避免严格别名分析限制的缓冲独占所有权指针。
    274+*/
    272275 template<typename _type>
    273276 using pun_ptr = placement_ptr<decay_t<_type>>;
    274277
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YBase/source/ystdex/memory_resource.cpp
    --- a/YBase/source/ystdex/memory_resource.cpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YBase/source/ystdex/memory_resource.cpp Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file memory_resource.cpp
    1212 \ingroup YStandardEx
    1313 \brief 存储资源。
    14-\version r1844
    14+\version r1859
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 842
    1717 \par 创建时间:
    1818 2018-10-27 19:30:12 +0800
    1919 \par 修改时间:
    20- 2022-09-05 22:07 +0800
    20+ 2022-11-21 07:14 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -35,7 +35,7 @@
    3535 # include <atomic> // for std::atomic;
    3636 #endif
    3737 #include "ystdex/pointer.hpp" // for tidy_ptr;
    38-#include "ystdex/scope_guard.hpp" // for unique_guard, ystdex::dismiss;
    38+#include "ystdex/scope_guard.hpp" // for make_unique_guard, ystdex::dismiss;
    3939 #include "ystdex/algorithm.hpp" // for std::min, std::max,
    4040 // ystdex::lower_bound_n;
    4141
    @@ -266,12 +266,9 @@
    266266 #else
    267267 if(alignment > 1)
    268268 {
    269- // TODO: Record 'sizeof' value for debugging?
    270- // TODO: Provide as an additonal %::operator new with extended alignment?
    271- // NOTE: The checks are necessary to prevent wrapping of the
    272- // results of '+'. See also
    273- // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19351.
    274- if(bytes + alignment > bytes)
    269+ // NOTE: The checks are necessary to prevent wrapping of the results of
    270+ // '+'. See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19351.
    271+ if(YB_LIKELY(bytes + alignment > bytes))
    275272 {
    276273 auto space(offset_n_t::value + bytes + alignment);
    277274
    @@ -303,12 +300,11 @@
    303300 }
    304301 }
    305302 }
    306- // NOTE: If the wrapping checks fail or there is not suitable
    307- // aligned storage available, the allocation fails. No
    308- // exception matching %std::bad_array_new_length is thrown even
    309- // it is caused by the wrapping failure, since it is never
    310- // thrown in an allocation function in the default case
    311- // specified by ISO C++.
    303+ // NOTE: If the wrapping checks fail or there is no suitable aligned
    304+ // storage available, the allocation fails. No exception matching
    305+ // %std::bad_array_new_length is thrown even it is caused by the
    306+ // wrapping failure, since it is never thrown in an allocation function
    307+ // in the default case specified by ISO C++.
    312308 throw std::bad_alloc();
    313309 }
    314310 return ::operator new(bytes);
    @@ -369,7 +365,6 @@
    369365 static_assert(is_power_of_2_positive(largest_required_pool_block_limit),
    370366 "Invalid limit value found.");
    371367
    372- // TODO: Add and use interval arithmetic library calls.
    373368 if(opts.max_blocks_per_chunk - 1 >= max_blocks_per_chunk_limit)
    374369 opts.max_blocks_per_chunk = max_blocks_per_chunk_limit;
    375370 if(opts.largest_required_pool_block - 1
    @@ -396,7 +391,7 @@
    396391 {
    397392 auto& upstream_ref(upstream());
    398393 const auto p(upstream_ref.allocate(bytes, alignment));
    399- auto gd(unique_guard([&]() ynothrow{
    394+ auto gd(make_unique_guard([&]() ynothrow{
    400395 upstream_ref.deallocate(p, bytes, alignment);
    401396 }));
    402397
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/Win32/source/YCLib/MinGW32.cpp
    --- a/YFramework/Win32/source/YCLib/MinGW32.cpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/Win32/source/YCLib/MinGW32.cpp Mon Nov 28 12:55:23 2022 +0800
    @@ -12,13 +12,13 @@
    1212 \ingroup YCLib
    1313 \ingroup Win32
    1414 \brief YCLib MinGW32 平台公共扩展。
    15-\version r2481
    15+\version r2483
    1616 \author FrankHB <frankhb1989@gmail.com>
    1717 \since build 427
    1818 \par 创建时间:
    1919 2013-07-10 15:35:19 +0800
    2020 \par 修改时间:
    21- 2022-11-05 20:53 +0800
    21+ 2022-11-21 07:14 +0800
    2222 \par 文本编码:
    2323 UTF-8
    2424 \par 模块名称:
    @@ -51,7 +51,7 @@
    5151 # include YFM_Win32_YCLib_NLS // for WCSToUTF8;
    5252 # include <ystdex/cache.hpp> // for ystdex::cache_lookup;
    5353 # include <ystdex/container.hpp> // for ystdex::retry_for_vector;
    54-# include <ystdex/scope_guard.hpp> // for ystdex::unique_guard,
    54+# include <ystdex/scope_guard.hpp> // for ystdex::make_unique_guard,
    5555 // ystdex::dismiss, std::bind, std::placeholders::_1;
    5656 # include <ystdex/swap.hpp> // for ystdex::exchange;
    5757
    @@ -490,7 +490,7 @@
    490490
    491491 name.remove_suffix(1);
    492492 TryInvoke([&]{
    493- auto gd(ystdex::unique_guard([&]() ynothrow{
    493+ auto gd(ystdex::make_unique_guard([&]() ynothrow{
    494494 res |= NodeCategory::Invalid;
    495495 }));
    496496
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/include/CHRLib/CharacterProcessing.h
    --- a/YFramework/include/CHRLib/CharacterProcessing.h Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/include/CHRLib/CharacterProcessing.h Mon Nov 28 12:55:23 2022 +0800
    @@ -1,5 +1,5 @@
    11 /*
    2- © 2009-2015, 2018-2019, 2021 FrankHB.
    2+ © 2009-2015, 2018-2019, 2021-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 CharacterProcessing.h
    1212 \ingroup CHRLib
    1313 \brief 字符编码处理。
    14-\version r2416
    14+\version r2420
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 565
    1717 \par 创建时间:
    1818 2009-11-17 17:52:35 +0800
    1919 \par 修改时间:
    20- 2021-12-27 03:15 +0800
    20+ 2022-11-21 05:58 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -32,8 +32,9 @@
    3232 #include YFM_CHRLib_CharacterMapping
    3333 #include <ystdex/cstring.h> // for ystdex::uchar_t;
    3434 #include <ystdex/string.hpp> // for ystdex::is_null, ystdex::ntctslen,
    35-// ystdex::string_traits, std::allocator_arg_t,
    36-// ystdex::make_obj_using_allocator, std::basic_string, std::allocator_arg;
    35+// ystdex::string_traits, std::basic_string;
    36+#include <ystdex/allocator.hpp> // for std::allocator_arg_t,
    37+// ystdex::make_obj_using_allocator, std::allocator_arg;
    3738 #include <cstdio> // for std::FILE;
    3839 #include <memory> // for std::move;
    3940
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/include/NPL/Dependency.h
    --- a/YFramework/include/NPL/Dependency.h Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/include/NPL/Dependency.h Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Dependency.h
    1212 \ingroup NPL
    1313 \brief 依赖管理。
    14-\version r646
    14+\version r647
    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-22 20:16 +0800
    20+ 2022-11-28 05:09 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -121,6 +121,7 @@
    121121
    122122 /*!
    123123 \note 支持的具体语法形式参考 Documentation::NPL 。
    124+\pre 间接断言:加载的目标环境未被冻结。
    124125 \since build 955
    125126 */
    126127 //@{
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/include/NPL/NPLA.h
    --- a/YFramework/include/NPL/NPLA.h Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/include/NPL/NPLA.h Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA.h
    1212 \ingroup NPL
    1313 \brief NPLA 公共接口。
    14-\version r10114
    14+\version r10228
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 663
    1717 \par 创建时间:
    1818 2016-01-07 10:32:34 +0800
    1919 \par 修改时间:
    20- 2022-11-21 03:32 +0800
    20+ 2022-11-28 05:13 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -51,7 +51,8 @@
    5151 // NPL::AsTermNode, ystdex::is_bitwise_swappable;
    5252 #include <ystdex/base.h> // for ystdex::derived_entity;
    5353 #include <ystdex/type_op.hpp> // for ystdex::exclude_self_params_t;
    54-#include <ystdex/container.hpp> // for ystdex::insert_or_assign;
    54+#include <ystdex/container.hpp> // for ystdex::insert_or_assign,
    55+// ystdex::erase_first;
    5556 #include <libdefect/exception.h> // for std::exception_ptr;
    5657
    5758 namespace NPL
    @@ -2147,6 +2148,37 @@
    21472148 */
    21482149 using EnvironmentList = vector<ValueObject>;
    21492150
    2151+/*!
    2152+\brief 绑定映射。
    2153+\since build 788
    2154+*/
    2155+using BindingMap = YSLib::map<string, TermNode, ystdex::less<>>;
    2156+
    2157+/*!
    2158+\brief 名称解析结果。
    2159+\since build 821
    2160+
    2161+名称解析结果可以是:
    2162+环境中的绑定目标的非空对象指针和直接保存绑定目标的环境的引用;
    2163+表示没有找到指定变量的空指针和未指定的环境引用的值。
    2164+*/
    2165+using NameResolution
    2166+ = pair<observer_ptr<BindingMap::mapped_type>, shared_ptr<Environment>>;
    2167+
    2168+
    2169+/*!
    2170+\brief 查找名称。
    2171+\return 查找到的名称,或查找失败时的空值。
    2172+\since build 961
    2173+
    2174+在绑定列表中查找名称。
    2175+*/
    2176+YB_ATTR_nodiscard YB_PURE inline PDefH(NameResolution::first_type, LookupName,
    2177+ BindingMap& m, string_view id)
    2178+ ImplRet(YAssertNonnull(id.data()), make_observer(ystdex::call_value_or<
    2179+ BindingMap::mapped_type*>(ystdex::compose(ystdex::addrof<>(),
    2180+ ystdex::second_of<>()), m.find(id), {}, m.cend())))
    2181+
    21502182
    21512183 /*!
    21522184 \brief 环境。
    @@ -2158,18 +2190,6 @@
    21582190 private ystdex::equality_comparable<Environment>
    21592191 {
    21602192 public:
    2161- //! \since build 788
    2162- using BindingMap = YSLib::map<string, TermNode, ystdex::less<>>;
    2163- /*!
    2164- \brief 名称解析结果。
    2165- \since build 821
    2166-
    2167- 名称解析结果可以是:
    2168- 环境中的绑定目标的非空对象指针和直接保存绑定目标的环境的引用;
    2169- 表示没有找到指定变量的空指针和未指定的环境引用的值。
    2170- */
    2171- using NameResolution
    2172- = pair<observer_ptr<BindingMap::mapped_type>, shared_ptr<Environment>>;
    21732193 /*!
    21742194 \brief 绑定映射对象使用的分配器类型。
    21752195 \note 支持 uses-allocator 构造。
    @@ -2322,22 +2342,37 @@
    23222342 DefGetter(const ynothrow, const BindingMap&, Map, bindings)
    23232343 /*!
    23242344 \brief 取可变名称绑定映射。
    2345+ \throw TypeError 环境被冻结。
    2346+ \since build 961
    2347+ */
    2348+ YB_ATTR_nodiscard YB_PURE BindingMap&
    2349+ GetMapCheckedRef();
    2350+ /*!
    2351+ \brief 取可变名称绑定映射。
    2352+ \pre 断言:环境未被冻结。
    2353+ \since build 961
    2354+ */
    2355+ DefGetter(ynothrowv, BindingMap&, MapRef,
    2356+ YAssert(!IsFrozen(), "Frozen environment found."), bindings)
    2357+ /*!
    2358+ \brief 取可变名称绑定映射。
    23252359 \warning 不检查冻结状态。
    2360+ \since build 961
    23262361 */
    2327- DefGetter(ynothrow, BindingMap&, MapRef, bindings)
    2362+ DefGetter(ynothrow, BindingMap&, MapUncheckedRef, bindings)
    23282363 //@}
    23292364
    23302365 /*!
    2331- \brief 添加或覆盖绑定。
    2332- \since build 857
    2366+ \brief 在第一参数添加或覆盖绑定。
    2367+ \since build 961
    23332368 */
    23342369 template<typename _tKey, class _tNode>
    2335- TermNode&
    2336- Bind(_tKey&& k, _tNode&& tm)
    2370+ static TermNode&
    2371+ Bind(BindingMap& m, _tKey&& k, _tNode&& tm)
    23372372 {
    2338- // XXX: %YSLib::map::insert_or_assign does not allows keys not of
    2373+ // XXX: %BindingMap::insert_or_assign does not allows keys not of
    23392374 // %BindingMap::key_type to be directly forwarded.
    2340- return NPL::Deref(ystdex::insert_or_assign(GetMapRef(), yforward(k),
    2375+ return NPL::Deref(ystdex::insert_or_assign(m, yforward(k),
    23412376 yforward(tm)).first).second;
    23422377 }
    23432378
    @@ -2412,16 +2447,6 @@
    24122447
    24132448 public:
    24142449 /*!
    2415- \brief 查找名称。
    2416- \return 查找到的名称,或查找失败时的空值。
    2417- \since build 852
    2418-
    2419- 在环境中查找名称。
    2420- */
    2421- YB_ATTR_nodiscard YB_PURE NameResolution::first_type
    2422- LookupName(string_view) const;
    2423-
    2424- /*!
    24252450 \brief 根据当前状态创建指定项的引用。
    24262451 \note 项通常表示当前环境对象所有的被绑定对象。
    24272452 \since build 906
    @@ -2433,37 +2458,39 @@
    24332458 /*!
    24342459 \pre 断言:第一参数的数据指针非空。
    24352460 \warning 应避免对被替换或移除的值的悬空引用。
    2436- \since build 867
    2461+ \since build 961
    24372462 */
    24382463 //@{
    24392464 /*!
    24402465 \brief 以字符串为标识符在指定上下文移除定义。
    24412466 \return 是否成功移除。
    24422467 */
    2443- bool
    2444- Remove(string_view);
    2468+ static PDefH(bool, Remove, BindingMap& m, string_view id)
    2469+ ImplRet(YAssertNonnull(id.data()),
    2470+ // XXX: %BindingMap does not have transparent key %erase. This is
    2471+ // like %std::set.
    2472+ ystdex::erase_first(m, id))
    24452473 /*!
    24462474 \brief 以字符串为标识符在指定上下文移除定义并检查是否成功。
    24472475 \throw BadIdentifier 定义不存在。
    24482476 */
    2449- void
    2450- RemoveChecked(string_view);
    2477+ static void
    2478+ RemoveChecked(BindingMap&, string_view);
    24512479
    24522480 /*!
    24532481 \brief 以字符串为标识符在指定上下文的名称查找结果中替换定义。
    24542482 \note 若定义不存在则忽略。
    24552483 \return 是否成功替换。
    2456- \since build 899
    24572484 */
    2458- bool
    2459- Replace(string_view, ValueObject&&);
    2485+ static bool
    2486+ Replace(BindingMap&, string_view, ValueObject&&);
    24602487
    24612488 /*!
    24622489 \brief 以字符串为标识符在指定上下文的名称查找结果中替换已存在的定义。
    24632490 \throw BadIdentifier 定义不存在。
    24642491 */
    2465- void
    2466- ReplaceChecked(string_view, ValueObject&&);
    2492+ static void
    2493+ ReplaceChecked(BindingMap&, string_view, ValueObject&&);
    24672494 //@}
    24682495
    24692496 /*!
    @@ -2750,7 +2777,7 @@
    27502777 此后,名称解析最终应失败或不终止。
    27512778 若使用被解析的对象的循环引用,可在对象语言中引起未定义行为。
    27522779 */
    2753- function<Environment::NameResolution(shared_ptr<Environment>, string_view)>
    2780+ function<NameResolution(shared_ptr<Environment>, string_view)>
    27542781 Resolve{DefaultResolve};
    27552782
    27562783 private:
    @@ -2956,7 +2983,7 @@
    29562983 对列表,使用 DFS(深度优先搜索)依次递归检查其元素。
    29572984 循环重定向不终止。
    29582985 */
    2959- YB_ATTR_nodiscard static Environment::NameResolution
    2986+ YB_ATTR_nodiscard static NameResolution
    29602987 DefaultResolve(shared_ptr<Environment>, string_view);
    29612988
    29622989 /*!
    @@ -3110,7 +3137,7 @@
    31103137
    31113138 /*!
    31123139 \brief 切换环境。
    3113- \since build 872
    3140+ \since build 961
    31143141 */
    31153142 //@{
    31163143 /*!
    @@ -3118,12 +3145,13 @@
    31183145 \sa SwitchEnvironmentUnchecked
    31193146 */
    31203147 shared_ptr<Environment>
    3121- SwitchEnvironment(const shared_ptr<Environment>&);
    3148+ SwitchEnvironment(shared_ptr<Environment>);
    31223149
    31233150 //! \pre 断言:参数指针非空。
    31243151 PDefH(shared_ptr<Environment>, SwitchEnvironmentUnchecked,
    3125- const shared_ptr<Environment>& p_env) ynothrowv
    3126- ImplRet(YAssertNonnull(p_env), ystdex::exchange(p_record, p_env))
    3152+ shared_ptr<Environment> p_env) ynothrowv
    3153+ ImplRet(YAssertNonnull(p_env),
    3154+ ystdex::exchange(p_record, std::move(p_env)))
    31273155 //@}
    31283156
    31293157 //! \since build 894
    @@ -3201,7 +3229,7 @@
    32013229 */
    32023230 //@{
    32033231 YB_ATTR_nodiscard YB_PURE inline PDefH(Environment::allocator_type,
    3204- ToBindingsAllocator, const Environment::BindingMap& m) ynothrow
    3232+ ToBindingsAllocator, const BindingMap& m) ynothrow
    32053233 ImplRet(m.get_allocator())
    32063234 YB_ATTR_nodiscard YB_PURE inline PDefH(Environment::allocator_type,
    32073235 ToBindingsAllocator, const Environment& env) ynothrow
    @@ -3271,14 +3299,14 @@
    32713299 \since build 838
    32723300
    32733301 设置被绑定对象的值数据成员并清空子项。
    3274-可访问 Environment::GetMapRef() 、Environment
    3302+可访问 Environment::GetMapCheckedRef() 、Environment
    32753303 或 ContextNode 类型中指定名称的绑定。
    32763304 因为直接替换被绑定对象,不需要检查目标是否和 TermNode 的正规表示一致。
    32773305 */
    32783306 //@{
    32793307 template<typename _type, typename... _tParams>
    32803308 inline bool
    3281-EmplaceLeaf(Environment::BindingMap& m, string_view name, _tParams&&... args)
    3309+EmplaceLeaf(BindingMap& m, string_view name, _tParams&&... args)
    32823310 {
    32833311 YAssertNonnull(name.data());
    32843312 // XXX: The implementation is depended on the fact that %TermNode is simply
    @@ -3296,8 +3324,7 @@
    32963324 //! \since build 927
    32973325 template<typename _type, typename... _tParams>
    32983326 inline bool
    3299-EmplaceLeaf(Environment::BindingMap& m, string_view name,
    3300- trivial_swap_t, _tParams&&... args)
    3327+EmplaceLeaf(BindingMap& m, string_view name, trivial_swap_t, _tParams&&... args)
    33013328 {
    33023329 YAssertNonnull(name.data());
    33033330 return ystdex::insert_or_assign(m, name, NPL::AsTermNode(m.get_allocator(),
    @@ -3307,7 +3334,8 @@
    33073334 inline bool
    33083335 EmplaceLeaf(Environment& env, string_view name, _tParams&&... args)
    33093336 {
    3310- return NPL::EmplaceLeaf<_type>(env.GetMapRef(), name, yforward(args)...);
    3337+ return NPL::EmplaceLeaf<_type>(env.GetMapCheckedRef(), name,
    3338+ yforward(args)...);
    33113339 }
    33123340 template<typename _type, typename... _tParams>
    33133341 inline bool
    @@ -3328,7 +3356,7 @@
    33283356 解析指定上下文的当前环境中的名称。
    33293357 解析名称以当前当前环境作为参数调用上下文的 ContextNode::Resolve 实现。
    33303358 */
    3331-YB_ATTR_nodiscard inline PDefH(Environment::NameResolution, ResolveName,
    3359+YB_ATTR_nodiscard inline PDefH(NameResolution, ResolveName,
    33323360 const ContextNode& ctx, string_view id)
    33333361 ImplRet(YAssertNonnull(id.data()), ctx.Resolve(ctx.GetRecordPtr(), id))
    33343362
    @@ -3447,11 +3475,12 @@
    34473475
    34483476 /*!
    34493477 \brief 环境切换器。
    3478+\ingroup functors
    34503479 \warning 非虚析构。
    34513480 \sa Environment::SwitchEnvironmentUnchecked
    34523481 \since build 821
    34533482
    3454-类 NPL::EnvironmentSwitcher 用于保存切换上下文的当前环境的结果。
    3483+用于保存切换上下文的当前环境的结果的仿函数。
    34553484 配合作用域守卫可用于以异常中立的方式恢复被切换的环境。
    34563485 */
    34573486 struct EnvironmentSwitcher
    @@ -3460,8 +3489,9 @@
    34603489 lref<ContextNode> Context;
    34613490 mutable shared_ptr<Environment> SavedPtr;
    34623491
    3463- //! \since build 911
    3492+ //! \since build 961
    34643493 EnvironmentSwitcher(ContextNode& ctx, shared_ptr<Environment> p_saved = {})
    3494+ ynothrow
    34653495 : Context(ctx), SavedPtr(std::move(p_saved))
    34663496 {}
    34673497 DefDeMoveCtor(EnvironmentSwitcher)
    @@ -3474,6 +3504,23 @@
    34743504 if(SavedPtr)
    34753505 Context.get().SwitchEnvironmentUnchecked(std::move(SavedPtr));
    34763506 }
    3507+
    3508+ //! \since build 961
    3509+ //@{
    3510+ shared_ptr<Environment>
    3511+ Switch() const ynothrowv
    3512+ {
    3513+ return SavedPtr ? Context.get().SwitchEnvironmentUnchecked(
    3514+ std::move(SavedPtr)) : nullptr;
    3515+ }
    3516+
    3517+ //! \sa ystdex::dismiss 。
    3518+ friend void
    3519+ dismiss(EnvironmentSwitcher& s) ynothrow
    3520+ {
    3521+ s.SavedPtr.reset();
    3522+ }
    3523+ //@}
    34773524 };
    34783525
    34793526
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/include/NPL/NPLA1.h
    --- a/YFramework/include/NPL/NPLA1.h Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/include/NPL/NPLA1.h Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA1.h
    1212 \ingroup NPL
    1313 \brief NPLA1 公共接口。
    14-\version r10362
    14+\version r10448
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 472
    1717 \par 创建时间:
    1818 2014-02-02 17:58:24 +0800
    1919 \par 修改时间:
    20- 2022-11-06 20:14 +0800
    20+ 2022-11-28 05:29 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -1721,7 +1721,7 @@
    17211721 AssignParent(ctx, std::move(parent));
    17221722 ystdex::invoke(yforward(f), yforward(args)...);
    17231723 ctx.GetRecordRef().Freeze();
    1724- return ctx.ShareRecord();
    1724+ return gd.func.Switch();
    17251725 }
    17261726
    17271727 /*!
    @@ -1730,29 +1730,69 @@
    17301730 */
    17311731 //@{
    17321732 //! \brief 加载模块为变量,若已存在则忽略。
    1733+//@{
    1734+//! \since build 961
    1735+template<typename _fCallable, typename... _tParams>
    1736+inline void
    1737+LoadModule(BindingMap& m, ContextNode& ctx, string_view module_name,
    1738+ _fCallable&& f, _tParams&&... args)
    1739+{
    1740+ Environment::Define(m, module_name,
    1741+ A1::GetModuleFor(ctx, yforward(f), yforward(args)...));
    1742+}
    1743+//! \since build 961
    1744+template<typename _fCallable, typename... _tParams>
    1745+inline void
    1746+LoadModule(Environment& env, ContextNode& ctx, string_view module_name,
    1747+ _fCallable&& f, _tParams&&... args)
    1748+{
    1749+ A1::LoadModule(env.GetMapCheckedRef(), ctx, module_name, yforward(f),
    1750+ yforward(args)...);
    1751+}
    17331752 template<typename _fCallable, typename... _tParams>
    17341753 inline void
    17351754 LoadModule(ContextNode& ctx, string_view module_name, _fCallable&& f,
    17361755 _tParams&&... args)
    17371756 {
    1738- Environment::Define(ctx.GetRecordRef().GetMapRef(), module_name,
    1739- A1::GetModuleFor(ctx, yforward(f), yforward(args)...));
    1757+ A1::LoadModule(ctx.GetRecordRef(), ctx, module_name, yforward(f),
    1758+ yforward(args)...);
    17401759 }
    1760+//@}
    17411761
    17421762 /*!
    17431763 \brief 加载模块为变量,若已存在抛出异常。
    17441764 \exception BadIdentifier 变量绑定已存在。
    17451765 */
    1766+//@{
    1767+//! \since build 961
    1768+template<typename _fCallable, typename... _tParams>
    1769+inline void
    1770+LoadModuleChecked(BindingMap& m, ContextNode& ctx, string_view module_name,
    1771+ _fCallable&& f, _tParams&&... args)
    1772+{
    1773+ Environment::DefineChecked(m, module_name,
    1774+ A1::GetModuleFor(ctx, yforward(f), yforward(args)...));
    1775+}
    1776+//! \since build 961
    1777+template<typename _fCallable, typename... _tParams>
    1778+inline void
    1779+LoadModuleChecked(Environment& env, ContextNode& ctx, string_view module_name,
    1780+ _fCallable&& f, _tParams&&... args)
    1781+{
    1782+ A1::LoadModuleChecked(env.GetMapCheckedRef(), ctx, module_name, yforward(f),
    1783+ yforward(args)...);
    1784+}
    17461785 template<typename _fCallable, typename... _tParams>
    17471786 inline void
    17481787 LoadModuleChecked(ContextNode& ctx, string_view module_name, _fCallable&& f,
    17491788 _tParams&&... args)
    17501789 {
    1751- Environment::DefineChecked(ctx.GetRecordRef().GetMapRef(), module_name,
    1752- A1::GetModuleFor(ctx, yforward(f), yforward(args)...));
    1790+ A1::LoadModuleChecked(ctx.GetRecordRef(), ctx, module_name, yforward(f),
    1791+ yforward(args)...);
    17531792 }
    17541793 //@}
    17551794 //@}
    1795+//@}
    17561796
    17571797
    17581798 /*!
    @@ -1825,10 +1865,12 @@
    18251865 ExtractEnvironmentFormal(TermNode&);
    18261866 //@}
    18271867
    1868+//! \pre 间接断言:第三参数的标签可表示一等对象的值。
    1869+//@{
    18281870 /*!
    18291871 \throw InvalidSyntax 嵌套异常 ArityMismatch :参数数匹配失败。
    18301872 \throw InvalidSyntax 嵌套异常 ParameterMismatch :参数匹配失败。
    1831-\note 不具有强异常安全保证。匹配失败时,其它的绑定状态未指定。
    1873+\note 不具有强异常安全保证:匹配失败时,其它的绑定状态未指定。
    18321874
    18331875 递归遍历参数和操作数树进行结构化匹配。
    18341876 若匹配失败,则抛出异常。
    @@ -1885,20 +1927,22 @@
    18851927 void(const TokenValue&, TermNode&, TermTags, const EnvironmentReference&)>,
    18861928 TermTags, const EnvironmentReference&);
    18871929
    1888-//! \pre 间接断言:第三参数的标签可表示一等对象的值。
    1889-//@{
    18901930 /*!
    18911931 \brief 使用操作数结构化匹配并绑定参数。
    18921932 \pre 间接断言:第一参数非空。
    18931933 \throw ArityMismatch 子项数匹配失败。
    18941934 \throw InvalidReference 非法的 @ 引用标记字符绑定。
    18951935 \throw InvalidSyntax 嵌套异常 ParameterMismatch :形式参数项不符合语法要求。
    1896-\note 第一参数指定绑定所在的环境。
    1936+\note 第一参数指定绑定的目标。
    18971937 \sa MatchParameter
    18981938 \sa TermReference
    18991939 \since build 894
    19001940
    19011941 形式参数和操作数为项指定的表达式树。
    1942+若第一参数是绑定映射,则绑定的目标是第一参数,
    1943+ 且最后一个参数指定绑定时使用的环境引用;
    1944+否则,绑定的目标是第一参数中的非冻结的可变名称绑定映射,
    1945+ 且绑定时使用的环境引用是第一参数初始化的环境弱引用。
    19021946 第二参数指定形式参数,第三参数指定操作数。
    19031947 进行匹配的算法递归搜索形式参数及其子项,要求参见 MatchParameter 。
    19041948 若匹配成功,在第一参数指定的环境内绑定未被忽略的匹配的非列表项。
    @@ -1910,8 +1954,18 @@
    19101954 当绑定的引用标记字符为 @ 且不是列表项时抛出异常。
    19111955 按引用传递绑定直接转移该项的内容。
    19121956 */
    1957+//@{
    1958+//! \since build 961
    1959+YF_API void
    1960+BindParameter(BindingMap&, const TermNode&, TermNode&,
    1961+ const EnvironmentReference&);
    1962+/*!
    1963+\throw TypeError 嵌套异常 TypeError :第一参数被冻结。
    1964+\sa Environment::GetMapCheckedRef
    1965+*/
    19131966 YF_API void
    19141967 BindParameter(const shared_ptr<Environment>&, const TermNode&, TermNode&);
    1968+//@}
    19151969
    19161970 /*!
    19171971 \brief 使用操作数结构化匹配并绑定参数到合式的形式参数树。
    @@ -1921,17 +1975,26 @@
    19211975 \sa CheckParameterTree
    19221976 \since build 917
    19231977
    1924-同 BindParameter ,但假定形式参数树确保通过检查没有语法错误,否则行为未定义。
    1978+同 BindParameter ,但假定形式参数树确保通过检查没有语法错误。
    1979+调用时应当确保满足假设,否则行为未定义。
    19251980 实现假定不存在形式参数树具有引起语法错误的错误条件。
    19261981 通过先前在同一形式参数树上的 CheckParameterTree 调用可保证符合前置条件。
    19271982 若确保绑定不具有引起对象语言中可观察行为的副作用,先前的 BindParameter
    19281983 或 BindParameterWellFormed 也可确保满足前置条件。
    19291984 */
    1985+//@{
    1986+//! \since build 961
    1987+YF_API void
    1988+BindParameterWellFormed(BindingMap&, const TermNode&, TermNode&,
    1989+ const EnvironmentReference&);
    1990+/*!
    1991+\throw TypeError 嵌套异常 TypeError :第一参数被冻结。
    1992+\sa Environment::GetMapCheckedRef
    1993+*/
    19301994 YF_API void
    19311995 BindParameterWellFormed(const shared_ptr<Environment>&, const TermNode&,
    19321996 TermNode&);
    19331997 //@}
    1934-//@}
    19351998
    19361999 /*!
    19372000 \brief 使用操作数结构化匹配并绑定符号。
    @@ -1939,8 +2002,20 @@
    19392002
    19402003 同 BindParameter ,但形式参数指定为符号,不进行递归绑定或结尾序列匹配。
    19412004 */
    2005+//@{
    2006+//! \since build 961
    2007+YF_API void
    2008+BindSymbol(BindingMap&, const TokenValue&, TermNode&,
    2009+ const EnvironmentReference&);
    2010+/*!
    2011+\throw TypeError 嵌套异常 TypeError :第一参数被冻结。
    2012+\sa Environment::GetMapCheckedRef
    2013+*/
    19422014 YF_API void
    19432015 BindSymbol(const shared_ptr<Environment>&, const TokenValue&, TermNode&);
    2016+//@}
    2017+//@}
    2018+//@}
    19442019
    19452020
    19462021 /*!
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/include/NPL/NPLA1Forms.h
    --- a/YFramework/include/NPL/NPLA1Forms.h Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/include/NPL/NPLA1Forms.h Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA1Forms.h
    1212 \ingroup NPL
    1313 \brief NPLA1 语法形式。
    14-\version r8897
    14+\version r8898
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 882
    1717 \par 创建时间:
    1818 2020-02-15 11:19:21 +0800
    1919 \par 修改时间:
    20- 2022-10-13 12:57 +0800
    20+ 2022-11-26 09:37 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -1282,7 +1282,7 @@
    12821282
    12831283 /*!
    12841284 \throw InvalidSyntax 标识符不是符号。
    1285-\throw TypeError 当前环境被冻结。
    1285+\throw TypeError 嵌套异常 TypeError :当前环境被冻结。
    12861286 \sa RemoveIdentifier
    12871287 \since build 867
    12881288 */
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/include/YSLib/Core/YApplication.h
    --- a/YFramework/include/YSLib/Core/YApplication.h Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/include/YSLib/Core/YApplication.h Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file YApplication.h
    1212 \ingroup Core
    1313 \brief 系统资源和应用程序实例抽象。
    14-\version r1800
    14+\version r1802
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 577
    1717 \par 创建时间:
    1818 2009-12-27 17:12:27 +0800
    1919 \par 修改时间:
    20- 2022-09-03 21:39 +0800
    20+ 2022-11-21 07:14 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -33,7 +33,7 @@
    3333 // default_allocator, byte, stack, any, stack, recursive_mutex, shared_ptr,
    3434 // std::is_nothrow_copy_constructible, locked_ptr, ystdex::decay_t,
    3535 // YSLib::unchecked_any_cast;
    36-#include <ystdex/scope_guard.hpp> // for ystdex::unique_guard;
    36+#include <ystdex/scope_guard.hpp> // for ystdex::make_unique_guard;
    3737
    3838 namespace YSLib
    3939 {
    @@ -130,7 +130,7 @@
    130130 "Invalid guard function found.");
    131131 lock_guard<recursive_mutex> lck(on_exit_mutex);
    132132
    133- TryExpr(PushExit(ystdex::unique_guard(f)))
    133+ TryExpr(PushExit(ystdex::make_unique_guard(f)))
    134134 catch(...)
    135135 {
    136136 f();
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/source/Helper/HostRenderer.cpp
    --- a/YFramework/source/Helper/HostRenderer.cpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/source/Helper/HostRenderer.cpp Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file HostRenderer.cpp
    1212 \ingroup Helper
    1313 \brief 宿主渲染器。
    14-\version r718
    14+\version r721
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 426
    1717 \par 创建时间:
    1818 2013-07-09 05:37:27 +0800
    1919 \par 修改时间:
    20- 2021-12-29 01:37 +0800
    20+ 2022-11-28 07:03 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -35,7 +35,7 @@
    3535 #elif YCL_Win32
    3636 # include YFM_Win32_Helper_Win32Control
    3737 #endif
    38-#include <ystdex/scope_guard.hpp> // for ystdex::unique_guard;
    38+#include <ystdex/scope_guard.hpp> // for ystdex::make_unique_guard;
    3939
    4040 namespace YSLib
    4141 {
    @@ -112,7 +112,7 @@
    112112 {
    113113 #if YF_Multithread == 1
    114114 wnd.GetGUIHostRef().EnterWindowThread();
    115- return ystdex::unique_guard([&]() ynothrow{
    115+ return ystdex::make_unique_guard([&]() ynothrow{
    116116 FilterExceptions([&]{
    117117 wnd.GetGUIHostRef().LeaveWindowThread();
    118118 }, "default event guard destructor");
    @@ -345,7 +345,7 @@
    345345 CatchExpr(LoggedEvent& e, ExtractAndTrace(e, Warning))
    346346 }
    347347
    348-Window&
    348+YB_PURE Window&
    349349 HostRenderer::Wait()
    350350 {
    351351 observer_ptr<Host::Window> p_wnd;
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/source/NPL/Dependency.cpp
    --- a/YFramework/source/NPL/Dependency.cpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/source/NPL/Dependency.cpp Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file Dependency.cpp
    1212 \ingroup NPL
    1313 \brief 依赖管理。
    14-\version r7656
    14+\version r7761
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 623
    1717 \par 创建时间:
    1818 2015-08-09 22:14:45 +0800
    1919 \par 修改时间:
    20- 2022-11-21 04:37 +0800
    20+ 2022-11-28 06:49 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -323,7 +323,7 @@
    323323 void
    324324 CopyEnvironmentDFS(Environment& d, const Environment& e)
    325325 {
    326- auto& m(d.GetMapRef());
    326+ auto& m(d.GetMapUncheckedRef());
    327327 // TODO: Check environments allocator equality.
    328328 const auto a(NPL::ToBindingsAllocator(m));
    329329 const auto copy_parent([&](Environment& dst, const Environment& parent){
    @@ -560,44 +560,45 @@
    560560 namespace Primitive
    561561 {
    562562
    563+//! \since build 961
    564+//@{
    563565 void
    564-LoadEquals(ContextNode& ctx)
    566+LoadEquals(BindingMap& m)
    565567 {
    566- RegisterStrict(ctx, "eq?", Eq);
    567- RegisterStrict(ctx, "eql?", EqLeaf);
    568- RegisterStrict(ctx, "eqr?", EqReference);
    569- RegisterStrict(ctx, "eqv?", EqValue);
    568+ RegisterStrict(m, "eq?", Eq);
    569+ RegisterStrict(m, "eql?", EqLeaf);
    570+ RegisterStrict(m, "eqr?", EqReference);
    571+ RegisterStrict(m, "eqv?", EqValue);
    570572 }
    571573
    572574 void
    573-LoadControl(ContextNode& ctx)
    575+LoadControl(BindingMap& m)
    574576 {
    575577 // NOTE: Like Scheme but not Kernel, '$if' treats non-boolean value as
    576578 // '#f', for zero overhead principle.
    577- RegisterForm(ctx, "$if", If);
    579+ RegisterForm(m, "$if", If);
    578580 }
    579581
    580-//! \since build 855
    581582 void
    582-LoadObjects(ContextNode& ctx)
    583+LoadObjects(BindingMap& m)
    583584 {
    584- RegisterUnary(ctx, "null?", ComposeReferencedTermOp(IsEmpty));
    585- RegisterUnary(ctx, "nullv?", IsEmpty);
    586- RegisterUnary(ctx, "branch?", ComposeReferencedTermOp(IsBranch));
    587- RegisterUnary(ctx, "branchv?", IsBranch);
    588- RegisterUnary(ctx, "pair?", ComposeReferencedTermOp(IsPair));
    589- RegisterUnary(ctx, "pairv?", IsPair);
    590- RegisterUnary(ctx, "symbol?",
    585+ RegisterUnary(m, "null?", ComposeReferencedTermOp(IsEmpty));
    586+ RegisterUnary(m, "nullv?", IsEmpty);
    587+ RegisterUnary(m, "branch?", ComposeReferencedTermOp(IsBranch));
    588+ RegisterUnary(m, "branchv?", IsBranch);
    589+ RegisterUnary(m, "pair?", ComposeReferencedTermOp(IsPair));
    590+ RegisterUnary(m, "pairv?", IsPair);
    591+ RegisterUnary(m, "symbol?",
    591592 [] YB_LAMBDA_ANNOTATE((const TermNode& x), ynothrow, pure){
    592593 return IsTypedRegular<TokenValue>(ReferenceTerm(x));
    593594 });
    594- RegisterUnary(ctx, "reference?", IsReferenceTerm);
    595- RegisterUnary(ctx, "unique?", IsUniqueTerm);
    596- RegisterUnary(ctx, "modifiable?", IsModifiableTerm);
    597- RegisterUnary(ctx, "temporary?", IsTemporaryTerm);
    598- RegisterUnary(ctx, "bound-lvalue?", IsBoundLValueTerm);
    599- RegisterUnary(ctx, "uncollapsed?", IsUncollapsedTerm);
    600- RegisterStrict(ctx, "deshare", [](TermNode& term){
    595+ RegisterUnary(m, "reference?", IsReferenceTerm);
    596+ RegisterUnary(m, "unique?", IsUniqueTerm);
    597+ RegisterUnary(m, "modifiable?", IsModifiableTerm);
    598+ RegisterUnary(m, "temporary?", IsTemporaryTerm);
    599+ RegisterUnary(m, "bound-lvalue?", IsBoundLValueTerm);
    600+ RegisterUnary(m, "uncollapsed?", IsUncollapsedTerm);
    601+ RegisterStrict(m, "deshare", [](TermNode& term){
    601602 return CallRawUnary([&](TermNode& tm){
    602603 if(const auto p = TryAccessLeafAtom<const TermReference>(tm))
    603604 LiftTermRef(tm, p->get());
    @@ -606,77 +607,76 @@
    606607 return ReductionStatus::Retained;
    607608 }, term);
    608609 });
    609- RegisterStrict(ctx, "as-const", trivial_swap,
    610+ RegisterStrict(m, "as-const", trivial_swap,
    610611 ystdex::bind1(Qualify, TermTags::Nonmodifying));
    611- RegisterStrict(ctx, "expire", trivial_swap,
    612+ RegisterStrict(m, "expire", trivial_swap,
    612613 ystdex::bind1(Qualify, TermTags::Unique));
    613- RegisterStrict(ctx, "move!", trivial_swap,
    614+ RegisterStrict(m, "move!", trivial_swap,
    614615 ystdex::bind1(DoMoveOrTransfer, std::ref(LiftOtherOrCopy)));
    615- RegisterStrict(ctx, "transfer!", trivial_swap,
    616+ RegisterStrict(m, "transfer!", trivial_swap,
    616617 ystdex::bind1(DoMoveOrTransfer, std::ref(LiftTermValueOrCopy)));
    617- RegisterStrict(ctx, "ref&", [](TermNode& term){
    618+ RegisterStrict(m, "ref&", [](TermNode& term){
    618619 CallUnary([&](TermNode& tm){
    619620 LiftToReference(term, tm);
    620621 }, term);
    621622 return ReductionStatus::Retained;
    622623 });
    623- RegisterBinary(ctx, "assign@!", [](TermNode& x, TermNode& y){
    624+ RegisterBinary(m, "assign@!", [](TermNode& x, TermNode& y){
    624625 return DoAssign(ystdex::bind1(static_cast<void(&)(TermNode&,
    625626 TermNode&)>(LiftOther), std::ref(y)), x);
    626627 });
    627628 }
    628629
    629630 void
    630-LoadLists(ContextNode& ctx)
    631+LoadLists(BindingMap& m)
    631632 {
    632- RegisterStrict(ctx, "cons", Cons);
    633- RegisterStrict(ctx, "cons%", ConsRef);
    633+ RegisterStrict(m, "cons", Cons);
    634+ RegisterStrict(m, "cons%", ConsRef);
    634635 // NOTE: Like '$set-cdr!' in Kernel, with no references.
    635- RegisterStrict(ctx, "set-rest!", SetRest);
    636+ RegisterStrict(m, "set-rest!", SetRest);
    636637 // NOTE: Like '$set-cdr!' in Kernel.
    637- RegisterStrict(ctx, "set-rest%!", SetRestRef);
    638+ RegisterStrict(m, "set-rest%!", SetRestRef);
    638639 }
    639640
    640-//! \since build 908
    641641 void
    642-LoadSymbols(ContextNode& ctx)
    642+LoadSymbols(BindingMap& m)
    643643 {
    644- RegisterUnary<Strict, const TokenValue>(ctx, "desigil", [](TokenValue s){
    644+ RegisterUnary<Strict, const TokenValue>(m, "desigil", [](TokenValue s){
    645645 return TokenValue(!s.empty() && (s.front() == '&' || s.front() == '%')
    646646 ? s.substr(1) : std::move(s));
    647647 });
    648648 }
    649649
    650650 void
    651-LoadEnvironments(ContextNode& ctx)
    651+LoadEnvironments(BindingMap& m)
    652652 {
    653653 using namespace std::placeholders;
    654654
    655655 // NOTE: The applicative 'copy-es-immutable' is unsupported currently due to
    656656 // different implementation of control primitives.
    657- RegisterStrict(ctx, "eval", Eval);
    658- RegisterStrict(ctx, "eval%", EvalRef);
    659- RegisterUnary<Strict, const string>(ctx, "bound?",
    657+ RegisterStrict(m, "eval", Eval);
    658+ RegisterStrict(m, "eval%", EvalRef);
    659+ RegisterUnary<Strict, const string>(m, "bound?",
    660660 [](const string& id, ContextNode& c){
    661661 return bool(ResolveName(c, id).first);
    662662 });
    663- RegisterForm(ctx, "$resolve-identifier", trivial_swap,
    663+ RegisterForm(m, "$resolve-identifier", trivial_swap,
    664664 std::bind(DoResolve, std::ref(ResolveIdentifier), _1, _2));
    665- RegisterForm(ctx, "$move-resolved!", trivial_swap,
    665+ RegisterForm(m, "$move-resolved!", trivial_swap,
    666666 std::bind(DoResolve, std::ref(MoveResolved), _1, _2));
    667667 // NOTE: This is now primitive since in NPL environment capture is more
    668668 // basic than vau.
    669- RegisterStrict(ctx, "copy-environment", CopyEnvironment);
    670- RegisterUnary<Strict, const EnvironmentReference>(ctx, "lock-environment",
    669+ RegisterStrict(m, "copy-environment", CopyEnvironment);
    670+ RegisterUnary<Strict, const EnvironmentReference>(m, "lock-environment",
    671671 [](const EnvironmentReference& r_env) ynothrow{
    672672 return r_env.Lock();
    673673 });
    674- RegisterUnary(ctx, "freeze-environment!", [](TermNode& x){
    674+ RegisterUnary(m, "freeze-environment!", [](TermNode& x){
    675675 Environment::EnsureValid(ResolveEnvironment(x).first).Freeze();
    676676 return ValueToken::Unspecified;
    677677 });
    678- RegisterStrict(ctx, "make-environment", MakeEnvironment);
    679- RegisterUnary<Strict, const shared_ptr<Environment>>(ctx,
    678+ RegisterStrict(m, "make-environment", MakeEnvironment);
    679+ RegisterUnary<Strict, const shared_ptr<Environment>>(m,
    680680 "weaken-environment", [](const shared_ptr<Environment>& p_env) ynothrow{
    681681 return EnvironmentReference(p_env);
    682682 });
    @@ -685,52 +685,50 @@
    685685 // '$def!') is preferred. The recursion variant (named '$defrec!') is more
    686686 // than '$define!' in Kernel because of more native interoperations
    687687 // (shared object holders) supported, and is used only when necessary.
    688- RegisterForm(ctx, "$def!", DefineWithNoRecursion);
    689- RegisterForm(ctx, "$defrec!", DefineWithRecursion);
    688+ RegisterForm(m, "$def!", DefineWithNoRecursion);
    689+ RegisterForm(m, "$defrec!", DefineWithRecursion);
    690690 }
    691691
    692692 void
    693-LoadCombiners(ContextNode& ctx)
    693+LoadCombiners(BindingMap& m)
    694694 {
    695695 // NOTE: For ground environment applicatives (see below for
    696696 // 'get-current-environment'), the result of evaluation of expression
    697697 // 'eqv? (() get-current-environment) (() ($vau () d d))' shall be '#t'.
    698- RegisterForm(ctx, "$vau/e", VauWithEnvironment);
    699- RegisterForm(ctx, "$vau/e%", VauWithEnvironmentRef);
    700- RegisterStrict(ctx, "wrap", Wrap);
    701- RegisterStrict(ctx, "wrap%", WrapRef);
    702- RegisterStrict(ctx, "unwrap", Unwrap);
    698+ RegisterForm(m, "$vau/e", VauWithEnvironment);
    699+ RegisterForm(m, "$vau/e%", VauWithEnvironmentRef);
    700+ RegisterStrict(m, "wrap", Wrap);
    701+ RegisterStrict(m, "wrap%", WrapRef);
    702+ RegisterStrict(m, "unwrap", Unwrap);
    703703 }
    704704
    705-//! \since build 859
    706705 void
    707-LoadErrorsAndChecks(ContextNode& ctx)
    706+LoadErrorsAndChecks(BindingMap& m)
    708707 {
    709- RegisterUnary<Strict, const string>(ctx, "raise-error",
    708+ RegisterUnary<Strict, const string>(m, "raise-error",
    710709 [] YB_LAMBDA_ANNOTATE((const string& str), , noreturn){
    711710 throw NPLException(str);
    712711 });
    713- RegisterUnary<Strict, const string>(ctx, "raise-invalid-syntax-error",
    712+ RegisterUnary<Strict, const string>(m, "raise-invalid-syntax-error",
    714713 [] YB_LAMBDA_ANNOTATE((const string& str), , noreturn){
    715714 ThrowInvalidSyntaxError(str);
    716715 });
    717- RegisterUnary<Strict, const string>(ctx, "raise-type-error",
    716+ RegisterUnary<Strict, const string>(m, "raise-type-error",
    718717 [] YB_LAMBDA_ANNOTATE((const string& str), , noreturn){
    719718 throw TypeError(str);
    720719 });
    721- RegisterStrict(ctx, "check-list-reference", CheckListReference);
    722- RegisterStrict(ctx, "check-pair-reference", CheckPairReference);
    723-}
    724-
    725-//! \since build 855
    726-void
    727-LoadEncapsulations(ContextNode& ctx)
    728-{
    729- RegisterStrict(ctx, "make-encapsulation-type", MakeEncapsulationType);
    720+ RegisterStrict(m, "check-list-reference", CheckListReference);
    721+ RegisterStrict(m, "check-pair-reference", CheckPairReference);
    730722 }
    731723
    732724 void
    733-Load(ContextNode& ctx)
    725+LoadEncapsulations(BindingMap& m)
    726+{
    727+ RegisterStrict(m, "make-encapsulation-type", MakeEncapsulationType);
    728+}
    729+
    730+void
    731+Load(BindingMap& m)
    734732 {
    735733 // NOTE: Primitive features, listed as RnRK, except mentioned above.
    736734 /*
    @@ -741,16 +739,17 @@
    741739 There are some difference of listed primitives.
    742740 See $2017-02 @ %Documentation::Workflow.
    743741 */
    744- LoadEquals(ctx);
    745- LoadControl(ctx);
    746- LoadObjects(ctx);
    747- LoadLists(ctx);
    748- LoadSymbols(ctx);
    749- LoadEnvironments(ctx);
    750- LoadCombiners(ctx);
    751- LoadErrorsAndChecks(ctx);
    752- LoadEncapsulations(ctx);
    742+ LoadEquals(m);
    743+ LoadControl(m);
    744+ LoadObjects(m);
    745+ LoadLists(m);
    746+ LoadSymbols(m);
    747+ LoadEnvironments(m);
    748+ LoadCombiners(m);
    749+ LoadErrorsAndChecks(m);
    750+ LoadEncapsulations(m);
    753751 }
    752+//@}
    754753
    755754 } // namespace Primitive;
    756755
    @@ -1388,7 +1387,7 @@
    13881387 $if (null? l) #f ($if (first-null? l) #t (nonfoldable? (rest& l)));
    13891388 $defl%! assq (&x &alist) $cond ((null? alist))
    13901389 ((eq? x (first& (first& alist))) first% alist)
    1391- (#t assq (forward! x) (rest& alist));
    1390+ (#t assq (forward! x) (rest% alist));
    13921391 $defl%! assv (&x &alist) $cond ((null? alist))
    13931392 ((eqv? x (first& (first& alist))) first% alist)
    13941393 (#t assv (forward! x) (rest% alist));
    @@ -1468,11 +1467,13 @@
    14681467 void
    14691468 Load(ContextState& cs)
    14701469 {
    1471-// LoadObjects(cs.GetRecordRef());
    1472- Primitive::Load(cs);
    1470+ auto& env(cs.GetRecordRef());
    1471+
    1472+// LoadObjects(env);
    1473+ Primitive::Load(env.GetMapRef());
    14731474 Derived::Load(cs);
    14741475 // NOTE: Prevent the ground environment from modification.
    1475- cs.GetRecordRef().Freeze();
    1476+ env.Freeze();
    14761477 }
    14771478
    14781479 } // namespace Ground;
    @@ -2112,7 +2113,8 @@
    21122113 {
    21132114 auto& con(term.GetContainerRef());
    21142115
    2115- p_env->Bind("module-parameters", NPL::AsTermNode(
    2116+ Environment::Bind(p_env->GetMapRef(), "module-parameters",
    2117+ NPL::AsTermNode(
    21162118 ResolveEnvironment(std::move(*con.rbegin())).first));
    21172119 // XXX: This is needed for the call to %ReduceToLoadExternal
    21182120 // later.
    @@ -2289,9 +2291,10 @@
    22892291 RegisterUnary<Strict, const string>(m, "unregister-requirement!",
    22902292 trivial_swap, [&](const string& req){
    22912293 CheckRequirement(req);
    2292- if(YB_UNLIKELY(registry.erase(req) == 0))
    2293- throw NPLException("Requirement '" + to_std_string(req)
    2294- + "' is not registered.");
    2294+ if(registry.erase(req) != 0)
    2295+ return ValueToken::Unspecified;
    2296+ throw NPLException(
    2297+ "Requirement '" + to_std_string(req) + "' is not registered.");
    22952298 });
    22962299 RegisterUnary<Strict, const string>(m, "find-requirement-filename",
    22972300 // TODO: Blocked. Use C++14 lambda initializers to optimize the
    @@ -2345,7 +2348,8 @@
    23452348 switch(con.size())
    23462349 {
    23472350 case 3:
    2348- val.second->Bind("module-parameters", NPL::AsTermNode(
    2351+ Environment::Bind(val.second->GetMapRef(), "module-parameters",
    2352+ NPL::AsTermNode(
    23492353 ResolveEnvironment(std::move(*con.rbegin())).first));
    23502354 con.pop_back();
    23512355 YB_ATTR_fallthrough;
    @@ -2493,15 +2497,14 @@
    24932497 EnsureDirectory(IO::Path(str));
    24942498 return ValueToken::Unspecified;
    24952499 });
    2496- RegisterStrict(m, "SHBuild_EchoVar", trivial_swap,
    2497- [&](TermNode& term){
    2500+ RegisterStrict(m, "SHBuild_EchoVar", trivial_swap, [&](TermNode& term){
    24982501 // XXX: To be overriden if %Terminal is usable (platform specific).
    2499- CallBinaryAs<const string, const string>(
    2502+ return CallBinaryAs<const string, const string>(
    25002503 [&](const string& n, const string& val){
    25012504 // NOTE: Since root environment can be switched, reference to the
    25022505 // initial instance is necessary to be captured explicitly.
    2503- if(const auto p = GetValuePtrOf(renv.LookupName(
    2504- "SHBuild_BaseTerminalHook_")))
    2506+ if(const auto p = GetValuePtrOf(LookupName(
    2507+ renv.GetMapUncheckedRef(), "SHBuild_BaseTerminalHook_")))
    25052508 if(const auto p_hook = AccessPtr<
    25062509 function<void(const string&, const string&)>>(*p))
    25072510 (*p_hook)(n, val);
    @@ -2665,11 +2668,13 @@
    26652668 void
    26662669 LoadStandardContext(ContextState& cs)
    26672670 {
    2671+ auto& m(cs.GetRecordRef().GetMapRef());
    2672+
    26682673 LoadGroundContext(cs);
    26692674 // XXX: A lambda-expression is OK and the generated code can be equally
    26702675 // efficient, but not succinct as using macro in the invocation sites.
    26712676 #define NPL_Impl_LoadStd(_name) \
    2672- LoadModuleChecked(cs, "std." #_name, LoadModule_std_##_name, cs)
    2677+ LoadModuleChecked(m, cs, "std." #_name, LoadModule_std_##_name, cs)
    26732678 NPL_Impl_LoadStd(continuations),
    26742679 NPL_Impl_LoadStd(promises);
    26752680 NPL_Impl_LoadStd(math),
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/source/NPL/NPLA.cpp
    --- a/YFramework/source/NPL/NPLA.cpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/source/NPL/NPLA.cpp Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA.cpp
    1212 \ingroup NPL
    1313 \brief NPLA 公共接口。
    14-\version r4270
    14+\version r4318
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 663
    1717 \par 创建时间:
    1818 2016-01-07 10:32:45 +0800
    1919 \par 修改时间:
    20- 2022-11-21 04:37 +0800
    20+ 2022-11-28 05:25 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -32,15 +32,16 @@
    3232 // AccessPtr, ystdex::value_or, ystdex::write, std::bind, TraverseSubnodes,
    3333 // bad_any_cast, std::allocator_arg, YSLib::NodeSequence, ystdex::begins_with,
    3434 // shared_ptr, ystdex::sfmt, ystdex::unchecked_function, observer_ptr,
    35-// ystdex::make_obj_using_allocator, trivial_swap, CountPrefix, make_observer,
    36-// TermTags, TryAccessLeafAtom, NPL::Deref, YSLib::sfmt, AssertReferentTags,
    37-// ystdex::call_value_or, ystdex::compose, GetLValueTagsOf, std::mem_fn,
    38-// IsTyped, ystdex::invoke_value_or, ystdex::ref, PropagateTo, IsSticky,
    39-// FindSticky, std::distance, ystdex::as_const, TryAccessLeaf,
    40-// AccessFirstSubterm, YSLib::FilterExceptions, YSLib::allocate_shared,
    41-// ystdex::addrof, ystdex::second_of, type_info, std::current_exception,
    42-// std::rethrow_exception, std::throw_with_nested, lref, ystdex::retry_on_cond,
    43-// ystdex::id, pair, IsAtom, NPL::IsMovable, YSLib::ExtractException;
    35+// ystdex::make_obj_using_allocator, trivial_swap, make_observer, TermTags,
    36+// TryAccessLeafAtom, NPL::Deref, YSLib::sfmt, CountPrefix, IsSticky,
    37+// AssertReferentTags, ystdex::call_value_or, ystdex::compose, GetLValueTagsOf,
    38+// std::mem_fn, IsTyped, ystdex::invoke_value_or, ystdex::ref, PropagateTo,
    39+// std::distance, ystdex::as_const, FindSticky, TryAccessLeaf,
    40+// AccessFirstSubterm, ystdex::addrof, ystdex::second_of,
    41+// YSLib::FilterExceptions, YSLib::allocate_shared, type_info,
    42+// std::current_exception, std::rethrow_exception, std::throw_with_nested,
    43+// lref, ystdex::retry_on_cond, ystdex::id, pair, IsAtom, NPL::IsMovable,
    44+// YSLib::ExtractException;
    4445
    4546 //! \since build 903
    4647 //@{
    @@ -851,6 +852,14 @@
    851852 ImplDeDtor(Environment)
    852853 #endif
    853854
    855+YB_ATTR_nodiscard YB_PURE BindingMap&
    856+Environment::GetMapCheckedRef()
    857+{
    858+ if(!IsFrozen())
    859+ return GetMapRef();
    860+ throw TypeError("Frozen environment found.");
    861+}
    862+
    854863 void
    855864 Environment::CheckParent(const ValueObject& vo)
    856865 {
    @@ -926,35 +935,17 @@
    926935 return YSLib::allocate_shared<AnchorData>(a);
    927936 }
    928937
    929-Environment::NameResolution::first_type
    930-Environment::LookupName(string_view id) const
    938+void
    939+Environment::RemoveChecked(BindingMap& m, string_view id)
    931940 {
    932- YAssertNonnull(id.data());
    933- return make_observer(ystdex::call_value_or<BindingMap::mapped_type*>(
    934- ystdex::compose(ystdex::addrof<>(), ystdex::second_of<>()),
    935- bindings.find(id), {}, bindings.cend()));
    936-}
    937-
    938-bool
    939-Environment::Remove(string_view id)
    940-{
    941- YAssertNonnull(id.data());
    942- // XXX: %BindingMap does not have transparent key %erase. This is like
    943- // %std::set.
    944- return ystdex::erase_first(bindings, id);
    945-}
    946-
    947-void
    948-Environment::RemoveChecked(string_view id)
    949-{
    950- if(!Remove(id))
    941+ if(!Remove(m, id))
    951942 throw BadIdentifier(id, 0);
    952943 }
    953944
    954945 bool
    955-Environment::Replace(string_view id, ValueObject&& vo)
    946+Environment::Replace(BindingMap& m, string_view id, ValueObject&& vo)
    956947 {
    957- if(const auto p = LookupName(id))
    948+ if(const auto p = LookupName(m, id))
    958949 {
    959950 swap(p->Value, vo);
    960951 return true;
    @@ -963,9 +954,9 @@
    963954 }
    964955
    965956 void
    966-Environment::ReplaceChecked(string_view id, ValueObject&& vo)
    957+Environment::ReplaceChecked(BindingMap& m, string_view id, ValueObject&& vo)
    967958 {
    968- if(!Replace(id, std::move(vo)))
    959+ if(!Replace(m, id, std::move(vo)))
    969960 throw BadIdentifier(id, 0);
    970961 }
    971962
    @@ -979,9 +970,8 @@
    979970 void
    980971 Environment::ThrowForInvalidValue(bool record)
    981972 {
    982- throw std::invalid_argument(record
    983- ? "Invalid environment record pointer found."
    984- : "Invalid environment found.");
    973+ throw std::invalid_argument(record ? "Invalid environment record pointer"
    974+ " found." : "Invalid environment found.");
    985975 }
    986976
    987977
    @@ -1060,7 +1050,7 @@
    10601050 std::throw_with_nested(TypeError(MismatchedTypesToString(e))))
    10611051 }
    10621052
    1063-Environment::NameResolution
    1053+NameResolution
    10641054 ContextNode::DefaultResolve(shared_ptr<Environment> p_env, string_view id)
    10651055 {
    10661056 YAssertNonnull(p_env);
    @@ -1072,10 +1062,9 @@
    10721062 // XXX: Flatten attribute is less efficient with x86_64-pc-linux G++
    10731063 // 12.1.
    10741064 #if YB_IMPL_GNUCPP >= 120000
    1075- [&](Environment::NameResolution::first_type p)
    1065+ [&](NameResolution::first_type p)
    10761066 #else
    1077- [&] YB_LAMBDA_ANNOTATE(
    1078- (Environment::NameResolution::first_type p), , flatten)
    1067+ [&] YB_LAMBDA_ANNOTATE((NameResolution::first_type p), , flatten)
    10791068 #endif
    10801069 // XXX: This uses G++ extension to work around the compatible issue. See
    10811070 // also %YB_ATTR_LAMBDA_QUAL.
    @@ -1139,7 +1128,7 @@
    11391128 }
    11401129 return false;
    11411130 }, [&, id]{
    1142- return p_env->LookupName(id);
    1131+ return LookupName(p_env->GetMapUncheckedRef(), id);
    11431132 }));
    11441133
    11451134 return {p_obj, std::move(p_env)};
    @@ -1167,10 +1156,10 @@
    11671156 }
    11681157
    11691158 shared_ptr<Environment>
    1170-ContextNode::SwitchEnvironment(const shared_ptr<Environment>& p_env)
    1159+ContextNode::SwitchEnvironment(shared_ptr<Environment> p_env)
    11711160 {
    11721161 if(p_env)
    1173- return SwitchEnvironmentUnchecked(p_env);
    1162+ return SwitchEnvironmentUnchecked(std::move(p_env));
    11741163 Environment::ThrowForInvalidValue(true);
    11751164 }
    11761165
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/source/NPL/NPLA1.cpp
    --- a/YFramework/source/NPL/NPLA1.cpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/source/NPL/NPLA1.cpp Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA1.cpp
    1212 \ingroup NPL
    1313 \brief NPLA1 公共接口。
    14-\version r24399
    14+\version r24638
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 472
    1717 \par 创建时间:
    1818 2014-02-02 18:02:47 +0800
    1919 \par 修改时间:
    20- 2022-11-12 21:00 +0800
    20+ 2022-11-27 12:14 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -47,7 +47,7 @@
    4747 // AssertValueTags, ystdex::retry_on_cond, AccessFirstSubterm, ystdex::ref_eq,
    4848 // ystdex::make_transform, IsCombiningTerm, NPL::IsMovable, std::placeholders,
    4949 // NoContainer, ystdex::try_emplace, Access, YSLib::Informative,
    50-// ystdex::unique_guard, CategorizeBasicLexeme, DeliteralizeUnchecked,
    50+// ystdex::make_unique_guard, CategorizeBasicLexeme, DeliteralizeUnchecked,
    5151 // Deliteralize, IsLeaf, TryAccessTerm, YSLib::share_move,
    5252 // ystdex::call_value_or, std::piecewise_construct, type_id, make_observer,
    5353 // YSLib::Notice, YSLib::FilterException, Session;
    @@ -98,7 +98,11 @@
    9898 // compared to expansion level 2 (~7x when using %Action or ~1.5x when
    9999 // using %YSLib::stack and %vector).
    100100 #ifndef NPL_Impl_NPLA1_BindParameter_ExpandLevel
    101-# if !defined(NDEBUG) || __OPTIMIZE_SIZE__
    101+// XXX: 'YCL_Win32 && YCL_MinGW' is added temporarily to work around MinGW32
    102+// native GCC's cc1plus.exe out-of-memory problem. This is not accurate e.g.
    103+// for cross compilers from x86_64 which have sufficient address space.
    104+# if !defined(NDEBUG) || __OPTIMIZE_SIZE__ \
    105+ || (YB_IMPL_GNUCPP && YCL_Win32 && YCL_MinGW)
    102106 # define NPL_Impl_NPLA1_BindParameter_ExpandLevel 0
    103107 # else
    104108 # define NPL_Impl_NPLA1_BindParameter_ExpandLevel 1
    @@ -296,7 +300,7 @@
    296300 return RelaySwitched(ctx, GLContinuation<>(h));
    297301 #else
    298302
    299- auto gd(ystdex::unique_guard([&]() ynothrow{
    303+ auto gd(ystdex::make_unique_guard([&]() ynothrow{
    300304 // XXX: This term is fixed, as in the term cleanup in %TCOAction.
    301305 term.Clear();
    302306 }));
    @@ -592,18 +596,45 @@
    592596 inline PDefH(void, CopyTermTags, TermNode& term, const TermNode& tm) ynothrow
    593597 ImplExpr(term.Tags = GetLValueTagsOf(tm.Tags))
    594598
    595-//! \since build 858
    596-void
    597-MarkTemporaryTerm(TermNode& term, char sigil) ynothrow
    599+//! \since build 961
    600+struct BindAdd final
    598601 {
    599- if(sigil != char())
    600- // XXX: This is like lifetime extension of temporary objects with rvalue
    601- // references in the host language.
    602- term.Tags |= TermTags::Temporary;
    603-}
    602+ BindingMap& m;
    603+ string_view& id;
    604+
    605+ void
    606+ operator()(const TermNode& tm) const
    607+ {
    608+ CopyTermTags(Environment::Bind(m, id, tm), tm);
    609+ }
    610+ TermNode&
    611+ operator()(TermNode::Container&& c, ValueObject&& vo)
    612+ {
    613+ // XXX: Allocators are not used here for performance.
    614+ return Environment::Bind(m, id, TermNode(std::move(c), std::move(vo)));
    615+ }
    616+};
    617+
    618+//! \since build 961
    619+struct BindInsert final
    620+{
    621+ TermNode::Container& tcon;
    622+
    623+ void
    624+ operator()(const TermNode& tm) const
    625+ {
    626+ CopyTermTags(tcon.emplace_back(tm.GetContainer(), tm.Value), tm);
    627+ }
    628+ TermNode&
    629+ operator()(TermNode::Container&& c, ValueObject&& vo) const
    630+ {
    631+ tcon.emplace_back(std::move(c), std::move(vo));
    632+ return tcon.back();
    633+ }
    634+};
    604635
    605636 //! \since build 828
    606-class BindParameterObject
    637+class BindParameterObject final
    607638 {
    608639 public:
    609640 // XXX: This is actually used for references of lvalues and it
    @@ -612,16 +643,19 @@
    612643 //! \since build 882
    613644 lref<const EnvironmentReference> Referenced;
    614645
    615- //! \since build 882
    616- BindParameterObject(const EnvironmentReference& r_env)
    617- : Referenced(r_env)
    646+private:
    647+ //! \since build 961
    648+ //@{
    649+ char sigil;
    650+
    651+public:
    652+ BindParameterObject(const EnvironmentReference& r_env, char s) ynothrow
    653+ : Referenced(r_env), sigil(s)
    618654 {}
    619655
    620- //! \since build 916
    621- template<typename _fCopy, typename _fMove>
    656+ template<typename _fInit>
    622657 void
    623- operator()(char sigil, bool ref_temp, TermTags o_tags, TermNode& o,
    624- _fCopy cp, _fMove mv) const
    658+ operator()(TermTags o_tags, TermNode& o, _fInit init) const
    625659 {
    626660 // NOTE: For elements binding here, %TermTags::Unique in %o_tags is
    627661 // irrelavant.
    @@ -647,23 +681,25 @@
    647681 {
    648682 if(sigil != char())
    649683 {
    650- // NOTE: If %ref_temp is set, xvalues are treated as
    651- // prvalues in terms of the tags of the bound object. This
    652- // only occurs on sigil '&' as per the object language
    684+ // NOTE: If the sigil is '&', xvalues are treated as
    685+ // prvalues in terms of the tags of the bound object by
    686+ // calling to %BindReferenceTags instead of
    687+ // %TermReference::GetTags. This only occurs on sigil '&'
    688+ // for non-trailing binding as per the object language
    653689 // rules.
    654- const auto ref_tags(PropagateTo(ref_temp
    690+ const auto ref_tags(PropagateTo(sigil == '&'
    655691 ? BindReferenceTags(*p) : p->GetTags(), o_tags));
    656692
    657693 // XXX: Allocators are not used here on %TermReference for
    658694 // performance in most cases.
    659695 if(can_modify && temp)
    660696 // NOTE: Reference collapsed by move.
    661- mv(std::move(o.GetContainerRef()),
    697+ init(std::move(o.GetContainerRef()),
    662698 ValueObject(in_place_type<TermReference>, ref_tags,
    663699 std::move(*p)));
    664700 else
    665701 // NOTE: Reference collapsed by copy.
    666- mv(TermNode::Container(o.GetContainer(), a),
    702+ init(TermNode::Container(o.GetContainer(), a),
    667703 ValueObject(in_place_type<TermReference>, ref_tags,
    668704 *p));
    669705 }
    @@ -674,9 +710,9 @@
    674710 // NOTE: Since it is passed by value copy, direct
    675711 // destructive lifting cannot be used.
    676712 if(!p->IsMovable())
    677- cp(src);
    713+ init(src);
    678714 else
    679- mv(std::move(src.GetContainerRef()),
    715+ init(std::move(src.GetContainerRef()),
    680716 std::move(src.Value));
    681717 }
    682718 }
    @@ -688,8 +724,8 @@
    688724 else if((can_modify || sigil == '%') && temp)
    689725 // XXX: The object is bound to reference as temporary, implying
    690726 // copy elision in the object language.
    691- MarkTemporaryTerm(mv(std::move(o.GetContainerRef()),
    692- std::move(o.Value)), sigil);
    727+ MarkTemporaryTerm(init(std::move(o.GetContainerRef()),
    728+ std::move(o.Value)));
    693729 // NOTE: Binding on list prvalues is always unsafe. However, since
    694730 // %TermTags::Nonmodifying is not allowed on prvalues, being not
    695731 // %can_modify currently implies some ancestor of %o is a
    @@ -700,7 +736,7 @@
    700736 // The anchor here (if any) is not accurate because it refers
    701737 // to the anchor saved by the reference (if any), not
    702738 // necessarily the original environment owning the referent.
    703- mv(TermNode::Container(a),
    739+ init(TermNode::Container(a),
    704740 // NOTE: Term tags on prvalues are reserved and should be
    705741 // ignored normally except for the possible overlapped
    706742 // encoding of %TermTags::Sticky and future internal use.
    @@ -713,14 +749,14 @@
    713749 // %PropagateTo in functionality except %TermTags::Unique.
    714750 GetLValueTagsOf(o.Tags | o_tags), o, Referenced));
    715751 else
    716- cp(o);
    752+ init(o);
    717753 }
    718754 else if(!temp)
    719755 // XXX: Ditto, except that tags other than %TermTags::Nonmodifying
    720756 // as well as %o.Tags are ignored intentionally. This may cause
    721757 // differences on derivations using '@' or not, see $2021-08
    722758 // @ %Documentation::Workflow.
    723- mv(TermNode::Container(o.get_allocator()),
    759+ init(TermNode::Container(o.get_allocator()),
    724760 ValueObject(std::allocator_arg, o.get_allocator(),
    725761 in_place_type<TermReference>, o_tags & TermTags::Nonmodifying,
    726762 o, Referenced));
    @@ -728,11 +764,9 @@
    728764 throw
    729765 InvalidReference("Invalid operand found on binding sigil '@'.");
    730766 }
    731- //! \since build 951
    732- template<typename _fMove>
    767+ template<typename _fInit>
    733768 void
    734- operator()(char sigil, bool ref_temp, TermTags o_tags, TermNode& o,
    735- TNIter first, _fMove mv) const
    769+ operator()(TermTags o_tags, TermNode& o, TNIter first, _fInit init) const
    736770 {
    737771 // NOTE: Same to the overload above, except that %o can be a pair and %j
    738772 // specifies the 1st subterm of the suffix.
    @@ -743,16 +777,16 @@
    743777 [&](TermNode& src, TNIter j, TermTags tags) -> TermNode&{
    744778 YAssert(sigil == char() || sigil == '%', "Invalid sigil found.");
    745779
    746- auto t(CreateForBindSubpairPrefix(sigil, src, j, tags));
    780+ auto t(CreateForBindSubpairPrefix(src, j, tags));
    747781
    748782 if(o.Value)
    749783 BindSubpairCopySuffix(t, src, j);
    750- return mv(std::move(t.GetContainerRef()), std::move(t.Value));
    784+ return init(std::move(t.GetContainerRef()), std::move(t.Value));
    751785 });
    752786 const auto bind_subpair_ref_at([&](TermTags tags){
    753787 YAssert(sigil == '&' || sigil == '@', "Invalid sigil found.");
    754788
    755- auto t(CreateForBindSubpairPrefix(sigil, o, first, tags));
    789+ auto t(CreateForBindSubpairPrefix(o, first, tags));
    756790
    757791 if(o.Value)
    758792 // XXX: The container is ignored, since it is assumed always
    @@ -773,16 +807,14 @@
    773807 // XXX: Reuse %tcon.
    774808 tcon.clear();
    775809 tcon.push_back(MakeSubobjectReferent(a, std::move(p_sub)));
    776- // XXX: The anchor indicated by %Referenced is not accurate, as
    777- // the overload %operator() above.
    778- mv(std::move(tcon), ValueObject(std::allocator_arg, a,
    810+ // XXX: The anchor indicated by %Referenced is not accurate, as the
    811+ // overload %operator() above.
    812+ init(std::move(tcon), ValueObject(std::allocator_arg, a,
    779813 in_place_type<TermReference>, tags, sub, Referenced));
    780814 #else
    781- // NOTE: Any optimized implemenations shall be equivalent to
    782- // this.
    783- ReduceAsSubobjectReference(t, std::move(p_sub), Referenced,
    784- tags);
    785- mv(std::move(tcon), std::move(t.Value));
    815+ // NOTE: Any optimized implemenations shall be equivalent to this.
    816+ ReduceAsSubobjectReference(t, std::move(p_sub), Referenced, tags);
    817+ init(std::move(tcon), std::move(t.Value));
    786818 #endif
    787819 });
    788820
    @@ -795,15 +827,15 @@
    795827 {
    796828 if(sigil != char())
    797829 {
    798- const auto ref_tags(PropagateTo(ref_temp
    830+ const auto ref_tags(PropagateTo(sigil == '&'
    799831 ? BindReferenceTags(*p) : p->GetTags(), o_tags));
    800832
    801833 if(can_modify && temp)
    802- mv(MoveSuffix(o, first),
    834+ init(MoveSuffix(o, first),
    803835 ValueObject(in_place_type<TermReference>, ref_tags,
    804836 std::move(*p)));
    805837 else
    806- mv(TermNode::Container(first, o.end(), a),
    838+ init(TermNode::Container(first, o.end(), a),
    807839 ValueObject(in_place_type<TermReference>, ref_tags,
    808840 *p));
    809841 }
    @@ -815,7 +847,7 @@
    815847 CopyTermTags(bind_subpair_val_fwd(src, src.begin(),
    816848 GetLValueTagsOf(o_tags & ~TermTags::Unique)), src);
    817849 else
    818- mv(MoveSuffix(o, first), std::move(src.Value));
    850+ init(MoveSuffix(o, first), std::move(src.Value));
    819851 }
    820852 }
    821853 // NOTE: This is different to the element binding overload above. It
    @@ -828,15 +860,14 @@
    828860 {
    829861 if(sigil == char())
    830862 LiftPrefixToReturn(o, first);
    831- MarkTemporaryTerm(mv(MoveSuffix(o, first), std::move(o.Value)),
    832- sigil);
    863+ MarkTemporaryTerm(init(MoveSuffix(o, first),
    864+ std::move(o.Value)));
    833865 }
    834866 else if(sigil == '&')
    835867 bind_subpair_ref_at(GetLValueTagsOf(o.Tags | o_tags));
    836868 // NOTE: The temporary tag cannot be in %o_tags here.
    837869 else
    838- MarkTemporaryTerm(bind_subpair_val_fwd(o, first, o_tags),
    839- sigil);
    870+ MarkTemporaryTerm(bind_subpair_val_fwd(o, first, o_tags));
    840871 }
    841872 else if(!temp)
    842873 bind_subpair_ref_at(o_tags & TermTags::Nonmodifying);
    @@ -847,7 +878,6 @@
    847878
    848879 private:
    849880 //! \since build 954
    850- //@{
    851881 static void
    852882 BindSubpairCopySuffix(TermNode& t, TermNode& o, TNIter& j)
    853883 {
    @@ -857,8 +887,8 @@
    857887 }
    858888
    859889 void
    860- BindSubpairPrefix(char sigil, TermNode::Container& tcon, TermNode& o,
    861- TNIter& j, TermTags tags) const
    890+ BindSubpairPrefix(TermNode::Container& tcon, TermNode& o, TNIter& j,
    891+ TermTags tags) const
    862892 {
    863893 // NOTE: This guarantees no subpair element will have
    864894 // %TermTags::Temporary.
    @@ -868,35 +898,24 @@
    868898 // to the elements of the sublist, depending on the sigil.
    869899 for(; j != o.end() && !IsSticky(j->Tags); ++j)
    870900 #if true
    871- BindSubpairSubterm(sigil, tcon, tags, NPL::Deref(j));
    901+ BindSubpairSubterm(tcon, tags, NPL::Deref(j));
    872902 #else
    873- // NOTE: Any optimized implemenations shall be equivalent to this.
    874- (*this)(sigil, {}, tags, NPL::Deref(j), [&](const TermNode& tm){
    875- CopyTermTags(tcon.emplace_back(tm.GetContainer(), tm.Value),
    876- tm);
    877- }, [&](TermNode::Container&& c, ValueObject&& vo) -> TermNode&{
    878- tcon.emplace_back(std::move(c), std::move(vo));
    879- return tcon.back();
    880- });
    903+ // NOTE: Any optimized implemenations shall be equivalent to this,
    904+ // except that the 1st argument of the call to %PropagateTo is
    905+ // always assumed '{}'.
    906+ (*this)(tags, NPL::Deref(j), BindInsert{tcon});
    881907 #endif
    882908 }
    883909
    884910 // XXX: Keep this a separated function may lead to more efficient code.
    885911 void
    886- BindSubpairSubterm(char sigil, TermNode::Container& tcon, TermTags o_tags,
    887- TermNode& o) const
    912+ BindSubpairSubterm(TermNode::Container& tcon, TermTags o_tags, TermNode& o)
    913+ const
    888914 {
    889915 // NOTE: As %BindSubpairPrefix.
    890916 YAssert(!bool(o_tags & TermTags::Temporary),
    891917 "Unexpected temporary tag found.");
    892- const auto cp([&](const TermNode& tm){
    893- CopyTermTags(tcon.emplace_back(tm.GetContainer(), tm.Value), tm);
    894- });
    895- const auto
    896- mv([&](TermNode::Container&& c, ValueObject&& vo) -> TermNode&{
    897- tcon.emplace_back(std::move(c), std::move(vo));
    898- return tcon.back();
    899- });
    918+ const BindInsert init{tcon};
    900919
    901920 if(sigil != '@')
    902921 {
    @@ -905,37 +924,39 @@
    905924 if(const auto p = TryAccessLeafAtom<TermReference>(o))
    906925 {
    907926 if(sigil != char())
    908- mv(TermNode::Container(o.GetContainer(), a),
    927+ init(TermNode::Container(o.GetContainer(), a),
    909928 ValueObject(in_place_type<TermReference>,
    929+ // XXX: Do not use %BindReferenceTags as in
    930+ // %operator()#1. This is required by the object
    931+ // language rules.
    910932 PropagateTo(p->GetTags(), o_tags), *p));
    911933 else
    912934 {
    913935 auto& src(p->get());
    914936
    915937 if(!p->IsMovable())
    916- cp(src);
    938+ init(src);
    917939 else
    918- mv(std::move(src.GetContainerRef()),
    940+ init(std::move(src.GetContainerRef()),
    919941 std::move(src.Value));
    920942 }
    921943 }
    922944 else if(sigil == '&')
    923- mv(TermNode::Container(a), ValueObject(std::allocator_arg, a,
    945+ init(TermNode::Container(a), ValueObject(std::allocator_arg, a,
    924946 in_place_type<TermReference>,
    925947 GetLValueTagsOf(o.Tags | o_tags), o, Referenced));
    926948 else
    927- cp(o);
    949+ init(o);
    928950 }
    929951 else
    930- mv(TermNode::Container(o.get_allocator()),
    952+ init(TermNode::Container(o.get_allocator()),
    931953 ValueObject(std::allocator_arg, o.get_allocator(),
    932954 in_place_type<TermReference>, o_tags & TermTags::Nonmodifying,
    933955 o, Referenced));
    934956 }
    935957
    936958 TermNode
    937- CreateForBindSubpairPrefix(char sigil, TermNode& o, TNIter first,
    938- TermTags tags) const
    959+ CreateForBindSubpairPrefix(TermNode& o, TNIter first, TermTags tags) const
    939960 {
    940961 // NOTE: There is no %TermTags::Temprary in %tags due to the constrains
    941962 // in the caller. This guarantees no element will have
    @@ -948,12 +969,21 @@
    948969
    949970 // NOTE: No tags are set in the result implies no %TermTags::Temporary
    950971 // in the elements finally.
    951- BindSubpairPrefix(sigil, t.GetContainerRef(), o, first, tags);
    972+ BindSubpairPrefix(t.GetContainerRef(), o, first, tags);
    952973 if(!o.Value)
    953974 // XXX: As in %LiftPrefixToReturn.
    954975 YAssert(first == o.end(), "Invalid representation found.");
    955976 return t;
    956977 }
    978+
    979+ void
    980+ MarkTemporaryTerm(TermNode& term) const ynothrow
    981+ {
    982+ if(sigil != char())
    983+ // XXX: This is like lifetime extension of temporary objects with
    984+ // rvalue references in the host language.
    985+ term.Tags |= TermTags::Temporary;
    986+ }
    957987 //@}
    958988
    959989 //! \since build 951
    @@ -1442,40 +1472,24 @@
    14421472 MakeParameterMatcher(TermNode::allocator_type a,
    14431473 _fBindTrailing bind_trailing_seq, _fBindValue bind_value)
    14441474 {
    1445- return GParameterMatcher<_tTraits, GBinder<_fBindTrailing, _fBindValue>>(
    1446- a, std::move(bind_trailing_seq), std::move(bind_value));
    1475+ return GParameterMatcher<_tTraits, GBinder<_fBindTrailing, _fBindValue>>(a,
    1476+ std::move(bind_trailing_seq), std::move(bind_value));
    14471477 }
    14481478 //@}
    14491479
    1450-//! \since build 948
    1451-// XXX: 'YB_FLATTEN' cannot used with G++ 12.1.0 when %BindParameterImpl is also
    1452-// using 'YB_FLATTEN', to avoid ICE in 'gimple_duplicate_bb' at
    1453-// 'tree-cfg.c:6420'. This is no more efficient otherwise.
    1454-void
    1455-BindRawSymbol(const EnvironmentReference& r_env, string_view id,
    1456- TermNode& o, TermTags o_tags, Environment& env, char sigil)
    1457-{
    1458- BindParameterObject{r_env}(sigil, sigil == '&', o_tags, o,
    1459- [&](const TermNode& tm){
    1460- CopyTermTags(env.Bind(id, tm), tm);
    1461- }, [&](TermNode::Container&& c, ValueObject&& vo) -> TermNode&{
    1462- // XXX: Allocators are not used here for performance.
    1463- return env.Bind(id, TermNode(std::move(c), std::move(vo)));
    1464- });
    1465-}
    1466-
    14671480
    14681481 //! \since build 949
    14691482 struct DefaultBinder final
    14701483 {
    1471- lref<Environment> EnvRef;
    1484+ //! \since build 961
    1485+ lref<BindingMap> MapRef;
    14721486
    1473- inline
    1474- DefaultBinder(Environment& env)
    1475- : EnvRef(env)
    1487+ //! \since build 961
    1488+ DefaultBinder(BindingMap& m) ynothrow
    1489+ : MapRef(m)
    14761490 {}
    14771491
    1478- void
    1492+ YB_FLATTEN void
    14791493 operator()(TermNode& o_nd, TNIter first, string_view id, TermTags o_tags,
    14801494 const EnvironmentReference& r_env) const
    14811495 {
    @@ -1489,32 +1503,41 @@
    14891503 // NOTE: Ignore the name of single '.' followed by a sigil (if it is
    14901504 // from the trailing subterm of the list).
    14911505 if(!id.empty())
    1492- {
    1493- auto& env(EnvRef.get());
    1494-
    1495- BindParameterObject{r_env}(sigil, sigil == '&', o_tags, o_nd,
    1496- first,
    1497- [&](TermNode::Container&& c, ValueObject&& vo) -> TermNode&{
    1498- // XXX: Allocators are not used here for performance.
    1499- return env.Bind(id, TermNode(std::move(c), std::move(vo)));
    1500- });
    1501- }
    1506+ Bind(r_env, sigil, id, o_tags, o_nd, first);
    15021507 }
    15031508 }
    1509+ // XXX: As of b948, 'YB_FLATTEN' cannot be used with G++ 12.1.0 on a
    1510+ // separated function for binding raw symbols when %BindParameterImpl is
    1511+ // also using 'YB_FLATTEN', to avoid ICE in 'gimple_duplicate_bb' at
    1512+ // 'tree-cfg.c:6420'. This is no more efficient otherwise. However, this is
    1513+ // not the case as of b961, and it makes improvement to all values of
    1514+ // %NPL_Impl_NPLA1_BindParameter_ExpandLevel, so it is enabled
    1515+ // unconditionally except for value '0' where the debug information and
    1516+ // binary size may take higher priority.
    1517+#if NPL_Impl_NPLA1_BindParameter_ExpandLevel > 0
    1518+ YB_FLATTEN
    1519+#endif
    15041520 void
    15051521 operator()(string_view id, TermNode& o, TermTags o_tags,
    15061522 const EnvironmentReference& r_env) const
    15071523 {
    1508- // XXX: This shall be sequenced before the following call since %id can
    1509- // be modified.
    1510- const char sigil(ExtractSigil(id));
    1524+ // XXX: The call to %ExtractSigil shall be sequenced before the
    1525+ // following call since %id can be modified.
    1526+ Bind(r_env, ExtractSigil(id), id, o_tags, o);
    1527+ }
    15111528
    1512- BindRawSymbol(r_env, id, o, o_tags, EnvRef, sigil);
    1529+ template<typename... _tParams>
    1530+ YB_FLATTEN inline void
    1531+ Bind(const EnvironmentReference& r_env, char sigil, string_view& id,
    1532+ _tParams&&... args) const
    1533+ {
    1534+ BindParameterObject(r_env, sigil)(yforward(args)...,
    1535+ BindAdd{MapRef, id});
    15131536 }
    15141537 };
    15151538
    15161539
    1517-//! \since build 917
    1540+//! \since build 961
    15181541 template<class _tTraits>
    15191542 // XXX: 'YB_FLATTEN' here may make the generated code a bit more efficient, but
    15201543 // significantly slow in compiling without manually annotated 'always_inline',
    @@ -1528,19 +1551,30 @@
    15281551 YB_FLATTEN
    15291552 #endif
    15301553 inline void
    1531-BindParameterImpl(const shared_ptr<Environment>& p_env, const TermNode& t,
    1532- TermNode& o)
    1554+BindParameterImpl(BindingMap& m, const TermNode& t, TermNode& o,
    1555+ const EnvironmentReference& r_env)
    15331556 {
    1534- auto& env(NPL::Deref(p_env));
    1535-
    15361557 AssertValueTags(o);
    15371558 // XXX: This should normally be true, but not yet relied on.
    15381559 // AssertMatchedAllocators(t, o);
    15391560 // NOTE: No duplication check here. Symbols can be rebound.
    15401561 // NOTE: The call is essentially same as %MatchParameter, with a bit better
    15411562 // performance by avoiding %function instances.
    1542- MakeParameterMatcher<_tTraits>(t.get_allocator(), DefaultBinder(env))(t, o,
    1543- TermTags::Temporary, p_env);
    1563+ MakeParameterMatcher<_tTraits>(t.get_allocator(), DefaultBinder(m))(t, o,
    1564+ TermTags::Temporary, r_env);
    1565+}
    1566+//! \since build 917
    1567+template<class _tTraits>
    1568+#if NPL_Impl_NPLA1_BindParameter_ExpandLevel >= 2
    1569+YB_FLATTEN
    1570+#endif
    1571+inline void
    1572+BindParameterImpl(const shared_ptr<Environment>& p_env, const TermNode& t,
    1573+ TermNode& o)
    1574+{
    1575+ // NOTE: See below.
    1576+ BindParameterImpl<_tTraits>(NPL::Deref(p_env).GetMapCheckedRef(), t, o,
    1577+ p_env);
    15441578 }
    15451579
    15461580 } // unnamed namespace;
    @@ -1920,13 +1954,13 @@
    19201954 auto p_env(cs.ShareRecord());
    19211955
    19221956 // TODO: Support different place if the environment is frozen?
    1923- ystdex::try_emplace(p_env->GetMapRef(), name, NoContainer,
    1957+ ystdex::try_emplace(p_env->GetMapUncheckedRef(), name, NoContainer,
    19241958 in_place_type<size_t>);
    19251959 // TODO: Blocked. Use C++14 lambda initializers to simplify the
    19261960 // implementation.
    1927- cs.Guard += std::bind([name](TermNode& term, ContextNode& ctx,
    1928- shared_ptr<Environment>& p_e){
    1929- if(const auto p = p_e->LookupName(name))
    1961+ cs.Guard += std::bind(
    1962+ [name](TermNode& term, ContextNode& ctx, shared_ptr<Environment>& p_e){
    1963+ if(const auto p = LookupName(p_e->GetMapUncheckedRef(), name))
    19301964 {
    19311965 using ystdex::pvoid;
    19321966 auto& depth(Access<size_t>(*p));
    @@ -1935,7 +1969,7 @@
    19351969 YTraceDe(YSLib::Informative, "Depth = %zu, context = %p, semantics"
    19361970 " = %p.", depth, pvoid(&ctx), pvoid(&term));
    19371971 ++depth;
    1938- return ystdex::unique_guard([&]() ynothrow{
    1972+ return ystdex::make_unique_guard([&]() ynothrow{
    19391973 --depth;
    19401974 });
    19411975 }
    @@ -2593,9 +2627,8 @@
    25932627 // AssertValueTags(o);
    25942628 // XXX: See %BindParameterImpl.
    25952629 // AssertMatchedAllocators(t, o);
    2596- MakeParameterMatcher<ParameterCheck>(t.get_allocator(),
    2597- std::move(bind_trailing_seq),
    2598- std::move(bind_value))(t, o, o_tags, r_env);
    2630+ MakeParameterMatcher<ParameterCheck>(t.get_allocator(), std::move(
    2631+ bind_trailing_seq), std::move(bind_value))(t, o, o_tags, r_env);
    25992632 }
    26002633
    26012634 // XXX: 'YB_FLATTEN' is a bit better for the quality of the generated code with
    @@ -2603,6 +2636,12 @@
    26032636 // %BindParameterWellFormed), so it is not used here if compilation time is
    26042637 // concerned. See %NPL_Impl_NPLA1_BindParameter_ExpandLevel for more details.
    26052638 void
    2639+BindParameter(BindingMap& m, const TermNode& t, TermNode& o,
    2640+ const EnvironmentReference& r_env)
    2641+{
    2642+ BindParameterImpl<ParameterCheck>(m, t, o, r_env);
    2643+}
    2644+void
    26062645 BindParameter(const shared_ptr<Environment>& p_env, const TermNode& t,
    26072646 TermNode& o)
    26082647 {
    @@ -2614,6 +2653,16 @@
    26142653 YB_FLATTEN
    26152654 #endif
    26162655 void
    2656+BindParameterWellFormed(BindingMap& m, const TermNode& t, TermNode& o,
    2657+ const EnvironmentReference& r_env)
    2658+{
    2659+ BindParameterImpl<NoParameterCheck>(m, t, o, r_env);
    2660+}
    2661+// XXX: Ditto.
    2662+#if NPL_Impl_NPLA1_BindParameter_ExpandLevel == 1
    2663+YB_FLATTEN
    2664+#endif
    2665+void
    26172666 BindParameterWellFormed(const shared_ptr<Environment>& p_env, const TermNode& t,
    26182667 TermNode& o)
    26192668 {
    @@ -2621,13 +2670,25 @@
    26212670 }
    26222671
    26232672 void
    2624-BindSymbol(const shared_ptr<Environment>& p_env, const TokenValue& n,
    2625- TermNode& o)
    2673+BindSymbol(BindingMap& m, const TokenValue& n, TermNode& o,
    2674+ const EnvironmentReference& r_env)
    26262675 {
    26272676 AssertValueTags(o);
    26282677 // NOTE: As %BindSymbolImpl expecting the parameter tree as a single symbol
    26292678 // term without trailing handling.
    2630- DefaultBinder(NPL::Deref(p_env))(n, o, TermTags::Temporary, p_env);
    2679+ DefaultBinder{m}(n, o, TermTags::Temporary, r_env);
    2680+}
    2681+void
    2682+BindSymbol(const shared_ptr<Environment>& p_env, const TokenValue& n,
    2683+ TermNode& o)
    2684+{
    2685+ // NOTE: As %BindSymbolImpl expecting the parameter tree as a single symbol
    2686+ // term without trailing handling.
    2687+ auto& env(NPL::Deref(p_env));
    2688+
    2689+ // XXX: Using explicit anchor pointer is more efficient.
    2690+ BindSymbol(env.GetMapCheckedRef(), n, o,
    2691+ EnvironmentReference(p_env, env.GetAnchorPtr()));
    26312692 }
    26322693 #undef NPL_Impl_NPLA1_BindParameter_Inline
    26332694
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/source/NPL/NPLA1Forms.cpp
    --- a/YFramework/source/NPL/NPLA1Forms.cpp Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/source/NPL/NPLA1Forms.cpp Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA1Forms.cpp
    1212 \ingroup NPL
    1313 \brief NPLA1 语法形式。
    14-\version r28919
    14+\version r29048
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 882
    1717 \par 创建时间:
    1818 2014-02-15 11:19:51 +0800
    1919 \par 修改时间:
    20- 2022-11-15 00:37 +0800
    20+ 2022-11-28 05:25 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -34,34 +34,34 @@
    3434 // AccessFirstSubterm, ReduceOrdered, LiftOtherValue, std::bind, std::ref,
    3535 // std::placeholders, std::declval, RetainN, ystdex::as_const, ValueObject,
    3636 // ReferenceLeaf, IsAtom, ReferenceTerm, ystdex::ref_eq, CountPrefix, IsSticky,
    37-// RelaySwitched, trivial_swap, shared_ptr, ContextHandler,
    38-// YSLib::unordered_map, string, Environment, lref, TokenValue,
    37+// RelaySwitched, trivial_swap, shared_ptr, ContextHandler, string_view,
    38+// YSLib::unordered_map, Environment, std::throw_with_nested, string, TokenValue,
    3939 // any_ops::use_holder, in_place_type, YSLib::HolderFromPointer,
    40-// YSLib::allocate_shared, InvalidReference, std::throw_with_nested, TypeError,
    41-// BindParameter, Retain, MoveFirstSubterm,L ResolveEnvironment, ShareMoveTerm,
    42-// BindParameterWellFormed, ystdex::sfmt, TermToStringWithReferenceMark,
    43-// ResolveTerm, LiftOtherOrCopy, ClearCombiningTags, SContext::Analyze,
    44-// std::allocator_arg, NPL::ResolveRegular, ystdex::make_transform,
    45-// TryAccessLeafAtom, TermReference, EnvironmentList, NPL::AllocateEnvironment,
    46-// IsTypedRegular, TryAccessLeaf, ystdex::equality_comparable, IsList,
    40+// YSLib::allocate_shared, InvalidReference, TypeError, BindParameter, Retain,
    41+// MoveFirstSubterm, ResolveEnvironment, BindParameterWellFormed, ystdex::sfmt,
    42+// TermToStringWithReferenceMark, ResolveTerm, LiftOtherOrCopy,
    43+// ClearCombiningTags, SContext::Analyze, std::allocator_arg,
    44+// NPL::ResolveRegular, ystdex::make_transform, TryAccessLeafAtom,
    45+// TermReference, EnvironmentList, NPL::AllocateEnvironment, IsTypedRegular,
    46+// TryAccessLeaf, BindSymbol, ystdex::equality_comparable, IsList,
    4747 // ystdex::fast_all_of, IsEmpty, CheckParameterTree, AssertValueTags,
    4848 // NPL::AsTermNode, ystdex::exchange, TermTags, YSLib::Debug, NPLException,
    4949 // YSLib::sfmt, AssignParent, ThrowListTypeErrorForNonList,
    5050 // GuardFreshEnvironment, A1::MakeForm, ystdex::expand_proxy, AccessRegular,
    5151 // GetLValueTagsOf, RegularizeTerm, IsPair, LiftPropagatedReference, LiftOther,
    5252 // IsLeaf, LiftMovedOther, LiftTerm, ThrowValueCategoryError,
    53-// ThrowListTypeErrorForAtom, ThrowInvalidSyntaxError,
    53+// ThrowListTypeErrorForAtom, ThrowInvalidSyntaxError, ShareMoveTerm,
    5454 // ExtractEnvironmentFormal, LiftTermOrCopy, EnsureValueTags, type_id,
    5555 // ystdex::update_thunk, AssertCombiningTerm, LiftToReturn,
    5656 // ystdex::prefix_eraser, IsTyped, IsBranchedList, EnvironmentGuard,
    57-// AssignWeakParent, TryAccessLeaf, BindSymbol, A1::AsForm, ystdex::bind1,
    58-// IsNPLASymbol, ystdex::isdigit, std::strchr, ystdex::call_value_or,
    59-// ystdex::equal_to, LiftCollapsed, std::distance, ReduceCombinedBranch,
    60-// YSLib::usystem, std::mem_fn;
    57+// AssignWeakParent, lref, A1::AsForm, ystdex::bind1, IsNPLASymbol,
    58+// ystdex::isdigit, std::strchr, ystdex::call_value_or, ystdex::equal_to,
    59+// LiftCollapsed, std::distance, ReduceCombinedBranch, YSLib::usystem,
    60+// std::mem_fn;
    6161 #include "NPLA1Internals.h" // for A1::Internals API;
    6262 #include YFM_NPL_SContext // for Session;
    63-#include <ystdex/scope_guard.hpp> // for ystdex::unique_guard, ystdex::dismiss,
    64-// ystdex::make_guard;
    63+#include <ystdex/scope_guard.hpp> // for ystdex::unique_guard,
    64+// ystdex::make_unique_guard, ystdex::dismiss, ystdex::make_guard;
    6565
    6666 namespace NPL
    6767 {
    @@ -77,7 +77,8 @@
    7777 # define NPL_Impl_NPLA1Forms_VauHandler_OptimizeLevel 3
    7878 # endif
    7979 #endif
    80-//@}//! \since build 945
    80+//@}
    81+//! \since build 945
    8182 //@{
    8283 #ifndef NDEBUG
    8384 # define NPL_Impl_NPLA1Forms_TraceVauCall true
    @@ -361,6 +362,15 @@
    361362 #endif
    362363 //@}
    363364
    365+//! \since build 961
    366+YB_ATTR_nodiscard YB_PURE BindingMap&
    367+FetchDefineMapRef(const shared_ptr<Environment>& p_env)
    368+{
    369+ TryRet(NPL::Deref(p_env).GetMapCheckedRef())
    370+ CatchExpr(..., std::throw_with_nested(
    371+ TypeError("Cannot define variables in a frozen environment.")))
    372+}
    373+
    364374
    365375 // NOTE: This type is a thunk, but not used as a thunk value stored in
    366376 // %TermNode::ValueObject, hence not an NPLA1 thunk value type.
    @@ -373,34 +383,28 @@
    373383 using shared_ptr_t = shared_ptr<ContextHandler>;
    374384 //! \since build 784
    375385 YSLib::unordered_map<string, shared_ptr_t> store;
    376-
    377386 public:
    378- //! \since build 894
    379- shared_ptr<Environment> RecordPtr;
    380- //! \since build 893
    381- lref<const TermNode> TermRef;
    382-
    383- //! \since build 917
    384- RecursiveThunk(const shared_ptr<Environment>& p_env, const TermNode& t)
    385- : store(t.get_allocator()), RecordPtr(p_env), TermRef(t)
    387+#if NPL_Impl_NPLA1_Enable_Thunked
    388+ //! \since build 961
    389+ TermNode Saved;
    390+#endif
    391+
    392+ //! \since build 961
    393+#if NPL_Impl_NPLA1_Enable_Thunked
    394+ RecursiveThunk(BindingMap& m, TermNode& formals)
    395+ : store(formals.get_allocator()), Saved(std::move(formals))
    396+#else
    397+ RecursiveThunk(BindingMap& m, const TermNode& t)
    398+ : store(t.get_allocator())
    399+#endif
    386400 {
    387- Fix(RecordPtr, TermRef);
    388- }
    389- //! \since build 841
    390- DefDeMoveCtor(RecursiveThunk)
    391-
    392- //! \since build 841
    393- DefDeMoveAssignment(RecursiveThunk)
    394-
    395-private:
    396- //! \since build 894
    397- void
    398- Fix(const shared_ptr<Environment>& p_env, const TermNode& t)
    399- {
    401+#if NPL_Impl_NPLA1_Enable_Thunked
    402+ const auto& t(Saved);
    403+#endif
    404+ const auto a(t.get_allocator());
    405+
    400406 // XXX: This is served as the addtional static environment.
    401- auto& env(NPL::Deref(p_env));
    402-
    403- MakeParameterValueMatcher(t.get_allocator(), [&](const TokenValue& n){
    407+ MakeParameterValueMatcher(a, [&](const TokenValue& n){
    404408 string_view id(n);
    405409
    406410 ExtractSigil(id);
    @@ -413,14 +417,20 @@
    413417 // NOTE: This binds value to a local thunk value. The
    414418 // bound symbol can then be rebound to an ordinary
    415419 // (non-sharing object.
    416- env.Bind(k, TermNode(TermNode::Container(t.get_allocator()),
    420+ Environment::Bind(m, k, TermNode(TermNode::Container(a),
    417421 ValueObject(any_ops::use_holder, in_place_type<
    418422 YSLib::HolderFromPointer<shared_ptr_t>>,
    419- store[k] = YSLib::allocate_shared<ContextHandler>(
    420- t.get_allocator(), ThrowInvalidCyclicReference))));
    423+ store[k] = YSLib::allocate_shared<ContextHandler>(a,
    424+ ThrowInvalidCyclicReference))));
    421425 })(t);
    422426 }
    423-
    427+ //! \since build 841
    428+ DefDeMoveCtor(RecursiveThunk)
    429+
    430+ //! \since build 841
    431+ DefDeMoveAssignment(RecursiveThunk)
    432+
    433+private:
    424434 //! \since build 780
    425435 YB_NORETURN static ReductionStatus
    426436 ThrowInvalidCyclicReference(TermNode&, ContextNode&)
    @@ -459,21 +469,12 @@
    459469 CatchExpr(..., std::throw_with_nested(std::move(e)))
    460470 }
    461471
    462-//! \since build 917
    463-void
    464-CheckFrozenEnvironment(const shared_ptr<Environment>& p_env)
    465-{
    466- if(YB_UNLIKELY(NPL::Deref(p_env).IsFrozen()))
    467- throw TypeError("Cannot define variables in a frozen environment.");
    468-}
    469-
    470472 //! \since build 919
    471473 void
    472474 CheckBindParameter(const shared_ptr<Environment>& p_env, const TermNode& t,
    473475 TermNode& o)
    474476 {
    475- CheckFrozenEnvironment(p_env);
    476- BindParameter(p_env, t, o);
    477+ BindParameter(FetchDefineMapRef(p_env), t, o, p_env);
    477478 }
    478479
    479480 //! \since build 868
    @@ -586,41 +587,42 @@
    586587 Call(TermNode& term, ContextNode& ctx, shared_ptr<Environment> p_env,
    587588 TermNode& formals, _tParams&&... args)
    588589 {
    590+ auto& m(FetchDefineMapRef(p_env));
    589591 #if NPL_Impl_NPLA1_Enable_Thunked
    590- // XXX: Terms shall be moved and saved into the actions.
    591- auto p_saved(ShareMoveTerm(formals));
    592-
    593- // TODO: Avoid %shared_ptr?
    592+
    594593 // TODO: Blocked. Use C++14 lambda initializers to simplify the
    595594 // implementation.
    596- return ReduceSubsequentPinned(term, ctx,
    597- A1::NameTypedReducerHandler(std::bind([&](const
    598- shared_ptr<TermNode>&, const shared_ptr<RecursiveThunk>& p_gd,
    599- const _tParams&...){
    600- CheckFrozenEnvironment(p_gd->RecordPtr);
    601- // NOTE: The parameter tree shall have been checked in the
    602- // initialization of %RecursiveThunk.
    603- BindParameterWellFormed(p_gd->RecordPtr, p_gd->TermRef, term);
    604- // NOTE: This support PTC only when the thunk cleanup is not existed
    605- // at the tail context.
    606- return ReduceReturnUnspecified(term);
    607- }, std::move(p_saved), YSLib::allocate_shared<RecursiveThunk>(
    608- term.get_allocator(), std::move(p_env), *p_saved),
    595+ return ReduceSubsequentPinned(term, ctx, A1::NameTypedReducerHandler(
    596+ std::bind([&](const shared_ptr<Environment>& p_e,
    597+ const RecursiveThunk& gd, const _tParams&...){
    598+ return ReduceCallBind(m, p_e, gd.Saved, term);
    599+ // XXX: Terms shall be moved and saved into the actions.
    600+ }, std::move(p_env), RecursiveThunk(m, formals),
    609601 std::move(args)...), "match-ptree-recursive"));
    610602 #else
    611603 // NOTE: This does not support PTC.
    612- RecursiveThunk gd(std::move(p_env), formals);
    604+ RecursiveThunk gd(m, formals);
    613605
    614606 yunseq(0, args...);
    615607 ReduceOnce(term, ctx);
    616- CheckFrozenEnvironment(gd.RecordPtr);
    608+ return ReduceCallBind(m, p_env, formals, term);
    609+#endif
    610+ }
    611+
    612+private:
    613+ //! \since build 961
    614+ YB_ATTR_always_inline static ReductionStatus
    615+ ReduceCallBind(BindingMap& m, const shared_ptr<Environment>& p_env,
    616+ const TermNode& formals, TermNode& term)
    617+ {
    617618 // NOTE: The parameter tree shall have been checked in the
    618619 // initialization of %RecursiveThunk.
    619- BindParameterWellFormed(gd.RecordPtr, formals, term);
    620+ // XXX: Using explicit anchor pointer is more efficient.
    621+ BindParameterWellFormed(m, formals, term, EnvironmentReference(p_env,
    622+ NPL::Deref(p_env).GetAnchorPtr()));
    620623 // NOTE: This support PTC only when the thunk cleanup is not existed at
    621624 // the tail context.
    622625 return ReduceReturnUnspecified(term);
    623-#endif
    624626 }
    625627 };
    626628
    @@ -840,7 +842,7 @@
    840842 // NOTE: Forming beta-reducible terms using parameter binding, to substitute
    841843 // them as arguments for later closure reduction.
    842844 // NOTE: The environment is assumed not frozen, so no need to use
    843- // %CheckFrozenEnvironment.
    845+ // %FetchDefineMapRef.
    844846 // NOTE: The parameter tree shall have been checked in the initialization of
    845847 // %VauHandler.
    846848 BindParameterWellFormed(ctx.GetRecordPtr(), formals, term);
    @@ -1177,6 +1179,7 @@
    11771179 auto gd(GuardFreshEnvironment(ctx));
    11781180
    11791181 // NOTE: Bound the dynamic environment.
    1182+ // XXX: The fresh environment is always not frozen.
    11801183 NPL::AddValueTo(ctx.GetRecordRef().GetMapRef(), static_cast<const
    11811184 DynamicVauHandler&>(vau).eformal, std::allocator_arg,
    11821185 ctx.get_allocator(), std::move(r_env));
    @@ -1881,24 +1884,23 @@
    18811884 return ResolveTerm(MakeResolvedParent, term);
    18821885 }
    18831886
    1884-//! \since build 899
    1885-pair<lref<Environment>, lref<const TokenValue>>
    1886-CheckToUndefine(TermNode& term, ContextNode& ctx)
    1887+//! \since build 961
    1888+YB_ATTR_nodiscard const TokenValue&
    1889+UndefineId(TermNode& term)
    18871890 {
    18881891 Retain(term);
    18891892 if(term.size() == 2)
    1890- {
    1891- const auto&
    1892- n(NPL::ResolveRegular<const TokenValue>(*std::next(term.begin())));
    1893- auto& env(ctx.GetRecordRef());
    1894-
    1895- if(!env.IsFrozen())
    1896- return {env, n};
    1897- throw TypeError("Cannot remove a variable in a frozen environment.");
    1898- }
    1899- else
    1900- ThrowInvalidSyntaxError(
    1901- "Expected exact one term as name to be undefined.");
    1893+ return NPL::ResolveRegular<const TokenValue>(*std::next(term.begin()));
    1894+ ThrowInvalidSyntaxError("Expected exact one term as name to be undefined.");
    1895+}
    1896+
    1897+//! \since build 961
    1898+YB_ATTR_nodiscard BindingMap&
    1899+FetchUndefineMapRef(ContextNode& ctx)
    1900+{
    1901+ TryRet(ctx.GetRecordRef().GetMapCheckedRef())
    1902+ CatchExpr(..., std::throw_with_nested(
    1903+ TypeError("Cannot remove a variable in a frozen environment.")))
    19021904 }
    19031905
    19041906 // NOTE: This assumes %f is called synchrnously.
    @@ -2243,14 +2245,14 @@
    22432245
    22442246 //! \since build 942
    22452247 //@{
    2246-using TermPrefixGuard = decltype(ystdex::unique_guard(ystdex::prefix_eraser<
    2247- TermNode::Container>(std::declval<TermNode::Container&>())));
    2248+using TermPrefixGuard
    2249+ = ystdex::unique_guard<ystdex::prefix_eraser<TermNode::Container>>;
    22482250
    22492251 YB_ATTR_nodiscard inline TermPrefixGuard
    22502252 GuardTermPrefix(TermNode::Container& con) ynothrow
    22512253 {
    2252- return
    2253- ystdex::unique_guard(ystdex::prefix_eraser<TermNode::Container>(con));
    2254+ return ystdex::make_unique_guard(
    2255+ ystdex::prefix_eraser<TermNode::Container>(con));
    22542256 }
    22552257
    22562258 //! \since build 947
    @@ -3563,12 +3565,11 @@
    35633565 ImplRet(HasImportsSigil(s) ? TokenValue(s.substr(1)) : s)
    35643566 //@}
    35653567
    3566-//! \since build 920
    3567-//@{
    35683568 #if false
    35693569 // NOTE: Lock a weak environment reference to a strong environment reference
    35703570 // accepting modifications later.
    3571-shared_ptr<Environment>
    3571+//! \since build 920
    3572+YB_ATTR_nodiscard pair<shared_ptr<Environment>, lref<BindingMap>>
    35723573 LockEnvironmentToModify(const EnvironmentReference& r_env)
    35733574 {
    35743575 auto p_env(r_env.Lock());
    @@ -3579,12 +3580,12 @@
    35793580 Environment::EnsureValid(p_env);
    35803581 // NOTE: Evaluate only once. Equivalent to %SymbolsToImports for more than
    35813582 // one calls of assignment with less overhead.
    3582- CheckFrozenEnvironment(p_env);
    3583- return p_env;
    3583+ return {p_env, p_env->GetMapCheckedRef()};
    35843584 }
    35853585 #endif
    35863586
    3587-inline void
    3587+//! \since build 961
    3588+YB_ATTR_nodiscard inline BindingMap&
    35883589 ShareEnvironmentToModify(const shared_ptr<Environment>& p_env)
    35893590 {
    35903591 // NOTE: This is like the type check in %SetWithNoRecursion, expecting
    @@ -3592,9 +3593,10 @@
    35923593 YAssert(p_env, "Invalid environment found.");
    35933594 // NOTE: Evaluate only once. Equivalent to %SymbolsToImports for more than
    35943595 // one calls of assignment with less overhead.
    3595- CheckFrozenEnvironment(p_env);
    3596-}
    3597-
    3596+ return p_env->GetMapCheckedRef();
    3597+}
    3598+
    3599+//! \since build 920
    35983600 void
    35993601 BindImports(const shared_ptr<Environment>& p_env, TermNode& term, ContextNode&
    36003602 ctx, const shared_ptr<Environment>& p_src, bool ref_symbols = {})
    @@ -3602,7 +3604,8 @@
    36023604 YAssert(IsList(term), "Invalid symbols term found.");
    36033605 if(IsBranch(term))
    36043606 {
    3605- ShareEnvironmentToModify(p_env);
    3607+ auto& m(ShareEnvironmentToModify(p_env));
    3608+
    36063609 for(auto& x : term)
    36073610 {
    36083611 auto& n(NPL::ResolveRegular<TokenValue>(x));
    @@ -3614,6 +3617,7 @@
    36143617 {
    36153618 auto& bound(*pr.first);
    36163619 TermNode nterm(bound.get_allocator());
    3620+ auto& env(NPL::Deref(p_env));
    36173621
    36183622 // XXX: As %EvaluateIdentifier and the loop body in the
    36193623 // applicative in %SymbolsToImports, with some optimizations
    @@ -3639,7 +3643,9 @@
    36393643 if(ref_symbols)
    36403644 n = Ensigil(n);
    36413645 EnsureValueTags(nterm.Tags);
    3642- BindSymbol(p_env, n, nterm);
    3646+ // XXX: Using explicit anchor pointer is more efficient.
    3647+ BindSymbol(m, n, nterm,
    3648+ EnvironmentReference(p_env, env.GetAnchorPtr()));
    36433649 }
    36443650 else
    36453651 TryExpr(throw BadIdentifier(s))
    @@ -3656,7 +3662,6 @@
    36563662 }
    36573663 }
    36583664 }
    3659-//@}
    36603665
    36613666 //! \since build 919
    36623667 // NOTE: See $2022-05 @ %Documentation::Workflow.
    @@ -4506,17 +4511,17 @@
    45064511 void
    45074512 Undefine(TermNode& term, ContextNode& ctx)
    45084513 {
    4509- const auto pr(CheckToUndefine(term, ctx));
    4510-
    4511- term.Value = pr.first.get().Remove(pr.second.get());
    4514+ const auto& id(UndefineId(term));
    4515+
    4516+ term.Value = Environment::Remove(FetchUndefineMapRef(ctx), id);
    45124517 }
    45134518
    45144519 void
    45154520 UndefineChecked(TermNode& term, ContextNode& ctx)
    45164521 {
    4517- const auto pr(CheckToUndefine(term, ctx));
    4518-
    4519- pr.first.get().RemoveChecked(pr.second.get());
    4522+ const auto& id(UndefineId(term));
    4523+
    4524+ Environment::RemoveChecked(FetchUndefineMapRef(ctx), id);
    45204525 }
    45214526
    45224527
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 YFramework/source/NPL/NPLA1Internals.h
    --- a/YFramework/source/NPL/NPLA1Internals.h Mon Nov 21 05:49:50 2022 +0800
    +++ b/YFramework/source/NPL/NPLA1Internals.h Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPLA1Internals.h
    1212 \ingroup NPL
    1313 \brief NPLA1 内部接口。
    14-\version r22808
    14+\version r22815
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 882
    1717 \par 创建时间:
    1818 2020-02-15 13:20:08 +0800
    1919 \par 修改时间:
    20- 2022-11-07 12:01 +0800
    20+ 2022-11-21 08:06 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 非公开模块名称:
    @@ -39,7 +39,8 @@
    3939 // IsIgnore, ParameterMismatch, IsPair, IsEmpty, IsList, NPL::AsTermNode,
    4040 // NPL::AsTermNodeTagged, ystdex::is_bitwise_swappable;
    4141 #include <ystdex/compose.hpp> // for ystdex::get_less;
    42-#include <ystdex/scope_guard.hpp> // for ystdex::unique_guard;
    42+#include <ystdex/scope_guard.hpp> // for ystdex::unique_guard,
    43+// ystdex::make_unique_guard;
    4344 #include <ystdex/utility.hpp> // for ystdex::exchange;
    4445 #include <ystdex/ref.hpp> // for std::reference_wrapper, std::ref,
    4546 // ystdex::unref;
    @@ -390,8 +391,8 @@
    390391 class TCOAction final
    391392 {
    392393 private:
    393- // NOTE: Specialized guard type (instead of using %ystdex::unique_guard) is
    394- // more efficient here.
    394+ // NOTE: Specialized guard type (instead of %ystdex::unique_guard) is more
    395+ // efficient here.
    395396 // XXX: More specialized guard type without %ystdex::unique_guard works, but
    396397 // it is acually less efficient, at least on x86_64-pc-linux G++ 10.2.
    397398 //! \since build 910
    @@ -435,8 +436,7 @@
    435436 //! \since build 946
    436437 mutable EnvironmentGuard env_guard;
    437438 //! \since build 909
    438- mutable decltype(ystdex::unique_guard(std::declval<GuardFunction>()))
    439- term_guard;
    439+ mutable ystdex::unique_guard<GuardFunction> term_guard;
    440440 /*!
    441441 \brief 可选的附加信息。
    442442 \since build 947
    @@ -454,7 +454,7 @@
    454454 : req_lift_result(lift ? 1 : 0), record_list(ctx.get_allocator()),
    455455 // NOTE: The external environment pointer is not saved in the guard yet,
    456456 // and it should be set later if any environment switch is needed.
    457- env_guard(ctx), term_guard(ystdex::unique_guard(GuardFunction{term}))
    457+ env_guard(ctx), term_guard(ystdex::make_unique_guard(GuardFunction{term}))
    458458 // XXX: Do not call %AssertValueTags on %term, as it can be (and is
    459459 // usually) a combiniation instead of the representation of some
    460460 // object language value.
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 doc/ChangeLog.V0.9.txt
    --- a/doc/ChangeLog.V0.9.txt Mon Nov 21 05:49:50 2022 +0800
    +++ b/doc/ChangeLog.V0.9.txt Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file ChangeLog.V0.9.txt
    1212 \ingroup Documentation
    1313 \brief 版本更新历史记录 - V0.9 。
    14-\version r12759
    14+\version r13039
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 800
    1717 \par 创建时间:
    1818 2020-10-12 17:19:23 +0800
    1919 \par 修改时间:
    20- 2022-11-21 05:12 +0800
    20+ 2022-11-28 08:41 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -34,6 +34,232 @@
    3434 (
    3535 / %YBase.YStandardEx $=
    3636 (
    37+ + DD '\ingroup grauds' @ "Doxygen comment" @ ("alias template \
    38+ %pun_ptr" @ %TypePun, ("class templates (guard, state_guard)",
    39+ "alias template %swap_guard") @ %ScopeGuard),
    40+ / %ScopeGuard $=
    41+ (
    42+ * "missing %_bNoThrow as the template argument" @ "return type"
    43+ @ "all 2 function templates %make_guard" $since b605,
    44+ (
    45+ / "function template %unique_guard" => "%make_unique_guard"
    46+ + "alias template %unique_guard";
    47+ / DLDI "simplified %make_unique_guard" ^ "%unique_guard"
    48+ ),
    49+ (
    50+ / "function template %unique_state_guard"
    51+ => "%make_unique_state_guard"
    52+ + "alias template %unique_state_guard";
    53+ / DLDI "simplified %make_unique_state_guard" ^ "%unique_state_guard"
    54+ );
    55+ / $dev $lib @ "all function templates %(make_guard, \
    56+ make_unique_guard, make_unique_state_guard)" $=
    57+ (
    58+ + 'YB_ATTR_nodiscard inline',
    59+ / $design $impl "all %_tState" => "%_tCond"
    60+ // To be consistent with %state_guard.
    61+ )
    62+ ),
    63+ + DLI 'YB_LIKELY' @ "success branch for overflow check" @ "member \
    64+ function %new_delete_resource_t::do_allocate" @ %MemoryResource
    65+ ),
    66+ * DD "outdated %Environment::DefaultResolve" @ %Documentation.NPL
    67+ $since 884,
    68+ / $forced DLDI $effective %(YBase.YStandardEx.(Cache, MemoryResource),
    69+ YFramework.('YCLib_(Win32)'.MinGW32, YSLib.Core.YApplication,
    70+ NPL.(NPLA1, NPLA1Forms, NPLA1Internals), Helper.HostRenderer))
    71+ $dep_from "%make_unique_guard" @ %ScopeGuard,
    72+ / %YFramework $=
    73+ (
    74+ * DLDI "missing header inclusinon %YBase.YStandardEx.Allocator"
    75+ @ %CHRLib.CharacterProcessing $since b861,
    76+ // This is the internal dependency which should not be used out of \
    77+ %YBase.
    78+ / %NPL $=
    79+ (
    80+ / %NPLA $=
    81+ (
    82+ / @ "class %Environment" $=
    83+ (
    84+ (
    85+ / "aliases %(BindingMap; NameResolution)"
    86+ >> "namespace %NPL";
    87+ / "function %LookupName" -> ("inline function" @ "%NPL")
    88+ // This can more efficient by inlining in the key paths.
    89+ ),
    90+ + "function %GetMapCheckedRef",
    91+ (
    92+ + "function %GetMapUncheckedRef";
    93+ // As old %GetMapRef.
    94+ / DLDI "static function %DefaultResolve"
    95+ $dep_from $forced "%LookupName",
    96+ $= (/ $impl ^ "%GetMapUncheckedRef");
    97+ / @ "function %GetMapRef" $dep_from ("function \
    98+ %SetupTraceDepth" @ %NPLA1, "native implementation"
    99+ @ "applicative 'copy-environment'"
    100+ @ "function %LoadGroundContext" @ %Dependency) $=
    101+ (
    102+ / 'ynothrow' -> 'ynothrowv';
    103+ + "assertion to ensure non-frozen environment";
    104+ + DD "'\pre' command" @ "Doxygen comment"
    105+ )
    106+ ),
    107+ / $re_add(b960) "function template %Bind"
    108+ -> "static function template",
    109+ / $re_add(b960) "functions %(Remove, RemoveChecked)"
    110+ -> "static functions",
    111+ / $re_add(b960) "functions %(Replace, ReplaceChecked)"
    112+ -> "static functions"
    113+ $= (/ DLDI $dep_from $forced ^ "%LookupName"),
    114+ / DLI "functions %(Remove, EnsureValid)"
    115+ -> "inline functions"
    116+ ),
    117+ / "checked against frozen environments" @ ("function template \
    118+ %EmplaceLeaf#3"; $comp "function templates %EmplaceLeaf#4")
    119+ ^ ($dep_from "%Environment::GetMapCheckedRef")
    120+ ~ "%Environment::GetMapRef",
    121+ / "parameter type 'const shared_ptr<Environment>&'" @ "member \
    122+ functions %ContextNode::(SwitchEnvironment, \
    123+ SwitchEnvironmentUnchecked)" -> 'shared_ptr<Environment>',
    124+ // This at least improves %EnvironmentSwitcher::operator().
    125+ / @ "class %EnvironmentSwitcher" $=
    126+ (
    127+ + DD '\ingroup functors' @ "Doxygen comment",
    128+ + 'ynothrow' @ "constructor",
    129+ + "function %Switch",
    130+ + "friend function %dismiss"
    131+ )
    132+ ),
    133+ / %NPLA1 $=
    134+ (
    135+ / "functions %(BindParameter, BindParameterWellFormed, \
    136+ BindSymbol)" $=
    137+ (
    138+ / DLI "simplified sigil handling initialization",
    139+ // The common paths for handling the sigil for \
    140+ non-trailing and trailing binding are merged as \
    141+ they are the same by propagating tags as \
    142+ non-trailing bindings since b951, after the \
    143+ subterms binding is specialized. This is a bit \
    144+ less inefficient, but the further simplificiation \
    145+ makes it a bit more efficient overall.
    146+ / DLDI $dep_from $forced ("%Environment::Bind" @ %NPLA)
    147+ $= (/ $dep_from "%Environment::BindingMap"),
    148+ (
    149+ + "overload with 'BindingMap&' and \
    150+ 'const EnvironmentReference&' parameters"
    151+ $dep_from ("%Environment::BindingMap" @ %NPLA)
    152+ $= (/ $impl ^ (($dep_from
    153+ "%Environment::GetMapCheckedRef",
    154+ $re_add(b959) "%Environment::GetAnchorPtr")
    155+ @ %NPLA));
    156+ / "simplified overload with 'Environment&' parameter with \
    157+ the additional check from %GetMapCheckedRef"
    158+ ^ "overload with 'BindingMap&' and \
    159+ 'const EnvironmentReference&' parameters"
    160+ ),
    161+ / $dev $build "worked around native GCC's cc1plus.exe \
    162+ out-of-memory problem \
    163+ 'NPL_Impl_NPLA1_BindParameter_ExpandLevel' defaulted \
    164+ to '0'" @ "platform %MinGW32"
    165+ ),
    166+ / "function %SetupTraceDepth"
    167+ $dep_from $forced "%Environment::LookupName"
    168+ $= (/ $impl ^ ("%Environment::GetMapUncheckedRef" @ %NPLA)),
    169+ / DLI "avoided redundant result copy" @ "function template \
    170+ %GetModuleFor" ^ ($dep_from "%EnvironmentSwitcher::Switch"
    171+ ~ "%ContextNode::ShareRecord") @ %NPLA,
    172+ / @ "function templates %(LoadModule, LoadModuleChecked)" $=
    173+ (
    174+ // As %EmplaceLeaf.
    175+ + "2 overloads with 'BidingMap&' or 'Environment&' as \
    176+ additional 1st parameter";
    177+ / "overload#3" ^ "overload#2";
    178+ + $comp "checked against frozen environments" @ "overload#3"
    179+ )
    180+ ),
    181+ / @ "namespace %Forms" @ %NPLA1Forms $=
    182+ (
    183+ / DLI @ "functions %(DefineWithRecursion, SetWithRecursion)" $=
    184+ (
    185+ / $design
    186+ ^ $dep_from $forced ("%Environment::Bind" @ %NPLA),
    187+ / "simplified initialization without redundant environment \
    188+ pointer copy"
    189+ ^ $dep_from ("%Environment::GetMapCheckedRef" @ %NPLA),
    190+ / $re_add(b959) DLI "optimized environment reference \
    191+ accesses for defining" ^ "%Environment::GetAnchorPtr",
    192+ / "simplified" !^ ("saving the term reference in the thunk",
    193+ ("%shared_ptr for terms or thunks"; "%ShareMoveTerm"))
    194+ @ 'NPL_Impl_NPLA1_Enable_Thunked'
    195+ ),
    196+ / DLDI "function %Undefine"
    197+ ^ $dep_from $forced ("%Environment::Remove" @ %NPLA),
    198+ / DLDI "function %UndefineChecked"
    199+ ^ $dep_from $forced ("%Environment::RemoveChecked" @ %NPLA),
    200+ / "threw nested %TypeError on non-frozen environment check \
    201+ failure" @ ("functions %(Undefine, UndefineChecked)",
    202+ "functions %(DefineLazy, DefineWithNoRecursion, \
    203+ DefineWithRecursion, SetWithNoRecursion, SetWithRecursion)"
    204+ ^ $dep_from ("%BindParameterWellFormed" @ %NPLA))
    205+ ^ $dep_from ("%Environment::GetMapCheckedRef" @ %NPLA),
    206+ / $re_add(b959) DLI "optimized environment reference accesses \
    207+ for imports" $effective @ "functions %(Provide, \
    208+ ProvideLet, Import, ImportRef)"
    209+ ^ "%Environment::GetAnchorPtr"
    210+ ),
    211+ / "namespace %Forms" @ %Dependency $=
    212+ (
    213+ / DLDI "native implementation" @ ("applicative 'get-module'"
    214+ @ "function %LoadModule_std_io", "applicative %require"
    215+ @ "function %LoadModule_std_modules")
    216+ $dep_from $forced ("%Environment::Bind" @ %NPLA),
    217+ / @ "function %LoadGroundContext" $=
    218+ (
    219+ * "possible invalid reference values in the result"
    220+ @ "alternative derivation" @ "applicative %assq"
    221+ $since b943
    222+ $= (/ $impl ^ 'rest%' ~ 'rest&'),
    223+ / DLI "primitive bindings" ^ "%BindingMap",
    224+ // This is a bit inefficient, but better for the \
    225+ change after %EmplaceLeaf because there are no \
    226+ redundant checks.
    227+ / DLDI "native implementation" @ "applicative \
    228+ 'copy-environment'" ^ ($dep_from
    229+ "%Environment::GetMapUncheckedRef"
    230+ ~ "%Environment::GetMapRef") @ %NPLA
    231+ ),
    232+ * $re_add(b928) "wrong result" @ "native implemenation"
    233+ @ "applicative 'unregister-requirement!'"
    234+ @ "function %LoadModule_std_modules" $since b923
    235+ // This was a bug because of the consistency with the \
    236+ derivation.
    237+ $= (/ $impl "returned %ValueToken::Unspecified"),
    238+ / DLDI @ "function %LoadModule_SHBuild" $=
    239+ (
    240+ / "returned the value of the call to %CallBinaryAs"
    241+ @ "applicative %SHBuild_EchoVar",
    242+ / "applicative %SHBuild_EchoVar"
    243+ $dep_from $forced ("%Environment::LookupName" @ %NPLA)
    244+ $= (/ $impl
    245+ ^ ("%Environment::GetMapUncheckedRef" @ %NPLA))
    246+ ),
    247+ / DLDI "function %LoadStandardContext"
    248+ ^ $dep_from ("%LoadModuleChecked#1" @ %NPLA1),
    249+ + DD "'\pre' command" @ "Doxygen comment" @ "all functions"
    250+ $dep_from ("%Environment::GetMapRef" @ %NPLA)
    251+ )
    252+ ),
    253+ + DLDI 'YB_PURE' @ "member function %HostRenderer::Wait"
    254+ @ %Helper.HostRenderer
    255+ // To eliminate G++ 12.1 warning: [-Wsuggest-attribute=pure].
    256+ )
    257+),
    258+
    259+b960
    260+(
    261+ / %YBase.YStandardEx $=
    262+ (
    37263 / @ "trait %tuple_size" %Apply $=
    38264 (
    39265 * "missing deailed code inclusion when %std::tuple_size is not used"
    @@ -396,7 +622,7 @@
    396622 refactored with some additional checks.
    397623 )
    398624 ),
    399- / $forced DLDI $dep_from ("%Environment::Frozen" @ %NPL.NPLA)
    625+ / DLDI $dep_from $forced ("%Environment::Frozen" @ %NPL.NPLA)
    400626 $effective (("function %MoveResolved" @ %NPLA, "function template \
    401627 %GetModuleFor" @ %NPLA1, "functions %Forms::('Define*', \
    402628 'SetWith*', 'Import*', %Undefine)" @ %NPLA1Forms, ("native \
    @@ -545,7 +771,7 @@
    545771 / "simplified internal unwrapping"
    546772 ^ "%FormContextHandler::IsOperative"
    547773 ~ "%FormContextHandler::GetWrappingCount",
    548- / DLI "optimized local reference accesses"
    774+ / DLI "optimized local environment reference accesses"
    549775 ^ "%Environment::GetAnchorPtr" $effective
    550776 @ "functions %(AccL, AccR, FoldR1, Map1)"
    551777 ),
    @@ -967,8 +1193,8 @@
    9671193 + "function %GetFrameRecordList",
    9681194 (
    9691195 + "function %AddOperator";
    970- / $forced "2 function overloads %Attach"
    971- -> "function %Attach" $dep_from "%FrameRecord",
    1196+ / "2 function overloads %Attach"
    1197+ -> "function %Attach" $dep_from $forced "%FrameRecord",
    9721198 ),
    9731199 (
    9741200 - "data member %OperatorName"
    @@ -1343,9 +1569,9 @@
    13431569 / $forced DLI "constructors" $dep_from "%REPLContext"
    13441570 )
    13451571 ),
    1346- / $forced "1st parameter type 'REPLContext&'"
    1572+ / "1st parameter type 'REPLContext&'"
    13471573 @ "function template %TryLoadSource"
    1348- -> 'const GlobalState&' $dep_from "%REPLContext",
    1574+ -> 'const GlobalState&' $dep_from $forced "%REPLContext",
    13491575 + "function template %Perform"
    13501576 $dep_from ("%Perform" @ "GlobalState"),
    13511577 / "data members %(EvaluationPasses, EvaluateLeaf, \
    @@ -1353,12 +1579,11 @@
    13531579 >> "class %GlobalState" $dep_to "pass lifting";
    13541580 // The guard pass which has no context parameter is not \
    13551581 moved.
    1356- / $forced "simplified constructors and friend function %swap"
    1357- @ "class %ContextState" $dep_from "pass lifting",
    1358- / $forced "1st parameter type 'ContextState&'"
    1359- @ "function %SetupDefaultInterpretation"
    1360- -> 'GlobalState&' $dep_from ("class %REPLContext",
    1361- "pass lifting")
    1582+ / "simplified constructors and friend function %swap"
    1583+ @ "class %ContextState" $dep_from $forced "pass lifting",
    1584+ / "1st parameter type 'ContextState&'" @ "function \
    1585+ %SetupDefaultInterpretation" -> 'GlobalState&'
    1586+ $dep_from $forced ("class %REPLContext", "pass lifting")
    13621587 // This is required by both %GlobalState constructor and \
    13631588 the passes lifted to the global state.
    13641589 ),
    @@ -1623,8 +1848,8 @@
    16231848 / DLI %ShlExplorer $=
    16241849 (
    16251850 / $re_add(b942) $design "header inclusion %Functional" -> %Bind,
    1626- / $forced "NPL test entry for test subitem 2"
    1627- @ "constructor %ShlExplorer" $dep_from ("%TestNPL" @ %Shells)
    1851+ / "NPL test entry for test subitem 2" @ "constructor %ShlExplorer"
    1852+ $dep_from $forced ("%TestNPL" @ %Shells)
    16281853 ^ $dep_from (("%Environment::DefaultOutputStream",
    16291854 "%YF_Helper_Environment_UseStdout")
    16301855 @ %YFramework.Helper.Environment)
    @@ -2895,8 +3120,8 @@
    28953120 (
    28963121 / DLI "%LDFLAGS_LOWBASE_" => "%LDFLAGS_WKRD_",
    28973122 / "disabled workaround" @ "platform %MinGW64",
    2898- + $forced "workaround for mingw-w64-x86_64-binutils 2.38-3"
    2899- ^ '-fuse-ld=lld' $dep_from "MinGW64 toolchain update"
    3123+ + "workaround for mingw-w64-x86_64-binutils 2.38-3"
    3124+ ^ '-fuse-ld=lld' $dep_from $forced "MinGW64 toolchain update"
    29003125 // This is also faster.
    29013126 ),
    29023127 + "selected '-flto=jobserver' over '-flto=auto' for G++ only on \
    @@ -3667,20 +3892,20 @@
    36673892 + $dev $lib 'YB_ATTR_nodiscard YB_PURE' @ ("all 2 functions \
    36683893 %(begin, end)", "functions %(get, list, size)")
    36693894 + 'ynothrow' @ "all 2 functions %(begin, end)",
    3670- / $forced DLDI "removed internal checks"
    3671- @ "%recent_used_list::shrink",
    36723895 / @ "data member %flush" $=
    36733896 (
    36743897 / "supported empty state" ^ "%optional_function"
    36753898 ~ "%function" $dep_to "optional flush",
    36763899 + DD "commands" @ "Doxygen comment"
    36773900 ),
    3678- / "internal maximum elements checks" $=
    3679- (
    3680- / $comp $forced DLDI $dep_from "optional flush"
    3681- $dep_from "%recent_used_list::shrink",
    3682- / DLI "prevended copy of %flush" ^ "%std::ref"
    3683- ),
    3901+ / DLI "internal maximum used elements check" $=
    3902+ (
    3903+ / $comp $design $dep_from "optional flush"
    3904+ $dep_to "optional flush for internal check",
    3905+ / "prevented copy of data member %flush" ^ "%std::ref"
    3906+ ),
    3907+ / DLDI "removed internal checks" @ "%recent_used_list::shrink"
    3908+ $forced $dep_from "optional flush for internal check",
    36843909 / @ "function template %emplace with parameter of \
    36853910 'const key_type&'" $=
    36863911 (
    @@ -3761,7 +3986,7 @@
    37613986 -> "2 function templates %RegisterFormHandler",
    37623987 / DLI @ "functions %(RegisterForm, RegisterStrict)" $=
    37633988 (
    3764- / $forced $design $dep_from "%RegisterHandler"
    3989+ / $design $dep_from $forced "%RegisterHandler",
    37653990 + 'YB_ATTR_always_inline'
    37663991 ),
    37673992 / DLDI "leaf handling" @ "functions %(MatchParameter, \
    @@ -3791,9 +4016,9 @@
    37914016 ("%ystdex::prefix_eraser" @ %YBase.YStandardEx.Container),
    37924017 / DLDI "newline" @ "alternative derivation" @ "appliative \
    37934018 'env-empty?'" @ "function %LoadModule_std_system",
    3794- + DD ("'\pre' command", "'\exception' command") @ "Doxygen comment"
    3795- @ "functions %(LoadModule_std_io, LoadModule_std_system, \
    3796- LoadModule_std_modules)",
    4019+ + DD ("'\pre' command", "'\exception' command")
    4020+ @ "Doxygen comment" @ "functions %(LoadModule_std_io, \
    4021+ LoadModule_std_system, LoadModule_std_modules)",
    37974022 / "forwareded function parameter"
    37984023 @ "function templates %(InvokeIn, GetModuleFor)",
    37994024 + "pamameter pack as invocation arguments" @ "function templates \
    @@ -6016,10 +6241,10 @@
    60166241 ParseLeafWithSourceInformation)" @ %NPLA1
    60176242 !^ "%IsNPLAExtendedLiteral"
    60186243 ),
    6019- / $forced DLDI @ "%floor_lb" @ %YBase.YStandardEx.CStandardInteger
    6244+ / DLDI @ "%floor_lb" @ %YBase.YStandardEx.CStandardInteger
    60206245 @ %YSLib.Core.ValueNode ^ $dep_from %YBase.YStandardEx.Bit,
    6021- / $forced DLDI @ "%byte_order" @ %YBase.YStandardEx.CStandardInteger
    6022- @ %CHRLib.Encoding ^ $dep_from %YBase.YStandardEx.Bit
    6246+ / DLDI @ "%byte_order" @ %YBase.YStandardEx.CStandardInteger
    6247+ @ %CHRLib.Encoding ^ $dep_from $forced %YBase.YStandardEx.Bit
    60236248 )
    60246249 ),
    60256250
    @@ -6847,6 +7072,10 @@
    68477072 $comp "alternative derivation" @ "applicative %puts")
    68487073 @ "function %LoadModule_std_io" $since b925
    68497074 $= (/ $impl ^ "%ReduceReturnUnspecified")
    7075+ // This is different to b922 where the similar change is \
    7076+ not a bug then. This is buggy because 'newline' \
    7077+ returns '#inert' and it is required by \
    7078+ %NPL.Documentation since b858 to be the same here.
    68507079 ),
    68517080 / %NPLA1 $=
    68527081 (
    @@ -7744,7 +7973,7 @@
    77447973 different to that in the derivations.
    77457974 / "simplified exception thrown for insufficient subterms"
    77467975 @ "functions %(Vau, VauRef, Lambda, LambdaRef, WVau, \
    7747- WVauRef, VauWithEnvironment, VauWithEnvrionmentRef, \
    7976+ WVauRef, VauWithEnvironment, VauWithEnvironmentRef, \
    77487977 LambdaWithEnvironment, LambdaWithEnvironmentRef, \
    77497978 WVauWithEnvironment, WVauWithEnvironmentRef)"
    77507979 ^ $dep_from ("%CheckVariadicArity" @ %NPLA1);
    @@ -8534,7 +8763,7 @@
    85348763 / @ "namespace %Forms" @ %NPLA1Forms $=
    85358764 (
    85368765 / $lib @ "functions %(Let, LetRef, LetWithEnvironment, \
    8537- LetWithEnvrionmentRef, LetAsterisk, LetAsteriskRef, \
    8766+ LetWithEnvironmentRef, LetAsterisk, LetAsteriskRef, \
    85388767 LetRec, LetRecRef)" $=
    85398768 (
    85408769 / "minor adjustment" @ "assertion",
    @@ -8547,7 +8776,7 @@
    85478776 ),
    85488777 / DLI ^ "allocator" @ ("setting the environment"
    85498778 $effective @ "functions %(LetWithEnvironment, \
    8550- LetWithEnvrionmentRef, GetCurrentEnvironment, \
    8779+ LetWithEnvironmentRef, GetCurrentEnvironment, \
    85518780 LockCurrentEnvironment, MakeEnvironment)",
    85528781 "list prepareation" $effective @ ("functions \
    85538782 %(FoldR1, Map1, ListExtractFirst, ListExtractRest)",
    @@ -8565,7 +8794,7 @@
    85658794 / DLI "optimized parent environment initialization"
    85668795 @ "functions %(VauWithEnvironment, \
    85678796 VauWithEnvironmentRef, LetWithEnvironment, \
    8568- LetWithEnvrionmentRef)" !^ "%ValueObject::emplace",
    8797+ LetWithEnvironmentRef)" !^ "%ValueObject::emplace",
    85698798 / DLDI "removed redundant %std::move" @ "function %AccL",
    85708799 // Also to eliminate Clang++ warning: [-Wpessimizing-move].
    85718800 - DLI 'YB_FLATTEN' @ "internal implementation"
    @@ -9538,11 +9767,11 @@
    95389767 @ "function %MakeEncapsulationType"
    95399768 $dep_to "removal of tail environment check",
    95409769 (
    9541- / $forced DLI "simplified combiner subobject reference \
    9542- construction" $dep_from "simplified combiner subobjct \
    9543- reference construction" $effective @ "functions (AccL, \
    9544- AccR, Apply, FoldR1, ForwardFirst, Map1, Unwrap, Wrap, \
    9545- WrapOnce, WrapOnceRef, WrapRef)";
    9770+ / DLI "simplified combiner subobject reference construction"
    9771+ $dep_from $forced "simplified combiner subobjct reference \
    9772+ construction" $effective @ "functions (AccL, AccR, Apply, \
    9773+ FoldR1, ForwardFirst, Map1, Unwrap, Wrap, WrapOnce, \
    9774+ WrapOnceRef, WrapRef)";
    95469775 - "context parameter" @ "functions %(Unwrap, Wrap, WrapOnce, \
    95479776 WrapOnceRef, WrapRef)"
    95489777 ),
    @@ -10210,13 +10439,13 @@
    1021010439 (
    1021110440 + "applicative 'check-parent'"
    1021210441 ^ $dep_from ("%CheckParent" @ %NPLA1Forms);
    10213- / $forced "all uses of applicative 'check-environment' for \
    10214- applicative derivation of function name with '/e'"
    10215- -> 'check-parent' $dep_from ("%(VauWithEnvironment, \
    10442+ / "all uses of applicative 'check-environment' for applicative \
    10443+ derivation of function name with '/e'" -> 'check-parent'
    10444+ $dep_from $forced ("%(VauWithEnvironment, \
    1021610445 VauWithEnvironmentRef)" @ %NPLA1Forms)
    1021710446 ),
    10218- / $forced "alternative derivation" @ "applicative \
    10219- 'check-environment'" $dep_from ("%(VauWithEnvironment, \
    10447+ / "alternative derivation" @ "applicative 'check-environment'"
    10448+ $dep_from $forced ("%(VauWithEnvironment, \
    1022010449 VauWithEnvironmentRef)" @ %NPLA1Forms)
    1022110450 $= (/ $impl ^ 'eval%' ~ '$vau/e%'),
    1022210451 / "simplified derivation" @ "applicative 'derive-environment'"
    @@ -12105,8 +12334,9 @@
    1210512334 // To avoid unexpected copies.
    1210612335 + 'const' @ "parameter" @ "constructor#1"
    1210712336 ),
    12108- / $forced DLDI "simplified (member function %Partition::ChangeDir, \
    12109- constructor %DirState)" $dep_from "DEntry constructor split",
    12337+ / DLDI "simplified (member function %Partition::ChangeDir, \
    12338+ constructor %DirState)"
    12339+ $dep_from $forced "DEntry constructor split",
    1211012340 + DLD "2 'nullptr' at end of %devoptab_t object"
    1211112341 $dep_from "devkitARM update"
    1211212342 // To eliminate G++ warning: [-Wmissing-field-initializers].
    @@ -12317,7 +12547,7 @@
    1231712547 ),
    1231812548 / @ "%SHBuild-YSLib-build.txt" $=
    1231912549 (
    12320- + $forced "libFreeImaged support" $dep_from "libFreeImaged",
    12550+ + "libFreeImaged support" $dep_from $forced "libFreeImaged",
    1232112551 / "checked %(SHBuild_UseDebug, SHBuild_UseRelease)"
    1232212552 @ "3rdparty library installation",
    1232312553 + $re_add(b885) $re_ex(b897) "'-gdwarf-3' as workaround after '-Og'"
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 doc/NPL.txt
    --- a/doc/NPL.txt Mon Nov 21 05:49:50 2022 +0800
    +++ b/doc/NPL.txt Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file NPL.txt
    1212 \ingroup Documentation
    1313 \brief NPL 规范和实现规格说明。
    14-\version r29946
    14+\version r30039
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 304
    1717 \par 创建时间:
    1818 2012-04-25 10:34:20 +0800
    1919 \par 修改时间:
    20- 2022-11-15 07:31 +0800
    20+ 2022-11-28 06:53 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -946,7 +946,7 @@
    946946 除非另行指定,本节中的以下描述提供允许派生实现提供保证或假设的机制,并非要求。派生实现可附加规则改变此处对一等对象的保证或性质。
    947947
    948948 @4.2.2 同一性关联扩展性质:
    949-NPL 中,对象的同一性关联的属性包括明确开始和终止的生存期。
    949+NPL 中,对象的同一性关联的属性包括明确开始和终止的生存期(@4.1) 。
    950950 推论:对象是表示能明确生存期开始和终止的实体。
    951951 一等对象之间总是能准确地判断影响程序语义的同一性(@4.1.4.1) :仅当能证明不改变可观察行为(@4.1.3) 时,两个一等对象的同一性可能未指定。
    952952 通过一等对象关联同一性,允许语言提供依赖同一性差异的特性。
    @@ -1214,7 +1214,7 @@
    12141214 这包含对象对其它对象具有所有权的对象的情形,如一些语言(包括宿主语言)的对象可指定具有子对象(subobject) 。后者统称为内部对象(internal object) 。
    12151215 为维护数据结构的边界,满足最小依赖原则(@1.5.4.3) ,数据结构作为宿主语言对象,其中的内部对象应具有以下性质:
    12161216 数据结构对内部对象具有整体所有权。
    1217-推论:数据结构不引用自身。
    1217+推论:仅考虑具有所有权的引用时,数据结构不引用自身。
    12181218 以上性质是逻辑上的普遍要求。具体的一些语言中,可能因为通过只通过外部所有者代理的方式的访问而无法在实现上保证,但这种逻辑关系仍应存在。
    12191219 不具有所有权的对象不是内部对象。
    12201220
    @@ -1230,11 +1230,23 @@
    12301230 这些问题的根本原因是所有权没有被足够早地显式区分。更进一步地,不附加外部所有者的普遍的循环引用要求不能直接区分,否则可通过定义某种规则从中判断出不循环的(acyclic) 的引用链的子集而不构成循环引用(实际上若能保证复杂度(@1.2.4) 上限,这也是消除循环引用的主要方式)。
    12311231 因此,除非允许语言隐含不由用户程序指定的所有者,保留循环引用无法解决这些问题;甚至即便允许这样的所有者,也无法彻底解决实现开销的问题(而需要更多地依赖语言实现系统外部的假定减缓这些开销),仍然一定程度上不符合以上提及的所有原则的要求。
    12321232
    1233-@4.2.4.3 自引用数据结构相关的一般实现:
    1233+@4.2.4.3 一般引用数据结构的一般实现:
    12341234 没有理由表明通过任意对象支持循环引用是自引用(self-referencing) 数据结构的唯一实现方式,不论使用自引用数据结构的普遍程度。
    12351235 自引用数据结构可通过在更高的抽象层次上编码,转换为由用户(而不是语言实现)指定明确的外部所有者的形式消除上述所有问题,同时对外部保证同等的功能正确性(@1.5.3.1) 。
    12361236 典型地,在不支持循环引用的对象构造中保存无所有权的一等实体引用其它实体,构造出不蕴含所有权的仅以特定对象构成的循环引用,而在外部引入对象作为所有这些构成引用的对象的所有者。这也是 C 和 C++ 等语言惯用的实现图(graph) 的数据结构的合理方式。
    1237-此外,无限数据结构不一定需要自引用数据结构表示。并且,即使使用自引用数据结构,也只适合直接表示其中的具有周期性的无限结构。使用生成序列替代无限数据结构的直接表示则没有周期性要求和限制。
    1237+在这个基础上,一般的自引用或循环引用需要的附加指涉仍然可通过添加不蕴含所有权语义的引用解决。这些引用是弱引用(weak reference) ,区分于具有所有权的引用是强引用(strong reference) 。
    1238+强引用总是可转换为弱引用使用。弱引用通过解析(resolve) 取得强引用。解析可能失败,以允许弱引用指涉已经不存在的对象,而避免影响对象生存期(@4.1) 和所有权关系。
    1239+
    1240+@4.2.4.4 无限数据结构:
    1241+具有潜在的无限构造的数据结构不一定需要自引用数据结构表示。
    1242+并且,即使使用自引用数据结构,也只适合直接表示其中的具有周期性的无限结构。
    1243+使用生成序列替代无限数据结构的直接表示则没有周期性要求和限制。
    1244+**注释**
    1245+数学中出现一些常见的无限构造,如实数和循环的连分数,在实际实现具有的计算资源可承载计算复杂度(主要是空间复杂度)的限制下,不能被直接地完整表示。
    1246+相对地,这种构造通常使用一种元语言的构造方式,即潜无限(potential infinity) ,而避免直接的实无限(actual infinity) 表示的资源限制问题。
    1247+数学使用的表示在语法上可能提供一些约定以利用这些构造。
    1248+使用潜无限是分析学的标准方法。其它方法,如非标准分析,对实无限的实体直接建模,其表示也是有限的。
    1249+这些通过有限的表示代替无限构造的实体的方式在通用语言中应当仍适用。
    12381250
    12391251 @4.2.5 其它普遍性质:
    12401252 更一般地,基于和 [RnRK] 中讨论类似的其它实用性理由,定义一等对象的准则和设计决策还应满足以下几点:
    @@ -2238,7 +2250,7 @@
    22382250 对象语言中的环境以表示环境记录的引用的一等对象(@4.2.1) 表示,称为环境引用。
    22392251 环境引用共享环境对象的所有权(@4.2.2.3) 。
    22402252 按值传递(@4.4.6.5) 环境引用不引起其中所有的对象被复制。另见引用(@4.2.3) 。
    2241-根据所有权管理机制的不同,环境引用包括环境强引用(strong reference) 和环境弱引用(weak reference) 。
    2253+根据所有权管理机制的不同,环境引用包括环境强引用(@4.2.4.3) 和环境弱引用(@4.2.4.3) 。
    22422254 引入环境弱引用作为一般的引用机制,且仅在必要时使用环境强引用,以避免过于容易引入循环引用引起强内存泄漏(@5.6.4.1) ,符合 @1.5.5.2 。
    22432255 传递环境引用不引起被引用的环境对象被复制。
    22442256 **原理**
    @@ -3132,7 +3144,7 @@
    31323144 分配器分配资源,用于提供供实现指定的宿主语言的存储资源的来源。这和对象语言的存储资源(@5.6) 管理机制类似,但不保证对应。
    31333145 分配器隐含在被映射的类型中,不显式出现在对象语言。
    31343146 NPLA 中的分配器具有可和 TermNode::allocator_type 互相隐式转换的类型,接受 YSLib::pmr::memory_resource 类型的存储资源。
    3135-这些分配器通常来自 TermNode(@6.2) 、ContextNode(@6.11.3) 的存储资源以及 Environment::BindingMap(@6.11.1.1) 的分配器,用于这些类型和 NPL::EnvironmentList(@6.11.1.2) 以及其它被运行时使用相同存储资源管理的项中的对象的初始化。
    3147+这些分配器通常来自 TermNode(@6.2) 、ContextNode(@6.11.3) 的存储资源以及 NPL::BindingMap(@6.11.1.1) 的分配器,用于这些类型和 NPL::EnvironmentList(@6.11.1.1) 以及其它被运行时使用相同存储资源管理的项中的对象的初始化。
    31363148 NPLA 和派生实现的本机实现(@5.3) 应保证分配器的使用符合以下小节的约定。
    31373149
    31383150 @6.4.1.1 相等性要求:
    @@ -3156,7 +3168,7 @@
    31563168 由 C++ 分配器要求,使用相等的分配器效果一致。但除非另行指定,若需要指定分配器,仍按以下规则(自上而下优先)尝试确定用于复制初始化的分配器的来源:
    31573169 引起表示对象语言的值(@6.3) 的 TermNode 对象创建时,若分配器必须依赖操作中的一个或若干个已知分配器相等的、表示对象语言的值的 TermNode 对象,后者中的任一个 TermNode 对象提供分配器。
    31583170 引起 TermNode 对象创建时,若这个对象被一个或多个其它 TermNode 对象共同所有,它的分配器以表示关联所有者的 TermNode 类型的值提供。
    3159- 引起 Environment 对象创建时,需要的分配器由关联的 Environment::BindingMap(@6.11.1.1) 的分配器提供。
    3171+ 引起 Environment 对象创建时,需要的分配器由关联的 NPL::BindingMap(@6.11.1.2) 的分配器提供。
    31603172 引起满足 allocator-aware 的容器要求的对象(至少支持迭代器和对其元素具有所有权)的元素的创建时,由符合容器要求的分配器提供。
    31613173 引起 ValueObject 的目标对象(@6.2) 通过复制初始化创建时,若需分配器且可通过源对象取得分配器,则分配器来自此对象。
    31623174 创建 ContextNode 时:
    @@ -3421,7 +3433,7 @@
    34213433 预期作为表达式或一等对象的表示(@6.3.4) 的宿主值时,这些值应非空,这可通过接口约束被检查(@6.3) 。
    34223434 NPL::EnvironmentReference 值通过锁定后取得的 shared_ptr<Environment> 值确定是否为空值。
    34233435 因为当前实现不保证这些值在多线程环境下蕴含同步操作,存在数据竞争时行为未定义,可忽略并发访问冲突。
    3424-NPL::EnvironmentReference 可使用空 shared_ptr<Environment> 值初始化,此时锚对象指针为空指针值;否则,锚对象指针和指向的环境(@6.11.1.1) 的关联的值共享。
    3436+NPL::EnvironmentReference 可使用空 shared_ptr<Environment> 值初始化,此时锚对象指针为空指针值;否则,锚对象指针和指向的环境(@6.11.1.2) 的关联的值共享。
    34253437 NPL::EnvironmentReference 也可显式分别初始化 weak_ptr<Environment> 和锚对象指针,此时不需要附加空指针检查,在确定环境存在时更高效。但调用者应确保锚对象关联的引用和 weak_ptr<Environment> 引用的环境共享,否则行为未定义。
    34263438 **注释**
    34273439 主要使用方式参见环境相关的宿主类型(@6.11.1.3) 和上下文数据结构(@6.11.3) 。
    @@ -3873,7 +3885,7 @@
    38733885 NPLA 提供维护程序运行状态的数据结构的接口,包括环境、上下文和相关的其它 API 。
    38743886
    38753887 @6.11.1 环境数据结构:
    3876-NPL 中定义的类 Environment(@6.11.1.1) 表示环境记录(@5.7.1) 。
    3888+NPL 中定义的类 Environment(@6.11.1.2) 表示环境记录(@5.7.1) 。
    38773889 环境对象(@5.7.1) 以类 Environment 相关的类型表示。
    38783890 显式的数据结构直接支持求值环境是一等环境(@5.7) 。
    38793891 TermNode 对象在名称绑定映射中表示被绑定对象(@5.7) 。
    @@ -3890,8 +3902,15 @@
    38903902 不同宿主值类型具有不同的所有权。作为一等对象的环境引用的一般表达式值中,应根据是否需要具有所有权区分使用这些宿主类型的环境引用。
    38913903 和 Kernel 类似,默认的重定向算法默认使用 DFS(Depth-First Search ,深度优先搜索)遍历目标。
    38923904
    3893-@6.11.1.1 环境类:
    3894-类 Environment 中,指定变量绑定的名称绑定映射(@6.11.1) 类型为 Environment::BindingMap 。
    3905+@6.11.1.1 环境和变量绑定相关 API :
    3906+类 NPL::EnvironmentBase 是 Environment 和 NPL::EnvironmentReference 的基类。
    3907+NPL::EnvironmentList 是 NPL::vector<ValueObject> 的别名,表示一个环境列表,作为父环境(@5.7) 时可用于递归重定向(@4.3.3) 。
    3908+NPL::BindingMap
    3909+NPL::NameResolution
    3910+函数 LookupName 在绑定集合中查找(一般作为局部变量的)标识符指定的名称,实现名称查找(@4.3.3) 。输入字符串指定(假定名称验证已通过的)名称。
    3911+
    3912+@6.11.1.2 环境类:
    3913+类 Environment 中,指定变量绑定的名称绑定映射(@6.11.1) 类型为 NPL::BindingMap 。
    38953914 类 Environment 提供父环境(@5.7) 以及基本的名称解析(@4.3.3) 等操作的接口。其中的操作可被针对特定的环境对象重新设置。
    38963915 类 Environment 包含以下相关的数据成员:
    38973916 Parent :作为可在运行时确定类型的父环境引用,用于重定向(@4.3.3) 算法的实现。
    @@ -3899,39 +3918,32 @@
    38993918 成员函数 IsOrphan 判断是否为孤立的环境,即锚对象(@6.8.2) 未被外部引用。
    39003919 成员函数 IsFrozen
    39013920 成员函数 GetAnchorPtr 取锚对象指针(@6.7.2) 。
    3902-成员函数 GetMap 取名称绑定映射的引用:类型为 Environment::BindingMap 的变量绑定容器,实现变量名称到表示被绑定对象的映射(@6.11.1) 。
    3921+成员函数 GetMap 取名称绑定映射的引用:类型为 NPL::BindingMap 的变量绑定容器,实现变量名称到表示被绑定对象的映射(@6.11.1) 。
    39033922 成员函数 GetMapRef 取名称绑定映射的可变引用。
    39043923 成员函数 Define 、Redefine 和 Remove 修改上下文中的值。
    39053924 静态成员函数 Define 和 DefineChecked 在绑定映射中添加定义。后者在定义已存在时抛出异常。
    39063925 静态成员函数 EnsureValid 提供失败时抛出异常的环境强引用空值检查(@6.8.1) 。
    39073926 成员函数 Freeze
    3908-成员函数 LookupName 在绑定集合中查找(一般作为局部变量的)标识符指定的名称,实现名称查找(@4.3.3) 。输入字符串指定(假定名称验证已通过的)名称。
    3909-成员函数 Remove 和 RemoveChecked 以字符串为标识符在指定上下文移除定义。后者在定义不存在时抛出异常。
    3910-成员函数 Replace 和 ReplaceChecked 以字符串为标识符在指定上下文的名称查找结果中替换定义。后者在定义不存在时抛出异常。
    3927+静态成员函数 Remove 和 RemoveChecked 以字符串为标识符在指定上下文移除定义。后者在定义不存在时抛出异常。
    3928+静态成员函数 Replace 和 ReplaceChecked 以字符串为标识符在指定上下文的名称查找结果中替换定义。后者在定义不存在时抛出异常。
    39113929 成员函数 Unfreeze
    39123930
    3913-@6.11.1.2 环境和变量绑定相关类型:
    3914-NPL::EnvironmentList 是 NPL::vector<ValueObject> 的别名,表示一个环境列表,作为父环境(@5.7) 时可用于递归重定向(@4.3.3) 。
    3915-Environment::DefaultResolve(@6.11.1.1) 中的重定向(@4.3.3) 依次检查如下之一的重定向目标的宿主值(@6.3.5) 类型:
    3916-NPL::EnvironmentList ;
    3917-shared_ptr<Environment> ;
    3918-NPL::EnvironmentReference 。
    3919-实现可提供其它宿主类型,如 observer_ptr<Environment> ,用于内部实现而不要求所有使用环境的操作支持。
    3920-派生实现可提供其它公开的宿主类型。
    3921-
    39223931 @6.11.1.3 环境引用相关类型和检查:
    39233932 类型 shared_ptr<Environment> 和类 NPL::EnvironmentReference(作为中间值另见 @6.8.2 )是环境强引用和环境强引用(@5.7.2) 的宿主类型(@5.3.1) 。
    39243933 访问环境的 API 可使用非空的环境引用值引用对象,或空的引用值指定不存在环境对象。
    3925-使用可能具有这些值的代码需要对空值进行检查。因为这些空值不出现在对象语言,一般通过 Environment::ThrowForInvalidValue(@6.11.1.1) 抛出 std::invalid_argument 而非 NPL 异常(@6.5) 。
    3934+使用可能具有这些值的代码需要对空值进行检查。因为这些空值不出现在对象语言,一般通过 Environment::ThrowForInvalidValue(@6.11.1.2) 抛出 std::invalid_argument 而非 NPL 异常(@6.5) 。
    39263935 使用环境弱引用可避免非预期的所有权(@4.2.2.3) 关系构成循环引用(@5.2) 。
    39273936 当前支持循环引用检查的上下文有:
    3928-Environment::DefaultResolve(@6.11.1.1) 重定向父环境(@5.7) ;
    3937+ContextNode::DefaultResolve(@6.11.3.1) 重定向父环境(@5.7) ;
    39293938 以引用的环境作为动态环境(@4.6.1.2) 创建 vau 抽象(@8.4.5) 且创建的对象不对环境有所有权。
    39303939 因为循环引用是对象语言的未定义行为,检查循环引用失败抛出 std::bad_weak_ptr 而非 NPL 异常(@6.5) 。
    3931-对象语言中支持环境引用的宿主值类型是 Environment::DefaultResolve(@6.11.1.1) 中的重定向目标的宿主值类型(@6.11.1.2) 中公开的类型,即:
    3940+对象语言中支持环境引用的宿主值类型是 ContextNode::DefaultResolve 中的重定向(@4.3.3) 目标的宿主值(@6.3.5) 的类型中公开的类型(@6.11.1.1) ,即:
    3941+NPL::EnvironmentList ;
    39323942 shared_ptr<Environment> ;
    3933-NPL::EnvironmentReference ;
    3934-派生实现定义的提供明确支持的其它类型。
    3943+NPL::EnvironmentReference 。
    3944+重定向依次检查这些类型。
    3945+实现可提供其它宿主类型,如 observer_ptr<Environment> ,用于内部实现而不要求所有使用环境的操作支持。
    3946+派生实现的其它重定向可定义提供明确支持的其它类型,包括公开的宿主值的类型。
    39353947 除 shared_ptr<Environment> 的 use_count 的结果外,环境的引用计数具体值是实现细节,不保证具有明确含义的稳定的结果。
    39363948
    39373949 @6.11.2 上下文相关的规约函数类型别名:
    @@ -3944,8 +3956,8 @@
    39443956 上下文(@4.6) 使用类 ContextNode 表示。
    39453957 ContextNode 对象保存上下文相关的公共状态。
    39463958 上下文的公共状态包括当前处理的环境的强引用(@5.7.2) ,指定活动记录中当前的处理的帧(@4.5.3.4) ,表示对象语言中对应当前处理的帧的当前环境(@5.7.3) 。
    3947-环境强引用决定上下文对环境具有共享所有权(@5.6) ,通过环境对象的引用可以取指向它的引用(@6.11.1.1) 。
    3948-只使用上下文中包含的当前环境时,可使用 ContextNode(@6.11.3.1) 和 Environment(@6.11.1.1) 的成员访问环境的数据。
    3959+环境强引用决定上下文对环境具有共享所有权(@5.6) ,通过环境对象的引用可以取指向它的引用(@6.11.1.2) 。
    3960+只使用上下文中包含的当前环境时,可使用 ContextNode(@6.11.3.1) 和 Environment(@6.11.1.2) 的成员访问环境的数据。
    39493961 需要上下文时,一般使用现有(通过规约函数的参数得到的)上下文,可能替换和重置状态;或通过现有上下文和环境创建新的上下文。
    39503962 上下文支持设置对应规约迭代(@6.10.4) 中对应的规约动作(action) ,保存特定的当前动作(current action) 和若干后继的定界动作(delimited actions) 组成当前动作序列(current action sequence) 。
    39513963 其中,当前动作和后继的动作分别表示元语言中处理当前和后继的求值上下文(@4.4.8) 中的操作。
    @@ -4022,7 +4034,7 @@
    40224034 NPL::AssignParentWeak
    40234035
    40244036 @6.11.4.4 上下文切换:
    4025-NPL::EnvironmentSwitcher 类型用于切换上下文(@6.11.3.1) 中的当前环境(@6.11.3) 。
    4037+仿函数 NPL::EnvironmentSwitcher 和 NPL::EnvironmentExchanger 用于切换上下文(@6.11.3.1) 中的当前环境(@6.11.3) 。
    40264038
    40274039 @6.12 异步规约(asynchronous reduction) :
    40284040 直接风格(direct style) 的语言实现利用宿主语言的函数调用实现图规约(@6.2) ,满足规约函数(@6.10.5) 的调用包含子项的规约,即同步规约(synchronized reduction) 。
    @@ -4510,12 +4522,14 @@
    45104522 @7.1.5 互操作约定:
    45114523 非 NPLA1 实现提供的类型的宿主 == 操作不要求支持嵌套调用安全(@5.4.2) 。
    45124524 作为嵌套调用安全的约定(@6.1.4) 的扩展,若存在 == 操作不支持嵌套调用安全的类型,具体类型由派生实现的定义。
    4525+对象语言操作和互操作不修改对象语言中已经可见的一等环境的父环境。
    45134526 **原理**
    45144527 调用假定异步规约不存在的实现允许使用直接风格(@6.12) 代替异步调用(@6.11.3) ,一般能显著节约调用开销,但对非特定类型,这不保证提供(在宿主语言无法提供的)嵌套调用安全保证。
    45154528 本机实现的 == 因为宿主语言的接口缺乏一般异步调用支持,不提供在宿主语言无法提供的嵌套调用安全保证。
    45164529 由于宿主语言的接口限制,要求本机实现的 == 操作使用 NPLA1 异步规约(@6.12) 需要显著增加接口设计的复杂性和实现开销,因此在此不作要求。
    45174530 为满足嵌套调用安全保证,实现需要避免异步调用,或自行使用其它的异步调用机制。
    45184531 NPLA1 中提供的类型仍需要支持嵌套调用安全,以满足嵌套调用安全的约定中的要求。
    4532+避免修改已在对象语言可访问的一定对象的父环境符合同 [RnRK] 的环境封装性对对象语言的要求。这允许实现假定仅在有限的上下文中父环境可修改,而减少优化实现的难度。
    45194533
    45204534 @7.2 NPLA1 中间值:
    45214535 NPLA1 扩展了 NPLA 的中间值(@6.8) 机制。
    @@ -5070,8 +5084,8 @@
    50705084 若不存在标记字符 @ ,则:
    50715085 若操作数为可转移的(@5.8.3.6) 对象的引用值,则被绑定对象是按以下规则初始化的蕴含隐含的引用折叠(@7.7.3.4) 的引用值:
    50725086 存在标记字符时,使用引用推断规则(@7.7.3.4) ,被绑定对象是操作数直接初始化的项引用,其标签由操作数的(引用值)的标签决定:
    5073- 当存在标记字符 & 、绑定非结尾列表且作为操作数的引用值的标签包含唯一引用标签(@6.2.2) 时,其中包含绑定临时对象标签(@7.7.3.2) 。
    5074- **注释** 使用 % 可避免操作数中的唯一引用标签在被绑定对象中蕴含临时对象标签的行为。
    5087+ 当存在标记字符 & 、绑定非结尾序列且作为操作数的引用值的标签包含唯一引用标签(@6.2.2) 时,其中包含绑定临时对象标签(@7.7.3.2) 。
    5088+ **注释** 使用 % 可避免操作数中的唯一引用标签在被绑定对象中蕴含临时对象标签。
    50755089 否则,被绑定对象的标签和作为操作数的引用值的标签相同。
    50765090 否则,被绑定对象是操作数复制初始化(复制或转移)的值。
    50775091 否则,若操作数标签(@7.7.3.6) 指定可修改的临时值或有标记字符 % 时的临时值,操作数是可转移的非引用值,被绑定的对象是临时对象。
    @@ -5112,27 +5126,38 @@
    51125126 绑定的默认行为对引用值特殊处理,是为了满足 G1b(@1.5.5.1) ,而不是像某些语言(如 ISO C 和 [Rust] )仅通过内建的机制提供特定左值上下文(lvalue context) 。
    51135127 绑定的默认行为不使用析构性转移(@6.3.6) 的操作(类似 [Rust] 的设计),原因是考虑到绑定的副作用影响操作数(即便因为对象被销毁而不一定是修改操作)和破坏幂等性(@4.1) (特别是指定过程调用的形式参数时,参见过程抽象(@8.4.5) )违反易预测性原则(@1.5.5.2) 。
    51145128 为允许调用宿主对象的转移构造函数(@5.8.2.3) ,限制复制消除。初始化引用之外的参数创建也不是 ISO C++17 约定要求消除复制的上下文。
    5115-作为操作数的引用值中的唯一引用可能蕴含绑定临时对象标签(@7.7.3.2) ,这使绑定为变量的消亡值可能以名称表达式求值结果(不会是消亡值)的引用值访问时,能和其它引用值区分。提供这种设计的理由是:
    5116- 以消亡值初始化一个变量,通常需要使变量指称消亡值引用的资源,而不仅仅是表示即将被转移的消亡值自身。
    5117- 和表示即将被转移的资源的消亡值不同,具有临时对象标签的引用值通过右值初始化,相当于宿主语言中的右值引用,典型地表示能被转移的资源。
    5118- 消亡值应和纯右值在初始化时在此的作用一致。
    5119- 直接求值名称表达式往往比其它替代方式更直接高效,但结果不具有唯一引用标签(@7.7.3.2) ,而使用临时对象标签没有这个问题。
    5120- 转发操作对消亡值和绑定到变量的消亡值通过名称表达式求值得到的结果都可以作为被转发的右值一并处理,这种设计能简化一般的使用。
    5129+作为操作数的引用值中的唯一引用在使用 & 引用标记字符时可同时蕴含绑定临时对象标签(@7.7.3.2) ,这使绑定为变量的消亡值可能以名称表达式求值结果(不会是消亡值)的引用值访问时,能和其它引用值区分。提供这种设计的理由是:
    5130+ 以下两种涉及消亡值的资源访问可被统一:
    5131+ 直接访问消亡值表达式。
    5132+ 消亡值表示即将被转移的资源。
    5133+ 以消亡值初始化一个带有 & 引用标记字符的非结尾序列变量,并以这个变量的名称作为表达式进行访问。
    5134+ 这通常需要使变量指称消亡值引用的资源,而不仅仅是表示即将被转移的消亡值自身。
    5135+ 具有临时对象标签的引用值通过右值初始化,相当于宿主语言中的右值引用,典型地表示能被转移的资源(而不一定需要立刻被转移)。
    5136+ 初始化变量同时转移资源,相当于宿主语言中复制初始化时调用转移构造函数转移操作数的资源到变量(对象或绑定到临时对象的引用),使之表示转移后的资源。
    5137+ 尽管值类别可能不同,这两种表达式都可以表示蕴含被转移的资源的对象。
    5138+ 直接求值名称表达式往往比其它替代方式更直接高效,但结果总是左值(@7.8.2.3) 而不具有唯一引用标签(@7.7.3.2) ,而使用临时对象标签允许在求值的结果中被保留。
    5139+ 引用值(而不是临时对象引用(@5.8.3.3) )中的临时对象标签不影响值类别。
    5140+ 类似地,在宿主语言中,和值类别不同的状态以右值引用类型声明的形式编码在类型系统中。
    5141+ 引用值中的临时对象标签接近宿主语言中转发引用(@7.7.3.2) 蕴含的静态类型。
    5142+ 但和宿主语言不同,临时对象标签能随初始化后的引用值跨过程传递,而无需多次转发并在每次推导引用类型。
    5143+ 基于上述规则,对象语言中特定的转发操作处理可统一的方式处理两种表达式以转移资源。这种设计能简化一般的使用。
    51215144 引用值支持临时对象标签对有效的转发对象应用子的实现是必要的。
    51225145 通过标签,转发对象操作可避免总是从实际的操作数提取值类别的需要,允许作为应用子而非操作子(@4.5.3.2) 。
    5123- 如果不使用临时对象标签,也需要其它值编码和值类别不同的状态以和消亡值区分。
    5124- 其它大多数操作需要转发资源时只需要使用转发对象操作,可安全忽略引用值中的临时对象标签。
    5125- 类似地,在宿主语言中,和值类别不同的状态以右值引用类型声明的形式编码在类型系统中。
    5126- 右值引用类型的变量作为左值(而不是消亡值)被访问,在大多数操作中没有和其它左值区分的意义。
    5146+ 若不使用临时对象标签,则需要其它方式编码和值类别不同的状态以和消亡值区分,例如宿主语言的静态类型信息。
    5147+ 这会增加语言规则的复杂性。
    5148+ 需要转发资源时,一般只需要使用转发对象操作;其它情形可安全忽略引用值中的临时对象标签。
    5149+ 类似地,在宿主语言中,编码在类型系统中的状态在特定上下文中用于实现完美转发(@5.8.2.2) 。
    5150+ 宿主语言中,右值引用类型的变量作为左值(而不是消亡值)被访问,在大多数操作中没有和其它左值区分的意义。
    51275151 在 std::forward 这样需要区分引用类型的转发操作(实例是一个函数,而不是宏)中,右值引用类型在局部是有意义的。
    51285152 但是这仍然存在限制:因为没有跨过程传递的状态支持,明确具体类型还是需要程序显式指定 std::forward 的类型参数(或者宏),而不是 C++ 函数(应用子)的方式实现。
    5129- 通过唯一引用标签仍可区分一个具有临时对象标签的引用值以消亡值还是纯右值初始化。
    5130- 可使用不同的引用标记字符避免使引用值引入非预期的引用标签。
    5153+ 消亡值应和纯右值在初始化其它变量时转移资源的作用一致,对应唯一引用标签和临时对象标签的相似处理。
    5154+ 通过唯一引用标签仍可区分一个具有临时对象标签的引用值以消亡值还是纯右值初始化。
    5155+ 可使用 & 以外的引用标记字符避免这里的行为而被初始化的被绑定对象(引用值)中引入非预期的临时对象标签。
    51315156 绑定结尾序列和非结尾序列的非递归绑定规则略有不同。
    51325157 特别地,除非被绑定对象是引用值,引用标记字符(不论是否存在)同时被作用到作为一等对象的元素上。这是因为:
    51335158 此时,需要把操作数作为一等对象进行分解,使用引用标记字符或者不使用引用标记字符不破坏其它语义规则。
    5134- 和非引用结尾序列相比,使有序对的两个元素在初始化时的规则不同,但这具有合理性,因为:
    5135- 有序对作为(非真)列表时,地位不是相同的。
    5159+ 和非引用结尾序列相比,这使有序对的两个元素在初始化时的规则不同,但这具有合理性,因为:
    5160+ 有序对作为(非真)列表时,结尾元素和其它元素的地位不是相同的。
    51365161 有序对的元素在 NPLA 对象表示中即已不对称,地位不可交换。
    51375162 这种设计简化了一些重要的派生实现,例如 list 应用子(@11.4.1) 。
    51385163 若不依赖无引用标记字符影响被初始化的元素的规则,使用基本派生操作(@11.4.1) 中在 list 前定义的操作,list 的派生近似(和内部表示实现细节相关仍不确保完全正确):
    @@ -5147,6 +5172,10 @@
    51475172 $def! list wrap ($vau (.x) #ignore move! x);
    51485173 为创建子对象引用时避免被引用对象的复制,不复制被引用对象的子项(即便被引用对象可能具有非正规表示(@6.3.9) ),且使用非引用值间接值作为被绑定对象的值数据成员。
    51495174 和引用值的间接访问可被配置运行时检查(@6.1.2.1) 不同,对通过非引用值间接值的访问不被检查(@6.4.6.2) 。但和引用值的间接访问类似,这种情形已违反内存安全(@5.6.3) ,且可能引起宿主语言的未定义行为(@5.4) 。因此,不另行保存子项。
    5175+ 蕴含绑定临时对象标签的规则不适用绑定结尾序列中的元素,因为:
    5176+ 结尾序列的元素不具有名称,而不是通过绑定创建的能作为名称访问表达式的变量。访问元素需通过其它方式(如对象语言中的子对象访问操作(@9.8.2.1) ),方法和结果不唯一(如可能具有不同的值类别,可能即时转移资源等),不具有和消亡值的统一性。
    5177+ 引入附加的临时对象标签容易引起非预期的转移。除子对象访问时可能发生的直接转移(通常较明确),随引用值跨过程传递的临时对象标签在之后可能继续引起其它转移。因为首先通过子对象而非名称表达式访问,这种转移的存在性在创建变量绑定的位置通常不显然而无法预知,容易误用。
    5178+ 一旦不需要附加的临时对象标签,去除标签而得到引用值通常是较为困难的,需要对象语言提供特设的操作或绑定新的对象(尽管引入临时对象标签可能同样困难)。
    51505179 **注释**
    51515180 引用折叠的结果满足不可修改引用属性的传播性质(@5.8.3.3) 。其它情形也应满足 NPLA1 间接值使用规则(@7.1.3) 。因此,仅有使用标记字符 % 进行消除引用时,被消除的引用值的不可修改属性被忽略。
    51525181 绑定临时对象外不和 [ISO C++] 一样可能延长右值类类型子对象的生存期(@5.6.6) 。
    @@ -5748,7 +5777,7 @@
    57485777 因为维护资源(@7.10.5) 的需要,NPLA1 规范求值算法(@7.8.2) 不处理 WHNF(@4.4.5.1) 以外的操作数且允许宿主类型的调用(@7.6.1.2) 处理 WHNF 的第一项。
    57495778 当前在 TCO 动作中被分配的临时对象(@5.8.5) 的操作都针对作为 WHNF 的第一项的合并子(@4.5.3.2) ,其中合并子的相等关系由相等性(@8.4.5.5) 或不影响可观察行为的其它宿主实现提供的 == 操作确定。
    57505779 由相等性(@8.4.5.5) ,捕获不同环境的 vau 合并子不相等;不论是否具有相等的外部表示(@1.2.4) 和来源,其右值不会被直接操作压缩(@7.10.4) 避免多次添加而被 TCO ;若其嵌套调用因为捕获不同的存在引用关系的环境,不支持其它形式的 TCO ;因此,不支持 PTC 。
    5751-实现依赖 Environment::IsOrphan(@6.11.1.1) 等判断确保内存安全(@5.6.3) 。
    5780+实现依赖 Environment::IsOrphan(@6.11.1.2) 等判断确保内存安全(@5.6.3) 。
    57525781 忽略非平凡析构判断(假定所有对象都可平凡析构),允许移除可证明不被继续引用(@5.10) (如被总是新的环境隐藏)的变量。
    57535782 被移除的对象生存期提前结束(@5.10) 。
    57545783 除被隐藏的变量被单独移除外,若一个活动记录帧(环境)内存在任意不满足可证明幂等的操作的情形,整个帧的剩余部分都被保持存储(因为不支持对 NPL::TermReference(@6.8.3) 分别保存引用计数)。
    @@ -6239,7 +6268,8 @@
    62396268 @9 NPLA1 核心语言设计:
    62406269 NPL 是独立设计的,但其派生语言和其它一些语言有类似之处;这些语言和 NPL 方言之间并不具有派生关系。但为简化描述,部分地引用这些现有语言规范(@1.2.1.2) 中的描述,仅强调其中的不同。
    62416270 NPLA1 符合 NPL 和 NPLA 的语言规则,其实现环境(@1.2.4) 还应提供本章起的其它程序接口。
    6242-NPLA1 支持和宿主语言的互操作,一些接口处理的值可约定宿主类型(@5.3.1) 。但这些类型不一定在对象语言层次上稳定,可能在之后的版本变化。稳定性由具体实现提供的附加规则(若存在)保证。
    6271+NPLA1 支持和宿主语言的互操作,其实现应满足互操作(@7.1.5) 。
    6272+互操作中的一些接口处理的值可约定宿主类型(@5.3.1) 。但这些类型不一定在对象语言层次上稳定,可能在之后的版本变化。稳定性由具体实现提供的附加规则(若存在)保证。
    62436273 NPLA1 和 Kernel 语言(即 [RnRK] )的特性设计(如 vau(@4.5.2.5) 和作为一等对象(@4.1) 的环境表达过程抽象(@8.4.5) )有很多类似之处,因此许多概念是通用的;但从设计哲学(@1.5) 到本章介绍的各个细节(如默认求值规则(@9.7.1) )都存在深刻的差异。
    62446274 部分名称指定的操作和 [RnRS] 或 klisp (http://klisp.org/docs/index.html) 指定的类似。
    62456275 以下章节主要介绍和 Kernel 约定不同的设计。各节的通用约定不再在之后的各个接口单独说明。
    @@ -6903,7 +6933,7 @@
    69036933
    69046934 @9.8.5 等价比较:
    69056935 和 Kernel 不同,一些类型的对象若可修改(@9.8.3)(如环境(@9.9.3) ),不保证 eq? 和其它等价谓词(@11.3.2) 的比较结果等价。
    6906-但是,基于环境类(@6.11.1.1) 已约定宿主值的类型,在对象语言中传递环境引用(@6.11.1) 不改变环境的这些等价性。
    6936+但是,基于环境类(@6.11.1.2) 已约定宿主值的类型(@6.11.1.3) ,在对象语言中传递环境引用(@6.11.1) 不改变环境的这些等价性。
    69076937 为了满足不依赖引用的一等对象(@4.1) ,区分引用和被引用的对象都作为一等实体,这是必要的。
    69086938 一般地,谓词 eq? 用于判断两个参数对象的同一性(@4.1) 。
    69096939
    @@ -6961,7 +6991,7 @@
    69616991 而求值当前设计中等价的:
    69626992 $def! f $lambda/e (() get-current-environment)
    69636993 不引起未定义行为。
    6964-同时,若访问悬空引用(@9.4.3.2) ,实现可利用 NPL::EnvironmentReference(@6.11.1.1) 在闭包中对引用进行检查,使用户无需像 lock-current-environment 一样特别关照 get-current-environment 引起的风险。
    6994+同时,若访问悬空引用(@9.4.3.2) ,实现可利用 NPL::EnvironmentReference(@6.11.1.2) 在闭包中对引用进行检查,使用户无需像 lock-current-environment 一样特别关照 get-current-environment 引起的风险。
    69656995
    69666996 @9.9.1.2 自引用(self-referencing) 数据结构:
    69676997 因为不支持循环引用(@9.9.1.1) ,不支持引用自身的自引用数据结构。
    @@ -7026,7 +7056,7 @@
    70267056 **注释**
    70277057 不满足环境稳定性的环境的被绑定对象可能被修改。若这个对象是一个环境的唯一强引用,则对应的环境对象在替换为其它值时被销毁。
    70287058 特别地,应注意使用函数时引入父环境的生存期。
    7029-当前实现对环境引用(@6.11.1) 是 NPL::EnvironmentReference(@6.11.1.1) 的情形提供一定程度的检查(@6.1.2.1) ,这通过引用环境时检查 NPL::EnvironmentReference 中的弱引用是否可被实现。
    7059+当前实现对环境引用(@6.11.1) 是 NPL::EnvironmentReference(@6.11.1.2) 的情形提供一定程度的检查(@6.1.2.1) ,这通过引用环境时检查 NPL::EnvironmentReference 中的弱引用是否可被实现。
    70307060 特别地,这可针对在 vau 抽象(@8.4.5) 中捕获的静态环境。
    70317061 如以下程序(假设 + 是可接受 2 个整数值的应用子)引起无效引用错误(抛出 NPL::InvalidReference 异常(@6.5) ):
    70327062 $def! addn ($lambda (a) ($lambda (n) + a n)); (addn 1) 2;
    @@ -8221,7 +8251,7 @@
    82218251 () copy-environment :递归复制当前环境。当前忽略父环境(@9.9.3) 中的环境列表(@6.11.1) 。
    82228252 结果是新创建的环境,具有宿主值类型 shared_ptr<Environment> 。
    82238253 使用类似 @6.11.1 的 DFS 搜索操作数的父环境和绑定的对象,若非环境则直接复制值,否则创建环境并递归使用 DFS 复制值。
    8224-当前只支持复制具有 shared_ptr<Environment> 和 EnvrionmentReference 的宿主值的环境,其它对象直接视为非环境对象。
    8254+当前只支持复制具有 shared_ptr<Environment> 和 EnvironmentReference 的宿主值的环境,其它对象直接视为非环境对象。
    82258255 警告:这个函数仅用于测试时示例构造环境,通常不应被用户程序使用,且可能在未来移除。未确定环境宿主值时可引起未定义行为。
    82268256 freeze-environment! <environment> :冻结环境。
    82278257 这个操作处理操作数指定的一等环境。对隐藏环境(@9.9.3.1) 初始化时的相同操作参见冻结操作(@9.9.3.9) 。
    @@ -8234,7 +8264,7 @@
    82348264 weaken-environment <environment> :使用环境强引用创建环境弱引用(@6.11.1) 。
    82358265 检查参数类型是环境强引用,若失败则引起类型错误(@9.5.4.1) 。
    82368266 **原理** 因为 NPLA1 需要精确控制所有权而不依赖 GC(@5.2) ,这可用于派生实现某些操作(如 $sequence(@11.4.1) 必要的)。
    8237-**注释** 实现检查操作数的宿主值类型(@6.11.1.1) 是 shared_ptr<Environment> ,结果的宿主类型 NPL::EnvironmentReference 。
    8267+**注释** 实现检查操作数的宿主值类型(@6.11.1.2) 是 shared_ptr<Environment> ,结果的宿主类型 NPL::EnvironmentReference 。
    82388268 $def! <definiend> <body> :修改当前环境中的绑定。
    82398269 类似 Kernel 的 $define! ,但满足绑定构造(@9.7.3) 的约定。
    82408270 和 Kernel 的 $define! 不同,$def! 和 $defrec! 在求值 <body> 后,进行类型检查(@9.5.4.1) ,确保环境没有被冻结后添加绑定。
    @@ -8615,15 +8645,17 @@
    86158645 参数是同 [RnRK] 的 map 操作可接受的列表参数或空列表,但排除非真列表(@6.2.1) 。
    86168646 若参数是空列表,结果是 #f 。
    86178647 assq <object> <lists> :取关联列表中和参数的引用相同的元素。
    8618-以 eq? 依次判断第二参数指定的列表中的第一个元素是否和第一参数指定的元素等价。
    8619-若不存在相等的元素,结果为空列表右值;否则是同 first% 访问得到的等价的列表的值。
    8648+第二参数指定的列表中的元素应为有序对。
    8649+以 eq? 依次判断第二参数指定的列表中的每个元素的第一个元素是否和第一参数指定的元素等价。
    8650+若不存在等价的元素,结果为空列表右值;否则是同 first% 访问得到的等价的列表的值。
    86208651 **原理** 和 Kernel 不同,NPLA1 只支持真列表(@9.9.4) ,因此可以要求顺序,提供关于等价的元素的更强的保证。
    86218652 **原理** 尽管和 Kernel 相同而和 Scheme 不同,<test> 支持非布尔类型的值(@11.3.3) ,不存在元素时的 #f 结果可以简化比较,但和 [RnRK] 的原理类似,这不利于提供清晰的类型错误,且没有如空列表值这样作为求值算法的特殊值的自然推论。使用空列表值和传统 Lisp 也一致。
    86228653 **注释** 类似 Kernel 的 assq ,但保证顺序且转发参数。
    86238654 **注释** 类似 Scheme 的 assq ,但失败的结果不是 #f 。
    86248655 assv <object> <lists> :取关联列表中和参数的值相等的元素。
    8656+第二参数指定的列表中的元素应为有序对。
    86258657 以 eqv? 依次判断第二参数指定的列表中的第一个元素是否和第一参数指定的元素等价。
    8626-若不存在相等的元素,结果为空列表右值;否则是同 first% 访问得到的等价的列表的值。
    8658+若不存在等价的元素,结果为空列表右值;否则是同 first% 访问得到的等价的列表的值。
    86278659 **原理** 参见 assq 。
    86288660 **注释** 类似 Kernel 的 assoc ,但使用 eqv? 而不是 equal? ,保证顺序且转发参数。
    86298661 **注释** 和 Scheme 的 assv 类似,但失败的结果不是 #f 。
    diff -r 6aa0c02516b0 -r 04558a9cb7d4 doc/YBase.txt
    --- a/doc/YBase.txt Mon Nov 21 05:49:50 2022 +0800
    +++ b/doc/YBase.txt Mon Nov 28 12:55:23 2022 +0800
    @@ -11,13 +11,13 @@
    1111 /*! \file YBase.txt
    1212 \ingroup Documentation
    1313 \brief YBase 说明。
    14-\version r1981
    14+\version r1984
    1515 \author FrankHB <frankhb1989@gmail.com>
    1616 \since build 305
    1717 \par 创建时间:
    1818 2012-04-29 17:11:42 +0800
    1919 \par 修改时间:
    20- 2022-10-01 12:57 +0800
    20+ 2022-11-21 05:55 +0800
    2121 \par 文本编码:
    2222 UTF-8
    2323 \par 模块名称:
    @@ -327,10 +327,10 @@
    327327 "iterator_op.hpp" 依赖 "range.hpp" 和 "deref_op.hpp" ;
    328328 "exception.h" 依赖 <libdefect/exception.h> 、<stdexcept> 和 <system_error> ;
    329329 "typeindex.h" 依赖 "typeinfo.h" ;
    330-"type_traits.hpp" 依赖 "type_inspection.hpp" 、"integral_constant.hpp" 、"invoke.hpp" 和 "swap.hpp" ;
    330+"type_traits.hpp" 依赖 "type_inspection.hpp" 、"integral_constant.hpp" 、"invoke.hpp" 和 "swap.hpp" ;
    331331 "utility.hpp" 依赖 "swap.hpp" 、"enum.hpp" 和 "integer_sequence.hpp" ;
    332332 "tuple.hpp" 依赖 "apply.hpp" ;
    333-"memory.hpp" 依赖 "pointer.hpp" ;
    333+"memory.hpp" 依赖 "pointer.hpp" 和 "allocator.hpp" ;
    334334 "functional.hpp" 依赖 "invoke.hpp" 、"ref.hpp" 、"functor.hpp" 、"bind.hpp" 、"function.hpp" 和 "hash.hpp";
    335335 "string.hpp" 、"array.hpp" 、"string_view" 、"list.hpp" 、"map.hpp" 和 "set.hpp" 依赖 "range.hpp" ;
    336336 "iterator.hpp" 依赖 "iterator_op.hpp" 。
    @@ -379,7 +379,7 @@
    379379 "apply.hpp" 依赖 "invoke.hpp" ;
    380380 "tuple.hpp" 依赖 "apply.hpp" ;
    381381 "allocator.hpp" 内部依赖 "type_op.hpp" 和 "pointer.hpp" ;
    382-"memory.hpp" 依赖 "pointer.hpp"(蕴含内部依赖 "iterator_op.hpp" );
    382+"memory.hpp" 依赖 "pointer.hpp"(蕴含内部依赖 "iterator_op.hpp" )和 "allocator.hpp" ;
    383383 "memory.hpp" 内部依赖 "placement.hpp" 和 "ref.hpp" ;
    384384 "memory_resource.h" 内部依赖 "memory.hpp" ;
    385385 "hash.hpp" 和 "mixin.hpp" 依赖 "tuple.hpp" ;
    Show on old repository browser