• R/O
  • SSH

YSLib: Commit

The YSLib project - main repository


Commit MetaInfo

Revision04895f90f831afdfbf92c1d98a93bffd34f116a4 (tree)
Time2021-02-17 03:25:32
AuthorFrankHB <frankhb1989@gmai...>
CommiterFrankHB

Log Message

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

Change Summary

Incremental Difference

diff -r c91b75c1e8bc -r 04895f90f831 Tools/Scripts/SHBuild-YSLib-common.txt
--- a/Tools/Scripts/SHBuild-YSLib-common.txt Sat Feb 06 16:04:05 2021 +0800
+++ b/Tools/Scripts/SHBuild-YSLib-common.txt Wed Feb 17 02:25:32 2021 +0800
@@ -224,7 +224,7 @@
224224 (
225225 $import! std.strings string<-;
226226
227- $unless (safeenv-empty? "SHELL")
227+ $when (safeenv-empty? "COMSPEC")
228228 (string<- src (system-quote src));
229229 system-ok (cons-cmd "echo" src "|" (system-quote compile) "-pipe" "-xc++"
230230 "-o" (system-quote out) opt "- 2>" err-out)
diff -r c91b75c1e8bc -r 04895f90f831 Tools/Scripts/SHBuild-build.sh
--- a/Tools/Scripts/SHBuild-build.sh Sat Feb 06 16:04:05 2021 +0800
+++ b/Tools/Scripts/SHBuild-build.sh Wed Feb 17 02:25:32 2021 +0800
@@ -27,15 +27,31 @@
2727 # shellcheck disable=2034
2828 LDFLAGS_IMPL_OPT=' '
2929 # shellcheck source=./SHBuild-bootstrap.sh
30-. "$SHBuild_ToolDir/SHBuild-bootstrap.sh" # for SHBuild_Pushd, SHBuild_BaseDir,
31-# SHBuild_Puts, CXXFLAGS, LDFLAGS, INCLUDES, LIBS, SHBuild_Popd.
30+. "$SHBuild_ToolDir/SHBuild-bootstrap.sh" # for SHBuild_Host_OS,
31+# SHBuild_Host_Arch, SHBuild_Pushd, SHBuild_BaseDir, SHBuild_Puts, CXXFLAGS,
32+# LDFLAGS, INCLUDES, LIBS, SHBuild_Popd;
3233
3334 : "${SHBuild_Output:=SHBuild}"
3435
36+# XXX: After MSYS2 enables ASLR by default, x86_64 binutils with g++ is buggy.
37+# See https://www.msys2.org/news/#2021-01-31-aslr-enabled-by-default,
38+# https://github.com/msys2/MINGW-packages/issues/6986,
39+# https://github.com/msys2/MINGW-packages/issues/7023,
40+# and https://sourceware.org/bugzilla/show_bug.cgi?id=26659. Here is a
41+# workaround to the issue.
42+if [[ "$SHBuild_Host_OS" == 'Win32' && "$SHBuild_Host_Arch" == 'x86_64' \
43+ && "$SHBuild_CXX_Style_" == 'G++' ]]; then
44+ LDFLAGS_LOWBASE_="$(SHBuild_CheckCompiler "$CXX" \
45+ 'int main(){}' -Wl,--default-image-base-low '' \
46+ -xc++ -Wl,--default-image-base-low)"
47+else
48+ LDFLAGS_LOWBASE_=
49+fi
50+
3551 SHBuild_Pushd .
3652 cd "$SHBuild_BaseDir"
3753
38-SHBuild_Puts Building ...
54+SHBuild_Puts "Building ..."
3955
4056 # Precompiled header is not used here because it does not work well with
4157 # external %CXXFLAGS_OPT_DBG. It is also not used frequently like in stage 2.
@@ -55,13 +71,13 @@
5571 # XXX: Value of several variables may contain whitespaces.
5672 # shellcheck disable=2086
5773 SHBuild_Puts "$CXX" Main.cpp -o"$SHBuild_Output" $CXXFLAGS $LDFLAGS \
58- $SHBuild_IncPCH $INCLUDES $LIBS
74+ $LDFLAGS_LOWBASE_ $SHBuild_IncPCH $INCLUDES $LIBS
5975 fi
6076 # XXX: Value of several variables may contain whitespaces.
6177 # shellcheck disable=2086
62-"$CXX" Main.cpp -o"$SHBuild_Output" $CXXFLAGS $LDFLAGS $SHBuild_IncPCH \
63- $INCLUDES $LIBS
78+"$CXX" Main.cpp -o"$SHBuild_Output" $CXXFLAGS $LDFLAGS $LDFLAGS_LOWBASE_ \
79+ $SHBuild_IncPCH $INCLUDES $LIBS
6480
6581 SHBuild_Popd
66-SHBuild_Puts Done.
82+SHBuild_Puts "Done."
6783
diff -r c91b75c1e8bc -r 04895f90f831 Tools/Scripts/SHBuild-common-toolchain.sh
--- a/Tools/Scripts/SHBuild-common-toolchain.sh Sat Feb 06 16:04:05 2021 +0800
+++ b/Tools/Scripts/SHBuild-common-toolchain.sh Wed Feb 17 02:25:32 2021 +0800
@@ -17,6 +17,7 @@
1717 # Params: $2 = the source to compile.
1818 # Params: $3 = optional output on success.
1919 # Params: $4 = optional output on failure.
20+# Params: $5... = options to compile.
2021 SHBuild_CheckCompiler()
2122 {
2223 local compile="$1"
@@ -26,13 +27,16 @@
2627 # NOTE: The output path cannot be '/dev/null'. See http://sourceforge.net/p/msys2/discussion/general/thread/2d6adff2/?limit=25.
2728 if [[ "$compile" != */* ]] && (hash "$compile" > /dev/null 2>& 1) \
2829 || [[ "$compile" == */* && ! -d "$compile" && -x "$compile" ]]; then
30+ local success="$3"
31+ local failure="$4"
32+ shift 4
2933 # XXX: %SHBuild_Env_TempDir is external.
3034 # shellcheck disable=2154
31- if echo "$src" | "$compile" \
32- -xc -o"$SHBuild_Env_TempDir/null" - 2> /dev/null; then
33- SHBuild_Put "$3"
35+ if echo "$src" | "$compile" "$@" -o"$SHBuild_Env_TempDir/null" - \
36+ 2> /dev/null; then
37+ SHBuild_Put "$success"
3438 else
35- SHBuild_Put "$4"
39+ SHBuild_Put "$failure"
3640 fi
3741 else
3842 SHBuild_Put ""
@@ -44,7 +48,7 @@
4448 # Params: $1 = path of the C compiler.
4549 SHBuild_CheckCC()
4650 {
47- SHBuild_CheckCompiler "$1" 'int main(void){return __clang__;}' "Clang" "GCC"
51+ SHBuild_CheckCompiler "$1" 'int main(void){return __clang__;}' Clang GCC -xc
4852 }
4953
5054 # Check the availablity of the C++ compiler.
@@ -52,7 +56,7 @@
5256 # Params: $1 = path of the C++ compiler.
5357 SHBuild_CheckCXX()
5458 {
55- SHBuild_CheckCompiler "$1" 'int main(){return __clang__;}' "Clang++" "G++"
59+ SHBuild_CheckCompiler "$1" 'int main(){return __clang__;}' Clang++ G++ -xc++
5660 }
5761
5862 SHBuild_GetAR_()
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/YFramework.vcxproj
--- a/YFramework/YFramework.vcxproj Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/YFramework.vcxproj Wed Feb 17 02:25:32 2021 +0800
@@ -139,7 +139,7 @@
139139 <ClInclude Include="include\YSLib\Core\YObject.h" />
140140 <ClInclude Include="include\YSLib\Core\YShell.h" />
141141 <ClInclude Include="include\YSLib\Core\YMessage.h" />
142- <ClInclude Include="include\YSLib\Core\ymsgdef.h" />
142+ <ClInclude Include="include\YSLib\Core\YMessageDefinition.h" />
143143 <ClInclude Include="include\YSLib\Core\YShellDefinition.h" />
144144 <ClInclude Include="include\YSLib\Core\YStorage.hpp" />
145145 <ClInclude Include="include\YSLib\Core\YString.h" />
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/YFramework.vcxproj.filters
--- a/YFramework/YFramework.vcxproj.filters Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/YFramework.vcxproj.filters Wed Feb 17 02:25:32 2021 +0800
@@ -301,9 +301,6 @@
301301 <ClInclude Include="include\YSLib\UI\ListControl.h">
302302 <Filter>include\YSLib\UI</Filter>
303303 </ClInclude>
304- <ClInclude Include="include\YSLib\Core\ymsgdef.h">
305- <Filter>include\YSLib\Core</Filter>
306- </ClInclude>
307304 <ClInclude Include="include\YSLib\Core\YMessage.h">
308305 <Filter>include\YSLib\Core</Filter>
309306 </ClInclude>
@@ -730,6 +727,9 @@
730727 <ClInclude Include="source\NPL\NPLA1Internals.h">
731728 <Filter>source\NPL</Filter>
732729 </ClInclude>
730+ <ClInclude Include="include\YSLib\Core\YMessageDefinition.h">
731+ <Filter>include\YSLib\Core</Filter>
732+ </ClInclude>
733733 </ItemGroup>
734734 <ItemGroup>
735735 <ClCompile Include="source\YSLib\Adaptor\YNew.cpp">
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/include/NPL/NPLA.h
--- a/YFramework/include/NPL/NPLA.h Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/include/NPL/NPLA.h Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA.h
1212 \ingroup NPL
1313 \brief NPLA 公共接口。
14-\version r8045
14+\version r8053
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 663
1717 \par 创建时间:
1818 2016-01-07 10:32:34 +0800
1919 \par 修改时间:
20- 2021-01-27 18:14 +0800
20+ 2021-02-15 22:49 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -3086,14 +3086,19 @@
30863086 /*!
30873087 \brief 解析环境。
30883088 \return 取得所有权的环境指针及是否具有所有权。
3089-\note 只支持宿主值类型 \c shared_ptr<Environment> 或 \c weak_ptr<Environment> 。
3089+\sa Environment::EnsureValid
3090+
3091+尝试从参数指定的对象中访问环境指针。
3092+只支持访问宿主值类型 \c shared_ptr<Environment> 或 \c weak_ptr<Environment> 。
3093+所有权由成功访问的对象类型确定:环境强引用具有所有权,否则不具有所有权。
3094+不检查宿主值类型以外的有效性。成功访问的环境指针的值可能为空,而需进一步检查。
30903095 */
30913096 //@{
30923097 //! \since build 830
30933098 YB_ATTR_nodiscard YF_API pair<shared_ptr<Environment>, bool>
30943099 ResolveEnvironment(const ValueObject&);
30953100 /*!
3096-\note 第二参数指定是否转移。
3101+\note 第二参数指定是否转移第一参数。
30973102 \since build 909
30983103 */
30993104 YB_ATTR_nodiscard YF_API pair<shared_ptr<Environment>, bool>
@@ -3129,8 +3134,8 @@
31293134 lref<ContextNode> Context;
31303135 mutable shared_ptr<Environment> SavedPtr;
31313136
3132- EnvironmentSwitcher(ContextNode& ctx,
3133- shared_ptr<Environment>&& p_saved = {})
3137+ //! \since build 911
3138+ EnvironmentSwitcher(ContextNode& ctx, shared_ptr<Environment> p_saved = {})
31343139 : Context(ctx), SavedPtr(std::move(p_saved))
31353140 {}
31363141 DefDeMoveCtor(EnvironmentSwitcher)
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/include/NPL/NPLA1Forms.h
--- a/YFramework/include/NPL/NPLA1Forms.h Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/include/NPL/NPLA1Forms.h Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1Forms.h
1212 \ingroup NPL
1313 \brief NPLA1 语法形式。
14-\version r7797
14+\version r7802
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 882
1717 \par 创建时间:
1818 2020-02-15 11:19:21 +0800
1919 \par 修改时间:
20- 2021-02-04 15:15 +0800
20+ 2021-02-14 11:34 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -692,17 +692,16 @@
692692 //@{
693693 /*!
694694 \brief 取列表的第一元素并转发给指定的应用子。
695-\since build 875
695+\since build 911
696696
697-使用第一参数指定的应用子调用第三参数指定的列表,取结果匹配的第一元素作为参数,
698- 调用第二参数指定的应用子。
697+取第三参数指定的列表的第一个元素作为参数,调用第二参数指定的应用子。
699698 列表参数在对象语言中按引用传递。
700699
701700 参考调用文法:
702-<pre>forward-list-first% \<applicative1> \<applicative2> \<list></pre>
701+<pre>forward-first% \<applicative> \<list></pre>
703702 */
704703 YF_API ReductionStatus
705-ForwardListFirst(TermNode&, ContextNode&);
704+ForwardFirst(TermNode&, ContextNode&);
706705
707706 /*!
708707 \brief 取参数指定的列表中的第一元素的值。
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/include/NPL/SContext.h
--- a/YFramework/include/NPL/SContext.h Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/include/NPL/SContext.h Wed Feb 17 02:25:32 2021 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2012-2020 FrankHB.
2+ © 2012-2021 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 SContext.h
1212 \ingroup NPL
1313 \brief S 表达式上下文。
14-\version r3805
14+\version r3817
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 304
1717 \par 创建时间:
1818 2012-08-03 19:55:41 +0800
1919 \par 修改时间:
20- 2020-10-06 21:19 +0800
20+ 2021-02-06 22:59 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,19 +29,19 @@
2929 #define NPL_INC_SContext_h_ 1
3030
3131 #include "YModules.h"
32-#include YFM_NPL_Lexical // for function, pmr, ByteParser, ystdex::expand_proxy,
33-// ystdex::unref, ystdex::as_const, LexemeList;
34-#include YFM_YSLib_Core_ValueNode // for YSLib::Deref, YSLib::LoggedEvent,
35-// YSLib::MakeIndex, YSLib::NoContainer, YSLib::NoContainerTag,
36-// YSLib::ValueNode, YSLib::ValueObject, YSLib::forward_as_tuple, YSLib::get,
32+#include YFM_NPL_Lexical // for ystdex::copy_and_swap, pmr, ByteParser,
33+// ystdex::expand_proxy, ystdex::unref, ystdex::as_const, LexemeList;
34+#include YFM_YSLib_Core_ValueNode // for YSLib::Deref, YSLib::MakeIndex,
35+// YSLib::NoContainer, YSLib::NoContainerTag, YSLib::ValueNode,
36+// YSLib::ValueObject, YSLib::forward_as_tuple, YSLib::get,
3737 // YSLib::make_observer, YSLib::make_pair, YSLib::share_move,
3838 // YSLib::make_shared, YSLib::make_weak, YSLib::observer_ptr, YSLib::tuple,
3939 // YSLib::weak_ptr, list, YSLib::ListContainerTag, std::initializer_list,
40-// ystdex::create_and_swap, ystdex::forward_like, ystdex::invoke,
41-// YSLib::AccessPtr, ystdex::false_, std::is_convertible, ystdex::decay_t,
42-// ystdex::bool_, ystdex::cond_or_t, ystdex::not_, ystdex::enable_if_t,
43-// ystdex::call_value_or, ystdex::addrof, ystdex::compose, pair,
44-// std::is_lvalue_reference, YSLib::Alert, YSLib::stack;
40+// ystdex::forward_like, ystdex::invoke, YSLib::AccessPtr, ystdex::false_,
41+// std::is_convertible, ystdex::decay_t, ystdex::bool_, ystdex::cond_or_t,
42+// ystdex::not_, ystdex::enable_if_t, ystdex::call_value_or, ystdex::addrof,
43+// ystdex::compose, pair, std::is_lvalue_reference, YSLib::Alert, YSLib::stack;
44+#include YFM_YSLib_Core_YException // for YSLib::LoggedEvent;
4545 #include <ystdex/range.hpp> // for std::iterator_traits,
4646 // ystdex::range_iterator_t, ystdex::begin, ystdex::end,
4747 // std::input_iterator_tag, std::random_access_iterator_tag;
@@ -307,7 +307,7 @@
307307 {}
308308
309309 /*!
310- \brief 复制赋值:使用以参数的分配器构造的副本和交换操作。
310+ \brief 复制赋值:使用参数副本和交换操作。
311311 \since build 879
312312 */
313313 PDefHOp(TermNode&, =, const TermNode& tm)
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/include/YSLib/Core/YDevice.h
--- a/YFramework/include/YSLib/Core/YDevice.h Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/include/YSLib/Core/YDevice.h Wed Feb 17 02:25:32 2021 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2009-2015, 2019-2020 FrankHB.
2+ © 2009-2015, 2019-2021 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 YDevice.h
1212 \ingroup Core
1313 \brief 平台无关的设备抽象层。
14-\version r2097
14+\version r2100
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 586
1717 \par 创建时间:
1818 2009-12-28 16:39:39 +0800
1919 \par 修改时间:
20- 2020-01-25 16:02 +0800
20+ 2021-02-06 22:41 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,7 +29,8 @@
2929 #define YSL_INC_Core_YDevice_h_ 1
3030
3131 #include "YModules.h"
32-#include YFM_YSLib_Core_YObject // for function, ystdex::unsupported;
32+#include YFM_YSLib_Core_YFunc // for function;
33+#include <ystdex/exception.h> // for ystdex::unsupported;
3334 #include YFM_YSLib_Core_YGraphics
3435
3536 namespace YSLib
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/include/YSLib/Core/YEvent.hpp
--- a/YFramework/include/YSLib/Core/YEvent.hpp Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/include/YSLib/Core/YEvent.hpp Wed Feb 17 02:25:32 2021 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2010-2020 FrankHB.
2+ © 2010-2021 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 YEvent.hpp
1212 \ingroup Core
1313 \brief 事件回调。
14-\version r6098
14+\version r6102
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 560
1717 \par 创建时间:
1818 2010-04-23 23:08:23 +0800
1919 \par 修改时间:
20- 2020-10-10 18:46 +0800
20+ 2021-02-06 22:40 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,11 +29,11 @@
2929 #define YSL_INC_Core_yevt_hpp_ 1
3030
3131 #include "YModules.h"
32-#include YFM_YSLib_Core_YObject // for ystdex::is_expandable,
33-// ystdex::is_decayed, ystdex::examiners::equal_examiner, std::allocator_arg_t,
32+#include YFM_YSLib_Core_YFunc // for module YSLib::Core::YFunc,
33+// ystdex::is_expandable, ystdex::is_decayed, std::allocator_arg_t,
3434 // std::allocator_arg, ystdex::make_expanded, ystdex::default_last_value,
3535 // std::piecewise_construct, YSLib::forward_as_tuple;
36-#include YFM_YSLib_Core_YFunc
36+#include <ystdex/examiner.hpp> // for ystdex::examiners::equal_examiner;
3737 #include <ystdex/type_op.hpp> // for ystdex::exclude_self_t,
3838 // ystdex::exclude_self_params_t;
3939 #include <ystdex/iterator.hpp> // for ystdex::make_transform, ystdex::get_value;
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/include/YSLib/Core/YMessage.h
--- a/YFramework/include/YSLib/Core/YMessage.h Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/include/YSLib/Core/YMessage.h Wed Feb 17 02:25:32 2021 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2009-2018, 2020 FrankHB.
2+ © 2009-2018, 2020-2021 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 r2076
14+\version r2081
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 586
1717 \par 创建时间:
1818 2009-12-06 02:44:31 +0800
1919 \par 修改时间:
20- 2020-10-06 21:31 +0800
20+ 2021-02-06 22:56 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,8 +29,10 @@
2929 #define YSL_INC_Core_YMessage_h_ 1
3030
3131 #include "YModules.h"
32-#include YFM_YSLib_Core_YObject // for std::piecewise_construct,
33-// YSLib::tuple<Priority, YSLib::forward_as_tuple;
32+#include YFM_YSLib_Core_YObject // for module YSLib::Core::YObject, ValueObject,
33+// std::piecewise_construct, YSLib::tuple, YSLib::forward_as_tuple;
34+#include YFM_YSLib_Core_YException // for module YSLib::Core::YException,
35+// LoggedEvent;
3436 #include <ctime>
3537
3638 namespace YSLib
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/include/YSLib/Core/YObject.h
--- a/YFramework/include/YSLib/Core/YObject.h Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/include/YSLib/Core/YObject.h Wed Feb 17 02:25:32 2021 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2009-2020 FrankHB.
2+ © 2009-2021 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 YObject.h
1212 \ingroup Core
1313 \brief 平台无关的基础对象。
14-\version r6594
14+\version r6599
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 561
1717 \par 创建时间:
1818 2009-11-16 20:06:58 +0800
1919 \par 修改时间:
20- 2020-10-09 11:20 +0800
20+ 2021-02-06 22:33 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,7 +29,7 @@
2929 #define YSL_INC_Core_YObject_h_ 1
3030
3131 #include "YModules.h"
32-#include YFM_YSLib_Core_YCoreUtilities // for std::is_base_of,
32+#include YFM_YSLib_Core_YShellDefinition // for std::is_base_of,
3333 // ystdex::exclude_tagged_params_t, ystdex::enable_if_t,
3434 // ystdex::throw_invalid_construction, std::allocator_arg_t,
3535 // std::allocator_arg, ystdex::false_, ystdex::true_,
@@ -607,6 +607,8 @@
607607
608608 /*!
609609 \brief 带等于接口的值类型多态动态泛型持有者。
610+\note 模板参数指定值类型、存储的目标类型和分配器。
611+\note 存储的目标类型通常是值类型的派生类或其引用包装类型。
610612 \since build 899
611613 */
612614 template<class _type, class _tTarget>
@@ -726,6 +728,7 @@
726728 /*!
727729 \brief 在复制初始化时传播分配器的多态值持有者。
728730 \note 模板参数指定值类型、存储的目标类型和分配器。
731+\note 存储的目标类型通常是值类型的派生类。
729732 \since build 899
730733 */
731734 template<class _type, class _tTarget, class _tByteAlloc>
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/include/YSLib/Core/YString.h
--- a/YFramework/include/YSLib/Core/YString.h Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/include/YSLib/Core/YString.h Wed Feb 17 02:25:32 2021 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2010-2016, 2018-2019 FrankHB.
2+ © 2010-2016, 2018-2019, 2021 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 YString.h
1212 \ingroup Core
1313 \brief 基础字符串管理。
14-\version r2367
14+\version r2370
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 594
1717 \par 创建时间:
1818 2010-03-05 22:06:05 +0800
1919 \par 修改时间:
20- 2019-07-07 17:09 +0800
20+ 2021-02-06 22:46 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -29,7 +29,8 @@
2929 #define YSL_INC_Core_YString_h_ 1
3030
3131 #include "YModules.h"
32-#include YFM_YSLib_Core_YObject // for allocator_arg;
32+#include YFM_YSLib_Core_YShellDefinition // for module
33+// YSLib::Core::YShellDefinition, allocator_arg;
3334 #include YFM_YSLib_Adaptor_YTextBase // for u16string;
3435
3536 namespace YSLib
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/source/NPL/Dependency.cpp
--- a/YFramework/source/NPL/Dependency.cpp Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/source/NPL/Dependency.cpp Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file Dependency.cpp
1212 \ingroup NPL
1313 \brief 依赖管理。
14-\version r4189
14+\version r4196
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 623
1717 \par 创建时间:
1818 2015-08-09 22:14:45 +0800
1919 \par 修改时间:
20- 2021-02-05 15:59 +0800
20+ 2021-02-14 14:29 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -678,7 +678,7 @@
678678 RegisterStrict(renv, "apply", Apply);
679679 RegisterStrict(renv, "list*", ListAsterisk);
680680 RegisterStrict(renv, "list*%", ListAsteriskRef);
681- RegisterStrict(renv, "forward-list-first%", ForwardListFirst);
681+ RegisterStrict(renv, "forward-first%", ForwardFirst);
682682 RegisterStrict(renv, "first", First);
683683 RegisterStrict(renv, "first@", FirstAt);
684684 RegisterStrict(renv, "first&", FirstRef);
@@ -842,13 +842,11 @@
842842 (cons% (forward! head) (apply list*% tail));
843843 $defv! $defw%! (&f &formals &ef .&body) d
844844 eval (list $set! d f wrap (list* $vau% formals ef (move! body))) d;
845- $defw%! forward-list-first% (&list-appv &appv &l) d
846- ($lambda% ((&x .))
847- apply (forward! appv) (list% ($move-resolved! x)) d)
848- (apply (forward! list-appv) (list% l) d);
845+ $defw%! forward-first% (&appv (&x .)) d
846+ apply (forward! appv) (list% ($move-resolved! x)) d;
849847 $defl%! first@ (&l) ($lambda% ((@x .)) x) (check-list-reference l);
850848 $defl%! first (%l)
851- ($lambda% (fwd) forward-list-first% fwd forward! l)
849+ ($lambda% (fwd) forward-first% forward! (fwd l))
852850 ($if (bound-lvalue? ($resolve-identifier l)) id expire);
853851 $defl%! first& (&l) ($lambda% ((&x .)) x) (check-list-reference l);
854852 $defl! firstv ((&x .)) x;
@@ -1102,7 +1100,7 @@
11021100 $if (null? l) #f ($if (first-null? l) #t (nonfoldable? (rest& l)));
11031101 $defl%! list-extract (&l &extr)
11041102 accr l null? ()
1105- ($lambda% (&l) forward-list-first% expire extr l) rest% cons%;
1103+ ($lambda% (&l) forward-first% extr (expire l)) rest% cons%;
11061104 $defl%! list-extract-first (&l) list-extract l first;
11071105 $defl%! list-extract-rest% (&l) list-extract l rest%;
11081106 $defl! list-push-front! (&l &x)
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/source/NPL/NPLA1Forms.cpp
--- a/YFramework/source/NPL/NPLA1Forms.cpp Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/source/NPL/NPLA1Forms.cpp Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1Forms.cpp
1212 \ingroup NPL
1313 \brief NPLA1 语法形式。
14-\version r20138
14+\version r20405
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 882
1717 \par 创建时间:
1818 2014-02-15 11:19:51 +0800
1919 \par 修改时间:
20- 2021-02-04 18:34 +0800
20+ 2021-02-16 00:42 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -27,24 +27,23 @@
2727
2828 #include "NPL/YModules.h"
2929 #include YFM_NPL_NPLA1Forms // for YSLib, std::next, ReduceOnceLifted,
30-// NPL::IsMovable, function, NPL::TryAccessReferencedTerm, ystdex::value_or,
31-// ThrowInsufficientTermsError, NPL::Deref, A1::NameTypedReducerHandler,
32-// ReduceReturnUnspecified, RemoveHead, IsBranch, AccessFirstSubterm,
33-// ReduceSubsequent, ReduceCombinedBranch, std::placeholders, ystdex::as_const,
34-// IsLeaf, ystdex::ref_eq, RelaySwitched, ContextHandler, shared_ptr, string,
35-// unordered_map, Environment, lref, list, IsBranchedList, TokenValue,
36-// NPL::TryAccessLeaf, ValueObject, weak_ptr, any_ops::use_holder,
37-// in_place_type, ystdex::type_id, YSLib::allocate_shared, InvalidReference,
38-// MoveFirstSubterm, ShareMoveTerm, ThrowInvalidSyntaxError,
39-// ResolvedTermReferencePtr, LiftOtherOrCopy, ResolveTerm,
40-// ystdex::equality_comparable, std::allocator_arg, NPL::AsTermNode,
41-// ystdex::exchange, NPL::SwitchToFreshEnvironment, TermTags,
30+// ResolvedTermReferencePtr, NPL::IsMovable, NPL::TryAccessReferencedTerm,
31+// ystdex::value_or, ThrowInsufficientTermsError, NPL::Deref,
32+// A1::NameTypedReducerHandler, ReduceReturnUnspecified, RemoveHead, IsBranch,
33+// AccessFirstSubterm, ReduceSubsequent, ReduceCombinedBranch,
34+// std::placeholders, std::ref, std::bind, ystdex::as_const, IsLeaf,
35+// ValueObject, ystdex::ref_eq, RelaySwitched, ContextHandler, shared_ptr,
36+// string, unordered_map, Environment, lref, list, IsBranchedList, TokenValue,
37+// NPL::TryAccessLeaf, weak_ptr, any_ops::use_holder, in_place_type,
38+// ystdex::type_id, YSLib::allocate_shared, InvalidReference, MoveFirstSubterm,
39+// ShareMoveTerm, ThrowInvalidSyntaxError, LiftOtherOrCopy, ResolveTerm,
40+// ystdex::make_transform, ystdex::equality_comparable, std::allocator_arg,
41+// NPL::AsTermNode, ystdex::exchange, NPL::SwitchToFreshEnvironment, TermTags,
4242 // ystdex::expand_proxy, NPL::AccessRegular, TermReference, GetLValueTagsOf,
4343 // RegularizeTerm, ThrowValueCategoryError, ThrowListTypeErrorForNonlist,
4444 // ystdex::update_thunk, NPL::TryAccessReferencedLeaf, ystdex::invoke_value_or,
45-// ystdex::call_value_or, LiftMovedOther, LiftCollapsed,
46-// ystdex::make_transform, NPL::AllocateEnvironment, NPL::TryAccessTerm,
47-// std::mem_fn;
45+// ystdex::call_value_or, LiftMovedOther, ystdex::bind1, LiftCollapsed,
46+// NPL::AllocateEnvironment, NPL::TryAccessTerm, std::mem_fn;
4847 #include "NPLA1Internals.h" // for A1::Internals API;
4948 #include YFM_NPL_SContext // for Session;
5049
@@ -380,6 +379,15 @@
380379 };
381380
382381
382+//! \since build 911
383+YB_ATTR_nodiscard inline PDefH(const shared_ptr<Environment>&,
384+ FetchValidEnvironment, const shared_ptr<Environment>& p_env)
385+ ImplRet(Environment::EnsureValid(p_env), p_env)
386+//! \since build 911
387+YB_ATTR_nodiscard inline PDefH(shared_ptr<Environment>&&,
388+ FetchValidEnvironment, shared_ptr<Environment>&& p_env)
389+ ImplRet(Environment::EnsureValid(p_env), std::move(p_env))
390+
383391 //! \since build 894
384392 YB_ATTR_nodiscard inline PDefH(const shared_ptr<Environment>&,
385393 FetchDefineOrSetEnvironment, ContextNode& ctx) ynothrow
@@ -388,7 +396,7 @@
388396 YB_ATTR_nodiscard inline PDefH(const shared_ptr<Environment>&,
389397 FetchDefineOrSetEnvironment, ContextNode&,
390398 const shared_ptr<Environment>& p_env)
391- ImplRet(Environment::EnsureValid(p_env), p_env)
399+ ImplRet(FetchValidEnvironment(p_env))
392400
393401 //! \since build 904
394402 YB_NORETURN inline void
@@ -624,127 +632,6 @@
624632 }
625633
626634
627-// XXX: Same to %RelayForEvalOrDirect, except that %no_lift is always %true, and
628-// no TCO is enforced.
629-//! \since build 898
630-template<typename _fNext>
631-YB_FLATTEN inline ReductionStatus
632-RelayNextGuarded(ContextNode& ctx, TermNode& term, EnvironmentGuard&& gd,
633- _fNext&& cur)
634-{
635- // XXX: See %RelayForEvalOrDirect.
636-#if NPL_Impl_NPLA1_Enable_Thunked
637- // TODO: Blocked. Use C++14 lambda initializers to simplify the
638- // implementation.
639- return A1::RelayCurrentNext(ctx, term, yforward(cur), MakeMoveGuard(gd));
640-#else
641- yunused(gd);
642- return A1::RelayDirect(ctx, cur, term);
643-#endif
644-}
645-
646-// XXX: Same to %RelayForEvalOrDirect, except that %no_lift is always %true.
647-/*!
648-\pre TCO 实现:当前动作是 TCO 动作,且其中的当前项和被规约的项相同。
649-\since build 898
650-*/
651-template<typename _fNext>
652-YB_FLATTEN inline ReductionStatus
653-RelayNextGuardedTail(ContextNode& ctx, TermNode& term,
654- EnvironmentGuard&& gd, _fNext&& cur)
655-{
656- // XXX: See %RelayForEvalOrDirect.
657-#if NPL_Impl_NPLA1_Enable_TCO
658- // TODO: Simplified without term regularization if call sites do not need
659- // it?
660- PrepareTCOEvaluation(ctx, term, std::move(gd));
661- return A1::RelayCurrentOrDirect(ctx, yforward(cur), term);
662-#else
663- return A1::RelayNextGuarded(ctx, term, std::move(gd), yforward(cur));
664-#endif
665-}
666-
667-//! \since build 910
668-//@{
669-// XXX: A combination of an operative and its operand shall always be evaluated
670-// in a tail context. However, for a combiner call, sometimes it is not in the
671-// tail context in the enclosing context. If the call needs no creation of
672-// %TCOAction (e.g. fully implemented native code), avoiding calling
673-// %PrepareTCOEvaluation needs no precondition of the existence of %TCOAction,
674-// and this can be an optimization.
675-#if false
676-YB_FLATTEN inline ReductionStatus
677-ReduceCombindEnv(TermNode& term, ContextNode& ctx,
678- shared_ptr<Environment> p_env)
679-{
680- // NOTE: The next term is set here unless direct inlining call of
681- // %ReduceCombinedBranch is used.
682-#if !NPL_Impl_NPLA1_Enable_InlineDirect
683- SetupNextTerm(ctx, term);
684-#endif
685- // NOTE: %ReduceFirst and other passes would not be called again. The
686- // unwrapped combiner should have been evaluated and it would not be
687- // wrongly evaluated again.
688- // XXX: Consider optimization when the combiner subterm is known regular.
689- // NOTE: Term is set in %A1::RelayNextGuarded, even for direct
690- // inlining call of %ReduceCombinedBranch.
691- return A1::RelayNextGuarded(ctx, term,
692- EnvironmentGuard(ctx, ctx.SwitchEnvironment(std::move(p_env))),
693- std::ref(ReduceCombinedBranch));
694-}
695-#endif
696-
697-// XXX: Do not use %YB_FLATTEN here for LTO compiling performance.
698-//! \pre TCO 实现:当前动作是 TCO 动作,且其中的当前项和被规约的项相同。
699-inline ReductionStatus
700-RelayCombindEnvTail(ContextNode& ctx, TermNode& term,
701- shared_ptr<Environment> p_env)
702-{
703- // NOTE: The precondition is similar to the last call in
704- // %EvalImplUnchecked in the presense of the assumption that %term is from
705- // the current term saved in the context.
706- return A1::RelayNextGuardedTail(ctx, term,
707- EnvironmentGuard(ctx, ctx.SwitchEnvironment(std::move(p_env))),
708- std::ref(ReduceCombinedBranch));
709-}
710-
711-// XXX: Do not use %YB_FLATTEN here for LTO compiling performance.
712-//! \pre TCO 实现:当前动作是 TCO 动作,且其中的当前项和被规约的项相同。
713-inline ReductionStatus
714-ReduceCombindEnvTail(TermNode& term, ContextNode& ctx,
715- shared_ptr<Environment> p_env)
716-{
717- // NOTE: See %ReduceCombindEnv.
718-#if !NPL_Impl_NPLA1_Enable_InlineDirect
719- SetupNextTerm(ctx, term);
720-#endif
721- return RelayCombindEnvTail(ctx, term, std::move(p_env));
722-}
723-
724-//! \pre TCO 实现:当前动作非 TCO 动作。
725-YB_FLATTEN inline ReductionStatus
726-ReduceCombindEnvNonTail(TermNode& term, ContextNode& ctx,
727- shared_ptr<Environment> p_env)
728-{
729-#if NPL_Impl_NPLA1_Enable_TCO
730- YAssert(!AccessTCOAction(ctx), "Non-tail context expected.");
731-#endif
732- // XXX: Assume %next is not a %TCOAction.
733- ctx.LastStatus = ReductionStatus::Neutral;
734- // NOTE: This does not rely on the existence of the %TCOAction, as it
735- // will call %EnsureTCOAction. Since the call would rely on %TCOAction,
736- // anyway, creating the TCO action here instead of a new action
737- // to restore the environment is more efficient.
738-#if NPL_Impl_NPLA1_Enable_TCO
739- SetupTailTCOAction(ctx, term, {});
740-#endif
741- // NOTE: The precondition is same to the current continuation call in
742- // %ReduceCombindEnvTail.
743- return ReduceCombindEnvTail(term, ctx, std::move(p_env));
744-}
745-//@}
746-
747-
748635 /*!
749636 \param no_lift 指定是否避免保证规约后提升结果。
750637 \since build 835
@@ -1317,6 +1204,7 @@
13171204 return EvaluateToLValueReference(o, p_env);
13181205 }
13191206
1207+#if false
13201208 // NOTE: See %BindMoveLocalObjectInPlace and %EvaluateBoundLValueMoved.
13211209 //! \since build 897
13221210 YB_ATTR_nodiscard TermNode
@@ -1333,6 +1221,7 @@
13331221 o.Tags |= TermTags::Temporary;
13341222 return EvaluateToLValueReference(o, p_env);
13351223 }
1224+#endif
13361225
13371226 //! \since build 897
13381227 void
@@ -1383,45 +1272,6 @@
13831272 {}, TermReference(term.Tags, term, NPL::Nonnull(p_env)), ctx, term);
13841273 }
13851274
1386-// NOTE: As %ReduceSubsequent.
1387-// NOTE: This does not guarantee PTC.
1388-//! \since build 875
1389-template<typename _fCurrent>
1390-ReductionStatus
1391-ReduceCallSubsequent(TermNode& term, ContextNode& ctx,
1392- shared_ptr<Environment> p_env, _fCurrent&& next)
1393-{
1394- using namespace std::placeholders;
1395-
1396- // TODO: Blocked. Use C++14 lambda initializers to simplify the
1397- // implementation.
1398- return A1::ReduceCurrentNext(term, ctx,
1399- std::bind([](shared_ptr<Environment>& p_e, TermNode& t, ContextNode& c){
1400- return ReduceCombindEnvNonTail(t, c, std::move(p_e));
1401- }, std::move(p_env), _1, _2), yforward(next));
1402-}
1403-
1404-#if false
1405-//! \since build 898
1406-template<typename _fCurrent>
1407-ReductionStatus
1408-ReduceCallSubsequentTail(TermNode& term, ContextNode& ctx,
1409- shared_ptr<Environment> p_env, _fCurrent&& next)
1410-{
1411- using namespace std::placeholders;
1412-
1413- // TODO: Blocked. Use C++14 lambda initializers to simplify the
1414- // implementation.
1415- return A1::ReduceCurrentNext(term, ctx,
1416- std::bind([](shared_ptr<Environment>& p_e, TermNode& t, ContextNode& c){
1417- // NOTE: This does not calls %EnsureTCOAction, so an %TCOAction shall be
1418- // already existed in the context.
1419- // NOTE: See the precondition for %ReduceCombindEnvTail.
1420- return ReduceCombindEnvTail(t, c, std::move(p_e));
1421- }, std::move(p_env), _1, _2), yforward(next));
1422-}
1423-#endif
1424-
14251275
14261276 //! \since build 874
14271277 template<typename _func>
@@ -2009,8 +1859,8 @@
20091859 ConsItem(expr, NPL::Deref(++i));
20101860 term = std::move(expr);
20111861 // NOTE: The precondition is same to the last call in %EvalImplUnchecked.
2012- // See also the precondition for %RelayCombindEnvTail.
2013- return RelayCombindEnvTail(ctx, term, std::move(p_env));
1862+ // See also the precondition of %Combine<TailCall>::RelayEnvSwitch.
1863+ return Combine<TailCall>::RelayEnvSwitch(ctx, term, std::move(p_env));
20141864 }
20151865
20161866 //! \since build 860
@@ -2062,7 +1912,9 @@
20621912 = TermNode::Container({std::move(lv_pred), lv_l}, term.get_allocator());
20631913 // TODO: Blocked. Use C++14 lambda initializers to simplify the
20641914 // implementation.
2065- return ReduceCallSubsequent(nterm, ctx, d, A1::NameTypedReducerHandler(
1915+ return Combine<NonTailCall>::ReduceCallSubsequent(nterm, ctx,
1916+ EnvironmentGuard(ctx, d), A1::NameTypedReducerHandler(
1917+ // XXX: Capture of %d by copy is a slightly more efficient.
20661918 std::bind([&, d, f](TNIter& i_0) -> ReductionStatus{
20671919 auto& base(*++i_0);
20681920
@@ -2073,7 +1925,7 @@
20731925
20741926 nterm.GetContainerRef() = {std::move(lv_head), lv_l};
20751927 nterm.Value.Clear();
2076- return ReduceCallSubsequent(nterm, ctx, d,
1928+ return Combine<NonTailCall>::ReduceCallSubsequent(nterm, ctx, d,
20771929 A1::NameTypedReducerHandler(
20781930 std::bind([&, d, f](TNIter& i_1){
20791931 return f(l, base, lv_l, nterm, d, i_1);
@@ -2097,12 +1949,13 @@
20971949
20981950 base.GetContainerRef() = TermNode::Container({std::move(lv_sum),
20991951 std::move(nterm), std::move(base)}, term.get_allocator());
2100- return ReduceCallSubsequent(base, ctx, d,
1952+ return Combine<NonTailCall>::ReduceCallSubsequent(base, ctx, d,
1953+ // XXX: Capture of %d by copy is a slightly more efficient.
21011954 A1::NameTypedReducerHandler([&, d]() YB_FLATTEN{
21021955 auto lv_tail(EvaluateBoundLValueUnwrapped(tail, ctx, d));
21031956
21041957 nterm.GetContainerRef() = {std::move(lv_tail), std::move(lv_l)};
2105- return ReduceCallSubsequent(nterm, ctx, d,
1958+ return Combine<NonTailCall>::ReduceCallSubsequent(nterm, ctx, d,
21061959 A1::NameTypedReducerHandler([&]() YB_FLATTEN{
21071960 l = std::move(nterm);
21081961 return AccLImpl(term, ctx);
@@ -2123,7 +1976,8 @@
21231976
21241977 n2term.GetContainerRef()
21251978 = TermNode::Container({std::move(lv_tail), std::move(lv_l)}, a);
2126- return ReduceCallSubsequent(n2term, ctx, d,
1979+ return Combine<NonTailCall>::ReduceCallSubsequent(n2term, ctx, d,
1980+ // XXX: Capture of %d by copy is a slightly more efficient.
21271981 A1::NameTypedReducerHandler([&, a, d]() YB_FLATTEN{
21281982 l = std::move(n2term);
21291983
@@ -2135,7 +1989,7 @@
21351989 [&](TermNode& t, ContextNode& c){
21361990 return AccRImpl(t, c, sum);
21371991 }, A1::NameTypedReducerHandler([&, d]() YB_FLATTEN{
2138- return ReduceCombindEnvNonTail(term, ctx, d);
1992+ return Combine<NonTailCall>::ReduceEnvSwitch(term, ctx, d);
21391993 }, "eval-accr-sum"));
21401994 }, "eval-accr-accr"));
21411995 }, term, ctx);
@@ -2216,27 +2070,31 @@
22162070 auto i(term.begin());
22172071 auto& knil(*++(++i));
22182072 auto& l(*++i);
2219- const auto& d(ctx.GetRecordPtr());
2220- auto lv_l(EvaluateLocalObject(l, d));
2073+ auto lv_l(EvaluateLocalObject(l, ctx.GetRecordPtr()));
22212074
22222075 // XXX: Keeping %lv_l is a slightly more efficient.
22232076 return NPL::ResolveTerm(
2224- [&, d](TermNode& nd, ResolvedTermReferencePtr p_ref) -> ReductionStatus{
2077+ [&](TermNode& nd, ResolvedTermReferencePtr p_ref) -> ReductionStatus{
22252078 if(!IsEmpty(nd))
22262079 {
22272080 auto& nterm(FoldRMap1Impl(term, nd, p_ref, l));
2228- auto lv_kons(EvaluateBoundLValueUnwrapped(kons, ctx, d));
2081+ auto lv_kons(EvaluateBoundLValueUnwrapped(kons, ctx,
2082+ ctx.GetRecordPtr()));
22292083 auto& rterm(*term.emplace(ystdex::exchange(term.GetContainerRef(),
22302084 TermNode::Container({std::move(lv_kons), std::move(nterm)},
22312085 term.get_allocator()))));
22322086
22332087 nterm.ClearContainer();
2088+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
2089+ // implementation.
22342090 return A1::ReduceCurrentNext(rterm, ctx,
22352091 [&](TermNode& t, ContextNode& c){
22362092 return FoldR1Impl(t, c, kons);
2237- }, A1::NameTypedReducerHandler([&, d]() YB_FLATTEN{
2238- return ReduceCombindEnvNonTail(term, ctx, d);
2239- }, "eval-foldr1-kons"));
2093+ }, A1::NameTypedReducerHandler(
2094+ std::bind([&](shared_ptr<Environment>& d) YB_FLATTEN{
2095+ return Combine<NonTailCall>::ReduceEnvSwitch(term, ctx,
2096+ std::move(d));
2097+ }, ctx.ShareRecord()), "eval-foldr1-kons"));
22402098 }
22412099 LiftOther(term, knil);
22422100 return ReductionStatus::Retained;
@@ -2250,27 +2108,31 @@
22502108
22512109 auto i(term.begin());
22522110 auto& l(*++(++i));
2253- const auto& d(ctx.GetRecordPtr());
2254- auto lv_l(EvaluateLocalObject(l, d));
2111+ auto lv_l(EvaluateLocalObject(l, ctx.GetRecordPtr()));
22552112
22562113 // XXX: Keep %lv_l is a slightly more efficient.
22572114 return NPL::ResolveTerm(
2258- [&, d](TermNode& nd, ResolvedTermReferencePtr p_ref) -> ReductionStatus{
2115+ [&](TermNode& nd, ResolvedTermReferencePtr p_ref) -> ReductionStatus{
22592116 if(!IsEmpty(nd))
22602117 {
22612118 auto& nterm(FoldRMap1Impl(term, nd, p_ref, l));
2262- auto lv_appv(EvaluateBoundLValueUnwrapped(appv, ctx, d));
2119+ auto lv_appv(EvaluateBoundLValueUnwrapped(appv, ctx,
2120+ ctx.GetRecordPtr()));
22632121 const auto a(term.get_allocator());
22642122 auto& rterm(*term.emplace(ystdex::exchange(term.GetContainerRef(),
22652123 TermNode::Container({TermNode({std::move(lv_appv),
22662124 std::move(nterm)}, a)}, a))));
22672125
22682126 nterm.ClearContainer();
2127+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
2128+ // implementation.
22692129 return A1::ReduceCurrentNext(rterm, ctx,
22702130 [&](TermNode& t, ContextNode& c){
22712131 return Map1Impl(t, c, appv);
2272- }, A1::NameTypedReducerHandler([&, d]() YB_FLATTEN{
2273- return ReduceCallSubsequent(*term.begin(), ctx, d,
2132+ }, A1::NameTypedReducerHandler(
2133+ std::bind([&](shared_ptr<Environment>& d) YB_FLATTEN{
2134+ return Combine<NonTailCall>::ReduceCallSubsequent(*term.begin(),
2135+ ctx, std::move(d),
22742136 A1::NameTypedReducerHandler([&]() YB_FLATTEN{
22752137 auto i_term(term.begin());
22762138
@@ -2278,7 +2140,7 @@
22782140 term.erase(i_term);
22792141 return ReductionStatus::Retained;
22802142 }, "eval-map1-cons"));
2281- }, "eval-map1-appv"));
2143+ }, ctx.ShareRecord()), "eval-map1-appv"));
22822144 }
22832145 term.Clear();
22842146 return ReductionStatus::Regular;
@@ -2302,13 +2164,13 @@
23022164 AccFoldR1LiftSum(TermNode& term, ContextNode& ctx, TermNode& rterm,
23032165 _func f, TermNode::Container& con)
23042166 {
2305- using namespace std::placeholders;
2306-
23072167 #if NPL_Impl_NPLA1_Enable_Thunked
2168+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
2169+ // implementation.
23082170 return A1::ReduceCurrentNext(rterm, ctx,
2309- std::bind([&](_func& acc, TermNode& t, ContextNode& c){
2171+ ystdex::bind1([&](TermNode& t, ContextNode& c, _func& acc){
23102172 return acc(t, c, con.back());
2311- }, std::move(f), _1, _2), A1::NameTypedReducerHandler([&]{
2173+ }, std::placeholders::_2, std::move(f)), A1::NameTypedReducerHandler([&]{
23122174 LiftOther(term, rterm);
23132175 return ctx.LastStatus;
23142176 }, "eval-lift-sum"));
@@ -2518,60 +2380,46 @@
25182380 }
25192381
25202382 ReductionStatus
2521-ForwardListFirst(TermNode& term, ContextNode& ctx)
2383+ForwardFirst(TermNode& term, ContextNode& ctx)
25222384 {
2523- RetainN(term, 3);
2385+ RetainN(term, 2);
25242386
25252387 auto i(term.begin());
25262388 auto& op(*i);
2527- const auto i_list_app(++i);
2528- auto& app(*++i);
2529- auto& l(*++i);
2530- const auto a(term.get_allocator());
2531- const auto& d(ctx.GetRecordPtr());
2532- TermNode::Container con({EvaluateLocalObjectMoved(l, d)}, a);
2533-
2534- ForwardToUnwrapped(*i_list_app, ctx);
2535- con.splice(con.cbegin(), term.GetContainerRef(), i_list_app);
2536- op = TermNode(std::allocator_arg, a, std::move(con));
2389+ auto& appv(*++i);
2390+
25372391 // TODO: Blocked. Use C++14 lambda initializers to simplify the
25382392 // implementation.
2539- return ReduceCallSubsequent(op, ctx, d, A1::NameTypedReducerHandler(
2540- std::bind([&, d](shared_ptr<Environment>& p_e0) YB_FLATTEN{
2541- return NPL::ResolveTerm(
2542- [&](TermNode& nd, ResolvedTermReferencePtr p_ref) YB_FLATTEN{
2543- if(IsBranchedList(nd))
2544- {
2545- const auto assign_term(
2546- [&](TermNode::Container&& c, ValueObject&& vo) YB_FLATTEN{
2547- // XXX: The term %l is reused as a shared bound operand as
2548- // the referent.
2549- l = TermNode(std::allocator_arg, term.get_allocator(),
2550- std::move(c), std::move(vo));
2551- return std::ref(l);
2552- });
2553- auto& x(AccessFirstSubterm(nd));
2554-
2555- if(p_ref)
2556- BindLocalReference(p_ref->GetTags()
2557- & (TermTags::Unique | TermTags::Nonmodifying), x,
2558- assign_term, p_ref->GetEnvironmentReference());
2559- else
2560- BindMoveLocalObject(x, assign_term);
2561- ForwardToUnwrapped(app, ctx);
2562-#if true
2563- // XXX: This is more efficient.
2564- term.GetContainerRef() = {std::move(app), std::move(l)};
2565-#else
2566- term.GetContainerRef().pop_front();
2567-#endif
2568- // NOTE: See the precondition for %ReduceCombindEnvTail.
2569- return ReduceCombindEnvTail(term, ctx, std::move(p_e0));
2570- }
2393+ return NPL::ResolveTerm(
2394+ [&](TermNode& nd, ResolvedTermReferencePtr p_ref) YB_FLATTEN{
2395+ if(IsBranchedList(nd))
2396+ {
2397+ const auto assign_term(
2398+ [&](TermNode::Container&& c, ValueObject&& vo) YB_FLATTEN{
2399+ // XXX: The term %op is reused as a shared bound operand as
2400+ // the referent.
2401+ op = TermNode(std::allocator_arg, term.get_allocator(),
2402+ std::move(c), std::move(vo));
2403+ return std::ref(op);
2404+ });
2405+ auto& x(AccessFirstSubterm(nd));
2406+
2407+ if(p_ref)
2408+ BindLocalReference(p_ref->GetTags()
2409+ & (TermTags::Unique | TermTags::Nonmodifying), x,
2410+ assign_term, p_ref->GetEnvironmentReference());
25712411 else
2572- ThrowInsufficientTermsError(nd, p_ref);
2573- }, op);
2574- }, d), "eval-forward-list-first"));
2412+ BindMoveLocalObject(x, assign_term);
2413+ ForwardToUnwrapped(appv, ctx);
2414+ term.GetContainerRef() = {std::move(appv), std::move(op)};
2415+ // NOTE: See the precondition of
2416+ // %Combine<TailCall>::ReduceEnvSwitch.
2417+ return Combine<TailCall>::ReduceEnvSwitch(term, ctx,
2418+ EnvironmentGuard(ctx, ctx.GetRecordPtr()));
2419+ }
2420+ else
2421+ ThrowInsufficientTermsError(nd, p_ref);
2422+ }, *++i);
25752423 }
25762424
25772425 ReductionStatus
@@ -3025,8 +2873,8 @@
30252873 return ApplyImpl(term, ctx,
30262874 NPL::AllocateEnvironment(term.get_allocator()));
30272875 if(size == 4)
3028- return ApplyImpl(term, ctx,
3029- ResolveEnvironment(*std::next(term.begin(), 3)).first);
2876+ return ApplyImpl(term, ctx, FetchValidEnvironment(
2877+ ResolveEnvironment(*std::next(term.begin(), 3)).first));
30302878 ThrowInvalidSyntaxError("Syntax error in applying form.");
30312879 }
30322880
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/source/NPL/NPLA1Internals.cpp
--- a/YFramework/source/NPL/NPLA1Internals.cpp Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/source/NPL/NPLA1Internals.cpp Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1Internals.cpp
1212 \ingroup NPL
1313 \brief NPLA1 内部接口。
14-\version r20372
14+\version r20401
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 473
1717 \par 创建时间:
1818 2020-02-15 13:20:08 +0800
1919 \par 修改时间:
20- 2021-01-31 21:26 +0800
20+ 2021-02-12 14:18 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 非公开模块名称:
@@ -128,11 +128,35 @@
128128 YAssert(ystdex::ref_eq<>()(EnvGuard.func.Context.get(), ctx),
129129 "Invalid context found.");
130130
131- // NOTE: Many orders are siginificant, see %Documentation::NPL. The comments
132- // here only specify the implementation-dependent ones.
133- // NOTE: Lifting is optional, but it shall be performed before release
134- // of guards. See also $2018-02 @ %Documentation::Workflow.
135- const auto res(HandleResultRequests(ctx));
131+ // NOTE: Many orders are siginificant, see %Documentation::NPL. For example,
132+ // lifting (if any) shall be performed before release of guards (see also
133+ // $2018-02 @ %Documentation::Workflow). The comments below only specify
134+ // the implementation-dependent ones.
135+ // NOTE: If this is called properly, %ctx.LastStatus should be maintained to
136+ // refer to the reduction status of the right term by
137+ // %PushedAction::operator() in %NPLA1.cpp.
138+ const auto res([&]() -> ReductionStatus{
139+ // NOTE: This implies the call of %RegularizeTerm before lifting.
140+ // XXX: Since the call of %RegularizeTerm is idempotent without term
141+ // modification before the next reduction of term if it does not
142+ // represent an uncollapsed reference value, there is no need to call
143+ // %RegularizeTerm if the lift is not needed. However, this is not
144+ // easily provable, so leave it as-is.
145+ if(req_lift_result != 0)
146+ {
147+ RegularizeTerm(GetTermRef(), ctx.LastStatus);
148+ for(; req_lift_result != 0; --req_lift_result)
149+ LiftToReturn(GetTermRef());
150+ return ReductionStatus::Retained;
151+ }
152+ // XXX: This is only needed on a real call from the evaluation is
153+ // reentered. However, whether here is the reentrant call is not easily
154+ // provable.
155+ // TODO: Anything necessary to prepare for invocation of first-class
156+ // continuations?
157+ RegularizeTerm(GetTermRef(), ctx.LastStatus);
158+ return ctx.LastStatus;
159+ }());
136160
137161 ystdex::dismiss(term_guard);
138162 {
diff -r c91b75c1e8bc -r 04895f90f831 YFramework/source/NPL/NPLA1Internals.h
--- a/YFramework/source/NPL/NPLA1Internals.h Sat Feb 06 16:04:05 2021 +0800
+++ b/YFramework/source/NPL/NPLA1Internals.h Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1Internals.h
1212 \ingroup NPL
1313 \brief NPLA1 内部接口。
14-\version r20579
14+\version r20902
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 882
1717 \par 创建时间:
1818 2020-02-15 13:20:08 +0800
1919 \par 修改时间:
20- 2021-02-04 00:46 +0800
20+ 2021-02-17 01:51 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 非公开模块名称:
@@ -30,11 +30,11 @@
3030
3131 #include "YModules.h"
3232 #include YFM_NPL_NPLA1 // for ContextNode, TermNode, ContextState,
33-// ReductionStatus, Reducer, NPL::tuple, YSLib::get, list, EnvironmentGuard,
34-// std::declval, std::ref, make_observer, std::bind, ystdex::unique_guard,
35-// RegularizeTerm, EnvironmentReference, ystdex::cast_mutable, TermReference,
36-// ystdex::get_less, YSLib::map, set, ystdex::retry_on_cond, ystdex::id,
37-// A1::NameTypedReducerHandler, A1::NameTypedContextHandler;
33+// ReductionStatus, Reducer, ystdex::get_less, EnvironmentReference,
34+// NPL::tuple, YSLib::get, list, ystdex::unique_guard, std::declval,
35+// EnvironmentGuard, make_observer, std::bind, std::placeholders, std::ref,
36+// TermReference, YSLib::map, set, A1::NameTypedReducerHandler,
37+// A1::NameTypedContextHandler, ystdex::bind1;
3838 #include <ystdex/ref.hpp> // for ystdex::unref;
3939
4040 namespace NPL
@@ -378,41 +378,6 @@
378378 // empty.
379379 AddRecord({});
380380 }
381-
382- /*!
383- \brief 处理操作压缩的结果请求。
384- \pre 规约上下文的最后一次规约状态表示的是当前项上的状态。
385- \sa ContextNode::LastStatus
386- */
387- ReductionStatus
388- HandleResultRequests(ContextNode& ctx) const
389- {
390- // NOTE: If this is called properly, %ctx.LastStatus should be
391- // maintained to refer to the reduction status of the right term by
392- // %PushedAction::operator() in NPLA1.cpp.
393- // NOTE: This implies the call of %RegularizeTerm before lifting. Since
394- // the call of %RegularizeTerm is idempotent without term modification
395- // before the next reduction of term, there is no need to call
396- // %RegularizeTerm if the lift is not needed.
397- if(req_lift_result != 0)
398- {
399- // NOTE: This is for the previous reduction. The order of the calls
400- // is significant.
401- RegularizeTerm(GetTermRef(), ctx.LastStatus);
402- for(; req_lift_result != 0; --req_lift_result)
403- LiftToReturn(GetTermRef());
404- return ReductionStatus::Retained;
405- }
406- // NOTE: This is only needed on a real call from the evaluation is
407- // reentered. Currently, other evaluations (e.g. for continuation are
408- // all administrative) and expected not reentered with unbound number
409- // of times when no lifting is required. However, since the TCO action
410- // should have been initialized in a call whose resouces to be reused,
411- // this should be normally unconditionally true.
412- // TODO: Prepare for invocation of first-class continuations?
413- RegularizeTerm(GetTermRef(), ctx.LastStatus);
414- return ctx.LastStatus;
415- }
416381 //@}
417382
418383 //! \since build 825
@@ -439,27 +404,30 @@
439404 return res;
440405 }
441406
407+ //! \since build 911
408+ //@{
409+ //! \brief 设置提升请求。
410+ void
411+ SetupLift() const
412+ {
413+ // NOTE: The flag indicates a request for handling during next time
414+ // before %TCOAction is finished, handled in %operator().
415+ ++req_lift_result;
416+ if(YB_UNLIKELY(req_lift_result == 0))
417+ throw NPLException(
418+ "TCO action lift request count overflow detected.");
419+ }
442420 /*
443- \brief 按参数设置 TCO 动作提升请求。
444- \param act TCO 动作。
445- \param no_lift 指定是否避免保证规约后提升结果。
446- \since build 910
421+ \brief 按参数设置提升请求。
422+ \param lift 指定规约后提升结果。
447423 */
448424 void
449- SetupTCOLift(bool no_lift) const
425+ SetupLift(bool lift) const
450426 {
451- // NOTE: The flag indicates a request for handling during next time (by
452- // the %HandleResultRequests call above before the last one) before
453- // %TCOAction is finished. The last request would be handled by
454- // %operator(), which also calls %HandleResultRequests.
455- if(!no_lift)
456- {
457- ++req_lift_result;
458- if(YB_UNLIKELY(req_lift_result == 0))
459- throw NPLException(
460- "TCO action lift request count overflow detected.");
461- }
427+ if(lift)
428+ SetupLift();
462429 }
430+ //@}
463431 };
464432
465433 //! \since build 886
@@ -509,13 +477,6 @@
509477 YAssert(&act.GetTermRef() == &term,
510478 "Invalid term for target TCO action found.");
511479 yunused(term);
512- // NOTE: The lift is handled according to the previous status of
513- // the lifting request in %act, rather than a seperated boolean value (e.g.
514- // the parameter %no_lift in %RelayForEval).
515- // NOTE: As %TCOAction::operator(), the order is significant. Otherwise,
516- // wrong environments would be destroyed and there could be dangling
517- // references.
518- act.HandleResultRequests(ctx);
519480 act.CompressForGuard(ctx, std::move(gd));
520481 return act;
521482 }
@@ -678,50 +639,6 @@
678639 }
679640 //@}
680641
681-/*!
682-\pre TCO 实现:当前动作是 TCO 动作,且其中的当前项和被规约的项相同。
683-\since build 878
684-*/
685-template<typename _fNext>
686-ReductionStatus
687-RelayForEvalOrDirect(ContextNode& ctx, TermNode& term, EnvironmentGuard&& gd,
688- bool no_lift, _fNext&& next)
689-{
690- // XXX: For thunked code, %next shall likely be a %Continuation before being
691- // captured and it is not capturable here. No %SetupNextTerm needs to be
692- // called here. Otherwise, %next is not a %Contiuation and it shall still
693- // handle the capture of the term by itself. The %term is optinonally used
694- // in direct calls instead of the setup next term, while they shall be
695- // equivalent.
696-#if NPL_Impl_NPLA1_Enable_TCO
697- PrepareTCOEvaluation(ctx, term, std::move(gd)).SetupTCOLift(no_lift);
698- return A1::RelayCurrentOrDirect(ctx, yforward(next), term);
699-#elif NPL_Impl_NPLA1_Enable_Thunked
700- // TODO: Blocked. Use C++14 lambda initializers to simplify the
701- // implementation.
702- auto act(MakeMoveGuard(gd));
703-
704- if(no_lift)
705- return A1::RelayCurrentNext(ctx, term, yforward(next), std::move(act));
706-
707- // XXX: Term reused. Call of %SetupNextTerm is not needed as the next
708- // term is guaranteed not changed when %next is a continuation.
709- Continuation cont(A1::NameTypedContextHandler([&]{
710- // TODO: Avoid fixed continuation parameter.
711- return ReduceForLiftedResult(term);
712- }, "eval-lift-result"), ctx);
713-
714- RelaySwitched(ctx, std::move(act));
715- return A1::RelayCurrentNext(ctx, term, yforward(next), std::move(cont));
716-#else
717- yunused(gd);
718-
719- const auto res(RelayDirect(ctx, next, term));
720-
721- return no_lift ? res : ReduceForLiftedResult(term);
722-#endif
723-}
724-
725642
726643 //! \since build 821
727644 template<typename _fNext>
@@ -732,17 +649,255 @@
732649 std::ref(ContextState::Access(ctx).ReduceOnce), yforward(next));
733650 }
734651
735-//! \since build 884
652+
653+//! \since build 911
654+//@{
655+struct NonTailCall final
656+{
657+ template<typename _fCurrent>
658+ YB_FLATTEN static inline ReductionStatus
659+ RelayNextGuarded(ContextNode& ctx, TermNode& term, EnvironmentGuard&& gd,
660+ _fCurrent&& cur)
661+ {
662+ // XXX: For thunked code, %cur shall likely be a %Continuation before
663+ // being captured and it is not capturable here. No %SetupNextTerm
664+ // needs to be called here. Otherwise, %cur is not a %Contiuation and
665+ // it shall still handle the capture of the term by itself. The %term
666+ // is optinonally used in direct calls instead of the next term setup,
667+ // while they shall be equivalent.
668+#if NPL_Impl_NPLA1_Enable_Thunked
669+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
670+ // implementation.
671+ return
672+ A1::RelayCurrentNext(ctx, term, yforward(cur), MakeMoveGuard(gd));
673+#else
674+ yunused(gd);
675+ return A1::RelayDirect(ctx, cur, term);
676+#endif
677+ }
678+
679+ template<typename _fCurrent>
680+ YB_FLATTEN static inline ReductionStatus
681+ RelayNextGuardedLifted(ContextNode& ctx, TermNode& term,
682+ EnvironmentGuard&& gd, _fCurrent&& cur)
683+ {
684+ // XXX: See %RelayNextGuarded.
685+#if NPL_Impl_NPLA1_Enable_Thunked
686+ auto act(MakeMoveGuard(gd));
687+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
688+ // implementation.
689+ // XXX: Term reused. Call of %SetupNextTerm is not needed as the next
690+ // term is guaranteed not changed when %cur is a continuation.
691+ Continuation cont(A1::NameTypedContextHandler([&]{
692+ // TODO: Avoid fixed continuation parameter.
693+ return ReduceForLiftedResult(term);
694+ }, "eval-lift-result"), ctx);
695+
696+ RelaySwitched(ctx, std::move(act));
697+ return A1::RelayCurrentNext(ctx, term, yforward(cur), std::move(cont));
698+#else
699+ yunused(gd);
700+ RelayDirect(ctx, cur, term);
701+ return ReduceForLiftedResult(term);
702+#endif
703+ }
704+
705+ template<typename _fCurrent>
706+ static ReductionStatus
707+ RelayNextGuardedProbe(ContextNode& ctx, TermNode& term,
708+ EnvironmentGuard&& gd, bool lift, _fCurrent&& cur)
709+ {
710+ // XXX: See %RelayNextGuarded.
711+#if NPL_Impl_NPLA1_Enable_Thunked
712+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
713+ // implementation.
714+ auto act(MakeMoveGuard(gd));
715+
716+ if(lift)
717+ {
718+ // XXX: Term reused. Call of %SetupNextTerm is not needed as the
719+ // next term is guaranteed not changed when %cur is a continuation.
720+ Continuation cont(A1::NameTypedContextHandler([&]{
721+ // TODO: Avoid fixed continuation parameter.
722+ return ReduceForLiftedResult(term);
723+ }, "eval-lift-result"), ctx);
724+
725+ RelaySwitched(ctx, std::move(act));
726+ return A1::RelayCurrentNext(ctx, term, yforward(cur),
727+ std::move(cont));
728+ }
729+ return A1::RelayCurrentNext(ctx, term, yforward(cur), std::move(act));
730+#else
731+ yunused(gd);
732+
733+ const auto res(RelayDirect(ctx, cur, term));
734+
735+ return lift ? ReduceForLiftedResult(term) : res;
736+#endif
737+ }
738+
739+ //! \pre TCO 实现:当前动作非 TCO 动作。
740+ static void
741+ SetupForNonTail(ContextNode& ctx, TermNode& term)
742+ {
743+#if NPL_Impl_NPLA1_Enable_TCO
744+ YAssert(!AccessTCOAction(ctx), "Non-tail context expected.");
745+#endif
746+ // XXX: Assume the next action is not a %TCOAction.
747+ ctx.LastStatus = ReductionStatus::Neutral;
748+ // NOTE: This does not rely on the existence of the %TCOAction, as it
749+ // will call %EnsureTCOAction. Since the call would rely on %TCOAction,
750+ // anyway, creating the TCO action here instead of a new action
751+ // to restore the environment is more efficient.
752+#if NPL_Impl_NPLA1_Enable_TCO
753+ SetupTailTCOAction(ctx, term, {});
754+#else
755+ yunused(term);
756+#endif
757+ }
758+};
759+
760+
761+struct TailCall final
762+{
763+ //! \pre TCO 实现:当前动作是 TCO 动作,且其中的当前项和被规约的项相同。
764+ template<typename _fCurrent>
765+ YB_FLATTEN static inline ReductionStatus
766+ RelayNextGuarded(ContextNode& ctx, TermNode& term, EnvironmentGuard&& gd,
767+ _fCurrent&& cur)
768+ {
769+ // XXX: See %NonTailCall::RelayNextGuarded.
770+#if NPL_Impl_NPLA1_Enable_TCO
771+ PrepareTCOEvaluation(ctx, term, std::move(gd));
772+ return A1::RelayCurrentOrDirect(ctx, yforward(cur), term);
773+#else
774+ return NonTailCall::RelayNextGuarded(ctx, term, std::move(gd),
775+ yforward(cur));
776+#endif
777+ }
778+
779+ //! \pre TCO 实现:当前动作是 TCO 动作,且其中的当前项和被规约的项相同。
780+ template<typename _fCurrent>
781+ YB_FLATTEN static inline ReductionStatus
782+ RelayNextGuardedLifted(ContextNode& ctx, TermNode& term,
783+ EnvironmentGuard&& gd, _fCurrent&& cur)
784+ {
785+ // XXX: See %NonTailCall::RelayNextGuardedLifted.
786+#if NPL_Impl_NPLA1_Enable_TCO
787+ PrepareTCOEvaluation(ctx, term, std::move(gd)).SetupLift();
788+ return A1::RelayCurrentOrDirect(ctx, yforward(cur), term);
789+#else
790+ return NonTailCall::RelayNextGuardedLifted(ctx, term, std::move(gd),
791+ yforward(cur));
792+#endif
793+ }
794+
795+ template<typename _fCurrent>
796+ static inline ReductionStatus
797+ RelayNextGuardedProbe(ContextNode& ctx, TermNode& term,
798+ EnvironmentGuard&& gd, bool lift, _fCurrent&& cur)
799+ {
800+ // XXX: See %TailCall::RelayNextGuarded.
801+#if NPL_Impl_NPLA1_Enable_TCO
802+ PrepareTCOEvaluation(ctx, term, std::move(gd)).SetupLift(lift);
803+ return A1::RelayCurrentOrDirect(ctx, yforward(cur), term);
804+#else
805+ return NonTailCall::RelayNextGuardedProbe(ctx, term, std::move(gd),
806+ lift, yforward(cur));
807+#endif
808+ }
809+
810+ static void
811+ SetupForNonTail(ContextNode&, TermNode&) ynothrow
812+ {}
813+};
814+
815+
816+/*!
817+\pre TCO 实现:当前动作是 TCO 动作,且其中的当前项和被规约的项相同。
818+\since build 878
819+*/
736820 template<typename _fCurrent>
737821 inline ReductionStatus
738-ReduceSubsequentCombinedBranch(TermNode& term, ContextNode& ctx,
739- _fCurrent&& next)
822+RelayForEvalOrDirect(ContextNode& ctx, TermNode& term, EnvironmentGuard&& gd,
823+ bool no_lift, _fCurrent&& cur)
740824 {
741- return A1::ReduceCurrentNext(term, ctx,
742- Continuation(std::ref(ReduceCombinedBranch), ctx), yforward(next));
825+ return TailCall::RelayNextGuardedProbe(ctx, term, std::move(gd), !no_lift,
826+ yforward(cur));
743827 }
744828
745829
830+template<class _tTraits>
831+struct Combine final
832+{
833+ // XXX: A combination of an operative and its operand shall always be
834+ // evaluated in a tail context. However, for a combiner call, sometimes it
835+ // is not in the tail context in the enclosing context. If the call needs
836+ // no creation of %TCOAction (e.g. fully implemented native code), avoiding
837+ // calling %PrepareTCOEvaluation needs no precondition of the existence of
838+ // %TCOAction, and this (with %_tTraits as %TailCall) can be an
839+ // optimization.
840+ //! \pre TCO 实现:当前动作是 TCO 动作,且其中的当前项和被规约的项相同。
841+ //@{
842+ // XXX: Do not use %YB_FLATTEN here for LTO compiling performance.
843+ static ReductionStatus
844+ RelayEnvSwitch(ContextNode& ctx, TermNode& term, EnvironmentGuard gd)
845+ {
846+ // NOTE: %ReduceFirst and other passes would not be called again. The
847+ // unwrapped combiner should have been evaluated and it would not be
848+ // wrongly evaluated again.
849+ // XXX: Consider optimization when the combiner subterm is known
850+ // regular.
851+ // NOTE: Term is set in %_tTraits::RelayNextGuarded, even for direct
852+ // inlining call of %ReduceCombinedBranch.
853+ // NOTE: The precondition is similar to the last call in
854+ // %EvalImplUnchecked in the presense of the assumption that %term is
855+ // from the current term saved in the context.
856+ return _tTraits::RelayNextGuarded(ctx, term, std::move(gd),
857+ std::ref(ReduceCombinedBranch));
858+ }
859+ //! \pre 间接断言:环境指针参数非空。
860+ static ReductionStatus
861+ RelayEnvSwitch(ContextNode& ctx, TermNode& term,
862+ shared_ptr<Environment> p_env)
863+ {
864+ return RelayEnvSwitch(ctx, term, EnvironmentGuard(ctx,
865+ ctx.SwitchEnvironmentUnchecked(std::move(p_env))));
866+ }
867+
868+ // NOTE: A %_tGuardOrEnv does not support an empty environment pointer.
869+ template<class _tGuardOrEnv>
870+ // XXX: Do not use %YB_FLATTEN here for LTO compiling performance.
871+ static inline ReductionStatus
872+ ReduceEnvSwitch(TermNode& term, ContextNode& ctx, _tGuardOrEnv&& gd_or_env)
873+ {
874+ _tTraits::SetupForNonTail(ctx, term);
875+ // NOTE: The next term is set here unless direct inlining call of
876+ // %ReduceCombinedBranch is used.
877+#if !NPL_Impl_NPLA1_Enable_InlineDirect
878+ SetupNextTerm(ctx, term);
879+#endif
880+ return RelayEnvSwitch(ctx, term, yforward(gd_or_env));
881+ }
882+
883+ // NOTE: As %ReduceSubsequent.
884+ template<typename _fNext, class _tGuardOrEnv>
885+ static ReductionStatus
886+ ReduceCallSubsequent(TermNode& term, ContextNode& ctx,
887+ _tGuardOrEnv&& gd_or_env, _fNext&& next)
888+ {
889+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
890+ // implementation.
891+ return A1::ReduceCurrentNext(term, ctx,
892+ ystdex::bind1([](TermNode& t, ContextNode& c, _tGuardOrEnv& g_e){
893+ return ReduceEnvSwitch(t, c, std::move(g_e));
894+ }, std::placeholders::_2, std::move(gd_or_env)), yforward(next));
895+ }
896+ //@}
897+};
898+//@}
899+
900+
746901 //! \since build 897
747902 YB_ATTR_nodiscard YB_PURE inline
748903 PDefH(TermReference, EnsureLValueReference, const TermReference& ref)
diff -r c91b75c1e8bc -r 04895f90f831 doc/ChangeLog.V0.9.txt
--- a/doc/ChangeLog.V0.9.txt Sat Feb 06 16:04:05 2021 +0800
+++ b/doc/ChangeLog.V0.9.txt Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file ChangeLog.V0.9.txt
1212 \ingroup Documentation
1313 \brief 版本更新历史记录 - V0.9 。
14-\version r2531
14+\version r2653
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 800
1717 \par 创建时间:
1818 2020-10-12 17:19:23 +0800
1919 \par 修改时间:
20- 2021-02-06 15:35 +0800
20+ 2021-02-17 01:51 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -32,6 +32,129 @@
3232
3333 $now
3434 (
35+ / %Tools.Scripts $=
36+ (
37+ * "passed wrongly quoted string as the command"
38+ @ "applicative 'compile-ok'" @ "platform %Win32"
39+ @ "%SHBuild-YSLib-common.txt" @ $since b796
40+ // This would detected the wrong compiler style and the compiler \
41+ options.
42+ $= (/ ^ "negated %COMSPEC detection" ~ "%SHELL detection"),
43+ // %SHELL can be set by MSYS shells. %COMSPEC is assumed to \
44+ be compatible to 'CMD.exe', which is more reliable. See \
45+ also https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/system-wsystem#remarks.
46+ / @ "%SHBuild-common-toolchain.sh" $=
47+ (
48+ * "missing optional parameter for options other than '-xc'"
49+ @ "function %SHBuild_CheckCompiler"
50+ $= (+ "trailing parameters");
51+ / $forced DLDI "functions %(SHBuild_CheckCC, SHBuild_CheckCXX)"
52+ ),
53+ / @ "%SHBuild-build.sh" $=
54+ (
55+ / DLDI "quoted all arguments" @ "%SHBuild_Puts calls"
56+ @ "%SHBuild-build.sh",
57+ + "workaround to MSYS2 x86_64 binutils with ASLR enabled by \
58+ default used with G++" ^ $dep_from
59+ ("%SHBuild_CheckCompiler" @ "%SHBuild-common-toolchain.sh")
60+ )
61+ ),
62+ / %YFramework $=
63+ (
64+ * $dev "missing renaming %ymsgdef.h" @ "Microsoft VC++ project"
65+ $since b872,
66+ / %NPL $=
67+ (
68+ + $dev "inclusion %YException" @ %SContext,
69+ / %NPLA1Internals $=
70+ (
71+ / @ 'NPL_Impl_NPLA1_Enable_TCO' $=
72+ (
73+ - "call to %HandleResultRequests"
74+ @ "function %PrepareTCOEvaluation";
75+ * $comp "invalid lifting requests for TCO"
76+ $orig (@ %NPLA1 $since b854)
77+ $dep_to "redundant TCO result lifting",
78+ // See $2021-02 @ %Documentation::Workflow.
79+ / @ "class %TCOAction" $=
80+ (
81+ / ("merged %HandleResultRequests" -> "%operator()"),
82+ / "function %SetupTCOLift" -> "2 functions %SetupLift"
83+ )
84+ ),
85+ - $revert(b884)
86+ "function template %ReduceSubsequentCombinedBranch",
87+ // This is no longer used. A similar function template \
88+ with an environment guard parameter could be more \
89+ useful.
90+ + "struct %NonTailCall",
91+ (
92+ + "struct %TailCall";
93+ / DLDI "simplified function %RelayForEvalOrDirect"
94+ ),
95+ + "class template %Combine"
96+ ),
97+ - '&&' @ "2nd parameter type" @ "constructor %EnvironmentSwitcher"
98+ @ %NPLA,
99+ / @ "namespace %Forms" @ %NPLA1Forms $=
100+ (
101+ + "function %ForwardFirst"
102+ ^ $dep_from ("%EnvironmentSwitcher" @ %NPLA),
103+ - "function %ForwardListFirst"
104+ $dep_from "removal of old list forwarding applicative",
105+ / DLDI "optimized environment switching",
106+ / DLDI "simplified functions %(FoldR1, Map1)",
107+ (
108+ / $revert_ex(b872) "checked host environment values"
109+ @ "function %Apply" ^ "%Environment::EnsureValid";
110+ / DLI "simplified reduction function calls" ^ $dep_from
111+ ("%(NonTailCall, TailCall, Combine)" @ %NPLA1Internals);
112+ / $comp DLI "simplified environment switch"
113+ ^ "%NPL::SwitchEnvironmentUnchecked"
114+ ~ "%NPL::SwitchEnvironment"
115+ )
116+ ),
117+ / @ "function %LoadGroundContext" @ %Dependency $=
118+ (
119+ * $comp "missing proper lifting of the call result"
120+ @ "alternative derivation" @ "operative '$sequence'"
121+ @ 'NPL_Impl_NPLA1_Enable_TCO' $since b910
122+ $dep_from "redundant TCO result lifting",
123+ // See $2021-02 @ %Documentation::Workflow.
124+ (
125+ + "applicative 'forward-first%'" ^ $dep_from
126+ ("%ForwardFirst" @ %NPLA1Forms);
127+ / DLDI "simplified" @ ("alternative derivation"
128+ @ "appliative %first", "derivation"
129+ @ "applicative 'list-extract'")
130+ ^ 'forward-first%' ~ 'forward-list-first%';
131+ - "applicative 'forward-list-first%'"
132+ $dep_from "removal of old list forwarding applicative"
133+ )
134+ )
135+ ),
136+ / %YSLib $=
137+ (
138+ / %Core $=
139+ (
140+ / $dev "inclusion %YObject" @ %YEvent
141+ -> "inclusion %YBase.YStandardEx.Examiner",
142+ (
143+ + $dev $lib "include %YException" @ %YMessage;
144+ / $dev "inclusion %YCoreUtilities" @ %YObject
145+ -> "inclusion %YShellDefinition" $dep_from %NPL.SContext,
146+ ),
147+ / $dev "include %YObject" @ %YString
148+ -> "inclusion %YShellDefinition",
149+ / $dev "inclusion %YObject" @ %YDevice
150+ -> "inclusion %(YFunc, YBase.YStandardEx.Exception)"
151+ )
152+ )
153+ )
154+),
155+
156+b910
157+(
35158 / DLDI 'friend YB_PURE' -> 'YB_PURE friend' $effective @ "%operator=="
36159 @ "class template %WrappedContextHandler" @ %YFramework.NPL.NPLA1,
37160 // More consistent to other code.
diff -r c91b75c1e8bc -r 04895f90f831 doc/NPL.txt
--- a/doc/NPL.txt Sat Feb 06 16:04:05 2021 +0800
+++ b/doc/NPL.txt Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPL.txt
1212 \ingroup Documentation
1313 \brief NPL 规范和实现规格说明。
14-\version r19650
14+\version r19717
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 304
1717 \par 创建时间:
1818 2012-04-25 10:34:20 +0800
1919 \par 修改时间:
20- 2021-02-05 15:58 +0800
20+ 2021-02-15 17:58 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -1310,7 +1310,7 @@
13101310 合并子应用使用应用序(@4.4.4.5) 。
13111311 被应用的合并子是应用合并子(applicative combiner) ,简称应用子(applicative) ;
13121312 由派生实现定义的扩展合并子(extended combiner) 。
1313-应用子总是由底层(underlying) 对应的合并子通过一元的包装(wrap) 操作得到;其逆操作为解包装(unwrap) 。
1313+应用子总是对应一个底层(underlying) 合并子,可通过底层合并子上的一元的包装(wrap) 操作得到;其逆操作为解包装(unwrap) 。
13141314 解包装结果不是扩展合并子的合并子称为真合并子(proper combiner) 。
13151315 合并子被调用时通常返回(@4.5.3.1) 且仅返回一次(详见 @4.5.3.3)。
13161316 合并子上可以定义若干等价关系,这些等价关系蕴含关于函数应用替换的基本形式:
@@ -3987,66 +3987,22 @@
39873987 回收使函数对象在表达式求值外完毕之前结束,这仍然符合 @5.2.6 的要求。
39883988 当前 NPL::LiftToReturn(@6.6.3) 的调用非嵌套调用安全(@6.1) 。在项的嵌套深度依赖调用深度时,不满足 PTC 。
39893989
3990-@7.11.6 元数据:
3991-模块 NPL::NPLA1 提供特定可由函数 A1::QueryContinuationName 查询得到。
3990+@7.11.6 续延名称:
3991+模块 NPL::NPLA1 提供特定可由函数 A1::QueryContinuationName 查询得到的续延名称。
39923992 其中查询结果的名称和 A1::Continuation::Handler 或 Reducer 的特定目标类型关联。
3993-除非另行指定,关联的类型是非公开的内部类型。这些名称包括:
3994-conditional-eval-sequence
3995-equal-subterm
3996-equal-siblings
3997-eval-acc-head-next
3998-eval-acc-nested
3999-eval-accl-accl
4000-eval-accl-tail
4001-eval-accr-accr
4002-eval-accr-sum
3993+除非另行指定,关联的类型是非公开的内部类型。
3994+在 NPLA1 实现中引入的这些名称包括:
40033995 eval-argument-list
4004-eval-booleans
40053996 eval-combine-operands
40063997 eval-combine-operator
40073998 eval-combine-return
4008-eval-cond-list
4009-eval-foldr1-kons
4010-eval-forward-list-first
40113999 eval-guard
40124000 eval-lift-result
4013-eval-lift-sum
4014-eval-map1-appv
4015-eval-map1-cons
40164001 eval-sequence
40174002 eval-sequence-return
40184003 eval-tail :关联 TCO 动作(@7.10.3) 。
4019-eval-vau
4020-load-external
4021-match-ptree
4022-match-ptree-recursive
4023-select-clause
40244004 若特定对象语言操作使用非本机实现(@5.2.1) ,可使用其它续延。
4025-上述名称中部分名称和 klisp 0.3 中作用近似的续延的名称一致,功能近似。
4026-不一致的名称包括:
4027-equal-subterm :Forms::EqualTermValue(@8.4.1) 比较直接子项。
4028-equal-siblings :Forms::EqualTermValue 比较同一个项中的剩余其它子项。
4029-因为 klisp 的 equal? 直接使用自动机实现,在比较操作中没有对应的续延。
4030-eval-acc-head-next :Forms::AccL 和 Forms::AccR(@8.4.9) 公共操作后分派的不同操作。
4031-eval-acc-nested :Forms::AccL 和 Forms::AccR(@8.4.9) 嵌套调用抽象列表余下的元素的公共操作。
4032-eval-accl-accl :Forms::AccL 递归调用。
4033-eval-accl-tail :Forms::AccL 调用取抽象列表余下的元素的函数。
4034-eval-accr-accr :Forms::AccR 递归调用。
4035-eval-accr-sum :Forms::AccR 调用取抽象列表部分和的函数。
4036-eval-combine-return :非 TCO 的规约合并求值(@7.6.4.2) 实现中设置规约合并最后的返回结果。
4037-eval-foldr1-kons :Forms::FoldR1(@8.4.9) 应用子调用。
4038-eval-forward-list-first :Forms::ForwardListFirst(@8.4.3) 取列表第一个元素。
4039-eval-guard :非 TCO 的求值实现重置守卫的附加动作帧(@5.10.6)。
4040-eval-lift-result :非 TCO 的求值实现调用 NPL::ReduceForLiftedResult(@6.7.1) 提升返回结果。
4041-eval-lift-sum :Forms::AccR、Forms::FoldR1 和 Forms::Map1(@8.4.9) 公共的部分和提升调用。
4042-eval-map1-appv :Forms::Map1(@8.4.9) 应用子调用。
4043-eval-map1-cons :Forms::Map1 列表构造调用。
4044-eval-sequence-return :非 TCO 的 A1::ReduceOrdered(@7.4.6) 实现中设置规约合并最后的返回结果。
4045-eval-tail :TCO 动作尾上下文求值(和 klisp 不同,不依赖 GC(@5.2.4.4) 而在 TCO 动作单独保存资源(@7.10.5.1) )。
4046-eval-vau :求值过程抽象(@8.4.5) 在带环境的函数构造器中作为续延。
4047-注意 klisp 的 $vau 不具有应保证被求值的实际参数,不需要异步调用,没有对应的续延。
4048-load-external :A1::RelayToLoadExternal(@8.5.2) 加载外部翻译单元。
4049-match-ptree-recursive :支持延迟递归绑定( Forms::DefineWithRecursion 和 Forms::SetWithRecursion(@8.4.4.3) )。
4005+另见其它 NPLA1 实现模块中引入的续延名称(@8.6.1) 。
40504006
40514007 @7.11.7 嵌套调用说明:
40524008 显式保证嵌套调用安全(@5.2.7) 的异步调用 API 包括:
@@ -4057,7 +4013,6 @@
40574013 例外参见:
40584014 @6.1
40594015 @8.4.5
4060-@8.4.8
40614016 另见 @7.9.2 。
40624017
40634018 @8 NPLA1 对象语言扩展实现:
@@ -4159,7 +4114,7 @@
41594114 Forms 提供以下函数实现对象语言中的列表操作:
41604115 Forms::Cons
41614116 Forms::ConsRef
4162-Forms::ForwardListFirst
4117+Forms::ForwardFirst
41634118 Forms::First
41644119 Forms::FirstAt
41654120 Forms::FirstRef
@@ -4278,7 +4233,6 @@
42784233 其中,结果第二项的应用子用于取被封装类型的值。
42794234 作用于右值时,使用引入不安全引用值(@5.6.3.1) 的项引用操作(@6.4.4) 而不提供检查(@5.2.2) 。
42804235 因为访问的是右值,不影响内存安全(@5.2.4.3) 。
4281-封装类型的相等判断在判断具有封装类型的子对象时,非嵌套调用安全(参见 @6.1 )。
42824236
42834237 @8.4.9 通用基本派生操作:
42844238 Forms 提供以下可通过对象语言派生的操作的对应本机实现的函数:
@@ -4321,7 +4275,7 @@
43214275 不保证是真合并子(@4.5.3.2) 。
43224276 因为不直接公开合并子的实现(如 @8 ),其中不需要有项检查(如 @8.2.2);但可能仍有遍处理器的检查(@7.6.1.3) 。
43234277 在对象语言中的对应接口参见 NPLA1 参考实现环境(@10) 。
4324-NPL::Dependency 还提供其它一些接口,调用函数 Forms::LoadGroundContext 初始化上下文后继续调用,初始化特定操作的环境:
4278+模块 NPL::Dependency 还提供其它一些接口,调用函数 Forms::LoadGroundContext 初始化上下文后继续调用,初始化特定操作的环境:
43254279 函数模板 Forms::GetModuleFor 加载代码作为模块(@1.4.6.4) 以提供特定集合的对象语言实体的定义。
43264280 函数模板 Forms::LoadModule 和 Forms::LoadModuleChecked 加载模块为变量。后者在指定名称的绑定已存在时抛出异常。
43274281 函数 Forms::LoadModule_std_environments 提供环境操作(@12.1) ;
@@ -4332,6 +4286,59 @@
43324286 函数 Forms::LoadModule_SHBuild 提供其它一些供 SHBuild 间接调用的操作(@13.1.1) 。
43334287 函数 Forms::LoadStandardContext 调用 Forms::LoadGroundContext 并加载基础上下文中提供的库模块(@10.2) ;另见 @12 。
43344288
4289+@8.6 实现注记:
4290+
4291+@8.6.1 NPLA1 实现模块的续延名称(@7.11.6) :
4292+在模块 NPL::NPLA1Forms 中引入的续延名称包括:
4293+conditional-eval-sequence
4294+equal-subterm
4295+equal-siblings
4296+eval-acc-head-next
4297+eval-acc-nested
4298+eval-accl-accl
4299+eval-accl-tail
4300+eval-accr-accr
4301+eval-accr-sum
4302+eval-booleans
4303+eval-cond-list
4304+eval-foldr1-kons
4305+eval-lift-sum
4306+eval-map1-appv
4307+eval-map1-cons
4308+eval-vau
4309+match-ptree
4310+match-ptree-recursive
4311+select-clause
4312+在模块 NPL::Dependency 中引入的续延名称包括:
4313+load-external
4314+在模块 NPL::Dependency 中,若特定对象语言操作使用非本机实现(@5.2.1) ,可使用不同的续延名称。
4315+
4316+@8.6.2 klisp 续延名称:
4317+NPLA1 续延名称(@7.11.6) 和上述续延名称(@8.6.1) 中,部分名称和 klisp 0.3 中作用近似的续延的名称一致,功能近似。
4318+不一致的名称包括:
4319+equal-subterm :Forms::EqualTermValue(@8.4.1) 比较直接子项。
4320+equal-siblings :Forms::EqualTermValue 比较同一个项中的剩余其它子项。
4321+因为 klisp 的 equal? 直接使用自动机实现,在比较操作中没有对应的续延。
4322+eval-acc-head-next :Forms::AccL 和 Forms::AccR(@8.4.9) 公共操作后分派的不同操作。
4323+eval-acc-nested :Forms::AccL 和 Forms::AccR(@8.4.9) 嵌套调用抽象列表余下的元素的公共操作。
4324+eval-accl-accl :Forms::AccL 递归调用。
4325+eval-accl-tail :Forms::AccL 调用取抽象列表余下的元素的函数。
4326+eval-accr-accr :Forms::AccR 递归调用。
4327+eval-accr-sum :Forms::AccR 调用取抽象列表部分和的函数。
4328+eval-combine-return :非 TCO 的规约合并求值(@7.6.4.2) 实现中设置规约合并最后的返回结果。
4329+eval-foldr1-kons :Forms::FoldR1(@8.4.9) 应用子调用。
4330+eval-guard :非 TCO 的求值实现重置守卫的附加动作帧(@5.10.6)。
4331+eval-lift-result :非 TCO 的求值实现调用 NPL::ReduceForLiftedResult(@6.7.1) 提升返回结果。
4332+eval-lift-sum :Forms::AccR、Forms::FoldR1 和 Forms::Map1(@8.4.9) 公共的部分和提升调用。
4333+eval-map1-appv :Forms::Map1(@8.4.9) 应用子调用。
4334+eval-map1-cons :Forms::Map1 列表构造调用。
4335+eval-sequence-return :非 TCO 的 A1::ReduceOrdered(@7.4.6) 实现中设置规约合并最后的返回结果。
4336+eval-tail :TCO 动作尾上下文求值(和 klisp 不同,不依赖 GC(@5.2.4.4) 而在 TCO 动作单独保存资源(@7.10.5.1) )。
4337+eval-vau :求值过程抽象(@8.4.5) 在带环境的函数构造器中作为续延。
4338+注意 klisp 的 $vau 不具有应保证被求值的实际参数,不需要异步调用,没有对应的续延。
4339+load-external :A1::RelayToLoadExternal(@8.5.2) 加载外部翻译单元。
4340+match-ptree-recursive :支持延迟递归绑定( Forms::DefineWithRecursion 和 Forms::SetWithRecursion(@8.4.4.3) )。
4341+
43354342 @9 NPLA1 核心语言设计:
43364343 NPL 是独立设计的,但其派生语言和其它一些语言有类似之处;这些语言和 NPL 方言之间并不具有派生关系。但为简化描述,部分地引用这些现有语言规范(@2.3.1.2) 中的描述,仅强调其中的不同。
43374344 NPLA1 符合 NPL 和 NPLA 的语言规则,其实现环境(@2.3.4) 还应提供本章起的其它程序接口。
@@ -5806,10 +5813,10 @@
58065813 对一个操作数的情形返回原值,否则类似 cons ,检查最后一个实际参数是 <list> 。
58075814 为不需要如 Kernel 支持派生 $vau ,直接使用 apply 派生。
58085815 list*% <object>+ :同 list* ,但创建的列表元素保留引用值。
5809-forward-list-first% <applicative1> <applicative2> <list> :取列表的第一元素并转发给指定的应用子。
5810-对参数列表 (&list-appv &appv &l) ,结果定义为和以下求值表达式等价:
5811-($lambda% ((&x .)) (forward! appv) ($move-resolved! x)) ((forward! list-appv) l) ;
5812-其中,调用 (forward! list-appv) 和 (forward! appv)(除参数求值外)的动态环境同调用 forward-list-first% 的动态环境。
5816+forward-first% <applicative> <list> :取列表的第一元素并转发给指定的应用子。
5817+对参数列表 (&appv (&x .)) ,结果定义为和以下求值表达式等价:
5818+(forward! appv) (list% ($move-resolved! x)) ;
5819+其中,调用 appv 的底层合并子(@4.5.3.2) 的动态环境同调用 forward-first% 的动态环境。
58135820 assign%! <reference> <object> :同 assign@!(@11.3.4) ,但 <object> 是引用时被折叠。
58145821 assign! <reference> <object> :同 assign%! ,但 <object> 隐含左值到右值转换。
58155822 set-first! <list> <object> :修改列表的第一个元素。
@@ -5975,7 +5982,7 @@
59755982 nonfoldable? <list> :判断参数是否不可被继续折叠映射:存在空列表。
59765983 输入类似 Kernel map 操作可接受的列表参数或空列表。若输入是空列表,结果为 #f 。
59775984 list-extract <list> <applicative> :以指定应用子在指定列表中选取并合并内容为新的列表。
5978-对参数列表 (&l &extr) ,结果同求值 accr l null? () ($lambda% (&l) forward-list-first% expire extr l) rest% cons% 。
5985+对参数列表 (&l &extr) ,结果同求值 accr l null? () ($lambda% (&l) forward-first% extr (expire l)) rest% cons% 。
59795986 list-extract-first <list> :同指定应用子为 first 的 list-extract 。
59805987 对参数列表 (&l &extr) ,结果同求值 list-extract ls first 。
59815988 list-extract-first-rest%! <list> :同指定应用子为 rest% 的 list-extract 。
diff -r c91b75c1e8bc -r 04895f90f831 doc/Workflow.txt
--- a/doc/Workflow.txt Sat Feb 06 16:04:05 2021 +0800
+++ b/doc/Workflow.txt Wed Feb 17 02:25:32 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file Workflow.txt
1212 \ingroup Documentation
1313 \brief 工作流汇总报告。
14-\version r4224
14+\version r4235
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 433
1717 \par 创建时间:
1818 2013-07-31 01:27:41 +0800
1919 \par 修改时间:
20- 2021-02-04 08:20 +0800
20+ 2021-02-12 12:05 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -4164,13 +4164,11 @@
41644164 This bug was hidden by a TCO implementation detail, see below.
41654165 Implementation of the TCO action is revised.
41664166 Some implementations are refactored and now it is a slightly more efficient.
4167- The order of the result handling relative to frame compression in the operation compression (TCO action prepration) is fixed.
4168- The bug would case some reference retained unexpectedly.
41694167 Some bugs in the result handling has been fixed.
41704168 When the combining request is missing, the term regularization is just ignored, which is wrong.
41714169 This would make impossible to preserve references in the middle of the tail call sequence if it is finally lifted.
41724170 Previously, the bug of those native implementation is hidden by the missing of the request.
4173- As an optimization, the combining request now further removed after the above fix and the fix in 'Forms::AccR', 'Forms::FoldR1' and 'Forms::Map1'.
4171+ As an optimization after the above fix and the fix in 'Forms::AccR', 'Forms::FoldR1' and 'Forms::Map1', the combining request is now further removed totally.
41744172 When the lifting request is handled, it is not consumed.
41754173 This would hide the bug of wrong reference handling when the enclosing call has required the lifting of the call result.
41764174 For example, the applcative 'list-concat' (defined by '$defl!') implementation was buggy but the bug was not shown, for subtle implementation-specific reasons.
@@ -4186,9 +4184,16 @@
41864184 The lifting request is now recorded as a count in the TCO action.
41874185 This fixes the bug that uncollapsed reference values can have different result (to correct ones not in TCO actions) after one operation of result handling.
41884186 Like adding the combiner wrapping count ('A1::FormContextHandler::Wrapping'), if the count overflow, an exception is thrown.
4187+ The redundant lifting request in the operation compression (TCO action preparation) is removed.
4188+ This was originally introduced in internal 'RelayForEval' in module NPL::NPLA1 since build 854.
4189+ The bug would cause the result handling incorrectly by missing lifts when the lifts only requested in some enclosing calls.
4190+ In particular, it would lead to invalid reference returned without lifting, e.g. in '$bindings/p->environment' with derived '$sequence'.
4191+ With native implementation '$sequence' there would be no invalid reference because the native implementation using no TCO actions inside.
4192+ This bug was not shown before build 910, because once there was an lifting request, the bug of redundant lifting for uncollapsed references just provided the missing lifts onward.
4193+ The bug also implying the order relative to the frame compression is wrong, which would case some reference retained unexpectedly.
41894194 A bug in the native implementation of applicatives with applicative arguments (i.e. callbacks) has been fixed.
41904195 The bug missed the setup of the next term in certain contexts, effective only when configured '!NPL_Impl_NPLA1_Enable_InlineDirect' and 'NPL_Impl_NPLA1_Enable_Thunk', since build 898.
4191- The bug would cause an assertion failure in 'A1::ReduceCombinedBranch' debug configurations due wrong term used.
4196+ The bug would cause an assertion failure in 'A1::ReduceCombinedBranch' debug configurations due to wrong term used.
41924197 Currently, this would affect functions 'AccL', 'AccR', 'FoldR1', 'Map1' and 'ForwardListFirst' in namespace 'A1::Forms'.
41934198 The fix is as the change in functions 'A1::RelayForEval' and 'A1::RelayForCall' since build 909.
41944199
diff -r c91b75c1e8bc -r 04895f90f831 doc/YSLib.txt
--- a/doc/YSLib.txt Sat Feb 06 16:04:05 2021 +0800
+++ b/doc/YSLib.txt Wed Feb 17 02:25:32 2021 +0800
@@ -1,5 +1,5 @@
11 /*
2- © 2009-2020 FrankHB.
2+ © 2009-2021 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 YSLib.txt
1212 \ingroup Documentation
1313 \brief YSLib 库及相关库的细节汇总和说明。
14-\version r3241
14+\version r3258
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since 早于 build 132
1717 \par 创建时间:
1818 2009-12-02 05:14:30 +0800
1919 \par 修改时间:
20- 2020-08-09 13:06 +0800
20+ 2021-02-06 22:24 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -72,7 +72,7 @@
7272
7373 @1.1.6 名称引用限制:
7474 除 Adaptor 中的 using 声明、 using 指令和命名空间别名外, YSLib 命名空间下不直接使用 YSLib 、std 和 ystdex 以外的根命名空间以及其中的名称;不直接使用 std::tr1 及其中的名称。
75-不使用除了 operator new 、operator new[] 、operator delete 、operator delete[] 和 main 以外的全局命名空间中的名称。
75+不使用除 operator new 、operator new[] 、operator delete 、operator delete[] 和 main 外的全局命名空间中的名称。
7676
7777 @1.1.7 附加名称限制:
7878 不在 Adaptor 和 Helper 等确定可以使用平台相关的代码以外区域使用环境、编译器和版本判断宏。
@@ -81,7 +81,7 @@
8181 本节描述 YSLib 和外部依赖项之间以及 YSLib 内部的头文件包含关联。
8282
8383 @1.2.1 引入自 C 标准库的 C++ 标准库头依赖项:
84-不在本体的必要文件中显式包含,除了以下例外:
84+不在本体的必要文件中显式包含,除以下例外:
8585 Adaptor::YAdaptor 需要保证 <cstddef> 、<cstdint> 、<climits> 和 <cmath> 被包含;
8686
8787 @1.2.2 不在本体中显式包含,需要在 Adaptor::YAdaptor 包含或提供替代品的 C++ 标准库依赖项:
@@ -120,14 +120,14 @@
120120 实现源文件依赖同名头文件,应保证包含此头文件,但不重复包含此头文件已经包含的其它头文件。
121121 在 Core 中,以下模块对应的头文件依赖关系是确定的:
122122 YShellDefinition 依赖 Adaptor::YAdaptor 和 Adaptor::YReference ;
123-除了 YShellDefinition 外都直接或间接依赖 YShellDefinition;
124-YCoreUtilities 和 YGDIBase 依赖 YException ;
125-YObject 依赖 YCoreUtilities ;
126-YDevice 、YString 和 YMessage 依赖 YObject ;
123+除 YShellDefinition 外都直接或间接依赖 YShellDefinition;
124+YString 依赖 Adaptor::YTextBase ;
125+YException 和 YEvent 依赖 YFunc ;
126+YCoreUtilities 依赖 YException ;
127+YGDIBase 依赖 YCoreUtilities ;
127128 YGraphics 依赖 YGDIBase ;
128129 YDevice 依赖 YGraphics ;
129-YString 依赖 Adaptor::YTextBase ;
130-YEvent 依赖 YObject 和 YFunc ;
130+YMessage 依赖 YObject ;
131131 YMessageDefinition 依赖 YMessage ;
132132 YShell 依赖 YMessageDefinition ;
133133 YApplication 依赖 YShell 。
@@ -138,7 +138,7 @@
138138 YBrush 依赖 YBlit 、YResource 和 Core::YEvent ;
139139 在 UI 中,以下模块对应的头文件依赖关系是确定的:
140140 YComponent 依赖 Core::YGraphics 、Core::YFunc 、Core::YMessageDefinition ;
141-除了 YComponent 外都直接或间接依赖 YComponent;
141+除 YComponent 外都直接或间接依赖 YComponent;
142142 YStyle 依赖 Service::YDraw ;
143143 YWidgetEvent 依赖 Core::YEvent ;
144144 YWidget 依赖 YFocus 和 YWidgetView ;
@@ -166,7 +166,7 @@
166166 @2 YSLib 适配器(Adaptor) :
167167 位于 "/Adaptor" 。
168168 负责衔接和封装外部库,便于移植。
169-除了 C++ 标准库以外,其它外部库的名称需要在此声明。
169+除 C++ 标准库以外,其它外部库的名称需要在此声明。
170170 直接使用除 C++ 标准库、 POSIX / GNU C 兼容函数库、 YCLib 库之外的外部库原代码片段所在文件都从属于 Adaptor 。
171171 除非另行指定,仅保证必要文件[Documentation::YFramework @@2.1.1] 提供接口中的可重入性和线程安全性同本体([Documentation::YFramework @@2.1.5]) 。
172172
@@ -230,7 +230,7 @@
230230
231231 @3 核心构件:
232232 位于 "/Core" 。
233-除了核心定义 YShellDefinition 以外,主要包含以下几大部分:
233+除核心定义 YShellDefinition 外,主要包含以下模块:
234234 核心实用模块 YCoreUtilities ;
235235 平台无关的基础对象 YObject ;
236236 对象计数器 YCounter;
@@ -309,18 +309,16 @@
309309 @3.8.3 虚拟设备:
310310
311311 @3.8.3.1 桌面:
312-桌面是大小和对应输出屏幕相等的窗口(@5.1.4.4.3) ,默认实现为 UI::Desktop 类,除了 YShellDefinition 的前向声明,并非位于 Core 。
312+桌面是大小和对应输出屏幕相等的窗口(@5.1.4.4.3) ,默认实现为 UI::Desktop 类。
313+除了 YShellDefinition 的前向声明,并非位于 Core 。
313314
314315 @3.9 事件回调 YEvent :
315316 实现事件。
316317 事件处理器 GHEvent 支持目标的相等比较:若不支持 == 操作则以类型判定相等性。
317318 KeyEventArgs ,键盘输入事件参数类。
318319 以下用模板定义用于事件处理机制的接口和实现类:
319-事件处理器接口模板 GIHEvent ,提供两个参数的 operator() 抽象方法。
320320 事件处理器模板 GHEvent ,标准版 HEvent ;基于 Function 和 multimap 实现。
321321 事件模板 GEvent 为多播版本,实现为以优先级为键的 GHEvent 的关联容器。
322-事件包装类 GEventWrapper ,包装 GEvent 作为 GIHEvent 的实现。
323-事件映射表模板 GEventMap ,映射特定的枚举 ID 到 GEventWrapper 模板实例。
324322
325323 @3.9.1 YSLib 标准事件处理实现概述:
326324 仅实现同步事件。
Show on old repository browser