The YSLib project - main repository
Revision | 220a0255d5fc7690b2b52ea03b38c446ef091989 (tree) |
---|---|
Time | 2022-06-15 02:36:26 |
Author | FrankHB <frankhb1989@gmai...> |
Commiter | FrankHB |
更新主分支版本: build 947 rev 10 。
@@ -154,8 +154,8 @@ | ||
154 | 154 | putss "Found SHBuild build directory \"" SHBuild_BuildDir "\"."; |
155 | 155 | $env-de! SHBuild ++ SR_Bin_ "/SHBuild"; |
156 | 156 | $assert-nonempty SHBuild; |
157 | - build-with-conf-opt (++ SHBuild_BuildDir "." SHBuild_Conf) host-os debug | |
158 | - dynamic "" #t ($if debug ld-ext-noadjust_ | |
157 | + build-with-conf-opt (++ SHBuild_BuildDir "." SHBuild_Conf) host-arch host-os | |
158 | + debug dynamic "" #t ($if debug ld-ext-noadjust_ | |
159 | 159 | ld-ext-adjust_win32_subsystem_) ($lambda (#ignore CXXFLAGS SHBOPT .) |
160 | 160 | ( |
161 | 161 | "TODO", "Support precompiled headers?"; |
@@ -104,6 +104,11 @@ | ||
104 | 104 | ++ SHBuild_BuildDir "/.shbuild" ($if dynamic "-dll" "") |
105 | 105 | ($if debug "-debug" ""); |
106 | 106 | |
107 | +$defl! host-build-with-conf-opt_ | |
108 | + (outdir debug dynamic shbopt-ext app do-ld-ext do-build) | |
109 | + build-with-conf-opt outdir host-arch host-os debug dynamic shbopt-ext app | |
110 | + do-ld-ext do-build; | |
111 | + | |
107 | 112 | SHBuild_EnsureDirectory_ SHBuild_BuildDir; |
108 | 113 | $defl! skip-or-build_ (nskip dynamic debug) $let |
109 | 114 | ( |
@@ -142,7 +147,7 @@ | ||
142 | 147 | "XXX", "No need to set %LDFLAGS, since it is always set in the", |
143 | 148 | " call to 'build-with-conf-opt' for dynamic libraries."; |
144 | 149 | $if dynamic (safeenv-restore "LIBS"); |
145 | - build-with-conf-opt outdir host-os debug dynamic | |
150 | + host-build-with-conf-opt_ outdir debug dynamic | |
146 | 151 | "-xid,alternative -xid,data -xid,include -xid,Android" #f |
147 | 152 | ld-ext-noadjust_ ($lambda (CXX CXXFLAGS SHBOPT LIBPFX) |
148 | 153 | ( |
@@ -336,8 +341,8 @@ | ||
336 | 341 | putss "Building " target-name " ..."; |
337 | 342 | $assert-absolute-path src-dir; |
338 | 343 | "XXX", "Extra options for SHBOPT are always empty now."; |
339 | - build-with-conf-opt SR_SHBuild_ host-os #f #t "" #t ld-ext-noadjust_ | |
340 | - ($lambda (CXX CXXFLAGS SHBOPT LIBPFX) | |
344 | + host-build-with-conf-opt_ SR_SHBuild_ #f #t "" #t | |
345 | + ld-ext-noadjust_ ($lambda (CXX CXXFLAGS SHBOPT LIBPFX) | |
341 | 346 | system-check (apply cons-cmd (append (list e_S1_SHBuild_ |
342 | 347 | src-dir SHBOPT) extra-opts (list CXXFLAGS INCLUDES_)))); |
343 | 348 | putss "Finished building " target-name "." |
@@ -366,7 +371,7 @@ | ||
366 | 371 | $def! tools-list list "RevisionPatcher" "SXML2XML" "ProjectGenerator"; |
367 | 372 | "XXX", "'SHBuild_BaseDir' is fixed in parallel to these directories of", |
368 | 373 | " these tools, while 'SHBuild_ToolDir' is expected more portable."; |
369 | - build-with-conf-opt SR_SHBuild_ host-os #f #t "" #t | |
374 | + host-build-with-conf-opt_ SR_SHBuild_ #f #t "" #t | |
370 | 375 | ld-ext-noadjust_ ($lambda (CXX CXXFLAGS SHBOPT LIBPFX) |
371 | 376 | for-each-ltr ($lambda (name) |
372 | 377 | system-check (apply cons-cmd (append |
@@ -382,8 +382,8 @@ | ||
382 | 382 | $defl! use-ubsan? (opt) use-fsanitize? "undefined" opt; |
383 | 383 | $defl! use-lsan? (opt) use-fsanitize? "leak" opt; |
384 | 384 | |
385 | -$defl! build-with-conf-opt (outdir host-os debug dynamic shbopt-ext app | |
386 | - do-ld-ext do-build) | |
385 | +$defl! build-with-conf-opt (outdir host-arch host-os debug dynamic shbopt-ext | |
386 | + app do-ld-ext do-build) | |
387 | 387 | ( |
388 | 388 | $import! std.strings string->symbol, |
389 | 389 | $import! std.promises $lazy force, |
@@ -464,18 +464,19 @@ | ||
464 | 464 | "CXXFLAGS_IMPL_WARNING" cons-cmd |
465 | 465 | "-Wconditionally-supported" "-Wno-noexcept-type" |
466 | 466 | "-Wstrict-null-sentinel" "-Wzero-as-null-pointer-constant"; |
467 | + $def! LTO_ $if ($and (win32? host-os) (eqv? host-arch "i686")) | |
468 | + "-flto=jobserver" "-flto=auto"; | |
467 | 469 | $redef! prom_CXXFLAGS_IMPL_OPT $lazy-env-val "CXXFLAGS_IMPL_OPT" |
468 | - cons-cmd "-fexpensive-optimizations" | |
469 | - ($if (win32? host-os) "-flto=auto" "-flto=jobserver") | |
470 | + cons-cmd "-fexpensive-optimizations" LTO_ | |
470 | 471 | "-fno-enforce-eh-specs"; |
471 | 472 | $if use-ld |
472 | 473 | ( |
473 | - "XXX", "Workaround for LTO bug on MinGW. See https://sourceware.org/bugzilla/show_bug.cgi?id=12762."; | |
474 | + "XXX", "Workaround for LTO bug on MinGW. See", | |
475 | + " https://sourceware.org/bugzilla/show_bug.cgi?id=12762."; | |
474 | 476 | $redef! prom_LDFLAGS_IMPL_OPT $lazy-env-val "LDFLAGS_IMPL_OPT" |
475 | - $if (win32? host-os) | |
476 | - (++ "-fexpensive-optimizations -flto=jobserver" | |
477 | - " -Wl,-allow-multiple-definition") | |
478 | - "-fexpensive-optimizations -flto=auto" | |
477 | + (++ "-fexpensive-optimizations " LTO_ | |
478 | + ($if (win32? host-os) " -Wl,-allow-multiple-definition" | |
479 | + "")) | |
479 | 480 | ) |
480 | 481 | )); |
481 | 482 | $def! prom_CFLAGS_STD $lazy-env-val "CFLAGS_STD" "-std=c11"; |
@@ -1,5 +1,5 @@ | ||
1 | 1 | #!/usr/bin/env bash |
2 | -# (C) 2014-2018, 2020-2021 FrankHB. | |
2 | +# (C) 2014-2018, 2020-2022 FrankHB. | |
3 | 3 | # Build script for SHBuild. |
4 | 4 | |
5 | 5 | set -e |
@@ -33,19 +33,28 @@ | ||
33 | 33 | |
34 | 34 | : "${SHBuild_Output:=SHBuild}" |
35 | 35 | |
36 | -# XXX: After MSYS2 enables ASLR by default, x86_64 binutils with g++ is buggy. | |
36 | +# XXX: After MSYS2 enabling ASLR by default, x86_64 binutils with g++ is buggy. | |
37 | 37 | # See https://www.msys2.org/news/#2021-01-31-aslr-enabled-by-default, |
38 | 38 | # https://github.com/msys2/MINGW-packages/issues/6986, |
39 | 39 | # https://github.com/msys2/MINGW-packages/issues/7023, |
40 | 40 | # and https://sourceware.org/bugzilla/show_bug.cgi?id=26659. Here is a |
41 | 41 | # workaround to the issue. |
42 | +# XXX: This is now fixed by https://github.com/msys2/MINGW-packages/pull/8259. | |
43 | +# TODO: Detect precise version? | |
44 | +# XXX: There are some other bugs not resolved for ld.bfd on PE targets: | |
45 | +# https://sourceware.org/bugzilla/show_bug.cgi?id=11539, | |
46 | +# https://sourceware.org/bugzilla/show_bug.cgi?id=19803. | |
42 | 47 | if [[ "$SHBuild_Host_OS" == 'Win32' && "$SHBuild_Host_Arch" == 'x86_64' \ |
43 | 48 | && "$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)" | |
49 | +# LDFLAGS_WKRD_="$(SHBuild_CheckCompiler "$CXX" \ | |
50 | +# 'int main(){}' -Wl,--default-image-base-low '' \ | |
51 | +# -xc++ -Wl,--default-image-base-low)" | |
52 | + # XXX: The linker (ld) from mingw-w64-x86_64-binutils 2.38-3 versions does | |
53 | + # not work otherwise. And mingw-w64-x86_64-lld-14.0.4-1 does not work with | |
54 | + # LTO here. | |
55 | + LDFLAGS_WKRD_='-fuse-ld=lld' | |
47 | 56 | else |
48 | - LDFLAGS_LOWBASE_= | |
57 | + LDFLAGS_WKRD_= | |
49 | 58 | fi |
50 | 59 | |
51 | 60 | SHBuild_Pushd . |
@@ -71,11 +80,11 @@ | ||
71 | 80 | # XXX: Value of several variables may contain whitespaces. |
72 | 81 | # shellcheck disable=2086 |
73 | 82 | SHBuild_Puts "$CXX" Main.cpp -o"$SHBuild_Output" $CXXFLAGS $LDFLAGS \ |
74 | - $LDFLAGS_LOWBASE_ $SHBuild_IncPCH $INCLUDES $LIBS | |
83 | + $LDFLAGS_WKRD_ $SHBuild_IncPCH $INCLUDES $LIBS | |
75 | 84 | fi |
76 | 85 | # XXX: Value of several variables may contain whitespaces. |
77 | 86 | # shellcheck disable=2086 |
78 | -"$CXX" Main.cpp -o"$SHBuild_Output" $CXXFLAGS $LDFLAGS $LDFLAGS_LOWBASE_ \ | |
87 | +"$CXX" Main.cpp -o"$SHBuild_Output" $CXXFLAGS $LDFLAGS $LDFLAGS_WKRD_ \ | |
79 | 88 | $SHBuild_IncPCH $INCLUDES $LIBS |
80 | 89 | |
81 | 90 | SHBuild_Popd |
@@ -115,7 +115,8 @@ | ||
115 | 115 | # LDFLAGS_IMPL_USE_LLD_=true |
116 | 116 | #: "${CXXFLAGS_IMPL_OPT:=-flto}" |
117 | 117 | #: "${LDFLAGS_IMPL_OPT:=-flto}" |
118 | - # XXX: LTO is disabled by default for compatibility to the prebuilt binaries. | |
118 | + # XXX: LTO is disabled by default for compatibility to the prebuilt | |
119 | + # binaries (by G++). | |
119 | 120 | elif [[ $SHBuild_CXX_Style_ == "G++" ]]; then |
120 | 121 | : "${C_CXXFLAGS_IMPL_WARNING:="-Wdouble-promotion \ |
121 | 122 | -Wlogical-op \ |
@@ -129,23 +130,27 @@ | ||
129 | 130 | -Wsuggest-final-types \ |
130 | 131 | -Wsuggest-final-methods \ |
131 | 132 | -Wzero-as-null-pointer-constant"}" |
132 | - if [[ "$SHBuild_Host_OS" == 'Win32' ]]; then | |
133 | - : "${CXXFLAGS_IMPL_OPT:="-fexpensive-optimizations \ | |
134 | --flto=jobserver \ | |
135 | --fno-enforce-eh-specs"}" | |
133 | + # XXX: %SHBuild_Host_OS and %SHBuild_host_Arch are external. | |
134 | + # shellcheck disable=2154 | |
135 | + # XXX: Only i686 MinGW32 uses old GCC not supporting -flto=auto now. | |
136 | + if [[ "$SHBuild_Host_OS" == 'Win32' && "$SHBuild_Host_Arch" == 'i686' ]]; \ | |
137 | +then | |
138 | + LTO_=-flto=jobserver | |
136 | 139 | else |
137 | - : "${CXXFLAGS_IMPL_OPT:="-fexpensive-optimizations \ | |
138 | --flto=auto \ | |
140 | + LTO_=-flto=auto | |
141 | + fi | |
142 | + : "${CXXFLAGS_IMPL_OPT:="-fexpensive-optimizations \ | |
143 | +$LTO_ \ | |
139 | 144 | -fno-enforce-eh-specs"}" |
140 | - fi | |
141 | - # XXX: Workarond for LTO bug on MinGW. See https://sourceware.org/bugzilla/show_bug.cgi?id=12762. | |
142 | 145 | # XXX: %SHBuild_Host_OS is external. |
143 | 146 | # shellcheck disable=2154 |
144 | 147 | if [[ "$SHBuild_Host_OS" == 'Win32' ]]; then |
145 | - : "${LDFLAGS_IMPL_OPT:="-fexpensive-optimizations -flto=jobserver \ | |
148 | + # XXX: Workarond for LTO bug on MinGW. See | |
149 | + # https://sourceware.org/bugzilla/show_bug.cgi?id=12762. | |
150 | + : "${LDFLAGS_IMPL_OPT:="-fexpensive-optimizations $LTO_ \ | |
146 | 151 | -Wl,-allow-multiple-definition"}" |
147 | 152 | else |
148 | - : "${LDFLAGS_IMPL_OPT:=-fexpensive-optimizations -flto=auto}" | |
153 | + : "${LDFLAGS_IMPL_OPT:=-fexpensive-optimizations $LTO_}" | |
149 | 154 | fi |
150 | 155 | fi |
151 | 156 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r9468 | |
14 | +\version r9543 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 663 |
17 | 17 | \par 创建时间: |
18 | 18 | 2016-01-07 10:32:34 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-05-08 16:16 +0800 | |
20 | + 2022-06-14 18:41 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -36,16 +36,16 @@ | ||
36 | 36 | // ystdex::is_nothrow_copy_constructible, ystdex::is_nothrow_copy_assignable, |
37 | 37 | // ystdex::is_nothrow_move_constructible, ystdex::is_nothrow_move_assignable, |
38 | 38 | // EnsureValueTags, AssertValueTags, IsTyped, ThrowListTypeErrorForInvalidType, |
39 | -// observer_ptr, TryAccessValue, IsLeaf, ystdex::equality_comparable, weak_ptr, | |
40 | -// lref, ystdex::get_equal_to, NPL::IsMovable, pair, ystdex::invoke_value_or, | |
41 | -// ystdex::expand_proxy, NPL::Access, ystdex::ref_eq, ValueObject, | |
42 | -// NPL::SetContentWith, std::for_each, AccessFirstSubterm, AssertBranch, | |
43 | -// NPL::Deref, YSLib::EmplaceCallResult, ystdex::less, YSLib::map, pmr, | |
44 | -// ystdex::copy_and_swap, NoContainer, ystdex::try_emplace, | |
45 | -// ystdex::try_emplace_hint, ystdex::insert_or_assign, type_info, | |
46 | -// ystdex::expanded_function, ystdex::enable_if_same_param_t, | |
39 | +// observer_ptr, TryAccessValue, IsAtom, IsLeaf, ystdex::equality_comparable, | |
40 | +// weak_ptr, lref, AssertReferentTags, ystdex::get_equal_to, NPL::IsMovable, | |
41 | +// pair, std::declval, ystdex::invoke_value_or, ystdex::expand_proxy, | |
42 | +// Access, ystdex::ref_eq, ValueObject, NPL::SetContentWith, std::for_each, | |
43 | +// AccessFirstSubterm, AssertBranch, NPL::Deref, YSLib::EmplaceCallResult, | |
44 | +// ystdex::less, YSLib::map, pmr, ystdex::copy_and_swap, NoContainer, | |
45 | +// ystdex::try_emplace, ystdex::try_emplace_hint, ystdex::insert_or_assign, | |
46 | +// type_info, ystdex::expanded_function, ystdex::enable_if_same_param_t, | |
47 | 47 | // ystdex::exclude_self_t, ystdex::make_obj_using_allocator, |
48 | -// YSLib::forward_list, ystdex::swap_dependent, NPL::make_observer, | |
48 | +// YSLib::forward_list, ystdex::swap_dependent, make_observer, | |
49 | 49 | // YSLib::allocate_shared, YSLib::Logger, trivial_swap, ystdex::exchange, |
50 | 50 | // NPL::AsTermNode, ystdex::is_bitwise_swappable; |
51 | 51 | #include <ystdex/base.h> // for ystdex::derived_entity; |
@@ -112,7 +112,7 @@ | ||
112 | 112 | /*! |
113 | 113 | \brief 转义 NPLA 节点字面量。 |
114 | 114 | \return 调用 EscapeLiteral 转义访问字符串的结果。 |
115 | -\exception bad_any_cast 异常中立:由 NPL::Access 抛出。 | |
115 | +\exception bad_any_cast 异常中立:由 Access 抛出。 | |
116 | 116 | \since build 597 |
117 | 117 | */ |
118 | 118 | YB_ATTR_nodiscard YF_API YB_PURE string |
@@ -498,15 +498,15 @@ | ||
498 | 498 | \note 第一参数是可能带有 const 的左值的 TermNode 或转换为 TermNode 的类型。 |
499 | 499 | \sa ThrowListTypeErrorForInvalidType |
500 | 500 | |
501 | -以 NPL::Access 访问调用 NPL::CheckRegular 检查后的项。 | |
501 | +以 Access 访问调用 NPL::CheckRegular 检查后的项。 | |
502 | 502 | */ |
503 | 503 | template<typename _type, class _tTerm> |
504 | 504 | YB_ATTR_nodiscard YB_PURE inline auto |
505 | 505 | AccessRegular(_tTerm& term, bool has_ref) |
506 | - -> yimpl(decltype(NPL::Access<_type>(term))) | |
506 | + -> yimpl(decltype(Access<_type>(term))) | |
507 | 507 | { |
508 | 508 | NPL::CheckRegular<_type>(term, has_ref); |
509 | - return NPL::Access<_type>(term); | |
509 | + return Access<_type>(term); | |
510 | 510 | } |
511 | 511 | //@} |
512 | 512 |
@@ -541,10 +541,33 @@ | ||
541 | 541 | //@} |
542 | 542 | |
543 | 543 | /*! |
544 | +\brief 尝试访问不构成有序对的节点的指定类型对象指针。 | |
545 | +\sa IsAtom | |
546 | +\sa TryAccessLeafAtom | |
547 | +\since build 947 | |
548 | + | |
549 | +尝试排除有序对并访问作为叶节点的 TermNode 。 | |
550 | +*/ | |
551 | +//@{ | |
552 | +template<typename _type> | |
553 | +YB_ATTR_nodiscard YB_PURE inline observer_ptr<_type> | |
554 | +TryAccessLeafAtom(TermNode& term) | |
555 | +{ | |
556 | + return IsAtom(term) ? TryAccessLeaf<_type>(term) : nullptr; | |
557 | +} | |
558 | +template<typename _type> | |
559 | +YB_ATTR_nodiscard YB_PURE inline observer_ptr<const _type> | |
560 | +TryAccessLeafAtom(const TermNode& term) | |
561 | +{ | |
562 | + return IsAtom(term) ? TryAccessLeaf<_type>(term) : nullptr; | |
563 | +} | |
564 | +//@} | |
565 | + | |
566 | +/*! | |
544 | 567 | \brief 尝试访问项的指定类型叶节点对象指针。 |
545 | 568 | |
546 | 569 | 尝试访问 TermNode 。 |
547 | -类似 NPL::TryAccessLeaf ,但先使用 NPL::IsLeaf 判断叶节点, | |
570 | +类似 TryAccessLeaf ,但先使用 NPL::IsLeaf 判断叶节点, | |
548 | 571 | 对非叶节点直接返回空指针。 |
549 | 572 | */ |
550 | 573 | //@{ |
@@ -552,13 +575,13 @@ | ||
552 | 575 | YB_ATTR_nodiscard YB_PURE inline observer_ptr<_type> |
553 | 576 | TryAccessTerm(TermNode& term) |
554 | 577 | { |
555 | - return IsLeaf(term) ? NPL::TryAccessLeaf<_type>(term) : nullptr; | |
578 | + return IsLeaf(term) ? TryAccessLeaf<_type>(term) : nullptr; | |
556 | 579 | } |
557 | 580 | template<typename _type> |
558 | 581 | YB_ATTR_nodiscard YB_PURE inline observer_ptr<const _type> |
559 | 582 | TryAccessTerm(const TermNode& term) |
560 | 583 | { |
561 | - return IsLeaf(term) ? NPL::TryAccessLeaf<_type>(term) : nullptr; | |
584 | + return IsLeaf(term) ? TryAccessLeaf<_type>(term) : nullptr; | |
562 | 585 | } |
563 | 586 | //@} |
564 | 587 | //@} |
@@ -571,7 +594,7 @@ | ||
571 | 594 | */ |
572 | 595 | YB_ATTR_nodiscard YB_PURE inline |
573 | 596 | PDefH(observer_ptr<const TokenValue>, TermToNamePtr, const TermNode& term) |
574 | - ImplRet(NPL::TryAccessTerm<TokenValue>(term)) | |
597 | + ImplRet(TryAccessTerm<TokenValue>(term)) | |
575 | 598 | |
576 | 599 | /*! |
577 | 600 | \return 转换得到的字符串。 |
@@ -600,9 +623,11 @@ | ||
600 | 623 | |
601 | 624 | /*! |
602 | 625 | \brief 访问项初始化标签。 |
603 | -\since build 857 | |
626 | +\pre 参数的标签可表示被引用对象。 | |
627 | +\sa AssertReferentTags | |
604 | 628 | \sa GetLValueTagsOf |
605 | 629 | \sa TermTags |
630 | +\since build 857 | |
606 | 631 | |
607 | 632 | 若项表示引用值,使用引用值排除 TermTags::Temporary 后的标签; |
608 | 633 | 否则,使用项的标签。 |
@@ -796,6 +821,7 @@ | ||
796 | 821 | lref<TermNode> term_ref; |
797 | 822 | /*! |
798 | 823 | \brief 引用标签。 |
824 | + \invariant \c IsReferentTags(tags) 。 | |
799 | 825 | \since build 857 |
800 | 826 | */ |
801 | 827 | TermTags tags = TermTags::Unqualified; |
@@ -816,6 +842,8 @@ | ||
816 | 842 | : TermReference(TermToTags(term), term, yforward(arg), |
817 | 843 | yforward(args)...) |
818 | 844 | {} |
845 | + //! \pre 第一参数可表示被引用对象。 | |
846 | + //@{ | |
819 | 847 | /*! |
820 | 848 | \brief 构造:使用参数指定的标签及引用。 |
821 | 849 | \since build 894 |
@@ -824,7 +852,7 @@ | ||
824 | 852 | inline |
825 | 853 | TermReference(TermTags t, TermNode& term, _tParam&& arg, _tParams&&... args) |
826 | 854 | ynothrow |
827 | - : term_ref(term), tags(t), | |
855 | + : term_ref(term), tags((AssertReferentTags(t), t)), | |
828 | 856 | r_env(yforward(arg), yforward(args)...) |
829 | 857 | {} |
830 | 858 | /*! |
@@ -833,12 +861,15 @@ | ||
833 | 861 | */ |
834 | 862 | //@{ |
835 | 863 | TermReference(TermTags t, const TermReference& ref) ynothrow |
836 | - : term_ref(ref.term_ref), tags(t), r_env(ref.r_env) | |
864 | + : term_ref(ref.term_ref), tags((AssertReferentTags(t), t)), | |
865 | + r_env(ref.r_env) | |
837 | 866 | {} |
838 | 867 | TermReference(TermTags t, TermReference&& ref) ynothrow |
839 | - : term_ref(ref.term_ref), tags(t), r_env(std::move(ref.r_env)) | |
868 | + : term_ref(ref.term_ref), tags((AssertReferentTags(t), t)), | |
869 | + r_env(std::move(ref.r_env)) | |
840 | 870 | {} |
841 | 871 | //@} |
872 | + //@} | |
842 | 873 | //! \since build 855 |
843 | 874 | DefDeCopyMoveCtorAssignment(TermReference) |
844 | 875 |
@@ -990,18 +1021,19 @@ | ||
990 | 1021 | \brief 访问项并取解析 TermReference 间接值后的引用。 |
991 | 1022 | \return 若项的 Value 数据成员为 TermReference 则为其中的引用,否则为参数。 |
992 | 1023 | \sa TermReference |
1024 | +\sa TryAccessLeafAtom | |
993 | 1025 | \since build 854 |
994 | 1026 | */ |
995 | 1027 | YB_ATTR_nodiscard YB_PURE inline |
996 | 1028 | PDefH(TermNode&, ReferenceTerm, TermNode& term) |
997 | 1029 | ynoexcept_spec(std::declval<TermReference>().get()) |
998 | 1030 | ImplRet(ystdex::invoke_value_or(&TermReference::get, |
999 | - NPL::TryAccessLeaf<const TermReference>(term), term)) | |
1031 | + TryAccessLeafAtom<TermReference>(term), term)) | |
1000 | 1032 | YB_ATTR_nodiscard YB_PURE inline |
1001 | 1033 | PDefH(const TermNode&, ReferenceTerm, const TermNode& term) |
1002 | - ynoexcept_spec(std::declval<TermReference>().get()) | |
1034 | + ynoexcept_spec(std::declval<const TermReference>().get()) | |
1003 | 1035 | ImplRet(ystdex::invoke_value_or(&TermReference::get, |
1004 | - NPL::TryAccessLeaf<const TermReference>(term), term)) | |
1036 | + TryAccessLeafAtom<const TermReference>(term), term)) | |
1005 | 1037 | |
1006 | 1038 | /*! |
1007 | 1039 | \ingroup functors |
@@ -1098,7 +1130,7 @@ | ||
1098 | 1130 | //@{ |
1099 | 1131 | /*! |
1100 | 1132 | \sa NPL::ReferenceTerm |
1101 | -\sa NPL::TryAccessLeaf | |
1133 | +\sa TryAccessLeaf | |
1102 | 1134 | \since build 854 |
1103 | 1135 | */ |
1104 | 1136 | //@{ |
@@ -1106,18 +1138,18 @@ | ||
1106 | 1138 | YB_ATTR_nodiscard YB_PURE inline observer_ptr<_type> |
1107 | 1139 | TryAccessReferencedLeaf(TermNode& term) |
1108 | 1140 | { |
1109 | - return NPL::TryAccessLeaf<_type>(ReferenceTerm(term)); | |
1141 | + return TryAccessLeafAtom<_type>(ReferenceTerm(term)); | |
1110 | 1142 | } |
1111 | 1143 | template<typename _type> |
1112 | 1144 | YB_ATTR_nodiscard YB_PURE inline observer_ptr<const _type> |
1113 | 1145 | TryAccessReferencedLeaf(const TermNode& term) |
1114 | 1146 | { |
1115 | - return NPL::TryAccessLeaf<_type>(ReferenceTerm(term)); | |
1147 | + return TryAccessLeafAtom<_type>(ReferenceTerm(term)); | |
1116 | 1148 | } |
1117 | 1149 | //@} |
1118 | 1150 | |
1119 | 1151 | /*! |
1120 | -\sa NPL::TryAccessTerm | |
1152 | +\sa TryAccessTerm | |
1121 | 1153 | \since build 858 |
1122 | 1154 | */ |
1123 | 1155 | //@{ |
@@ -1125,18 +1157,18 @@ | ||
1125 | 1157 | YB_ATTR_nodiscard YB_PURE inline observer_ptr<_type> |
1126 | 1158 | TryAccessReferencedTerm(TermNode& term) |
1127 | 1159 | { |
1128 | - return NPL::TryAccessTerm<_type>(ReferenceTerm(term)); | |
1160 | + return TryAccessTerm<_type>(ReferenceTerm(term)); | |
1129 | 1161 | } |
1130 | 1162 | template<typename _type> |
1131 | 1163 | YB_ATTR_nodiscard YB_PURE inline observer_ptr<const _type> |
1132 | 1164 | TryAccessReferencedTerm(const TermNode& term) |
1133 | 1165 | { |
1134 | - return NPL::TryAccessTerm<_type>(ReferenceTerm(term)); | |
1166 | + return TryAccessTerm<_type>(ReferenceTerm(term)); | |
1135 | 1167 | } |
1136 | 1168 | //@} |
1137 | 1169 | //@} |
1138 | 1170 | |
1139 | -//! \note 使用 NPL::TryAccessLeaf 访问。 | |
1171 | +//! \note 使用 TryAccessLeaf 访问。 | |
1140 | 1172 | //@{ |
1141 | 1173 | /*! |
1142 | 1174 | \brief 判断项(的值数据成员)是否为引用项。 |
@@ -1196,6 +1228,7 @@ | ||
1196 | 1228 | \sa ResolveTermHandler |
1197 | 1229 | \sa ResolvedTermReferencePtr |
1198 | 1230 | \sa TermReference |
1231 | +\sa TryAccessLeafAtom | |
1199 | 1232 | |
1200 | 1233 | 接受指定解析实现的函数和被解析的项作为参数,尝试访问其中是否具有引用值。 |
1201 | 1234 | 若确定是引用值,则被引用的项是被引用值引用的项;否则,被引用的项是第二参数指定的项。 |
@@ -1219,9 +1252,11 @@ | ||
1219 | 1252 | using handler_t = yimpl(void)(_tTerm&&, ResolvedTermReferencePtr); |
1220 | 1253 | |
1221 | 1254 | // XXX: Assume value representation of %term is not trivially regular. |
1222 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(term)) | |
1255 | + if(const auto p = TryAccessLeafAtom<const TermReference>(term)) | |
1256 | + { | |
1223 | 1257 | return ystdex::expand_proxy<handler_t>::call(do_resolve, p->get(), |
1224 | 1258 | NPL::ResolveToTermReferencePtr(p)); |
1259 | + } | |
1225 | 1260 | return ystdex::expand_proxy<handler_t>::call(do_resolve, |
1226 | 1261 | yforward(term), ResolvedTermReferencePtr()); |
1227 | 1262 | } |
@@ -1230,10 +1265,10 @@ | ||
1230 | 1265 | \brief 访问一次解析引用值后的项的指定类型正规值。 |
1231 | 1266 | \exception ListTypeError 异常中立:项为列表项。 |
1232 | 1267 | \exception bad_any_cast 异常中立:非列表项类型检查失败。 |
1233 | -\sa NPL::AccessRegular | |
1268 | +\sa AccessRegular | |
1234 | 1269 | \sa NPL::ResolveTerm |
1235 | 1270 | |
1236 | -以 NPL::AccessRegular 访问调用 NPL::ResolveTerm 解析引用值得到的项。 | |
1271 | +以 AccessRegular 访问调用 NPL::ResolveTerm 解析引用值得到的项。 | |
1237 | 1272 | 若遇到正规值为引用值,则进行解引用后继续访问。解引用至多一次。 |
1238 | 1273 | 和 YSLib::Access 访问 ValueNode 类似,但调用 NPL::ResolveTerm |
1239 | 1274 | 解析引用重定向到目标,且首先对检查项,若项为列表项使用 |
@@ -1241,11 +1276,11 @@ | ||
1241 | 1276 | */ |
1242 | 1277 | template<typename _type, class _tTerm> |
1243 | 1278 | YB_ATTR_nodiscard YB_PURE inline auto |
1244 | -ResolveRegular(_tTerm& term) -> yimpl(decltype(NPL::Access<_type>(term))) | |
1279 | +ResolveRegular(_tTerm& term) -> yimpl(decltype(Access<_type>(term))) | |
1245 | 1280 | { |
1246 | 1281 | return NPL::ResolveTerm([&](_tTerm& nd, bool has_ref) |
1247 | - -> yimpl(decltype(NPL::Access<_type>(term))){ | |
1248 | - return NPL::AccessRegular<_type>(nd, has_ref); | |
1282 | + -> yimpl(decltype(Access<_type>(term))){ | |
1283 | + return AccessRegular<_type>(nd, has_ref); | |
1249 | 1284 | }, term); |
1250 | 1285 | } |
1251 | 1286 | //@} |
@@ -1273,7 +1308,7 @@ | ||
1273 | 1308 | template<class _tTerm> |
1274 | 1309 | YB_ATTR_nodiscard YB_PURE inline auto |
1275 | 1310 | operator()(_tTerm& term) const |
1276 | - -> yimpl(decltype(NPL::Access<_type>(term))) | |
1311 | + -> yimpl(decltype(Access<_type>(term))) | |
1277 | 1312 | { |
1278 | 1313 | return NPL::ResolveRegular<_type>(term); |
1279 | 1314 | } |
@@ -1332,7 +1367,7 @@ | ||
1332 | 1367 | { |
1333 | 1368 | return NPL::ResolveTerm([](_tTerm& nd, ResolvedTermReferencePtr p_ref){ |
1334 | 1369 | return ResolvedArg<_type>( |
1335 | - NPL::AccessRegular<_type>(nd, p_ref), p_ref); | |
1370 | + AccessRegular<_type>(nd, p_ref), p_ref); | |
1336 | 1371 | }, term); |
1337 | 1372 | } |
1338 | 1373 | }; |
@@ -2408,6 +2443,8 @@ | ||
2408 | 2443 | void |
2409 | 2444 | clear() ynothrow |
2410 | 2445 | { |
2446 | + // XXX: There is generally no more efficient implementation using | |
2447 | + // iterator explicitly for %forward_list. | |
2411 | 2448 | while(!empty()) |
2412 | 2449 | pop_front(); |
2413 | 2450 | } |
@@ -2437,7 +2474,7 @@ | ||
2437 | 2474 | |
2438 | 2475 | public: |
2439 | 2476 | ReductionGuard(ContextNode& ctx) ynothrow |
2440 | - : p_ctx(NPL::make_observer(&ctx)), i_stacked(ctx.stacked.cbegin()) | |
2477 | + : p_ctx(make_observer(&ctx)), i_stacked(ctx.stacked.cbegin()) | |
2441 | 2478 | { |
2442 | 2479 | ctx.stacked.splice_after(ctx.stacked.cbefore_begin(), |
2443 | 2480 | ctx.current); |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 公共接口。 |
14 | -\version r9469 | |
14 | +\version r9480 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 472 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-02-02 17:58:24 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-05-30 18:54 +0800 | |
20 | + 2022-06-14 18:41 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -32,7 +32,7 @@ | ||
32 | 32 | #include YFM_NPL_NPLA // for NPLATag, TermNode, ContextNode, |
33 | 33 | // ystdex::equality_comparable, std::declval, ystdex::exclude_self_t, |
34 | 34 | // trivial_swap_t, trivial_swap, ystdex::ref_eq, string_view, |
35 | -// CombineReductionResult, pmr::memory_resource, NPL::make_observer, | |
35 | +// CombineReductionResult, pmr::memory_resource, make_observer, | |
36 | 36 | // AssertMatchedAllocators, TNIter, LiftOtherValue, ValueNode, NPL::Deref, |
37 | 37 | // NPL::AsTermNode, std::make_move_iterator, std::next, ystdex::retry_on_cond, |
38 | 38 | // std::find_if, ystdex::exclude_self_params_t, YSLib::AreEqualHeld, |
@@ -388,14 +388,14 @@ | ||
388 | 388 | \since build 895 |
389 | 389 | */ |
390 | 390 | PDefH(void, SetCombiningTermRef, TermNode& term) ynothrow |
391 | - ImplExpr(combining_term_ptr = NPL::make_observer(&term)) | |
391 | + ImplExpr(combining_term_ptr = make_observer(&term)) | |
392 | 392 | /*! |
393 | 393 | \brief 设置下一求值项引用。 |
394 | 394 | \sa next_term_ptr |
395 | 395 | \since build 883 |
396 | 396 | */ |
397 | 397 | PDefH(void, SetNextTermRef, TermNode& term) ynothrow |
398 | - ImplExpr(next_term_ptr = NPL::make_observer(&term)) | |
398 | + ImplExpr(next_term_ptr = make_observer(&term)) | |
399 | 399 | |
400 | 400 | /*! |
401 | 401 | \brief 清除规约合并项指针。 |
@@ -1371,7 +1371,7 @@ | ||
1371 | 1371 | // NOTE: This is optional, as it is not guaranteed to be saved as |
1372 | 1372 | // %ContextHandler in %ReduceCombined. |
1373 | 1373 | ImplExpr([&]{ |
1374 | - if(const auto p_handler = NPL::TryAccessTerm<const LiteralHandler>(tm)) | |
1374 | + if(const auto p_handler = TryAccessTerm<const LiteralHandler>(tm)) | |
1375 | 1375 | RegularizeTerm(term, (*p_handler)(ctx)); |
1376 | 1376 | }()) |
1377 | 1377 |
@@ -1800,10 +1800,10 @@ | ||
1800 | 1800 | \note 当参数指定 TCO 时且保存记号值时保存的值即为名称,否则名称不存在。 |
1801 | 1801 | \return 若存在名称则为内部保存的名称字符串,否则是数据指针为空的结果。 |
1802 | 1802 | \note 仅在 TCO 动作存在时支持。 |
1803 | -\since build 896 | |
1803 | +\since build 947 | |
1804 | 1804 | */ |
1805 | 1805 | YB_ATTR_nodiscard YF_API observer_ptr<const ValueObject> |
1806 | -QueryTailOperatorName(const Reducer&); | |
1806 | +QueryTailOperatorName(const Reducer&) ynothrow; | |
1807 | 1807 | |
1808 | 1808 | /*! |
1809 | 1809 | \brief 查询全局类型名称表。 |
@@ -1817,13 +1817,13 @@ | ||
1817 | 1817 | \return 是否成功。 |
1818 | 1818 | \warning 若不满足上下文状态类型要求,行为未定义。 |
1819 | 1819 | \sa ContextState::GetCombiningTermPtr |
1820 | -\since build 896 | |
1820 | +\since build 947 | |
1821 | 1821 | |
1822 | 1822 | 检查第一参数指定的项是否同第二参数保存的规约合并项的第一项,若成功视为操作符项, |
1823 | 1823 | 并转移操作符项的值数据成员到规约合并项。 |
1824 | 1824 | */ |
1825 | -YF_API bool | |
1826 | -SetupTailOperatorName(TermNode&, const ContextNode&); | |
1825 | +bool | |
1826 | +SetupTailOperatorName(TermNode&, const ContextNode&) ynothrow; | |
1827 | 1827 | |
1828 | 1828 | /*! |
1829 | 1829 | \brief 追踪记录 NPL 续延。 |
@@ -2234,7 +2234,9 @@ | ||
2234 | 2234 | \brief 尝试加载源代码。 |
2235 | 2235 | \exception NPLException 嵌套异常:加载失败。 |
2236 | 2236 | \note 第二参数表示来源,仅用于诊断消息。 |
2237 | +\note 不使用可能自定义的 REPLContext::Load 。 | |
2237 | 2238 | \relates REPLContext |
2239 | +\sa REPLContext::LoadFrom | |
2238 | 2240 | \since build 838 |
2239 | 2241 | */ |
2240 | 2242 | template<typename... _tParams> |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Forms.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 语法形式。 |
14 | -\version r8723 | |
14 | +\version r8742 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 882 |
17 | 17 | \par 创建时间: |
18 | 18 | 2020-02-15 11:19:21 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-04-25 18:07 +0800 | |
20 | + 2022-06-14 18:32 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -31,11 +31,10 @@ | ||
31 | 31 | #include "YModules.h" |
32 | 32 | #include YFM_NPL_NPLA1 // for shared_ptr, TermNode, ReductionStatus, string, |
33 | 33 | // TokenValue, AssertBranch, ystdex::exclude_self_t, ystdex::expand_proxy, |
34 | -// NPL::ResolveTerm, std::next, NPL::Access, NPL::Deref, | |
35 | -// Forms::CallResolvedUnary, ResolvedTermReferencePtr, NPL::AccessRegular, | |
36 | -// ystdex::make_expanded, std::ref, ystdex::invoke_nonvoid, TNIter, | |
37 | -// NPL::AccessTypedValue, ystdex::make_transform, std::accumulate, | |
38 | -// std::placeholders::_2, ystdex::bind1, ContextNode, | |
34 | +// NPL::ResolveTerm, std::next, Access, NPL::Deref, Forms::CallResolvedUnary, | |
35 | +// ResolvedTermReferencePtr, AccessRegular, ystdex::make_expanded, std::ref, | |
36 | +// ystdex::invoke_nonvoid, TNIter, AccessTypedValue, ystdex::make_transform, | |
37 | +// std::accumulate, std::placeholders::_2, ystdex::bind1, ContextNode, | |
39 | 38 | // ystdex::equality_comparable, ystdex::exclude_self_params_t, |
40 | 39 | // ystdex::examiners::equal_examiner, trivial_swap_t, trivial_swap, |
41 | 40 | // Environment, ystdex::is_bitwise_swappable, ystdex::true_; |
@@ -53,7 +52,7 @@ | ||
53 | 52 | \sa Continuation |
54 | 53 | \since build 943 |
55 | 54 | |
56 | -若定义为 true ,则在续延调用时断言被捕获的帧在当前动作序列中存在。 | |
55 | +若定义为 true ,则在续延调用时断言被捕获的帧在当前动作序列中存在且满足实现约束。 | |
57 | 56 | */ |
58 | 57 | #ifndef NPL_NPLA1Forms_CheckContinuationFrames |
59 | 58 | # ifndef NDEBUG |
@@ -302,7 +301,7 @@ | ||
302 | 301 | inline auto |
303 | 302 | CallResolvedUnaryAs(_func&& f, TermNode& term, _tParams&&... args) |
304 | 303 | -> yimpl(decltype(ystdex::expand_proxy<void(_type&, const |
305 | - ResolvedTermReferencePtr&, _tParams&&...)>::call(f, NPL::Access<_type>( | |
304 | + ResolvedTermReferencePtr&, _tParams&&...)>::call(f, Access<_type>( | |
306 | 305 | term), ResolvedTermReferencePtr(), std::forward<_tParams>(args)...))) |
307 | 306 | { |
308 | 307 | using handler_t |
@@ -314,21 +313,21 @@ | ||
314 | 313 | -> decltype(ystdex::expand_proxy<handler_t>::call(f, |
315 | 314 | std::declval<_type&>(), p_ref)){ |
316 | 315 | // XXX: Blocked. 'yforward' cause G++ 7.1.0 failed silently. |
317 | - return ystdex::expand_proxy<handler_t>::call(f, NPL::Access<_type>(nd), | |
316 | + return ystdex::expand_proxy<handler_t>::call(f, Access<_type>(nd), | |
318 | 317 | p_ref, std::forward<_tParams>(args)...); |
319 | 318 | }, term); |
320 | 319 | } |
321 | 320 | |
322 | 321 | /*! |
323 | 322 | \note 访问节点的子节点,以正规值调用一元函数。 |
324 | -\sa NPL::AccessRegular | |
323 | +\sa AccessRegular | |
325 | 324 | \exception ListTypeError 异常中立:项为列表项。 |
326 | 325 | */ |
327 | 326 | template<typename _type, typename _func, typename... _tParams> |
328 | 327 | inline auto |
329 | 328 | CallRegularUnaryAs(_func&& f, TermNode& term, _tParams&&... args) |
330 | 329 | -> yimpl(decltype(ystdex::expand_proxy<void(_type&, const |
331 | - ResolvedTermReferencePtr&, _tParams&&...)>::call(f, NPL::Access<_type>( | |
330 | + ResolvedTermReferencePtr&, _tParams&&...)>::call(f, Access<_type>( | |
332 | 331 | term), ResolvedTermReferencePtr(), std::forward<_tParams>(args)...))) |
333 | 332 | { |
334 | 333 | using handler_t |
@@ -340,7 +339,7 @@ | ||
340 | 339 | -> decltype(ystdex::expand_proxy<handler_t>::call(f, |
341 | 340 | std::declval<_type&>(), p_ref)){ |
342 | 341 | // XXX: Blocked. 'yforward' cause G++ 7.1.0 failed silently. |
343 | - return ystdex::expand_proxy<handler_t>::call(f, NPL::AccessRegular< | |
342 | + return ystdex::expand_proxy<handler_t>::call(f, AccessRegular< | |
344 | 343 | _type>(nd, p_ref), p_ref, std::forward<_tParams>(args)...); |
345 | 344 | }, term); |
346 | 345 | } |
@@ -381,8 +380,8 @@ | ||
381 | 380 | // XXX: This is a bit more efficient than directly use of |
382 | 381 | // %ystdex::expand_proxy for G++. |
383 | 382 | return ystdex::make_expanded<void(decltype( |
384 | - NPL::AccessTypedValue<_type>(tm)), _tParams&&...)>(std::ref(f))( | |
385 | - NPL::AccessTypedValue<_type>(tm), std::forward<_tParams>(args)...); | |
383 | + AccessTypedValue<_type>(tm)), _tParams&&...)>(std::ref(f))( | |
384 | + AccessTypedValue<_type>(tm), std::forward<_tParams>(args)...); | |
386 | 385 | }, term); |
387 | 386 | } |
388 | 387 | //@} |
@@ -410,12 +409,12 @@ | ||
410 | 409 | RetainN(term, 2); |
411 | 410 | |
412 | 411 | auto i(term.begin()); |
413 | - auto&& x(NPL::AccessTypedValue<_type>(NPL::Deref(++i))); | |
412 | + auto&& x(AccessTypedValue<_type>(NPL::Deref(++i))); | |
414 | 413 | |
415 | 414 | return NPL::EmplaceCallResultOrReturn(term, ystdex::invoke_nonvoid( |
416 | 415 | ystdex::make_expanded<void(decltype(x), decltype( |
417 | - NPL::AccessTypedValue<_type2>(*i)), _tParams&&...)>(std::ref(f)), | |
418 | - yforward(x), NPL::AccessTypedValue<_type2>(NPL::Deref(++i)), | |
416 | + AccessTypedValue<_type2>(*i)), _tParams&&...)>(std::ref(f)), | |
417 | + yforward(x), AccessTypedValue<_type2>(NPL::Deref(++i)), | |
419 | 418 | yforward(args)...)); |
420 | 419 | } |
421 | 420 | //@} |
@@ -432,7 +431,7 @@ | ||
432 | 431 | const auto n(FetchArgumentN(term)); |
433 | 432 | auto i(term.begin()); |
434 | 433 | const auto j(ystdex::make_transform(++i, [](TNIter it){ |
435 | - return NPL::AccessTypedValue<_type>(NPL::Deref(it)); | |
434 | + return AccessTypedValue<_type>(NPL::Deref(it)); | |
436 | 435 | })); |
437 | 436 | |
438 | 437 | return NPL::EmplaceCallResultOrReturn(term, std::accumulate(j, std::next( |
@@ -856,7 +855,6 @@ | ||
856 | 855 | \since build 779 |
857 | 856 | |
858 | 857 | 按值传递返回值。构造的对象中的元素转换为右值。 |
859 | -替代引用值通过 NPL::LiftSubtermsToReturn(@6.6.2) 提升求值后的项的每个子项实现。 | |
860 | 858 | |
861 | 859 | 参考调用文法: |
862 | 860 | <pre>cons \<object> \<list></pre> |
@@ -1035,7 +1033,6 @@ | ||
1035 | 1033 | \sa LiftSubtermsToReturn |
1036 | 1034 | |
1037 | 1035 | 第二参数的元素转换为右值。 |
1038 | -替代引用值通过 LiftSubtermsToReturn 插入第一个元素前的每个子项实现。 | |
1039 | 1036 | |
1040 | 1037 | 参考调用文法: |
1041 | 1038 | <pre>set-rest! \<list> \<object></pre> |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file SContext.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief S 表达式上下文。 |
14 | -\version r4233 | |
14 | +\version r4421 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 304 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-08-03 19:55:41 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-04-28 03:46 +0800 | |
20 | + 2022-06-13 18:16 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -97,15 +97,34 @@ | ||
97 | 97 | using YSLib::weak_ptr; |
98 | 98 | |
99 | 99 | |
100 | +/*! | |
101 | +\brief 压缩项标签。 | |
102 | +\since build 947 | |
103 | + | |
104 | +若定义为 true ,则特定的项标签复用其它项标签的位。 | |
105 | +因为这些标签预期不会在表示一等对象中出现,非一等对象的表示可复用相同的位置。 | |
106 | +公开接口中使用的对象表示的这些标签是否复用这些位在是未指定的。 | |
107 | +为避免依赖实现配置,判断对应的标签是否存在时, | |
108 | + 应使用 API 而不是直接依赖标签的数值的操作(例如比较和位运算)。 | |
109 | +*/ | |
110 | +#ifndef NPL_SContext_CompressTermTags | |
111 | +# define NPL_SContext_CompressTermTags true | |
112 | +#endif | |
113 | + | |
100 | 114 | //! \since build 857 |
101 | 115 | //@{ |
102 | 116 | //! \brief 项标签索引:指定项标签元数据掩码的位。 |
103 | 117 | enum TermTagIndices : size_t |
104 | 118 | { |
105 | - UnqualifiedIndex = 0, | |
106 | 119 | UniqueIndex, |
107 | 120 | NonmodifyingIndex, |
108 | - TemporaryIndex | |
121 | + TemporaryIndex, | |
122 | + StickyIndex | |
123 | +#if NPL_SContext_CompressTermTags | |
124 | + // NOTE: This can be any other index except %UnqualifiedIndex, because | |
125 | + // all other indices do not qualify subobjects. | |
126 | + = yimpl(NonmodifyingIndex) | |
127 | +#endif | |
109 | 128 | }; |
110 | 129 | |
111 | 130 | /*! |
@@ -122,7 +141,7 @@ | ||
122 | 141 | 指定默认情形的对象或对象引用。 |
123 | 142 | 当前用于实现对象语言的被绑定的对象或消亡值以外的表达式。 |
124 | 143 | */ |
125 | - Unqualified = 1 << UnqualifiedIndex, | |
144 | + Unqualified = 0, | |
126 | 145 | /*! |
127 | 146 | \brief 唯一引用。 |
128 | 147 |
@@ -151,7 +170,19 @@ | ||
151 | 170 | 而不引入项引用。 |
152 | 171 | 不取得范式的项中,派生语言可指定指示被绑定对象以外的语义。 |
153 | 172 | */ |
154 | - Temporary = 1 << TemporaryIndex | |
173 | + Temporary = 1 << TemporaryIndex, | |
174 | + /*! | |
175 | + \brief 粘滞项。 | |
176 | + | |
177 | + 指定非平凡非正规表示中的第一个不作为一等对象的子项。 | |
178 | + 在非平凡非正规表示的项的子项以外的其它项的标签中不具有这个标签值, | |
179 | + 但数值相等的其它标签值可在项引用中使用。 | |
180 | + 若这个标签值在第一个子项的标签设置,则包含这个子项的整个项不是非真列表。 | |
181 | + 在这个标签值不在第一个子项的标签设置时,非平凡非正规表示的项表示非真列表: | |
182 | + 在第一个具有这个标签值的子项前的子项表示 cons 对的第二个元素以外的列表元素; | |
183 | + 其它子项和值数据成员表示最后的 cons 对的第二个元素。 | |
184 | + */ | |
185 | + Sticky = 1 << StickyIndex | |
155 | 186 | }; |
156 | 187 | |
157 | 188 | //! \relates TermTags |
@@ -168,6 +199,24 @@ | ||
168 | 199 | == TermTags::Unique) |
169 | 200 | |
170 | 201 | /*! |
202 | +\brief 判断标签可表示被引用对象。 | |
203 | +\note 一等对象的表示的标签可表示被引用对象。 | |
204 | +\since build 947 | |
205 | +*/ | |
206 | +YB_ATTR_nodiscard YB_STATELESS yconstfn | |
207 | + PDefH(bool, IsReferentTags, TermTags tags) ynothrow | |
208 | + ImplRet((tags & (TermTags::Unique | TermTags::Nonmodifying | |
209 | + | TermTags::Temporary)) == tags) | |
210 | + | |
211 | +/*! | |
212 | +\brief 判断标签具有粘滞位。 | |
213 | +\since build 947 | |
214 | +*/ | |
215 | +YB_ATTR_nodiscard YB_STATELESS yconstfn | |
216 | + PDefH(bool, IsSticky, TermTags tags) ynothrow | |
217 | + ImplRet(bool(tags & TermTags::Sticky)) | |
218 | + | |
219 | +/*! | |
171 | 220 | \brief 取转发推断为左值表达式时保留的标签。 |
172 | 221 | \sa TermTags::Temporary |
173 | 222 |
@@ -255,12 +304,29 @@ | ||
255 | 304 | TermNode(allocator_type a) |
256 | 305 | : container(a) |
257 | 306 | {} |
307 | + //! \since build 947 | |
308 | + explicit | |
309 | + TermNode(TermTags tags) | |
310 | + : Tags(tags) | |
311 | + {} | |
312 | + //! \since build 947 | |
313 | + TermNode(TermTags tags, allocator_type a) | |
314 | + : container(a), Tags(tags) | |
315 | + {} | |
258 | 316 | TermNode(const Container& con) |
259 | - : TermNode(con, con.get_allocator()) | |
317 | + : TermNode(TermTags::Unqualified, con) | |
260 | 318 | {} |
261 | 319 | TermNode(Container&& con) |
262 | 320 | : container(std::move(con)) |
263 | 321 | {} |
322 | + //! \since build 947 | |
323 | + TermNode(TermTags tags, const Container& con) | |
324 | + : TermNode(std::allocator_arg, con.get_allocator(), tags, con) | |
325 | + {} | |
326 | + //! \since build 947 | |
327 | + TermNode(TermTags tags, Container&& con) | |
328 | + : container(std::move(con)), Tags(tags) | |
329 | + {} | |
264 | 330 | /*! |
265 | 331 | \note 除非 Value 的构造非嵌套调用安全,支持构造任意子节点时的嵌套调用安全。 |
266 | 332 | \since build 853 |
@@ -283,6 +349,26 @@ | ||
283 | 349 | TermNode(Container&& con, _tParams&&... args) |
284 | 350 | : container(std::move(con)), Value(yforward(args)...) |
285 | 351 | {} |
352 | + //! \since build 947 | |
353 | + //@{ | |
354 | + template<typename... _tParams, | |
355 | + yimpl(typename = enable_value_constructible_t<_tParams...>)> | |
356 | + inline | |
357 | + TermNode(TermTags tags, NoContainerTag, _tParams&&... args) | |
358 | + : Value(yforward(args)...), Tags(tags) | |
359 | + {} | |
360 | + template<typename... _tParams, | |
361 | + yimpl(typename = enable_value_constructible_t<_tParams...>)> | |
362 | + TermNode(TermTags tags, const Container& con, _tParams&&... args) | |
363 | + : TermNode(std::allocator_arg, con.get_allocator(), tags, con, | |
364 | + yforward(args)...) | |
365 | + {} | |
366 | + template<typename... _tParams, | |
367 | + yimpl(typename = enable_value_constructible_t<_tParams...>)> | |
368 | + TermNode(TermTags tags, Container&& con, _tParams&&... args) | |
369 | + : container(std::move(con)), Value(yforward(args)...), Tags(tags) | |
370 | + {} | |
371 | + //@} | |
286 | 372 | template<typename... _tParams, |
287 | 373 | yimpl(typename = enable_value_constructible_t<_tParams...>)> |
288 | 374 | inline |
@@ -304,21 +390,60 @@ | ||
304 | 390 | _tParams&&... args) |
305 | 391 | : container(std::move(con), a), Value(yforward(args)...) |
306 | 392 | {} |
393 | + //! \since build 947 | |
394 | + //@{ | |
395 | + template<typename... _tParams, | |
396 | + yimpl(typename = enable_value_constructible_t<_tParams...>)> | |
397 | + inline | |
398 | + TermNode(std::allocator_arg_t, allocator_type a, TermTags tags, | |
399 | + NoContainerTag, _tParams&&... args) | |
400 | + : container(a), Value(yforward(args)...), Tags(tags) | |
401 | + {} | |
402 | + template<typename... _tParams, | |
403 | + yimpl(typename = enable_value_constructible_t<_tParams...>)> | |
404 | + inline | |
405 | + TermNode(std::allocator_arg_t, allocator_type a, TermTags tags, | |
406 | + const Container& con, _tParams&&... args) | |
407 | + : container(ConSub(con, a)), Value(yforward(args)...), Tags(tags) | |
408 | + {} | |
409 | + template<typename... _tParams, | |
410 | + yimpl(typename = enable_value_constructible_t<_tParams...>)> | |
411 | + inline | |
412 | + TermNode(std::allocator_arg_t, allocator_type a, TermTags tags, | |
413 | + Container&& con, _tParams&&... args) | |
414 | + : container(std::move(con), a), Value(yforward(args)...), Tags(tags) | |
415 | + {} | |
416 | + //@} | |
307 | 417 | //@} |
308 | 418 | //! \warning 不保证嵌套调用安全。 |
419 | + //@{ | |
420 | + explicit | |
421 | + TermNode(const ValueNode& nd) | |
422 | + : container(ConCons(nd.GetContainer())), Value(nd.Value) | |
423 | + {} | |
309 | 424 | TermNode(const ValueNode& nd, allocator_type a) |
310 | 425 | : container(ConCons(nd.GetContainer(), a)), Value(nd.Value) |
311 | 426 | {} |
312 | - //! \warning 不保证嵌套调用安全。 | |
427 | + explicit | |
428 | + TermNode(ValueNode&& nd) | |
429 | + : container(ConCons(std::move(nd.GetContainerRef()))), | |
430 | + Value(std::move(nd.Value)) | |
431 | + {} | |
313 | 432 | TermNode(ValueNode&& nd, allocator_type a) |
314 | 433 | : container(ConCons(std::move(nd.GetContainerRef()), a)), |
315 | 434 | Value(std::move(nd.Value)) |
316 | 435 | {} |
317 | 436 | //@} |
437 | + //@} | |
318 | 438 | // XXX: This needs tag to avoid clash with other constructors. |
319 | 439 | TermNode(YSLib::ListContainerTag, std::initializer_list<TermNode> il) |
320 | 440 | : container(il) |
321 | 441 | {} |
442 | + //! \since build 947 | |
443 | + TermNode(TermTags tags, std::initializer_list<TermNode> il, | |
444 | + allocator_type a = {}) | |
445 | + : container(il, a), Tags(tags) | |
446 | + {} | |
322 | 447 | TermNode(std::initializer_list<TermNode> il, allocator_type a) |
323 | 448 | : container(il, a) |
324 | 449 | {} |
@@ -330,16 +455,14 @@ | ||
330 | 455 | std::initializer_list<TermNode> il, _tParams&&... args) |
331 | 456 | : TermNode(std::allocator_arg, a, Container(il, a), yforward(args)...) |
332 | 457 | {} |
333 | - //! \warning 不保证嵌套调用安全。 | |
334 | - explicit | |
335 | - TermNode(const ValueNode& nd) | |
336 | - : container(ConCons(nd.GetContainer())), Value(nd.Value) | |
337 | - {} | |
338 | - //! \warning 不保证嵌套调用安全。 | |
339 | - explicit | |
340 | - TermNode(ValueNode&& nd) | |
341 | - : container(ConCons(std::move(nd.GetContainer()))), | |
342 | - Value(std::move(nd.Value)) | |
458 | + //! \since build 947 | |
459 | + template<typename... _tParams, | |
460 | + yimpl(typename = enable_value_constructible_t<_tParams...>)> | |
461 | + inline | |
462 | + TermNode(std::allocator_arg_t, allocator_type a, TermTags tags, | |
463 | + std::initializer_list<TermNode> il, _tParams&&... args) | |
464 | + : TermNode(std::allocator_arg, a, tags, Container(il, a), | |
465 | + yforward(args)...) | |
343 | 466 | {} |
344 | 467 | //! \note 除非 Value 的构造非嵌套调用安全,支持构造任意子节点时的嵌套调用安全。 |
345 | 468 | //@{ |
@@ -424,14 +547,15 @@ | ||
424 | 547 | PDefH(void, SetContent, TermNode&& nd) |
425 | 548 | ImplExpr(SwapContainer(nd), Value = std::move(nd.Value), Tags = nd.Tags) |
426 | 549 | //@} |
427 | - //! \since build 918 | |
428 | - //@{ | |
550 | + //! \since build 947 | |
429 | 551 | template<typename _tParam> |
430 | 552 | inline yimpl(ystdex::enable_if_same_param_t<ValueObject, _tParam>) |
431 | - SetValue(_tParam&& arg) ynoexcept_spec(yforward(arg)) | |
553 | + SetValue(_tParam&& arg) ynoexcept_spec(Value = yforward(arg)) | |
432 | 554 | { |
433 | 555 | Value = yforward(arg); |
434 | 556 | } |
557 | + //! \since build 918 | |
558 | + //@{ | |
435 | 559 | template<typename _tParam, typename... _tParams, |
436 | 560 | yimpl(ystdex::enable_if_t<sizeof...(_tParams) != 0 |
437 | 561 | || !ystdex::is_same_param<ValueObject, _tParam>::value, int> = 0, |
@@ -508,14 +632,10 @@ | ||
508 | 632 | private: |
509 | 633 | //! \warning 不保证嵌套调用安全。 |
510 | 634 | //@{ |
511 | - YB_ATTR_nodiscard YB_PURE static TermNode::Container | |
512 | - ConCons(const ValueNode::Container&); | |
513 | - YB_ATTR_nodiscard YB_PURE static TermNode::Container | |
514 | - ConCons(ValueNode::Container&&); | |
515 | - YB_ATTR_nodiscard YB_PURE static TermNode::Container | |
516 | - ConCons(const ValueNode::Container&, allocator_type); | |
517 | - YB_ATTR_nodiscard YB_PURE static TermNode::Container | |
518 | - ConCons(ValueNode::Container&&, allocator_type); | |
635 | + YB_ATTR_nodiscard YB_FLATTEN YB_PURE static TermNode::Container | |
636 | + ConCons(const ValueNode::Container&, allocator_type = {}); | |
637 | + YB_ATTR_nodiscard YB_FLATTEN YB_PURE static TermNode::Container | |
638 | + ConCons(ValueNode::Container&&, allocator_type = {}); | |
519 | 639 | //@} |
520 | 640 | |
521 | 641 | //! \since build 934 |
@@ -725,6 +845,16 @@ | ||
725 | 845 | YB_ATTR_nodiscard YB_PURE inline |
726 | 846 | PDefH(bool, IsRegular, const TermNode& nd) ynothrow |
727 | 847 | ImplRet(IsLeaf(nd) || IsList(nd)) |
848 | + | |
849 | +//! \brief 判断项是否为原子节点:不能表示为一等对象的有序对的节点。 | |
850 | +YB_ATTR_nodiscard YB_PURE inline | |
851 | + PDefH(bool, IsAtom, const TermNode& nd) ynothrow | |
852 | + ImplRet(IsLeaf(nd) || IsSticky(nd.begin()->Tags)) | |
853 | + | |
854 | +//! \brief 判断项是否为有序对节点。 | |
855 | +YB_ATTR_nodiscard YB_PURE inline | |
856 | + PDefH(bool, IsPair, const TermNode& nd) ynothrow | |
857 | + ImplRet(!IsAtom(nd)) | |
728 | 858 | //@} |
729 | 859 | |
730 | 860 | //! \since build 928 |
@@ -815,6 +945,23 @@ | ||
815 | 945 | ImplExpr(yunused(nd), yunused(msg), YAssert(IsBranchedList(nd), msg)) |
816 | 946 | |
817 | 947 | /*! |
948 | +\brief 断言具有可表示被引用对象的标签节点。 | |
949 | +\pre 断言:参数的标签可表示被引用对象的值。 | |
950 | +\sa IsReferentTags | |
951 | +\since build 947 | |
952 | +*/ | |
953 | +//@{ | |
954 | +YB_NONNULL(2) inline | |
955 | + PDefH(void, AssertReferentTags, TermTags tags, const char* msg | |
956 | + = "Invalid term of referent found.") ynothrowv | |
957 | + ImplExpr(yunused(tags), yunused(msg), YAssert(IsReferentTags(tags), msg)) | |
958 | +YB_NONNULL(2) inline | |
959 | + PDefH(void, AssertReferentTags, const TermNode& nd, const char* msg | |
960 | + = "Invalid term of referent found.") ynothrowv | |
961 | + ImplExpr(AssertReferentTags(nd.Tags, msg)) | |
962 | +//@} | |
963 | + | |
964 | +/*! | |
818 | 965 | \brief 断言具有可表示一等对象的值的标签节点。 |
819 | 966 | \pre 断言:参数的标签可表示一等对象的值。 |
820 | 967 | \note 较 EnsureValueTags 更严格,对不符合要求的项总是断言失败。 |
@@ -845,6 +992,24 @@ | ||
845 | 992 | { |
846 | 993 | return TermNode(std::allocator_arg, a, NoContainer, yforward(args)...); |
847 | 994 | } |
995 | + | |
996 | +//! \since build 947 | |
997 | +template<typename... _tParam, typename... _tParams> | |
998 | +YB_ATTR_nodiscard YB_PURE inline | |
999 | +yimpl(ystdex::enable_if_inconvertible_t)<ystdex::head_of_t<_tParams...>, | |
1000 | + TermNode::allocator_type, TermNode> | |
1001 | +AsTermNodeTagged(TermTags tags, _tParams&&... args) | |
1002 | +{ | |
1003 | + return TermNode(tags, NoContainer, yforward(args)...); | |
1004 | +} | |
1005 | +//! \since build 947 | |
1006 | +template<typename... _tParams> | |
1007 | +YB_ATTR_nodiscard YB_PURE inline TermNode | |
1008 | +AsTermNodeTagged(TermNode::allocator_type a, TermTags tags, _tParams&&... args) | |
1009 | +{ | |
1010 | + return | |
1011 | + TermNode(std::allocator_arg, a, tags, NoContainer, yforward(args)...); | |
1012 | +} | |
848 | 1013 | //@} |
849 | 1014 | |
850 | 1015 | //! \since build 852 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Dependency.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief 依赖管理。 |
14 | -\version r6902 | |
14 | +\version r6958 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 623 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-08-09 22:14:45 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-04-25 18:07 +0800 | |
20 | + 2022-06-14 18:33 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -29,11 +29,11 @@ | ||
29 | 29 | #include YFM_NPL_Dependency // for set, string, UnescapeContext, string_view, |
30 | 30 | // ystdex::isspace, std::istream, YSLib::unique_ptr, std::throw_with_nested, |
31 | 31 | // std::invalid_argument, ystdex::sfmt, YSLib::share_move, REPLContext, |
32 | -// RetainN, NPL::ResolveRegular, NPL::Deref, RelaySwitched, trivial_swap, | |
33 | -// A1::NameTypedReducerHandler, std::bind, std::ref, Forms::CallResolvedUnary, | |
34 | -// EnsureValueTags, ResolvedTermReferencePtr, NPL::TryAccessLeaf, | |
35 | -// TermReference, LiftTerm, MoveResolved, Environment, | |
36 | -// NPL::AllocateEnvironment, function, ValueObject, NPL::AccessPtr, | |
32 | +// RelaySwitched, trivial_swap, std::bind, SourceName, RetainN, | |
33 | +// NPL::ResolveRegular, NPL::Deref, A1::NameTypedReducerHandler, std::ref, | |
34 | +// Forms::CallResolvedUnary, EnsureValueTags, ResolvedTermReferencePtr, | |
35 | +// TryAccessLeafAtom, TermReference, LiftTerm, MoveResolved, Environment, | |
36 | +// NPL::AllocateEnvironment, function, ValueObject, AccessPtr, | |
37 | 37 | // EnvironmentReference, shared_ptr, std::piecewise_construct, |
38 | 38 | // NPL::forward_as_tuple, LiftOther, ThrowNonmodifiableErrorForAssignee, |
39 | 39 | // ThrowValueCategoryError, ValueToken, ResolveTerm, TokenValue, |
@@ -47,7 +47,7 @@ | ||
47 | 47 | // AccessFirstSubterm, ThrowInsufficientTermsError, AssertValueTags, Retain, |
48 | 48 | // RemoveHead, ClearCombiningTags, EmplaceCallResultOrReturn, NPL::AsTermNode, |
49 | 49 | // ReferenceTerm, ResolveName, ystdex::fast_any_of, Ensigil, YSLib::ufexists, |
50 | -// YSLib::to_std_string, EmplaceCallResultOrReturn, NPL::TryAccessTerm, | |
50 | +// YSLib::to_std_string, EmplaceCallResultOrReturn, TryAccessTerm, | |
51 | 51 | // ystdex::plus, ystdex::tolower, YSLib::OwnershipTag, YSLib::IO::StreamPut, |
52 | 52 | // YSLib::FetchEnvironmentVariable, YSLib::SetEnvironmentVariable, NPL::tuple, |
53 | 53 | // YSLib::IO::UniqueFile, YSLib::uremove, YSLib::allocate_shared, |
@@ -212,7 +212,8 @@ | ||
212 | 212 | { |
213 | 213 | auto p_is(A1::OpenFile(filename.c_str())); |
214 | 214 | |
215 | - // NOTE: Swap guard for %Context.CurrentSource is not used to support PTC. | |
215 | + // NOTE: Swap guard for %Context.CurrentSource is not used. It is up to the | |
216 | + // caller to support PTC or not. | |
216 | 217 | context.CurrentSource = YSLib::share_move(filename); |
217 | 218 | return p_is; |
218 | 219 | } |
@@ -233,10 +234,31 @@ | ||
233 | 234 | ReduceToLoadFile(TermNode& term, ContextNode& ctx, REPLContext& context, |
234 | 235 | string filename) |
235 | 236 | { |
236 | - term = context.Load(context, ctx, std::move(filename)); | |
237 | 237 | // NOTE: This is explicitly not same to klisp. This is also friendly to PTC. |
238 | 238 | // XXX: Same to %A1::ReduceOnce, without setup the next term. |
239 | +#if NPL_Impl_NPLA1_Enable_Thunked | |
240 | +# if NPL_Impl_NPLA1_Enable_TCO | |
241 | + RefTCOAction(ctx).SaveTailSourceName(context.CurrentSource, | |
242 | + std::move(context.CurrentSource)); | |
243 | +# else | |
244 | + RelaySwitched(ctx, trivial_swap, | |
245 | + A1::NameTypedReducerHandler(std::bind([&](SourceName& saved_src){ | |
246 | + context.CurrentSource = std::move(saved_src); | |
247 | + return ctx.LastStatus; | |
248 | + }, std::move(context.CurrentSource)), "recover-source-name")); | |
249 | +# endif | |
250 | + term = context.Load(context, ctx, std::move(filename)); | |
239 | 251 | return ContextState::Access(ctx).ReduceOnce.Handler(term, ctx); |
252 | +#else | |
253 | + auto saved_src(std::move(context.CurrentSource)); | |
254 | + | |
255 | + term = context.Load(context, ctx, std::move(filename)); | |
256 | + | |
257 | + const auto res(ContextState::Access(ctx).ReduceOnce.Handler(term, ctx)); | |
258 | + | |
259 | + context.CurrentSource = std::move(saved_src); | |
260 | + return res; | |
261 | +#endif | |
240 | 262 | } |
241 | 263 | |
242 | 264 | } // unnamed namespace; |
@@ -284,7 +306,7 @@ | ||
284 | 306 | Qualify(TermNode& term, TermTags tag_add) |
285 | 307 | { |
286 | 308 | return Forms::CallRawUnary([&](TermNode& tm){ |
287 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(tm)) | |
309 | + if(const auto p = TryAccessLeafAtom<TermReference>(tm)) | |
288 | 310 | p->AddTags(tag_add); |
289 | 311 | LiftTerm(term, tm); |
290 | 312 | return ReductionStatus::Retained; |
@@ -308,14 +330,14 @@ | ||
308 | 330 | }); |
309 | 331 | const auto copy_parent_ptr( |
310 | 332 | [&](function<Environment&()> mdst, const ValueObject& vo) -> bool{ |
311 | - if(const auto p = NPL::AccessPtr<EnvironmentReference>(vo)) | |
333 | + if(const auto p = AccessPtr<EnvironmentReference>(vo)) | |
312 | 334 | { |
313 | 335 | if(const auto p_parent = p->Lock()) |
314 | 336 | copy_parent(mdst(), *p_parent); |
315 | 337 | // XXX: Failure of locking is ignored. |
316 | 338 | return true; |
317 | 339 | } |
318 | - else if(const auto p_e = NPL::AccessPtr<shared_ptr<Environment>>(vo)) | |
340 | + else if(const auto p_e = AccessPtr<shared_ptr<Environment>>(vo)) | |
319 | 341 | { |
320 | 342 | if(const auto p_parent = *p_e) |
321 | 343 | copy_parent(mdst(), *p_parent); |
@@ -567,7 +589,7 @@ | ||
567 | 589 | RegisterUnary(ctx, "uncollapsed?", IsUncollapsedTerm); |
568 | 590 | RegisterStrict(ctx, "deshare", [](TermNode& term){ |
569 | 591 | return CallRawUnary([&](TermNode& tm){ |
570 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(tm)) | |
592 | + if(const auto p = TryAccessLeafAtom<const TermReference>(tm)) | |
571 | 593 | LiftTermRef(tm, p->get()); |
572 | 594 | NPL::SetContentWith(term, std::move(tm), |
573 | 595 | &ValueObject::MakeMoveCopy); |
@@ -770,7 +792,7 @@ | ||
770 | 792 | auto& tm(*pr.first); |
771 | 793 | |
772 | 794 | if(const auto p |
773 | - = NPL::TryAccessLeaf<const TermReference>(tm)) | |
795 | + = TryAccessLeafAtom<const TermReference>(tm)) | |
774 | 796 | return p->IsReferencedLValue(); |
775 | 797 | return !(bool(tm.Tags & TermTags::Unique) |
776 | 798 | || bool(tm.Tags & TermTags::Temporary)); |
@@ -915,7 +937,7 @@ | ||
915 | 937 | // implementation. |
916 | 938 | ystdex::bind1([](TermNode& term, const EnvironmentReference& ce){ |
917 | 939 | RetainN(term, 0); |
918 | - term.Value = CreateEnvironmentWithParent(term.get_allocator(), ce); | |
940 | + term.SetValue(CreateEnvironmentWithParent(term.get_allocator(), ce)); | |
919 | 941 | }, context.Root.WeakenRecord())); |
920 | 942 | RegisterStrict(renv, "derive-current-environment", |
921 | 943 | [] YB_LAMBDA_ANNOTATE((TermNode& term, ContextNode& ctx), , flatten){ |
@@ -1532,7 +1554,7 @@ | ||
1532 | 1554 | // is trustable to have only the tags of modifiable first-class object. |
1533 | 1555 | const bool list_not_move(!NPL::IsMovable(p_ref) || p_back); |
1534 | 1556 | |
1535 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(nd)) | |
1557 | + if(const auto p = TryAccessLeafAtom<const TermReference>(nd)) | |
1536 | 1558 | { |
1537 | 1559 | if(list_not_move) |
1538 | 1560 | { |
@@ -1548,7 +1570,7 @@ | ||
1548 | 1570 | else if(list_not_move) |
1549 | 1571 | { |
1550 | 1572 | // XXX: Allocators are not used here for performance. |
1551 | - term.Value.assign(in_place_type<TermReference>, nd.Tags, nd, | |
1573 | + term.SetValue(in_place_type<TermReference>, nd.Tags, nd, | |
1552 | 1574 | p_ref ? p_ref->GetEnvironmentReference() : r_env); |
1553 | 1575 | return ReductionStatus::Clean; |
1554 | 1576 | } |
@@ -1629,7 +1651,7 @@ | ||
1629 | 1651 | // the recursive call to %ForcePromise also reuses %nterm to hold the |
1630 | 1652 | // old %nprom for nested promise evaluation, so lifetimes of %prom and |
1631 | 1653 | // %nprom should not overlap. |
1632 | - auto& nprom(NPL::AccessRegular<Promise>(nd, p_ref)); | |
1654 | + auto& nprom(AccessRegular<Promise>(nd, p_ref)); | |
1633 | 1655 | |
1634 | 1656 | // NOTE: This is necessary to handle the promise forced during the |
1635 | 1657 | // evaluation on %nterm, see [RnRK]. |
@@ -1880,8 +1902,8 @@ | ||
1880 | 1902 | "string<-", [](ResolvedArg<>&& x, ResolvedArg<>&& y){ |
1881 | 1903 | if(x.IsModifiable()) |
1882 | 1904 | { |
1883 | - auto& str_x(NPL::AccessRegular<string>(x.get(), x.second)); | |
1884 | - auto& str_y(NPL::AccessRegular<string>(y.get(), y.second)); | |
1905 | + auto& str_x(AccessRegular<string>(x.get(), x.second)); | |
1906 | + auto& str_y(AccessRegular<string>(y.get(), y.second)); | |
1885 | 1907 | |
1886 | 1908 | if(y.IsMovable()) |
1887 | 1909 | str_x = std::move(str_y); |
@@ -2001,22 +2023,13 @@ | ||
2001 | 2023 | $defl! puts (&s) $sequence (put s) (() newline); |
2002 | 2024 | )NPL"); |
2003 | 2025 | #endif |
2004 | -#if true | |
2005 | 2026 | RegisterStrict(renv, "load", trivial_swap, |
2006 | 2027 | [&](TermNode& term, ContextNode& ctx){ |
2028 | + // NOTE: Since %load requires no additional barrier of catching the | |
2029 | + // inner exceptions and the reset of the source name, %TryLoadSource or | |
2030 | + // %PreloadExternal is not applicable here. | |
2007 | 2031 | return ReduceToLoadExternal(term, ctx, context); |
2008 | 2032 | }); |
2009 | -#else | |
2010 | - RegisterUnary<Strict, string>(renv, "load", [&](string& filename){ | |
2011 | - // NOTE: This is not applicable since %load has no additional barrier | |
2012 | - // here. | |
2013 | - // XXX: As %PreloadExternal. | |
2014 | - const auto p_is(OpenUnique(context, std::move(filename))); | |
2015 | - | |
2016 | - TryLoadSource(context, context.CurrentSource->c_str(), *p_is); | |
2017 | - return ValueToken::Unspecified; | |
2018 | - }); | |
2019 | -#endif | |
2020 | 2033 | #if NPL_Impl_NPLA1_Native_Forms |
2021 | 2034 | RegisterStrict(renv, "get-module", trivial_swap, |
2022 | 2035 | ystdex::bind1([&](TermNode& term, ContextNode& ctx, |
@@ -2048,7 +2061,7 @@ | ||
2048 | 2061 | # if NPL_Impl_NPLA1_Enable_Thunked |
2049 | 2062 | RelaySwitched(ctx, trivial_swap, A1::NameTypedReducerHandler( |
2050 | 2063 | std::bind([&](shared_ptr<Environment> p_res){ |
2051 | - term.Value = std::move(p_res); | |
2064 | + term.SetValue(std::move(p_res)); | |
2052 | 2065 | return ReductionStatus::Clean; |
2053 | 2066 | }, p_env), "get-module-return")); |
2054 | 2067 | return ReduceToLoadGuarded(term, ctx, context, std::move(p_env), |
@@ -2056,7 +2069,7 @@ | ||
2056 | 2069 | # else |
2057 | 2070 | ReduceToLoadGuarded(term, ctx, context, std::move(p_env), |
2058 | 2071 | ReduceToLoadExternal); |
2059 | - term.Value = std::move(p_env); | |
2072 | + term.SetValue(std::move(p_env)); | |
2060 | 2073 | return ReductionStatus::Clean; |
2061 | 2074 | # endif |
2062 | 2075 | } |
@@ -2087,7 +2100,7 @@ | ||
2087 | 2100 | RegisterStrict(renv, "get-current-repl", trivial_swap, |
2088 | 2101 | [&](TermNode& term){ |
2089 | 2102 | RetainN(term, 0); |
2090 | - term.Value = ValueObject(context, YSLib::OwnershipTag<>()); | |
2103 | + term.Value.assign(context, YSLib::OwnershipTag<>()); | |
2091 | 2104 | }); |
2092 | 2105 | RegisterStrict(renv, "eval-string", EvalString); |
2093 | 2106 | RegisterStrict(renv, "eval-string%", EvalStringRef); |
@@ -2245,15 +2258,15 @@ | ||
2245 | 2258 | // XXX: As %ReduceToReference for modifiable lvalues (with default |
2246 | 2259 | // tags). |
2247 | 2260 | AssertValueTags(tm); |
2248 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(tm)) | |
2261 | + if(const auto p = TryAccessLeafAtom<const TermReference>(tm)) | |
2249 | 2262 | { |
2250 | 2263 | // XXX: Since %tm is not shared with %term, it is safe to use |
2251 | 2264 | // %TermNode::SetContent instead of %TermNode::CopyContent. |
2252 | 2265 | term.SetContent(tm); |
2253 | 2266 | return ReductionStatus::Retained; |
2254 | 2267 | } |
2255 | - term.Value | |
2256 | - = TermReference(TermTags::Unqualified, tm, ctx.WeakenRecord()); | |
2268 | + term.SetValue(in_place_type<TermReference>, TermTags::Unqualified, | |
2269 | + tm, ctx.WeakenRecord()); | |
2257 | 2270 | return ReductionStatus::Clean; |
2258 | 2271 | }); |
2259 | 2272 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r4016 | |
14 | +\version r4055 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 663 |
17 | 17 | \par 创建时间: |
18 | 18 | 2016-01-07 10:32:45 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-05-29 08:09 +0800 | |
20 | + 2022-06-14 18:41 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -28,18 +28,17 @@ | ||
28 | 28 | #include "NPL/YModules.h" |
29 | 29 | #include YFM_NPL_NPLA // for YSLib::Warning, YSLib::Err, YSLib::RecordLevel, |
30 | 30 | // string, YSLib::make_string_view, std::to_string, YSLib::DecodeIndex, |
31 | -// std::invalid_argument, ValueNode, NPL::Access, EscapeLiteral, Literalize, | |
32 | -// NPL::AccessPtr, ystdex::value_or, ystdex::write, std::bind, | |
33 | -// TraverseSubnodes, bad_any_cast, std::allocator_arg, YSLib::NodeSequence, | |
34 | -// ystdex::begins_with, ystdex::sfmt, observer_ptr, | |
35 | -// ystdex::make_obj_using_allocator, trivial_swap, NPL::make_observer, | |
36 | -// TermTags, NPL::TryAccessLeaf, NPL::Deref, YSLib::sfmt, | |
37 | -// ystdex::call_value_or, IsTyped, ystdex::compose, GetLValueTagsOf, | |
38 | -// std::mem_fn, ystdex::invoke_value_or, ystdex::ref, PropagateTo, | |
39 | -// NPL::IsMovable, AccessFirstSubterm, YSLib::FilterExceptions, type_id, | |
40 | -// ystdex::addrof, ystdex::second_of, type_info, std::current_exception, | |
41 | -// std::rethrow_exception, std::throw_with_nested, ystdex::retry_on_cond, | |
42 | -// ystdex::id, pair, YSLib::ExtractException; | |
31 | +// std::invalid_argument, ValueNode, Access, EscapeLiteral, Literalize, | |
32 | +// AccessPtr, ystdex::value_or, ystdex::write, std::bind, TraverseSubnodes, | |
33 | +// bad_any_cast, std::allocator_arg, YSLib::NodeSequence, ystdex::begins_with, | |
34 | +// ystdex::sfmt, observer_ptr, ystdex::make_obj_using_allocator, trivial_swap, | |
35 | +// make_observer, TermTags, TryAccessLeafAtom, NPL::Deref, YSLib::sfmt, | |
36 | +// AssertReferentTags, ystdex::call_value_or, ystdex::compose, GetLValueTagsOf, | |
37 | +// std::mem_fn, IsTyped, ystdex::invoke_value_or, ystdex::ref, PropagateTo, | |
38 | +// NPL::IsMovable, TryAccessLeaf, AccessFirstSubterm, YSLib::FilterExceptions, | |
39 | +// type_id, ystdex::addrof, ystdex::second_of, type_info, | |
40 | +// std::current_exception, std::rethrow_exception, std::throw_with_nested, | |
41 | +// ystdex::retry_on_cond, ystdex::id, pair, YSLib::ExtractException; | |
43 | 42 | #include <ystdex/function.hpp> // for ystdex::unchecked_function; |
44 | 43 | |
45 | 44 | //! \since build 903 |
@@ -71,7 +70,7 @@ | ||
71 | 70 | string |
72 | 71 | EscapeNodeLiteral(const ValueNode& node) |
73 | 72 | { |
74 | - return EscapeLiteral(NPL::Access<string>(node)); | |
73 | + return EscapeLiteral(Access<string>(node)); | |
75 | 74 | } |
76 | 75 | |
77 | 76 | string |
@@ -83,7 +82,7 @@ | ||
83 | 82 | string |
84 | 83 | ParseNPLANodeString(const ValueNode& node) |
85 | 84 | { |
86 | - return ystdex::value_or(NPL::AccessPtr<string>(node)); | |
85 | + return ystdex::value_or(AccessPtr<string>(node)); | |
87 | 86 | } |
88 | 87 | |
89 | 88 |
@@ -140,7 +139,7 @@ | ||
140 | 139 | string |
141 | 140 | ParseNPLATermString(const TermNode& term) |
142 | 141 | { |
143 | - return ystdex::value_or(NPL::AccessPtr<string>(term)); | |
142 | + return ystdex::value_or(AccessPtr<string>(term)); | |
144 | 143 | } |
145 | 144 | |
146 | 145 | ValueNode |
@@ -162,7 +161,7 @@ | ||
162 | 161 | |
163 | 162 | if(node.empty()) |
164 | 163 | { |
165 | - if(const auto p = NPL::AccessPtr<YSLib::NodeSequence>(node)) | |
164 | + if(const auto p = AccessPtr<YSLib::NodeSequence>(node)) | |
166 | 165 | for(auto& nd : *p) |
167 | 166 | nested_call(nd); |
168 | 167 | else |
@@ -226,7 +225,7 @@ | ||
226 | 225 | cont = std::move(c); |
227 | 226 | return RedirectEnvironmentList(a, cont, i, last); |
228 | 227 | }, std::next(first), std::move(cont))); |
229 | - return NPL::make_observer(&*first); | |
228 | + return make_observer(&*first); | |
230 | 229 | } |
231 | 230 | return {}; |
232 | 231 | } |
@@ -246,7 +245,7 @@ | ||
246 | 245 | AssertValueTags(tm); |
247 | 246 | // XXX: Term tags are currently not respected in prvalues. However, this |
248 | 247 | // should be neutral here due to copy elision in the object language. |
249 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(tm)) | |
248 | + if(const auto p = TryAccessLeafAtom<const TermReference>(tm)) | |
250 | 249 | { |
251 | 250 | if(!p->IsReferencedLValue()) |
252 | 251 | return LiftMovedOther(term, *p, ((*p).*pm)()); |
@@ -376,9 +375,10 @@ | ||
376 | 375 | TermTags |
377 | 376 | TermToTags(TermNode& term) |
378 | 377 | { |
378 | + AssertReferentTags(term); | |
379 | 379 | return ystdex::call_value_or(ystdex::compose(GetLValueTagsOf, |
380 | 380 | std::mem_fn(&TermReference::GetTags)), |
381 | - NPL::TryAccessLeaf<const TermReference>(term), term.Tags); | |
381 | + TryAccessLeafAtom<const TermReference>(term), term.Tags); | |
382 | 382 | } |
383 | 383 | |
384 | 384 | void |
@@ -386,7 +386,7 @@ | ||
386 | 386 | { |
387 | 387 | for(auto& child : term) |
388 | 388 | TokenizeTerm(child); |
389 | - if(const auto p = NPL::AccessPtr<string>(term)) | |
389 | + if(const auto p = AccessPtr<string>(term)) | |
390 | 390 | term.Value.emplace<TokenValue>(std::move(*p)); |
391 | 391 | } |
392 | 392 |
@@ -406,7 +406,7 @@ | ||
406 | 406 | pair<TermReference, bool> |
407 | 407 | Collapse(TermReference ref) |
408 | 408 | { |
409 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(ref.get())) | |
409 | + if(const auto p = TryAccessLeafAtom<TermReference>(ref.get())) | |
410 | 410 | { |
411 | 411 | // XXX: Term tags on prvalues are reserved and should be ignored |
412 | 412 | // normally except for future internal use. The only case making the |
@@ -433,21 +433,21 @@ | ||
433 | 433 | bool |
434 | 434 | IsReferenceTerm(const TermNode& term) |
435 | 435 | { |
436 | - return bool(NPL::TryAccessLeaf<const TermReference>(term)); | |
436 | + return bool(TryAccessLeafAtom<const TermReference>(term)); | |
437 | 437 | } |
438 | 438 | |
439 | 439 | bool |
440 | 440 | IsUniqueTerm(const TermNode& term) |
441 | 441 | { |
442 | 442 | return ystdex::invoke_value_or(&TermReference::IsUnique, |
443 | - NPL::TryAccessLeaf<const TermReference>(term), true); | |
443 | + TryAccessLeafAtom<const TermReference>(term), true); | |
444 | 444 | } |
445 | 445 | |
446 | 446 | bool |
447 | 447 | IsModifiableTerm(const TermNode& term) |
448 | 448 | { |
449 | 449 | return ystdex::invoke_value_or(&TermReference::IsModifiable, |
450 | - NPL::TryAccessLeaf<const TermReference>(term), | |
450 | + TryAccessLeafAtom<const TermReference>(term), | |
451 | 451 | !bool(term.Tags & TermTags::Nonmodifying)); |
452 | 452 | } |
453 | 453 |
@@ -455,7 +455,7 @@ | ||
455 | 455 | IsTemporaryTerm(const TermNode& term) |
456 | 456 | { |
457 | 457 | return ystdex::invoke_value_or(&TermReference::IsTemporary, |
458 | - NPL::TryAccessLeaf<const TermReference>(term), | |
458 | + TryAccessLeafAtom<const TermReference>(term), | |
459 | 459 | bool(term.Tags & TermTags::Temporary)); |
460 | 460 | } |
461 | 461 |
@@ -463,7 +463,7 @@ | ||
463 | 463 | IsBoundLValueTerm(const TermNode& term) |
464 | 464 | { |
465 | 465 | return ystdex::invoke_value_or(&TermReference::IsReferencedLValue, |
466 | - NPL::TryAccessLeaf<const TermReference>(term)); | |
466 | + TryAccessLeafAtom<const TermReference>(term)); | |
467 | 467 | } |
468 | 468 | |
469 | 469 | bool |
@@ -471,7 +471,7 @@ | ||
471 | 471 | { |
472 | 472 | return ystdex::call_value_or(ystdex::compose(IsReferenceTerm, |
473 | 473 | std::mem_fn(&TermReference::get)), |
474 | - NPL::TryAccessLeaf<const TermReference>(term)); | |
474 | + TryAccessLeafAtom<const TermReference>(term)); | |
475 | 475 | } |
476 | 476 | |
477 | 477 |
@@ -529,7 +529,7 @@ | ||
529 | 529 | void |
530 | 530 | MoveCollapsed(TermNode& term, TermNode& tm) |
531 | 531 | { |
532 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(tm)) | |
532 | + if(const auto p = TryAccessLeafAtom<TermReference>(tm)) | |
533 | 533 | term.SetContent(TermNode(std::move(tm.GetContainerRef()), |
534 | 534 | Collapse(std::move(*p)).first)); |
535 | 535 | else |
@@ -567,9 +567,8 @@ | ||
567 | 567 | else if(tm.Value.OwnsCount() > 1) |
568 | 568 | // XXX: This is unsafe and not checkable because the anchor is not |
569 | 569 | // referenced. |
570 | - // XXX: Allocators are not used here for performance. | |
571 | - term.Value = TermReference(TermTags::Unqualified, tm, | |
572 | - EnvironmentReference()); | |
570 | + term.SetValue(in_place_type<TermReference>, TermTags::Unqualified, | |
571 | + tm, EnvironmentReference()); | |
573 | 572 | else |
574 | 573 | throw InvalidReference( |
575 | 574 | "Value of a temporary shall not be referenced."); |
@@ -585,7 +584,7 @@ | ||
585 | 584 | // should be neutral here due to copy elision in the object language. Note |
586 | 585 | // the operation here is idempotent for qualified expressions. |
587 | 586 | // TODO: Detect lifetime escape to perform copy elision? |
588 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(term)) | |
587 | + if(const auto p = TryAccessLeafAtom<const TermReference>(term)) | |
589 | 588 | // XXX: Using %LiftMovedOther instead of %LiftMoved is safe, because the |
590 | 589 | // referent is not allowed to be same to %term in NPLA. |
591 | 590 | LiftMovedOther(term, *p, p->IsMovable()); |
@@ -603,7 +602,7 @@ | ||
603 | 602 | LiftOtherValue(term, tm); |
604 | 603 | if(!IsBoundLValueTerm(term)) |
605 | 604 | { |
606 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(term)) | |
605 | + if(const auto p = TryAccessLeafAtom<const TermReference>(term)) | |
607 | 606 | LiftMovedOther(term, *p, p->IsModifiable()); |
608 | 607 | } |
609 | 608 | #endif |
@@ -682,7 +681,7 @@ | ||
682 | 681 | ReductionStatus |
683 | 682 | ReduceToReference(TermNode& term, TermNode& tm, ResolvedTermReferencePtr p_ref) |
684 | 683 | { |
685 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(tm)) | |
684 | + if(const auto p = TryAccessLeafAtom<const TermReference>(tm)) | |
686 | 685 | { |
687 | 686 | AssertValueTags(tm); |
688 | 687 | // NOTE: Reference collapsed. |
@@ -708,9 +707,8 @@ | ||
708 | 707 | // XXX: Term tags on prvalues are reserved and should be ignored normally |
709 | 708 | // except for future internal use. Since %tm is a term, |
710 | 709 | // %TermTags::Temporary is not expected, %GetLValueTagsOf is also not used. |
711 | - // XXX: Allocators are not used here for performance. | |
712 | - term.Value = TermReference(PropagateTo(tm.Tags, p_ref->GetTags()), tm, | |
713 | - NPL::Deref(p_ref).GetEnvironmentReference()); | |
710 | + term.SetValue(in_place_type<TermReference>, PropagateTo(tm.Tags, | |
711 | + p_ref->GetTags()), tm, NPL::Deref(p_ref).GetEnvironmentReference()); | |
714 | 712 | return ReductionStatus::Clean; |
715 | 713 | } |
716 | 714 |
@@ -834,7 +832,7 @@ | ||
834 | 832 | Environment::LookupName(string_view id) const |
835 | 833 | { |
836 | 834 | YAssertNonnull(id.data()); |
837 | - return NPL::make_observer(ystdex::call_value_or<BindingMap::mapped_type*>( | |
835 | + return make_observer(ystdex::call_value_or<BindingMap::mapped_type*>( | |
838 | 836 | ystdex::compose(ystdex::addrof<>(), ystdex::second_of<>()), |
839 | 837 | Bindings.find(id), {}, Bindings.cend())); |
840 | 838 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 公共接口。 |
14 | -\version r22377 | |
14 | +\version r22423 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 472 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-02-02 18:02:47 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-05-20 18:06 +0800 | |
20 | + 2022-06-14 18:22 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -29,23 +29,23 @@ | ||
29 | 29 | #include YFM_NPL_NPLA1Forms // for NPL, EvaluationPasses, lref, ContextHandler, |
30 | 30 | // RelaySwitched, trivial_swap, type_index, string_view, std::hash, |
31 | 31 | // ystdex::equal_to, YSLib::unordered_map, std::piecewise_construct, |
32 | -// YSLib::lock_guard, YSLib::mutex, type_id, NPL::make_observer, IsBranch, | |
32 | +// YSLib::lock_guard, YSLib::mutex, type_id, make_observer, IsBranch, | |
33 | 33 | // CheckReducible, IsNPLAExtendedLiteralNonDigitPrefix, IsAllSignLexeme, |
34 | 34 | // AllocatorHolder, ystdex::ref, YSLib::IValueHolder, |
35 | 35 | // YSLib::AllocatedHolderOperations, any, ystdex::as_const, |
36 | 36 | // NPL::forward_as_tuple, uintmax_t, ystdex::bind1, TokenValue, |
37 | 37 | // Forms::Sequence, std::allocator_arg, ReduceBranchToList, YSLib::stack, |
38 | 38 | // YSLib::vector, TermTags, function, TermReference, GetLValueTagsOf, |
39 | -// NPL::TryAccessLeaf, ListReductionFailure, ystdex::sfmt, PropagateTo, | |
40 | -// NPL::IsMovable, in_place_type, InvalidReference, NPL::Deref, IsLeaf, | |
41 | -// ResolveTerm, ThrowInsufficientTermsError, ThrowListTypeErrorForNonlist, | |
42 | -// ystdex::update_thunk, Environment, shared_ptr, NPL::AsTermNode, IsTyped, | |
43 | -// ystdex::retry_on_cond, AccessFirstSubterm, ystdex::make_transform, | |
44 | -// IsBranchedList, std::placeholders, NoContainer, ystdex::try_emplace, | |
45 | -// NPL::Access, YSLib::Informative, ystdex::unique_guard, | |
46 | -// CategorizeBasicLexeme, DeliteralizeUnchecked, Deliteralize, | |
47 | -// ystdex::isdigit, INT_MAX, ystdex::ref_eq, NPL::TryAccessTerm, | |
48 | -// YSLib::share_move, ystdex::call_value_or, std::to_string, YSLib::Notice, | |
39 | +// TryAccessLeaf, ListReductionFailure, ystdex::sfmt, TryAccessLeafAtom, | |
40 | +// PropagateTo, NPL::IsMovable, in_place_type, InvalidReference, NPL::Deref, | |
41 | +// IsLeaf, ResolveTerm, ThrowInsufficientTermsError, | |
42 | +// ThrowListTypeErrorForNonlist, ystdex::update_thunk, Environment, shared_ptr, | |
43 | +// NPL::AsTermNode, IsTyped, ystdex::retry_on_cond, AccessFirstSubterm, | |
44 | +// ystdex::make_transform, IsBranchedList, std::placeholders, NoContainer, | |
45 | +// ystdex::try_emplace, Access, YSLib::Informative, ystdex::unique_guard, | |
46 | +// CategorizeBasicLexeme, DeliteralizeUnchecked, Deliteralize, ystdex::isdigit, | |
47 | +// INT_MAX, ystdex::ref_eq, TryAccessTerm, YSLib::share_move, | |
48 | +// ystdex::call_value_or, std::to_string, YSLib::Notice, | |
49 | 49 | // YSLib::FilterException, Session; |
50 | 50 | #include "NPLA1Internals.h" // for A1::Internals API; |
51 | 51 | #include YFM_NPL_NPLAMath // for ReadDecimal; |
@@ -241,6 +241,7 @@ | ||
241 | 241 | term.Value.Clear(); |
242 | 242 | |
243 | 243 | auto gd(ystdex::unique_guard([&]() ynothrow{ |
244 | + // XXX: This term is fixed, as in the term cleanup in %TCOAction. | |
244 | 245 | term.Clear(); |
245 | 246 | })); |
246 | 247 | # if NPL_Impl_NPLA1_Enable_Thunked |
@@ -276,7 +277,7 @@ | ||
276 | 277 | string name(term.get_allocator()); |
277 | 278 | |
278 | 279 | // XXX: As %TermToNamePtr. |
279 | - if(const auto p = NPL::TryAccessLeaf<TokenValue>(term)) | |
280 | + if(const auto p = TryAccessLeaf<TokenValue>(term)) | |
280 | 281 | { |
281 | 282 | name = std::move(*p); |
282 | 283 | name += ": "; |
@@ -483,7 +484,7 @@ | ||
483 | 484 | # if NPL_Impl_NPLA1_Enable_ThunkedThreshold == 0 |
484 | 485 | YAssert(!remained.empty(), "Invalid state found."); |
485 | 486 | // XXX: For some reason, 'while' here is more efficient than 'do' in the |
486 | - // generated code with x86_64-pc-linux G++ 11.1.0. | |
487 | + // generated code with x86_64-pc-linux G++ 11.1. | |
487 | 488 | # endif |
488 | 489 | while(!remained.empty()) |
489 | 490 | { |
@@ -586,7 +587,7 @@ | ||
586 | 587 | |
587 | 588 | // NOTE: Subterms in arguments retained are also transferred for |
588 | 589 | // values. |
589 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
590 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
590 | 591 | { |
591 | 592 | if(sigil != char()) |
592 | 593 | { |
@@ -839,7 +840,8 @@ | ||
839 | 840 | // here. |
840 | 841 | if(IsLeaf(back)) |
841 | 842 | { |
842 | - if(const auto p = NPL::TryAccessLeaf<TokenValue>(back)) | |
843 | + if(const auto p | |
844 | + = TryAccessLeafAtom<TokenValue>(back)) | |
843 | 845 | { |
844 | 846 | if(!p->empty() && p->front() == '.') |
845 | 847 | --last; |
@@ -907,7 +909,7 @@ | ||
907 | 909 | has_ref).c_str())); |
908 | 910 | }, o); |
909 | 911 | } |
910 | - else if(const auto p_t = NPL::TryAccessLeaf<const TermReference>(t)) | |
912 | + else if(const auto p_t = TryAccessLeafAtom<const TermReference>(t)) | |
911 | 913 | { |
912 | 914 | auto& nd(p_t->get()); |
913 | 915 |
@@ -1153,13 +1155,15 @@ | ||
1153 | 1155 | { |
1154 | 1156 | AssertValueTags(term); |
1155 | 1157 | |
1158 | + // NOTE: For efficiency, only quite a few kinds of terms would be reduced | |
1159 | + // here. More specific handling can be implemented by context handlers or | |
1160 | + // replacement of %ContextState::DefaultReduceOnce. | |
1156 | 1161 | auto& cs(ContextState::Access(ctx)); |
1157 | 1162 | const bool non_list(!IsList(term)); |
1158 | 1163 | |
1159 | 1164 | // NOTE: Empty list or special value token has no-op to do with. |
1160 | 1165 | if(non_list) |
1161 | 1166 | { |
1162 | - // XXX: Add logic to directly handle special value tokens here? | |
1163 | 1167 | // NOTE: The reduction relies on proper handling of reduction status and |
1164 | 1168 | // proper tail action for the thunked implementations. |
1165 | 1169 | if(!IsTyped<ValueToken>(term)) |
@@ -1360,7 +1364,7 @@ | ||
1360 | 1364 | |
1361 | 1365 | // XXX: As %BindParameter. |
1362 | 1366 | for(auto& o : nd) |
1363 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
1367 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
1364 | 1368 | EmplaceReference(con, o, *p, !p_ref); |
1365 | 1369 | else if(p_ref) |
1366 | 1370 | con.emplace_back(TermNode::Container(o.get_allocator()), |
@@ -1397,13 +1401,13 @@ | ||
1397 | 1401 | const auto add_tags(p_ref->GetTags() | TermTags::Unique); |
1398 | 1402 | |
1399 | 1403 | for(auto& o : nd) |
1400 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
1404 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
1401 | 1405 | EmplaceReference(con, o, *p, {}); |
1402 | 1406 | else |
1403 | 1407 | con.emplace_back(TermNode::Container(o.get_allocator()), |
1404 | - ValueObject(std::allocator_arg, a, in_place_type< | |
1405 | - TermReference>, o.Tags | add_tags, o, | |
1406 | - p_ref->GetEnvironmentReference())); | |
1408 | + std::allocator_arg, a, in_place_type<TermReference>, | |
1409 | + o.Tags | add_tags, o, | |
1410 | + p_ref->GetEnvironmentReference()); | |
1407 | 1411 | con.swap(term.GetContainerRef()); |
1408 | 1412 | } |
1409 | 1413 | else |
@@ -1431,7 +1435,7 @@ | ||
1431 | 1435 | if(const auto p = p_e->LookupName(name)) |
1432 | 1436 | { |
1433 | 1437 | using ystdex::pvoid; |
1434 | - auto& depth(NPL::Access<size_t>(*p)); | |
1438 | + auto& depth(Access<size_t>(*p)); | |
1435 | 1439 | |
1436 | 1440 | yunused(term), yunused(ctx); |
1437 | 1441 | YTraceDe(YSLib::Informative, "Depth = %zu, context = %p, semantics" |
@@ -1495,6 +1499,8 @@ | ||
1495 | 1499 | ParseLeaf(TermNode& term, string_view id) |
1496 | 1500 | { |
1497 | 1501 | YAssertNonnull(id.data()); |
1502 | + // NOTE: The lexeme shall not be empty, although the code literal '' can be | |
1503 | + // converted to an empty symbol after the processing here. | |
1498 | 1504 | YAssert(!id.empty(), "Invalid leaf token found."); |
1499 | 1505 | switch(CategorizeBasicLexeme(id)) |
1500 | 1506 | { |
@@ -1527,8 +1533,7 @@ | ||
1527 | 1533 | // NOTE: Most are same to %ParseLeaf, except for additional source |
1528 | 1534 | // information mixed into the values of %TokenValue. |
1529 | 1535 | YAssertNonnull(id.data()); |
1530 | - // NOTE: The lexeme shall not be empty, although the code literal '' can be | |
1531 | - // converted to an empty symbol after the processing here. | |
1536 | + // NOTE: Ditto. | |
1532 | 1537 | YAssert(!id.empty(), "Invalid leaf token found."); |
1533 | 1538 | switch(CategorizeBasicLexeme(id)) |
1534 | 1539 | { |
@@ -1582,7 +1587,7 @@ | ||
1582 | 1587 | YAssert(!t.empty(), "Invalid term found."); |
1583 | 1588 | ReduceChildrenOrderedAsyncUnchecked(std::next(t.begin()), t.end(), c); |
1584 | 1589 | return ReductionStatus::Partial; |
1585 | - }, trivial_swap, A1::NameTypedReducerHandler([&, n](ContextNode& c){ | |
1590 | + }, trivial_swap, NameTypedReducerHandler([&, n](ContextNode& c){ | |
1586 | 1591 | SetupNextTerm(c, term); |
1587 | 1592 | return CallN(n - 1, term, c); |
1588 | 1593 | }, "eval-combine-operator")); |
@@ -1782,7 +1787,7 @@ | ||
1782 | 1787 | // XXX: Allocators are not used here on %TermReference to avoid G++ from |
1783 | 1788 | // folding code with other basic blocks with more inefficient |
1784 | 1789 | // implementations. |
1785 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(bound)) | |
1790 | + if(const auto p = TryAccessLeafAtom<const TermReference>(bound)) | |
1786 | 1791 | { |
1787 | 1792 | p_rterm = &p->get(); |
1788 | 1793 | // NOTE: If the bound object is a term reference, referencing it |
@@ -1835,7 +1840,7 @@ | ||
1835 | 1840 | YAssert(IsCombiningTerm(term), "Invalid term found for combined term."); |
1836 | 1841 | |
1837 | 1842 | auto& fm(AccessFirstSubterm(term)); |
1838 | - const auto p_ref_fm(NPL::TryAccessLeaf<const TermReference>(fm)); | |
1843 | + const auto p_ref_fm(TryAccessLeafAtom<const TermReference>(fm)); | |
1839 | 1844 | |
1840 | 1845 | // NOTE: If this call returns normally, the combiner object implied by %fm |
1841 | 1846 | // is not owned by %term. |
@@ -1866,7 +1871,7 @@ | ||
1866 | 1871 | // in %ReduceForCombinerRef. |
1867 | 1872 | const auto& referenced(p_ref_fm->get()); |
1868 | 1873 | |
1869 | - YAssert(ystdex::ref_eq<>()(NPL::Deref(NPL::Access< | |
1874 | + YAssert(ystdex::ref_eq<>()(NPL::Deref(Access< | |
1870 | 1875 | shared_ptr<TermNode>>(*fm.begin())), referenced), |
1871 | 1876 | "Invalid subobject reference found."); |
1872 | 1877 | // XXX: Explicit copy is necessary as in the implementation of |
@@ -1879,7 +1884,7 @@ | ||
1879 | 1884 | #endif |
1880 | 1885 | // NOTE: The combiner object is in an lvalue. It is not saved by %term. |
1881 | 1886 | if(const auto p_handler |
1882 | - = NPL::TryAccessLeaf<const ContextHandler>(p_ref_fm->get())) | |
1887 | + = TryAccessLeafAtom<const ContextHandler>(p_ref_fm->get())) | |
1883 | 1888 | // NOTE: This is neutral to %NPL_Impl_NPLA1_Enable_Thunked. |
1884 | 1889 | return CombinerReturnThunk(*p_handler, term, ctx); |
1885 | 1890 | } |
@@ -1891,7 +1896,7 @@ | ||
1891 | 1896 | // XXX: Converted terms (if used, see above) are also handled here as in |
1892 | 1897 | // prvalues. |
1893 | 1898 | // NOTE: To allow being moved, %p_handler is not qualified by 'const'. |
1894 | - if(const auto p_handler = NPL::TryAccessTerm<ContextHandler>(fm)) | |
1899 | + if(const auto p_handler = TryAccessTerm<ContextHandler>(fm)) | |
1895 | 1900 | #if NPL_Impl_NPLA1_Enable_TCO |
1896 | 1901 | return |
1897 | 1902 | CombinerReturnThunk(*p_handler, term, ctx, std::move(*p_handler)); |
@@ -1919,7 +1924,7 @@ | ||
1919 | 1924 | YAssert(IsCombiningTerm(term), "Invalid term found for combined term."); |
1920 | 1925 | // XXX: %SetupNextTerm is to be called in %CombinerReturnThunk. |
1921 | 1926 | ClearCombiningTags(term); |
1922 | - if(const auto p_handler = NPL::TryAccessLeaf<const ContextHandler>(fm)) | |
1927 | + if(const auto p_handler = TryAccessLeafAtom<const ContextHandler>(fm)) | |
1923 | 1928 | return CombinerReturnThunk(*p_handler, term, ctx); |
1924 | 1929 | return ThrowCombiningFailure(term, fm, true); |
1925 | 1930 | } |
@@ -2157,12 +2162,12 @@ | ||
2157 | 2162 | YB_STATELESS |
2158 | 2163 | #endif |
2159 | 2164 | observer_ptr<const ValueObject> |
2160 | -QueryTailOperatorName(const Reducer& act) | |
2165 | +QueryTailOperatorName(const Reducer& act) ynothrow | |
2161 | 2166 | { |
2162 | 2167 | #if NPL_Impl_NPLA1_Enable_TCO |
2163 | 2168 | if(const auto p_act = act.target<TCOAction>()) |
2164 | 2169 | if(p_act->OperatorName.type() == type_id<TokenValue>()) |
2165 | - return NPL::make_observer(&p_act->OperatorName); | |
2170 | + return make_observer(&p_act->OperatorName); | |
2166 | 2171 | #else |
2167 | 2172 | yunused(act); |
2168 | 2173 | #endif |
@@ -2182,7 +2187,7 @@ | ||
2182 | 2187 | } |
2183 | 2188 | |
2184 | 2189 | bool |
2185 | -SetupTailOperatorName(TermNode& term, const ContextNode& ctx) | |
2190 | +SetupTailOperatorName(TermNode& term, const ContextNode& ctx) ynothrow | |
2186 | 2191 | { |
2187 | 2192 | if(const auto p_combining = ContextState::Access(ctx).GetCombiningTermPtr()) |
2188 | 2193 | { |
@@ -2210,16 +2215,16 @@ | ||
2210 | 2215 | { |
2211 | 2216 | const auto name(QueryContinuationName(act)); |
2212 | 2217 | const auto p(name.data() ? name.data() : |
2213 | -# if NDEBUG | |
2218 | +#if NDEBUG | |
2214 | 2219 | "?" |
2215 | -# else | |
2220 | +#else | |
2216 | 2221 | // XXX: This is enabled for debugging only because the name |
2217 | 2222 | // is not guaranteed steady. |
2218 | 2223 | ystdex::call_value_or([](const Continuation& cont) |
2219 | 2224 | -> const type_info&{ |
2220 | 2225 | return cont.Handler.target_type(); |
2221 | 2226 | }, act.target<Continuation>(), act.target_type()).name() |
2222 | -# endif | |
2227 | +#endif | |
2223 | 2228 | ); |
2224 | 2229 | const auto p_opn_vo(QueryTailOperatorName(act)); |
2225 | 2230 | // XXX: No %NPL::TryAccessValue is needed, since %p_opn_vo comes |
@@ -2231,14 +2236,14 @@ | ||
2231 | 2236 | { |
2232 | 2237 | // XXX: This clause relies on the source information for |
2233 | 2238 | // meaningful output. Assume it is used. |
2234 | -# if true | |
2239 | +#if true | |
2235 | 2240 | if(const auto p_si = QuerySourceInformation(*p_opn_vo)) |
2236 | 2241 | trace.TraceFormat(Notice, "#[continuation: %s (%s) @" |
2237 | 2242 | " %s (line %zu, column %zu)]", p_o, p, |
2238 | 2243 | p_si->first ? p_si->first->c_str() : "<unknown>", |
2239 | 2244 | p_si->second.Line + 1, p_si->second.Column + 1); |
2240 | 2245 | else |
2241 | -# endif | |
2246 | +#endif | |
2242 | 2247 | trace.TraceFormat(Notice, "#[continuation: %s (%s)]", |
2243 | 2248 | p_o, p); |
2244 | 2249 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Forms.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 语法形式。 |
14 | -\version r27233 | |
14 | +\version r27377 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 882 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-02-15 11:19:51 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-05-29 08:09 +0800 | |
20 | + 2022-06-14 18:34 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -27,7 +27,7 @@ | ||
27 | 27 | |
28 | 28 | #include "NPL/YModules.h" |
29 | 29 | #include YFM_NPL_NPLA1Forms // for YSLib, std::next, ReduceOnceLifted, |
30 | -// ResolvedTermReferencePtr, NPL::IsMovable, NPL::TryAccessReferencedTerm, | |
30 | +// ResolvedTermReferencePtr, NPL::IsMovable, TryAccessReferencedTerm, | |
31 | 31 | // ystdex::value_or, ThrowInsufficientTermsError, NPL::Deref, |
32 | 32 | // A1::NameTypedReducerHandler, ReduceReturnUnspecified, RemoveHead, IsBranch, |
33 | 33 | // AccessFirstSubterm, ReduceSubsequent, ReduceCombinedBranch, |
@@ -39,17 +39,17 @@ | ||
39 | 39 | // ResolveEnvironment, ShareMoveTerm, BindParameterWellFormed, ystdex::sfmt, |
40 | 40 | // TermToStringWithReferenceMark, ResolveTerm, LiftOtherOrCopy, |
41 | 41 | // ClearCombiningTags, SContext::Analyze, std::allocator_arg, |
42 | -// NPL::ResolveRegular, ystdex::make_transform, NPL::TryAccessLeaf, | |
43 | -// TermReference, EnvironmentList, NPL::AllocateEnvironment, | |
44 | -// ystdex::equality_comparable, CheckParameterTree, AssertValueTags, | |
45 | -// NPL::AsTermNode, ystdex::exchange, NPLException, GuardFreshEnvironment, | |
46 | -// TermTags, YSLib::Debug, YSLib::sfmt, A1::MakeForm, ystdex::expand_proxy, | |
47 | -// NPL::AccessRegular, GetLValueTagsOf, RegularizeTerm, IsBranchedList, | |
48 | -// LiftMovedOther, LiftOtherValue, ThrowValueCategoryError, std::mem_fn, | |
49 | -// ThrowListTypeErrorForNonlist, ThrowInvalidSyntaxError, | |
50 | -// CheckEnvironmentFormal, type_id, ystdex::update_thunk, IsTyped, | |
51 | -// EnvironmentGuard, BindSymbol, A1::AsForm, ystdex::bind1, IsNPLASymbol, | |
52 | -// ystdex::fast_all_of, ystdex::call_value_or, LiftCollapsed, YSLib::usystem; | |
42 | +// NPL::ResolveRegular, ystdex::make_transform, TryAccessLeaf, TermReference, | |
43 | +// EnvironmentList, NPL::AllocateEnvironment, ystdex::equality_comparable, | |
44 | +// CheckParameterTree, AssertValueTags, NPL::AsTermNode, ystdex::exchange, | |
45 | +// NPLException, GuardFreshEnvironment, TermTags, YSLib::Debug, YSLib::sfmt, | |
46 | +// A1::MakeForm, ystdex::expand_proxy, AccessRegular, GetLValueTagsOf, | |
47 | +// RegularizeTerm, IsBranchedList, LiftMovedOther, LiftOtherValue, | |
48 | +// ThrowValueCategoryError, std::mem_fn, ThrowListTypeErrorForNonlist, | |
49 | +// ThrowInvalidSyntaxError, CheckEnvironmentFormal, type_id, | |
50 | +// ystdex::update_thunk, IsTyped, EnvironmentGuard, BindSymbol, A1::AsForm, | |
51 | +// ystdex::bind1, IsNPLASymbol, ystdex::fast_all_of, ystdex::call_value_or, | |
52 | +// LiftCollapsed, YSLib::usystem; | |
53 | 53 | #include "NPLA1Internals.h" // for A1::Internals API; |
54 | 54 | #include YFM_NPL_SContext // for Session; |
55 | 55 | #include <ystdex/functor.hpp> // for ystdex::id; |
@@ -116,7 +116,7 @@ | ||
116 | 116 | YB_ATTR_nodiscard YB_PURE bool |
117 | 117 | ExtractBool(const TermNode& term) |
118 | 118 | { |
119 | - return ystdex::value_or(NPL::TryAccessReferencedTerm<bool>(term), true); | |
119 | + return ystdex::value_or(TryAccessReferencedTerm<bool>(term), true); | |
120 | 120 | } |
121 | 121 | |
122 | 122 | //! \since build 860 |
@@ -695,7 +695,7 @@ | ||
695 | 695 | return ystdex::make_transform(iter, [&](TNIter i) -> ValueObject{ |
696 | 696 | // XXX: Like %LiftToReturn, but for %Value only. |
697 | 697 | if(const auto p |
698 | - = NPL::TryAccessLeaf<const TermReference>(NPL::Deref(i))) | |
698 | + = TryAccessLeafAtom<const TermReference>(NPL::Deref(i))) | |
699 | 699 | { |
700 | 700 | if(nonmodifying || !p->IsMovable()) |
701 | 701 | return p->get().Value; |
@@ -994,46 +994,44 @@ | ||
994 | 994 | }; |
995 | 995 | |
996 | 996 | |
997 | -//! \since build 944 | |
997 | +//! \since build 947 | |
998 | +//@{ | |
999 | +template<typename... _tParams> | |
998 | 1000 | void |
999 | -MakeValueListOrMove(TermNode::Container& con, TermNode& nd, | |
1000 | - ResolvedTermReferencePtr p_ref) | |
1001 | -{ | |
1002 | - MakeValueOrMove(p_ref, [&]{ | |
1003 | - for(const auto& sub : nd) | |
1004 | - con.push_back(sub); | |
1005 | - }, [&]{ | |
1006 | - // XXX: No cyclic reference check. | |
1007 | - con.splice(con.end(), nd.GetContainerRef()); | |
1008 | - }); | |
1009 | -} | |
1010 | - | |
1011 | -//! \since build 859 | |
1012 | -YB_NORETURN void | |
1013 | -ThrowConsError(TermNode& nd, ResolvedTermReferencePtr p_ref) | |
1014 | -{ | |
1015 | - throw ListTypeError(ystdex::sfmt( | |
1016 | - "Expected a list for the 2nd argument, got '%s'.", | |
1017 | - TermToStringWithReferenceMark(nd, p_ref).c_str())); | |
1018 | -} | |
1019 | - | |
1020 | -//! \since build 944 | |
1021 | -void | |
1022 | -ConsItem(TermNode::Container& con, TermNode& y) | |
1023 | -{ | |
1024 | - ResolveTerm([&](TermNode& nd_y, ResolvedTermReferencePtr p_ref){ | |
1001 | +ConsSplice(TermNode tm, TermNode& nd, _tParams&&... args) | |
1002 | +{ | |
1003 | + auto& tcon(tm.GetContainerRef()); | |
1004 | + auto& con(nd.GetContainerRef()); | |
1005 | + | |
1006 | + // XXX: No other cyclic reference check. | |
1007 | + YAssert(!ystdex::ref_eq<>()(con, tcon), "Invalid self move found."); | |
1008 | + tcon.splice(tcon.begin(), con, con.begin(), yforward(args)...); | |
1009 | + tcon.swap(con); | |
1010 | +} | |
1011 | + | |
1012 | +// XXX: Returning term instead of the container allows to pass improper lists, | |
1013 | +// also perserves the allocator on | |
1014 | +// copy. | |
1015 | +YB_ATTR_nodiscard TermNode | |
1016 | +ConsItem(TermNode& y) | |
1017 | +{ | |
1018 | + return ResolveTerm([&](TermNode& nd_y, ResolvedTermReferencePtr p_ref_y){ | |
1025 | 1019 | if(IsList(nd_y)) |
1026 | - MakeValueListOrMove(con, nd_y, p_ref); | |
1020 | + // TODO: Use %LiftOtherOrCopy? | |
1021 | + return MakeValueOrMove(p_ref_y, [&]{ | |
1022 | + // XXX: The order is significant for the exception safety | |
1023 | + // guarantee. | |
1024 | + return nd_y; | |
1025 | + }, [&]{ | |
1026 | + // NOTE: This is necessary because %con can be moved to its | |
1027 | + // ancestors. | |
1028 | + return std::move(nd_y); | |
1029 | + }); | |
1027 | 1030 | else |
1028 | - ThrowConsError(nd_y, p_ref); | |
1031 | + ThrowListTypeErrorForNonlist(nd_y, p_ref_y); | |
1029 | 1032 | }, y); |
1030 | 1033 | } |
1031 | -//! \since build 859 | |
1032 | -void | |
1033 | -ConsItem(TermNode& term, TermNode& y) | |
1034 | -{ | |
1035 | - ConsItem(term.GetContainerRef(), y); | |
1036 | -} | |
1034 | +//@} | |
1037 | 1035 | |
1038 | 1036 | //! \since build 912 |
1039 | 1037 | ReductionStatus |
@@ -1044,9 +1042,7 @@ | ||
1044 | 1042 | |
1045 | 1043 | auto i(term.begin()); |
1046 | 1044 | |
1047 | - ++i; | |
1048 | - ConsItem(term, NPL::Deref(i)); | |
1049 | - term.erase(i); | |
1045 | + ConsSplice(ConsItem(NPL::Deref(++i)), term); | |
1050 | 1046 | return ReductionStatus::Retained; |
1051 | 1047 | } |
1052 | 1048 |
@@ -1133,7 +1129,7 @@ | ||
1133 | 1129 | { |
1134 | 1130 | return NPL::ResolveTerm([&](TermNode& nd, ResolvedTermReferencePtr p_ref){ |
1135 | 1131 | return DispatchContextHandler( |
1136 | - NPL::AccessRegular<ContextHandler>(nd, p_ref), p_ref, f, f2); | |
1132 | + AccessRegular<ContextHandler>(nd, p_ref), p_ref, f, f2); | |
1137 | 1133 | }, term); |
1138 | 1134 | } |
1139 | 1135 | //@} |
@@ -1160,7 +1156,7 @@ | ||
1160 | 1156 | // NOTE: Simplified from 'sigil == '&' and 'can_modify && temp' branch in |
1161 | 1157 | // %BindParameterObject::operator(), except that %TermTags::Temporary is |
1162 | 1158 | // not set as %MarkTemporaryTerm in NPLA1.cpp. |
1163 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
1159 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
1164 | 1160 | // NOTE: Reference collapsed by move. |
1165 | 1161 | mv(std::move(o.GetContainerRef()), |
1166 | 1162 | TermReference(BindReferenceTags(*p), std::move(*p))); |
@@ -1174,7 +1170,7 @@ | ||
1174 | 1170 | // NOTE: Simplified from 'sigil == '&' and 'can_modify && temp' branch in |
1175 | 1171 | // %BindParameterObject::operator(), except that %TermTags::Temporary is |
1176 | 1172 | // not set as %MarkTemporaryTerm in NPLA1.cpp. |
1177 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
1173 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
1178 | 1174 | // NOTE: Reference collapsed by move. |
1179 | 1175 | p->SetTags(BindReferenceTags(*p)); |
1180 | 1176 | } |
@@ -1196,7 +1192,7 @@ | ||
1196 | 1192 | // NOTE: Simplified from '&' and not 'can_modify && temp' branch in |
1197 | 1193 | // %BindParameterObject::operator(). |
1198 | 1194 | mv(TermNode::Container(o.GetContainer()), [&]() -> TermReference{ |
1199 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
1195 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
1200 | 1196 | return TermReference(BindReferenceTags(*p), *p); |
1201 | 1197 | return TermReference(GetLValueTagsOf(o.Tags | o_tags), o, r_env); |
1202 | 1198 | }()); |
@@ -1217,7 +1213,7 @@ | ||
1217 | 1213 | YB_ATTR_nodiscard TermNode |
1218 | 1214 | EvaluateBoundLValue(TermNode& term, const shared_ptr<Environment>& p_env) |
1219 | 1215 | { |
1220 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(term)) | |
1216 | + if(const auto p = TryAccessLeafAtom<TermReference>(term)) | |
1221 | 1217 | return TermNode(std::allocator_arg, term.get_allocator(), |
1222 | 1218 | term.GetContainer(), EnsureLValueReference(*p)); |
1223 | 1219 | return EvaluateToLValueReference(term, p_env); |
@@ -1229,7 +1225,7 @@ | ||
1229 | 1225 | YB_ATTR_nodiscard TermNode |
1230 | 1226 | EvaluateBoundLValueMoved(TermNode& term, const shared_ptr<Environment>& p_env) |
1231 | 1227 | { |
1232 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(term)) | |
1228 | + if(const auto p = TryAccessLeafAtom<TermReference>(term)) | |
1233 | 1229 | { |
1234 | 1230 | *p = EnsureLValueReference(std::move(*p)); |
1235 | 1231 | return std::move(term); |
@@ -1245,7 +1241,7 @@ | ||
1245 | 1241 | EvaluateLocalObject(TermNode& o, const shared_ptr<Environment>& p_env) |
1246 | 1242 | { |
1247 | 1243 | // NOTE: Make unique reference as a bound temporary object. |
1248 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
1244 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
1249 | 1245 | { |
1250 | 1246 | p->SetTags(BindReferenceTags(*p)); |
1251 | 1247 | return TermNode(std::allocator_arg, o.get_allocator(), |
@@ -1264,7 +1260,7 @@ | ||
1264 | 1260 | EvaluateLocalObjectMoved(TermNode& o, const shared_ptr<Environment>& p_env) |
1265 | 1261 | { |
1266 | 1262 | // NOTE: Make unique reference as a bound temporary object. |
1267 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
1263 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
1268 | 1264 | { |
1269 | 1265 | // NOTE: See also %EnsureLValueReference. |
1270 | 1266 | *p = TermReference(BindReferenceTags(*p) & ~TermTags::Unique, |
@@ -1296,7 +1292,7 @@ | ||
1296 | 1292 | const TermNode::Container& con, TermReference ref, |
1297 | 1293 | TermNode& nd) |
1298 | 1294 | { |
1299 | - auto& h(NPL::AccessRegular<ContextHandler>(nd, true)); | |
1295 | + auto& h(AccessRegular<ContextHandler>(nd, true)); | |
1300 | 1296 | |
1301 | 1297 | if(const auto p = h.target<FormContextHandler>()) |
1302 | 1298 | { |
@@ -1320,7 +1316,7 @@ | ||
1320 | 1316 | EvaluateBoundLValueUnwrapped(TermNode& term, |
1321 | 1317 | const shared_ptr<Environment>& p_env) |
1322 | 1318 | { |
1323 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(term)) | |
1319 | + if(const auto p = TryAccessLeafAtom<TermReference>(term)) | |
1324 | 1320 | return EvaluateBoundUnwrappedLValueDispatch( |
1325 | 1321 | term.get_allocator(), term.GetContainer(), *p, p->get()); |
1326 | 1322 | return EvaluateBoundUnwrappedLValueDispatch(term.get_allocator(), |
@@ -1347,7 +1343,7 @@ | ||
1347 | 1343 | // XXX: Similar to the implementation of %ReduceToReference in NPLA.cpp. |
1348 | 1344 | term.CopyContent(tm); |
1349 | 1345 | // NOTE: Propagate tags if it is a term reference. |
1350 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(term)) | |
1346 | + if(const auto p = TryAccessLeafAtom<TermReference>(term)) | |
1351 | 1347 | p->PropagateFrom(tags); |
1352 | 1348 | // XXX: Term tags are currently not respected in prvalues. |
1353 | 1349 | } |
@@ -1389,7 +1385,7 @@ | ||
1389 | 1385 | // however, not x86_64-pc-linux G++ 11.1. |
1390 | 1386 | const bool list_not_move(!NPL::IsMovable(p_ref)); |
1391 | 1387 | |
1392 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(tm)) | |
1388 | + if(const auto p = TryAccessLeafAtom<const TermReference>(tm)) | |
1393 | 1389 | { |
1394 | 1390 | if(list_not_move) |
1395 | 1391 | LiftPropagatedReference(term, tm, p_ref->GetTags()); |
@@ -1432,7 +1428,7 @@ | ||
1432 | 1428 | auto& tm(AccessFirstSubterm(nd)); |
1433 | 1429 | const bool move(NPL::IsMovable(tags)); |
1434 | 1430 | |
1435 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(tm)) | |
1431 | + if(const auto p = TryAccessLeafAtom<const TermReference>(tm)) | |
1436 | 1432 | { |
1437 | 1433 | if(move) |
1438 | 1434 | { |
@@ -1456,9 +1452,8 @@ | ||
1456 | 1452 | // not unique due to 2-pass iterations (e.g. it may be also used in |
1457 | 1453 | // a interleaved call to %BranchRestFwdReferenced with unspecified |
1458 | 1454 | // order to this call). |
1459 | - term.Value = ValueObject(std::allocator_arg, term.get_allocator(), | |
1460 | - in_place_type<TermReference>, PropagateTo(tm.Tags, tags), tm, | |
1461 | - r_env); | |
1455 | + term.SetValue(in_place_type<TermReference>, PropagateTo(tm.Tags, tags), | |
1456 | + tm, r_env); | |
1462 | 1457 | // NOTE: No %TermNode::ClearContainer is here because %term is expected |
1463 | 1458 | // newly created. |
1464 | 1459 | YAssert(IsLeaf(term), "Invalid term found"); |
@@ -1504,7 +1499,7 @@ | ||
1504 | 1499 | { |
1505 | 1500 | // XXX: Simple 'ReduceToValue(term, tm)' is wrong because it may move |
1506 | 1501 | // non-unqiue reference object away. |
1507 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(tm)) | |
1502 | + if(const auto p = TryAccessLeafAtom<const TermReference>(tm)) | |
1508 | 1503 | LiftMovedOther(term, *p, move && p->IsMovable()); |
1509 | 1504 | else |
1510 | 1505 | // XXX: Term tags are currently not respected in prvalues. |
@@ -1583,7 +1578,7 @@ | ||
1583 | 1578 | SetFirstRest([f](TermNode& nd_x, TermNode& y){ |
1584 | 1579 | auto& dst(AccessFirstSubterm(nd_x)); |
1585 | 1580 | |
1586 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(y)) | |
1581 | + if(const auto p = TryAccessLeafAtom<TermReference>(y)) | |
1587 | 1582 | f(dst, y, *p); |
1588 | 1583 | else |
1589 | 1584 | LiftTerm(dst, y); |
@@ -1605,24 +1600,16 @@ | ||
1605 | 1600 | SetRestImpl(TermNode& term) |
1606 | 1601 | { |
1607 | 1602 | SetFirstRest([](TermNode& nd_x, TermNode& y){ |
1608 | - ResolveTerm([&](TermNode& nd_y, ResolvedTermReferencePtr p_ref_y){ | |
1609 | - // XXX: How to simplify? Merge with %BindParameterObject? | |
1610 | - if(IsList(nd_y)) | |
1611 | - { | |
1612 | - const auto a(nd_x.get_allocator()); | |
1613 | - TermNode::Container con_new(a); | |
1614 | - | |
1615 | - con_new.emplace_back(); | |
1616 | - MakeValueListOrMove(con_new, nd_y, p_ref_y); | |
1617 | - _rLift(con_new); | |
1618 | - // XXX: The order is significant. | |
1619 | - con_new.front() = MoveFirstSubterm(nd_x); | |
1620 | - swap(nd_x.GetContainerRef(), con_new); | |
1621 | - nd_x.Value.Clear(); | |
1622 | - } | |
1623 | - else | |
1624 | - ThrowListTypeErrorForNonlist(nd_y, p_ref_y); | |
1625 | - }, y); | |
1603 | + auto tcon(ConsItem(y)); | |
1604 | + | |
1605 | + ConsSplice(tcon, nd_x); | |
1606 | + // XXX: Assume the call to %_rLift does not throw, so it can be | |
1607 | + // reordered here. | |
1608 | + // TODO: What to do on %nd_x.Value if lifting is requested? | |
1609 | + _rLift(nd_x.GetContainerRef()); | |
1610 | + // XXX: The order is significant for the exception safety | |
1611 | + // guarantee. | |
1612 | + nd_x.Value.Clear(); | |
1626 | 1613 | }, term); |
1627 | 1614 | } |
1628 | 1615 |
@@ -1739,7 +1726,7 @@ | ||
1739 | 1726 | auto& tm(NPL::Deref(++i)); |
1740 | 1727 | |
1741 | 1728 | return ReduceSubsequent(tm, ctx, |
1742 | - A1::NameTypedReducerHandler([&, i, wrap, no_lift]{ | |
1729 | + NameTypedReducerHandler([&, i, wrap, no_lift]{ | |
1743 | 1730 | return ReduceCreateFunction(term, [&]{ |
1744 | 1731 | // XXX: Keep %ResolveParentFrom in lambda-expression is a bit more |
1745 | 1732 | // efficient for x86_64-pc-linux G++ 12.1. |
@@ -1918,13 +1905,11 @@ | ||
1918 | 1905 | |
1919 | 1906 | ForwardToUnwrapped(comb); |
1920 | 1907 | { |
1921 | - TermNode::Container tcon(term.get_allocator()); | |
1922 | - | |
1923 | - tcon.push_back(std::move(comb)); | |
1924 | - ConsItem(tcon, NPL::Deref(++i)); | |
1925 | - tcon.swap(term.GetContainerRef()); | |
1908 | + auto t(ConsItem(NPL::Deref(++i))); | |
1909 | + | |
1910 | + t.GetContainerRef().push_front(std::move(comb)); | |
1911 | + swap(t, term); | |
1926 | 1912 | } |
1927 | - ClearCombiningTags(term); | |
1928 | 1913 | // NOTE: The precondition is same to the last call in %EvalImplUnchecked. |
1929 | 1914 | // See also the precondition of %Combine<TailCall>::RelayEnvSwitch. |
1930 | 1915 | return Combine<TailCall>::RelayEnvSwitch(ctx, term, std::move(p_env)); |
@@ -1943,9 +1928,8 @@ | ||
1943 | 1928 | { |
1944 | 1929 | const auto last(std::prev(term.end())); |
1945 | 1930 | |
1946 | - ConsItem(term, Deref(last)); | |
1947 | - term.erase(last), | |
1948 | 1931 | RemoveHead(term); |
1932 | + ConsSplice(ConsItem(NPL::Deref(last)), term, last); | |
1949 | 1933 | } |
1950 | 1934 | else |
1951 | 1935 | LiftOther(term, head); |
@@ -1956,15 +1940,16 @@ | ||
1956 | 1940 | using TermPrefixGuard = decltype(ystdex::unique_guard(ystdex::prefix_eraser< |
1957 | 1941 | TermNode::Container>(std::declval<TermNode::Container&>()))); |
1958 | 1942 | |
1959 | -TermPrefixGuard | |
1943 | +YB_ATTR_nodiscard inline TermPrefixGuard | |
1960 | 1944 | GuardTermPrefix(TermNode::Container& con) ynothrow |
1961 | 1945 | { |
1962 | 1946 | return |
1963 | 1947 | ystdex::unique_guard(ystdex::prefix_eraser<TermNode::Container>(con)); |
1964 | 1948 | } |
1965 | 1949 | |
1950 | +//! \since build 947 | |
1966 | 1951 | void |
1967 | -RemoveTermPostfix(TermPrefixGuard& gd) ynothrow | |
1952 | +RemoveTermSuffix(TermPrefixGuard& gd) ynothrow | |
1968 | 1953 | { |
1969 | 1954 | auto& eraser(gd.func.func); |
1970 | 1955 | auto& tcon(eraser.container); |
@@ -1984,7 +1969,7 @@ | ||
1984 | 1969 | |
1985 | 1970 | con.insert(con.insert(con.begin(), yforward(lv_l)), |
1986 | 1971 | EvaluateBoundLValueUnwrapped(tail, d)); |
1987 | - RemoveTermPostfix(gd); | |
1972 | + RemoveTermSuffix(gd); | |
1988 | 1973 | } |
1989 | 1974 | term.Value.Clear(); |
1990 | 1975 | // XXX: No %ClearCombiningTags is called, as it would be determined later |
@@ -2116,6 +2101,8 @@ | ||
2116 | 2101 | }, term, ctx); |
2117 | 2102 | } |
2118 | 2103 | |
2104 | +// XXX: Direct assignment of %TermRange to %ValueObject is likely more efficient | |
2105 | +// than %SetValue. | |
2119 | 2106 | //! \since build 916 |
2120 | 2107 | struct TermRange final |
2121 | 2108 | { |
@@ -2164,7 +2151,7 @@ | ||
2164 | 2151 | if(p_ref->IsMovable()) |
2165 | 2152 | { |
2166 | 2153 | LiftOther(term, nd); |
2167 | - term.SetValue(TermRange(term)); | |
2154 | + term.Value = TermRange(term); | |
2168 | 2155 | } |
2169 | 2156 | else |
2170 | 2157 | // NOTE: Encode the value category information of the list. |
@@ -2177,11 +2164,11 @@ | ||
2177 | 2164 | // shall be copied on the element accesses later. This is |
2178 | 2165 | // comsumed by %IsExpiredRange, only used to provide the |
2179 | 2166 | // 3rd argument to the call to %ExtractRangeFirstOrCopy. |
2180 | - term.Tags |= TermTags::Nonmodifying, | |
2181 | - term.SetValue(TermRange(nd, p_ref->GetTags())); | |
2167 | + yunseq(term.Tags |= TermTags::Nonmodifying, | |
2168 | + term.Value = TermRange(nd, p_ref->GetTags())); | |
2182 | 2169 | } |
2183 | 2170 | else |
2184 | - term.SetValue(TermRange(term)); | |
2171 | + term.Value = TermRange(term); | |
2185 | 2172 | } |
2186 | 2173 | else |
2187 | 2174 | // NOTE: Always treat the list as an lvalue as in the derivation. |
@@ -2376,7 +2363,7 @@ | ||
2376 | 2363 | auto& nterm(tcon.emplace_back()); |
2377 | 2364 | auto& o(NPL::Deref(tr.First)); |
2378 | 2365 | |
2379 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(o)) | |
2366 | + if(const auto p = TryAccessLeafAtom<const TermReference>(o)) | |
2380 | 2367 | { |
2381 | 2368 | // NOTE: The tags of the term range shall be prepared in the |
2382 | 2369 | // call to %PrepareFoldRList or similar functions. The nonmodifying |
@@ -2417,7 +2404,7 @@ | ||
2417 | 2404 | const bool move(NPL::IsMovable(o_tags)); |
2418 | 2405 | |
2419 | 2406 | #if false |
2420 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(tm)) | |
2407 | + if(const auto p = TryAccessLeafAtom<const TermReference>(tm)) | |
2421 | 2408 | { |
2422 | 2409 | LiftOtherOrCopy(nterm, p->get(), move ? p->IsMovable() |
2423 | 2410 | : NPL::IsMovable(PropagateTo(p->GetTags(), o_tags))); |
@@ -2897,18 +2884,17 @@ | ||
2897 | 2884 | |
2898 | 2885 | for(auto& o : nd) |
2899 | 2886 | { |
2900 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(o)) | |
2901 | - con.emplace_back(o.GetContainer(), ValueObject( | |
2902 | - std::allocator_arg, a, in_place_type<TermReference>, *p)); | |
2887 | + if(const auto p = TryAccessLeafAtom<TermReference>(o)) | |
2888 | + con.emplace_back(o.GetContainer(), std::allocator_arg, a, | |
2889 | + in_place_type<TermReference>, *p); | |
2903 | 2890 | else |
2904 | 2891 | con.emplace_back(TermNode::Container(o.get_allocator()), |
2905 | - ValueObject(std::allocator_arg, a, in_place_type< | |
2906 | - TermReference>, GetLValueTagsOf(o.Tags | o_tags) | |
2907 | - | TermTags::Unique, o, r_env)); | |
2892 | + std::allocator_arg, a, in_place_type<TermReference>, | |
2893 | + GetLValueTagsOf(o.Tags | o_tags) | TermTags::Unique, o, r_env); | |
2908 | 2894 | } |
2909 | 2895 | con.swap(term.GetContainerRef()); |
2910 | 2896 | // NOTE: As %PrepareFoldRList. |
2911 | - term.SetValue(TermRange(term, TermTags::Temporary)); | |
2897 | + term.Value = TermRange(term, TermTags::Temporary); | |
2912 | 2898 | } |
2913 | 2899 | |
2914 | 2900 | //! \since build 918 |
@@ -2942,7 +2928,7 @@ | ||
2942 | 2928 | // NOTE: Optimize by the fast path for cases of zero arguments. |
2943 | 2929 | if(IsEmpty(bindings)) |
2944 | 2930 | return LetEmptyNoEnv(term, ctx, no_lift); |
2945 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(bindings)) | |
2931 | + if(const auto p = TryAccessLeafAtom<TermReference>(bindings)) | |
2946 | 2932 | { |
2947 | 2933 | auto& nd(p->get()); |
2948 | 2934 |
@@ -2961,7 +2947,7 @@ | ||
2961 | 2947 | else if(IsList(nd)) |
2962 | 2948 | { |
2963 | 2949 | bindings.ClearContainer(), |
2964 | - bindings.SetValue(TermRange(nd, p->GetTags())); | |
2950 | + bindings.Value = TermRange(nd, p->GetTags()); | |
2965 | 2951 | con.push_front(nd.GetContainer().front()); |
2966 | 2952 | ++bindings.Value.GetObject<TermRange>().First; |
2967 | 2953 | } |
@@ -2969,7 +2955,7 @@ | ||
2969 | 2955 | ThrowInsufficientTermsError(nd, true); |
2970 | 2956 | } |
2971 | 2957 | // NOTE: The %TermRange is from the converted result above. |
2972 | - else if(const auto p_tr = NPL::TryAccessLeaf<TermRange>(bindings)) | |
2958 | + else if(const auto p_tr = TryAccessLeaf<TermRange>(bindings)) | |
2973 | 2959 | { |
2974 | 2960 | // XXX: Empty ranges shall not be converted to %TermRange above; they |
2975 | 2961 | // are from the handling of other non-empty %TermRange values. |
@@ -3040,7 +3026,7 @@ | ||
3040 | 3026 | ContextState::Access(ctx).ClearCombiningTerm(); |
3041 | 3027 | term.Value.Clear(); |
3042 | 3028 | // XXX: The nested 'combine-return' continuations in |
3043 | - // %ReduceCombined are omitteed even when TCO is not available, | |
3029 | + // %ReduceCombined are omitted even when TCO is not available, | |
3044 | 3030 | // since they are still idempotent in the tail context |
3045 | 3031 | // (guaranteed by the semantics of the derivation in the |
3046 | 3032 | // operation). The enclosing call initialiating %LetAsterisk or |
@@ -3064,7 +3050,7 @@ | ||
3064 | 3050 | // XXX: The call to %GetLValueTagsOf on the tag argument for |
3065 | 3051 | // %BranchFirstReferenced is unnecessary. See the comments in |
3066 | 3052 | // %ListRangeExtract. |
3067 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(extracted)) | |
3053 | + if(const auto p = TryAccessLeafAtom<TermReference>(extracted)) | |
3068 | 3054 | { |
3069 | 3055 | auto& nd(p->get()); |
3070 | 3056 |
@@ -3085,7 +3071,7 @@ | ||
3085 | 3071 | auto& nterm(*con.emplace_front().emplace()); |
3086 | 3072 | auto& tm(AccessFirstSubterm(extracted)); |
3087 | 3073 | |
3088 | - if(const auto p_ref = NPL::TryAccessLeaf<const TermReference>(tm)) | |
3074 | + if(const auto p_ref = TryAccessLeafAtom<const TermReference>(tm)) | |
3089 | 3075 | { |
3090 | 3076 | if(!p_ref->IsReferencedLValue()) |
3091 | 3077 | LiftMovedOther(nterm, *p_ref, p_ref->IsMovable()); |
@@ -3120,7 +3106,7 @@ | ||
3120 | 3106 | ThrowInsufficientTermsError(nd, true); |
3121 | 3107 | }); |
3122 | 3108 | |
3123 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(extracted)) | |
3109 | + if(const auto p = TryAccessLeafAtom<TermReference>(extracted)) | |
3124 | 3110 | return letc(p->get(), p->GetEnvironmentReference(), p->GetTags(), |
3125 | 3111 | p->IsMovable()); |
3126 | 3112 | return letc(extracted, ctx.GetRecordPtr(), |
@@ -3159,7 +3145,7 @@ | ||
3159 | 3145 | // NOTE: Optimize by the fast path for cases of zero arguments. |
3160 | 3146 | if(IsEmpty(bindings)) |
3161 | 3147 | return LetEmpty(term, ctx, no_lift, with_env); |
3162 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(bindings)) | |
3148 | + if(const auto p = TryAccessLeafAtom<TermReference>(bindings)) | |
3163 | 3149 | { |
3164 | 3150 | auto& nd(p->get()); |
3165 | 3151 |
@@ -3174,8 +3160,8 @@ | ||
3174 | 3160 | p->GetTags()); |
3175 | 3161 | else if(IsList(nd)) |
3176 | 3162 | // NOTE: As %PrepareFoldRList. |
3177 | - forwarded.SetValue(TermRange(nd, p->GetTags())), | |
3178 | - forwarded.Tags = TermTags::Nonmodifying; | |
3163 | + yunseq(forwarded.Value = TermRange(nd, p->GetTags()), | |
3164 | + forwarded.Tags = TermTags::Nonmodifying); | |
3179 | 3165 | else |
3180 | 3166 | ThrowInsufficientTermsError(nd, true); |
3181 | 3167 | } |
@@ -3254,7 +3240,7 @@ | ||
3254 | 3240 | for(auto& x : term) |
3255 | 3241 | // NOTE: As %MoveRValueToForward, but with same term to |
3256 | 3242 | // be lifted. |
3257 | - if(const auto p = NPL::TryAccessLeaf<const TermReference>(x)) | |
3243 | + if(const auto p = TryAccessLeafAtom<const TermReference>(x)) | |
3258 | 3244 | if(!p->IsReferencedLValue()) |
3259 | 3245 | LiftOtherOrCopy(x, p->get(), p->IsModifiable()); |
3260 | 3246 | } |
@@ -3332,7 +3318,7 @@ | ||
3332 | 3318 | // not used of operator, so %SetupTailOperatorName is not |
3333 | 3319 | // called. |
3334 | 3320 | if(const auto p |
3335 | - = NPL::TryAccessLeaf<const TermReference>(bound)) | |
3321 | + = TryAccessLeafAtom<const TermReference>(bound)) | |
3336 | 3322 | { |
3337 | 3323 | if(p->IsTemporary()) |
3338 | 3324 | LiftOtherOrCopy(nterm, p->get(), p->IsModifiable()); |
@@ -3594,7 +3580,7 @@ | ||
3594 | 3580 | return bool(ystdex::call_value_or([this] YB_LAMBDA_ANNOTATE( |
3595 | 3581 | (const Encapsulation& enc), ynothrow, pure){ |
3596 | 3582 | return Get() == enc.Get(); |
3597 | - }, NPL::TryAccessReferencedTerm<Encapsulation>(tm))); | |
3583 | + }, TryAccessReferencedTerm<Encapsulation>(tm))); | |
3598 | 3584 | }, term); |
3599 | 3585 | } |
3600 | 3586 |
@@ -3612,13 +3598,13 @@ | ||
3612 | 3598 | // NOTE: As an lvalue reference, the object in %tm cannot be |
3613 | 3599 | // destroyed. |
3614 | 3600 | if(const auto p |
3615 | - = NPL::TryAccessLeaf<const TermReference>(tm)) | |
3601 | + = TryAccessLeafAtom<const TermReference>(tm)) | |
3616 | 3602 | term.SetContent(tm.GetContainer(), *p); |
3617 | 3603 | else |
3618 | 3604 | { |
3619 | 3605 | // XXX: Subterms cleanup is deferred. |
3620 | 3606 | // XXX: Allocators are not used here for performance. |
3621 | - term.Value.assign(in_place_type<TermReference>, tm, | |
3607 | + term.SetValue(in_place_type<TermReference>, tm, | |
3622 | 3608 | p_ref->GetEnvironmentReference()); |
3623 | 3609 | return ReductionStatus::Clean; |
3624 | 3610 | } |
@@ -3695,7 +3681,7 @@ | ||
3695 | 3681 | auto i(std::next(term.begin())); |
3696 | 3682 | |
3697 | 3683 | // XXX: Use captured %ctx seems more efficient here. |
3698 | - return ReduceSubsequent(*i, ctx, A1::NameTypedReducerHandler([&, i]{ | |
3684 | + return ReduceSubsequent(*i, ctx, NameTypedReducerHandler([&, i]{ | |
3699 | 3685 | auto j(i); |
3700 | 3686 | |
3701 | 3687 | if(!ExtractBool(*j)) |
@@ -4446,7 +4432,7 @@ | ||
4446 | 4432 | auto& x(*++i); |
4447 | 4433 | |
4448 | 4434 | if(const auto p |
4449 | - = NPL::TryAccessLeaf<const TermReference>(x)) | |
4435 | + = TryAccessLeafAtom<const TermReference>(x)) | |
4450 | 4436 | { |
4451 | 4437 | if(!p->IsReferencedLValue()) |
4452 | 4438 | LiftMovedOther(x, *p, p->IsMovable()); |
@@ -4649,7 +4635,7 @@ | ||
4649 | 4635 | |
4650 | 4636 | // TODO: Optimize the case of empty binding lists, as %LetEmpty. |
4651 | 4637 | // NOTE: As %LetOrRecImpl. |
4652 | - if(const auto p = NPL::TryAccessLeaf<TermReference>(bindings)) | |
4638 | + if(const auto p = TryAccessLeafAtom<TermReference>(bindings)) | |
4653 | 4639 | { |
4654 | 4640 | auto& nd(p->get()); |
4655 | 4641 |
@@ -4657,8 +4643,8 @@ | ||
4657 | 4643 | LetExpireChecked(forwarded, nd, p->GetEnvironmentReference(), |
4658 | 4644 | p->GetTags()); |
4659 | 4645 | else if(IsList(nd)) |
4660 | - forwarded.SetValue(TermRange(nd, p->GetTags())), | |
4661 | - forwarded.Tags = TermTags::Nonmodifying; | |
4646 | + yunseq(forwarded.Value = TermRange(nd, p->GetTags()), | |
4647 | + forwarded.Tags = TermTags::Nonmodifying); | |
4662 | 4648 | else |
4663 | 4649 | ThrowInsufficientTermsError(nd, true); |
4664 | 4650 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Internals.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 内部接口。 |
14 | -\version r20628 | |
14 | +\version r20644 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 473 |
17 | 17 | \par 创建时间: |
18 | 18 | 2020-02-15 13:20:08 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-06-05 01:26 +0800 | |
20 | + 2022-06-13 23:54 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 非公开模块名称: |
@@ -256,19 +256,20 @@ | ||
256 | 256 | |
257 | 257 | // NOTE: Irregular representation is constructed for the subobject |
258 | 258 | // reference. |
259 | - const auto a(term.get_allocator()); | |
260 | - auto& sub(NPL::Deref(p_sub)); | |
259 | + auto& con(term.GetContainerRef()); | |
260 | + auto i(con.begin()); | |
261 | 261 | |
262 | -#if true | |
263 | - TermNode tm(std::allocator_arg, a, {NPL::AsTermNode(a, std::move(p_sub))}, | |
264 | - std::allocator_arg, a, TermReference(sub, r_env)); | |
265 | - | |
266 | - term.SetContent(std::move(tm)); | |
267 | -#else | |
268 | - term = TermNode(std::allocator_arg, a, | |
269 | - {NPL::AsTermNode(a, std::move(p_sub))}, | |
270 | - std::allocator_arg, a, TermReference(sub, r_env)); | |
271 | -#endif | |
262 | + // XXX: Set %Value first. Although this is not strongly exception-safe, | |
263 | + // it guarantees no unexpected copies of user-defined objects remained even | |
264 | + // if the following operations exit via exception. The order of setting of | |
265 | + // %Tags is insignificant, though. | |
266 | + term.SetValue(TermReference(NPL::Deref(p_sub), r_env)), | |
267 | + term.Tags = TermTags::Unqualified; | |
268 | + // XXX: Not using %ystdex::prefix_eraser because there is known 1 subterm to | |
269 | + // be inserted. | |
270 | + con.insert(i, NPL::AsTermNodeTagged(con.get_allocator(), TermTags::Sticky, | |
271 | + std::move(p_sub))); | |
272 | + con.erase(i, con.end()); | |
272 | 273 | return ReductionStatus::Retained; |
273 | 274 | } |
274 | 275 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Internals.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 内部接口。 |
14 | -\version r22245 | |
14 | +\version r22378 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 882 |
17 | 17 | \par 创建时间: |
18 | 18 | 2020-02-15 13:20:08 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-06-05 01:26 +0800 | |
20 | + 2022-06-14 18:24 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 非公开模块名称: |
@@ -32,10 +32,10 @@ | ||
32 | 32 | #include YFM_NPL_NPLA1 // for shared_ptr, ContextNode, NPL::Deref, NPLException, |
33 | 33 | // TermNode, ReductionStatus, Reducer, YSLib::map, lref, Environment, set, |
34 | 34 | // IsTyped, EnvironmentList, EnvironmentReference, pair, YSLib::forward_list, |
35 | -// size_t, list, std::declval, EnvironmentGuard, MoveKeptGuard, | |
35 | +// size_t, tuple, std::declval, EnvironmentGuard, MoveKeptGuard, | |
36 | 36 | // A1::NameTypedContextHandler, TermReference, ThrowTypeErrorForInvalidType, |
37 | -// NPL::TryAccessLeaf, type_id, TermToNamePtr, IsIgnore, | |
38 | -// ystdex::exclude_self_t, ParameterMismatch; | |
37 | +// TryAccessLeafAtom, type_id, TermToNamePtr, IsIgnore, ystdex::exclude_self_t, | |
38 | +// ParameterMismatch; | |
39 | 39 | #include <ystdex/compose.hpp> // for ystdex::get_less; |
40 | 40 | #include <ystdex/scope_guard.hpp> // for ystdex::unique_guard; |
41 | 41 | #include <ystdex/optional.h> // for ystdex::optional; |
@@ -97,7 +97,33 @@ | ||
97 | 97 | ImplExpr(ContextState::Access(ctx).SetNextTermRef(term)) |
98 | 98 | |
99 | 99 | // NOTE: See $2018-09 @ %Documentation::Workflow for rationale of the |
100 | -// implementation. | |
100 | +// implementation of PTC. | |
101 | + | |
102 | +/*! | |
103 | +\brief 源代码名称恢复器。 | |
104 | +\since build 947 | |
105 | +*/ | |
106 | +class SourceNameRecoverer final | |
107 | +{ | |
108 | +private: | |
109 | + observer_ptr<SourceName> p_current{}; | |
110 | + SourceName Saved{}; | |
111 | + | |
112 | +public: | |
113 | + DefDeCtor(SourceNameRecoverer) | |
114 | + SourceNameRecoverer(SourceName& cur, SourceName name) | |
115 | + : p_current(&cur), Saved(name) | |
116 | + {} | |
117 | + DefDeCopyMoveCtorAssignment(SourceNameRecoverer) | |
118 | + | |
119 | + void | |
120 | + operator()() const ynothrow | |
121 | + { | |
122 | + if(p_current) | |
123 | + *p_current = std::move(Saved); | |
124 | + } | |
125 | +}; | |
126 | + | |
101 | 127 | // XXX: First-class continuations are not implemented completely yet, due to |
102 | 128 | // lack of term replacement mechanism in captured continuation. Kernel-style |
103 | 129 | // continuation interception is also unsupported because no reference for |
@@ -116,6 +142,8 @@ | ||
116 | 142 | OneShotChecker(ContextNode& ctx) |
117 | 143 | : p_shot(YSLib::allocate_shared<bool>(ctx.get_allocator())) |
118 | 144 | {} |
145 | + //! \since build 947 | |
146 | + DefDeCopyMoveCtorAssignment(OneShotChecker) | |
119 | 147 | |
120 | 148 | void |
121 | 149 | operator()() const ynothrow |
@@ -305,7 +333,7 @@ | ||
305 | 333 | public: |
306 | 334 | #if YB_IMPL_CLANGPP || YB_IMPL_GNUCPP >= 100000 |
307 | 335 | // XXX: See ContextNode::ReducerSequence. |
308 | - FrameRecordList() ynoexcept_spec(FrameRecordList()) | |
336 | + FrameRecordList() ynoexcept_spec(Base()) | |
309 | 337 | : Base() |
310 | 338 | {} |
311 | 339 | #elif __cpp_inheriting_constructors < 201511L |
@@ -358,6 +386,27 @@ | ||
358 | 386 | PDefHOp(void, (), ) const ynothrow |
359 | 387 | ImplExpr(TermRef.get().Clear()) |
360 | 388 | }; |
389 | + //! \since build 947 | |
390 | + //@{ | |
391 | + /*! | |
392 | + \brief 附加信息索引。 | |
393 | + \note 顺序保持和 ExtraInfo 的元素对应一致。 | |
394 | + */ | |
395 | + enum ExtraInfoIndex : size_t | |
396 | + { | |
397 | + RecoverSourceName, | |
398 | + CheckOneShot | |
399 | + }; | |
400 | + | |
401 | + /*! | |
402 | + \brief 帧记录。 | |
403 | + \note 成员顺序和 RecordFrameIndex 中的项对应。 | |
404 | + \note 成员析构的顺序是未指定的。 | |
405 | + \sa RecordFrameIndex | |
406 | + */ | |
407 | + using ExtraInfo = tuple<ystdex::guard<SourceNameRecoverer>, | |
408 | + ystdex::optional<ystdex::guard<OneShotChecker>>>; | |
409 | + //@} | |
361 | 410 | |
362 | 411 | //! \since build 910 |
363 | 412 | mutable size_t req_lift_result = 0; |
@@ -376,10 +425,10 @@ | ||
376 | 425 | |
377 | 426 | private: |
378 | 427 | /*! |
379 | - \brief 一次调用检查守卫。 | |
380 | - \since build 943 | |
428 | + \brief 可选的附加信息。 | |
429 | + \since build 947 | |
381 | 430 | */ |
382 | - mutable ystdex::optional<ystdex::guard<OneShotChecker>> one_shot_guard{}; | |
431 | + mutable ystdex::optional<ExtraInfo> opt_extra_info{}; | |
383 | 432 | |
384 | 433 | public: |
385 | 434 | //! \since build 819 |
@@ -407,10 +456,7 @@ | ||
407 | 456 | // object always live longer than the older one. |
408 | 457 | : req_lift_result(a.req_lift_result), |
409 | 458 | env_guard(std::move(a.env_guard)), term_guard(std::move(a.term_guard)) |
410 | - { | |
411 | - if(a.one_shot_guard) | |
412 | - one_shot_guard.emplace(a.one_shot_guard->func); | |
413 | - } | |
459 | + {} | |
414 | 460 | DefDeMoveCtor(TCOAction) |
415 | 461 | // XXX: Out-of-line destructor here is inefficient. |
416 | 462 |
@@ -420,6 +466,17 @@ | ||
420 | 466 | ReductionStatus |
421 | 467 | operator()(ContextNode&) const; |
422 | 468 | |
469 | +private: | |
470 | + //! \since build 947 | |
471 | + YB_ATTR_nodiscard ExtraInfo& | |
472 | + GetExtraInfoRef() | |
473 | + { | |
474 | + if(!opt_extra_info) | |
475 | + opt_extra_info.emplace(); | |
476 | + return *opt_extra_info; | |
477 | + } | |
478 | + | |
479 | +public: | |
423 | 480 | //! \since build 913 |
424 | 481 | DefGetter(const ynothrow, TermNode&, TermRef, term_guard.func.func.TermRef) |
425 | 482 |
@@ -474,13 +531,15 @@ | ||
474 | 531 | { |
475 | 532 | CompressForContext(ctx); |
476 | 533 | // NOTE: The temporary function and the environment are saved in |
477 | - // the frame record list as a new entry if necessary. | |
534 | + // the frame record list as a new entry if necessary. The | |
535 | + // existence of the entry shall be checked because it may be | |
536 | + // missing for function lvalues or calls not from a combiner | |
537 | + // (e.g. by 'eval'). | |
478 | 538 | if(!record_list.empty() && !record_list.front().second) |
479 | 539 | record_list.front().second = std::move(p_saved); |
480 | 540 | else |
481 | 541 | record_list.emplace_front(ContextHandler(), |
482 | 542 | std::move(p_saved)); |
483 | - return; | |
484 | 543 | } |
485 | 544 | // XXX: Normally this should not occur, but this is allowed by the |
486 | 545 | // interface (for an object %EnvironmentSwitcher initialized |
@@ -497,6 +556,8 @@ | ||
497 | 556 | YB_ATTR_nodiscard OneShotChecker |
498 | 557 | MakeOneShotChecker() |
499 | 558 | { |
559 | + auto& one_shot_guard(NPL::get<CheckOneShot>(GetExtraInfoRef())); | |
560 | + | |
500 | 561 | if(!one_shot_guard) |
501 | 562 | // XXX: The context is only used to determine the allocator, which |
502 | 563 | // is an implementation detail. Usually the context in caller |
@@ -518,16 +579,29 @@ | ||
518 | 579 | } |
519 | 580 | |
520 | 581 | /*! |
521 | - \pre \c one_shot_guard 。 | |
582 | + \pre \c NPL::get<CheckOneShot>(GetExtraInfoRef()) 。 | |
522 | 583 | \since build 945 |
523 | 584 | */ |
524 | 585 | void |
525 | 586 | ReleaseOneShotGuard() |
526 | 587 | { |
588 | + auto& one_shot_guard(NPL::get<CheckOneShot>(GetExtraInfoRef())); | |
589 | + | |
527 | 590 | YAssert(one_shot_guard, "One-shot guard is not initialized properly."); |
528 | 591 | return one_shot_guard.reset(); |
529 | 592 | } |
530 | 593 | |
594 | + /*! | |
595 | + \brief 保存尾上下文中的源代码名称。 | |
596 | + \since build 947 | |
597 | + */ | |
598 | + void | |
599 | + SaveTailSourceName(SourceName& cur, SourceName name) | |
600 | + { | |
601 | + NPL::get<RecoverSourceName>(GetExtraInfoRef()) | |
602 | + = SourceNameRecoverer(cur, std::move(name)); | |
603 | + } | |
604 | + | |
531 | 605 | //! \since build 911 |
532 | 606 | //@{ |
533 | 607 | //! \brief 设置提升请求。 |
@@ -589,6 +663,10 @@ | ||
589 | 663 | ImplExpr(SetupTailAction(ctx, TCOAction(ctx, term, lift))) |
590 | 664 | |
591 | 665 | |
666 | +// XXX: It is accidentally close to ECMAScript 6's %PrepareForTailCall in both | |
667 | +// name and semantics, but actually independent. In particular, ES6's "pop" | |
668 | +// wording indicates it only operate on one side of the activation records in | |
669 | +// relavant contexts, which differs than the %TCOAction here. | |
592 | 670 | /*! |
593 | 671 | \brief 准备 TCO 求值。 |
594 | 672 | \param ctx 规约上下文。 |
@@ -915,6 +993,30 @@ | ||
915 | 993 | //@{ |
916 | 994 | struct NonTailCall final |
917 | 995 | { |
996 | +#if NPL_Impl_NPLA1_Enable_Thunked | |
997 | + //! \since build 947 | |
998 | + YB_ATTR_nodiscard YB_FLATTEN static Reducer | |
999 | + MakeLiftResult(TermNode& term, ContextNode& ctx) | |
1000 | + { | |
1001 | + // NOTE: The term to be lifted is fixed regardless of continuation | |
1002 | + // capture, so this needs no setup of the next term and the reducer | |
1003 | + // does not need to be a %Continuation. | |
1004 | + // XXX: However, %Containuation is actually more efficient. Whether | |
1005 | + // %Continuation is used, %NPL::ToReducer here would be a bit | |
1006 | + // inefficient. | |
1007 | +#if true | |
1008 | + return Continuation(NameTypedContextHandler([&]{ | |
1009 | + return ReduceForLiftedResult(term); | |
1010 | + }, "eval-lift-result"), ctx); | |
1011 | +#else | |
1012 | + yunused(ctx); | |
1013 | + return NameTypedContextHandler([&]{ | |
1014 | + return ReduceForLiftedResult(term); | |
1015 | + }, "eval-lift-result"); | |
1016 | +#endif | |
1017 | + } | |
1018 | +#endif | |
1019 | + | |
918 | 1020 | //! \pre 最后一个参数的类型退化后可平凡交换。 |
919 | 1021 | //@{ |
920 | 1022 | template<typename _fCurrent> |
@@ -940,27 +1042,20 @@ | ||
940 | 1042 | } |
941 | 1043 | |
942 | 1044 | template<typename _fCurrent> |
943 | - YB_FLATTEN static inline ReductionStatus | |
1045 | + static inline ReductionStatus | |
944 | 1046 | RelayNextGuardedLifted(ContextNode& ctx, TermNode& term, |
945 | 1047 | EnvironmentGuard&& gd, _fCurrent&& cur) |
946 | 1048 | { |
947 | 1049 | // XXX: See %RelayNextGuarded. |
948 | 1050 | #if NPL_Impl_NPLA1_Enable_Thunked |
949 | 1051 | auto act(MoveKeptGuard(gd)); |
950 | - // TODO: Blocked. Use C++14 lambda initializers to simplify the | |
951 | - // implementation. | |
952 | - // XXX: Term reused. Call of %SetupNextTerm is not needed as the next | |
953 | - // term is guaranteed not changed when %cur is a continuation. | |
954 | - Continuation cont(A1::NameTypedContextHandler([&]{ | |
955 | - // TODO: Avoid fixed continuation parameter. | |
956 | - return ReduceForLiftedResult(term); | |
957 | - }, "eval-lift-result"), ctx); | |
958 | 1052 | |
1053 | + // XXX: Call of %SetupNextTerm is not needed because the next term is | |
1054 | + // guaranteed not changed whether %cur is a continuation. | |
959 | 1055 | RelaySwitched(ctx, trivial_swap, std::move(act)); |
960 | - // XXX: %Continuation is specialized enough without | |
961 | - // %trivial_swap. | |
1056 | + // XXX: %Reducer is specialized enough without %trivial_swap. | |
962 | 1057 | return A1::RelayCurrentNext(ctx, term, trivial_swap, yforward(cur), |
963 | - std::move(cont)); | |
1058 | + MakeLiftResult(term, ctx)); | |
964 | 1059 | #else |
965 | 1060 | yunused(gd); |
966 | 1061 | RelayDirect(ctx, cur, term); |
@@ -981,18 +1076,11 @@ | ||
981 | 1076 | |
982 | 1077 | if(lift) |
983 | 1078 | { |
984 | - // XXX: Term reused. Call of %SetupNextTerm is not needed as the | |
985 | - // next term is guaranteed not changed when %cur is a continuation. | |
986 | - Continuation cont(A1::NameTypedContextHandler([&]{ | |
987 | - // TODO: Avoid fixed continuation parameter. | |
988 | - return ReduceForLiftedResult(term); | |
989 | - }, "eval-lift-result"), ctx); | |
990 | - | |
1079 | + // XXX: As %RelayNextGuardedLifted. | |
991 | 1080 | RelaySwitched(ctx, trivial_swap, std::move(act)); |
992 | - // XXX: %Continuation is specialized enough without | |
993 | - // %trivial_swap. | |
994 | - return A1::RelayCurrentNext(ctx, term, trivial_swap, | |
995 | - yforward(cur), std::move(cont)); | |
1081 | + // XXX: As %RelayNextGuardedLifted. | |
1082 | + return A1::RelayCurrentNext(ctx, term, trivial_swap, yforward(cur), | |
1083 | + MakeLiftResult(term, ctx)); | |
996 | 1084 | } |
997 | 1085 | return A1::RelayCurrentNext(ctx, term, trivial_swap, yforward(cur), |
998 | 1086 | trivial_swap, std::move(act)); |
@@ -1183,7 +1271,7 @@ | ||
1183 | 1271 | const TermReference& ref) |
1184 | 1272 | // XXX: It is assumed that %term is not an ancestor of %bound. The source |
1185 | 1273 | // term tags are ignored. |
1186 | - ImplExpr(YAssert(NPL::TryAccessLeaf<const TermReference>(bound).get() | |
1274 | + ImplExpr(YAssert(TryAccessLeafAtom<const TermReference>(bound).get() | |
1187 | 1275 | == &ref, "Invalid term or reference value found."), term.SetContent( |
1188 | 1276 | bound.GetContainer(), EnsureLValueReference(TermReference(ref)))) |
1189 | 1277 |
@@ -1274,7 +1362,7 @@ | ||
1274 | 1362 | if(IsBranch(t)) |
1275 | 1363 | MatchSubterms(t.begin(), t.end()); |
1276 | 1364 | } |
1277 | - else if(const auto p_t = NPL::TryAccessLeaf<const TermReference>(t)) | |
1365 | + else if(const auto p_t = TryAccessLeafAtom<const TermReference>(t)) | |
1278 | 1366 | { |
1279 | 1367 | auto& nd(p_t->get()); |
1280 | 1368 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLAMath.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 数学功能。 |
14 | -\version r28330 | |
14 | +\version r28361 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 930 |
17 | 17 | \par 创建时间: |
18 | 18 | 2021-11-03 12:50:49 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-02-08 19:39 +0800 | |
20 | + 2022-06-14 18:30 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -28,7 +28,7 @@ | ||
28 | 28 | #include "NPL/YModules.h" |
29 | 29 | #include YFM_NPL_NPLAMath // for ValueObject, ResolvedArg, size_t, type_info, |
30 | 30 | // TermNode, ystdex::identity, ystdex::conditional_t, std::is_signed, |
31 | -// ystdex::_t, NPL::TryAccessValue, YAssert, TypeError, ystdex::sfmt, | |
31 | +// ystdex::_t, TryAccessValue, YAssert, TypeError, ystdex::sfmt, | |
32 | 32 | // NPL::Nonnull, std::string, ystdex::enable_if_t, std::is_floating_point, |
33 | 33 | // NPL::Deref, std::isfinite, std::nearbyint, ystdex::exclude_self_t, |
34 | 34 | // std::fmod, ystdex::and_, std::is_unsigned, std::abs, std::floor, std::trunc, |
@@ -288,32 +288,32 @@ | ||
288 | 288 | YB_ATTR_nodiscard _type |
289 | 289 | DoNumLeaf(_tValue& x, _func f) |
290 | 290 | { |
291 | - if(const auto p_i = NPL::TryAccessValue<int>(x)) | |
291 | + if(const auto p_i = TryAccessValue<int>(x)) | |
292 | 292 | return f(*p_i); |
293 | - if(const auto p_u = NPL::TryAccessValue<unsigned>(x)) | |
293 | + if(const auto p_u = TryAccessValue<unsigned>(x)) | |
294 | 294 | return f(*p_u); |
295 | - if(const auto p_ll = NPL::TryAccessValue<long long>(x)) | |
295 | + if(const auto p_ll = TryAccessValue<long long>(x)) | |
296 | 296 | return f(*p_ll); |
297 | - if(const auto p_ull = NPL::TryAccessValue<unsigned long long>(x)) | |
297 | + if(const auto p_ull = TryAccessValue<unsigned long long>(x)) | |
298 | 298 | return f(*p_ull); |
299 | - if(const auto p_d = NPL::TryAccessValue<double>(x)) | |
299 | + if(const auto p_d = TryAccessValue<double>(x)) | |
300 | 300 | return f(*p_d); |
301 | 301 | // TODO: Support bigint. |
302 | - if(const auto p_l = NPL::TryAccessValue<long>(x)) | |
302 | + if(const auto p_l = TryAccessValue<long>(x)) | |
303 | 303 | return f(*p_l); |
304 | - if(const auto p_ul = NPL::TryAccessValue<unsigned long>(x)) | |
304 | + if(const auto p_ul = TryAccessValue<unsigned long>(x)) | |
305 | 305 | return f(*p_ul); |
306 | - if(const auto p_s = NPL::TryAccessValue<short>(x)) | |
306 | + if(const auto p_s = TryAccessValue<short>(x)) | |
307 | 307 | return f(*p_s); |
308 | - if(const auto p_us = NPL::TryAccessValue<unsigned short>(x)) | |
308 | + if(const auto p_us = TryAccessValue<unsigned short>(x)) | |
309 | 309 | return f(*p_us); |
310 | - if(const auto p_sc = NPL::TryAccessValue<signed char>(x)) | |
310 | + if(const auto p_sc = TryAccessValue<signed char>(x)) | |
311 | 311 | return f(*p_sc); |
312 | - if(const auto p_uc = NPL::TryAccessValue<unsigned char>(x)) | |
312 | + if(const auto p_uc = TryAccessValue<unsigned char>(x)) | |
313 | 313 | return f(*p_uc); |
314 | - if(const auto p_f = NPL::TryAccessValue<float>(x)) | |
314 | + if(const auto p_f = TryAccessValue<float>(x)) | |
315 | 315 | return f(*p_f); |
316 | - if(const auto p_ld = NPL::TryAccessValue<long double>(x)) | |
316 | + if(const auto p_ld = TryAccessValue<long double>(x)) | |
317 | 317 | return f(*p_ld); |
318 | 318 | return f(x); |
319 | 319 | } |
@@ -780,7 +780,7 @@ | ||
780 | 780 | ++x; |
781 | 781 | else |
782 | 782 | // TODO: Support bigint with allocator? |
783 | - Result.get() = ValueObject(MakeExtType<_type>(x) + 1); | |
783 | + Result.get().assign(MakeExtType<_type>(x) + 1); | |
784 | 784 | } |
785 | 785 | }; |
786 | 786 |
@@ -811,7 +811,7 @@ | ||
811 | 811 | --x; |
812 | 812 | else |
813 | 813 | // TODO: Support bigint with allocator? |
814 | - Result.get() = ValueObject(MakeNExtType<_type>(x) - 1); | |
814 | + Result.get().assign(ValueObject(MakeNExtType<_type>(x) - 1)); | |
815 | 815 | } |
816 | 816 | }; |
817 | 817 |
@@ -3563,11 +3563,11 @@ | ||
3563 | 3563 | bool |
3564 | 3564 | IsRationalValue(const ValueObject& vo) ynothrow |
3565 | 3565 | { |
3566 | - if(const auto p_d = NPL::TryAccessValue<double>(vo)) | |
3566 | + if(const auto p_d = TryAccessValue<double>(vo)) | |
3567 | 3567 | return std::isfinite(*p_d); |
3568 | - if(const auto p_f = NPL::TryAccessValue<float>(vo)) | |
3568 | + if(const auto p_f = TryAccessValue<float>(vo)) | |
3569 | 3569 | return std::isfinite(*p_f); |
3570 | - if(const auto p_ld = NPL::TryAccessValue<long double>(vo)) | |
3570 | + if(const auto p_ld = TryAccessValue<long double>(vo)) | |
3571 | 3571 | return std::isfinite(*p_ld); |
3572 | 3572 | return IsExactValue(vo); |
3573 | 3573 | } |
@@ -3575,11 +3575,11 @@ | ||
3575 | 3575 | bool |
3576 | 3576 | IsIntegerValue(const ValueObject& vo) ynothrow |
3577 | 3577 | { |
3578 | - if(const auto p_d = NPL::TryAccessValue<double>(vo)) | |
3578 | + if(const auto p_d = TryAccessValue<double>(vo)) | |
3579 | 3579 | return FloatIsInteger(*p_d); |
3580 | - if(const auto p_f = NPL::TryAccessValue<float>(vo)) | |
3580 | + if(const auto p_f = TryAccessValue<float>(vo)) | |
3581 | 3581 | return FloatIsInteger(*p_f); |
3582 | - if(const auto p_ld = NPL::TryAccessValue<long double>(vo)) | |
3582 | + if(const auto p_ld = TryAccessValue<long double>(vo)) | |
3583 | 3583 | return FloatIsInteger(*p_ld); |
3584 | 3584 | return IsExactValue(vo); |
3585 | 3585 | } |
@@ -3588,11 +3588,11 @@ | ||
3588 | 3588 | bool |
3589 | 3589 | IsFinite(const ValueObject& x) ynothrowv |
3590 | 3590 | { |
3591 | - if(const auto p_d = NPL::TryAccessValue<double>(x)) | |
3591 | + if(const auto p_d = TryAccessValue<double>(x)) | |
3592 | 3592 | return std::isfinite(*p_d); |
3593 | - if(const auto p_f = NPL::TryAccessValue<float>(x)) | |
3593 | + if(const auto p_f = TryAccessValue<float>(x)) | |
3594 | 3594 | return std::isfinite(*p_f); |
3595 | - if(const auto p_ld = NPL::TryAccessValue<long double>(x)) | |
3595 | + if(const auto p_ld = TryAccessValue<long double>(x)) | |
3596 | 3596 | return std::isfinite(*p_ld); |
3597 | 3597 | return true; |
3598 | 3598 | } |
@@ -3600,11 +3600,11 @@ | ||
3600 | 3600 | bool |
3601 | 3601 | IsInfinite(const ValueObject& x) ynothrowv |
3602 | 3602 | { |
3603 | - if(const auto p_d = NPL::TryAccessValue<double>(x)) | |
3603 | + if(const auto p_d = TryAccessValue<double>(x)) | |
3604 | 3604 | return std::isinf(*p_d); |
3605 | - if(const auto p_f = NPL::TryAccessValue<float>(x)) | |
3605 | + if(const auto p_f = TryAccessValue<float>(x)) | |
3606 | 3606 | return std::isinf(*p_f); |
3607 | - if(const auto p_ld = NPL::TryAccessValue<long double>(x)) | |
3607 | + if(const auto p_ld = TryAccessValue<long double>(x)) | |
3608 | 3608 | return std::isinf(*p_ld); |
3609 | 3609 | return {}; |
3610 | 3610 | } |
@@ -3612,11 +3612,11 @@ | ||
3612 | 3612 | bool |
3613 | 3613 | IsNaN(const ValueObject& x) ynothrowv |
3614 | 3614 | { |
3615 | - if(const auto p_d = NPL::TryAccessValue<double>(x)) | |
3615 | + if(const auto p_d = TryAccessValue<double>(x)) | |
3616 | 3616 | return std::isnan(*p_d); |
3617 | - if(const auto p_f = NPL::TryAccessValue<float>(x)) | |
3617 | + if(const auto p_f = TryAccessValue<float>(x)) | |
3618 | 3618 | return std::isnan(*p_f); |
3619 | - if(const auto p_ld = NPL::TryAccessValue<long double>(x)) | |
3619 | + if(const auto p_ld = TryAccessValue<long double>(x)) | |
3620 | 3620 | return std::isnan(*p_ld); |
3621 | 3621 | return {}; |
3622 | 3622 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file SContext.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief S 表达式上下文。 |
14 | -\version r2292 | |
14 | +\version r2314 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 329 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-08-03 19:55:59 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-04-29 18:57 +0800 | |
20 | + 2022-06-13 01:32 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -150,7 +150,7 @@ | ||
150 | 150 | } |
151 | 151 | |
152 | 152 | // XXX: Making it a separate definition slightly improves the generated code |
153 | - // quality with x86_64-pc-linux G++ 11.1.0. | |
153 | + // quality with x86_64-pc-linux G++ 11.1. | |
154 | 154 | void |
155 | 155 | UpdateCopyValueAndTags(TermNode& dst, const TermNode& src) const |
156 | 156 | { |
@@ -198,41 +198,22 @@ | ||
198 | 198 | } |
199 | 199 | |
200 | 200 | // XXX: Simplify with %CreateRecursively? |
201 | -TermNode::Container | |
202 | -TermNode::ConCons(const ValueNode::Container& con) | |
203 | -{ | |
204 | - Container res; | |
205 | - | |
206 | - for(const auto& item : con) | |
207 | - res.emplace_back(ConCons(item.GetContainer()), item.Value); | |
208 | - return res; | |
209 | -} | |
210 | -TermNode::Container | |
211 | -TermNode::ConCons(ValueNode::Container&& con) | |
212 | -{ | |
213 | - Container res; | |
214 | - | |
215 | - for(auto& item : con) | |
216 | - res.emplace_back(ConCons(std::move(item.GetContainerRef())), | |
217 | - std::move(item.Value)); | |
218 | - return res; | |
219 | -} | |
220 | -TermNode::Container | |
201 | +YB_FLATTEN TermNode::Container | |
221 | 202 | TermNode::ConCons(const ValueNode::Container& con, allocator_type a) |
222 | 203 | { |
223 | 204 | Container res(a); |
224 | 205 | |
225 | 206 | for(const auto& item : con) |
226 | - res.emplace_back(ConCons(item.GetContainer()), item.Value); | |
207 | + res.emplace_back(ConCons(item.GetContainer(), a), item.Value); | |
227 | 208 | return res; |
228 | 209 | } |
229 | -TermNode::Container | |
210 | +YB_FLATTEN TermNode::Container | |
230 | 211 | TermNode::ConCons(ValueNode::Container&& con, allocator_type a) |
231 | 212 | { |
232 | 213 | Container res(a); |
233 | 214 | |
234 | 215 | for(auto& item : con) |
235 | - res.emplace_back(ConCons(std::move(item.GetContainerRef())), | |
216 | + res.emplace_back(ConCons(std::move(item.GetContainerRef()), a), | |
236 | 217 | std::move(item.Value)); |
237 | 218 | return res; |
238 | 219 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file SXML.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPL SXML 实现。 |
14 | -\version r4729 | |
14 | +\version r4735 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 936 |
17 | 17 | \par 创建时间: |
18 | 18 | 2022-01-20 17:41:15 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-01-21 02:03 +0800 | |
20 | + 2022-06-14 18:34 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -26,7 +26,7 @@ | ||
26 | 26 | |
27 | 27 | |
28 | 28 | #include "NPL/YModules.h" |
29 | -#include YFM_NPL_SXML // for YSLib::Warning, NPL::Access, string, NPL::Deref, | |
29 | +#include YFM_NPL_SXML // for YSLib::Warning, Access, string, NPL::Deref, | |
30 | 30 | // ystdex::write, AccessFirstSubterm, ystdex::unimplemented, IsTyped, |
31 | 31 | // bad_any_cast, ystdex::quote, ystdex::call_value_or; |
32 | 32 |
@@ -50,13 +50,13 @@ | ||
50 | 50 | case 2: |
51 | 51 | { |
52 | 52 | auto i(term.begin()); |
53 | - const auto& n(NPL::Access<string>(NPL::Deref(i))); | |
53 | + const auto& n(Access<string>(NPL::Deref(i))); | |
54 | 54 | |
55 | - return n + '=' + NPL::Access<string>(NPL::Deref(++i)); | |
55 | + return n + '=' + Access<string>(NPL::Deref(++i)); | |
56 | 56 | } |
57 | 57 | YB_ATTR_fallthrough; |
58 | 58 | case 1: |
59 | - return NPL::Access<string>(AccessFirstSubterm(term)); | |
59 | + return Access<string>(AccessFirstSubterm(term)); | |
60 | 60 | case 0: |
61 | 61 | break; |
62 | 62 | } |
@@ -79,7 +79,7 @@ | ||
79 | 79 | try |
80 | 80 | { |
81 | 81 | auto i(term.begin()); |
82 | - const auto& str(NPL::Access<string>(NPL::Deref(i))); | |
82 | + const auto& str(Access<string>(NPL::Deref(i))); | |
83 | 83 | |
84 | 84 | ++i; |
85 | 85 | if(str == "@") |
@@ -167,7 +167,7 @@ | ||
167 | 167 | string |
168 | 168 | ConvertStringNode(const TermNode& term) |
169 | 169 | { |
170 | - return ystdex::call_value_or(EscapeXML, NPL::AccessPtr<string>(term)); | |
170 | + return ystdex::call_value_or(EscapeXML, AccessPtr<string>(term)); | |
171 | 171 | } |
172 | 172 | |
173 | 173 | void |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file ChangeLog.V0.9.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 版本更新历史记录 - V0.9 。 |
14 | -\version r9480 | |
14 | +\version r9726 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 800 |
17 | 17 | \par 创建时间: |
18 | 18 | 2020-10-12 17:19:23 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-06-05 02:22 +0800 | |
20 | + 2022-06-15 01:04 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -32,6 +32,241 @@ | ||
32 | 32 | |
33 | 33 | $now |
34 | 34 | ( |
35 | + ( | |
36 | + / DLP "updated platform %MinGW64 toolchain" | |
37 | + $dep_to "MinGW64 toolchain update"; | |
38 | + / $re_ex(b900) $forced "rebuilt library %FreeImage" | |
39 | + ), | |
40 | + / $build %Tools $= | |
41 | + ( | |
42 | + / @ "%SHbuild-build.sh" $= | |
43 | + ( | |
44 | + / DLI "%LDFLAGS_LOWBASE_" => "%LDFLAGS_WKRD_", | |
45 | + / "disabled workaround" @ "platform %MinGW64", | |
46 | + + $forced "workaround for mingw-w64-x86_64-binutils 2.38-3" | |
47 | + ^ '-fuse-ld=lld' $dep_from "MinGW64 toolchain update" | |
48 | + // This is also faster. | |
49 | + ), | |
50 | + + "selected '-flto=jobserver' over '-flto=auto' for G++ only on \ | |
51 | + platform %MinGW32" @ "%SHBuild-common-options.sh", | |
52 | + // Now only MinGW32 uses '-flto=jobserver'. | |
53 | + / @ "applicative %build-with-conf-opt" | |
54 | + @ "%SHBuild-YSLib-common.txt" $= | |
55 | + ( | |
56 | + + "2nd argument 'host-arch'" | |
57 | + $dep_to "passing host architecture to build"; | |
58 | + + "selected '-flto=jobserver' over '-flto=auto' for G++ only on \ | |
59 | + platform %MinGW32" | |
60 | + // Ditto. | |
61 | + ), | |
62 | + / $forced "%SHBuild-YSLib-build.txt" | |
63 | + $dep_from "passing host architecture to build" | |
64 | + ), | |
65 | + / %YFramework.NPL $= | |
66 | + ( | |
67 | + + 'ynothrow' @ "function %(QueryTailOperatorName, \ | |
68 | + SetupTailOperatorName)" @ %NPLA1, | |
69 | + - "unnecessary 'A1::' before 'NameTypedReducerHandler'" | |
70 | + $effective @ "%(NPLA1, NPLA1Internals, NPLA1Forms)", | |
71 | + / DLI "simplified term value setting with a single value of types \ | |
72 | + except environment references" ^ '=' ~ "%TermValue::SetValue" | |
73 | + $effective %(NPLAMath, NPLA1Forms), | |
74 | + // In %NPLA1Forms, all modified instances are for %TermRange. It \ | |
75 | + is a bit more efficient to use assignment directly in this case. | |
76 | + / %Dependency $= | |
77 | + ( | |
78 | + * "missing source name recovery" @ (("functions \ | |
79 | + %(ReduceToLoadExternal, RelayToLoadExternal)", | |
80 | + "applicative %load" @ "function %LoadModule_std_io") | |
81 | + $since b899, "native implementation" @ "applicative %require" | |
82 | + @ "function %LoadModule_std_modules" $since b923) | |
83 | + $= (/ $impl ^ $dep_from | |
84 | + ("%TCOAction::SaveTailSourceName" @ %NPLA1Internals)), | |
85 | + / DLDI "simplified native implementation" @ "applicative %force" | |
86 | + @ "function %LoadModule_std_promises" | |
87 | + ^ "%TermNode::SetValue" ~ "%ValueObject::assign", | |
88 | + / DLI ("applicative 'make-standard-environment'" @ "funciton \ | |
89 | + %LoadGroundContext", "native implementation" | |
90 | + @ "applicative 'get-module'" @ "function \ | |
91 | + %LoadModule_std_modules") ^ "%TermNode::SetValue" ~ '.Value =', | |
92 | + // To be consistent to other modificiation of environments. | |
93 | + / DLI "applicative 'get-current-repl'" @ "%function \ | |
94 | + %LoadModule_std_system" ^ "%TermNode::Value::assign" ~ '=' | |
95 | + ), | |
96 | + / DLI "all term value assignment from %TermReference" | |
97 | + ^ "%(SetValue, in_place_type<TermReference>)" $effective | |
98 | + @ %(NPLA, Dependency) | |
99 | + // It is a bit more efficient with the tag argument. | |
100 | + / DLDI "simplified term container construction" $effective | |
101 | + @ ("functions %(ReduceToReferenceList, ReduceToReferenceUList)" | |
102 | + @ %NPLA1, "functions %Forms::(Let, LetRef, LetWithEnvironment, \ | |
103 | + LetWithEnvironmentRef, LetRec, LetRecRef, \ | |
104 | + BindingsWithParentToEnvironment, BindingsToEnvironment, ProvideLet)" | |
105 | + !^ "explicit %ValueObject initialization" @ %NPLA1Forms), | |
106 | + / @ %NPLA1Internals $= | |
107 | + ( | |
108 | + + 'DefDeCopyMoveCtorAssignment(OneShotChecker)' | |
109 | + @ "class %OneShotChecker", | |
110 | + + "class %SourceNameRecovery" | |
111 | + / @ "class %TCOAction" $= | |
112 | + ( | |
113 | + / DLDI "simplified function %CompressForGuard", | |
114 | + / DLDI "simplified copy constructior", | |
115 | + ( | |
116 | + / DLDI "functions %(MakeOneShotChecker, ReleaseOneShotGuard)"; | |
117 | + + "support of source name guard" @ "data members" | |
118 | + ^ $dep_from "%SourceNameRecovery"; | |
119 | + + "function %SaveTailSourceName" | |
120 | + ) | |
121 | + ), | |
122 | + / @ 'NPL_Impl_NPLA1_Enable_Thunked' @ "class %NonTailCall" $= | |
123 | + ( | |
124 | + - DLDI 'YB_FLATTEN' @ "static function %RelayNextGuardedLifted", | |
125 | + ( | |
126 | + + "static function %MakeLiftResult"; | |
127 | + / DLI "simplified static function templates \ | |
128 | + %(RelayNextGuardedLifted, RelayNextGuardedProbe)" | |
129 | + ) | |
130 | + ), | |
131 | + * "exception specification" @ "constructor %FrameRecordList" | |
132 | + $since b946, | |
133 | + // Also to eliminate Clang++ error. This is related to CWG \ | |
134 | + 1330. The original code is really not wanted here. \ | |
135 | + (Clang++ does have other related bugs as in \ | |
136 | + https://stackoverflow.com/questions/48340412.) | |
137 | + / @ "function %ReduceAsSubobjectReference" $= | |
138 | + ( | |
139 | + / DLI "avoided redundant term container copy", | |
140 | + / "tagged for irregular representation" ^ $dep_from | |
141 | + ("%(TermTags::Sticky, NPL::AsTermNodeTagged)" @ %SContext) | |
142 | + ) | |
143 | + ), | |
144 | + / %SContext $= | |
145 | + ( | |
146 | + ( | |
147 | + / $src "initializer" @ "enumerator %Unqualified" | |
148 | + @ "enum class %TermTags" -> '0' ~ '1 << UnqualifiedIndex'; | |
149 | + // Actually the non-zero value is not expected at the very \ | |
150 | + beginning of the design. However, no other code relies on \ | |
151 | + the fact previously, so this is not a bug. | |
152 | + ( | |
153 | + - "enumerator %UnqualifiedIndex" @ "enum %TermTagIndices"; | |
154 | + / $comp $src "underlying values" @ "all enumerators" | |
155 | + @ "enum %TermTags" | |
156 | + ), | |
157 | + * "exception specification" | |
158 | + @ "member function template % TermNode::SetValue#1" $since b918, | |
159 | + ( | |
160 | + + "function %IsReferentTags"; | |
161 | + // To be simpler, this relies on the change of \ | |
162 | + %TermTags::Unqualified above. | |
163 | + + "2 functions %AssertReferentTags" | |
164 | + ) | |
165 | + ), | |
166 | + / @ "constructors %TermNode" $= | |
167 | + ( | |
168 | + / DLDI "reordered and simplified with %ValueNode::Container \ | |
169 | + parameter", | |
170 | + ( | |
171 | + + "12 overloads with %TermTags parameter" | |
172 | + $dep_to "tagged term constructor"; | |
173 | + * "allocator used to initialize %Value instead of the container" | |
174 | + @ "overload with 'const Container&' parameter" $since b944 | |
175 | + ), | |
176 | + ( | |
177 | + * "copy" @ "overload with single 'ValueNode&&' parameter" | |
178 | + $since b853 | |
179 | + $= (/ $impl ^ "%GetContainerRef" ~ "%GetContainer"), | |
180 | + * "missing propagating allocator to subterms" | |
181 | + @ "all 2 overloads with single %ValueNode reference and \ | |
182 | + allocator parameters" $since b853, | |
183 | + ) | |
184 | + ), | |
185 | + + "2 function templates %AsTermNodeTagged" | |
186 | + $dep_from "tagged term constructor", | |
187 | + ( | |
188 | + + "macro %NPL_SContext_CompressTermTags"; | |
189 | + + "enumerator %StickyIndex" @ "enum %TermTagIndices"; | |
190 | + + "enumerator %Sticky" @ "enum class %TermTags"; | |
191 | + + "functions %(IsPair; IsAtom)" | |
192 | + ) | |
193 | + ), | |
194 | + / %NPLA $= | |
195 | + ( | |
196 | + + DLI "invariant, precondition and check" @ "constuctors \ | |
197 | + %TermReference" ^ $dep_from "%AssertReferentTags#1", | |
198 | + + DLI "precondition and check" @ "function %TermToTags" | |
199 | + ^ $dep_from "%AssertReferentTags#2", | |
200 | + + "2 function templates %TryAccessLeafAtom" | |
201 | + ^ $dep_from ("%IsAtom" @ %SContext), | |
202 | + + DLDI 'const' @ "operand" @ "exception specification" | |
203 | + @ "function template %ReferenceTerm#2", | |
204 | + + "function %LiftElementsToReturn" | |
205 | + ), | |
206 | + / "distinguished pairs from leaf values for first-class object accesses" | |
207 | + $effective @ (("function template %ResolveTerm", ("all 2 functions \ | |
208 | + %ReferenceTerm"; $comp "functor %ReferenceTermOp"), "all 2 \ | |
209 | + function templates %TryAccessReferencedLeaf", "functions \ | |
210 | + %(Collapse, MoveCollapsed, TermToTags, IsReferenceTerm, \ | |
211 | + IsUniqueTerm, IsModifiableTerm, IsTemporaryTerm, \ | |
212 | + IsBoundLValueTerm, IsUncollapsedTerm, LiftToReturn, \ | |
213 | + MoveRValueToForward, MoveRValueToReturn, ReduceToReference)") | |
214 | + @ %NPLA, "functions %(EvaluateIdentifier, ReduceCombinedBranch, \ | |
215 | + ReduceCombinedReferent, MatchParameter, BindParameter, \ | |
216 | + BindParameterWellFormed, BindSymbol, ReduceToReferenceList, \ | |
217 | + ReduceToReferenceUList)" @ %NPLA1, ("function \ | |
218 | + %SetEvaluatedReference", "class template %GParameterValueMatcher") | |
219 | + @ %NPLA1Internals, ("function %Decapsulate::operator()", | |
220 | + ("all functions with prefix 'Lambda', 'Vau', 'WVau', 'SetFirst', \ | |
221 | + 'Acc', 'Let', 'Bindings', 'ListExtract', 'Import' or 'Ass'", | |
222 | + "functions %(MakeEnvironment, CheckParent, ForwardFirst, First, \ | |
223 | + FirstFwd, FirstVal, RestFwd, RestVal, FoldR1, Map1, ListConcat, \ | |
224 | + Append, SymbolsToImports, ProvideLet, ListPushFront)") | |
225 | + @ "namespace %Forms") @ %NPLA1Forms, ("combiners ('as-const', \ | |
226 | + %(expire, deshare), '$lvalue-identifier?')" @ "function \ | |
227 | + %LoadGroundContext", "native implementation" @ ("applicative \ | |
228 | + %force" @ "function %LoadModule_std_promises", "applicative \ | |
229 | + %require" @ "function %LoadModule_std_modules")) @ %Dependency) | |
230 | + // These include almost all call sites of %TryAccessLeaf \ | |
231 | + except a few exceptions: the implementation of \ | |
232 | + %(TryAccessLeafAtom, TryAccessTerm), the internal \ | |
233 | + exception throwing in %ReduceCombinedBranch and %TermRange \ | |
234 | + accesses. Also 'GetObject<TermReference>()' calls in \ | |
235 | + %LiftPropagatedReference would be protected by these changes. | |
236 | + $= (/ $impl | |
237 | + ^ ($dep_from "%TryAccessLeafAtom" ~ "%TryAccessLeaf") @ %NPLA), | |
238 | + / @ "namespace %Forms" @ %NPLA1Forms $= | |
239 | + ( | |
240 | + + DLDI 'YB_ATTR_nodiscard' @ "internal implemenation" | |
241 | + @ "%(AccL, AccR)", | |
242 | + / DLDI "simplified member function %Decapsulate::operator()" | |
243 | + ^ "%TermNode::SetValue" ~ "%ValueObject::assign", | |
244 | + / DLDI "simplified explicit %ValueObject with allocator \ | |
245 | + assignment" ^ "%TermNode::SetValue" ~ '.Value =', | |
246 | + / @ "functions %(Cons, ConsRef, SetRest, SetRestRef, \ | |
247 | + ListAsterisk, ListAsteriskRef, Apply)" $= | |
248 | + ( | |
249 | + / DLDI "simplified by transferring 1st subterm from the \ | |
250 | + operand instead of the rest"; | |
251 | + + DLDI "assertion to check against self move" | |
252 | + ^ "%ystdex::ref_eq", | |
253 | + ( | |
254 | + / DLDI "throwing exception" ^ "%ThrowListTypeErrorForNonlist"; | |
255 | + // This changes the exception message a bit. | |
256 | + / "merged error handling" | |
257 | + ) | |
258 | + ) | |
259 | + ), | |
260 | + - DLDI "all 'NPL::' prefix" @ "calls to function templates with \ | |
261 | + prefix 'Access' or 'TryAccess', or name %make_observer" | |
262 | + $effective @ %(NPLA, NPLAMath, NPLA1, NPLA1Forms, NPLA1Internals, | |
263 | + Dependency, SXML) | |
264 | + // See $2022-06 @ %Documentation::Workflow. | |
265 | + ) | |
266 | +), | |
267 | + | |
268 | +b946 | |
269 | +( | |
35 | 270 | / %YFramework.NPL $= |
36 | 271 | ( |
37 | 272 | / DLI "enabled conditinoal inclusion for different G++ versions" |
@@ -129,6 +364,10 @@ | ||
129 | 364 | "%SHBuild-YSLib-common.txt") @ %Scripts, %ProjectGenerator.Main) |
130 | 365 | // Ditto. |
131 | 366 | ), |
367 | + + $lib $impl 'YB_ATTR(optimize("Os"))' @ "member function \ | |
368 | + %resource_pool::deallocate" @ %YBase.YStandardEx.MemoryResource, | |
369 | + // GCC 12.1 does not generate optimal code as before without this \ | |
370 | + attribute. See also $2022-05 @ %Documentation::Workflow. | |
132 | 371 | / %YFramework.NPL $= |
133 | 372 | ( |
134 | 373 | / DLI @ "static member function %ContextNode::DefaultResolve" @ %NPLA $= |
@@ -773,6 +1012,8 @@ | ||
773 | 1012 | ), |
774 | 1013 | / %NPLAMath $= |
775 | 1014 | ( |
1015 | + / $re_add(b940) DLDI "header inclusion %Functional" | |
1016 | + -> %(ExpandedFunction, Functor), | |
776 | 1017 | / DLDI "simplified internal static assertions" ^ '()' |
777 | 1018 | ~ '::value', |
778 | 1019 | / $re_add(b941) DLDI "all member type %traits" |
@@ -1106,7 +1347,7 @@ | ||
1106 | 1347 | // They should be same to implicily declared ones, hence \ |
1107 | 1348 | redundant. |
1108 | 1349 | ( |
1109 | - / "header inclusion %Placement" -> "%ComporessedPair", | |
1350 | + / "inclusion %Placement" -> "%ComporessedPair", | |
1110 | 1351 | / DLDI "function %get_allocator" |
1111 | 1352 | @ "class templates %(allocator_guard_delete, allocator_delete)" |
1112 | 1353 | !^ "using-declaration", |
@@ -1725,7 +1966,7 @@ | ||
1725 | 1966 | ), |
1726 | 1967 | / %TypeInspection $= |
1727 | 1968 | ( |
1728 | - / "header inclusion %CStandardDefinition" -> "%IntegralConstant" | |
1969 | + / "inclusion %CStandardDefinition" -> "%IntegralConstant" | |
1729 | 1970 | $dep_to "collapsed type inspection header inclusion", |
1730 | 1971 | + "conditionally defined macro %__cpp_lib_is_final"; |
1731 | 1972 | + "unary type trait %is_final" @ "inline namespace %cpp2014" |
@@ -2138,7 +2379,7 @@ | ||
2138 | 2379 | ( |
2139 | 2380 | / DLDI "simplified constructor template" @ "class %enum_union" |
2140 | 2381 | ^ "%empty_base" ~ "%std::tuple"; |
2141 | - / DLDI "header inclusion %Tuple" -> "%Variadic" | |
2382 | + / DLDI "inclusion %Tuple" -> "%Variadic" | |
2142 | 2383 | ), |
2143 | 2384 | + "function template %to_underlying" |
2144 | 2385 | ), |
@@ -2759,8 +3000,8 @@ | ||
2759 | 3000 | / "functions %((is_power_of_2; is_power_of_2_positive), ceiling_lb, \ |
2760 | 3001 | floor_lb)" -> "function templates with 'YB_ATTR_always_inline'" |
2761 | 3002 | @ %Bits; |
2762 | - - DLDI "header inclusion %CStandardInteger" @ %MemoryResource, | |
2763 | - - ("header inclusion %CStandardInteger" -> "%IteratorOperation") | |
3003 | + - DLDI "inclusion %CStandardInteger" @ %MemoryResource, | |
3004 | + / ("header inclusion %CStandardInteger" -> "%IteratorOperation") | |
2764 | 3005 | @ %Placement, |
2765 | 3006 | + $dev $lib 'YB_ATTR_always_inline' |
2766 | 3007 | @ "functions %(is_power_of_2, is_power_of_2_positive)" |
@@ -5594,7 +5835,7 @@ | ||
5594 | 5835 | for GCC 9.0.x. |
5595 | 5836 | + "macro %YB_LAMBDA_ANNOTATE" |
5596 | 5837 | ), |
5597 | - + $lib $impl "support of extra attributes powered by 'YB_ATTR_LAMBDA_PFRX'" | |
5838 | + / $lib $impl "supported of extra attributes powered by 'YB_ATTR_LAMBDA_PFX'" | |
5598 | 5839 | @ "all non-standard attributes" @ "lambda-expression" ^ $dep_from |
5599 | 5840 | ('YB_LAMBDA_ANNOTATE' @ %YBase.YDefinition) ~ ("'YB_*' attributes", |
5600 | 5841 | 'YB_LAMBDA_QUAL') $effective @ ("function %main" @ %SHBuild.Main, |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Definitions.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 方法和公共域定义与说明。 |
14 | -\version r14458 | |
14 | +\version r14459 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since 早于 build 132 |
17 | 17 | \par 创建时间: |
18 | 18 | 2010-01-26 19:34:51 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-05-24 18:20 +0800 | |
20 | + 2022-06-11 03:26 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -526,6 +526,7 @@ | ||
526 | 526 | { |
527 | 527 | $unit SContext |
528 | 528 | { |
529 | +#NPL_SContext_CompressTermTags | |
529 | 530 | NPL_Impl_SContext_Enable_ThunkedActions |
530 | 531 | #NPL_Impl_SContext_Enable_ThunkedThreshold |
531 | 532 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Dependencies.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 依赖说明。 |
14 | -\version r1680 | |
14 | +\version r1690 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 519 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-07-15 03:14:24 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-05-17 18:01 +0800 | |
20 | + 2022-06-10 18:43 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -66,9 +66,10 @@ | ||
66 | 66 | @1.1.2 非支持实现的已知问题: |
67 | 67 | 本节问题不提供变通。 |
68 | 68 | G++ 11.1.0 之后 12.1.0 前 LTO 因编译器内部错误不被支持。 |
69 | +部分 x86_64 GNU binutils 的 ld 链接 stage 1 SHBuild 时因不明原因无法解析符号,但 -fuse-ld=lld 可用,在此情形下(构建 stage 1 时)ld 不被支持。 | |
69 | 70 | |
70 | 71 | @1.1.2.1 历史版本的实现的问题: |
71 | -已知以下历史问题: | |
72 | +已知以下历史问题,不再适用于当前被支持的语言实现: | |
72 | 73 | G++ 4.8.2(4.8.2-17ubuntu1) : |
73 | 74 | 在启用 -flto 时,仅使用 std::thread 而不显式使用 pthread 的代码无法链接 pthread 导致运行时出错。 |
74 | 75 | 链接器命令行使用 -lpthread -Wl,--no-as-needed ,参见 http://stackoverflow.com/questions/19463602/compiling-multithread-code-with-g 。 |
@@ -78,7 +79,7 @@ | ||
78 | 79 | |
79 | 80 | @1.1.2.2 构建系统兼容性问题: |
80 | 81 | 已知以下问题可能通过构建系统提供通用的自动检测机制而避免,但当前没有实现: |
81 | -MinGW 平台输出可执行文件的后缀默认不为 .exe(如某些版本的 Clang++ )。 | |
82 | +特定工具链输出非预期文件名(如 MinGW 平台中某些版本的 Clang++ 输出的可执行文件后缀默认不为 .exe )。 | |
82 | 83 | |
83 | 84 | @1.1.3 正式支持变更记录: |
84 | 85 | YSLib 整体正式支持编译器版本要求变更如下: |
@@ -431,6 +432,13 @@ | ||
431 | 432 | 升级包 mingw64/mingw-w64-x86_64-winpthreads-git 和 mingw64/mingw-w64-x86_64-libwinpthread-git 版本 8.0.0.6001.98dad1fe-3 。 |
432 | 433 | 升级包 mingw64/mingw-w64-x86_64-binutils 版本 2.35.1-2 。 |
433 | 434 | 升级包 mingw64/mingw-w64-x86_64-freetype 2.10.2-2 。 |
435 | +2022-06-10(build 947) 起: | |
436 | +升级包 mingw64/mingw-w64-x86_64-gcc 和 mingw64/mingw-w64-x86_64-gcc-libs 版本 12.1.0-2 。 | |
437 | +升级包 mingw64/mingw-w64-x86_64-headers-git 和 mingw64/mingw-w64-x86_64-crt-git 版本 10.0.0.r32.g89bacd2be-1 。 | |
438 | +升级包 mingw64/mingw-w64-x86_64-winpthreads-git 和 mingw64/mingw-w64-x86_64-libwinpthread-git 版本 10.0.0.r32.g89bacd2be-1 。 | |
439 | +升级包 mingw64/mingw-w64-x86_64-binutils 版本 2.38-3 。 | |
440 | +升级包 mingw64/mingw-w64-x86_64-freetype 2.12.1-1 。 | |
441 | +使用包 mingw64/mingw-w64-x86_64-lld-14.0.4-1 。 | |
434 | 442 | |
435 | 443 | @1.7.1 MinGW64 库部署: |
436 | 444 | 同 MinGW32 库部署(@1.5.1) 的方式。 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Workflow.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 工作流汇总报告。 |
14 | -\version r4943 | |
14 | +\version r4958 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 433 |
17 | 17 | \par 创建时间: |
18 | 18 | 2013-07-31 01:27:41 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-06-05 02:19 +0800 | |
20 | + 2022-06-14 18:57 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -2590,7 +2590,7 @@ | ||
2590 | 2590 | This would cause undefined behavior with environment locking, e.g. in evaluation of expression '$let/e (() make-environment) () 42'. |
2591 | 2591 | The resolution of the bug also relies on removing the hack of collecting function prvalues (see below). |
2592 | 2592 | Now hack of prvalue function collection is also removed. |
2593 | - It seems at current it does not effect PTC typically. | |
2593 | + It seems at current it does not affect PTC typically. | |
2594 | 2594 | See $2018-06 for descriptions of original design. |
2595 | 2595 | |
2596 | 2596 | $2018-10: |
@@ -4821,7 +4821,7 @@ | ||
4821 | 4821 | The saved value is then never used. |
4822 | 4822 | This is generated for 'ystdex::tidy_ptr' copy constructor. |
4823 | 4823 | OTOH, x86_64-pc-linux Clang++ 13.0.1 always move the 'free_count' value from and to the memory in the call to 'add_free'. |
4824 | - The code generated is not changed by 'YB_ATTR(optimize("Os"))'. | |
4824 | + The code generated is not changed by 'YB_ATTR(optimize("Os"))' (actually ignored). | |
4825 | 4825 | Different to 'resource_pool::allocate', there is less chances to predicate the branches correctly, so more compact CMOVcc instructions can be a win. (And actually it generate worse code using '-Os' on 'resouce_pool::allocate'. |
4826 | 4826 | Note plain branch instructions can still be more compact in binary representations (and the compiler does not necessarily correctly figure that out), e.g. see https://bugs.llvm.org/show_bug.cgi?id=33013#c8. |
4827 | 4827 | This does not makes any differences with x86_64-pc-linux Clang++ 13.0.1, though. |
@@ -4879,6 +4879,19 @@ | ||
4879 | 4879 | This sequence is precisely implied by the destructor, as well as the the suffix except the returning value in 'operator()'. |
4880 | 4880 | By the call to 'dismiss' of the term guard in 'operator()' before the sequence, it remains compatible to both normal ('operator()') and abnormal (destructor entered by exception) returning. |
4881 | 4881 | Based on the fact that 'operator()' does not have custom actions relying on the program of the object language, the common sequence of the operation is deferred to the modification of 'ContextNode::TailAction' in 'ContextNode::ApplyTail'. |
4882 | +Some calls to qualified functions are cleanup. | |
4883 | + For calls with all function arguments of known types not being template specializations, ADL is not performed or has the results same to the unqualified name lookup. | |
4884 | + In such cases, the prefix (with '::') can be safely omitted without side effects, except there can be a bit worse compilation performance (usually ignored). | |
4885 | + It is now clear 'TermNode' and some other types defined as classes in namespace 'NPL' are the instances conform to the descriptions above. | |
4886 | + Notably, there are many calls to function templates named with prefix 'TryAccess'. | |
4887 | + Some other function templates named with prefix 'Access' and with the name 'TryAccessValue' are from namespace 'YSLib' by using declarations. | |
4888 | + Nevertheless, the only supported arguments 'ValueObject' is also introduced from 'YSLib' by same way. | |
4889 | + Additionally, function template 'NPL::make_observer' from 'YSLib' only accept built-in pointers, which have no associated namespaces respected to ADL. | |
4890 | + So it is also safe to remove the 'NPL::' prefix here. | |
4891 | + On the other hand, some calls to functions like 'TermToNamePtr', 'AccessFirstSubterm' and 'IsBranch' already has no 'NPL::' prefix. | |
4892 | + The changed calls would be more consistent to these calls. | |
4893 | + Similar calls out of the NPL implementation and calls like 'YSLib::make_observer' are also subjected to the cleanup. | |
4894 | + To make the changes in the current revision neat, the changes are planned in future. | |
4882 | 4895 | |
4883 | 4896 | //// |
4884 | 4897 |