• R/O
  • SSH

YSLib: Commit

The YSLib project - main repository


Commit MetaInfo

Revisión05c8e54ed1bb24bc8db8fff212ab5a59e7f6ccdc (tree)
Tiempo2022-09-05 22:43:00
AutorFrankHB <frankhb1989@gmai...>
CommiterFrankHB

Log Message

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

Cambiar Resumen

Diferencia incremental

diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/DS/source/Helper/DSMain.cpp
--- a/YFramework/DS/source/Helper/DSMain.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/DS/source/Helper/DSMain.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2010-2017, 2021 FrankHB.
2+ © 2010-2017, 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
@@ -12,13 +12,13 @@
1212 \ingroup Helper
1313 \ingroup DS
1414 \brief DS 平台框架。
15-\version r3241
15+\version r3243
1616 \author FrankHB <frankhb1989@gmail.com>
1717 \since build 296
1818 \par 创建时间:
1919 2012-03-25 12:48:49 +0800
2020 \par 修改时间:
21- 2021-12-29 01:23 +0800
21+ 2022-09-03 22:31 +0800
2222 \par 文本编码:
2323 UTF-8
2424 \par 模块名称:
@@ -42,6 +42,7 @@
4242 #endif
4343 #include YFM_YCLib_Debug
4444 #include YFM_Helper_Environment
45+#include YFM_YSLib_UI_YGUI // for UI::FetchGUIState;
4546
4647 namespace YSLib
4748 {
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/include/Helper/Environment.h
--- a/YFramework/include/Helper/Environment.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/include/Helper/Environment.h Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2013-2016, 2020 FrankHB.
2+ © 2013-2016, 2020, 2022 FrankHB.
33
44 This file is part of the YSLib project, and may only be used,
55 modified, and distributed under the terms of the YSLib project
@@ -11,13 +11,13 @@
1111 /*! \file Environment.h
1212 \ingroup Helper
1313 \brief 环境。
14-\version r1072
14+\version r1146
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 521
1717 \par 创建时间:
1818 2013-02-08 01:28:03 +0800
1919 \par 修改时间:
20- 2020-12-24 12:05 +0800
20+ 2022-09-05 08:41 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -31,6 +31,24 @@
3131 #include "YModules.h"
3232 #include YFM_Helper_YGlobal
3333 #include YFM_YSLib_Core_ValueNode // for ValueNode;
34+#if YF_Hosted
35+# if YCL_Win32 && defined(NDEBUG)
36+// XXX: Use Win32 subsystem.
37+# define YF_Helper_Environment_UseStdout false
38+# else
39+# define YF_Helper_Environment_UseStdout true
40+# endif
41+# define YF_Helper_Environment_NPL_UseBacktrace true
42+# define YF_Helper_Environment_NPL_UseSourceInfo true
43+#else
44+# define YF_Helper_Environment_UseStdout false
45+# define YF_Helper_Environment_NPL_UseBacktrace false
46+# define YF_Helper_Environment_NPL_UseSourceInfo false
47+#endif
48+#include YFM_YSLib_Core_YShellDefinition // for ostringstream;
49+#include YFM_NPL_NPLA1 // for NPL::A1::REPLContext, NPL::TermNode,
50+// NPL::ContextNode, NPL::A1::InvokeIn, NPL::Environment,
51+// NPL::A1::EnvironmentGuard, NPL::ToReducer, NPL::A1::ReduceOnce;
3452
3553 namespace YSLib
3654 {
@@ -57,7 +75,11 @@
5775
5876 /*!
5977 \brief 应用程序环境。
78+\warning 非线程安全。
6079 \since build 378
80+
81+应用程序实例使用的环境。
82+通常只支持一个实例,但没有检查。
6183 */
6284 class YF_API Environment
6385 {
@@ -67,7 +89,19 @@
6789 \since build 688
6890 */
6991 ValueNode Root{};
92+ //! \since build 954
93+ //@{
94+ ostringstream DefaultOutputStream;
95+ NPL::A1::REPLContext Context;
96+ NPL::TermNode Term{Context.Allocator};
7097
98+private:
99+# if YF_Helper_Environment_NPL_UseBacktrace
100+ NPL::ContextNode::ReducerSequence backtrace{Context.Allocator};
101+# endif
102+ //@}
103+
104+public:
71105 /*!
72106 \brief 构造:初始化环境。
73107 \note Win32 平台:尝试无参数调用 FixConsoleHandler ,若失败则跟踪警告。
@@ -86,6 +120,52 @@
86120 ValueNode&
87121 GetRootRef() ynothrowv;
88122 //@}
123+
124+ //! \since build 954
125+ //@{
126+ template<typename _func>
127+ void
128+ ExecuteNPLA1(_func f)
129+ {
130+ // NOTE: The ground environment is saved during the call to
131+ // %NPL::A1::InvokeIn.
132+ NPL::A1::InvokeIn(Context.Root, [&]{
133+ RewriteNPLA1(f);
134+ });
135+ }
136+ /*!
137+ \pre 断言:参数指针不等于当前环境。
138+ \pre 间接断言:参数指针非空。
139+ */
140+ template<typename _func>
141+ void
142+ ExecuteNPLA1(_func f, shared_ptr<NPL::Environment> p_env)
143+ {
144+ YAssert(p_env != Context.Root.GetRecordPtr(),
145+ "Invalid environment found.");
146+
147+ NPL::A1::EnvironmentGuard gd(Context.Root,
148+ Context.Root.SwitchEnvironmentUnchecked(std::move(p_env)));
149+
150+ RewriteNPLA1(f);
151+ }
152+
153+private:
154+ void
155+ PrepareExecution(NPL::ContextNode&);
156+
157+ template<typename _func>
158+ void
159+ RewriteNPLA1(_func f)
160+ {
161+ Context.Root.Rewrite(NPL::ToReducer(Context.Allocator, trivial_swap,
162+ [&](NPL::ContextNode& ctx){
163+ PrepareExecution(ctx);
164+ f(Term);
165+ return NPL::A1::ReduceOnce(Term, ctx);
166+ }));
167+ }
168+ //@}
89169 };
90170
91171 } // namespace YSLib;
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/include/Helper/GUIApplication.h
--- a/YFramework/include/Helper/GUIApplication.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/include/Helper/GUIApplication.h Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2012-2016, 2019-2020 FrankHB.
2+ © 2012-2016, 2019-2020, 2022 FrankHB.
33
44 This file is part of the YSLib project, and may only be used,
55 modified, and distributed under the terms of the YSLib project
@@ -11,13 +11,13 @@
1111 /*! \file GUIApplication.h
1212 \ingroup Helper
1313 \brief GUI 应用程序。
14-\version r565
14+\version r587
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 398
1717 \par 创建时间:
1818 2013-04-11 10:02:53 +0800
1919 \par 修改时间:
20- 2020-01-31 15:57 +0800
20+ 2022-09-03 22:29 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,15 +29,14 @@
2929 #define INC_Helper_GUIApplication_h_ 1
3030
3131 #include "YModules.h"
32-#include YFM_Helper_YGlobal // for Environment;
32+#include YFM_Helper_YGlobal // for YSLib::allocate_unique, Environment;
3333 #include YFM_Helper_HostWindow // for Host::Window;
3434 #include YFM_YCLib_NativeAPI
35-#include YFM_YSLib_Core_YApplication // for Application;
35+#include YFM_YSLib_Core_YApplication // for Application, Shell;
3636 #include <ystdex/cast.hpp> // for ystdex::polymorphic_downcast;
37-#include YFM_Helper_GUIShell
3837 #include YFM_YCLib_HostedGUI
3938 #include YFM_YCLib_Mutex // for once_flag;
40-#include <ystdex/utility.hpp> // for ystdex::call_once_init;
39+#include <ystdex/utility.hpp> // for std::declval, ystdex::call_once_init;
4140 #if YCL_Win32
4241 # include YFM_YSLib_UI_YPanel
4342 #elif YCL_Android
@@ -202,8 +201,12 @@
202201 //! \since build 692
203202 struct InitBlock final
204203 {
205- //! \brief 环境状态。
206- unique_ptr<Environment> p_env;
204+ /*!
205+ \brief 环境状态。
206+ \since build 954
207+ */
208+ decltype(YSLib::allocate_unique<Environment>(
209+ Application::allocator_type(), std::declval<Application&>())) p_env;
207210 //! \brief GUI 宿主状态。
208211 mutable GUIHost host{};
209212
@@ -217,9 +220,11 @@
217220 public:
218221 /*!
219222 \brief 用户界面输入响应阈值。
223+ \warning 非线程安全。
220224 \sa DSApplication::Run
221225
222226 用于主消息队列的消息循环中控制后台消息生成策略的全局消息优先级。
227+ 一般在进入消息循环前指定并不再修改,以避免并发访问冲突。
223228 */
224229 Messaging::Priority UIResponseLimit = 0x40;
225230
@@ -261,6 +266,8 @@
261266 \brief 取全局应用程序实例。
262267 \throw GeneralEvent 不存在初始化完成的应用程序实例。
263268 \warning 调用线程安全,但不保证调用结束后实例仍在生存期内。
269+\warning 取得的实例上的操作不保证线程安全。
270+\sa LockInstance
264271 \since build 550
265272 */
266273 //@{
@@ -302,10 +309,15 @@
302309 \brief 执行程序主消息循环。
303310 \throw GeneralEvent 激活主 shell 失败。
304311 \note 对宿主实现,设置退出所有窗口时向 YSLib 发送退出消息。
305-\since build 399
312+\since build 954
306313 */
314+//@{
315+//! \note 创建 \c Shells::GUIShell 的对象作为 Shell 。
307316 YF_API void
308-Execute(GUIApplication&, shared_ptr<Shell> = make_shared<Shells::GUIShell>());
317+Execute(GUIApplication&);
318+YF_API void
319+Execute(GUIApplication&, shared_ptr<Shell>);
320+//@}
309321
310322 } // namespace YSLib;
311323
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/include/NPL/Dependency.h
--- a/YFramework/include/NPL/Dependency.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/include/NPL/Dependency.h Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file Dependency.h
1212 \ingroup NPL
1313 \brief 依赖管理。
14-\version r557
14+\version r617
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 623
1717 \par 创建时间:
1818 2015-08-09 22:12:37 +0800
1919 \par 修改时间:
20- 2022-04-20 19:22 +0800
20+ 2022-09-05 08:50 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,8 +29,7 @@
2929 #define NPL_INC_Dependency_h_
3030
3131 #include "YModules.h"
32-#include YFM_NPL_NPLA1 // for string, vector, REPLContext, ystdex::invoke,
33-// YSLib::unique_ptr;
32+#include YFM_NPL_NPLA1 // for string, vector, REPLContext, YSLib::unique_ptr;
3433 #include <istream> // for std::istream;
3534 #include <ystdex/scope_guard.hpp> // for ystdex::guard;
3635
@@ -82,7 +81,7 @@
8281
8382 //! \since build 899
8483 //@{
85-//! \brief 打开指定路径的文件作为 NPL 输入流并在上下文设置名称。
84+//! \brief 打开指定路径的文件作为 NPL 输入流并在上下文设置源代码名称。
8685 YB_ATTR_nodiscard YF_API YSLib::unique_ptr<std::istream>
8786 OpenUnique(REPLContext&, string);
8887
@@ -90,7 +89,9 @@
9089 /*!
9190 \brief 在 REPL 上下文中加载指定名称的外部翻译单元。
9291 \note 使用跳板,不直接改变上下文中的续延。
93-\sa Reduce
92+\note 加载时在上下文中设置源代码名称。
93+\sa OpenUnique
94+\sa TryLoadSource
9495 */
9596 YB_NONNULL(2) YF_API void
9697 PreloadExternal(REPLContext&, const char*);
@@ -119,67 +120,6 @@
119120 namespace Forms
120121 {
121122
122-//! \since build 942
123-//@{
124-//! \brief 加载代码调用。
125-template<typename _fCallable, typename... _tParams>
126-void
127-InvokeIn(ContextNode& ctx, _fCallable&& f, _tParams&&... args)
128-{
129- EnvironmentGuard gd(ctx,
130- NPL::SwitchToFreshEnvironment(ctx, ValueObject(ctx.WeakenRecord())));
131-
132- ystdex::invoke(yforward(f), yforward(args)...);
133-}
134-
135-/*!
136-\brief 加载代码作为模块。
137-\return 作为环境模块的环境对象强引用。
138-\post 返回值非空,指定冻结的环境。
139-*/
140-template<typename _fCallable, typename... _tParams>
141-shared_ptr<Environment>
142-GetModuleFor(ContextNode& ctx, _fCallable&& f, _tParams&&... args)
143-{
144- EnvironmentGuard gd(ctx,
145- NPL::SwitchToFreshEnvironment(ctx, ValueObject(ctx.WeakenRecord())));
146-
147- ystdex::invoke(yforward(f), yforward(args)...);
148- ctx.GetRecordRef().Frozen = true;
149- return ctx.ShareRecord();
150-}
151-
152-/*!
153-\pre 间接断言:模块名称字符串的数据指针非空。
154-\sa Forms::GetModuleFor
155-*/
156-//@{
157-//! \brief 加载模块为变量,若已存在则忽略。
158-template<typename _fCallable, typename... _tParams>
159-inline void
160-LoadModule(ContextNode& ctx, string_view module_name, _fCallable&& f,
161- _tParams&&... args)
162-{
163- ctx.GetRecordRef().Define(module_name,
164- Forms::GetModuleFor(ctx, yforward(f), yforward(args)...));
165-}
166-
167-/*!
168-\brief 加载模块为变量,若已存在抛出异常。
169-\exception BadIdentifier 变量绑定已存在。
170-*/
171-template<typename _fCallable, typename... _tParams>
172-inline void
173-LoadModuleChecked(ContextNode& ctx, string_view module_name, _fCallable&& f,
174- _tParams&&... args)
175-{
176- ctx.GetRecordRef().DefineChecked(module_name,
177- Forms::GetModuleFor(ctx, yforward(f), yforward(args)...));
178-}
179-//@}
180-//@}
181-
182-
183123 /*!
184124 \note 支持的具体语法形式参考 Documentation::NPL 。
185125 \since build 839
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/include/NPL/NPLA.h
--- a/YFramework/include/NPL/NPLA.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/include/NPL/NPLA.h Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA.h
1212 \ingroup NPL
1313 \brief NPLA 公共接口。
14-\version r9772
14+\version r9807
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 663
1717 \par 创建时间:
1818 2016-01-07 10:32:34 +0800
1919 \par 修改时间:
20- 2022-08-17 03:54 +0800
20+ 2022-09-05 08:44 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -3101,20 +3101,20 @@
31013101 //@{
31023102 //! \since build 867
31033103 template<typename... _tParams>
3104-inline shared_ptr<Environment>
3104+YB_ATTR_nodiscard inline shared_ptr<Environment>
31053105 AllocateEnvironment(const Environment::allocator_type& a, _tParams&&... args)
31063106 {
31073107 return YSLib::allocate_shared<Environment>(a, yforward(args)...);
31083108 }
31093109 template<typename... _tParams>
3110-inline shared_ptr<Environment>
3110+YB_ATTR_nodiscard inline shared_ptr<Environment>
31113111 AllocateEnvironment(ContextNode& ctx, _tParams&&... args)
31123112 {
31133113 return NPL::AllocateEnvironment(ctx.GetBindingsRef().get_allocator(),
31143114 yforward(args)...);
31153115 }
31163116 template<typename... _tParams>
3117-inline shared_ptr<Environment>
3117+YB_ATTR_nodiscard inline shared_ptr<Environment>
31183118 AllocateEnvironment(TermNode& term, ContextNode& ctx, _tParams&&... args)
31193119 {
31203120 const auto a(ctx.GetBindingsRef().get_allocator());
@@ -3300,6 +3300,41 @@
33003300 //@}
33013301
33023302
3303+//! \since build 954
3304+//@{
3305+//! \brief 设置参数指定的父环境。
3306+//@{
3307+inline PDefH(void, AssignParent, ValueObject& parent, const ValueObject& vo)
3308+ ImplExpr(parent = vo)
3309+inline PDefH(void, AssignParent, ValueObject& parent, ValueObject&& vo)
3310+ ImplExpr(parent = std::move(vo))
3311+inline PDefH(void, AssignParent, ValueObject& parent,
3312+ TermNode::allocator_type a, EnvironmentReference&& r_env)
3313+ ImplExpr(AssignParent(parent,
3314+ ValueObject(std::allocator_arg, a, std::move(r_env))))
3315+inline PDefH(void, AssignParent, ValueObject& parent, TermNode& term,
3316+ EnvironmentReference&& r_env)
3317+ ImplExpr(AssignParent(parent, term.get_allocator(), std::move(r_env)))
3318+template<typename... _tParams>
3319+inline void
3320+AssignParent(ContextNode& ctx, _tParams&&... args)
3321+{
3322+ AssignParent(ctx.GetRecordRef().Parent, yforward(args)...);
3323+}
3324+//@}
3325+
3326+//! \brief 设置参数指定的父环境弱引用。
3327+//@{
3328+inline PDefH(void, AssignWeakParent, ValueObject& parent,
3329+ TermNode::allocator_type a, ContextNode& ctx)
3330+ ImplExpr(AssignParent(parent, a, ctx.WeakenRecord()))
3331+inline PDefH(void, AssignWeakParent, ValueObject& parent, TermNode& term,
3332+ ContextNode& ctx)
3333+ ImplExpr(AssignWeakParent(parent, term.get_allocator(), ctx))
3334+//@}
3335+//@}
3336+
3337+
33033338 /*!
33043339 \brief 环境切换器。
33053340 \warning 非虚析构。
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/include/NPL/NPLA1.h
--- a/YFramework/include/NPL/NPLA1.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/include/NPL/NPLA1.h Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1.h
1212 \ingroup NPL
1313 \brief NPLA1 公共接口。
14-\version r9735
14+\version r9803
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 472
1717 \par 创建时间:
1818 2014-02-02 17:58:24 +0800
1919 \par 修改时间:
20- 2022-08-20 16:35 +0800
20+ 2022-09-05 10:51 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -40,11 +40,11 @@
4040 // ystdex::make_parameter_list_t, ystdex::make_function_type_t, ystdex::true_,
4141 // AssertCombiningTerm, IsList, TryAccessLeaf, TermReference, IsSticky,
4242 // ThrowListTypeErrorForNonList, ResolveSuffix, ThrowInsufficientTermsError,
43-// CountPrefix, ArityMismatch, TermTags, RegularizeTerm, TokenValue, function,
44-// Environment, ParseResultOf, ByteParser, SourcedByteParser, type_info,
45-// type_id, SourceInformation, std::bind, std::placeholders::_1,
46-// std::integral_constant, SourceName, NPL::tuple, NPL::get,
47-// NPL::forward_as_tuple, ReaderState, YSLib::allocate_shared,
43+// CountPrefix, ArityMismatch, TermTags, RegularizeTerm, ystdex::invoke,
44+// AssignParent, TokenValue, function, Environment, ParseResultOf, ByteParser,
45+// SourcedByteParser, type_info, type_id, SourceInformation, std::bind,
46+// std::placeholders::_1, std::integral_constant, SourceName, NPL::tuple,
47+// NPL::get, NPL::forward_as_tuple, ReaderState, YSLib::allocate_shared,
4848 // ystdex::is_bitwise_swappable;
4949 #include YFM_YSLib_Core_YEvent // for YSLib::GHEvent, YSLib::GCombinerInvoker,
5050 // YSLib::GDefaultLastValueInvoker;
@@ -1532,15 +1532,83 @@
15321532 /*!
15331533 \brief 创建和切换新环境并以结果初始化求值环境守卫。
15341534 \since build 945
1535+
1536+以第一参数作为上下文,切换到参数指定的新创建的环境,并创建被切换的环境的守卫。
1537+其余参数被作为初始化新创建环境的参数。
1538+其余参数指定的父环境被 Environment 的构造函数检查。若不需检查(如已在之前调用
1539+ Environment::CheckParent 或 Environment::EnsureValid ),可不使用其余参数,
1540+ 而在创建环境后设置当前环境的父环境对象。
15351541 */
15361542 template<typename... _tParams>
15371543 YB_ATTR_nodiscard inline EnvironmentGuard
15381544 GuardFreshEnvironment(ContextNode& ctx, _tParams&&... args)
15391545 {
1540- return EnvironmentGuard(ctx, NPL::SwitchToFreshEnvironment(ctx),
1541- yforward(args)...);
1546+ return EnvironmentGuard(ctx,
1547+ NPL::SwitchToFreshEnvironment(ctx, yforward(args)...));
15421548 }
15431549
1550+//! \since build 942
1551+//@{
1552+//! \brief 加载代码调用。
1553+template<typename _fCallable, typename... _tParams>
1554+void
1555+InvokeIn(ContextNode& ctx, _fCallable&& f, _tParams&&... args)
1556+{
1557+ ValueObject parent(ctx.WeakenRecord());
1558+ auto gd(GuardFreshEnvironment(ctx));
1559+
1560+ AssignParent(ctx, std::move(parent));
1561+ ystdex::invoke(yforward(f), yforward(args)...);
1562+}
1563+
1564+/*!
1565+\brief 加载代码作为模块。
1566+\return 作为环境模块的环境对象强引用。
1567+\post 返回值非空,指定冻结的环境。
1568+*/
1569+template<typename _fCallable, typename... _tParams>
1570+shared_ptr<Environment>
1571+GetModuleFor(ContextNode& ctx, _fCallable&& f, _tParams&&... args)
1572+{
1573+ ValueObject parent(ctx.WeakenRecord());
1574+ auto gd(GuardFreshEnvironment(ctx));
1575+
1576+ AssignParent(ctx, std::move(parent));
1577+ ystdex::invoke(yforward(f), yforward(args)...);
1578+ ctx.GetRecordRef().Frozen = true;
1579+ return ctx.ShareRecord();
1580+}
1581+
1582+/*!
1583+\pre 间接断言:模块名称字符串的数据指针非空。
1584+\sa A1::GetModuleFor
1585+*/
1586+//@{
1587+//! \brief 加载模块为变量,若已存在则忽略。
1588+template<typename _fCallable, typename... _tParams>
1589+inline void
1590+LoadModule(ContextNode& ctx, string_view module_name, _fCallable&& f,
1591+ _tParams&&... args)
1592+{
1593+ ctx.GetRecordRef().Define(module_name,
1594+ A1::GetModuleFor(ctx, yforward(f), yforward(args)...));
1595+}
1596+
1597+/*!
1598+\brief 加载模块为变量,若已存在抛出异常。
1599+\exception BadIdentifier 变量绑定已存在。
1600+*/
1601+template<typename _fCallable, typename... _tParams>
1602+inline void
1603+LoadModuleChecked(ContextNode& ctx, string_view module_name, _fCallable&& f,
1604+ _tParams&&... args)
1605+{
1606+ ctx.GetRecordRef().DefineChecked(module_name,
1607+ A1::GetModuleFor(ctx, yforward(f), yforward(args)...));
1608+}
1609+//@}
1610+//@}
1611+
15441612
15451613 /*!
15461614 \pre ContextNode& 类型的参数引用的对象是 NPLA1 上下文状态或 public 继承的派生类。
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/include/YSLib/Core/YApplication.h
--- a/YFramework/include/YSLib/Core/YApplication.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/include/YSLib/Core/YApplication.h Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2009-2016, 2018-2019 FrankHB.
2+ © 2009-2016, 2018-2019, 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 YApplication.h
1212 \ingroup Core
1313 \brief 系统资源和应用程序实例抽象。
14-\version r1785
14+\version r1800
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 577
1717 \par 创建时间:
1818 2009-12-27 17:12:27 +0800
1919 \par 修改时间:
20- 2019-01-16 06:03 +0800
20+ 2022-09-03 21:39 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,7 +29,8 @@
2929 #define YSL_INC_Core_YApplication_h_ 1
3030
3131 #include "YModules.h"
32-#include YFM_YSLib_Core_YShell // for Shell, any, stack,
32+#include YFM_YSLib_Core_YShell // for Messaging::MessageQueue, Shell,
33+// default_allocator, byte, stack, any, stack, recursive_mutex, shared_ptr,
3334 // std::is_nothrow_copy_constructible, locked_ptr, ystdex::decay_t,
3435 // YSLib::unchecked_any_cast;
3536 #include <ystdex/scope_guard.hpp> // for ystdex::unique_guard;
@@ -45,6 +46,10 @@
4546 */
4647 class YF_API Application : public Shell
4748 {
49+public:
50+ //! \since build 954
51+ using allocator_type = default_allocator<yimpl(byte)>;
52+
4853 private:
4954 /*!
5055 \brief 初始化守卫。
@@ -77,7 +82,11 @@
7782 public:
7883 //! \brief 无参数构造:默认构造。
7984 Application();
80-
85+ /*!
86+ \brief 构造:使用分配器。
87+ \since build 954
88+ */
89+ Application(allocator_type);
8190 //! \brief 析构:释放 Shell 所有权和其它资源。
8291 ~Application() override;
8392
@@ -180,6 +189,11 @@
180189 */
181190 PDefH(bool, Switch, shared_ptr<Shell>&& h) ynothrow
182191 ImplRet(Switch(h))
192+
193+ //! \since build 954
194+ YB_ATTR_nodiscard YB_PURE
195+ PDefH(allocator_type, get_allocator, ) const ynothrow
196+ ImplRet(qMain.get_allocator())
183197 };
184198
185199
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/include/YSLib/Core/YMessage.h
--- a/YFramework/include/YSLib/Core/YMessage.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/include/YSLib/Core/YMessage.h Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2009-2018, 2020-2021 FrankHB.
2+ © 2009-2018, 2020-2022 FrankHB.
33
44 This file is part of the YSLib project, and may only be used,
55 modified, and distributed under the terms of the YSLib project
@@ -11,13 +11,13 @@
1111 /*! \file YMessage.h
1212 \ingroup Core
1313 \brief 消息处理。
14-\version r2081
14+\version r2093
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 586
1717 \par 创建时间:
1818 2009-12-06 02:44:31 +0800
1919 \par 修改时间:
20- 2021-02-06 22:56 +0800
20+ 2022-09-03 21:39 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -162,6 +162,8 @@
162162 public:
163163 //! \since build 449
164164 using BaseType = YSLib::multimap<Priority, Message, std::greater<Priority>>;
165+ //! \since build 954
166+ using allocator_type = BaseType::allocator_type;
165167 /*!
166168 \brief 迭代器。
167169 \since build 460
@@ -171,10 +173,15 @@
171173 using BaseType::const_iterator;
172174 //@}
173175
176+ //! \brief 无参数构造:默认实现。
177+ DefDeCtor(MessageQueue)
174178 /*!
175- \brief 无参数构造:默认实现。
179+ \brief 构造:使用分配器。
180+ \since build 954
176181 */
177- DefDeCtor(MessageQueue)
182+ MessageQueue(allocator_type a) ynoexcept_spec(BaseType())
183+ : BaseType(a)
184+ {}
178185 DefDeDtor(MessageQueue)
179186
180187 /*!
@@ -268,6 +275,9 @@
268275
269276 using BaseType::size;
270277 //@}
278+
279+ //! \since build 954
280+ using BaseType::get_allocator;
271281 };
272282
273283
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/include/YSLib/Core/YObject.h
--- a/YFramework/include/YSLib/Core/YObject.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/include/YSLib/Core/YObject.h Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file YObject.h
1212 \ingroup Core
1313 \brief 平台无关的基础对象。
14-\version r6965
14+\version r6971
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 561
1717 \par 创建时间:
1818 2009-11-16 20:06:58 +0800
1919 \par 修改时间:
20- 2022-02-14 07:40 +0800
20+ 2022-08-31 12:40 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -47,7 +47,7 @@
4747 #include <ystdex/memory.hpp> // for ystdex::default_init,
4848 // ystdex::is_allocatable, ystdex::is_byte_allocator,
4949 // ystdex::has_get_allocator, ystdex::is_sharing, ystdex::rebind_alloc_t,
50-// YSLib::make_observer, ystdex::is_bitwise_swappable;
50+// make_observer, ystdex::is_bitwise_swappable;
5151 #include <ystdex/utility.hpp> // for ystdex::boxed_value, ystdex::as_const,
5252 // ystdex::copy_or_move;
5353 #include <ystdex/ref.hpp> // for ystdex::ref, ystdex::cond_t,
@@ -662,7 +662,7 @@
662662
663663 YB_ATTR_nodiscard YB_PURE PDefH(bool, Equals, const void* p) const
664664 ImplI(IValueHolder)
665- ImplRet(bool(p) && IsTyped<value_type>(base::type) && AreEqualHeld(
665+ ImplRet(bool(p) && IsTyped<value_type>(base::type()) && AreEqualHeld(
666666 this->value, Deref(static_cast<const value_type*>(p))))
667667
668668 //! \since build 900
@@ -1469,13 +1469,13 @@
14691469 YB_ATTR_nodiscard YB_PURE inline observer_ptr<_type>
14701470 AccessPtr() ynothrow
14711471 {
1472- return YSLib::make_observer(YSLib::any_cast<_type>(&content));
1472+ return make_observer(YSLib::any_cast<_type>(&content));
14731473 }
14741474 template<typename _type>
14751475 YB_ATTR_nodiscard YB_PURE inline observer_ptr<const _type>
14761476 AccessPtr() const ynothrow
14771477 {
1478- return YSLib::make_observer(YSLib::any_cast<const _type>(&content));
1478+ return make_observer(YSLib::any_cast<const _type>(&content));
14791479 }
14801480 //@}
14811481
@@ -1690,14 +1690,14 @@
16901690 YB_ATTR_nodiscard YB_PURE inline observer_ptr<_type>
16911691 TryAccessValue(ValueObject& vo)
16921692 {
1693- return IsTyped<_type>(vo) ? YSLib::make_observer(
1693+ return IsTyped<_type>(vo) ? make_observer(
16941694 std::addressof(vo.GetObject<_type>())) : nullptr;
16951695 }
16961696 template<typename _type>
16971697 YB_ATTR_nodiscard YB_PURE inline observer_ptr<const _type>
16981698 TryAccessValue(const ValueObject& vo)
16991699 {
1700- return IsTyped<_type>(vo) ? YSLib::make_observer(
1700+ return IsTyped<_type>(vo) ? make_observer(
17011701 std::addressof(vo.GetObject<_type>())) : nullptr;
17021702 }
17031703 //@}
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/source/Helper/Environment.cpp
--- a/YFramework/source/Helper/Environment.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/source/Helper/Environment.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2013-2016, 2018-2021 FrankHB.
2+ © 2013-2016, 2018-2022 FrankHB.
33
44 This file is part of the YSLib project, and may only be used,
55 modified, and distributed under the terms of the YSLib project
@@ -11,13 +11,13 @@
1111 /*! \file Environment.cpp
1212 \ingroup Helper
1313 \brief 环境。
14-\version r1924
14+\version r1995
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 379
1717 \par 创建时间:
1818 2013-02-08 01:27:29 +0800
1919 \par 修改时间:
20- 2021-05-06 19:31 +0800
20+ 2022-09-05 12:33 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -26,7 +26,7 @@
2626
2727
2828 #include "Helper/YModules.h"
29-#include YFM_Helper_Environment // for in_place_type, any;
29+#include YFM_Helper_Environment // for make_any, string;
3030 #include YFM_Helper_Initialization // for InitializeEnvironment,
3131 // ShowInitializedLog, PerformKeyAction, LoadComponents;
3232 #if YCL_DS
@@ -40,6 +40,15 @@
4040 # include YFM_YSLib_Adaptor_YAdaptor // for FetchEnvironmentVariable;
4141 # include YFM_YCLib_Debug // for platform_ex::SendDebugString;
4242 #endif
43+#include YFM_NPL_Dependency // for NPL, NPL::make_observer, A1,
44+// NPL::A1::Forms::LoadStandardContext, TraceException, A1::TraceBacktrace,
45+// NPLException;
46+#if YF_Helper_Environment_UseStdout
47+# include <iostream> // for std::cout;
48+#endif
49+#if YF_Helper_Environment_NPL_UseBacktrace
50+# include <ystdex/scope_guard.hpp> // for ystdex::make_guard;
51+#endif
4352
4453 namespace YSLib
4554 {
@@ -50,6 +59,8 @@
5059 #endif
5160
5261 Environment::Environment(Application& app)
62+ : Root(app.get_allocator()), DefaultOutputStream(string(
63+ app.get_allocator())), Context(*app.get_allocator().resource())
5364 {
5465 #if !YF_Hosted
5566 // NOTE: This only effects freestanding implementations now, which may need
@@ -87,7 +98,7 @@
8798 }
8899 });
89100 PerformKeyAction([&]{
90- app.AddExit(any(in_place_type<FileSystem>));
101+ app.AddExit(make_any<FileSystem>());
91102 }, yfsig, " LibFAT Failure ",
92103 " An error is preventing the\n"
93104 " program from accessing\n"
@@ -129,10 +140,24 @@
129140 throw GeneralEvent("Call of std::setlocale() with %s failed.\n",
130141 locale_str);
131142 #endif
132- // NOTE: Ensure root node is initialized before lifetime of environment
143+ // XXX: This should not fail.
144+ PerformKeyAction([&]{
145+# if YF_Helper_Environment_NPL_UseSourceInfo
146+ Context.UseSourceLocation = true;
147+# endif
148+ Context.OutputStreamPtr = NPL::make_observer(&
149+# if YF_Helper_Environment_UseStdout
150+ std::cout
151+# else
152+ DefaultOutputStream
153+# endif
154+ );
155+ NPL::A1::Forms::LoadStandardContext(Context);
156+ }, yfsig, " NPLA1 Failure ",
157+ " An unexpected error occurs \n"
158+ " during the initializaiton.\n");
159+ // NOTE: Ensure the root node is initialized before lifetime of environment
133160 // begins.
134- string res;
135-
136161 YTraceDe(Notice, "Checking installation...");
137162 PerformKeyAction([&]{
138163 Root = LoadConfiguration(true);
@@ -149,5 +174,47 @@
149174 YF_Trace(Debug, "Environment lifetime ended.");
150175 }
151176
177+void
178+Environment::PrepareExecution(NPL::ContextNode& ctx)
179+{
180+ using namespace NPL;
181+
182+ ctx.SaveExceptionHandler();
183+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
184+ // implementation.
185+ ctx.HandleException = ystdex::bind1([&](std::exception_ptr p,
186+ const ContextNode::ReducerSequence::const_iterator& i){
187+ ctx.TailAction = nullptr;
188+# if YF_Helper_Environment_NPL_UseBacktrace
189+ ctx.Shift(backtrace, i);
190+# else
191+ yunused(i);
192+# endif
193+ YAssertNonnull(p);
194+ TryExpr(std::rethrow_exception(std::move(p)))
195+ catch(std::exception& e)
196+ {
197+# if YF_Helper_Environment_NPL_UseBacktrace
198+ const auto gd(ystdex::make_guard([&]() ynothrowv{
199+ backtrace.clear();
200+ }));
201+# endif
202+ auto& trace(ctx.Trace);
203+
204+ TraceException(e, trace);
205+ trace.TraceFormat(Notice, "Location: %s.", Context.CurrentSource
206+ ? Context.CurrentSource->c_str() : "<unknown>");
207+# if YF_Helper_Environment_NPL_UseBacktrace
208+ A1::TraceBacktrace(backtrace, trace);
209+ // NOTE: As %Tools.SHBuild.Main.
210+ throw NPLException("Error detected in the execution"
211+ " (see the backtrace for details).");
212+# else
213+ throw NPLException("Error detected in the execution.");
214+# endif
215+ }
216+ }, ctx.GetCurrent().cbegin());
217+}
218+
152219 } // namespace YSLib;
153220
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/source/Helper/GUIApplication.cpp
--- a/YFramework/source/Helper/GUIApplication.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/source/Helper/GUIApplication.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2012-2016, 2020 FrankHB.
2+ © 2012-2016, 2020, 2022 FrankHB.
33
44 This file is part of the YSLib project, and may only be used,
55 modified, and distributed under the terms of the YSLib project
@@ -11,13 +11,13 @@
1111 /*! \file GUIApplication.cpp
1212 \ingroup Helper
1313 \brief GUI 应用程序。
14-\version r582
14+\version r592
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 396
1717 \par 创建时间:
1818 2013-04-06 22:42:54 +0800
1919 \par 修改时间:
20- 2020-12-24 12:07 +0800
20+ 2022-09-03 22:27 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -26,7 +26,7 @@
2626
2727
2828 #include "Helper/YModules.h"
29-#include YFM_Helper_GUIApplication
29+#include YFM_Helper_GUIApplication // for YSLib::allocate_shared;
3030 #include YFM_Helper_Environment
3131 #include YFM_YCLib_Input // for platform_ex::FetchCursor;
3232 #if YCL_Win32
@@ -34,6 +34,7 @@
3434 #elif YCL_Android
3535 # include YFM_Android_Helper_AndroidHost // for Android::NativeHost;
3636 #endif
37+#include YFM_Helper_GUIShell // for Shells::GUIShell;
3738
3839 namespace YSLib
3940 {
@@ -227,7 +228,7 @@
227228
228229
229230 GUIApplication::InitBlock::InitBlock(Application& app)
230- : p_env(new Environment(app))
231+ : p_env(YSLib::allocate_unique<Environment>(app.get_allocator(), app))
231232 {}
232233
233234 GUIApplication::GUIApplication()
@@ -307,6 +308,12 @@
307308
308309
309310 void
311+Execute(GUIApplication& app)
312+{
313+ return Execute(app,
314+ YSLib::allocate_shared<Shells::GUIShell>(app.get_allocator()));
315+}
316+void
310317 Execute(GUIApplication& app, shared_ptr<Shell> p_shl)
311318 {
312319 #if YF_Hosted
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/source/NPL/Dependency.cpp
--- a/YFramework/source/NPL/Dependency.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/source/NPL/Dependency.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file Dependency.cpp
1212 \ingroup NPL
1313 \brief 依赖管理。
14-\version r7181
14+\version r7189
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 623
1717 \par 创建时间:
1818 2015-08-09 22:14:45 +0800
1919 \par 修改时间:
20- 2022-08-22 03:19 +0800
20+ 2022-09-04 23:03 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -245,7 +245,7 @@
245245 A1::NameTypedReducerHandler(std::bind([&](SourceName& saved_src){
246246 context.CurrentSource = std::move(saved_src);
247247 return ctx.LastStatus;
248- }, std::move(context.CurrentSource)), "recover-source-name"));
248+ }, std::move(context.CurrentSource)), "restore-source-name"));
249249 # endif
250250 term = context.Load(context, ctx, std::move(filename));
251251 return ContextState::Access(ctx).ReduceOnce.Handler(term, ctx);
@@ -1197,9 +1197,8 @@
11971197 $defl! firstv ((&x .)) $move-resolved! x;
11981198 $defl%! rest% ((#ignore .%xs)) $move-resolved! xs;
11991199 $defl%! rest& (&pr)
1200- ($lambda% ((#ignore .@xs)) $if (uncollapsed? xs)
1201- ($if (modifiable? pr) (idv xs) (as-const (idv xs)))
1202- ($if (unique? ($resolve-identifier pr)) (expire xs) xs))
1200+ ($lambda% ((#ignore .&xs)) $if (unique? ($resolve-identifier pr))
1201+ (expire xs) ($resolve-identifier xs))
12031202 ($if (unique? ($resolve-identifier pr)) pr
12041203 (check-pair-reference (forward! pr)));
12051204 $defl! restv ((#ignore .xs)) $move-resolved! xs;
@@ -1777,8 +1776,7 @@
17771776 RegisterStrict(renv, "continuation->applicative",
17781777 ContinuationToApplicative);
17791778 #if NPL_Impl_NPLA1_Native_Forms
1780- RegisterStrict(renv, "apply-continuation",
1781- ApplyContinuation);
1779+ RegisterStrict(renv, "apply-continuation", ApplyContinuation);
17821780 #else
17831781 context.ShareCurrentSource("<lib:std.continuations>");
17841782 context.Perform(R"NPL(
@@ -2086,8 +2084,8 @@
20862084 #endif
20872085 RegisterStrict(renv, "load", trivial_swap,
20882086 [&](TermNode& term, ContextNode& ctx){
2089- // NOTE: Since %load requires no additional barrier of catching the
2090- // inner exceptions and the reset of the source name, %TryLoadSource or
2087+ // NOTE: Since %load disallows additional barrier of catching the inner
2088+ // exceptions and the reset of the source name, %TryLoadSource or
20912089 // %PreloadExternal is not applicable here.
20922090 return ReduceToLoadExternal(term, ctx, context);
20932091 });
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/source/NPL/NPLA1.cpp
--- a/YFramework/source/NPL/NPLA1.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/source/NPL/NPLA1.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1.cpp
1212 \ingroup NPL
1313 \brief NPLA1 公共接口。
14-\version r23682
14+\version r23847
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 472
1717 \par 创建时间:
1818 2014-02-02 18:02:47 +0800
1919 \par 修改时间:
20- 2022-08-22 02:42 +0800
20+ 2022-08-25 12:06 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -31,14 +31,16 @@
3131 // ystdex::equal_to, YSLib::unordered_map, YSLib::lock_guard, YSLib::mutex,
3232 // std::ref, ListReductionFailure, ystdex::sfmt, TermToStringWithReferenceMark,
3333 // std::next, IsBranch, TermReference, std::allocator_arg, in_place_type,
34-// CheckReducible, IsNPLAExtendedLiteralNonDigitPrefix,
35-// IsAllSignLexeme, AllocatorHolder, YSLib::IValueHolder, ystdex::ref,
34+// CheckReducible, IsNPLAExtendedLiteralNonDigitPrefix, IsAllSignLexeme,
35+// AllocatorHolder, YSLib::IValueHolder, ystdex::ref,
3636 // YSLib::AllocatedHolderOperations, any, ystdex::as_const,
3737 // NPL::forward_as_tuple, uintmax_t, ystdex::bind1, TokenValue,
38-// Forms::Sequence, ReduceBranchToList, YSLib::stack, vector, GetLValueTagsOf,
39-// TermTags, function, TryAccessLeafAtom, PropagateTo, InvalidReference,
40-// IsList, IsIgnore, tuple, TNCIter, NPL::get, NPL::Deref, LiftTermRef,
41-// TryAccessLeaf, IsTyped, ResolveTerm, std::prev,
38+// Forms::Sequence, ReduceBranchToList, YSLib::stack, vector, size_t,
39+// GetLValueTagsOf, TermTags, function, TryAccessLeafAtom, PropagateTo,
40+// InvalidReference, LiftTermRef, TryAccessLeaf, LiftPrefixToReturn,
41+// NPL::Deref, ystdex::true_, IsList, ThrowFormalParameterTypeError,
42+// CountPrefix, ThrowNestedParameterTreeMismatch, ystdex::false_, IsIgnore,
43+// TermToNamePtr, tuple, TNCIter, NPL::get, ResolveTerm, IsTyped, std::prev,
4244 // ThrowListTypeErrorForNonList, ThrowInsufficientTermsError, ReferenceTerm,
4345 // ystdex::begins_with, FindStickySubterm, Environment, shared_ptr,
4446 // AssertValueTags, ystdex::retry_on_cond, AccessFirstSubterm, ystdex::ref_eq,
@@ -718,7 +720,6 @@
718720 InvalidReference("Invalid operand found on binding sigil '@'.");
719721 }
720722 //! \since build 951
721- //@{
722723 template<typename _fMove>
723724 void
724725 operator()(char sigil, bool ref_temp, TermTags o_tags, TermNode& o,
@@ -727,53 +728,53 @@
727728 // NOTE: Same to the overload above, except that %o can be a pair and %j
728729 // specifies the 1st subterm of the suffix.
729730 const bool temp(bool(o_tags & TermTags::Temporary));
730- const auto bind_subpair([&](TermTags tags){
731- // NOTE: There is no %TermTags::Temprary in %tags due to the
732- // constrains in the caller. This guarantees no element will have
733- // %TermTags::Temporary.
734- YAssert(!bool(tags & TermTags::Temporary),
735- "Unexpected temporary tag found.");
731+ // XXX: Placing %bind_subpair_val_fwd here instead of in the branch
732+ // below is more efficient.
733+ const auto bind_subpair_val_fwd(
734+ [&](TermNode& src, TNIter j, TermTags tags) -> TermNode&{
735+ YAssert(sigil == char() || sigil == '%', "Invalid sigil found.");
736+
737+ auto t(CreateForBindSubpairPrefix(sigil, src, j, tags));
738+
739+ if(o.Value)
740+ BindSubpairCopySuffix(t, src, j);
741+ return mv(std::move(t.GetContainerRef()), std::move(t.Value));
742+ });
743+ const auto bind_subpair_ref_at([&](TermTags tags){
744+ YAssert(sigil == '&' || sigil == '@', "Invalid sigil found.");
745+
746+ auto t(CreateForBindSubpairPrefix(sigil, o, first, tags));
747+
748+ if(o.Value)
749+ // XXX: The container is ignored, since it is assumed always
750+ // living when %Value is accessed (otherwise, the behavior
751+ // is undefined in the object language).
752+ LiftTermRef(t.Value, o.Value);
736753
737754 const auto a(o.get_allocator());
738- TermNode t(a);
755+ // NOTE: Make a subpair reference whose referent is the copy
756+ // constructed above. Irregular representation is constructed
757+ // for the subpair reference.
758+ // XXX: As %ReduceAsSubobjectReference in NPLA1Internals.
759+ auto p_sub(A1::AllocateSharedTerm(a, std::move(t)));
760+#if true
761+ auto& sub(*p_sub);
739762 auto& tcon(t.GetContainerRef());
740763
741- BindSubpairSubterms(sigil, tcon, o, first, tags);
742- if(o.Value)
743- {
744- if(sigil == '%' || sigil == char())
745- BindSubpairCopySubterms(t, o, first);
746- else
747- // XXX: The container is ignored, since it is assumed always
748- // living when %Value is accessed (otherwise, the behavior
749- // is undefined in the object language).
750- LiftTermRef(t.Value, o.Value);
751- // NOTE: No tags are set in %t, implying no %TermTags::Temporary
752- // in the elements finally.
753- }
754- else
755- // XXX: As in %LiftPrefixToReturn.
756- YAssert(first == o.end(), "Invalid representation found.");
757- if(sigil != '&' && sigil != '@')
758- MarkTemporaryTerm(mv(std::move(tcon), std::move(t.Value)),
759- sigil);
760- else
761- {
762- // NOTE: Make a subpair reference whose referent is the copy
763- // constructed above. Irregular representation is constructed
764- // for the subpair reference.
765- // XXX: As %ReduceAsSubobjectReference in NPLA1Internals.
766- auto p_sub(A1::AllocateSharedTerm(a, std::move(t)));
767- auto& sub(NPL::Deref(p_sub));
768-
769- // XXX: Reuse %tcon.
770- tcon.clear();
771- tcon.push_back(MakeSubobjectReferent(a, std::move(p_sub)));
772- // XXX: The anchor indicated by %Referenced is not accurate, as
773- // the overload %operator() above.
774- mv(std::move(tcon), ValueObject(std::allocator_arg, a,
775- in_place_type<TermReference>, tags, sub, Referenced));
776- }
764+ // XXX: Reuse %tcon.
765+ tcon.clear();
766+ tcon.push_back(MakeSubobjectReferent(a, std::move(p_sub)));
767+ // XXX: The anchor indicated by %Referenced is not accurate, as
768+ // the overload %operator() above.
769+ mv(std::move(tcon), ValueObject(std::allocator_arg, a,
770+ in_place_type<TermReference>, tags, sub, Referenced));
771+#else
772+ // NOTE: Any optimized implemenations shall be equivalent to
773+ // this.
774+ ReduceAsSubobjectReference(t, std::move(p_sub), Referenced,
775+ tags);
776+ mv(std::move(tcon), std::move(t.Value));
777+#endif
777778 });
778779
779780 if(sigil != '@')
@@ -802,23 +803,8 @@
802803 auto& src(p->get());
803804
804805 if(!p->IsMovable())
805- {
806- // XXX: As %bind_subpair, with different source subterms.
807- auto j(src.begin());
808- TermNode t(a);
809- auto& tcon(t.GetContainerRef());
810-
811- BindSubpairSubterms(sigil, tcon, src, j,
812- GetLValueTagsOf(o_tags & ~TermTags::Unique));
813- if(src.Value)
814- BindSubpairCopySubterms(t, src, j);
815- else
816- // XXX: As in %LiftPrefixToReturn.
817- YAssert(j == src.end(),
818- "Invalid representation found.");
819- CopyTermTags(mv(std::move(tcon), std::move(t.Value)),
820- src);
821- }
806+ CopyTermTags(bind_subpair_val_fwd(src, src.begin(),
807+ GetLValueTagsOf(o_tags & ~TermTags::Unique)), src);
822808 else
823809 mv(MoveSuffix(o, first), std::move(src.Value));
824810 }
@@ -836,21 +822,25 @@
836822 MarkTemporaryTerm(mv(MoveSuffix(o, first), std::move(o.Value)),
837823 sigil);
838824 }
825+ else if(sigil == '&')
826+ bind_subpair_ref_at(GetLValueTagsOf(o.Tags | o_tags));
827+ // NOTE: The temporary tag cannot be in %o_tags here.
839828 else
840- // NOTE: All temporary tags will not come here.
841- bind_subpair(
842- sigil == '&' ? GetLValueTagsOf(o.Tags | o_tags) : o_tags);
829+ MarkTemporaryTerm(bind_subpair_val_fwd(o, first, o_tags),
830+ sigil);
843831 }
844832 else if(!temp)
845- bind_subpair(o_tags & TermTags::Nonmodifying);
833+ bind_subpair_ref_at(o_tags & TermTags::Nonmodifying);
846834 else
847835 throw
848836 InvalidReference("Invalid operand found on binding sigil '@'.");
849837 }
850838
851839 private:
840+ //! \since build 954
841+ //@{
852842 static void
853- BindSubpairCopySubterms(TermNode& t, TermNode& o, TNIter& j)
843+ BindSubpairCopySuffix(TermNode& t, TermNode& o, TNIter& j)
854844 {
855845 while(j != o.end())
856846 t.emplace(*j++);
@@ -858,7 +848,7 @@
858848 }
859849
860850 void
861- BindSubpairSubterms(char sigil, TermNode::Container& tcon, TermNode& o,
851+ BindSubpairPrefix(char sigil, TermNode::Container& tcon, TermNode& o,
862852 TNIter& j, TermTags tags) const
863853 {
864854 // NOTE: This guarantees no subpair element will have
@@ -868,6 +858,10 @@
868858 // NOTE: Make a list as a copy of the sublist or as a list of references
869859 // to the elements of the sublist, depending on the sigil.
870860 for(; j != o.end() && !IsSticky(j->Tags); ++j)
861+#if true
862+ BindSubpairSubterm(sigil, tcon, tags, NPL::Deref(j));
863+#else
864+ // NOTE: Any optimized implemenations shall be equivalent to this.
871865 (*this)(sigil, {}, tags, NPL::Deref(j), [&](const TermNode& tm){
872866 CopyTermTags(tcon.emplace_back(tm.GetContainer(), tm.Value),
873867 tm);
@@ -875,9 +869,86 @@
875869 tcon.emplace_back(std::move(c), std::move(vo));
876870 return tcon.back();
877871 });
872+#endif
878873 }
879874
880- static TermNode::Container
875+ // XXX: Keep this a separated function may lead to more efficient code.
876+ void
877+ BindSubpairSubterm(char sigil, TermNode::Container& tcon, TermTags o_tags,
878+ TermNode& o) const
879+ {
880+ // NOTE: As %BindSubpairPrefix.
881+ YAssert(!bool(o_tags & TermTags::Temporary),
882+ "Unexpected temporary tag found.");
883+ const auto cp([&](const TermNode& tm){
884+ CopyTermTags(tcon.emplace_back(tm.GetContainer(), tm.Value), tm);
885+ });
886+ const auto
887+ mv([&](TermNode::Container&& c, ValueObject&& vo) -> TermNode&{
888+ tcon.emplace_back(std::move(c), std::move(vo));
889+ return tcon.back();
890+ });
891+
892+ if(sigil != '@')
893+ {
894+ const auto a(o.get_allocator());
895+
896+ if(const auto p = TryAccessLeafAtom<TermReference>(o))
897+ {
898+ if(sigil != char())
899+ mv(TermNode::Container(o.GetContainer(), a),
900+ ValueObject(in_place_type<TermReference>,
901+ PropagateTo(p->GetTags(), o_tags), *p));
902+ else
903+ {
904+ auto& src(p->get());
905+
906+ if(!p->IsMovable())
907+ cp(src);
908+ else
909+ mv(std::move(src.GetContainerRef()),
910+ std::move(src.Value));
911+ }
912+ }
913+ else if(sigil == '&')
914+ mv(TermNode::Container(a), ValueObject(std::allocator_arg, a,
915+ in_place_type<TermReference>,
916+ GetLValueTagsOf(o.Tags | o_tags), o, Referenced));
917+ else
918+ cp(o);
919+ }
920+ else
921+ mv(TermNode::Container(o.get_allocator()),
922+ ValueObject(std::allocator_arg, o.get_allocator(),
923+ in_place_type<TermReference>, o_tags & TermTags::Nonmodifying,
924+ o, Referenced));
925+ }
926+
927+ TermNode
928+ CreateForBindSubpairPrefix(char sigil, TermNode& o, TNIter first,
929+ TermTags tags) const
930+ {
931+ // NOTE: There is no %TermTags::Temprary in %tags due to the constrains
932+ // in the caller. This guarantees no element will have
933+ // %TermTags::Temporary.
934+ YAssert(!bool(tags & TermTags::Temporary),
935+ "Unexpected temporary tag found.");
936+
937+ const auto a(o.get_allocator());
938+ TermNode t(a);
939+
940+ // NOTE: No tags are set in the result implies no %TermTags::Temporary
941+ // in the elements finally.
942+ BindSubpairPrefix(sigil, t.GetContainerRef(), o, first, tags);
943+ if(!o.Value)
944+ // XXX: As in %LiftPrefixToReturn.
945+ YAssert(first == o.end(), "Invalid representation found.");
946+ return t;
947+ }
948+ //@}
949+
950+ //! \since build 951
951+ YB_ATTR_nodiscard static TermNode::Container
881952 MoveSuffix(TermNode& o, TNIter j)
882953 {
883954 TermNode::Container tcon(o.get_allocator());
@@ -885,7 +956,6 @@
885956 tcon.splice(tcon.end(), o.GetContainerRef(), j, o.end());
886957 return tcon;
887958 }
888- //@}
889959 };
890960
891961
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/source/NPL/NPLA1Forms.cpp
--- a/YFramework/source/NPL/NPLA1Forms.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/source/NPL/NPLA1Forms.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1Forms.cpp
1212 \ingroup NPL
1313 \brief NPLA1 语法形式。
14-\version r28193
14+\version r28289
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 882
1717 \par 创建时间:
1818 2014-02-15 11:19:51 +0800
1919 \par 修改时间:
20- 2022-08-22 04:57 +0800
20+ 2022-09-05 08:54 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -33,7 +33,7 @@
3333 // ReduceReturnUnspecified, RetainList, CheckVariadicArity, RemoveHead,
3434 // AccessFirstSubterm, ReduceOrdered, LiftOtherValue, std::bind, std::ref,
3535 // std::placeholders, std::declval, RetainN, ystdex::as_const, ValueObject,
36-// ReferenceLeaf, IsAtom, ReferenceTerm, ystdex::ref_eq, CountPrefix,
36+// ReferenceLeaf, IsAtom, ReferenceTerm, ystdex::ref_eq, CountPrefix, IsSticky,
3737 // RelaySwitched, trivial_swap, shared_ptr, ContextHandler,
3838 // YSLib::unordered_map, string, Environment, lref, TokenValue,
3939 // any_ops::use_holder, in_place_type, YSLib::HolderFromPointer,
@@ -45,16 +45,16 @@
4545 // TryAccessLeafAtom, TermReference, EnvironmentList, NPL::AllocateEnvironment,
4646 // ystdex::equality_comparable, CheckParameterTree, AssertValueTags,
4747 // NPL::AsTermNode, ystdex::exchange, NPLException, GuardFreshEnvironment,
48-// TermTags, YSLib::Debug, YSLib::sfmt, ReduceCombinedBranch, A1::MakeForm,
48+// TermTags, YSLib::Debug, YSLib::sfmt, AssignParent, A1::MakeForm,
4949 // ystdex::expand_proxy, AccessRegular, GetLValueTagsOf, RegularizeTerm,
50-// IsPair, IsSticky, LiftPropagatedReference, LiftOther, LiftMovedOther,
51-// IsLeaf, LiftTerm, IsList, ThrowListTypeErrorForNonList,
52-// ThrowValueCategoryError, ThrowListTypeErrorForAtom, ThrowInvalidSyntaxError,
53-// CheckEnvironmentFormal, LiftTermOrCopy, EnsureValueTags, type_id,
54-// ystdex::update_thunk, AssertCombiningTerm, LiftToReturn, IsTyped,
55-// IsBranchedList, EnvironmentGuard, TryAccessLeaf, BindSymbol, A1::AsForm,
50+// IsPair, LiftPropagatedReference, LiftOther, LiftMovedOther, IsLeaf,
51+// LiftTerm, IsList, ThrowListTypeErrorForNonList, ThrowValueCategoryError,
52+// ThrowListTypeErrorForAtom, ThrowInvalidSyntaxError, CheckEnvironmentFormal,
53+// LiftTermOrCopy, EnsureValueTags, type_id, ystdex::update_thunk,
54+// AssertCombiningTerm, LiftToReturn, IsTyped, IsBranchedList,
55+// EnvironmentGuard, AssignWeakParent, TryAccessLeaf, BindSymbol, A1::AsForm,
5656 // ystdex::bind1, IsNPLASymbol, ystdex::fast_all_of, ystdex::isdigit,
57-// std::strchr, ystdex::call_value_or, LiftCollapsed, FindStickySubterm,
57+// std::strchr, ystdex::call_value_or, LiftCollapsed, ReduceCombinedBranch,
5858 // YSLib::usystem, std::mem_fn;
5959 #include "NPLA1Internals.h" // for A1::Internals API;
6060 #include YFM_NPL_SContext // for Session;
@@ -295,6 +295,11 @@
295295 {
296296 if(first1 != last1)
297297 {
298+ YAssert(!IsSticky(NPL::Deref(first1).Tags),
299+ "Invalid representation found."),
300+ YAssert(!IsSticky(NPL::Deref(first2).Tags),
301+ "Invalid representation found.");
302+
298303 auto& x(ReferenceTerm(NPL::Deref(first1)));
299304 auto& y(ReferenceTerm(NPL::Deref(first2)));
300305
@@ -326,6 +331,11 @@
326331 {
327332 if(first1 != last1)
328333 {
334+ YAssert(!IsSticky(NPL::Deref(first1).Tags),
335+ "Invalid representation found."),
336+ YAssert(!IsSticky(NPL::Deref(first2).Tags),
337+ "Invalid representation found.");
338+
329339 auto& x(ReferenceTerm(NPL::Deref(first1)));
330340 auto& y(ReferenceTerm(NPL::Deref(first2)));
331341
@@ -729,34 +739,6 @@
729739 #endif
730740 }
731741
732-//! \since build 945
733-//@{
734-inline PDefH(void, AssignParent, ValueObject& parent, const ValueObject& vo)
735- ImplExpr(parent = vo)
736-inline PDefH(void, AssignParent, ValueObject& parent, ValueObject&& vo)
737- ImplExpr(parent = std::move(vo))
738-inline PDefH(void, AssignParent, ValueObject& parent,
739- TermNode::allocator_type a, EnvironmentReference&& r_env)
740- ImplExpr(AssignParent(parent,
741- ValueObject(std::allocator_arg, a, std::move(r_env))))
742-inline PDefH(void, AssignParent, ValueObject& parent, TermNode& term,
743- EnvironmentReference&& r_env)
744- ImplExpr(AssignParent(parent, term.get_allocator(), std::move(r_env)))
745-template<typename... _tParams>
746-inline void
747-AssignParent(ContextNode& ctx, _tParams&&... args)
748-{
749- AssignParent(ctx.GetRecordRef().Parent, yforward(args)...);
750-}
751-
752-inline PDefH(void, AssignWeakParent, ValueObject& parent,
753- TermNode::allocator_type a, ContextNode& ctx)
754- ImplExpr(AssignParent(parent, a, ctx.WeakenRecord()))
755-inline PDefH(void, AssignWeakParent, ValueObject& parent, TermNode& term,
756- ContextNode& ctx)
757- ImplExpr(AssignWeakParent(parent, term.get_allocator(), ctx))
758-//@}
759-
760742 //! \since build 918
761743 YB_ATTR_nodiscard shared_ptr<Environment>
762744 CreateEnvironment(TermNode& term)
@@ -811,8 +793,10 @@
811793 \pre 间接断言:形式参数对象指针非空。
812794 \pre 第三参数满足 Environment::CheckParent 检查不抛出异常。
813795 \pre 间接断言:第四参数的标签可表示一等对象的值。
796+ \pre 假定第三参数可表示父环境。
814797 \sa MakeParent
815798 \sa MakeParentSingle
799+ \sa MakeParentSingleNonOwning
816800 \since build 918
817801 */
818802 // XXX: Keep parameters of reference types, as it is more efficient, at
@@ -870,6 +854,13 @@
870854 // bindings would behave as in the old environment, which is too
871855 // expensive for direct execution of programs with first-class
872856 // environments.
857+ // NOTE: This call does not have the parent argument as it would be
858+ // assigned later in %DoCall by a call to %AssignParent. This allows
859+ // conditionally moving (instead of copying) the parent. Since %parent
860+ // is initialized from a value in the constructor of %VauHandler which
861+ // only accepts checked values, it need no redundant check in the
862+ // constructor of %Environment, hence the argument should also not be
863+ // used for %GuardFreshEnvironment.
873864 auto gd(GuardFreshEnvironment(ctx));
874865
875866 vau.BindEnvironment(ctx, std::move(r_env));
@@ -1333,7 +1324,7 @@
13331324 {
13341325 auto& tm(AccessFirstSubterm(nd));
13351326
1336- YAssert(!IsSticky(tm.Tags), "Invalid tags found.");
1327+ YAssert(!IsSticky(tm.Tags), "Invalid representation found.");
13371328 return f(tm, p_ref);
13381329 }
13391330 ThrowInsufficientTermsError(nd, p_ref);
@@ -1563,7 +1554,7 @@
15631554 auto first(nd.begin());
15641555 const auto last(nd.end());
15651556
1566- YAssert(!IsSticky(first->Tags), "Invalid tags found.");
1557+ YAssert(!IsSticky(first->Tags), "Invalid representation found.");
15671558 ++first;
15681559 // XXX: The transaction is not for providing more enhanced exception safety,
15691560 // but being more consistent to derived implementations.
@@ -1592,7 +1583,9 @@
15921583 if(IsPair(nd))
15931584 {
15941585 TermNode::Container tcon(term.get_allocator());
1595- YAssert(!IsSticky(nd.begin()->Tags), "Invalid tags found.");
1586+
1587+ YAssert(!IsSticky(nd.begin()->Tags),
1588+ "Invalid representation found.");
15961589 f(tcon, nd, p_ref);
15971590 tcon.swap(term.GetContainerRef());
15981591 }
@@ -1627,6 +1620,7 @@
16271620 SetFirstRest([f](TermNode& nd_x, TermNode& y){
16281621 auto& dst(AccessFirstSubterm(nd_x));
16291622
1623+ AssertValueTags(dst);
16301624 if(const auto p = TryAccessLeafAtom<TermReference>(y))
16311625 f(dst, y, *p);
16321626 else
@@ -1757,7 +1751,7 @@
17571751 NameTypedReducerHandler([&, i, wrap, no_lift]{
17581752 return ReduceCreateFunction(term, [&]{
17591753 // XXX: Keep %ResolveParentFrom in lambda-expression is a bit more
1760- // efficient for x86_64-pc-linux G++ 12.1.
1754+ // efficient with x86_64-pc-linux G++ 12.1.
17611755 return MakeVau(term, no_lift, _rShift, i, [&]{
17621756 return ResolveParentFrom(tm);
17631757 }());
@@ -1897,6 +1891,11 @@
18971891 {
18981892 if(first1 != last1)
18991893 {
1894+ YAssert(!IsSticky(NPL::Deref(first1).Tags),
1895+ "Invalid representation found."),
1896+ YAssert(!IsSticky(NPL::Deref(first2).Tags),
1897+ "Invalid representation found.");
1898+
19001899 auto& x(ReferenceTerm(NPL::Deref(first1)));
19011900 auto& y(ReferenceTerm(NPL::Deref(first2)));
19021901
@@ -2595,7 +2594,7 @@
25952594
25962595 //! \since build 945
25972596 //@{
2598-// XXX: Having 'YB_ATTR(always_inline)' here makes performace significantly
2597+// XXX: Having 'YB_ATTR_always_inline' here makes performace significantly
25992598 // better, at least with x86_64-pc-linux G++ 12.1. However, it will also warns
26002599 // about failing to inline with [-Wattributes]. To work it around, just ignore
26012600 // the warning here (and it seems that there is no effect to ignore it around
@@ -3054,6 +3053,7 @@
30543053 // XXX: As the following code with lower expansion level, but more
30553054 // specialized.
30563055 YAssert(term.size() >= 3, "Invalid nested call found.");
3056+
30573057 auto j(term.begin());
30583058 auto& operand(*j);
30593059 auto& formals(*++j);
@@ -3900,6 +3900,10 @@
39003900 ReductionStatus
39013901 FirstRef(TermNode& term)
39023902 {
3903+ // XXX: The pointer for the call to %ReduceToReference is guarnateed not
3904+ // null. However, explicit inline expansion here does not make it more
3905+ // efficient at least in code generation by x86_64-pc-linux G++ 12.1 when
3906+ // not called.
39033907 return FirstAtRef(term, ReduceToReference);
39043908 }
39053909
@@ -3986,8 +3990,8 @@
39863990 // NOTE: As %BindParameterObject::operator()#2 in NPLA1.cpp.
39873991 // XXX: Initial tags are trailing sequence tags for '&' bindings.
39883992 const auto tags(GetLValueTagsOf(nd.Tags | o_tags));
3989- TermNode t(a);
3990- auto& tcon(t.GetContainerRef());
3993+ auto p_sub(A1::AllocateSharedTerm(a));
3994+ auto& tcon(p_sub->GetContainerRef());
39913995 const auto& r_env(p_ref->GetEnvironmentReference());
39923996
39933997 for(; first != nd.end() && !IsSticky(first->Tags); ++first)
@@ -4017,18 +4021,11 @@
40174021 #endif
40184022 }
40194023 if(nd.Value)
4020- LiftTermRef(t.Value, nd.Value);
4024+ LiftTermRef(p_sub->Value, nd.Value);
40214025 else
40224026 YAssert(first == nd.end(), "Invalid representation found.");
4023-
4024- auto p_sub(A1::AllocateSharedTerm(a, std::move(t)));
4025- auto& sub(NPL::Deref(p_sub));
4026-
4027- tcon.clear();
4028- tcon.push_back(MakeSubobjectReferent(a, std::move(p_sub)));
4029- term.GetContainerRef() = std::move(tcon),
4030- term.Value = ValueObject(std::allocator_arg, a,
4031- in_place_type<TermReference>, tags, sub, r_env);
4027+ return
4028+ ReduceAsSubobjectReference(term, std::move(p_sub), r_env, tags);
40324029 }
40334030 return ReductionStatus::Retained;
40344031 }, term);
@@ -5066,20 +5063,28 @@
50665063 auto i_comb(++i);
50675064 auto& comb(*i_comb);
50685065
5069- // NOTE: As %ContinuationToApplicative.
5070- NPL::ResolveTerm([&](TermNode& nd, ResolvedTermReferencePtr p_ref){
5071- WrapO(comb, AccessRegular<Continuation>(nd, p_ref).Handler, p_ref);
5072- }, comb);
5073- comb.ClearContainer();
5074- // NOTE: As %ApplyImpl.
5075- ForwardToUnwrapped(comb);
5066+ AssertValueTags(comb);
50765067 [&] YB_LAMBDA_ANNOTATE(() , , flatten){
5068+ // NOTE: As %ContinuationToApplicative and %ApplyImpl.
5069+ ResolveTerm([&](TermNode& nd, ResolvedTermReferencePtr p_ref){
5070+ auto& h(AccessRegular<Continuation>(nd, p_ref).Handler);
5071+
5072+ comb.Value = A1::MakeForm(comb, MakeValueOrMove(p_ref, [&]{
5073+ return h;
5074+ }, [&]{
5075+ return std::move(h);
5076+ }));
5077+ }, comb);
5078+ comb.ClearContainer();
5079+
50775080 auto& t(*++i);
50785081
50795082 LiftToReturn(t);
50805083 t.GetContainerRef().splice(t.begin(), term.GetContainerRef(), i_comb);
50815084 LiftOtherValue(term, t);
50825085 }();
5086+ // XXX: Explicit inline expansion here does not make it more efficient at
5087+ // least in code generation by x86_64-pc-linux G++ 12.1 when not called.
50835088 return Combine<TailCall>::RelayEnvSwitch(ctx, term,
50845089 NPL::AllocateEnvironment(term.get_allocator()));
50855090 }
diff -r 479ab8c91071 -r 05c8e54ed1bb YFramework/source/YSLib/Core/YApplication.cpp
--- a/YFramework/source/YSLib/Core/YApplication.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YFramework/source/YSLib/Core/YApplication.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2009-2016, 2020-2021 FrankHB.
2+ © 2009-2016, 2020-2022 FrankHB.
33
44 This file is part of the YSLib project, and may only be used,
55 modified, and distributed under the terms of the YSLib project
@@ -11,13 +11,13 @@
1111 /*! \file YApplication.cpp
1212 \ingroup Core
1313 \brief 系统资源和应用程序实例抽象。
14-\version r1752
14+\version r1757
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since 早于 build 132
1717 \par 创建时间:
1818 2009-12-27 17:12:36 +0800
1919 \par 修改时间:
20- 2021-12-21 22:12 +0800
20+ 2022-09-03 21:39 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -35,6 +35,10 @@
3535 Application::Application()
3636 : Shell()
3737 {}
38+Application::Application(allocator_type a)
39+ : Shell(),
40+ on_exit(a), qMain(a)
41+{}
3842 Application::~Application()
3943 {
4044 // See $2020-04 @ %Documentation::Workflow.
diff -r 479ab8c91071 -r 05c8e54ed1bb YSTest/include/Shells.h
--- a/YSTest/include/Shells.h Mon Aug 22 05:35:12 2022 +0800
+++ b/YSTest/include/Shells.h Mon Sep 05 21:43:00 2022 +0800
@@ -15,13 +15,13 @@
1515 /*! \file Shells.h
1616 \ingroup YReader
1717 \brief Shell 框架逻辑。
18-\version r2955
18+\version r2967
1919 \author FrankHB <frankhb1989@gmail.com>
2020 \since 早于 build 132
2121 \par 创建时间:
2222 2010-03-06 21:38:16 +0800
2323 \par 修改时间:
24- 2021-10-22 18:05 +0800
24+ 2022-09-04 22:36 +0800
2525 \par 文本编码:
2626 UTF-8
2727 \par 模块名称:
@@ -33,15 +33,11 @@
3333 #define INC_YReader_Shells_h_ 1
3434
3535 #include <YSBuild.h>
36-#include YFM_DS_Helper_Shell_DS
36+#include YFM_DS_Helper_Shell_DS // for Environment;
3737 #include YFM_Helper_ShellHelper
3838 #include YFM_YCLib_Input
3939 #include YFM_YSLib_UI_Loader
40-#define YReader_Impl_TestNPL true
41-#if YReader_Impl_TestNPL
42-# include YFM_NPL_Lexical // for NPL::pmr::memory_resource;
43-# include <iosfwd> // for std::istream, std::ostream;
44-#endif
40+#include <iosfwd> // for std::istream;
4541
4642 namespace YSLib
4743 {
@@ -104,13 +100,9 @@
104100 SDst = 64);
105101
106102
107-//! \since build 928
108-//@{
109-#if YReader_Impl_TestNPL
103+//! \since build 954
110104 void
111-TestNPL(NPL::pmr::memory_resource&, std::istream&&, std::ostream&);
112-#endif
113-//@}
105+TestNPL(Environment&, std::istream&&);
114106
115107 } // namespace YReader;
116108
diff -r 479ab8c91071 -r 05c8e54ed1bb YSTest/source/Shells.cpp
--- a/YSTest/source/Shells.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YSTest/source/Shells.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file Shells.cpp
1212 \ingroup YReader
1313 \brief Shell 框架逻辑。
14-\version r6482
14+\version r6555
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since 早于 build 132
1717 \par 创建时间:
1818 2010-03-06 21:38:16 +0800
1919 \par 修改时间:
20- 2022-02-14 07:53 +0800
20+ 2022-09-05 00:51 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -25,19 +25,12 @@
2525 */
2626
2727
28-#include "Shells.h"
28+#include "Shells.h" // for std::throw_with_nested;
2929 #include "ShlExplorer.h"
3030 #include "ShlReader.h"
3131 #include <ytest/timing.hpp>
32-#if YReader_Impl_TestNPL
33-# if YF_Hosted
34-# define YReader_Impl_TestNPL_UseBacktrace true
35-# include <ystdex/scope_guard.hpp> // for ystdex::make_guard;
36-# define YReader_Impl_TestNPL_UseSourceInfo true
37-# endif
38-# include YFM_NPL_Dependency // for NPL, LoadStandardContext, InvokeIn,
39-// ContextNode;
40-#endif
32+#include YFM_NPL_Dependency // for NPL, A1::Forms::InvokeIn;
33+#include YFM_Helper_Environment // for complete Environment;
4134
4235 namespace YReader
4336 {
@@ -173,77 +166,18 @@
173166 }
174167
175168
176-#if YReader_Impl_TestNPL
177169 void
178-TestNPL(NPL::pmr::memory_resource& rsrc, std::istream&& is, std::ostream& os)
170+TestNPL(Environment& env, std::istream&& is)
179171 {
180172 using namespace NPL;
181- using namespace A1;
182- using namespace Forms;
183- REPLContext context{rsrc};
184- TermNode term{context.Allocator};
185-# if YReader_Impl_TestNPL_UseBacktrace
186- ContextNode::ReducerSequence backtrace{context.Allocator};
187-# endif
188-
189-# if YReader_Impl_TestNPL_UseSourceInfo
190- context.UseSourceLocation = true;
191-# endif
192- LoadStandardContext(context);
193- context.OutputStreamPtr = NPL::make_observer(&os);
194-
195- auto& rctx(context.Root);
196173
197- InvokeIn(rctx, [&]{
198- context.ShareCurrentSource("*TEST*");
199- try
200- {
201- context.Root.Rewrite(NPL::ToReducer(context.Allocator, trivial_swap,
202- [&](ContextNode& ctx){
203- ctx.SaveExceptionHandler();
204- // TODO: Blocked. Use C++14 lambda initializers to simplify the
205- // implementation.
206- ctx.HandleException = ystdex::bind1([&](std::exception_ptr p,
207- const ContextNode::ReducerSequence::const_iterator& i){
208- ctx.TailAction = nullptr;
209-# if YReader_Impl_TestNPL_UseBacktrace
210- ctx.Shift(backtrace, i);
211-# else
212- yunused(i);
213-# endif
214- YAssertNonnull(p);
215- TryExpr(std::rethrow_exception(std::move(p)))
216- catch(std::exception& e)
217- {
218-# if YReader_Impl_TestNPL_UseBacktrace
219- const auto gd(ystdex::make_guard([&]() ynothrowv{
220- backtrace.clear();
221- }));
222-# endif
223- auto& trace(ctx.Trace);
224-
225- TraceException(e, trace);
226- trace.TraceFormat(Notice, "Location: %s.",
227- context.CurrentSource
228- ? context.CurrentSource->c_str() : "<unknown>");
229-# if YReader_Impl_TestNPL_UseBacktrace
230- TraceBacktrace(backtrace, trace);
231-# endif
232- // NOTE: As %Tools.SHBuild.Main.
233- throw NPLException("Error detected in the execution"
234- " (see the backtrace for details).");
235- }
236- }, ctx.GetCurrent().cbegin());
237- term = context.ReadFrom(is);
238- return A1::ReduceOnce(term, ctx);
239- }));
240- }
241- // NOTE: As %A1::TryLoadSource.
242- CatchExpr(..., std::throw_with_nested(
243- NPLException("Failed loading the test unit.")));
244- });
174+ TryExpr(env.ExecuteNPLA1([&](TermNode& term){
175+ term = env.Context.ReadFrom(is);
176+ }))
177+ // NOTE: Like %A1::TryLoadSource, but not in the inner reduction.
178+ CatchExpr(..., std::throw_with_nested(
179+ NPLException("Failed loading the test unit.")))
245180 }
246-#endif
247181
248182 } // namespace YReader;
249183
diff -r 479ab8c91071 -r 05c8e54ed1bb YSTest/source/ShlExplorer.cpp
--- a/YSTest/source/ShlExplorer.cpp Mon Aug 22 05:35:12 2022 +0800
+++ b/YSTest/source/ShlExplorer.cpp Mon Sep 05 21:43:00 2022 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2010-2019, 2021 FrankHB.
2+ © 2010-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 ShlExplorer.cpp
1212 \ingroup YReader
1313 \brief 文件浏览器。
14-\version r1628
14+\version r1664
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 390
1717 \par 创建时间:
1818 2013-03-20 21:10:49 +0800
1919 \par 修改时间:
20- 2021-10-23 00:06 +0800
20+ 2022-09-04 22:38 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -26,25 +26,14 @@
2626
2727
2828 #include "ShlExplorer.h" // for ystdex::polymorphic_cast, ystdex::tolower,
29-// to_string, make_string_view, YReader_Impl_TestNPL, NPL::pmr::pool_resource,
30-// TestNPL;
29+// to_string, make_string_view, TestNPL;
3130 #include "ShlReader.h"
3231 #include YFM_YSLib_UI_ExStyle
33-#include <ystdex/functional.hpp> // for ystdex::bind1;
34-#if YReader_Impl_TestNPL
35-# include YFM_YSLib_Core_YShellDefinition // for YSLib::ostringstream,
32+#include <ystdex/bind.hpp> // for ystdex::bind1;
33+#include YFM_YSLib_Core_YShellDefinition // for YSLib::ostringstream,
3634 // YSLib::string, YSLib::istringstream;
37-# if YF_Hosted
38-# include <iostream> // for std::cout;
39-# if YCL_Win32 && defined(NDEBUG)
40-// XXX: Use Win32 subsystem.
41-# define YReader_Impl_TestNPL_NoStdout true
42-# endif
43-# else
44-# define YReader_Impl_TestNPL_NoStdout true
45-# endif
46-# include YFM_NPL_Dependency // for NPL, LoadStandardContext, InvokeIn;
47-#endif
35+#include YFM_Helper_Environment // for YF_Helper_Environment_UseStdout;
36+#include YFM_Helper_Initialization // for FetchEnvironment;
4837
4938 namespace YReader
5039 {
@@ -235,6 +224,12 @@
235224 IO::Path
236225 FetchDefaultShellDirectory()
237226 {
227+ // NOTE: It is intended to get the current working directory as the entry of
228+ // the shell, except on platforms where the current working directory is
229+ // not steadily available. For example, in Android NDK, the current working
230+ // directory is "/", which is usually not accessible by unprivileged
231+ // processes. And in Windows CE, there is no current working directory at
232+ // all.
238233 #if YCL_Android
239234 return
240235 Path(AccessChild<string>(FetchRoot()["YFramework"], "DataDirectory"));
@@ -607,32 +602,28 @@
607602 #endif
608603 if(e.Value == 0)
609604 SwitchVisibleToFront(pnlTest1);
610-#if YReader_Impl_TestNPL
611605 else if(e.Value == 1)
612606 {
613- // TODO: Share the resource with other tests?
607+ // TODO: Share more resources with other tests?
614608 // TODO: Count allocation & memory stats?
609+ auto& env(FetchEnvironment());
615610 // TODO: Use something like %boost::tee_device to duplicate the
616611 // output result for both the standard output and GUI output?
617- NPL::pmr::pool_resource rsrc;
618-# if YReader_Impl_TestNPL_NoStdout
619- YSLib::ostringstream os{YSLib::string(&rsrc)};
620-# else
621- auto& os(std::cout);
622-# endif
612+#if !YF_Helper_Environment_UseStdout
613+ auto& os(env.DefaultOutputStream);
614+#endif
623615 const char unit[]{R"NPL(
624616 $import! std.io &puts;
625617
626618 puts "ShlExplorer: Hello, world!";
627619 )NPL"};
628620
629- TestNPL(rsrc, YSLib::istringstream(unit), os);
630-# if YReader_Impl_TestNPL_NoStdout
621+ TestNPL(env, YSLib::istringstream(unit));
622+#if !YF_Helper_Environment_UseStdout
631623 lblInfo.Text = os.str();
632624 Invalidate(lblInfo);
633-# endif
625+#endif
634626 }
635-#endif
636627 },
637628 AddWidgetsZ(GetSubDesktop(), DefaultMenuZOrder, m0, m1),
638629 mhMain += m0, mhMain += m1,
diff -r 479ab8c91071 -r 05c8e54ed1bb doc/ChangeLog.V0.9.txt
--- a/doc/ChangeLog.V0.9.txt Mon Aug 22 05:35:12 2022 +0800
+++ b/doc/ChangeLog.V0.9.txt Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file ChangeLog.V0.9.txt
1212 \ingroup Documentation
1313 \brief 版本更新历史记录 - V0.9 。
14-\version r11098
14+\version r11302
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 800
1717 \par 创建时间:
1818 2020-10-12 17:19:23 +0800
1919 \par 修改时间:
20- 2022-08-22 05:03 +0800
20+ 2022-09-05 21:41 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -32,6 +32,195 @@
3232
3333 $now
3434 (
35+ / %YFramework $=
36+ (
37+ / %YSLib.Core $=
38+ (
39+ / %YObject $=
40+ (
41+ - DLDI $re_add(b954) "'YSLib::' prefix"
42+ @ "calls to %YSLib::make_observer",
43+ // As %NPL changes in b947.
44+ * "ill-formed type access" @ "function %Equals"
45+ @ "class template %PolymorphicValueHolder" $since b899
46+ ),
47+ + "allocator support" @ "class %MessageQueue" @ %YMessage $=
48+ (
49+ + 'using BaseType::get_allocator;';
50+ + "constructor with 1 allocator parameter",
51+ + 'using BaseType::get_allocator;'
52+ ),
53+ + "allocator support" @ "class %Application" @ %YApplication $=
54+ (
55+ + "alias %allocator_type";
56+ + "constructor with 1 allocator parameter" ^ $dep_from
57+ ("constructor %MessageQueue with 1 allocator parameter"
58+ @ %YMessage),
59+ + "function %get_allocator"
60+ ^ $dep_from ("%MessageQueue::get_allocator @ "%YMessage)
61+ )
62+ ),
63+ / DLDI "internal header inclusion" @ %'Helper_(DS)'.DSMain
64+ ^ %YSLib.UI.YGUI,
65+ / %NPL $=
66+ (
67+ / %Dependency $=
68+ (
69+ / @ "function %Forms::LoadGroundContext" $=
70+ (
71+ / @ "alternative derivation" @ "applicative 'rest&'" $=
72+ (
73+ * $revert_ex(b953) "unexpected uncollapsed elements \
74+ in the result" $since b953;
75+ $= (/ $impl ^ '&' ~ '@');
76+ * "xvalue arguments not properly preserved in the \
77+ result" $since b951
78+ $= (/ $impl ^ '$resolve-identifier')
79+ )
80+ ),
81+ / "reducer name 'recover-source-name'" => 'restore-source-name'
82+ $effective @ "functions %(ReduceToLoadExternal, \
83+ RelayToLoadExternal, Forms::LoadModule_std_modules)",
84+ / "function templates %(InvokeIn, GetModuleFor, LoadModule, \
85+ LoadModuleChecked)" @ "namespace %Forms"
86+ >> ("namespace %A1" @ %NPLA1)
87+ ),
88+ / %NPLA $=
89+ (
90+ + $dev $lib 'YB_ATTR_nodiscard'
91+ @ "all 3 function templates %AllocateEnvironment",
92+ (
93+ + "4 functions %AssignParent";
94+ + "function template %AssignParent",
95+ + "2 functions %AssignWeakParent"
96+ )
97+ ),
98+ / %NPLA1 $=
99+ (
100+ / @ "trailing sequence binding" @ "functions %(BindParameter, \
101+ BindParameterWellFormed, BindSymbol)" $=
102+ (
103+ + $design "alternative implementation of creation of the \
104+ subobject reference" ^ "%ReduceAsSubobjectReference",
105+ // This is not enabled, because the current \
106+ implementation is better a bit in performance.
107+ ^ $re_add(b953) $design '*' ~ "%NPL::Deref",
108+ / "optimized subpair creation"
109+ ),
110+ * "wrong handling of trailing arguments"
111+ @ "function template %GuardFreshEnvironment" $since b945,
112+ // It would be ill-formed if there is any argument.
113+ / DLI "removed redundant check on the parent" @ "function \
114+ templates %(InvokeIn, GetModuleFor)"
115+ ^ "%GuardFreshEnvironment" $dep_from
116+ ("%Forms::(InvokeIn, GetModuleFor)" @ %Dependency),
117+ ),
118+ / %NPLA1Forms %=
119+ (
120+ + $dev $lib "assertion to check against the sticky tag"
121+ @ ("function %Forms::EqualTermValue",
122+ "static member function %Encapsulation::Equal"),
123+ / @ "namespace %Forms" $=
124+ (
125+ / $dev $lib "assertion string for sticky tag check failure"
126+ @ "functions %(First, FirstVal, Rest, RestFwd, \
127+ RestVal, Let, LetRef, LetWithEnvironment, \
128+ LetWithEnvironmentRef, LetRec, LetRecRef, LetAsterisk, \
129+ LetAsteriskRef, BindingsWithParentToEnvironment, \
130+ BindingsToEnvironment)",
131+ // To be more consistent with other similar \
132+ implementations.
133+ / DLI "simplified function %RestRef"
134+ ^ "%ReduceAsSubobjectReference",
135+ / $re_add(b853) DLI "checked to ensure first-class object \
136+ representation in the subterm" @ "functions \
137+ %(SetFirst, SetFirstAt, SetFirstRef, ApplyContinuation)"
138+ ^ "%AssertValueTags",
139+ / DLI "simplified function %ApplyContinuation",
140+ / DLDI "simplified" @ ("%operator" @ "vau handler",
141+ "functions whose name have prefix 'Let' or 'Provide'")
142+ $dep_from
143+ ^ ("%(AssignParent, AssignWeakParent)" @ %NPLA)
144+ )
145+ )
146+ ),
147+ / %Helper $=
148+ (
149+ / %GUIApplication $=
150+ (
151+ / DLI "allocated %Environment with allocator"
152+ @ "class %GUIApplication"
153+ ^ $dep_from ("%Application::(allocator_type, get_allocator)"
154+ @ %YSLib.Core.Application),
155+ (
156+ / "function %Execute" -> "2 functions" $=
157+ (
158+ - "default argument";
159+ + "overload with 1 parameter"
160+ ^ $dep_from ("%Application::get_allocator"
161+ @ %YSLib.Core.Application)
162+ );
163+ - "header inclusion %GUIShell" $dep_from %'Helper_(DS)'.DSMain
164+ )
165+ )
166+ / %Environment $=
167+ (
168+ / DLI @ "constructor %Environment" $=
169+ (
170+ / $design "simplified" @ "platform %DS" ^ (("%make_any"
171+ ~ "%(any, in_place_type)") @ %YSLib.Core.YObject),
172+ / ^ "allocator" @ "initalizing %Root"
173+ ^ $dep_from ("%Application::get_allocator"
174+ @ %YSLib.Core.YApplication),
175+ * $design "redundant unused %string variable" $since b725
176+ ),
177+ (
178+ + "macros %(YF_Helper_Environment_UseStdout, \
179+ YF_Helper_Environment_NPL_UseBacktrace, \
180+ YF_Helper_Environment_NPL_UseSourceInfo";
181+ / @ "class %Environment" $=
182+ (
183+ + "data members %(DefaultOutputStream, Context)";
184+ + "non-trivial initialization of %NPL::REPLContext"
185+ @ "constructor",
186+ + "2 function templates %ExecuteNPLA1"
187+ $dep_from ("%InvokeIn" @ %NPL.Dependency)
188+ )
189+ )
190+ )
191+ )
192+ ),
193+ / %YReader $=
194+ (
195+ / %Shells $=
196+ (
197+ / @ "function %TestNPL" $=
198+ (
199+ / "simplified" ^ $dep_from ("%Environment::ExecuteNPLA1"
200+ @ %YFramework.Helper.Environment);
201+ * $comp "mentioned backtrace in the message of the nested \
202+ exception when the backtrace is not used" $since b928,
203+ // This should not affect the call site in %ShlExplorer \
204+ since it should not fail to throw the exception.
205+ - "'NPL::pmr::memory_resource&', 'std::ostream&' parameters",
206+ + "'Environment&' parameter"
207+ );
208+ - "header inclusion %NPL::Lexical"
209+ ),
210+ / DLI %ShlExplorer $=
211+ (
212+ / $re_add(b942) $design "header inclusion %Functional" -> %Bind,
213+ / $forced "NPL test entry for test subitem 2"
214+ @ "constructor %ShlExplorer" $dep_from ("%TestNPL" @ %Shells)
215+ ^ $dep_from (("%Environment::DefaultOutputStream",
216+ "%YF_Helper_Environment_UseStdout")
217+ @ %YFramework.Helper.Environment)
218+ )
219+ )
220+),
221+
222+b953
223+(
35224 / DD %Documentation.NPL $=
36225 (
37226 * "inconsistent grammar of alternative expressions" $since b855
@@ -180,7 +369,7 @@
180369 reprensentation",
181370 + $dev $lib "assertion to ensure the operand term having no \
182371 sticky bit",
183- / @ "binding trailing sequence" $=
372+ / @ "trailing sequence binding" $=
184373 (
185374 / $re_ex(b952) DLDI "simplified allocator using",
186375 // This is more consistent to non-trailing sequence \
@@ -250,7 +439,7 @@
250439 / @ "function %LoadGroundContext" %Dependency $=
251440 (
252441 * "missing preserving reference value in the result"
253- @ "applicative 'list*%'" $since b951
442+ @ "alternative derivation" @ "applicative 'list*%'" $since b918
254443 $= (/ ^ '$lambda%' ~ '$lambda'),
255444 * $comp "missing ignoring non-leaf values" @ ("applicative 'eql?'"
256445 $dep_from "%EqLeaf" @ %NPLA1Forms, "applicative 'eqr?'"
@@ -279,8 +468,9 @@
279468 @ "alternative derivation" @ "applicative 'first&'" $since b939,
280469 * $comp "native implementation" @ "applicative 'rest%'" $since b951
281470 $dep_from ("%RestRef" @ %NPLA1Forms),
282- * "misleading error message for improper lists" @ "derivation"
283- @ "applicatives ('list%', 'list*%')" $since b951
471+ * "misleading error message for improper lists"
472+ @ "alternative derivation" @ "applicatives ('list%', 'list*%')"
473+ $since b951
284474 // It would report expecting a pair (by binding \
285475 mismatching in the last recursive call) instead of \
286476 a list.
@@ -430,7 +620,7 @@
430620 %ListExtractFirst and other binding functions"
431621 ^ "%AssertValueTags",
432622 // To be consistent with the changes below.
433- * $re_add(b925) "missing clear %TermTags::Termporary for \
623+ * $re_add(b925) "missing clearing %TermTags::Temporary for \
434624 nested list elements from the referent" @ ("functions \
435625 %(ListContcat, Append)" $since b912, "function %RestFwd"
436626 $since b913, "functions %(FoldR1, Map1)" $since b899)
@@ -1129,8 +1319,14 @@
11291319 $dep_from ("%MakeParameterValueMatcher" @ %NPLA1Internals)
11301320 // As %(MatchParameter, BindParameter, BindParamaterWellFormed).
11311321 ),
1132- + "message after linking finished" @ "member function %BuildContext::Build"
1133- @ %Tools.SHBuild.Main
1322+ / %Tools.SHBuild.Main $=
1323+ (
1324+ - DLDI "'NPL::' prefix" @ "calls to %NPL::make_observer",
1325+ // As %NPL changes in b947, but with a different reason: the name \
1326+ is introced by a using directive.
1327+ + "message after linking finished"
1328+ @ "member function %BuildContext::Build"
1329+ )
11341330 ),
11351331
11361332 b948
@@ -2814,7 +3010,7 @@
28143010 * "unexpected ADL '!' of traits results"
28153011 $effective @ %YBase.YStandardEx.(Any, CompressedPair, Optional),
28163012 + DLDI "%yunused" @ '!YReader_Impl_TestNPL_UseBacktrace'
2817- @ "function %TestNPL" @ %YSTest.Shells
3013+ @ "function %TestNPL" @ %YSTest.Shells,
28183014 // To eliminate G++ warning in release modes: [-Wunused-parameter].
28193015 / %YBase.YStandardEx $=
28203016 (
@@ -5935,7 +6131,7 @@
59356131 conversion" @ "reducer functions and binding parameter \
59366132 functions" @ %(NPLA1, NPLA1Forms) $since b857
59376133 $dep_from ("%LiftSubtermsToReturn" @ %NPLA),
5938- * "missing clear %TermTags::Termporary of the result from \
6134+ * "missing clearing %TermTags::Temporary of the result from \
59396135 possibly bound objects in referents" @ (("function \
59406136 %LiftMovedOther" $since b876; $comp ("function \
59416137 %MoveRValueToForward" $since b872, "function \
diff -r 479ab8c91071 -r 05c8e54ed1bb doc/Definitions.txt
--- a/doc/Definitions.txt Mon Aug 22 05:35:12 2022 +0800
+++ b/doc/Definitions.txt Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file Definitions.txt
1212 \ingroup Documentation
1313 \brief 方法和公共域定义与说明。
14-\version r14477
14+\version r14483
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since 早于 build 132
1717 \par 创建时间:
1818 2010-01-26 19:34:51 +0800
1919 \par 修改时间:
20- 2022-08-01 19:02 +0800
20+ 2022-09-04 11:31 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -578,6 +578,12 @@
578578 {
579579 DefDynInitRef(_t, _n, _e)
580580 }
581+$header Environment
582+{
583+YF_Helper_Environment_UseStdout
584+YF_Helper_Environment_NPL_UseBacktrace
585+YF_Helper_Environment_NPL_UseSourceInfo
586+}
581587 } // $dir Helper;
582588 } // $dir YFramework;
583589
diff -r 479ab8c91071 -r 05c8e54ed1bb doc/NPL.txt
--- a/doc/NPL.txt Mon Aug 22 05:35:12 2022 +0800
+++ b/doc/NPL.txt Mon Sep 05 21:43:00 2022 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPL.txt
1212 \ingroup Documentation
1313 \brief NPL 规范和实现规格说明。
14-\version r29598
14+\version r29667
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 304
1717 \par 创建时间:
1818 2012-04-25 10:34:20 +0800
1919 \par 修改时间:
20- 2022-08-22 02:42 +0800
20+ 2022-09-05 08:39 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -2017,14 +2017,18 @@
20172017 空列表(empty list) 是不含有元素的列表。
20182018 每个真列表和有限个有序对(pair) 的嵌套组合表示同构。每个有序对具有两个元素。
20192019 有序对的第二个元素是列表时,则有序对是(非空的)真列表。否则,有序对是非真列表(improper list) 。
2020-以嵌套的有序对表示的列表中,若最后一个有序对的第二个元素是空列表,则有序对时真列表。除了这个空列表外,其余有序对中的元素都是列表的元素。
20212020 NPLA 对象不支持自引用和循环数据结构(@4.2.4) ,因此非真列表是无环(acyclic) 的,不包含环(cycle) 。
20222021 NPLA 广义列表是真列表或无环非真列表。
2022+取得嵌套的有序对的广义列表的同构表示分解(decompose) 这个广义列表。广义列表分解后若得到有序对,可继续被分解。经有限次分解后,广义列表不再可取得不同的同构表示,即被完全分解。
2023+广义列表的元素是其完全分解后得到的元素,且当广义列表是真列表时,最后一个(空列表)元素。
2024+广义列表对元素具有所有权。同一个广义列表的不同元素之间不具有所有权,生存期不相交。
20232025 除非另行指定,以下列表指真列表。
2024-广义列表的元素是构成广义列表的对象,广义列表对元素具有所有权。
2025-**注释**
2026-构造有序对的操作称为 cons ,有序对又称为 cons 对。
2027-无环非真列表和真列表类似,可通过 cons 逐次构造,区别是逻辑上结尾不含空元素。
2026+子有序对(subpair) 是一个有序对完全分解的序列中的元素的真子集构成的子对象。
2027+子列表(sublist) 是一个列表中的元素的真子集构成的列表子对象。
2028+**注释**
2029+一些编程语言中,构造有序对的操作称为 cons ,有序对又称为 cons 对。
2030+无环非真列表和真列表类似,可通过 cons 逐次构造。
2031+作为真列表和有序对结构定义的推论,无环非真列表最后一个元素不是空列表。
20282032
20292033 @5.6 存储和对象模型:
20302034 NPLA 使用统一的模型对存储和对象进行抽象,并提供若干保证。
@@ -3014,9 +3018,7 @@
30143018
30153019 @6.3.9.1 无环非真列表(@5.5.1) :
30163020 无环非真列表是不属于其它情形的非正规表示可表示的一等对象,具有至少一个子项表示一等对象。
3017-不考虑所有权时,无环非真列表总是能被表示为一个元素和一个非列表元素构成的有序对(@5.5.1) 。取得无环非真列表的有序对形式的表示分解(decompose) 这个无环非真列表。
3018-无环非真列表分解后的第二个元素可能继续可被分解。经有限次这样的分解后第二个元素不再是有序对而不能继续分解,得到完全分解的元素序列。除非另行指定,无环非真列表的元素是其完全分解得到的元素。
3019-推论:无环非真列表最后一个元素不是空列表。
3021+不考虑所有权时,无环非真列表总是能被表示为一个元素和一个非列表元素构成的有序对(@5.5.1) 。
30203022 类似真列表(@6.2.1) :
30213023 无环非真列表不支持环;
30223024 无环非真列表对其中的元素具有所有权,但其中的元素的销毁和释放顺序未指定。
@@ -3345,7 +3347,7 @@
33453347 为避免引入循环引用(@4.2.4) ,环境强引用应仅在必要时使用,而避免被非预期地捕获(尽管保存环境弱引用和到强引用的转换可能有附加开销)。
33463348 特别地,注意和一等环境不同,NPLA 一等续延(@4.5.3.3) 允许通过一等对象作为其子对象进行构造,但这些子对象之后在对象语言中不保证总是能被访问。
33473349 因此,通常应避免在可从上下文(@6.11.3.1) 捕获的一等续延内部捕获环境强引用,以免之后的操作可能使某个无法预知的作为子对象的续延被捕获的环境强引用所有而构成循环引用(这无法通过选择对象语言的构造避免)。
3348-修改当前环境的环境引用(上下文切换)应确保先前的当前环境具有合适的生存期,以避免通过环境弱引用锁定后取得空引用值。上下文切换 API(@6.11.4.2) 可保存此环境强引用。
3350+修改当前环境的环境引用(上下文切换)应确保先前的当前环境具有合适的生存期,以避免通过环境弱引用锁定后取得空引用值。上下文切换 API(@6.11.4.3) 可保存此环境强引用。
33493351 被上下文切换保存的环境同样需要避免循环引用。
33503352 注意上下文切换保存的环境使用环境强引用而不是弱引用,因为它可能是唯一引用,为确保环境对象的生存期,这是必要的。
33513353 一般地,具有这些环境强引用的所有权的资源可能:
@@ -3839,9 +3841,10 @@
38393841 除 shared_ptr<Environment> 的 use_count 的结果外,环境的引用计数具体值是实现细节,不保证具有明确含义的稳定的结果。
38403842
38413843 @6.11.2 上下文相关的规约函数类型别名:
3842-类型 ReducerFunctionType
3844+类型 NPL::ReducerFunctionType
38433845 类型 NPL::Reducer 是以上下文引用作为参数的规约器(@6.12.6) ,保存动作(@6.11.3) 。
3844-NPL::Reduer 能以兼容 ReducerFuntionType 的方式调用,可选提供一个 ContextNode& 参数。
3846+NPL::Reducer 能以兼容 ReducerFuntionType 的方式调用,可选提供一个 ContextNode& 参数。
3847+NPL::Reducer 以类型擦除(@4.7.3) 支持不同的目标类型(@6.2) 。
38453848
38463849 @6.11.3 上下文数据结构:
38473850 上下文(@4.6) 使用类 ContextNode 表示。
@@ -3913,7 +3916,12 @@
39133916 **注释**
39143917 当前实现对保留名称的约定参见 NPLA1 标识符附加规则(@7.1.1.2) 。
39153918
3916-@6.11.4.2 上下文切换:
3919+@6.11.4.2 父环境设置:
3920+以下函数或函数模板重载设置父环境:
3921+NPL::AssignParent
3922+NPL::AssignParentWeak
3923+
3924+@6.11.4.3 上下文切换:
39173925 NPL::EnvironmentSwitcher 类型用于切换上下文(@6.11.3.1) 中的当前环境(@6.11.3) 。
39183926
39193927 @6.12 异步规约(asynchronous reduction) :
@@ -4789,10 +4797,13 @@
47894797 规约合并求值(@7.6.4.2) API ;
47904798 绑定操作(@7.7.3) API 。
47914799
4792-@7.7.2 求值规约操作:
4800+@7.7.2 上下文相关的求值规约操作:
47934801 基于 NPLA 合并动作(@6.12.7) ,NPLA1 提供动作合并规约操作 API :
47944802 类型 A1::EnvironmentGuard
47954803 函数模板 A1::GuardFreshEnvironment
4804+函数模板 A1::InvokeIn
4805+函数模板 A1::GetModuleFor 加载代码作为模块(@1.5.6.4) 以提供特定集合的对象语言实体的定义。
4806+函数模板 A1::LoadModule 和 A1::LoadModuleChecked 加载模块为变量。后者在指定名称的绑定已存在时抛出异常。
47964807 函数 A1::RelayForEval 直接求值(@4.1) 规约:规约并传递求值的结果。
47974808 函数 A1::RelayForCall 函数调用规约( β 规约(@4.5.3) ):规约并传递词法闭包规则(@4.6.1.2) 下求值的结果。
47984809 使用合并动作 API ,可定义依赖这些合并动作的求值规约操作,附加相同的约束。
@@ -5302,23 +5313,31 @@
53025313 TCO 动作是用于实现 TCO 的动作帧(@6.12.6) 。
53035314 TCO 动作支持实现符合 PTC 的尾调用(@5.10.2) 的尾动作(@6.11.3) 。
53045315 TCO 动作支持动态 TCO(@7.10.1) 。
5305-TCO 动作具有特定的非公开类型。为简化实现,减小判断开销,当前是单一的非公开的类型。
5316+TCO 动作具有特定的非公开类型。为简化实现,减小判断开销,当前是单一的非公开的类型,被直接作为 Reducer(@6.11.2) 的目标类型(@6.2) 。
5317+**注释**
5318+为避免 TCO 实现失效,实现在尾上下文中应注意当前动作(@6.11.3) 是 TCO 动作(@7.10.3.2) 。
5319+使用 TCO 动作可实现和 TCO 无关的其它行为同时保持当前动作,参见组成(@7.10.3.1) 。
53065320
53075321 @7.10.3.1 组成:
53085322 TCO 动作包含当前项的引用,以指定一些操作(@7.10.4) 的默认目标。
53095323 TCO 动作也包含以下各节中描述的机制使用的状态:
5310-当前项作为临时对象的守卫(@7.10.7.4) ;
5311-操作结果(@7.10.6.2) 请求状态;
5312-暂存的函数对象(@7.10.7.1) ;
5313-当前处理的尾环境(@7.10.6.1) 的守卫;
5314-帧记录列表(@7.10.5.1) ;
5315-一次调用检查守卫(@7.10.5.3) 。
5316-此外,TCO 动作还包含用于诊断的操作数名称。
5324+ 操作结果(@7.10.6.2) 请求状态。
5325+ 帧记录列表(@7.10.5.1) ,可包含暂存的函数对象(@7.10.7.1) 。
5326+ 当前处理的尾环境(@7.10.6.1) 的守卫。
5327+ 当前项作为临时对象的守卫(@7.10.7.4) 。
5328+ 用于诊断的操作数名称。
5329+ 可选的附加信息,包括:
5330+ 加载翻译单元的元数据(@7.10.5.3) 。
5331+ 一次调用检查守卫(@7.10.5.4) 。
53175332 当前项的引用可在当前项的守卫中蕴含。
5333+**原理**
5334+TCO 动作的组成(@7.10.3.1) 的成员能使被调用时能具有一般其它动作的行为。
5335+若当前组成(因实现性能等原因)需被扩展,应注意在没有使用这些扩展时的一般开销。
5336+可选的附加信息预期支持这类不频繁创建和访问的信息。
53185337
53195338 @7.10.3.2 创建:
53205339 TCO 动作应在依赖 TCO 动作实现 PTC 的尾上下文时已被创建。若能静态确定创建,可不在之后的操作中检查是否已经存在。
5321-对应尾上下文的被创建为当前动作(@6.11.3) 的 TCO 动作是当前 TCO 动作。以下各节中,被访问的当前 TCO 动作应已被及时创建。
5340+对应尾上下文的被创建为当前动作的 TCO 动作是当前 TCO 动作。以下各节中,被访问的当前 TCO 动作应已被及时创建。
53225341 一般地,TCO 动作应通过合并子调用创建操作(@7.6.4.2) 或 A1::SetupTailContext(@7.8) 创建,以确保复用 TCO 资源的调用的存在。
53235342 TCO 动作创建时初始化当前项(@7.10.3.1) 的引用,不在生存期内改变。
53245343
@@ -5441,7 +5460,11 @@
54415460 **原理**
54425461 因为帧记录中资源释放的相对顺序的确定性(@7.10.5.1) ,帧压缩时,仅通过判断环境的引用决定是否能移除整个帧在资源回收的意义上是安全的。
54435462
5444-@7.10.5.3 一次调用检查:
5463+@7.10.5.3 翻译单元元数据:
5464+在 TCO 动作保存源名称,可实现在尾上下文中加载翻译单元后恢复先前的源名称,同时满足 PTC 要求。
5465+保存的源名称可用于诊断。
5466+
5467+@7.10.5.4 一次调用检查:
54455468 TCO 动作的一次调用检查守卫(@7.10.3.1) 保存能在一次续延(@4.5.3.3) 被捕获时的检查对象(@7.4.2.1) 。
54465469 因为捕获续延通过对象语言的合并子调用进入,可假定上下文中总是存在 TCO 动作。
54475470 这使捕获续延的调用满足 PTC 。
@@ -5486,11 +5509,10 @@
54865509
54875510 @7.10.7.1 函数临时对象:
54885511 函数临时对象是构成操作符(@4.4.5.1) 而被调用的活动(@4.5.3.1) 的函数纯右值。在 NPLA1 中,此处的函数即合并子(@4.5.3.2) 。
5489-最近的活动的函数临时对象由暂存的函数对象(@7.10.3.1) 表示。
54905512 在调用函数时,若函数是纯右值,则需在当前 TCO 动作(@7.10.3.2) 中保存函数临时对象。
5491-若其中已存在函数临时对象,则首先在帧记录列表中创建新的帧记录(@7.10.5.1) ,转移暂存的函数对象到帧记录(@7.10.5.1) 。创建的帧记录的环境引用是空值。
5513+最近的活动的函数临时对象由暂存的函数对象(@7.10.3.1) 表示,被附加(attach) 到 TCO 动作的帧记录列表(@7.10.5.1) 的最前一项:创建新的帧记录(@7.10.5.1),其中的环境引用是空值。
54925514 **原理**
5493-在临时对象管理的基础上,在保存函数临时对象前,可能尝试对其与暂存的函数对象(@7.10.3.1) 比较而进行去重(deduplicate) ,以在资源回收(@7.10.5.2) 前即尽可能接近 PTC 的要求:若函数相等,则不添加到已知的函数对象中。
5515+在临时对象管理的基础上,在确定在 TCO 动作中保存函数临时对象前,可能尝试对其与暂存的函数对象(@7.10.3.1) 比较而进行去重(deduplicate) ,以在资源回收(@7.10.5.2) 前即尽可能接近 PTC 的要求:若函数相等,则不添加到已知的函数对象中。
54945516 这不同于帧压缩(@7.10.4) 的资源回收(@7.10.5.2) ,后者针对帧记录列表(@7.10.5.1) ,且不对其中的函数临时对象进行特别的操作。
54955517 纯右值在对象语言中不被别名(@5.8.1) ,但以函数临时对象调用时,仍可通过调用同一个合并子左值的不同副本等方式重入(@4.5.2.2) 。
54965518 一般地,重入的不同调用的函数临时对象是不同的对象,其资源管理相互独立。
@@ -5499,6 +5521,7 @@
54995521 对被去重的函数临时对象,在帧记录(@7.10.5.1) 保存时,只保存其中的一个不重复的函数副本。
55005522 因去重一般并不能确保提升性能,也对本机函数的相等实现有更明确的限制(符合上述约定),因此在当前实现中不再支持。
55015523 转移暂存的函数对象到同一个帧记录,能维持重入的临时对象和对应的环境的资源释放的相对顺序(@7.10.5.1) 。
5524+去重自身存在开销。考虑到可去重的情形远不如添加函数纯右值频繁,当前实现不进行去重。
55025525
55035526 @7.10.7.2 非本机操作数临时对象:
55045527 资源回收支持处理操作数临时对象。资源回收以环境为单位,因此操作数临时对象应绑定到由 TCO 操作对象持有的环境对象上以便回收(@7.10.5.2) 时引用。
@@ -5990,8 +6013,6 @@
59906013 不保证是真合并子(@4.5.3.2) 。
59916014 在对象语言中的对应接口参见 NPLA1 参考实现环境(@10) 。
59926015 模块 NPL::Dependency 还提供其它一些接口,调用函数 Forms::LoadGroundContext 初始化上下文后继续调用,初始化特定操作的环境:
5993-函数模板 Forms::GetModuleFor 加载代码作为模块(@1.5.6.4) 以提供特定集合的对象语言实体的定义。
5994-函数模板 Forms::LoadModule 和 Forms::LoadModuleChecked 加载模块为变量。后者在指定名称的绑定已存在时抛出异常。
59956016 函数 Forms::LoadModule_std_continuations 提供一等续延(@4.5.3.3) 相关操作(@12.1) ;
59966017 函数 Forms::LoadModule_std_promises 提供延迟求值等操作(@12.2) ;
59976018 函数 Forms::LoadModule_std_math 提供数学功能相关操作(@12.3) ;
@@ -6044,7 +6065,7 @@
60446065 get-module-return
60456066 load-external
60466067 promise-handle-result
6047-recover-source-name
6068+restore-source-name
60486069 require-return
60496070 在模块 NPL::Dependency 中,若特定对象语言操作使用非本机实现(@5.3) ,可使用不同的续延名称。
60506071
@@ -6088,7 +6109,7 @@
60886109 load-external :A1::RelayToLoadExternal(@8.5.2) 加载外部翻译单元。
60896110 match-ptree-recursive :支持延迟递归绑定( Forms::DefineWithRecursion 和 Forms::SetWithRecursion(@8.4.4.3) )。
60906111 provide-let-return :Forms::ProvideLet(@8.4.9) 返回环境。
6091-recover-source-name :非 TCO 的 A1::ReduceToLoadExternal 和 A1::RelayToLoadExternal(@8.5.1) 及 Forms::LoadModule_std_modules(@8.5.2) 在加载模块求值后恢复 REPLContext(@7.8) 中保存的源代码名称。
6112+restore-source-name :非 TCO 的 A1::ReduceToLoadExternal 和 A1::RelayToLoadExternal(@8.5.1) 及 Forms::LoadModule_std_modules(@8.5.2) 在加载模块求值后恢复 REPLContext(@7.8) 中保存的源代码名称。
60926113 require-return :异步规约的 LoadModule_std_module 实现 require 加载翻译单元后设置和返回结果。
60936114 sequence-return :非 TCO 的 A1::ReduceOrdered(@7.4.6) 实现中设置规约合并最后的返回结果。
60946115 **注释**
@@ -6664,11 +6685,14 @@
66646685 作为使用名称表达式访问对象(@6.4.6.1) 的推广,特定操作可使用非环境的其它对象显式地访问其子对象。
66656686 这类访问操作包含访问器(@10.5.5) 和其它同时蕴含对象访问的操作。
66666687 除非另行指定,这些访问操作以本节约定的规则确定结果的值类别和类型(@9.7.2) 。
6667-指称非环境对象的 E1 是访问操作的(被求值的)实际参数,子对象来自这个参数指定的对象。具体的访问操作确定具体的被访问的子对象。
6668-访问操作中,若指定结果是引用值,或指定(在结果中)保留引用值(@9.4.4.1) 且被访问的对象实际存在可被保留的引用值,则结果是被访问的子对象的可能经引用折叠(@5.8.3.5) 的引用值;
6669-否则,结果是被访问的被访问的子对象复制初始化(@5.8.2) 的值。
6670-访问操作的结果复制初始化时,按其中使用不同的可转移条件(@5.8.3.6) 判断复制或转移。
6671-访问操作的结果满足值类别对应的类型的等价关系(@6.3.3) 。访问操作中没有明确指定的结果的值类别以此通过结果的类型推断。
6688+若指称非环境对象的 E1 是访问操作的(被求值的)实际参数,子对象来自这个参数指定的对象;
6689+否则,子对象来自 E1 引用的环境对象(@5.7.1) 中的被绑定对象(@5.7.1) 。
6690+具体的访问操作确定具体的被访问的子对象。
6691+访问操作中:
6692+ 若指定结果是引用值,或指定(在结果中)保留引用值(@9.4.4.1) 且被访问的对象实际存在可被保留的引用值,则结果是被访问的子对象的可能经引用折叠(@5.8.3.5) 的引用值。
6693+ 否则,结果是被访问的被访问的子对象复制初始化(@5.8.2) 的值。
6694+ 此时,按可转移条件(@5.8.3.6) 判断复制或转移。
6695+访问操作的结果的值的类型和值类别满足一一对应(@6.3.3) ,且结果经值类别转换后和被访问的子对象的类型相同。访问操作中没有明确指定的结果的值类别以此通过结果的类型推断。
66726696 若通过以上约定,仍没有明确结果的值类别,则按以下默认规则确定:
66736697 若被访问的子对象是引用值,则结果是泛左值。
66746698 否则,若 E1 是左值,则结果是左值。
@@ -6686,7 +6710,6 @@
66866710 因为不存在名称表达式 E2 ,不需要求值算法(@9.7.1) 使用类似 C++ 的 unqualified-id 一致的方式使结果总是左值;
66876711 被访问的对象是右值引用值时,结果是右值引用值(即消亡值),而不一定是左值;
66886712 和 C++ 不同,NPLA 消亡值总是右值引用类型,NPLA 纯右值也此类似 C++ 纯右值实质化转换初始化的消亡值,因此逻辑上需要 C++ 消亡值的情形和此处的 NPLA 右值近似。
6689-传播引用值属性和宿主语言及递归绑定(@7.7.3.6) 规则类似。
66906713 **注释**
66916714 初始化非引用值的复制初始化(包括以下的替换消亡值为右值)可能通过返回值转换(@6.4.6.4) 实现,如不保留引用值(@10.4.3) 的函数返回非引用值(@10.5.3) 。
66926715 在对象表示上,传播引用值的不可修改属性决定 E1 指定的被访问对象或被访问的子对象若具有不可修改标签(@6.2.2) ,结果也具有不可修改标签。
@@ -6694,6 +6717,7 @@
66946717 按默认规则访问相当于这些规则确定的值类似 C++ 表达式 std::forward<decltype(E1.E2)>(E1.E2) 的值。
66956718 具体操作可具有其它改变结果的值类别和类型的约定而实际使用不同的规则。
66966719 例如,推断结果的值类别的规则中的左值和消亡值可被替换为右值,则近似 C++ 表达式 std::forward<std::remove_cvref_t<decltype(E1.E2)>>(E1.E2) 。
6720+传播引用值属性和宿主语言及递归绑定(@7.7.3.6) 规则类似。
66976721 另见引用值作为间接值(@6.4.6.1) 。
66986722
66996723 @9.8.3 对象的修改和改变:
@@ -6963,10 +6987,8 @@
69636987
69646988 @9.9.4.1 有序对的子对象和子对象引用:
69656989 有序对的元素是有序对的子对象(@9.8.2) ,有序对对作为元素的表示具有所有权。同一个有序对的元素节点之间没有所有权关系。
6966-子有序对(subpair) 是一个有序对完全分解的序列中的元素的真子集构成的子对象。
6967-子有序对引用(subpair reference) 是子有序对作为被引用对象的引用。
6968-子列表(sublist) 是一个列表中的元素的真子集构成的列表子对象。
6969-子列表引用(sublist reference) 是子列表作为被引用对象的引用。
6990+子有序对引用(subpair reference) 是子有序对(@5.5.1) 作为被引用对象的引用。
6991+子列表引用(sublist reference) 是子列表(@5.5.1) 作为被引用对象的引用。
69706992 部分操作可能修改(@9.8.3) 有序对的子对象。
69716993 除非另行指定,以子项及值数据成员构成的有序对的子对象被转移(@9.8.3.2) ,使用项的转移(@6.3.6) 。被转移的子对象在被转移后不在被转移的有序对中存在。
69726994 子有序对引用可被绑定构造(@9.7.3) 引入。
@@ -7022,7 +7044,7 @@
70227044 本机调用中不指定下一求值项( klisp_CFunction 没有 TValue 参数),而非 A1::ContextHandler(@7.6.1) 和 A1::Continuation(@7.4.2) 对所有需要依赖下一求值项的实现提供不同层次的封装。
70237045 一等续延依赖 GC 而不维护对本机函数资源的所有权。
70247046 直接使用一等续延的表示 Continuation 作为内部使用的非一等续延的表示且共享相同的规约实现,而非 A1::Continuation 在特定的捕获操作(@8.4.10) 中仍需在其蕴含的 A1::ContextHandler 的目标函数中添加特定的逻辑。
7025- **注释** 这些逻辑实现一次调用检查(@7.10.5.3) ,并确保按引用捕获规约动作,和非一等续延的实现可能直接具有目标函数的所有权不同。
7047+ **注释** 这些逻辑实现一次调用检查(@7.10.5.4) ,并确保按引用捕获规约动作,和非一等续延的实现可能直接具有目标函数的所有权不同。
70267048 使用当前续延的应用( kapply_cc ,非对象语言的 apply-continuation )和合并子调用操作(如 ktail_call )等修改上下文的操作实现异步调用(@6.11.3) 。
70277049 通常不使用组合到当前动作的调用中的(可能同步调用的)函数调用的本机实现。
70287050 通常不单独设置下一求值项。
@@ -8573,8 +8595,8 @@
85738595 在构造结果时,<continuation> 被转发。
85748596 结果的底层合并子被调用时,传递操作数树给 <continuation> 。
85758597 apply-continuation <continuation> <object> :应用续延。
8576-以第二参数作为参数,以 apply 应用第一参数指定的续延转换的应用子,即同求值:
8577-apply (apply-continuation <continuation>) <object>
8598+以第二参数作为参数,以 apply 应用第一参数指定的续延转换的应用子。
8599+**注释** 即同求值:apply (apply-continuation <continuation>) <object> 。
85788600 **原理**
85798601 类似 Kernel 语言,NPLA1 续延不是合并子。这一设计的基本原理参见 [RnRK] §7 ,但理由不充分。更完整的分析如下:
85808602 使用守卫选择子(guard selector) 是 Kernel 的具体特性的设计,不是一般求值算法中蕴含需要实现的选项,因此仅在 [RnRK] 内部生效。
Show on old repository browser