• R/O
  • SSH

YSLib: Commit

The YSLib project - main repository


Commit MetaInfo

Revisiondfccd642351f5dd6a8b5933a9811bd809bac8511 (tree)
Time2021-04-14 13:24:53
AuthorFrankHB <frankhb1989@gmai...>
CommiterFrankHB

Log Message

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

Change Summary

Incremental Difference

diff -r 37835df0ac3b -r dfccd642351f 3rdparty/FreeImage/Makefile.gnu
--- a/3rdparty/FreeImage/Makefile.gnu Fri Mar 26 22:43:02 2021 +0800
+++ b/3rdparty/FreeImage/Makefile.gnu Wed Apr 14 12:24:53 2021 +0800
@@ -9,6 +9,12 @@
99 INCDIR ?= $(DESTDIR)/usr/include
1010 INSTALLDIR ?= $(DESTDIR)/usr/lib
1111
12+FREEIMAGE_LIBRARY_TYPE ?= SHARED
13+STATIC_FLAGS := -DFREEIMAGE_LIB
14+SHARED_FLAGS := -DFREEIMAGE_EXPORTS
15+
16+LIB_TYPE_FLAGS := $($(FREEIMAGE_LIBRARY_TYPE)_FLAGS)
17+
1218 # Converts cr/lf to just lf
1319 DOS2UNIX := dos2unix
1420
@@ -29,7 +35,7 @@
2935 else
3036 C_LTO ?= -flto -ffat-lto-objects
3137 endif
32-C_CXXFLAGS ?= -O3 $(C_LTO) -fPIC -pipe -Wno-attributes -fexceptions $(C_CXXFLAGS_GC)
38+C_CXXFLAGS ?= -O3 $(C_LTO) -fPIC -pipe -Wno-attributes -fexceptions $(C_CXXFLAGS_GC) $(LIB_TYPE_FLAGS)
3339 CFLAGS ?= $(C_CXXFLAGS)
3440 # OpenJPEG
3541 CFLAGS += -DOPJ_STATIC
diff -r 37835df0ac3b -r dfccd642351f 3rdparty/FreeImage/Readme.en-US.md
--- a/3rdparty/FreeImage/Readme.en-US.md Fri Mar 26 22:43:02 2021 +0800
+++ b/3rdparty/FreeImage/Readme.en-US.md Wed Apr 14 12:24:53 2021 +0800
@@ -286,10 +286,15 @@
286286
287287 The modified file `Makefile.mingw` should have been copied to the source directory and overwritten the original one.
288288
289-Run `mingw32-make -R FREEIMAGE_LIBRARY_TYPE=STATIC -f Makefile.mingw` (optionally with `-j` to build concurrently) to build static library for MinGW32.
289+Run `mingw32-make -R FREEIMAGE_LIBRARY_TYPE=STATIC -f Makefile.mingw libFreeImage.a` (optionally with `-j` to build concurrently) to build static library for MinGW32.
290290
291291 Run `mingw32-make -R -f Makefile.mingw clean` to delete all build files. Note the official `clean.bat` is not enough.
292292
293+Note that although omission of `libFreeImage.a` is allowed, it is not recommended because:
294+
295+* The `FREEIMAGE_LIBRARY_TYPE=STATIC` does not respect of the symbol visibility attributes. This makes the symbols not usable from the shared library, esp. not usable in a Win32 DLL.
296+* Only the static library is used by YFramework, so this is normally uncessary.
297+
293298 ## MinGW64
294299
295300 The enviornment is similar to MinGW32 with the proper x86-64 toolchain, except the setting of following environment variables:
@@ -304,11 +309,13 @@
304309
305310 NASM is required for compiling libjpeg-turbo SIMD source files.
306311
307-Run `make -R -f Makefile.gnu libfreeimage.a` (optionally with `-j` to build concurrently) to build static library.
312+Run `make -R FREEIMAGE_LIBRARY_TYPE=STATIC -f Makefile.gnu libfreeimage.a` (optionally with `-j` to build concurrently) to build static library.
308313
309314 Run `make -R -f Makefile.gnu clean` to delete all build files.
310315
311-For hosted Linux environment, `-f Makefile.gnu` can be omitted. Also `libfreeimage.a` can be omitted to build both static and shared library, although only the static library is used by YFramework.
316+For hosted Linux environment, `-f Makefile.gnu` can be omitted.
317+
318+Omission of `libfreeimage.a` in the building command line is not recommended for the similar reasons as in MinGW32.
312319
313320 If only the static library is built, the target `dist` is not run, so the library file is at the buidling directory but not `./Dist`.
314321
diff -r 37835df0ac3b -r dfccd642351f Tools/Scripts/SHBuild-YSLib-common.txt
--- a/Tools/Scripts/SHBuild-YSLib-common.txt Fri Mar 26 22:43:02 2021 +0800
+++ b/Tools/Scripts/SHBuild-YSLib-common.txt Wed Apr 14 12:24:53 2021 +0800
@@ -110,7 +110,7 @@
110110 (
111111 $letrec ((sym string->symbol name) (denv () get-current-environment))
112112 $unless (eval (list $binds1? emap sym) denv)
113- eval (list $set! emap sym (env-get name)) denv;
113+ (eval (list $set! emap sym (env-get name)) denv);
114114 log-set name val;
115115 env-set name val
116116 ),
diff -r 37835df0ac3b -r dfccd642351f YFramework/include/NPL/NPLA1Forms.h
--- a/YFramework/include/NPL/NPLA1Forms.h Fri Mar 26 22:43:02 2021 +0800
+++ b/YFramework/include/NPL/NPLA1Forms.h Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1Forms.h
1212 \ingroup NPL
1313 \brief NPLA1 语法形式。
14-\version r7923
14+\version r7933
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 882
1717 \par 创建时间:
1818 2020-02-15 11:19:21 +0800
1919 \par 修改时间:
20- 2021-03-12 18:01 +0800
20+ 2021-04-08 18:13 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -1492,19 +1492,6 @@
14921492 //! \since build 914
14931493 //@{
14941494 /*!
1495-\brief 以指定应用子在指定列表中选取并合并内容为新的列表。
1496-
1497-对参数列表 <pre>(&l &extr)</pre> ,结果同求值:
1498-<pre>accr l null? () ($lambda% (&l) forward-first% extr (expire l))
1499- rest% cons% </pre>
1500-
1501-参考调用文法:
1502-<pre>list-extract% \<list> \<applicative></pre>
1503-*/
1504-YF_API ReductionStatus
1505-ListExtract(TermNode&, ContextNode&);
1506-
1507-/*!
15081495 \brief 以 First 在指定列表中选取并合并内容为新的列表。
15091496 \sa First
15101497
diff -r 37835df0ac3b -r dfccd642351f YFramework/include/NPL/SContext.h
--- a/YFramework/include/NPL/SContext.h Fri Mar 26 22:43:02 2021 +0800
+++ b/YFramework/include/NPL/SContext.h Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file SContext.h
1212 \ingroup NPL
1313 \brief S 表达式上下文。
14-\version r3968
14+\version r3996
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 304
1717 \par 创建时间:
1818 2012-08-03 19:55:41 +0800
1919 \par 修改时间:
20- 2021-03-19 23:15 +0800
20+ 2021-03-31 07:04 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -177,6 +177,7 @@
177177
178178 /*!
179179 \brief 项节点:存储语法分析结果的值类型节点。
180+\waning 非虚析构。
180181 \since build 852
181182
182183 类似 ValueNode 的节点类型,但没有名称数据成员、按键比较和按键访问,
@@ -268,9 +269,11 @@
268269 : container(std::move(con), a), Value(yforward(args)...)
269270 {}
270271 //@}
272+ //! \warning 非嵌套调用安全。
271273 TermNode(const ValueNode& nd, allocator_type a)
272274 : container(ConCons(nd.GetContainer(), a)), Value(nd.Value)
273275 {}
276+ //! \warning 非嵌套调用安全。
274277 TermNode(ValueNode&& nd, allocator_type a)
275278 : container(ConCons(std::move(nd.GetContainerRef()), a)),
276279 Value(std::move(nd.Value))
@@ -291,10 +294,12 @@
291294 std::initializer_list<TermNode> il, _tParams&&... args)
292295 : TermNode(std::allocator_arg, a, Container(il, a), yforward(args)...)
293296 {}
297+ //! \warning 非嵌套调用安全。
294298 explicit
295299 TermNode(const ValueNode& nd)
296300 : container(ConCons(nd.GetContainer())), Value(nd.Value)
297301 {}
302+ //! \warning 非嵌套调用安全。
298303 explicit
299304 TermNode(ValueNode&& nd)
300305 : container(ConCons(std::move(nd.GetContainer()))),
@@ -327,6 +332,22 @@
327332 \warning 违反前置条件的转移可能引起循环引用。
328333 */
329334 DefDeMoveAssignment(TermNode)
335+ /*
336+ \brief 析构:类定义外默认实现。
337+ \note 支持移除任意子节点时的嵌套调用安全。
338+ \since build 916
339+ */
340+ ~TermNode()
341+ {
342+ // NOTE: Preprocess the node to prevent any deep nested node constructed
343+ // in the object language overflow in C++ calls, which violates the
344+ // nested call safety guarantee.
345+ // XXX: Assume the %Value has no such deep nested nodes as it is not
346+ // constructible in the object language. Note the %Clear call is
347+ // inefficient if the underlying destructor implementation of
348+ // %any has branch. Keep it as-is at current.
349+ Clear();
350+ }
330351
331352 //! \since build 853
332353 YB_PURE DefBoolNeg(YB_PURE explicit, bool(Value) || !empty())
@@ -378,10 +399,12 @@
378399
379400 //! \note 不访问 Tags 。
380401 PDefH(void, Clear, ) ynothrow
402+ // XXX: The order can be siginificant.
381403 ImplExpr(Value.Clear(), ClearContainer())
382404
383- PDefH(void, ClearContainer, ) ynothrow
384- ImplExpr(container.clear())
405+ //! \note 支持移除任意子节点时的嵌套调用安全。
406+ void
407+ ClearContainer() ynothrow;
385408
386409 /*!
387410 \note 允许被参数中被复制的对象直接或间接地被目标引用。
@@ -399,6 +422,8 @@
399422 //@}
400423
401424 private:
425+ //! \warning 非嵌套调用安全。
426+ //@{
402427 static TermNode::Container
403428 ConCons(const ValueNode::Container&);
404429 static TermNode::Container
@@ -407,6 +432,7 @@
407432 ConCons(const ValueNode::Container&, allocator_type);
408433 static TermNode::Container
409434 ConCons(ValueNode::Container&&, allocator_type);
435+ //@}
410436
411437 public:
412438 template<class _tCon, typename _fCallable,
diff -r 37835df0ac3b -r dfccd642351f YFramework/source/NPL/Dependency.cpp
--- a/YFramework/source/NPL/Dependency.cpp Fri Mar 26 22:43:02 2021 +0800
+++ b/YFramework/source/NPL/Dependency.cpp Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file Dependency.cpp
1212 \ingroup NPL
1313 \brief 依赖管理。
14-\version r4599
14+\version r4622
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 623
1717 \par 创建时间:
1818 2015-08-09 22:14:45 +0800
1919 \par 修改时间:
20- 2021-03-26 12:10 +0800
20+ 2021-04-10 17:59 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -760,7 +760,6 @@
760760 });
761761 RegisterStrict(renv, "list-concat", ListConcat);
762762 RegisterStrict(renv, "append", Append);
763- RegisterStrict(renv, "list-extract%", ListExtract);
764763 RegisterStrict(renv, "list-extract-first", ListExtractFirst);
765764 RegisterStrict(renv, "list-extract-rest%", ListExtractRestFwd);
766765 RegisterForm(renv, "$let", Let);
@@ -992,27 +991,26 @@
992991 (apply accr (list% (apply tail (list% l) d)
993992 pred? (forward! base) head tail sum) d)) d);
994993 $defw%! foldr1 (&kons &knil &l) d
995- apply accr
996- (list% (forward! l) null? (forward! knil) first% rest% kons) d;
994+ apply accr (list% (($lambda ((.@xs)) xs) l) null? (forward! knil)
995+ ($if ($lvalue-identifier? l) ($lambda (&l) first% l)
996+ ($lambda (&l) expire (first% l))) rest% kons) d;
997997 $defw%! map1 (&appv &l) d
998- foldr1 ($lambda (&x &xs) cons%
999- (apply appv (list% (forward! x)) d) (move! xs)) () (forward! l);
998+ foldr1 ($lambda (%x &xs) cons%
999+ (apply appv (list% ($move-resolved! x)) d) (move! xs)) ()
1000+ (forward! l);
10001001 $defl! first-null? (&l) null? (first l);
10011002 $defl%! rulist (&l)
10021003 $if ($lvalue-identifier? l)
10031004 (accr (($lambda ((.@xs)) xs) l) null? ()
10041005 ($lambda% (%l) $sequence ($def! %x idv (first@ l))
1005- (($if (uncollapsed? x) idv expire) x)) rest%
1006- ($lambda (&x &xs)
1006+ (($if (uncollapsed? x) idv expire) (expire x))) rest%
1007+ ($lambda (%x &xs)
10071008 (cons% ($resolve-identifier x) (move! xs))))
1008- (rlist (forward! l));
1009+ (idv (forward! l));
10091010 $defl! list-concat (&x &y) foldr1 cons% (forward! y) (forward! x);
10101011 $defl! append (.&ls) foldr1 list-concat () (move! ls);
1011- $defw%! list-extract% (&l &extr) d
1012- accr l null? () ($lambda% (&l)
1013- apply forward-first% (list% extr (expire l)) d) rest% cons%;
1014- $defl%! list-extract-first (&l) list-extract% l first;
1015- $defl%! list-extract-rest% (&l) list-extract% l rest%;
1012+ $defl%! list-extract-first (&l) map1 first l;
1013+ $defl%! list-extract-rest% (&l) map1 rest% l;
10161014 $defv! $defw! (&f &formals &ef .&body) d
10171015 eval (list $set! d f wrap (list* $vau formals ef (move! body))) d;
10181016 $defw! derive-current-environment (.&envs) d
@@ -1147,14 +1145,13 @@
11471145 )NPL");
11481146 #if NPL_Impl_NPLA1_Native_Forms
11491147 context.Perform(R"NPL(
1150- $def! ($let* $let*% $letrec $letrec%)
1151- ($lambda (&ce)
1148+ $def! ($let* $let*% $letrec $letrec%) ($lambda (&ce)
11521149 (
11531150 $def! mods () ($lambda/e ce ()
11541151 (
11551152 $defv%! $lqual (&ls) d
1156- $if (eval (list $lvalue-identifier? ls) d)
1157- (eval% (list as-const ls) d) (rulist (eval% ls d));
1153+ ($if (eval (list $lvalue-identifier? ls) d) as-const rulist)
1154+ (eval% ls d);
11581155 $defv%! $lqual* (&x) d
11591156 ($if (eval (list $lvalue-identifier? x) d) as-const expire)
11601157 (eval% x d);
@@ -1163,7 +1160,7 @@
11631160 (list $let (list (first% ($lqual* bindings)))
11641161 (list* $let* (rest% ($lqual* bindings)) (move! body)));
11651162 $defl%! mk-letrec ($let &bindings &body)
1166- list $let% () $sequence (list $def! (list-extract-first
1163+ list $let () $sequence (list $def! (list-extract-first
11671164 bindings) (list* () list (list-extract-rest% bindings)))
11681165 (move! body);
11691166 () lock-current-environment
@@ -1187,8 +1184,8 @@
11871184 $def! mods () ($lambda/e ce ()
11881185 (
11891186 $defv%! $lqual (&ls) d
1190- $if (eval (list $lvalue-identifier? ls) d)
1191- (eval% (list as-const ls) d) (rulist (eval% ls d));
1187+ ($if (eval (list $lvalue-identifier? ls) d) as-const rulist)
1188+ (eval% ls d);
11921189 $defv%! $lqual* (&x) d
11931190 ($if (eval (list $lvalue-identifier? x) d) as-const expire)
11941191 (eval% x d);
@@ -1203,7 +1200,7 @@
12031200 (list $let (list (first% ($lqual* bindings)))
12041201 (list* $let* (rest% ($lqual* bindings)) (move! body)));
12051202 $defl%! mk-letrec ($let &bindings &body)
1206- list $let% () $sequence (list $def! (list-extract-first
1203+ list $let () $sequence (list $def! (list-extract-first
12071204 bindings) (list* () list (list-extract-rest% bindings)))
12081205 (move! body);
12091206 () lock-current-environment
diff -r 37835df0ac3b -r dfccd642351f YFramework/source/NPL/NPLA1.cpp
--- a/YFramework/source/NPL/NPLA1.cpp Fri Mar 26 22:43:02 2021 +0800
+++ b/YFramework/source/NPL/NPLA1.cpp Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1.cpp
1212 \ingroup NPL
1313 \brief NPLA1 公共接口。
14-\version r20493
14+\version r20500
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 473
1717 \par 创建时间:
1818 2014-02-02 18:02:47 +0800
1919 \par 修改时间:
20- 2021-03-26 02:47 +0800
20+ 2021-04-10 08:25 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -331,7 +331,7 @@
331331 else
332332 con.emplace_back(o.GetContainer(), ValueObject(
333333 std::allocator_arg, con.get_allocator(), in_place_type<
334- TermReference>, BindReferenceTags(ref), ref));
334+ TermReference>, ref.GetTags(), ref));
335335 }
336336
337337
@@ -500,11 +500,11 @@
500500 : Referenced(r_env)
501501 {}
502502
503- //! \since build 858
503+ //! \since build 916
504504 template<typename _fCopy, typename _fMove>
505505 void
506- operator()(char sigil, TermTags o_tags, TermNode& o, _fCopy cp, _fMove mv)
507- const
506+ operator()(char sigil, bool ref_temp, TermTags o_tags, TermNode& o,
507+ _fCopy cp, _fMove mv) const
508508 {
509509 // NOTE: This shall be %true if the operand is stored in a term tree to
510510 // be reduced (and eventually cleanup). See also
@@ -525,7 +525,7 @@
525525 {
526526 if(sigil != char())
527527 {
528- const auto ref_tags(PropagateTo(sigil == '&'
528+ const auto ref_tags(PropagateTo(ref_temp
529529 ? BindReferenceTags(*p) : p->GetTags(), o_tags));
530530
531531 // XXX: Allocators are not used here on %TermReference for
@@ -1666,7 +1666,7 @@
16661666 for(; first != last; ++first)
16671667 // TODO: Blocked. Use C++17 sequence container return
16681668 // value.
1669- BindParameterObject{r_env}(sigil, o_tags,
1669+ BindParameterObject{r_env}(sigil, {}, o_tags,
16701670 NPL::Deref(first), [&](const TermNode& tm){
16711671 con.emplace_back(tm.GetContainer(), tm.Value);
16721672 CopyTermTags(con.back(), tm);
@@ -1704,7 +1704,7 @@
17041704 const char sigil(check_sigil(id));
17051705
17061706 if(!id.empty())
1707- BindParameterObject{r_env}(sigil, o_tags, b,
1707+ BindParameterObject{r_env}(sigil, sigil == '&', o_tags, b,
17081708 [&](const TermNode& tm){
17091709 CopyTermTags(env.Bind(id, tm), tm);
17101710 }, [&](TermNode::Container&& c, ValueObject&& vo)
diff -r 37835df0ac3b -r dfccd642351f YFramework/source/NPL/NPLA1Forms.cpp
--- a/YFramework/source/NPL/NPLA1Forms.cpp Fri Mar 26 22:43:02 2021 +0800
+++ b/YFramework/source/NPL/NPLA1Forms.cpp Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1Forms.cpp
1212 \ingroup NPL
1313 \brief NPLA1 语法形式。
14-\version r21958
14+\version r22371
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 882
1717 \par 创建时间:
1818 2014-02-15 11:19:51 +0800
1919 \par 修改时间:
20- 2021-03-26 03:34 +0800
20+ 2021-04-14 12:01 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -964,7 +964,7 @@
964964 MoveValueListSplice(TermNode& term, TermNode& nd)
965965 {
966966 // XXX: No cyclic reference check.
967- term.GetContainerRef().splice(term.end(), std::move(nd.GetContainerRef()));
967+ term.GetContainerRef().splice(term.end(), nd.GetContainerRef());
968968 }
969969
970970 //! \since build 874
@@ -1030,7 +1030,8 @@
10301030 // %A1::NameTypedReducerHandler.
10311031 enum ConsTag
10321032 {
1033- Map1Appv,
1033+ //! \since build 916
1034+ Map1Cons,
10341035 ListConcatCons,
10351036 ListExtractCons
10361037 };
@@ -1441,7 +1442,7 @@
14411442 const auto last(nd.end());
14421443
14431444 ++first;
1444- if(!p_ref || p_ref->IsMovable() || p_ref->IsTemporary())
1445+ if(!p_ref || p_ref->IsMovable())
14451446 {
14461447 lift(nd);
14471448 con.splice(con.end(), nd.GetContainerRef(), first, last);
@@ -2151,7 +2152,7 @@
21512152 // XXX: Capture of %d by copy is a slightly more efficient.
21522153 A1::NameTypedReducerHandler([&, d]() YB_FLATTEN{
21532154 l = std::move(n2term);
2154- return A1::ReduceCurrentNext(
2155+ return A1::ReduceCurrentNextThunked(
21552156 *term.emplace(ystdex::exchange(term.GetContainerRef(), [&]{
21562157 TermNode::Container tcon(term.get_allocator());
21572158
@@ -2166,8 +2167,22 @@
21662167 }, term, ctx);
21672168 }
21682169
2170+//! \since build 916
2171+struct TermRange final
2172+{
2173+ TNIter First, Last;
2174+ TermTags Tags = TermTags::Unqualified;
2175+
2176+ TermRange(TermNode& nd, TermTags tags = TermTags::Unqualified) ynothrow
2177+ : First(nd.begin()), Last(nd.end()), Tags(tags)
2178+ {}
2179+
2180+ YB_ATTR_nodiscard YB_PURE PDefH(bool, empty, ) const ynothrow
2181+ ImplRet(First == Last)
2182+};
2183+
21692184 /*!
2170-\brief 准备递归调用使用的列表对象:绑定对象为列表临时对象。
2185+\brief 准备递归调用使用的列表对象:绑定对象为列表临时对象范围。
21712186 \since build 913
21722187 */
21732188 YB_FLATTEN void
@@ -2175,14 +2190,29 @@
21752190 {
21762191 // NOTE: The 1st call can be applied to reference to list, but the nested
21772192 // application is only for non-list objects due to the rest list is extract
2178- // as if a call of 'rest%'.
2193+ // as if a call of 'rest%' to the references of the list subobjects.
21792194 NPL::ResolveTerm(
21802195 [&](TermNode& nd, ResolvedTermReferencePtr p_ref) YB_FLATTEN{
21812196 // NOTE: This is only needed for the outermost call.
21822197 if(IsList(nd))
21832198 {
21842199 if(p_ref)
2185- LiftOtherOrCopy(term, nd, p_ref->IsMovable());
2200+ {
2201+ // NOTE: Not using %LiftOtherOrCopy to allow delaying the copy.
2202+ if(p_ref->IsMovable())
2203+ {
2204+ LiftOther(term, nd);
2205+ term.Value = TermRange(term);
2206+ }
2207+ else
2208+ // XXX: Term tags are currently not respected in prvalues.
2209+ // This is used to indicate the list is an lvalue which
2210+ // shall be copied on the element accesses later.
2211+ yunseq(term.Tags |= TermTags::Nonmodifying,
2212+ term.Value = TermRange(nd, p_ref->GetTags()));
2213+ }
2214+ else
2215+ term.Value = TermRange(term);
21862216 }
21872217 else
21882218 // NOTE: Always treat the list as an lvalue as in the derivation.
@@ -2204,36 +2234,54 @@
22042234 // %term and the 1st subterm of %tm is not the same.
22052235 // XXX: Term tags are currently not respected in prvalues.
22062236 LiftOther(term, AccessFirstSubterm(tm));
2207- tm.GetContainerRef().pop_front();
2237+ RemoveHead(tm);
2238+}
2239+
2240+//! \since build 916
2241+YB_FLATTEN void
2242+ExtractRangeFirstOrCopy(TermNode& term, TermRange& tr, bool move)
2243+{
2244+ YAssert(!tr.empty(), "Invalid term found.");
2245+ if(move)
2246+ LiftOther(term, NPL::Deref(tr.First));
2247+ // XXX: As %LiftCopyPropagate.
2248+ else
2249+ {
2250+ term.CopyContent(NPL::Deref(tr.First));
2251+ if(const auto p = NPL::TryAccessLeaf<TermReference>(term))
2252+ p->SetTags(PropagateTo(p->GetTags(), tr.Tags));
2253+ }
2254+ ++tr.First;
22082255 }
22092256
22102257 YB_FLATTEN ReductionStatus
22112258 DoFoldR1(TermNode& term, ContextNode& ctx)
22122259 {
2213- // NOTE: Subterms are %nterm, the underlying combiner of 'kons', 'knil',
2214- // temporary 'l'.
2215- YAssert(term.size() == 4, "Invalid recursive call found.");
2216-
2217- auto& tm(term.GetContainerRef().back());
2260+ // NOTE: Subterms are the underlying combiner of 'kons', 'knil',
2261+ // the term range of 'l' with optional temporary list.
2262+ YAssert(term.size() == 3, "Invalid recursive call found.");
2263+
2264+ auto& con(term.GetContainerRef());
2265+ auto& tm(con.back());
2266+
2267+ // XXX: This should have been guaranteed by the call to %PrepareFoldRList.
2268+ YAssert(tm.Value.type() == ystdex::type_id<TermRange>(),
2269+ "Invalid non-list term found.");
2270+
2271+ auto& tr(tm.Value.GetObject<TermRange>());
22182272 auto i(term.begin());
22192273
2220- ++i;
2221- // XXX: This should have been guaranteed by the call of %PrepareFoldRList.
2222- YAssert(IsList(tm), "Invalid non-list term found.");
2223- if(IsBranch(tm))
2274+ if(!tr.empty())
22242275 {
2225- auto& nterm(term.GetContainerRef().front());
2226-
2227- ExtractFirst(nterm, tm);
2228- return A1::ReduceCurrentNext(
2229- *term.emplace(ystdex::exchange(term.GetContainerRef(), [&]{
2276+ return A1::ReduceCurrentNextThunked(
2277+ *term.emplace(ystdex::exchange(con, [&]{
22302278 TermNode::Container tcon(term.get_allocator());
22312279
22322280 tcon.push_back(*i);
2233- tcon.push_back(std::move(nterm));
2281+ ExtractRangeFirstOrCopy(tcon.emplace_back(), tr,
2282+ !bool(tm.Tags & TermTags::Nonmodifying));
22342283 return tcon;
2235- }())), ctx, DoFoldR1,
2236- A1::NameTypedReducerHandler(
2284+ }())), ctx, DoFoldR1, A1::NameTypedReducerHandler(
22372285 // TODO: Blocked. Use C++14 lambda initializers to simplify the
22382286 // implementation.
22392287 std::bind([&](shared_ptr<Environment>& d) YB_FLATTEN{
@@ -2250,8 +2298,8 @@
22502298 YB_FLATTEN ReductionStatus
22512299 DoBranchListOrNull(TermNode& term, TermNode& tm, _func f)
22522300 {
2253- // XXX: This should have been guaranteed by the call of %PrepareFoldRList
2254- // or some other preconditions in the caller site.
2301+ // XXX: This should have been guaranteed by preconditions in the caller
2302+ // site.
22552303 YAssert(IsList(tm), "Invalid non-list term found.");
22562304 if(IsBranch(tm))
22572305 return f(term.GetContainerRef().front());
@@ -2259,47 +2307,59 @@
22592307 return ReductionStatus::Regular;
22602308 }
22612309
2310+//! \since build 916
2311+template<typename _func>
2312+YB_FLATTEN ReductionStatus
2313+DoBranchListRangeOrNull(TermNode& term, TermNode& tm, _func f)
2314+{
2315+ // XXX: This should have been guaranteed by the call to %PrepareFoldRList.
2316+ YAssert(tm.Value.type() == ystdex::type_id<TermRange>(),
2317+ "Invalid non-list term found.");
2318+
2319+ auto& tr(tm.Value.GetObject<TermRange>());
2320+
2321+ if(!tr.empty())
2322+ return f(tr, !bool(tm.Tags & TermTags::Nonmodifying));
2323+ term.Clear();
2324+ return ReductionStatus::Regular;
2325+}
2326+
22622327 YB_FLATTEN ReductionStatus
22632328 DoMap1(TermNode& term, ContextNode& ctx)
22642329 {
2265- // NOTE: Subterms are %nterm, the underlying combiner of 'appv',
2266- // temporary 'l'.
2267- YAssert(term.size() == 3, "Invalid recursive call found.");
2268-
2269- auto& tm(term.GetContainerRef().back());
2270-
2271- return DoBranchListOrNull(term, tm, [&](TermNode& nterm) YB_FLATTEN{
2272- auto i(term.begin());
2273-
2274- ExtractFirst(nterm, tm);
2275- return A1::ReduceCurrentNext(
2276- *term.emplace(ystdex::exchange(term.GetContainerRef(), [&]{
2330+ // NOTE: Subterms are the underlying combiner of 'appv', the term range of
2331+ // 'l' with optional temporary list.
2332+ YAssert(term.size() == 2, "Invalid recursive call found.");
2333+
2334+ auto& con(term.GetContainerRef());
2335+
2336+ return DoBranchListRangeOrNull(term, con.back(),
2337+ [&](TermRange& tr, bool move) YB_FLATTEN{
2338+ return A1::ReduceCurrentNextThunked(
2339+ *term.emplace(ystdex::exchange(con, [&]{
22772340 TermNode::Container tcon(term.get_allocator());
22782341 auto& subtcon(tcon.emplace_back().GetContainerRef());
22792342
2280- subtcon.push_back(*++i);
2281- subtcon.push_back(std::move(nterm));
2343+ subtcon.push_back(con.front());
2344+ ExtractRangeFirstOrCopy(subtcon.emplace_back(), tr, move);
22822345 return tcon;
2283- }())), ctx, DoMap1,
2284- A1::NameTypedReducerHandler(
2346+ }())), ctx, DoMap1, A1::NameTypedReducerHandler(
22852347 // TODO: Blocked. Use C++14 lambda initializers to simplify the
22862348 // implementation.
22872349 std::bind([&](shared_ptr<Environment>& d) YB_FLATTEN{
22882350 return Combine<NonTailCall>::ReduceCallSubsequent(*term.begin(),
22892351 ctx, std::move(d), A1::NameTypedReducerHandler(
2290- ConsMoveSubNextRV<Map1Appv>{term}, "eval-map1-cons"));
2352+ ConsMoveSubNextRV<Map1Cons>{term}, "eval-map1-cons"));
22912353 }, ctx.ShareRecord()), "eval-map1-appv"));
22922354 });
22932355 }
22942356
22952357 // NOTE: This is needed for the last operation called recursively. Also
22962358 // unwrap here to avoid redundant unwrapping operations.
2297-//! \since build 914
2359+//! \since build 916
22982360 YB_FLATTEN void
2299-PrepareTailOp(TermNode& term, ContextNode& ctx, TermNode& rterm, ptrdiff_t n)
2361+PrepareTailOp(TermNode& term, ContextNode& ctx, TermNode& op)
23002362 {
2301- auto& op(*std::next(rterm.begin(), n));
2302-
23032363 op = EvaluateBoundLValueUnwrapped(*term.emplace(std::move(op)),
23042364 ctx.GetRecordPtr());
23052365 }
@@ -2330,6 +2390,7 @@
23302390 {
23312391 auto& con(term.GetContainerRef());
23322392
2393+ con.pop_front();
23332394 // NOTE: Bind the last argument as the local reference to list temporary
23342395 // object.
23352396 PrepareFoldRList(con.back());
@@ -2338,31 +2399,34 @@
23382399 TermNode::Container(term.get_allocator()))));
23392400
23402401 // NOTE: Save 'kons' (for %FoldR1) or 'appv' (for %Map1).
2341- PrepareTailOp(term, ctx, rterm, 1);
2402+ PrepareTailOp(term, ctx, *rterm.begin());
23422403 return DoRLiftSum(term, ctx, rterm, f);
23432404 }
23442405
23452406 YB_FLATTEN ReductionStatus
23462407 DoListConcat(TermNode& term, ContextNode& ctx)
23472408 {
2348- // NOTE: Subterms are %nterm, temporary 'x', 'y'.
2349- YAssert(term.size() == 3, "Invalid recursive call found.");
2409+ // NOTE: Subterms are the term range of 'x' with optional temporary list,
2410+ // 'y'.
2411+ YAssert(term.size() == 2, "Invalid recursive call found.");
23502412
23512413 auto i(term.begin());
2352- auto& tm(*++i);
2353-
2354- // XXX: This should have been guaranteed by the call of %PrepareFoldRList.
2355- YAssert(IsList(tm), "Invalid non-list term found.");
2356- if(IsBranch(tm))
2414+ auto& tm(*i);
2415+
2416+ // XXX: This should have been guaranteed by the call to %PrepareFoldRList.
2417+ YAssert(tm.Value.type() == ystdex::type_id<TermRange>(),
2418+ "Invalid non-list term found.");
2419+
2420+ auto& tr(tm.Value.GetObject<TermRange>());
2421+
2422+ if(!tr.empty())
23572423 {
2358- auto& nterm(term.GetContainerRef().front());
2359-
2360- ExtractFirst(nterm, tm);
2361- return A1::ReduceCurrentNext(
2424+ return A1::ReduceCurrentNextThunked(
23622425 *term.emplace(ystdex::exchange(term.GetContainerRef(), [&]{
23632426 TermNode::Container tcon(term.get_allocator());
2364-
2365- tcon.push_back(std::move(nterm));
2427+
2428+ ExtractRangeFirstOrCopy(tcon.emplace_back(), tr,
2429+ !bool(tm.Tags & TermTags::Nonmodifying));
23662430 return tcon;
23672431 }())), ctx, DoListConcat, A1::NameTypedReducerHandler(
23682432 ConsMoveSubNextRV<ListConcatCons>{term}, "eval-list-concat-cons"));
@@ -2374,22 +2438,22 @@
23742438 YB_FLATTEN ReductionStatus
23752439 DoAppend(TermNode& term, ContextNode& ctx)
23762440 {
2377- // NOTE: Subterms are %nterm, %ls.
2378- YAssert(term.size() == 2, "Invalid recursive call found.");
2379-
2380- auto& ls(term.GetContainerRef().back());
2381-
2382- return DoBranchListOrNull(term, ls, [&](TermNode& nterm) YB_FLATTEN{
2383- ExtractFirst(nterm, ls);
2384- // NOTE: Bind the first term as the local reference to list temporary
2385- // object.
2386- PrepareFoldRList(nterm);
2387- return A1::ReduceCurrentNext(
2388- *term.emplace(ystdex::exchange(term.GetContainerRef(), [&]{
2441+ // NOTE: The subterm is %ls.
2442+ YAssert(term.size() == 1, "Invalid recursive call found.");
2443+
2444+ auto& con(term.GetContainerRef());
2445+ auto& ls(con.back());
2446+
2447+ return DoBranchListOrNull(term, ls, [&](TermNode&) YB_FLATTEN{
2448+ return A1::ReduceCurrentNextThunked(
2449+ *term.emplace(ystdex::exchange(con, [&]{
23892450 TermNode::Container tcon(term.get_allocator());
2390-
2391- tcon.emplace_back();
2392- tcon.push_back(std::move(nterm));
2451+ auto& nterm(tcon.emplace_back());
2452+
2453+ ExtractFirst(nterm, ls);
2454+ // NOTE: Bind the first term as the local reference to list
2455+ // temporary object.
2456+ PrepareFoldRList(nterm);
23932457 return tcon;
23942458 }())), ctx, DoAppend, A1::NameTypedReducerHandler([&]() YB_FLATTEN{
23952459 return DoListConcat(term, ctx);
@@ -2398,105 +2462,101 @@
23982462 }
23992463 //@}
24002464
2465+//! \since build 916
2466+//@{
2467+void
2468+BindListExtractFirst_Ref(TermNode& nterm, TermReference& oref, TermTags tags)
2469+{
2470+ TermReference ref(BindReferenceTags(tags), oref);
2471+ auto& nd(ref.get());
2472+
2473+ if(IsBranchedList(nd))
2474+ RegularizeTerm(nterm,
2475+ ReduceToFirst(nterm, AccessFirstSubterm(nd), &ref));
2476+ else
2477+ ThrowInsufficientTermsError(nd, true);
2478+}
2479+void
2480+BindListExtractFirst_Val(TermNode& nterm, TermNode& o, TermTags tm_tags)
2481+{
2482+ auto& x(AccessFirstSubterm(o));
2483+
2484+ if(const auto p = NPL::TryAccessLeaf<const TermReference>(x))
2485+ {
2486+ if(!p->IsReferencedLValue())
2487+ {
2488+ LiftMovedOther(nterm, *p, p->IsMovable());
2489+ return;
2490+ }
2491+ }
2492+ // XXX: Term tags are currently not respected in prvalues.
2493+ LiftOtherOrCopy(nterm, x,
2494+ !bool((o.Tags | x.Tags | tm_tags) & TermTags::Nonmodifying));
2495+}
2496+
2497+void
2498+BindListExtractRestFwd_Ref(TermNode& nterm, TermReference& oref, TermTags tags)
2499+{
2500+ TermReference ref(tags, oref);
2501+ auto& nd(ref.get());
2502+
2503+ ReduceToRestOrVal(nterm, nd, &ref, [](TermNode&) ynothrow{},
2504+ [&](TermNode& dst, TermNode& tm, ResolvedTermReferencePtr){
2505+ LiftOtherOrCopy(dst, tm, ref.IsMovable());
2506+ });
2507+}
2508+void
2509+BindListExtractRestFwd_Val(TermNode& nterm, TermNode& o, TermTags tm_tags)
2510+{
2511+ TermNode::Container con(nterm.get_allocator());
2512+
2513+ auto first(o.begin());
2514+ const auto last(o.end());
2515+
2516+ ++first;
2517+ if(!bool((o.Tags | tm_tags) & TermTags::Nonmodifying))
2518+ con.splice(con.end(), o.GetContainerRef(), first, last);
2519+ else
2520+ for(; first != last; ++first)
2521+ con.emplace_back().CopyContent(*first);
2522+ con.swap(nterm.GetContainerRef());
2523+}
2524+//@}
2525+
24012526 //! \since build 914
24022527 //@{
2403-YB_FLATTEN TNIter
2404-PrepareListExtract(TermNode& term)
2405-{
2406- auto& con(term.GetContainerRef());
2407- auto i(con.begin());
2408-
2409- // NOTE: Bind the 1st argument as the local reference to list temporary
2410- // object.
2411- PrepareFoldRList(*++i);
2412- return i;
2413-}
2414-
2415-YB_FLATTEN ReductionStatus
2416-DoListExtract(TermNode& term, ContextNode& ctx)
2417-{
2418- // NOTE: Subterms are %nterm, temporary 'l', 'extr'.
2419- YAssert(term.size() == 3, "Invalid recursive call found.");
2420-
2421- auto i(term.begin());
2422- auto& tm(*++i);
2423-
2424- return DoBranchListOrNull(term, tm, [&](TermNode& nterm) YB_FLATTEN{
2425- const auto& d(ctx.GetRecordPtr());
2426-
2427- tm.Tags |= TermTags::Temporary;
2428- nterm.GetContainerRef() = [&]{
2429- TermNode::Container tcon(nterm.get_allocator());
2430- auto& o(AccessFirstSubterm(tm));
2431-
2432- tcon.push_back(EvaluateBoundLValueUnwrapped(*++i, d));
2433- // XXX: As %BindLocalReference in %ForwardFirst. Note that %tm is
2434- // supposed as if an operand in the local environment to be
2435- // accessed by an lvalue via local variable, rather than an rvalue
2436- // operand. Thus, a virtual %TermReference is always assumed and
2437- // %BindMoveLocalObject cannot be used here.
2438- tcon.emplace_back(o.GetContainer(), [&]() -> TermReference{
2439- if(const auto p = NPL::TryAccessLeaf<TermReference>(o))
2440- return TermReference(BindReferenceTags(*p), *p);
2441- return TermReference(GetLValueTagsOf(o.Tags
2442- | (tm.Tags & TermTags::Nonmodifying) | TermTags::Unique), o,
2443- d);
2444- }());
2445- return tcon;
2446- }();
2447- nterm.Value.Clear();
2448- return Combine<NonTailCall>::ReduceCallSubsequent(nterm, ctx, d,
2449- A1::NameTypedReducerHandler([&, d](){
2450- tm.GetContainerRef().pop_front();
2451- return A1::ReduceCurrentNext(
2452- *term.emplace(ystdex::exchange(term.GetContainerRef(), [&]{
2453- TermNode::Container tcon(term.get_allocator());
2454-
2455- tcon.push_back(std::move(nterm));
2456- return tcon;
2457- }())), ctx, DoListExtract,
2458- A1::NameTypedReducerHandler(ConsMoveSubNextRV<ListConcatCons>{
2459- term}, "eval-list-extract-cons"));
2460- }, "eval-list-extract-next"));
2461- });
2462-}
2463-
24642528 template<typename _func, typename _func2>
24652529 YB_FLATTEN ReductionStatus
24662530 DoListExtractFirstRest(TermNode& term, ContextNode& ctx, _func f, _func2 f2)
24672531 {
2468- // NOTE: Subterms are %nterm, temporary 'l'.
2469- YAssert(term.size() == 2, "Invalid recursive call found.");
2470-
2471- auto i(term.begin());
2472- auto& tm(*++i);
2473-
2474- return DoBranchListOrNull(term, tm, [&](TermNode& nterm) YB_FLATTEN{
2475- auto& o(AccessFirstSubterm(tm));
2476-
2477- nterm.Value.Clear();
2478- if(const auto p = NPL::TryAccessLeaf<TermReference>(o))
2479- {
2480- TermReference ref(BindReferenceTags(*p), *p);
2481- auto& nd(ref.get());
2482-
2483- f(nterm, ref, nd);
2484- }
2485- else if(IsBranchedList(o))
2486- f2(nterm, o, tm.Tags);
2487- else
2488- ThrowInsufficientTermsError(o, true);
2489- // XXX: This invalidates the irregular reference in %o (if any).
2490- tm.GetContainerRef().pop_front();
2491- return A1::ReduceCurrentNext(
2492- *term.emplace(ystdex::exchange(term.GetContainerRef(), [&]{
2532+ // NOTE: The subterm is the term range of 'l'.
2533+ YAssert(term.size() == 1, "Invalid recursive call found.");
2534+
2535+ auto& con(term.GetContainerRef());
2536+
2537+ return DoBranchListRangeOrNull(term, con.back(),
2538+ [&](TermRange& tr, bool) YB_FLATTEN{
2539+ return A1::ReduceCurrentNextThunked(
2540+ *term.emplace(ystdex::exchange(con, [&]{
24932541 TermNode::Container tcon(term.get_allocator());
2494-
2495- tcon.push_back(std::move(nterm));
2542+ auto& nterm(tcon.emplace_back());
2543+ auto& o(NPL::Deref(tr.First));
2544+
2545+ if(const auto p = NPL::TryAccessLeaf<TermReference>(o))
2546+ // NOTE: The tags of the term range shall be prepared in the
2547+ // call to %PrepareFoldRList. The nonmodifying tag indicates
2548+ // the reference is not movable.
2549+ f(nterm, *p,
2550+ GetLValueTagsOf(PropagateTo(p->GetTags(), tr.Tags)));
2551+ else if(IsBranchedList(o))
2552+ f2(nterm, o, tr.Tags);
2553+ else
2554+ ThrowInsufficientTermsError(o, true);
2555+ ++tr.First;
24962556 return tcon;
24972557 }())), ctx, [=](TermNode& t, ContextNode& c){
24982558 return DoListExtractFirstRest(t, c, f, f2);
2499- }, A1::NameTypedReducerHandler(ConsMoveSubNextRV<ListConcatCons>{term},
2559+ }, A1::NameTypedReducerHandler(ConsMoveSubNextRV<ListExtractCons>{term},
25002560 "eval-list-extract-cons"));
25012561 });
25022562 }
@@ -2504,77 +2564,58 @@
25042564 YB_FLATTEN ReductionStatus
25052565 DoListExtractFirst(TermNode& term, ContextNode& ctx)
25062566 {
2507- return DoListExtractFirstRest(term, ctx,
2508- [](TermNode& nterm, TermReference& ref, TermNode& nd){
2509- if(IsBranchedList(nd))
2510- RegularizeTerm(nterm,
2511- ReduceToFirst(nterm, AccessFirstSubterm(nd), &ref));
2512- else
2513- ThrowInsufficientTermsError(nd, true);
2514- }, [](TermNode& nterm, TermNode& o, TermTags){
2515- auto& x(AccessFirstSubterm(o));
2516-
2517- if(const auto p = NPL::TryAccessLeaf<const TermReference>(x))
2518- {
2519- if(!p->IsReferencedLValue())
2520- {
2521- LiftMovedOther(nterm, *p, p->IsMovable());
2522- return;
2523- }
2524- }
2525- // XXX: Term tags are currently not respected in prvalues.
2526- LiftOtherOrCopy(nterm, x,
2527- !bool((o.Tags | x.Tags) & TermTags::Nonmodifying));
2528- });
2567+ return DoListExtractFirstRest(term, ctx, BindListExtractFirst_Ref,
2568+ BindListExtractFirst_Val);
25292569 }
25302570
25312571 YB_FLATTEN ReductionStatus
25322572 DoListExtractRestFwd(TermNode& term, ContextNode& ctx)
25332573 {
2534- return DoListExtractFirstRest(term, ctx,
2535- [](TermNode& nterm, TermReference& ref, TermNode& nd){
2536- ReduceToRestOrVal(nterm, nd, &ref, [](TermNode&) ynothrow{},
2537- [&](TermNode& dst, TermNode& tm, ResolvedTermReferencePtr){
2538- LiftOtherOrCopy(dst, tm, ref.IsMovable());
2539- });
2540- }, [](TermNode& nterm, TermNode& o, TermTags tm_tags){
2541- TermNode::Container con(nterm.get_allocator());
2542-
2543- auto first(o.begin());
2544- const auto last(o.end());
2545-
2546- ++first;
2547- if(!bool((o.Tags | tm_tags) & TermTags::Nonmodifying))
2548- con.splice(con.end(), o.GetContainerRef(), first, last);
2549- else
2550- for(; first != last; ++first)
2551- con.emplace_back().CopyContent(*first);
2552- con.swap(nterm.GetContainerRef());
2553- });
2574+ return DoListExtractFirstRest(term, ctx, BindListExtractRestFwd_Ref,
2575+ BindListExtractRestFwd_Val);
25542576 }
25552577
2556-
2557-ReductionStatus
2578+//! \since build 916
2579+YB_ATTR_nodiscard ReductionStatus
2580+ListExtractFirstRest(TermNode& term, ContextNode& ctx,
2581+ ReductionStatus(&f)(TermNode&, ContextNode&))
2582+{
2583+ RetainN(term);
2584+
2585+ auto& con(term.GetContainerRef());
2586+
2587+ con.pop_front();
2588+
2589+ auto& rterm(*term.emplace(ystdex::exchange(con,
2590+ TermNode::Container(term.get_allocator()))));
2591+ auto& tm(*rterm.begin());
2592+
2593+ // NOTE: Save the optional temporary list and bind the last argument as the
2594+ // local reference to list temporary object.
2595+ PrepareFoldRList(con.emplace_back(std::move(tm)));
2596+
2597+ tm.ClearContainer();
2598+ tm.Value = std::move(con.back().Value);
2599+ return DoRLiftSum(term, ctx, rterm, f);
2600+}
2601+
2602+YB_FLATTEN ReductionStatus
25582603 LetCore(TermNode& term, ContextNode& ctx, bool no_lift, bool with_env)
25592604 {
2560- // NOTE: Subterms are %nterm, optional 'e', originally bound 'bindings',
2605+ // NOTE: Subterms are %nterm (the term range of 'bindings' with optional
2606+ // temporary list), optional 'e', originally bound 'bindings',
25612607 // trailing 'body'.
25622608 YAssert(term.size() >= (with_env ? 3 : 2), "Invalid nested call found.");
25632609
25642610 auto i(term.begin());
25652611 auto& nterm(*i);
2566-
2567- // NOTE: The %nterm variable should hold the forwarded 'binding' at this
2568- // point. It cannot have the unique tag, so it can be directly used as an
2569- // lvalue as if returned by the name resolution.
2570- YAssert(!bool(nterm.Tags & TermTags::Unique), "Invalid term found.");
2571-
25722612 auto& con(term.GetContainerRef());
25732613 const auto& d(ctx.GetRecordPtr());
25742614
25752615 if(with_env)
25762616 ++i;
25772617 ++i;
2618+
25782619 return A1::ReduceCurrentNext(*term.emplace([&]{
25792620 const auto a(term.get_allocator());
25802621 TermNode::Container tcon(a);
@@ -2584,26 +2625,28 @@
25842625 // NOTE: Now subterms are 'bindings', optional 'e',
25852626 // originally bound 'bindings', 'body'.
25862627 tcon.clear();
2587- tcon.emplace_back();
2588- tcon.push_back(nterm);
2589- PrepareFoldRList(tcon.back());
2628+ tcon.emplace_back(NPL::AsTermNode(nterm.Value)).Tags = nterm.Tags;
25902629 return tcon;
25912630 }()), ctx, DoListExtractFirst,
25922631 A1::NameTypedReducerHandler([&, d, no_lift, with_env]{
2593- // NOTE: Now subterms are 'bindings', optional 'e', originally bound
2632+ // NOTE: Now subterms are %nterm, optional 'e', originally bound
25942633 // 'bindings', 'body', extracted 'formals' for the lambda abstraction.
25952634 const auto a(nterm.get_allocator());
2596-
2597- PrepareFoldRList(nterm);
2598- // NOTE: Replace 'bindings' (%nterm) directly to the call expression, as
2599- // 'bindings' is not needed after this call. Note %nterm.Tags is
2600- // uninterested.
2601- nterm.emplace(ystdex::exchange(nterm, TermNode(a)));
2602- nterm.GetContainerRef().emplace_front();
2603- // TODO: Blocked. Use C++14 lambda initializers to simplify the
2604- // implementation.
2635+ // NOTE: Replace %nterm directly to the call expression, as 'bindings'
2636+ // is not needed after this call.
2637+ auto& n2term(*nterm.emplace(ystdex::exchange(nterm, TermNode(a))));
2638+
2639+ if(!bool(n2term.Tags & TermTags::Nonmodifying))
2640+ {
2641+ auto& n2tr(n2term.Value.GetObject<TermRange>());
2642+
2643+ // NOTE: The old range is invalidated. Refresh it.
2644+ n2tr = TermRange(n2term, n2tr.Tags);
2645+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
2646+ // implementation.
2647+ }
26052648 return A1::ReduceCurrentNext(nterm, ctx, DoListExtractRestFwd,
2606- A1::NameTypedReducerHandler([&, no_lift, with_env]() YB_FLATTEN{
2649+ A1::NameTypedReducerHandler([&, d, no_lift, with_env]{
26072650 // NOTE: Now subterms are extracted arguments for the call,
26082651 // optional 'e', originally bound 'bindings', 'body',
26092652 // extracted 'formals' for the lambda abstraction.
@@ -2613,12 +2656,18 @@
26132656 // 'formals' for the lambda abstraction.
26142657 YAssert(term.size() == 4, "Invalid term found.");
26152658 VauHandler::CheckParameterTree(con.back());
2659+
2660+ auto& alist(con.front());
2661+
26162662 return A1::RelayCurrentNext(ctx, con.front(),
2617- Continuation([](TermNode& t, ContextNode& c) YB_FLATTEN{
2618- ReduceChildren(t, c);
2663+ Continuation([&](TermNode&, ContextNode& c){
2664+ // NOTE: This does not support continuation capture, so
2665+ // %alist is directly captured here without setup of the
2666+ // next term.
2667+ ReduceChildren(alist, c);
26192668 return ReductionStatus::Partial;
26202669 }, ctx), NPL::ToReducer(ctx.get_allocator(),
2621- A1::NameTypedReducerHandler([&, no_lift]() YB_FLATTEN{
2670+ A1::NameTypedReducerHandler([&, no_lift]{
26222671 const auto let_call([&]{
26232672 EnvironmentGuard
26242673 egd(ctx, NPL::SwitchToFreshEnvironment(ctx));
@@ -2701,9 +2750,10 @@
27012750 }, "eval-let-extract-arguments"));
27022751 }
27032752
2704-//! \since build 915
2753+//! \since build 916
27052754 void
2706-ExpireReferenceListLV(TermNode& term, TermNode& nd, const TermReference& ref)
2755+ExpireReferenceListLV(TermNode& term, TermNode& nd,
2756+ const EnvironmentReference& r_env, TermTags o_tags)
27072757 {
27082758 if(IsList(nd))
27092759 {
@@ -2711,15 +2761,12 @@
27112761 // %BindParameterObject in NPLA1.cpp.
27122762 const auto a(term.get_allocator());
27132763 TermNode::Container con(a);
2714- const auto& r_env(ref.GetEnvironmentReference());
2715- auto o_tags(ref.GetTags() & TermTags::Nonmodifying);
27162764
27172765 for(auto& o : nd)
27182766 {
27192767 if(const auto p = NPL::TryAccessLeaf<TermReference>(o))
27202768 con.emplace_back(o.GetContainer(), ValueObject(
2721- std::allocator_arg, a, in_place_type<TermReference>,
2722- BindReferenceTags(*p), *p));
2769+ std::allocator_arg, a, in_place_type<TermReference>, *p));
27232770 else
27242771 con.emplace_back(TermNode::Container(o.get_allocator()),
27252772 ValueObject(std::allocator_arg, a, in_place_type<
@@ -2730,11 +2777,12 @@
27302777 }
27312778 else
27322779 ThrowListTypeErrorForNonlist(nd, true);
2733- term.Value.Clear(),
2780+ // NOTE: As %PrepareFoldRList.
2781+ term.Value = TermRange(term);
27342782 term.Tags = TermTags::Temporary;
27352783 }
27362784
2737-ReductionStatus
2785+YB_FLATTEN ReductionStatus
27382786 LetImpl(TermNode& term, ContextNode& ctx, bool no_lift, bool with_env = {})
27392787 {
27402788 Retain(term);
@@ -2751,23 +2799,26 @@
27512799
27522800 if(const auto p = NPL::TryAccessLeaf<TermReference>(bindings))
27532801 {
2754- if(p->IsReferencedLValue())
2802+ auto& nd(p->get());
2803+
2804+ if(p->IsMovable())
2805+ ExpireReferenceListLV(forwarded, nd,
2806+ p->GetEnvironmentReference(), p->GetTags());
2807+ else
27552808 {
27562809 p->AddTags(TermTags::Nonmodifying);
2757- forwarded = std::move(bindings);
2758- forwarded.Tags = TermTags::Unqualified;
2810+ // NOTE: As %PrepareFoldRList.
2811+ if(IsList(nd))
2812+ yunseq(forwarded.Value = TermRange(nd, p->GetTags()),
2813+ forwarded.Tags = TermTags::Nonmodifying);
2814+ else
2815+ ThrowInsufficientTermsError(nd, true);
27592816 return LetCore(term, ctx, no_lift, with_env);
27602817 }
2761- else
2762- ExpireReferenceListLV(forwarded, p->get(), *p);
27632818 }
27642819 else
2765- {
2766- forwarded.Value = TermReference(GetLValueTagsOf(bindings.Tags)
2767- & ~TermTags::Unique, bindings, ctx.GetRecordPtr());
2768- ExpireReferenceListLV(forwarded, bindings,
2769- forwarded.Value.GetObject<const TermReference>());
2770- }
2820+ ExpireReferenceListLV(forwarded, bindings, ctx.GetRecordPtr(),
2821+ bindings.Tags);
27712822 return LetCore(term, ctx, no_lift, with_env);
27722823 }
27732824 else
@@ -3467,16 +3518,14 @@
34673518 // XXX: Ditto.
34683519 BindMoveNextNLocalSubobjectInPlace(std::next(term.begin()), 5);
34693520
3470- auto& con(term.GetContainerRef());
3471- auto& rterm(*term.emplace(ystdex::exchange(con,
3521+ auto& rterm(*term.emplace(ystdex::exchange(term.GetContainerRef(),
34723522 TermNode::Container(term.get_allocator()))));
34733523
3474- // NOTE: This is for the store of %n2term.
3524+ // NOTE: Save 'sum'.
3525+ PrepareTailOp(term, ctx, *rterm.rbegin());
3526+ // NOTE: These are for the store of %n2term and the lvalue list.
34753527 rterm.emplace();
3476- // NOTE: This is for the store of lvalue list.
34773528 rterm.emplace();
3478- // NOTE: Save 'sum'.
3479- PrepareTailOp(term, ctx, rterm, 6);
34803529 return DoRLiftSum(term, ctx, rterm, DoAccR);
34813530 }
34823531
@@ -3513,6 +3562,7 @@
35133562 LiftToReturn(*ri);
35143563 // NOTE: Bind 'x' as the local reference to list temporary object.
35153564 PrepareFoldRList(*++ri);
3565+ RemoveHead(term);
35163566 return DoListConcat(term, ctx);
35173567 }
35183568
@@ -3520,45 +3570,33 @@
35203570 Append(TermNode& term, ContextNode& ctx)
35213571 {
35223572 Retain(term);
3523-
3524- auto& con(term.GetContainerRef());
3525- const auto a(con.get_allocator());
3526-
3573+#if true
3574+ // XXX: This is a bit more efficient.
35273575 RemoveHead(term);
3528- term.emplace(ystdex::exchange(term.GetContainerRef(), [&]{
3529- TermNode::Container tcon(term.get_allocator());
3530-
3531- tcon.emplace_back().GetContainerRef().emplace_back();
3532- return tcon;
3533- }()));
3576+ term.emplace(ystdex::exchange(term.GetContainerRef(),
3577+ TermNode::Container(term.get_allocator())));
3578+#else
3579+
3580+ auto i(term.begin());
3581+ auto& tm(NPL::Deref(i));
3582+
3583+ tm.Clear();
3584+ tm.GetContainerRef().splice(tm.end(), term.GetContainerRef(), ++i,
3585+ term.end());
3586+#endif
35343587 return DoAppend(term, ctx);
35353588 }
35363589
35373590 ReductionStatus
3538-ListExtract(TermNode& term, ContextNode& ctx)
3539-{
3540- RetainN(term, 2);
3541-
3542- auto i(PrepareListExtract(term));
3543-
3544- BindMoveLocalObjectInPlace(*++i);
3545- return DoListExtract(term, ctx);
3546-}
3547-
3548-ReductionStatus
35493591 ListExtractFirst(TermNode& term, ContextNode& ctx)
35503592 {
3551- RetainN(term);
3552- PrepareListExtract(term);
3553- return DoListExtractFirst(term, ctx);
3593+ return ListExtractFirstRest(term, ctx, DoListExtractFirst);
35543594 }
35553595
35563596 ReductionStatus
35573597 ListExtractRestFwd(TermNode& term, ContextNode& ctx)
35583598 {
3559- RetainN(term);
3560- PrepareListExtract(term);
3561- return DoListExtractRestFwd(term, ctx);
3599+ return ListExtractFirstRest(term, ctx, DoListExtractRestFwd);
35623600 }
35633601
35643602 ReductionStatus
diff -r 37835df0ac3b -r dfccd642351f YFramework/source/NPL/NPLA1Internals.h
--- a/YFramework/source/NPL/NPLA1Internals.h Fri Mar 26 22:43:02 2021 +0800
+++ b/YFramework/source/NPL/NPLA1Internals.h Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPLA1Internals.h
1212 \ingroup NPL
1313 \brief NPLA1 内部接口。
14-\version r20923
14+\version r20982
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 882
1717 \par 创建时间:
1818 2020-02-15 13:20:08 +0800
1919 \par 修改时间:
20- 2021-03-01 18:44 +0800
20+ 2021-04-05 02:53 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 非公开模块名称:
@@ -518,7 +518,7 @@
518518
519519 //! \since build 879
520520 //@{
521-#if NPL_Impl_NPLA1_Enable_Thunked && !NPL_Impl_NPLA1_Enable_InlineDirect
521+#if NPL_Impl_NPLA1_Enable_Thunked
522522 YB_ATTR(always_inline) inline ReductionStatus
523523 RelayCurrent(ContextNode& ctx, Continuation&& cur)
524524 {
@@ -536,30 +536,6 @@
536536 {
537537 return A1::RelayCurrent(ctx, Continuation(yforward(cur), ctx));
538538 }
539-
540-template<typename _fNext>
541-YB_ATTR(always_inline) inline ReductionStatus
542-RelayNextOrDirect(ContextNode& ctx, Continuation&& cur, _fNext&& next)
543-{
544- RelaySwitched(ctx, yforward(next));
545- return RelaySwitched(ctx, yforward(cur));
546-}
547-template<typename _fNext>
548-YB_ATTR(always_inline) inline ReductionStatus
549-RelayNextOrDirect(ContextNode& ctx,
550- std::reference_wrapper<Continuation> cur, _fNext&& next)
551-{
552- RelaySwitched(ctx, yforward(next));
553- return RelaySwitched(ctx, cur);
554-}
555-template<typename _fCurrent, typename _fNext>
556-YB_ATTR(always_inline) inline auto
557-RelayNextOrDirect(ContextNode& ctx, _fCurrent&& cur, _fNext&& next)
558- -> decltype(cur(std::declval<TermNode&>(), ctx))
559-{
560- return A1::RelayNextOrDirect(ctx, Continuation(yforward(cur), ctx),
561- yforward(next));
562-}
563539 #endif
564540 //@}
565541
@@ -610,13 +586,8 @@
610586 _fNext&& next)
611587 {
612588 #if NPL_Impl_NPLA1_Enable_Thunked
613-# if NPL_Impl_NPLA1_Enable_InlineDirect
614- RelaySwitched(ctx, yforward(next));
615- return A1::RelayDirect(ctx, yforward(cur), term);
616-# else
617- yunused(term);
618- return A1::RelayNextOrDirect(ctx, yforward(cur), yforward(next));
619-# endif
589+ NPL::RelaySwitched(ctx, yforward(next));
590+ return A1::RelayCurrentOrDirect(ctx, yforward(cur), term);
620591 #else
621592 A1::RelayDirect(ctx, yforward(cur), term);
622593 return ystdex::expand_proxy<ReductionStatus(ContextNode&)>::call(
@@ -624,6 +595,21 @@
624595 #endif
625596 }
626597
598+//! \since build 916
599+template<typename _fCurrent, typename _fNext>
600+YB_FLATTEN inline ReductionStatus
601+RelayCurrentNextThunked(ContextNode& ctx, TermNode& term, _fCurrent&& cur,
602+ _fNext&& next)
603+{
604+#if NPL_Impl_NPLA1_Enable_Thunked
605+ yunused(term);
606+ NPL::RelaySwitched(ctx, yforward(next));
607+ return A1::RelayCurrent(ctx, yforward(cur));
608+#else
609+ return A1::RelayCurrentNext(ctx, term, yforward(cur), yforward(next));
610+#endif
611+}
612+
627613 template<typename _fCurrent, typename _fNext>
628614 // XXX: This is a workaround for G++'s LTO bug.
629615 #if YB_IMPL_GNUCPP >= 100000 || !NPL_Impl_NPLA1_Enable_Thunked \
@@ -637,6 +623,21 @@
637623 SetupNextTerm(ctx, term);
638624 return A1::RelayCurrentNext(ctx, term, yforward(cur), yforward(next));
639625 }
626+
627+//! \since build 916
628+template<typename _fCurrent, typename _fNext>
629+#if YB_IMPL_GNUCPP >= 100000 || !NPL_Impl_NPLA1_Enable_Thunked \
630+ || NPL_Impl_NPLA1_Enable_TCO
631+YB_FLATTEN
632+#endif
633+inline ReductionStatus
634+ReduceCurrentNextThunked(TermNode& term, ContextNode& ctx, _fCurrent&& cur,
635+ _fNext&& next)
636+{
637+ SetupNextTerm(ctx, term);
638+ return A1::RelayCurrentNextThunked(ctx, term, yforward(cur),
639+ yforward(next));
640+}
640641 //@}
641642
642643
@@ -858,7 +859,7 @@
858859 ReduceEnvSwitch(TermNode& term, ContextNode& ctx, _tGuardOrEnv&& gd_or_env)
859860 {
860861 _tTraits::SetupForNonTail(ctx, term);
861- // NOTE: The next term is set here unless direct inlining call of
862+ // NOTE: The next term is set here unless the direct inlining call in
862863 // %ReduceCombinedBranch is used.
863864 #if !NPL_Impl_NPLA1_Enable_InlineDirect
864865 SetupNextTerm(ctx, term);
@@ -872,9 +873,9 @@
872873 ReduceCallSubsequent(TermNode& term, ContextNode& ctx,
873874 _tGuardOrEnv&& gd_or_env, _fNext&& next)
874875 {
875- // TODO: Blocked. Use C++14 lambda initializers to simplify the
876- // implementation.
877876 return A1::ReduceCurrentNext(term, ctx,
877+ // TODO: Blocked. Use C++14 lambda initializers to simplify the
878+ // implementation.
878879 ystdex::bind1([](TermNode& t, ContextNode& c, _tGuardOrEnv& g_e){
879880 return ReduceEnvSwitch(t, c, std::move(g_e));
880881 }, std::placeholders::_2, std::move(gd_or_env)), yforward(next));
diff -r 37835df0ac3b -r dfccd642351f YFramework/source/NPL/SContext.cpp
--- a/YFramework/source/NPL/SContext.cpp Fri Mar 26 22:43:02 2021 +0800
+++ b/YFramework/source/NPL/SContext.cpp Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file SContext.cpp
1212 \ingroup NPL
1313 \brief S 表达式上下文。
14-\version r2039
14+\version r2052
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 329
1717 \par 创建时间:
1818 2012-08-03 19:55:59 +0800
1919 \par 修改时间:
20- 2021-03-12 18:13 +0800
20+ 2021-03-31 06:26 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -34,6 +34,21 @@
3434 namespace NPL
3535 {
3636
37+void
38+TermNode::ClearContainer() ynothrow
39+{
40+ // NOTE: See %~TermNode.
41+ while(!container.empty())
42+ {
43+ const auto i(container.begin());
44+
45+ // NOTE: Flatten the subterms and insert them before the leftmost
46+ // recursive subterm.
47+ container.splice(i, std::move(NPL::Deref(i).container));
48+ container.erase(i);
49+ }
50+}
51+
3752 // XXX: Simplify with %CreateRecursively?
3853 TermNode::Container
3954 TermNode::ConCons(const ValueNode::Container& con)
diff -r 37835df0ac3b -r dfccd642351f doc/ChangeLog.V0.9.txt
--- a/doc/ChangeLog.V0.9.txt Fri Mar 26 22:43:02 2021 +0800
+++ b/doc/ChangeLog.V0.9.txt Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file ChangeLog.V0.9.txt
1212 \ingroup Documentation
1313 \brief 版本更新历史记录 - V0.9 。
14-\version r3284
14+\version r3465
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 800
1717 \par 创建时间:
1818 2020-10-12 17:19:23 +0800
1919 \par 修改时间:
20- 2021-03-26 22:13 +0800
20+ 2021-04-14 12:02 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -32,6 +32,186 @@
3232
3333 $now
3434 (
35+ (
36+ / "supported 'FREEIMAGE_LIBRARY_TYPE=STATIC'"
37+ @ "%3rdparty/FreeImage/Makefile.gnu";
38+ / "rebuilt library %FreeImage" @ "platform %Linux"
39+ // This eliminates unnecessary FreeImage initialization (by calling \
40+ %::FreeImage_SO_Initialise) and finalization (by calling \
41+ %::FreeImage_SO_DeInitialise) on loading libYFramework.so.
42+ ),
43+ / %Tools.Scripts $=
44+ (
45+ * "saving initial value had no effect" @ "applicative 'env-set'"
46+ @ "%SHBuild-YSLib-common.txt" @ $since b840;
47+ * $comp "wrong initial value of %LIBS used for stage 2 SHBuild build" @
48+ @ "%SHBuild-YSLib-build.txt" $since b840
49+ // This would cause wrong debug libraries linked after debug builds.
50+ ),
51+ / %YFramework.NPL $=
52+ (
53+ * $re_add(b863) "missing nested call safety in handling terms from \
54+ object language" @ ("function %ClearContainer"; ("destructor",
55+ $comp "function %Clear")) @ "type %TermNode" @ %SContext
56+ $since b674,
57+ // This would potentionally cause undefined behavior due to native \
58+ call for large input (usually constructed in the user \
59+ program). The implementation never supported nested call \
60+ safety before, but this was introduced in the document since \
61+ b868 and this case was not explicitly in the documented \
62+ exceptional ones.
63+ / %NPLA1Internals $=
64+ (
65+ / DLDI "function %RelayCurrentNext" ^ "%A1::RelayCurrentOrDirect"
66+ ~ "%RelayNextOrDirect";
67+ - $revert(b879) "function templates %ReduceNextOrDirect";
68+ * "missing qualified 'NPL::'" @ "call to %ReduceSwitched"
69+ $effective @ "function template %RelayCurrentNext",
70+ (
71+ / "enabled functions %RelayCurrent"
72+ @ 'NPL_Impl_NPLA1_Enable_InlineDirect';
73+ + "function templates %(RelayCurrentNextThunked, \
74+ ReduceCurrentNextThunked)"
75+ )
76+ ),
77+ / %NPLA1 $=
78+ (
79+ * "redundant temporary tag on unique references in the result"
80+ @ ("function %ReduceToReferenceList" $since b914,
81+ "function %ReduceToReferenceUList" $since b915),
82+ / "avoided bound tempoaray tag on non-temporary object bound with \
83+ sigil '&' in trailing lists" @ "function %BindParameter"
84+ // The temporary tag was added in b875, to simplified the \
85+ argument to 'forward!' calls in typical cases. However, \
86+ this is too aggressive for a trailing binding and there \
87+ would be no easy and efficient way to undo the addition \
88+ of the temporary tag on every elements in derived \
89+ implementations. So, avoided the tag initially in such \
90+ cases.
91+ ),
92+ / @ "namespace %Forms" @ %NPLA1Forms $=
93+ (
94+ (
95+ / DLI @ "function %Append" $=
96+ (
97+ / "avoided redundant list initialization",
98+ / "refactored to avoid redundant term move before the list \
99+ concatenation"
100+ ),
101+ / "avoided copy list lvalues at first" @ "functions %(Append, \
102+ ListConcat, Map1, FoldR1, ListExtractFirst, ListExtractRest)"
103+ $dep_to "native list forwarding";
104+ / DLI "simplified object layout"
105+ @ "functions %(Append, ListConcat, Map1, FoldR1)"
106+ ),
107+ * "missing nested call safety in recursive calls"
108+ @ 'NPL_Impl_NPLA1_Enable_InlineDirect' $effective @ ("function \
109+ %AccR" $since b898, "functions %(FoldR1, Map1)" $since b908,
110+ "functions %(Append, ListConcat)" $since b912, "functions \
111+ %(ListExtract, ListExtractFirst, ListExtractLast)" $since b914)
112+ $= (/ $impl ^ $dep_from ("%A1::ReduceCurrentNextThunked"
113+ @ %NPLA1Internals) ~ "%A1::ReduceCurrentNext"),
114+ * $impl "wrong continuation type used"
115+ @ "functions %(ListExtractFirst, ListExtractRest)" $since b914,
116+ // This made the continuation clash with the one used by \
117+ %ListConcat.
118+ / DLDI "simplified function %AccR",
119+ * "arguments of reference to temporary objects wrongly moved"
120+ @ "functions %(RestVal, RestFwd)" $since b910,
121+ - $revert(b914) "function %ListExtract"
122+ $dep_from ("applicative 'list-extract%'"
123+ @ "function %LoadGroundContext" @ %Dependency),
124+ / "functions %Forms::(Let, LetRef, LetWithEnvironment, \
125+ LetWithEnvironmentRef)" $=
126+ (
127+ * @ 'NPL_Impl_NPLA1_Enable_Thunked && \
128+ !NPL_Impl_NPLA1_Enable_InlineDirect' $since b915 $=
129+ (
130+ * "current environment corrupted caused by missing \
131+ internal capture of the dynamic environment",
132+ * "wrong term used as the initializers being initialized"
133+ ),
134+ / $forced "avoided binding temporary tags on elements of \
135+ binding list rvalue arguments" $=
136+ (/ $impl !^ "%BindReferenceTags"),
137+ // Same to %BindParameter in %NPLA1.
138+ * "wrongly moved binding parameter of reference with \
139+ temporary tag" $since b914
140+ $= (/ $impl ^ "%TermReference::IsMovable"
141+ ~ "%TermReference::IsReferencedLValue"),
142+ / $forced DLI "simplified list preparation and avoided \
143+ redundant copies of list preparation"
144+ $dep_from "%(ListExtractFirst, ListExtractRest)"
145+ $dep_to "let-family native list forwarding",
146+ / DLDI
147+ "simplified initialization of binding from movable argument"
148+ )
149+ ),
150+ / @ "function %LoadGroundContext" @ %Dependency $=
151+ (
152+ / "allowed shard list references without copies" @ "%foldr1" $=
153+ (
154+ / $impl "alternative derivation"
155+ ^ "variables initialized with '@' sigil";
156+ * "differences of redundant copies between the alternative \
157+ derivation and the native implemention"
158+ @ "call to %foldr1 alternative derivation" $since b913
159+ $dep_from "native list forwarding" @ %NPLA1Forms),
160+ // See $2021-04 @ %Documentation::Workflow.
161+ ),
162+ * "missing lifting of the result" @ "derivation"
163+ @ "operative '$letrec'" $since b914
164+ $= (/ $impl ^ '$let' ~ '$let%'),
165+ // The bug might be hidden by the TCO implementation, though.
166+ * $comp "native implementation" @ "applicatives ('rest%', %restv)"
167+ $since b910 $dep_from ("%(RestFwd, RestVal)" @ %NPLA1Forms),
168+ / "simplified alternative derivation" @ "applicative %rulist"
169+ ^ "%idv" ~ "%rlist",
170+ * "redundant temporary tag on unique references in the result"
171+ @ ("applicative %rlist" $since b914,
172+ "applicative %rulist" $since b915) $=
173+ (
174+ / $comp "native implementations" $dep_from
175+ ("%(ReduceToReferenceList, ReduceToReferenceList)"
176+ @ %NPLA1),
177+ / $comp "alternative derivations" $dep_from
178+ ("%BindParameter" @ %NPLA1)
179+ ),
180+ / @ "applicative %map1"
181+ (
182+ * "wrong forwarding" @ "alternative derivation" $since b899;
183+ * "differences of wrong forwarding between the alternative \
184+ derivation and the native implemantion" $since b899
185+ // See $2021-04 @ %Documentation::Workflow.
186+ ),
187+ / "supported preserving non-movable lists and avoided redundant \
188+ copies of subobjects of the list argument"
189+ @ "applicatives ('list-extract-first', 'list-extract-rest%')" $=
190+ (
191+ / "alternative derivations"
192+ $= (/ $impl ^ ($dep_from "%map1") ~ 'list-extract%'
193+ $dep_from ("applicative %foldr1", "%BindParameter"
194+ @ %NPLA1) $dep_to "avoiding dedicated list extraction"),
195+ / $comp "native implementations" $dep_from ("functions \
196+ %(ListExtractFirst, ListExtractRest)" @ %NPLA1Forms)
197+ ),
198+ - "applicative 'list-extract%'"
199+ $dep_from "avoiding dedicated list extraction",
200+ / DLDI "simplified derivations" @ "operatives ('$let', '$let%', \
201+ '$let/e', '$let/e%', '$letrec', '$letrec%')",
202+ / $comp "avoided redundant copies of subobjects of the binding \
203+ list argument" @ "operatives ('$let', '$let%', '$let/e', \
204+ '$let/e%')" $dep_from "let-family native list forwarding"
205+ // Similar to 'foldr1' calls, but not a bug.
206+ )
207+
208+ ),
209+ + "restriction of copies" @ "applicative %foldr1"
210+ @ %Documentation.NPL $dep_from %YFramework.NPL.Dependency
211+),
212+
213+b915
214+(
35215 / %YFramework.NPL $=
36216 (
37217 / DLDI "simplified all calls to construct %TermNode with a sole \
@@ -1377,7 +1557,7 @@
13771557 offending.
13781558 * "%LDFLAGS pollution caused by %SHBuild_LDFLAGS extension \
13791559 when %LDFLAGS is unused" @ "library build" $since b906
1380- // This is needed fixing even if the call of \
1560+ // This is needed fixing even if the call to \
13811561 %SHBuild_Extend_CallVariables is removed, for base \
13821562 %LDFLAGS used by %Win32 at least.
13831563 ),
@@ -2085,7 +2265,7 @@
20852265 / DLI @ "%SHBuild-bootstrap.sh" $=
20862266 (
20872267 / "shrinked prefixed tabs" @ "all default values",
2088- / $design "quoted arguments" @ "1st call of %SHBuild_Puts"
2268+ / $design "quoted arguments" @ "1st call to %SHBuild_Puts"
20892269 ),
20902270 / @ "%SHBuild-common.sh" $=
20912271 (
@@ -2151,7 +2331,7 @@
21512331 / "supported build variables %(SHBuild_Host_Arch, SHBuild_Host_OS) for \
21522332 build scripts" $=
21532333 (
2154- / "call of %SHBuild_CheckUName" -> ($dep_from
2334+ / "call to %SHBuild_CheckUName" -> ($dep_from
21552335 "%SHBuild_PrepareBuild" @ ("%SHBuild-common.sh" @ %Tools.Scripts))
21562336 $effecitive @ ("%install-sysroot.sh", "%(SHBuild-bootstrap.sh, \
21572337 SHBuild-toolchain-options.sh)" @ %Scripts) @ %Tools,
diff -r 37835df0ac3b -r dfccd642351f doc/Dependencies.txt
--- a/doc/Dependencies.txt Fri Mar 26 22:43:02 2021 +0800
+++ b/doc/Dependencies.txt Wed Apr 14 12:24:53 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 Dependencies.txt
1212 \ingroup Documentation
1313 \brief 依赖说明。
14-\version r1606
14+\version r1613
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 519
1717 \par 创建时间:
1818 2014-07-15 03:14:24 +0800
1919 \par 修改时间:
20- 2020-10-11 03:52 +0800
20+ 2021-03-27 15:12 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -436,9 +436,12 @@
436436 升级包 core/gcc 和 core/gcc-libs 版本 5.1.0-4 。
437437 升级包 extra/nasm 版本 2.11.08-1 。
438438 2020-10-10(build 900) 起:
439-升级包 core/binutils 版本 2.32-2 。
439+升级包 core/binutils 版本 2.35-2 。
440440 升级包 core/gcc 和 core/gcc-libs 版本 10.2.0-3 。
441441 升级包 extra/nasm 版本 2.15.05-1 。
442+2021-03-27(build 916) 起:
443+升级包 core/binutils 版本 2.36.1-2 。
444+升级包 core/gcc 和 core/gcc-libs 版本 10.2.0-6 。
442445
443446 @1.6.1 Android 平台构建说明:
444447 需要使用宏 ANDROID_SDK 指定 Android SDK 的路径。
@@ -604,6 +607,8 @@
604607 2020-10-10(build 900) 起:
605608 支持 makefile 命令行选项 CONF=debug 指定 debug 配置的 YFreamwork 库文件。
606609 追加 debug 配置的 DS 、MinGW32 、Linux 和 MinGW64 库文件,并重新构建这些平台上非 debug 配置的库文件。
610+2021-03-27(build 915) 起:
611+指定 FREEIMAGE_LIBRARY_TYPE=STATIC 重新构建 Linux 库文件。
607612
608613 @3 可选外部依赖:
609614
diff -r 37835df0ac3b -r dfccd642351f doc/NPL.txt
--- a/doc/NPL.txt Fri Mar 26 22:43:02 2021 +0800
+++ b/doc/NPL.txt Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file NPL.txt
1212 \ingroup Documentation
1313 \brief NPL 规范和实现规格说明。
14-\version r22172
14+\version r22216
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 304
1717 \par 创建时间:
1818 2012-04-25 10:34:20 +0800
1919 \par 修改时间:
20- 2021-03-26 12:17 +0800
20+ 2021-04-12 23:37 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -1123,6 +1123,7 @@
11231123 非决定性规约规则:除非派生实现另行指定,递归蕴含规则(@4.4.4.1) 约定外的任意表达式的求值之间无序。
11241124 非决定性规约规则允许在语言中表达并发实现(@2.4.2) 。
11251125 规约规则的顺序直接适用于求值,其顺序为求值顺序(evaluation order) 。
1126+规约规则的顺序也适用在能以规约描述相对顺序的事件上,如两个对象的生存期(@4.1) 的起始。
11261127
11271128 @4.4.2 求值性质:
11281129 两个具体求值等价,当且仅当两者的作用相等。
@@ -1916,8 +1917,8 @@
19161917
19171918 @5.11 嵌套调用安全:
19181919 宿主语言的 API 提供嵌套调用安全,当且仅当若非调用没有宿主语言无法分配资源的未定义行为(@5.4) ,则同时避免嵌套调用深度过大时引起这样的未定义行为。
1919-嵌套调用安全应包括支持 @5.10.4.1 不保证的情形。
19201920 嵌套调用安全允许不限制嵌套深度的可靠的调用,如递归调用。
1921+嵌套调用安全应包括支持可能通过对象语言构造的输入使对应宿主语言的操作中的嵌套调用不保证的情形(如 @5.10.4.1 )。
19211922 宿主语言实现在宿主语言的尾上下文可能支持宿主 TCO(@5.10.4.2) 而使递归调用满足嵌套调用安全,但这并不是语言提供的保证,不应在可移植的实现中依赖。
19221923 非嵌套调用安全的情形在过程嵌套调用深度过大时,可因为宿主语言的存储资源消耗导致的宿主语言实现的未定义行为,典型地包括实现中的栈溢出(stack overflow) 。
19231924
@@ -3479,32 +3480,31 @@
34793480 绑定引用时,可使用引用推断规则:引用值按值传递(@4.4.4.5) 给形式参数,非引用值按引用传递(@4.4.4.5) 给形式参数(@7.7.3.3) ;
34803481 否则,操作数按值传递给形式参数。
34813482 标记字符引起的绑定的差异为:
3482- 没有标记字符生效时,对操作数按值绑定,实际参数值传递给对应的形式参数。
3483+ 不存在标记字符时,对操作数按值绑定,实际参数值传递给对应的形式参数。
34833484 若实际参数是泛左值(@5.8.1) ,则实际参数上首先隐含左值到右值转换(@6.4.6.1) 。
3484- 标记字符 % 或 & 生效时,按引用推断规则直接绑定或转发操作数。
3485+ 存在标记字符 % 或 & 时,按引用推断规则直接绑定或转发操作数。
34853486 当实际参数是引用值时,隐含一次引用折叠(@6.6.3.3.2) 。
3486- 标记字符 @ 生效时,绑定以实际参数作为被引用对象的引用值,不论操作数的类型和值类别。
3487+ 存在标记字符 @ 时,绑定以实际参数作为被引用对象的引用值,不论操作数的类型和值类别。
34873488 初始化引用值时,没有引用折叠。
34883489
34893490 @7.7.3.5 非递归绑定:
34903491 非递归绑定在一次匹配之后创建对应的变量绑定。
3491-合并使用或不使用引用标记字符的情形,非结尾列表(@7.7.3.3) 的单一参数对象的绑定初始化包含以下过程:
3492+合并使用或不使用引用标记字符(@7.7.3.4) 的情形,非结尾列表(@7.7.3.3) 的单一参数对象的绑定初始化包含以下过程:
34923493 若没有绑定标记字符 @ ,则:
3493- 若操作数为可转移的(@6.6.3.3.4) 对象的引用值,则:
3494- 有标记字符时,使用引用推断规则,绑定变量为通过操作数直接初始化的引用值。
3495- 没有标记字符时,绑定变量为操作数复制初始化的值。
3496- 被绑定对象(引用值)的标签由操作数的(引用值)的标签决定:
3497- 当有标记字符 & 时,被绑定对象(引用值)中包含绑定临时对象标签(@7.7.3.2) ,当且仅当引用值的标签包含 TermTags::Unique 。
3494+ 若操作数为可转移的(@6.6.3.3.4) 对象的引用值,则被绑定对象是按以下规则初始化的蕴含隐含的引用折叠(@7.7.3.4) 的引用值:
3495+ 存在标记字符时,使用引用推断规则(@7.7.3.4) ,被绑定对象是操作数直接初始化的值,其中被绑定对象(引用值)的标签由操作数的(引用值)的标签决定:
3496+ 当有标记字符 & 、绑定非结尾列表且引用值的标签指定唯一引用(@6.2.2) 时,被绑定对象(引用值)中包含绑定临时对象标签(@7.7.3.2) 。
34983497 否则,被绑定对象的标签和引用值的标签相同。
3498+ 否则,被绑定对象是操作数复制初始化(复制或转移)的值。
34993499 否则,若操作数标签(@7.7.3.6) 指定可修改的唯一引用或有标记字符 % 时的唯一引用,操作数是可转移的非引用值,被绑定的对象是临时对象。
3500- 否则,当有标记字符 & 时,被绑定对象是操作数的引用值。
3500+ 否则,当存在标记字符 & 时,被绑定对象是操作数的引用值。
35013501 否则,被绑定对象是复制自操作数的值。
35023502 否则,被绑定的是操作数的引用:
35033503 绑定操作数的引用时,要求引用的是列表中的项,否则抛出 NPL::InvalidReference(@6.5) 异常。
35043504 被绑定的对象应是不唯一的值(直接绑定操作数右值以外的值),被绑定对象是操作数的引用值。
35053505 绑定结尾列表包含以下情形:
35063506 若绑定的列表是临时对象,则绑定子项复制消除,拆分新的列表对象作为被绑定对象;
3507- 否则,若有标记字符 & ,则创建列表的子对象引用(@6.6.3.3.5) 作为被绑定对象;
3507+ 否则,若存在标记字符 & ,则创建列表的子对象引用(@6.6.3.3.5) 作为被绑定对象;
35083508 否则,创建新的列表,作为被绑定对象。
35093509 绑定结尾列表若创建列表(包括子对象引用隐含创建的共享列表对象),其中的子对象的元素是对应的操作数以对应的引用标记字符(若存在)绑定单一参数得到的值。
35103510 除绑定临时对象(@7.7.3.2) 外,若绑定操作数的初始化的引用值时实际引用临时对象,则行为未定义。(不和宿主语言一样可能延长右值类类型子对象的生存期。)
@@ -3514,7 +3514,7 @@
35143514 具有引用标记字符的形式参数支持引入引用值并支持绑定引入临时对象的实际参数(@5.8.5) 。
35153515 为允许调用宿主对象的转移构造函数(@5.8.2.3) ,仅在绑定临时对象到引用时使用复制消除(@5.8.5.3) 。
35163516 (实际上,初始化引用之外的参数创建也不是 ISO C++17 约定要求消除复制的上下文。)
3517-绑定临时对象时可能设置被绑定对象上的 TermTags::Temporary 标签(@7.7.3.2) 。
3517+绑定临时对象时,若绑定的是以 & 引用标签引入的引用值,设置被绑定对象上的 TermTags::Temporary 标签(@7.7.3.2) 。
35183518
35193519 @7.7.3.6 递归绑定:
35203520 递归的绑定匹配(@7.7.3.3) 对应递归的绑定,即可能绑定子项。(注意这和绑定结尾列表(@7.7.3.6) 不同,可包含项和其子项的多次递归的匹配。)
@@ -4232,7 +4232,6 @@
42324232 Forms::Map1
42334233 Forms::ListConcat
42344234 Forms::Append
4235-Forms::ListExtract
42364235 Forms::ListExtractFirst
42374236 Forms::ListExtractRestFwd
42384237 Forms::Let
@@ -4302,7 +4301,6 @@
43024301 eval-lift-sum
43034302 eval-list-concat-cons
43044303 eval-list-extract-cons
4305-eval-list-extract-next
43064304 eval-map1-appv
43074305 eval-map1-cons
43084306 eval-vau-parent
@@ -4335,10 +4333,9 @@
43354333 eval-let-make-combiner :Forms::Let 、Forms::LetRef 、Forms::LetWithEnvironment 和 Forms::LetWithEnvironmentRef 中从绑定列表中创建合并子。
43364334 eval-let-parent :Forms::LetWithEnvironment 和 Forms::LetWithEnvironmentRef 中求值过程抽象(@8.4.5) 的父环境的表达式。
43374335 eval-lift-result :非 TCO 的求值实现调用 NPL::ReduceForLiftedResult(@6.7.12.1) 提升返回结果。
4338-eval-lift-sum :Forms::AccR、Forms::FoldR1 和 Forms::Map1(@8.4.9) 公共的部分和提升调用。
4336+eval-lift-sum :Forms::AccR、Forms::FoldR1 、 Forms::Map1 、Forms::ListExtractFirst 和 Forms::ListExtractRestFwd(@8.4.9) 公共的部分和提升调用。
43394337 eval-list-concat-cons :Forms::ListConcat(@8.4.9) 列表构造调用。
4340-eval-list-extract-cons :Forms::ListExtract(@8.4.9) 列表构造调用。
4341-eval-list-extract-next :Forms::ListExtract 列表剩余项访问。
4338+eval-list-extract-cons :Forms::ListExtractFirst 和 Forms::ListExtractRestFwd(@8.4.9) 列表构造调用。
43424339 eval-map1-appv :Forms::Map1(@8.4.9) 应用子调用。
43434340 eval-map1-cons :Forms::Map1 列表构造调用。
43444341 eval-sequence-return :非 TCO 的 A1::ReduceOrdered(@7.4.6) 实现中设置规约合并最后的返回结果。
@@ -4734,8 +4731,11 @@
47344731 对象引用通常不保证对象同一性,包括唯一引用(@6.2.2) 的情形。但除非另行指定,类似 ISO C++ [res.on.arguments] ,作为函数实际参数的对象若是右值引用,则实现可假定被引用对象唯一。
47354732
47364733 @9.8.2 子对象(subobject) :
4737-子对象(subobject) 同宿主语言的约定;在宿主语言的表示中表现为子对象的对象语言中的对象,也是对象语言的子对象。
4738-对象对其存储期和生存期的约束和宿主语言相同。
4734+除非另行指定,子对象(subobject) 及其性质同宿主语言的约定:在宿主语言的表示中表现为子对象的对象语言中的对象,也是对象语言的子对象。
4735+对象的子对象的生存期不先序于(@4.4.1) 对象的生存期起始,对象的子对象的生存期结束不后序于(@4.4.1) 对象的生存期结束。
4736+对象的子对象的生存期起始后序于(@4.4.1) 对象的生存期起始,对象的子对象的生存期结束先序于(@4.4.1) 对象的生存期结束。
4737+除非另行指定,同一个的对象不同子对象的存储期起始、存储期结束、生存期起始、生存期结束之间分别无序。
4738+对象对其存储期和生存期的其它约束和宿主语言相同。
47394739 子对象可具有引用值。子对象的引用值可能使用子对象引用(@6.6.3.3.5) 而非通常的项引用(@6.6.3.3) 实现。
47404740
47414741 @9.8.3 对象的修改和变化 :
@@ -4850,7 +4850,7 @@
48504850 一般地,隐藏环境是某一个(非隐藏的)一等环境的直接或间接父环境(而能通过求值等间接操作被访问)。
48514851
48524852 @9.9.3.2 新环境(fresh environment) :
4853-新环境是新创建的环境,和先前的现有环境不共享相同环境对象。
4853+新环境是新创建的环境,和先前的当前环境(@6.8.3) 不共享相同环境对象。
48544854 除非另行指定,新环境是不存在能引起程序行为改变的父环境的空环境(@4.6.1.1) 。(创建新环境的一个例子是 Vau 抽象(@8.4.5) 实现过程调用。)
48554855
48564856 @9.9.3.3 环境的宿主值和所有权:
@@ -5783,7 +5783,7 @@
57835783 NPL_Impl_NPLA1_Native_EnvironmentPrimitives
57845784 NPL_Impl_NPLA1_Use_Id_Vau
57855785 NPL_Impl_NPLA1_Use_LockEnvironment
5786-不直接使用本机实现的替代实现仅供参考,可能引入和本机实现不同的未指定行为,且可能有和核心特性实现相关的限制:
5786+不直接使用本机实现的替代实现仅供参考,可能引入和本机实现不同的未指定行为(如子对象生存期(@9.8.2) 不同),且可能有和核心特性实现相关的限制:
57875787 由合并子调用的参数绑定(@8.4.5.3) 引起(@9.5.1) 的静态语法错误(@9.5.1) 可能具有不同的诊断(@9.5) ;
57885788 类型检查(@9.5.4.1) 可具有不同的顺序,多次失败的类型检查引起的类型错误可能具有不同的诊断;
57895789 使用 TCO 实现 PTC(@9.7.4) ,可能具有不同的支持(@9.7.4.1) 和实现(如 TCO 动作消除(@7.10.9) );
@@ -5855,7 +5855,7 @@
58555855 为不需要如 Kernel 支持派生 $vau ,直接使用 apply 派生。
58565856 list*% <object>+ :同 list* ,但创建的列表元素保留引用值。
58575857 forward-first% <applicative> <list> :取列表的第一元素并转发给指定的应用子。
5858-对参数列表 (&appv (&x .)) ,作用同求值:
5858+设参数列表 (&appv (&x .)) ,作用同求值:
58595859 (forward! appv) (list% ($move-resolved! x)) ;
58605860 其中,调用 appv 的底层合并子(@4.5.3.2) 的当前环境同调用 forward-first% 的动态环境。
58615861 assign%! <reference> <object> :同 assign@!(@11.3.4) ,但 <object> 是引用时被折叠。
@@ -5921,13 +5921,16 @@
59215921 accr <object1> <predicate> <object2> <applicative1> <applicative2> <applicative3> :在抽象列表的元素上应用右结合的二元操作。
59225922 操作方式同 accl 。
59235923 和 accl 不同,可保证合并操作是尾调用;相应地,递归调用不是尾上下文而无法确保 PTC(@9.7.4.1) 。
5924-foldr1 <applicative> <object> <list> :同 accr ,但指定谓词为 null? ,应用子分别为 first% 和 rest% 。
5925-参数 <applicative> 同 accr 的参数 <applicative3> 。
5924+foldr1 <applicative> <object> <list> :作用同符合以下要求的 accr 调用:
5925+指定 accr 的参数为 <list> 、null? 、(forward! <object>) 、first% 、rest% 和 <applicative> ;
5926+调用应用子 rest% 时不复制 <object> 或其子对象。
5927+参数指定的应用子的调用不添加或移除列表元素,否则行为未定义。
59265928 同 SRFI-1 的 fold-right ,但只接受一个真列表(@9.9.4) 。
59275929 名称中的 1 指 <list> 参数的个数。
59285930 map1 <applicative> <list> :单列表映射操作:使用指定应用子对列表中每个参数进行调用,结果为调用结果的列表。
59295931 参数 <applicative> 应接受一个参数,否则引起错误。
59305932 任意两个 <applicative> 调用的求值及列表构造操作的相对顺序未指定。
5933+<applicative> 的调用不添加或移除列表元素,否则行为未指定。
59315934 类似 Kernel 的 map ,但只接受一个真列表(@9.9.4) 。
59325935 first-null? <list> :复合 first 和 null? 操作。
59335936 可用于实现 nonfoldable?(@11.4.3) 的检查中的单个项。
@@ -5937,14 +5940,10 @@
59375940 list-concat <list1> <list2> :顺序连接两个列表。
59385941 append <list>... :顺序连接零个或多个列表。
59395942 若没有参数,结果为空列表。
5940-list-extract% <list> <applicative> :以指定应用子在指定列表中选取并合并内容为新的列表。
5941-对参数列表 (&l &extr) ,作用同求值:
5942-accr l null? () ($lambda% (&l) forward-first% extr (expire l)) rest% cons% ;
5943-其中,调用 forward-first% 的底层合并子的当前环境同调用 list-extract% 的动态环境。
5944-list-extract-first <list> :同指定应用子为 first 的 list-extract 。
5945-对参数列表 (&l &extr) ,结果同求值 list-extract l first 。
5946-list-extract-first-rest%! <list> :同指定应用子为 rest% 的 list-extract 。
5947-对参数列表 (&l &extr) ,结果同求值 list-extract l rest% 。
5943+list-extract-first <list> :以 first 在指定列表中选取并合并内容为新的列表。
5944+设参数列表 (&l) ,结果同在新环境中求值表达式 map1 first l ,其中 map1 和 first 是标准库函数。
5945+list-extract-rest%! <list> :以 rest% 在指定列表中选取并合并内容为新的列表。
5946+设参数列表 (&l) ,结果同在新环境中求值表达式 map1 rest% l ,其中 map1 和 rest% 是标准库函数。
59485947 $let <bindings> <body> :局部绑定求值:创建以当前环境为父环境的空环境,在其中添加 <bindings> 指定的变量绑定,再求值 <body> 。
59495948 类似 Kernel 的同名操作,但返回非引用值(@10.4.2) 。
59505949 创建的环境同合并子的局部环境(@8.4.5) 。
@@ -6205,7 +6204,8 @@
62056204 cons-cmd <string>... :串接命令。
62066205 参数指定构成命令的字符串。空字符串被忽略。结果是没有被忽略的字符串构成的串接,每个字符串附带一个后缀空格。
62076206 rmatch? <string1> <string2> :简单正则匹配。
6208-使用 std.strings(@12.3) 的操作,对参数列表 (x r) ,结果同求值 regex-match? x (string->regex r) 。
6207+使用 std.strings(@12.3) 的操作:
6208+设参数列表 (&x &r) ,结果同求值 regex-match? x (string->regex r) 。
62096209 putss <string>... :输出串接的字符串。
62106210 以 puts(@12.4) 输出参数字符串的串接结果。
62116211 system-ok <string> :调用外部命令并判断是否调用成功。
diff -r 37835df0ac3b -r dfccd642351f doc/Workflow.txt
--- a/doc/Workflow.txt Fri Mar 26 22:43:02 2021 +0800
+++ b/doc/Workflow.txt Wed Apr 14 12:24:53 2021 +0800
@@ -11,13 +11,13 @@
1111 /*! \file Workflow.txt
1212 \ingroup Documentation
1313 \brief 工作流汇总报告。
14-\version r4286
14+\version r4306
1515 \author FrankHB <frankhb1989@gmail.com>
1616 \since build 433
1717 \par 创建时间:
1818 2013-07-31 01:27:41 +0800
1919 \par 修改时间:
20- 2021-03-08 18:37 +0800
20+ 2021-04-10 08:51 +0800
2121 \par 文本编码:
2222 UTF-8
2323 \par 模块名称:
@@ -4246,5 +4246,27 @@
42464246 It requires to change the data structure of the internal representation of the term to allow partially reduction of a term.
42474247 All these changes are not trivial. It is not worth making a small improvement like this.
42484248
4249+$2021-04:
4250+
4251+report.impl:
4252+Several list operations of NPLA1 have been optimized with subtle semantic changes.
4253+ Requirements on applicatives called in 'foldr1' and 'map1' are refined.
4254+ As a precondition, they should not add or remove any elements, otherwise the behavior is undefined.
4255+ Disallowing the removal of elemetns guarantees no elements would be invalidated by the call.
4256+ This allows the using of '@' sigil to construct a list of uncollapsed reference values to access elements indirectly later in the derivation.
4257+ Disallowing the addition of elements further guarantees the stability of list element membership.
4258+ This allows using of iterators directly in native implementations, without differences to accessing the list of uncollapsed reference values.
4259+ Now they also do not use 'forward!', to allow copy elision of each element being constructed into the resulted list.
4260+ This also allows 'map1' to be an exact replacement of the old 'list-extract%' except that modifiable lvalue list arguments would not be expired.
4261+ Note that this is still compatible to the safety guarantee on cases like '$let () ($def! li list 1; map1 id li)'.
4262+ A bug of unexpected copies by 'rest%' in alternative derviation relying on 'foldr1' have been fixed.
4263+ The copies were not expected but allowed by the specification previously.
4264+ This was changed in the native implementations but not alternative derivations since build 913.
4265+ For list parameter '&l', replacing the argument of the call of 'accr' in 'foldr1' implementation with 'idv (forward! l)' should be sufficient to make these derivations equivalent to the native implementations.
4266+ Further, the implementations are optimized with semantic changes.
4267+ That is, the initial copy of the list parameter is avoided.
4268+ This is done by using '@' sigil for list element accesses in the derivations.
4269+ This also requires changes in the native implementations to keep them equivalent to the derivations.
4270+
42494271 ////
42504272
Show on old repository browser