The YSLib project - main repository
Revision | 63856ce04e5eda2e8bb05b73126939919b58ce95 (tree) |
---|---|
Zeit | 2022-05-08 23:20:20 |
Autor | FrankHB <frankhb1989@gmai...> |
Commiter | FrankHB |
更新主分支版本: build 944 rev 10 。
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2012-2016, 2018-2021 FrankHB. | |
2 | + © 2012-2016, 2018-2022 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file cassert.h |
12 | 12 | \ingroup YStandardEx |
13 | 13 | \brief ISO C 断言/调试跟踪扩展。 |
14 | -\version r309 | |
14 | +\version r311 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 432 |
17 | 17 | \par 创建时间: |
18 | 18 | 2013-07-27 04:11:53 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2021-12-13 12:37 +0800 | |
20 | + 2022-04-30 21:53 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -150,7 +150,7 @@ | ||
150 | 150 | // NOTE: As %assert, this may be undefined and redefined. |
151 | 151 | #ifndef YAssertNonnull |
152 | 152 | //! \since build 495 |
153 | -# define YAssertNonnull(_expr) YAssert(bool(_expr), "Null reference found.") | |
153 | +# define YAssertNonnull(_expr) YAssert(_expr, "Null reference found.") | |
154 | 154 | #endif |
155 | 155 | |
156 | 156 | #ifndef YTrace |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file container.hpp |
12 | 12 | \ingroup YStandardEx |
13 | 13 | \brief 通用容器操作。 |
14 | -\version r2610 | |
14 | +\version r2611 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 338 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-09-12 01:36:20 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-04-05 07:04 +0800 | |
20 | + 2022-05-05 02:34 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -202,7 +202,7 @@ | ||
202 | 202 | const_iterator position; |
203 | 203 | |
204 | 204 | prefix_eraser(container_type& con) ynothrow |
205 | - : prefix_eraser(con, con.end()) | |
205 | + : prefix_eraser(con, con.begin()) | |
206 | 206 | {} |
207 | 207 | //! \pre 第二参数是第一参数的迭代器。 |
208 | 208 | prefix_eraser(container_type& con, const_iterator i) |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file function.hpp |
12 | 12 | \ingroup YStandardEx |
13 | 13 | \brief 函数基本操作和调用包装对象。 |
14 | -\version r5052 | |
14 | +\version r5053 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 847 |
17 | 17 | \par 创建时间: |
18 | 18 | 2018-12-13 01:24:06 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-03-21 12:08 +0800 | |
20 | + 2022-04-29 00:50 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -377,7 +377,7 @@ | ||
377 | 377 | static _tRet |
378 | 378 | call(const _tContent& content, const _fInvoke& f, _tParams&&... args) |
379 | 379 | { |
380 | - yconstraint(bool(content)); | |
380 | + yconstraint(bool(content.has_value())); | |
381 | 381 | yassume(f); |
382 | 382 | return f(content, yforward(args)...); |
383 | 383 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r9455 | |
14 | +\version r9468 | |
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-04-22 19:31 +0800 | |
20 | + 2022-05-08 16:16 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -613,6 +613,7 @@ | ||
613 | 613 | /*! |
614 | 614 | \brief 标记记号节点:递归变换节点,转换其中的词素为记号值。 |
615 | 615 | \note 先变换子节点。 |
616 | +\warning 不保证嵌套调用安全。 | |
616 | 617 | \since build 753 |
617 | 618 | */ |
618 | 619 | YF_API void |
@@ -1602,10 +1603,15 @@ | ||
1602 | 1603 | /*! |
1603 | 1604 | \brief 对每个子项提升项的值数据成员可能包含的引用值。 |
1604 | 1605 | \sa LiftToReturn |
1605 | -\since build 830 | |
1606 | 1606 | */ |
1607 | +//@{ | |
1608 | +//! \since build 944 | |
1609 | +inline PDefH(void, LiftSubtermsToReturn, TermNode::Container& con) | |
1610 | + ImplExpr(std::for_each(con.begin(), con.end(), LiftToReturn)) | |
1611 | +//! \since build 830 | |
1607 | 1612 | inline PDefH(void, LiftSubtermsToReturn, TermNode& term) |
1608 | - ImplExpr(std::for_each(term.begin(), term.end(), LiftToReturn)) | |
1613 | + ImplExpr(LiftSubtermsToReturn(term.GetContainerRef())) | |
1614 | +//@} | |
1609 | 1615 | |
1610 | 1616 | //! \pre 断言:参数指定的项是枝节点。 |
1611 | 1617 | //@{ |
@@ -1947,7 +1953,9 @@ | ||
1947 | 1953 | \brief 名称解析结果。 |
1948 | 1954 | \since build 821 |
1949 | 1955 | |
1950 | - 名称解析的返回结果是环境中的绑定目标的对象指针和直接保存绑定目标的环境的引用。 | |
1956 | + 名称解析结果可以是: | |
1957 | + 环境中的绑定目标的非空对象指针和直接保存绑定目标的环境的引用; | |
1958 | + 表示没有找到指定变量的空指针和未指定的环境引用的值。 | |
1951 | 1959 | */ |
1952 | 1960 | using NameResolution |
1953 | 1961 | = pair<observer_ptr<BindingMap::mapped_type>, shared_ptr<Environment>>; |
@@ -2699,7 +2707,7 @@ | ||
2699 | 2707 | 若重定向可能具有共享所有权的失败,则表示资源访问错误,如构成循环引用; |
2700 | 2708 | 发现环境的循环引用视为失败,抛出异常;其它情形行为未定义。 |
2701 | 2709 | 以上支持的宿主值类型被依次尝试访问。若成功,则使用此宿主值类型访问环境。 |
2702 | - 对列表,使用 DFS (深度优先搜索)依次递归检查其元素。 | |
2710 | + 对列表,使用 DFS(深度优先搜索)依次递归检查其元素。 | |
2703 | 2711 | 循环重定向不终止。 |
2704 | 2712 | */ |
2705 | 2713 | YB_ATTR_nodiscard static Environment::NameResolution |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 公共接口。 |
14 | -\version r9447 | |
14 | +\version r9448 | |
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-04-26 00:10 +0800 | |
20 | + 2022-05-02 05:35 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -677,7 +677,7 @@ | ||
677 | 677 | \since build 896 |
678 | 678 | */ |
679 | 679 | inline PDefH(ReductionStatus, ReduceReturnUnspecified, TermNode& term) ynothrow |
680 | - ImplRet(term.SetValue(ValueToken::Unspecified), ReductionStatus::Clean) | |
680 | + ImplRet(term.Value = ValueToken::Unspecified, ReductionStatus::Clean) | |
681 | 681 | |
682 | 682 | |
683 | 683 | /*! |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file SContext.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief S 表达式上下文。 |
14 | -\version r4186 | |
14 | +\version r4233 | |
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-03-18 03:12 +0800 | |
20 | + 2022-04-28 03:46 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -29,8 +29,9 @@ | ||
29 | 29 | #define NPL_INC_SContext_h_ 1 |
30 | 30 | |
31 | 31 | #include "YModules.h" |
32 | -#include YFM_NPL_Lexical // for ystdex::copy_and_swap, pmr, ByteParser, | |
33 | -// ystdex::expand_proxy, ystdex::unref, ystdex::as_const, LexemeList; | |
32 | +#include YFM_NPL_Lexical // for ystdex::copy_and_swap, std::swap, pmr, | |
33 | +// ByteParser, ystdex::expand_proxy, ystdex::unref, ystdex::as_const, | |
34 | +// LexemeList; | |
34 | 35 | #include YFM_YSLib_Core_ValueNode // for YSLib::Deref, YSLib::MakeIndex, |
35 | 36 | // YSLib::NoContainer, YSLib::NoContainerTag, YSLib::ValueNode, |
36 | 37 | // YSLib::ValueObject, YSLib::forward_as_tuple, YSLib::get, |
@@ -43,6 +44,7 @@ | ||
43 | 44 | // YSLib::AccessPtr, ystdex::head_of_t, ystdex::addrof, ystdex::compose, pair, |
44 | 45 | // std::is_lvalue_reference, YSLib::Alert, YSLib::stack; |
45 | 46 | #include YFM_YSLib_Core_YException // for YSLib::LoggedEvent; |
47 | +#include <ystdex/operators.hpp> // for ystdex::equality_comparable; | |
46 | 48 | #include <ystdex/deref_op.hpp> // for ystdex::call_value_or; |
47 | 49 | #include <ystdex/range.hpp> // for std::iterator_traits, |
48 | 50 | // ystdex::range_iterator_t, ystdex::begin, ystdex::end, |
@@ -213,7 +215,7 @@ | ||
213 | 215 | 类似 ValueNode 的节点类型,但没有名称数据成员、按键比较和按键访问, |
214 | 216 | 且使用 list 而不是 ystdex::mapped_set 作为容器。 |
215 | 217 | */ |
216 | -class YF_API TermNode | |
218 | +class YF_API TermNode : private ystdex::equality_comparable<TermNode> | |
217 | 219 | { |
218 | 220 | private: |
219 | 221 | // TODO: Deduplicate within %ValueNode? |
@@ -254,12 +256,15 @@ | ||
254 | 256 | : container(a) |
255 | 257 | {} |
256 | 258 | TermNode(const Container& con) |
257 | - : container(con) | |
259 | + : TermNode(con, con.get_allocator()) | |
258 | 260 | {} |
259 | 261 | TermNode(Container&& con) |
260 | 262 | : container(std::move(con)) |
261 | 263 | {} |
262 | - //! \since build 853 | |
264 | + /*! | |
265 | + \note 除非 Value 的构造非嵌套调用安全,支持构造任意子节点时的嵌套调用安全。 | |
266 | + \since build 853 | |
267 | + */ | |
263 | 268 | //@{ |
264 | 269 | template<typename... _tParams, |
265 | 270 | yimpl(typename = enable_value_constructible_t<_tParams...>)> |
@@ -270,7 +275,8 @@ | ||
270 | 275 | template<typename... _tParams, |
271 | 276 | yimpl(typename = enable_value_constructible_t<_tParams...>)> |
272 | 277 | TermNode(const Container& con, _tParams&&... args) |
273 | - : container(con), Value(yforward(args)...) | |
278 | + : TermNode(std::allocator_arg, con.get_allocator(), con, | |
279 | + yforward(args)...) | |
274 | 280 | {} |
275 | 281 | template<typename... _tParams, |
276 | 282 | yimpl(typename = enable_value_constructible_t<_tParams...>)> |
@@ -289,7 +295,7 @@ | ||
289 | 295 | inline |
290 | 296 | TermNode(std::allocator_arg_t, allocator_type a, const Container& con, |
291 | 297 | _tParams&&... args) |
292 | - : container(con, a), Value(yforward(args)...) | |
298 | + : container(ConSub(con, a)), Value(yforward(args)...) | |
293 | 299 | {} |
294 | 300 | template<typename... _tParams, |
295 | 301 | yimpl(typename = enable_value_constructible_t<_tParams...>)> |
@@ -299,11 +305,11 @@ | ||
299 | 305 | : container(std::move(con), a), Value(yforward(args)...) |
300 | 306 | {} |
301 | 307 | //@} |
302 | - //! \warning 非嵌套调用安全。 | |
308 | + //! \warning 不保证嵌套调用安全。 | |
303 | 309 | TermNode(const ValueNode& nd, allocator_type a) |
304 | 310 | : container(ConCons(nd.GetContainer(), a)), Value(nd.Value) |
305 | 311 | {} |
306 | - //! \warning 非嵌套调用安全。 | |
312 | + //! \warning 不保证嵌套调用安全。 | |
307 | 313 | TermNode(ValueNode&& nd, allocator_type a) |
308 | 314 | : container(ConCons(std::move(nd.GetContainerRef()), a)), |
309 | 315 | Value(std::move(nd.Value)) |
@@ -324,17 +330,19 @@ | ||
324 | 330 | std::initializer_list<TermNode> il, _tParams&&... args) |
325 | 331 | : TermNode(std::allocator_arg, a, Container(il, a), yforward(args)...) |
326 | 332 | {} |
327 | - //! \warning 非嵌套调用安全。 | |
333 | + //! \warning 不保证嵌套调用安全。 | |
328 | 334 | explicit |
329 | 335 | TermNode(const ValueNode& nd) |
330 | 336 | : container(ConCons(nd.GetContainer())), Value(nd.Value) |
331 | 337 | {} |
332 | - //! \warning 非嵌套调用安全。 | |
338 | + //! \warning 不保证嵌套调用安全。 | |
333 | 339 | explicit |
334 | 340 | TermNode(ValueNode&& nd) |
335 | 341 | : container(ConCons(std::move(nd.GetContainer()))), |
336 | 342 | Value(std::move(nd.Value)) |
337 | 343 | {} |
344 | + //! \note 除非 Value 的构造非嵌套调用安全,支持构造任意子节点时的嵌套调用安全。 | |
345 | + //@{ | |
338 | 346 | /*! |
339 | 347 | \brief 复制构造:使用参数和参数的分配器。 |
340 | 348 | \since build 879 |
@@ -344,13 +352,14 @@ | ||
344 | 352 | {} |
345 | 353 | //! \brief 复制构造:使用参数和参数指定的分配器。 |
346 | 354 | TermNode(const TermNode& nd, allocator_type a) |
347 | - : container(nd.container, a), Value(nd.Value), Tags(nd.Tags) | |
355 | + : container(ConSub(nd.container, a)), Value(nd.Value), Tags(nd.Tags) | |
348 | 356 | {} |
349 | 357 | DefDeMoveCtor(TermNode) |
350 | 358 | TermNode(TermNode&& nd, allocator_type a) |
351 | 359 | : container(std::move(nd.container), a), Value(std::move(nd.Value)), |
352 | 360 | Tags(nd.Tags) |
353 | 361 | {} |
362 | + //@} | |
354 | 363 | |
355 | 364 | /*! |
356 | 365 | \brief 复制赋值:使用参数副本和交换操作。 |
@@ -365,7 +374,7 @@ | ||
365 | 374 | DefDeMoveAssignment(TermNode) |
366 | 375 | /* |
367 | 376 | \brief 析构:类定义外默认实现。 |
368 | - \note 支持移除任意子节点时的嵌套调用安全。 | |
377 | + \note 除非 Value 的析构非嵌套调用安全,支持移除任意子节点时的嵌套调用安全。 | |
369 | 378 | \since build 916 |
370 | 379 | */ |
371 | 380 | ~TermNode() |
@@ -380,6 +389,16 @@ | ||
380 | 389 | Clear(); |
381 | 390 | } |
382 | 391 | |
392 | + /*! | |
393 | + \brief 比较相等。 | |
394 | + \warning 不保证嵌套调用安全。 | |
395 | + \since build 944 | |
396 | + */ | |
397 | + YB_ATTR_nodiscard YB_PURE friend | |
398 | + PDefHOp(bool, ==, const TermNode& x, const TermNode& y) ynothrow | |
399 | + ImplRet(x.Tags == y.Tags && x.GetContainer() == y.GetContainer() | |
400 | + && x.Value == y.Value) | |
401 | + | |
383 | 402 | //! \since build 853 |
384 | 403 | YB_PURE DefBoolNeg(YB_PURE explicit, bool(Value) || !empty()) |
385 | 404 |
@@ -456,6 +475,8 @@ | ||
456 | 475 | con.emplace(position, NoContainer, yforward(args)...); |
457 | 476 | } |
458 | 477 | |
478 | + //! \note 除非 Value 的析构非嵌套调用安全,支持移除任意子节点时的嵌套调用安全。 | |
479 | + //@{ | |
459 | 480 | //! \note 不访问 Tags 。 |
460 | 481 | PDefH(void, Clear, ) ynothrow |
461 | 482 | // XXX: The order can be siginificant. |
@@ -464,10 +485,10 @@ | ||
464 | 485 | /*! |
465 | 486 | \brief 清除容器。 |
466 | 487 | \post 断言:\c IsLeaf(*this) 。 |
467 | - \note 支持移除任意子节点时的嵌套调用安全。 | |
468 | 488 | */ |
469 | 489 | void |
470 | 490 | ClearContainer() ynothrow; |
491 | + //@} | |
471 | 492 | |
472 | 493 | /*! |
473 | 494 | \note 允许被参数中被复制的对象直接或间接地被目标引用。 |
@@ -485,18 +506,22 @@ | ||
485 | 506 | //@} |
486 | 507 | |
487 | 508 | private: |
488 | - //! \warning 非嵌套调用安全。 | |
509 | + //! \warning 不保证嵌套调用安全。 | |
489 | 510 | //@{ |
490 | - static TermNode::Container | |
511 | + YB_ATTR_nodiscard YB_PURE static TermNode::Container | |
491 | 512 | ConCons(const ValueNode::Container&); |
492 | - static TermNode::Container | |
513 | + YB_ATTR_nodiscard YB_PURE static TermNode::Container | |
493 | 514 | ConCons(ValueNode::Container&&); |
494 | - static TermNode::Container | |
515 | + YB_ATTR_nodiscard YB_PURE static TermNode::Container | |
495 | 516 | ConCons(const ValueNode::Container&, allocator_type); |
496 | - static TermNode::Container | |
517 | + YB_ATTR_nodiscard YB_PURE static TermNode::Container | |
497 | 518 | ConCons(ValueNode::Container&&, allocator_type); |
498 | 519 | //@} |
499 | 520 | |
521 | + //! \since build 934 | |
522 | + YB_ATTR_nodiscard YB_PURE static Container | |
523 | + ConSub(const Container&, allocator_type); | |
524 | + | |
500 | 525 | public: |
501 | 526 | template<class _tCon, typename _fCallable, |
502 | 527 | yimpl(typename = ystdex::enable_if_t< |
@@ -588,7 +613,8 @@ | ||
588 | 613 | "Invalid allocator found."), container.swap(nd.container)) |
589 | 614 | |
590 | 615 | PDefH(void, SwapContent, TermNode& term) ynothrowv |
591 | - ImplExpr(SwapContainer(term), swap(Value, term.Value)) | |
616 | + ImplExpr(SwapContainer(term), swap(Value, term.Value), | |
617 | + std::swap(Tags, term.Tags)) | |
592 | 618 | |
593 | 619 | YB_ATTR_nodiscard YB_PURE PDefH(iterator, begin, ) ynothrow |
594 | 620 | ImplRet(container.begin()) |
@@ -638,7 +664,7 @@ | ||
638 | 664 | ImplRet(container.size()) |
639 | 665 | |
640 | 666 | friend PDefH(void, swap, TermNode& x, TermNode& y) ynothrowv |
641 | - ImplExpr(x.SwapContent(y), std::swap(x.Tags, y.Tags)) | |
667 | + ImplExpr(x.SwapContent(y)) | |
642 | 668 | }; |
643 | 669 | |
644 | 670 | //! \relates TermNode |
@@ -871,7 +897,7 @@ | ||
871 | 897 | /*! |
872 | 898 | \brief 根据节点和节点容器创建操作设置目标节点的值或子节点。 |
873 | 899 | \note 可用于创建副本。 |
874 | -\warning 不检查嵌套深度,不支持嵌套调用安全。 | |
900 | +\warning 不保证嵌套调用安全。 | |
875 | 901 | */ |
876 | 902 | template<typename _fCallable, class _tNode> |
877 | 903 | void |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2010-2015, 2019-2021 FrankHB. | |
2 | + © 2010-2015, 2019-2022 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file ShellHelper.cpp |
12 | 12 | \ingroup Helper |
13 | 13 | \brief Shell 助手模块。 |
14 | -\version r633 | |
14 | +\version r636 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 278 |
17 | 17 | \par 创建时间: |
18 | 18 | 2010-04-04 13:42:15 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2021-12-13 01:21 +0800 | |
20 | + 2022-04-30 21:53 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -73,7 +73,7 @@ | ||
73 | 73 | snftime(char* buf, size_t n, const std::tm& tm, |
74 | 74 | const char* format = DefaultTimeFormat) |
75 | 75 | { |
76 | - // FIXME: correct behavior for time with BC date(i.e. tm_year < -1900); | |
76 | + // FIXME: Correct behavior for time with BC date(i.e. tm_year < -1900). | |
77 | 77 | std::snprintf(buf, n, format, tm.tm_year + 1900, |
78 | 78 | tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); |
79 | 79 | } |
@@ -165,7 +165,7 @@ | ||
165 | 165 | auto p_list(make_shared<TextList::ListType>(styles.cbegin() |
166 | 166 | | ystdex::get_key, styles.cend() | ystdex::get_key)); |
167 | 167 | |
168 | - YAssert(bool(p_list) && !p_list->empty(), | |
168 | + YAssert(p_list && !p_list->empty(), | |
169 | 169 | "Invalid style mapping state found"); |
170 | 170 | p_list->front() = std::move(default_name); |
171 | 171 | return make_shared<TextList::ListType>(p_list->cbegin(), p_list->cend()); |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 公共接口。 |
14 | -\version r22322 | |
14 | +\version r22367 | |
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-04-26 00:32 +0800 | |
20 | + 2022-05-02 05:35 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -474,19 +474,24 @@ | ||
474 | 474 | : alloc(a) |
475 | 475 | {} |
476 | 476 | |
477 | - YB_FLATTEN ReductionStatus | |
477 | + ReductionStatus | |
478 | 478 | operator()(TermNode& term) const |
479 | 479 | { |
480 | 480 | #if NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass |
481 | 481 | YAssert(remained.empty(), "Invalid state found."); |
482 | - Transform(term, remained); | |
482 | + Transform(term); | |
483 | +# if NPL_Impl_NPLA1_Enable_ThunkedThreshold == 0 | |
484 | + YAssert(!remained.empty(), "Invalid state found."); | |
485 | + // 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 | +# endif | |
483 | 488 | while(!remained.empty()) |
484 | 489 | { |
485 | 490 | const auto term_ref(std::move(remained.top())); |
486 | 491 | |
487 | 492 | remained.pop(); |
488 | 493 | for(auto& tm : term_ref.get()) |
489 | - Transform(tm, remained); | |
494 | + Transform(tm); | |
490 | 495 | } |
491 | 496 | #else |
492 | 497 | Transform(term); |
@@ -495,25 +500,40 @@ | ||
495 | 500 | } |
496 | 501 | |
497 | 502 | private: |
503 | + YB_FLATTEN void | |
504 | + Transform(TermNode& term | |
505 | +# if defined(NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass) \ | |
506 | + && NPL_Impl_NPLA1_Enable_ThunkedThreshold != 0 | |
507 | + , size_t n = 0 | |
508 | +# endif | |
509 | + ) const | |
510 | + { | |
498 | 511 | #if NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass |
499 | - //! \since build 882 | |
512 | +# if NPL_Impl_NPLA1_Enable_ThunkedThreshold != 0 | |
513 | + if(++n < NPL_Impl_NPLA1_Enable_ThunkedThreshold) | |
514 | + { | |
515 | + TransformLeaf(term); | |
516 | + for(auto& tm : term) | |
517 | + Transform(tm, n); | |
518 | + return; | |
519 | + } | |
520 | +# endif | |
521 | + remained.push(term); | |
522 | + TransformLeaf(term); | |
523 | +#else | |
524 | + TransformLeaf(term); | |
525 | + for(auto& tm : term) | |
526 | + Transform(tm); | |
527 | +#endif | |
528 | + } | |
529 | + | |
530 | + //! \since build 944 | |
500 | 531 | void |
501 | - Transform(TermNode& term, TermStack& terms) const | |
532 | + TransformLeaf(TermNode& term) const | |
502 | 533 | { |
503 | - terms.push(term); | |
504 | 534 | SeparatorTransformer::ReplaceChildren(term, pfx, std::ref(filter)); |
505 | 535 | SeparatorTransformer::ReplaceChildren(term, pfx2, std::ref(filter2)); |
506 | 536 | } |
507 | -#else | |
508 | - void | |
509 | - Transform(TermNode& term) const | |
510 | - { | |
511 | - SeparatorTransformer::ReplaceChildren(term, pfx, std::ref(filter)); | |
512 | - SeparatorTransformer::ReplaceChildren(term, pfx2, std::ref(filter2)); | |
513 | - for(auto& tm : term) | |
514 | - Transform(tm); | |
515 | - } | |
516 | -#endif | |
517 | 537 | }; |
518 | 538 | |
519 | 539 |
@@ -702,7 +722,7 @@ | ||
702 | 722 | { |
703 | 723 | const auto p(TermToNamePtr(t)); |
704 | 724 | |
705 | - YAssert(bool(p), "Invalid parameter tree found."); | |
725 | + YAssert(p, "Invalid parameter tree found."); | |
706 | 726 | f(*p); |
707 | 727 | } |
708 | 728 | } |
@@ -1614,10 +1634,7 @@ | ||
1614 | 1634 | break; |
1615 | 1635 | case 'i': |
1616 | 1636 | if(id.substr(1) == "nert") |
1617 | - { | |
1618 | - term.Value = ValueToken::Unspecified; | |
1619 | - return ReductionStatus::Clean; | |
1620 | - } | |
1637 | + return ReduceReturnUnspecified(term); | |
1621 | 1638 | else if(id.substr(1) == "gnore") |
1622 | 1639 | { |
1623 | 1640 | term.Value = ValueToken::Ignore; |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Forms.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 语法形式。 |
14 | -\version r26599 | |
14 | +\version r26663 | |
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-04-26 00:40 +0800 | |
20 | + 2022-05-06 01:57 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -34,7 +34,7 @@ | ||
34 | 34 | // std::placeholders, std::ref, std::bind, ystdex::as_const, IsLeaf, |
35 | 35 | // ValueObject, ystdex::ref_eq, RelaySwitched, trivial_swap, shared_ptr, |
36 | 36 | // ContextHandler, YSLib::unordered_map, string, Environment, lref, TokenValue, |
37 | -// any_ops::use_holder, YSLib::in_place_type, YSLib::HolderFromPointer, | |
37 | +// any_ops::use_holder, in_place_type, YSLib::HolderFromPointer, | |
38 | 38 | // YSLib::allocate_shared, InvalidReference, BindParameter, MoveFirstSubterm, |
39 | 39 | // ResolveEnvironment, ShareMoveTerm, BindParameterWellFormed, ystdex::sfmt, |
40 | 40 | // TermToStringWithReferenceMark, ResolveTerm, LiftOtherOrCopy, |
@@ -46,13 +46,14 @@ | ||
46 | 46 | // NPL::SwitchToFreshEnvironment, TermTags, YSLib::Debug, YSLib::sfmt, |
47 | 47 | // A1::MakeForm, ystdex::expand_proxy, NPL::AccessRegular, GetLValueTagsOf, |
48 | 48 | // RegularizeTerm, IsBranchedList, LiftMovedOther, LiftOtherValue, |
49 | -// ThrowValueCategoryError, std::mem_fn, ystdex::bind1, | |
50 | -// ThrowListTypeErrorForNonlist, ThrowInvalidSyntaxError, | |
51 | -// CheckEnvironmentFormal, type_id, ystdex::update_thunk, IsTyped, BindSymbol, | |
52 | -// IsNPLASymbol, ystdex::fast_all_of, ystdex::call_value_or, A1::AsForm, | |
53 | -// LiftCollapsed, YSLib::usystem; | |
49 | +// ThrowValueCategoryError, std::mem_fn, ThrowListTypeErrorForNonlist, | |
50 | +// ThrowInvalidSyntaxError, CheckEnvironmentFormal, type_id, | |
51 | +// ystdex::update_thunk, IsTyped, BindSymbol, A1::AsForm, ystdex::bind1, | |
52 | +// IsNPLASymbol, ystdex::fast_all_of, ystdex::call_value_or, LiftCollapsed, | |
53 | +// YSLib::usystem; | |
54 | 54 | #include "NPLA1Internals.h" // for A1::Internals API; |
55 | 55 | #include YFM_NPL_SContext // for Session; |
56 | +#include <ystdex/functor.hpp> // for ystdex::id; | |
56 | 57 | #include <ystdex/scope_guard.hpp> // for ystdex::unique_guard, ystdex::dismiss; |
57 | 58 | #include <ystdex/container.hpp> // for ystdex::prefix_eraser; |
58 | 59 |
@@ -365,7 +366,7 @@ | ||
365 | 366 | // bound symbol can then be rebound to an ordinary |
366 | 367 | // (non-sharing object. |
367 | 368 | env.Bind(k, TermNode(TermNode::Container(t.get_allocator()), |
368 | - ValueObject(any_ops::use_holder, YSLib::in_place_type< | |
369 | + ValueObject(any_ops::use_holder, in_place_type< | |
369 | 370 | YSLib::HolderFromPointer<shared_ptr_t>>, |
370 | 371 | store[k] = YSLib::allocate_shared<ContextHandler>( |
371 | 372 | t.get_allocator(), ThrowInvalidCyclicReference)))); |
@@ -941,17 +942,17 @@ | ||
941 | 942 | }; |
942 | 943 | |
943 | 944 | |
944 | -//! \since build 874 | |
945 | +//! \since build 944 | |
945 | 946 | void |
946 | -MakeValueListOrMove(TermNode& term, TermNode& nd, | |
947 | +MakeValueListOrMove(TermNode::Container& con, TermNode& nd, | |
947 | 948 | ResolvedTermReferencePtr p_ref) |
948 | 949 | { |
949 | 950 | MakeValueOrMove(p_ref, [&]{ |
950 | 951 | for(const auto& sub : nd) |
951 | - term.Add(sub); | |
952 | + con.push_back(sub); | |
952 | 953 | }, [&]{ |
953 | 954 | // XXX: No cyclic reference check. |
954 | - term.GetContainerRef().splice(term.end(), nd.GetContainerRef()); | |
955 | + con.splice(con.end(), nd.GetContainerRef()); | |
955 | 956 | }); |
956 | 957 | } |
957 | 958 |
@@ -964,16 +965,22 @@ | ||
964 | 965 | TermToStringWithReferenceMark(nd, p_ref).c_str())); |
965 | 966 | } |
966 | 967 | |
968 | +//! \since build 944 | |
969 | +void | |
970 | +ConsItem(TermNode::Container& con, TermNode& y) | |
971 | +{ | |
972 | + ResolveTerm([&](TermNode& nd_y, ResolvedTermReferencePtr p_ref){ | |
973 | + if(IsList(nd_y)) | |
974 | + MakeValueListOrMove(con, nd_y, p_ref); | |
975 | + else | |
976 | + ThrowConsError(nd_y, p_ref); | |
977 | + }, y); | |
978 | +} | |
967 | 979 | //! \since build 859 |
968 | 980 | void |
969 | 981 | ConsItem(TermNode& term, TermNode& y) |
970 | 982 | { |
971 | - ResolveTerm([&](TermNode& nd_y, ResolvedTermReferencePtr p_ref){ | |
972 | - if(IsList(nd_y)) | |
973 | - MakeValueListOrMove(term, nd_y, p_ref); | |
974 | - else | |
975 | - ThrowConsError(nd_y, p_ref); | |
976 | - }, y); | |
983 | + ConsItem(term.GetContainerRef(), y); | |
977 | 984 | } |
978 | 985 | |
979 | 986 | //! \since build 912 |
@@ -1397,7 +1404,9 @@ | ||
1397 | 1404 | // not unique due to 2-pass iterations (e.g. it may be also used in |
1398 | 1405 | // a interleaved call to %BranchRestFwdReferenced with unspecified |
1399 | 1406 | // order to this call). |
1400 | - term.Value = TermReference(PropagateTo(tm.Tags, tags), tm, r_env); | |
1407 | + term.Value = ValueObject(std::allocator_arg, term.get_allocator(), | |
1408 | + in_place_type<TermReference>, PropagateTo(tm.Tags, tags), tm, | |
1409 | + r_env); | |
1401 | 1410 | // NOTE: No %TermNode::ClearContainer is here because %term is expected |
1402 | 1411 | // newly created. |
1403 | 1412 | YAssert(IsLeaf(term), "Invalid term found"); |
@@ -1463,7 +1472,7 @@ | ||
1463 | 1472 | |
1464 | 1473 | ++first; |
1465 | 1474 | if(move) |
1466 | - con.splice(con.end(), f(nd), first, last); | |
1475 | + con.splice(con.end(), f(nd.GetContainerRef()), first, last); | |
1467 | 1476 | else |
1468 | 1477 | for(; first != last; ++first) |
1469 | 1478 | f2(con.emplace_back(), *first); |
@@ -1474,21 +1483,21 @@ | ||
1474 | 1483 | void |
1475 | 1484 | BranchRestFwdReferenced(TermNode& term, TermNode& nd, bool move) |
1476 | 1485 | { |
1477 | - TransactRest(term, nd, move, std::mem_fn(&TermNode::GetContainerRef), | |
1478 | - ystdex::bind1(&TermNode::CopyContent, std::placeholders::_2)); | |
1479 | -} | |
1480 | - | |
1481 | -//! \since build 918 | |
1482 | -template<void(&_rLift)(TermNode&), typename _fInsert> | |
1486 | + TransactRest(term, nd, move, ystdex::id<>(), | |
1487 | + std::mem_fn(&TermNode::CopyContent)); | |
1488 | +} | |
1489 | + | |
1490 | +//! \since build 944 | |
1491 | +template<void(&_rLift)(TermNode::Container&), typename _fInsert> | |
1483 | 1492 | ReductionStatus |
1484 | 1493 | RestOrVal(TermNode& term, _fInsert insert) |
1485 | 1494 | { |
1486 | 1495 | return CallResolvedUnary([&](TermNode& nd, ResolvedTermReferencePtr p_ref){ |
1487 | 1496 | if(IsBranchedList(nd)) |
1488 | 1497 | TransactRest(term, nd, NPL::IsMovable(p_ref), |
1489 | - [](TermNode& tm) -> TermNode::Container&{ | |
1490 | - _rLift(tm); | |
1491 | - return tm.GetContainerRef(); | |
1498 | + [](TermNode::Container& con) -> TermNode::Container&{ | |
1499 | + _rLift(con); | |
1500 | + return con; | |
1492 | 1501 | }, [&](TermNode& nterm, TermNode& tm){ |
1493 | 1502 | insert(nterm, tm, p_ref->GetTags()); |
1494 | 1503 | }); |
@@ -1529,17 +1538,17 @@ | ||
1529 | 1538 | }, term); |
1530 | 1539 | } |
1531 | 1540 | |
1532 | -//! \since build 853 | |
1541 | +//! \since build 944 | |
1533 | 1542 | void |
1534 | -LiftNoOp(TermNode&) | |
1543 | +LiftNoOp(TermNode::Container&) | |
1535 | 1544 | // XXX: See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100472. |
1536 | 1545 | #if !(YB_IMPL_GNUCPP && YB_HAS_NOEXCEPT && __cplusplus >= 201703L) |
1537 | 1546 | ynothrow |
1538 | 1547 | #endif |
1539 | 1548 | {} |
1540 | 1549 | |
1541 | -//! \since build 918 | |
1542 | -template<void(&_rLift)(TermNode&)> | |
1550 | +//! \since build 944 | |
1551 | +template<void(&_rLift)(TermNode::Container&)> | |
1543 | 1552 | void |
1544 | 1553 | SetRestImpl(TermNode& term) |
1545 | 1554 | { |
@@ -1549,14 +1558,15 @@ | ||
1549 | 1558 | if(IsList(nd_y)) |
1550 | 1559 | { |
1551 | 1560 | const auto a(nd_x.get_allocator()); |
1552 | - TermNode nd_new(a); | |
1553 | - | |
1554 | - nd_new.emplace(); | |
1555 | - MakeValueListOrMove(nd_new, nd_y, p_ref_y); | |
1556 | - _rLift(nd_new); | |
1561 | + TermNode::Container con_new(a); | |
1562 | + | |
1563 | + con_new.emplace_back(); | |
1564 | + MakeValueListOrMove(con_new, nd_y, p_ref_y); | |
1565 | + _rLift(con_new); | |
1557 | 1566 | // XXX: The order is significant. |
1558 | - AccessFirstSubterm(nd_new) = MoveFirstSubterm(nd_x); | |
1559 | - swap(nd_x, nd_new); | |
1567 | + con_new.front() = MoveFirstSubterm(nd_x); | |
1568 | + swap(nd_x.GetContainerRef(), con_new); | |
1569 | + nd_x.Value.Clear(); | |
1560 | 1570 | } |
1561 | 1571 | else |
1562 | 1572 | ThrowListTypeErrorForNonlist(nd_y, p_ref_y); |
@@ -1832,19 +1842,27 @@ | ||
1832 | 1842 | } |
1833 | 1843 | |
1834 | 1844 | |
1835 | -//! \since build 859 | |
1845 | +/*! | |
1846 | +\pre 第三参数非空。 | |
1847 | +\since build 859 | |
1848 | +*/ | |
1836 | 1849 | ReductionStatus |
1837 | 1850 | ApplyImpl(TermNode& term, ContextNode& ctx, shared_ptr<Environment> p_env) |
1838 | 1851 | { |
1852 | + YAssert(p_env, "Invalid environment found."); | |
1853 | + | |
1839 | 1854 | auto i(term.begin()); |
1840 | 1855 | auto& comb(NPL::Deref(++i)); |
1841 | 1856 | |
1842 | 1857 | ForwardToUnwrapped(comb); |
1843 | - | |
1844 | - TermNode expr(std::allocator_arg, term.get_allocator(), {std::move(comb)}); | |
1845 | - | |
1846 | - ConsItem(expr, NPL::Deref(++i)); | |
1847 | - term = std::move(expr); | |
1858 | + { | |
1859 | + TermNode::Container tcon(term.get_allocator()); | |
1860 | + | |
1861 | + tcon.push_back(std::move(comb)); | |
1862 | + ConsItem(tcon, NPL::Deref(++i)); | |
1863 | + tcon.swap(term.GetContainerRef()); | |
1864 | + } | |
1865 | + ClearCombiningTags(term); | |
1848 | 1866 | // NOTE: The precondition is same to the last call in %EvalImplUnchecked. |
1849 | 1867 | // See also the precondition of %Combine<TailCall>::RelayEnvSwitch. |
1850 | 1868 | return Combine<TailCall>::RelayEnvSwitch(ctx, term, std::move(p_env)); |
@@ -1907,6 +1925,8 @@ | ||
1907 | 1925 | RemoveTermPostfix(gd); |
1908 | 1926 | } |
1909 | 1927 | term.Value.Clear(); |
1928 | + // XXX: No %ClearCombiningTags is called, as it would be determined later | |
1929 | + // in the subsequent combiner call. | |
1910 | 1930 | } |
1911 | 1931 | //@} |
1912 | 1932 |
@@ -2364,8 +2384,8 @@ | ||
2364 | 2384 | // to make the list elements having %TermTags::Temporary. |
2365 | 2385 | BranchRestFwdReferenced(nterm, nd, NPL::IsMovable(tags)); |
2366 | 2386 | }, [](TermNode& nterm, TermNode& o, TermTags o_tags){ |
2367 | - TransactRest(nterm, o, NPL::IsMovable(o.Tags | o_tags), std::mem_fn( | |
2368 | - &TermNode::GetContainerRef), std::mem_fn(&TermNode::CopyContent)); | |
2387 | + TransactRest(nterm, o, NPL::IsMovable(o.Tags | o_tags), ystdex::id<>(), | |
2388 | + std::mem_fn(&TermNode::CopyContent)); | |
2369 | 2389 | }); |
2370 | 2390 | return ReductionStatus::Retained; |
2371 | 2391 | } |
@@ -4485,7 +4505,6 @@ | ||
4485 | 4505 | yunseq(term.GetContainerRef() = std::move(con), |
4486 | 4506 | term.Value = std::move(vo)); |
4487 | 4507 | SetupNextTerm(ctx, term); |
4488 | - ClearCombiningTags(term); | |
4489 | 4508 | RemoveHead(term); |
4490 | 4509 | return ReductionStatus::Retained; |
4491 | 4510 | }, |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Internals.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 内部接口。 |
14 | -\version r20599 | |
14 | +\version r20602 | |
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-04-05 15:19 +0800 | |
20 | + 2022-04-30 21:54 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 非公开模块名称: |
@@ -177,8 +177,6 @@ | ||
177 | 177 | void |
178 | 178 | TCOAction::CompressFrameList() |
179 | 179 | { |
180 | - auto i(RecordList.cbegin()); | |
181 | - | |
182 | 180 | ystdex::retry_on_cond(ystdex::id<>(), [&]() -> bool{ |
183 | 181 | bool removed = {}; |
184 | 182 |
@@ -250,8 +248,7 @@ | ||
250 | 248 | ReduceAsSubobjectReference(TermNode& term, shared_ptr<TermNode> p_sub, |
251 | 249 | const EnvironmentReference& r_env) |
252 | 250 | { |
253 | - YAssert(bool(p_sub), | |
254 | - "Invalid subterm to form a subobject reference found."); | |
251 | + YAssert(p_sub, "Invalid subterm to form a subobject reference found."); | |
255 | 252 | |
256 | 253 | // NOTE: Irregular representation is constructed for the subobject |
257 | 254 | // reference. |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Internals.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 内部接口。 |
14 | -\version r22076 | |
14 | +\version r22108 | |
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-04-25 01:04 +0800 | |
20 | + 2022-05-06 01:22 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 非公开模块名称: |
@@ -29,9 +29,9 @@ | ||
29 | 29 | #define NPL_INC_NPLA1Internals_h_ 1 |
30 | 30 | |
31 | 31 | #include "YModules.h" |
32 | -#include YFM_NPL_NPLA1 // for ContextNode, TermNode, ContextState, | |
33 | -// ReductionStatus, Reducer, YSLib::map, lref, Environment, | |
34 | -// set, NPL::Deref, IsTyped, EnvironmentList, EnvironmentReference, tuple, | |
32 | +#include YFM_NPL_NPLA1 // for shared_ptr, ContextNode, NPL::Deref, NPLException, | |
33 | +// TermNode, ReductionStatus, Reducer, YSLib::map, lref, Environment, | |
34 | +// set, IsTyped, EnvironmentList, EnvironmentReference, tuple, | |
35 | 35 | // YSLib::get, YSLib::forward_list, size_t, list, std::declval, |
36 | 36 | // EnvironmentGuard, MoveKeptGuard, A1::NameTypedContextHandler, TermReference, |
37 | 37 | // ThrowTypeErrorForInvalidType, NPL::TryAccessLeaf, type_id, |
@@ -43,6 +43,7 @@ | ||
43 | 43 | #include <ystdex/ref.hpp> // for std::reference_wrapper, std::ref, |
44 | 44 | // ystdex::unref; |
45 | 45 | #include <ystdex/bind.hpp> // for ystdex::bind1, std::placeholders::_2; |
46 | +#include <ystdex/function.hpp> // for ystdex::unchecked_function; | |
46 | 47 | #include <ystdex/function_adaptor.hpp> // for ystdex::update_thunk; |
47 | 48 | #include <iterator> // for std::next; |
48 | 49 |
@@ -78,6 +79,13 @@ | ||
78 | 79 | // supporting PTC are noted in implementations separatedly. |
79 | 80 | #define NPL_Impl_NPLA1_Enable_TCO true |
80 | 81 | #define NPL_Impl_NPLA1_Enable_Thunked true |
82 | +// NOTE: If non zero, thunks are only used only for more than certain level of | |
83 | +// nested calls occur. The value should be small enough to ensure the nested | |
84 | +// call safety guarantee still works in practice. Currently only enabled for | |
85 | +// thunked separator passes (see below). | |
86 | +#ifndef NPL_Impl_NPLA1_Enable_ThunkedThreshold | |
87 | +# define NPL_Impl_NPLA1_Enable_ThunkedThreshold yimpl(16U) | |
88 | +#endif | |
81 | 89 | #define NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass NPL_Impl_NPLA1_Enable_Thunked |
82 | 90 | |
83 | 91 | //! \since build 820 |
@@ -331,7 +339,7 @@ | ||
331 | 339 | \brief 一次调用检查守卫。 |
332 | 340 | \since build 943 |
333 | 341 | */ |
334 | - mutable ystdex::optional<ystdex::guard<OneShotChecker>> one_shot_guard; | |
342 | + mutable ystdex::optional<ystdex::guard<OneShotChecker>> one_shot_guard{}; | |
335 | 343 | |
336 | 344 | public: |
337 | 345 | //! \since build 819 |
@@ -347,7 +355,7 @@ | ||
347 | 355 | "Invalid value for combining term found."); |
348 | 356 | return std::move(term.Value); |
349 | 357 | // XXX: After the move, %term.Value is unspecified. |
350 | - }()), one_shot_guard() | |
358 | + }()) | |
351 | 359 | // XXX: Do not call %AssertValueTags on %term, as it is usually a |
352 | 360 | // combinitation instead of the representation of some object language |
353 | 361 | // value. |
@@ -359,11 +367,10 @@ | ||
359 | 367 | // object always live longer than the older one. |
360 | 368 | : term_guard(std::move(a.term_guard)), |
361 | 369 | req_lift_result(a.req_lift_result), stashed(ystdex::exchange(a.stashed, |
362 | - ContextHandler())), EnvGuard(std::move(a.EnvGuard)), | |
363 | - one_shot_guard() | |
370 | + ContextHandler())), EnvGuard(std::move(a.EnvGuard)) | |
364 | 371 | { |
365 | - if(a.one_shot_guard.has_value()) | |
366 | - one_shot_guard.emplace((*a.one_shot_guard).func); | |
372 | + if(a.one_shot_guard) | |
373 | + one_shot_guard.emplace(a.one_shot_guard->func); | |
367 | 374 | } |
368 | 375 | DefDeMoveCtor(TCOAction) |
369 | 376 | // XXX: Out of line destructor here is inefficient. |
@@ -456,12 +463,12 @@ | ||
456 | 463 | YB_ATTR_nodiscard OneShotChecker |
457 | 464 | MakeOneShotChecker() |
458 | 465 | { |
459 | - if(!one_shot_guard.has_value()) | |
466 | + if(!one_shot_guard) | |
460 | 467 | // XXX: The context is only used to determine the allocator, which |
461 | 468 | // is an implementation detail. Usually the context in caller |
462 | 469 | // should be the same, though. |
463 | 470 | one_shot_guard.emplace(EnvGuard.func.Context.get()); |
464 | - return (*one_shot_guard).func; | |
471 | + return one_shot_guard->func; | |
465 | 472 | } |
466 | 473 | |
467 | 474 | //! \since build 940 |
@@ -1099,7 +1106,7 @@ | ||
1099 | 1106 | |
1100 | 1107 | |
1101 | 1108 | //! \since build 881 |
1102 | -using Action = function<void()>; | |
1109 | +using Action = ystdex::unchecked_function<void()>; | |
1103 | 1110 | |
1104 | 1111 | |
1105 | 1112 | //! \since build 897 |
@@ -1123,11 +1130,18 @@ | ||
1123 | 1130 | == &ref, "Invalid term or reference value found."), term.SetContent( |
1124 | 1131 | bound.GetContainer(), EnsureLValueReference(TermReference(ref)))) |
1125 | 1132 | |
1126 | -//! \since build 920 | |
1127 | -inline PDefH(void, SetEvaluatedValue, TermNode& term, | |
1128 | - TermNode& bound, shared_ptr<Environment>& p_env) | |
1129 | - ImplExpr(term.Value = TermReference(NPL::Deref(p_env).MakeTermTags(bound) | |
1130 | - & ~TermTags::Unique, bound, std::move(p_env))) | |
1133 | +/*! | |
1134 | +\pre 第三参数非空。 | |
1135 | +\since build 944 | |
1136 | +*/ | |
1137 | +inline PDefH(void, SetEvaluatedValue, TermNode& term, TermNode& bound, | |
1138 | + const shared_ptr<Environment>& p_env) | |
1139 | + ImplExpr(term.Value = [&](Environment& env){ | |
1140 | + return ValueObject(std::allocator_arg, term.get_allocator(), | |
1141 | + in_place_type<TermReference>, env.MakeTermTags(bound) | |
1142 | + & ~TermTags::Unique, bound, | |
1143 | + EnvironmentReference(p_env, env.GetAnchorPtr())); | |
1144 | + }(NPL::Deref(p_env))) | |
1131 | 1145 | |
1132 | 1146 | |
1133 | 1147 | //! \since build 917 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file SContext.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief S 表达式上下文。 |
14 | -\version r2120 | |
14 | +\version r2292 | |
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-03-14 18:23 +0800 | |
20 | + 2022-04-29 18:57 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -26,11 +26,143 @@ | ||
26 | 26 | |
27 | 27 | |
28 | 28 | #include "NPL/YModules.h" |
29 | -#include YFM_NPL_SContext // for ystdex::ref_eq; | |
29 | +#include YFM_NPL_SContext // for vector, NPL::Deref, std::allocator_arg, | |
30 | +// YSLib::stack, pair, lref; | |
31 | +#include <ystdex/function.hpp> // for ystdex::unchecked_function, | |
32 | +// ystdex::trivial_swap; | |
33 | +// NOTE: This enables thunked actions in copy for nested call safety, instead of | |
34 | +// using stacks. | |
35 | +#define NPL_Impl_SContext_Enable_ThunkedActions true | |
36 | +#if NPL_Impl_SContext_Enable_ThunkedActions | |
37 | +// NOTE: If non zero, thunks are only used only for more than certain level of | |
38 | +// nested calls occur. The value should be small enough to ensure the nested | |
39 | +// call safety guarantee still works in practice. | |
40 | +# ifndef NPL_Impl_SContext_Enable_ThunkedThreshold | |
41 | +# define NPL_Impl_SContext_Enable_ThunkedThreshold yimpl(32U) | |
42 | +# endif | |
43 | +#else | |
44 | +# include <ystdex/expanded_function.hpp> // for ystdex::retry_on_cond; | |
45 | +#endif | |
30 | 46 | |
31 | 47 | namespace NPL |
32 | 48 | { |
33 | 49 | |
50 | +#if NPL_Impl_SContext_Enable_ThunkedActions | |
51 | +//! \since build 944 | |
52 | +namespace | |
53 | +{ | |
54 | + | |
55 | +struct ConSubThunk final | |
56 | +{ | |
57 | + // XXX: This is more efficient than %function instance with | |
58 | + // %ystdex::update_thunk for normal cases. | |
59 | + using Action = ystdex::unchecked_function<void()>; | |
60 | + mutable vector<Action> Current; | |
61 | + | |
62 | + ConSubThunk(TermNode::allocator_type a) ynothrow | |
63 | + : Current(a) | |
64 | + {} | |
65 | + | |
66 | + void | |
67 | + operator()(TermNode::Container& res, const TermNode::Container& con) | |
68 | + const | |
69 | + { | |
70 | + CopySubterms(res, con.begin(), con.end()); | |
71 | + while(!Current.empty()) | |
72 | + { | |
73 | + const auto f(std::move(Current.back())); | |
74 | + | |
75 | + Current.pop_back(); | |
76 | + f(); | |
77 | + } | |
78 | + } | |
79 | + | |
80 | + void | |
81 | + CopySubterms(TermNode::Container& r, TNCIter first, TNCIter last | |
82 | +# if NPL_Impl_SContext_Enable_ThunkedThreshold != 0 | |
83 | + , size_t n = 0 | |
84 | +# endif | |
85 | + ) const | |
86 | + { | |
87 | + YAssert(first != last, "Invalid range found."); | |
88 | + | |
89 | + auto& dst(r.emplace_back()); | |
90 | + const auto& src(NPL::Deref(first)); | |
91 | + | |
92 | + ++first; | |
93 | +# if NPL_Impl_SContext_Enable_ThunkedThreshold != 0 | |
94 | + if(++n < NPL_Impl_SContext_Enable_ThunkedThreshold) | |
95 | + { | |
96 | + if(!src.empty()) | |
97 | + CopySubterms(dst.GetContainerRef(), src.begin(), src.end(), n); | |
98 | + if(first != last) | |
99 | + CopySubterms(r, first, last, n); | |
100 | + CopyValueAndTags(dst, src); | |
101 | + return; | |
102 | + } | |
103 | +# endif | |
104 | + UpdateCopyValueAndTags(dst, src); | |
105 | + if(first != last) | |
106 | + UpdateCopySubterms(r, first, last | |
107 | +# if NPL_Impl_SContext_Enable_ThunkedThreshold != 0 | |
108 | + , n | |
109 | +# endif | |
110 | + ); | |
111 | + if(!src.empty()) | |
112 | + Update( | |
113 | +# if NPL_Impl_SContext_Enable_ThunkedThreshold != 0 | |
114 | + [&, n]{ | |
115 | + CopySubterms(dst.GetContainerRef(), src.begin(), src.end(), n); | |
116 | +# else | |
117 | + [&]{ | |
118 | + CopySubterms(dst.GetContainerRef(), src.begin(), src.end()); | |
119 | +# endif | |
120 | + }); | |
121 | + } | |
122 | + | |
123 | + static PDefH(void, CopyValueAndTags, TermNode& dst, const TermNode& src) | |
124 | + ImplUnseq(dst.Value = src.Value, dst.Tags = src.Tags) | |
125 | + | |
126 | + template<typename _func> | |
127 | + void | |
128 | + Update(_func f) const | |
129 | + { | |
130 | + // XXX: Allocators are not used here for performance. | |
131 | + Current.push_back(std::move(f)); | |
132 | + } | |
133 | + | |
134 | + void | |
135 | + UpdateCopySubterms(TermNode::Container& r, TNCIter first, TNCIter last | |
136 | +# if NPL_Impl_SContext_Enable_ThunkedThreshold != 0 | |
137 | + , size_t n = 0 | |
138 | +# endif | |
139 | + ) const | |
140 | + { | |
141 | + Update( | |
142 | +# if NPL_Impl_SContext_Enable_ThunkedThreshold != 0 | |
143 | + [&, first, last, n]{ | |
144 | + CopySubterms(r, first, last, n); | |
145 | +# else | |
146 | + [&, first, last]{ | |
147 | + CopySubterms(r, first, last); | |
148 | +# endif | |
149 | + }); | |
150 | + } | |
151 | + | |
152 | + // XXX: Making it a separate definition slightly improves the generated code | |
153 | + // quality with x86_64-pc-linux G++ 11.1.0. | |
154 | + void | |
155 | + UpdateCopyValueAndTags(TermNode& dst, const TermNode& src) const | |
156 | + { | |
157 | + Update([&]{ | |
158 | + CopyValueAndTags(dst, src); | |
159 | + }); | |
160 | + } | |
161 | +}; | |
162 | + | |
163 | +} // unnamed namespace; | |
164 | +#endif | |
165 | + | |
34 | 166 | void |
35 | 167 | TermNode::ClearContainer() ynothrow |
36 | 168 | { |
@@ -106,6 +238,65 @@ | ||
106 | 238 | } |
107 | 239 | |
108 | 240 | |
241 | +TermNode::Container | |
242 | +TermNode::ConSub(const Container& con, allocator_type a) | |
243 | +{ | |
244 | + Container res(a); | |
245 | + | |
246 | + if(!con.empty()) | |
247 | + { | |
248 | +#if NPL_Impl_SContext_Enable_ThunkedActions | |
249 | + // XXX: This works more efficiently when | |
250 | + // %NPL_Impl_SContext_Enable_ThunkedThreshold is sufficient large. | |
251 | + ConSubThunk{a}(res, con); | |
252 | +#else | |
253 | + // XXX: Use of the default container (%deque) is more efficient. | |
254 | + YSLib::stack<pair<lref<TermNode>, lref<const TermNode>>> remained(a), | |
255 | + tms(a); | |
256 | + | |
257 | + // XXX: The order of copying the %Value objects is preserved. Otherwise | |
258 | + // the resource allocations and tags modifications are consided pure, | |
259 | + // so the order is not necessarily the same in naive implementations | |
260 | + // not supporting the nested call safety. | |
261 | + for(const auto& sub : con) | |
262 | + { | |
263 | + res.emplace_back(); | |
264 | + remained.emplace(res.back(), sub), | |
265 | + tms.emplace(res.back(), sub), | |
266 | + res.back().Tags = sub.Tags; | |
267 | + // TODO: Use %not_fn? | |
268 | + ystdex::retry_on_cond([&]() ynothrow{ | |
269 | + return !remained.empty(); | |
270 | + }, [&]{ | |
271 | + auto& dst_con(remained.top().first.get().GetContainerRef()); | |
272 | + auto& src(remained.top().second.get()); | |
273 | + | |
274 | + remained.pop(); | |
275 | + for(auto i(src.rbegin()); i != src.rend(); ++i) | |
276 | + { | |
277 | + dst_con.emplace_front(); | |
278 | + | |
279 | + auto& nterm(dst_con.front()); | |
280 | + auto& tm(*i); | |
281 | + | |
282 | + remained.emplace(nterm, tm), | |
283 | + tms.emplace(nterm, tm), | |
284 | + nterm.Tags = tm.Tags; | |
285 | + } | |
286 | + }); | |
287 | + ystdex::retry_on_cond([&]() ynothrow{ | |
288 | + return !tms.empty(); | |
289 | + }, [&]{ | |
290 | + tms.top().first.get().Value = tms.top().second.get().Value; | |
291 | + tms.pop(); | |
292 | + }); | |
293 | + } | |
294 | +#endif | |
295 | + } | |
296 | + return res; | |
297 | +} | |
298 | + | |
299 | + | |
109 | 300 | void |
110 | 301 | ReaderState::UpdateLexeme(const string& lexeme) |
111 | 302 | { |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2011-2021 FrankHB. | |
2 | + © 2011-2022 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file FileSystem.cpp |
12 | 12 | \ingroup YCLib |
13 | 13 | \brief 平台相关的文件系统接口。 |
14 | -\version r4989 | |
14 | +\version r4991 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 312 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-05-30 22:41:35 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2021-12-12 16:54 +0800 | |
20 | + 2022-04-30 21:54 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -711,7 +711,7 @@ | ||
711 | 711 | { |
712 | 712 | if(*this) |
713 | 713 | { |
714 | - YAssert(bool(GetNativeHandle()), "Invariant violation found."); | |
714 | + YAssert(GetNativeHandle(), "Invariant violation found."); | |
715 | 715 | |
716 | 716 | #if YCL_Win32 |
717 | 717 | const auto res(Deref(static_cast<platform_ex::DirectoryFindData*>( |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2014-2015, 2021 FrankHB. | |
2 | + © 2014-2015, 2021-2022 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file ImageProcessing.cpp |
12 | 12 | \ingroup Service |
13 | 13 | \brief 图像处理。 |
14 | -\version r285 | |
14 | +\version r287 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 554 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-11-16 16:37:27 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2021-12-24 23:51 +0800 | |
20 | + 2022-04-30 21:54 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -37,7 +37,7 @@ | ||
37 | 37 | CompactPixmap |
38 | 38 | Zoom(const HBitmap& bitmap, ImageScale ratio) |
39 | 39 | { |
40 | - YAssert(bool(bitmap), "Invalid bitmap found."); | |
40 | + YAssert(bitmap, "Invalid bitmap found."); | |
41 | 41 | |
42 | 42 | const Size bmp_size(bitmap.GetSize()); |
43 | 43 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2009-2015, 2017, 2019 FrankHB. | |
2 | + © 2009-2015, 2017, 2019, 2022 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file TextRenderer.cpp |
12 | 12 | \ingroup Service |
13 | 13 | \brief 文本渲染。 |
14 | -\version r2766 | |
14 | +\version r2768 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 275 |
17 | 17 | \par 创建时间: |
18 | 18 | 2009-11-13 00:06:05 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2019-01-14 18:54 +0800 | |
20 | + 2022-04-30 21:55 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -48,7 +48,7 @@ | ||
48 | 48 | YB_ATTR_nodiscard PaintContext |
49 | 49 | ClipChar(const Graphics& g, const Point& pen, const CharBitmap& cbmp, Rect r) |
50 | 50 | { |
51 | - YAssert(bool(g), "Invalid graphics context found."); | |
51 | + YAssert(g, "Invalid graphics context found."); | |
52 | 52 | |
53 | 53 | const auto pt(ClipBounds(r, Rect(pen.X + cbmp.GetLeft(), |
54 | 54 | pen.Y - cbmp.GetTop(), cbmp.GetWidth(), cbmp.GetHeight()))); |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2015 FrankHB. | |
2 | + © 2015, 2022 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file YBlend.cpp |
12 | 12 | \ingroup Service |
13 | 13 | \brief 平台无关的图像块操作。 |
14 | -\version r56 | |
14 | +\version r59 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 584 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-03-17 06:19:55 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2015-03-17 06:45 +0800 | |
20 | + 2022-04-30 21:56 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -39,7 +39,7 @@ | ||
39 | 39 | void |
40 | 40 | BlendRect(const Graphics& g, const Rect& r, Color c) |
41 | 41 | { |
42 | - YAssert(bool(g), "Invalid graphics context found."); | |
42 | + YAssert(g, "Invalid graphics context found."); | |
43 | 43 | BlendRectRaw(g.GetBufferPtr(), Pixel(c), g.GetSize(), r); |
44 | 44 | } |
45 | 45 |
@@ -47,7 +47,7 @@ | ||
47 | 47 | void |
48 | 48 | CompositeRect(const Graphics& g, const Rect& r, Color c) |
49 | 49 | { |
50 | - YAssert(bool(g), "Invalid graphics context found."); | |
50 | + YAssert(g, "Invalid graphics context found."); | |
51 | 51 | CompositeRectRaw(g.GetBufferPtr(), Pixel(c), g.GetSize(), r); |
52 | 52 | } |
53 | 53 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2011-2016, 2019 FrankHB. | |
2 | + © 2011-2016, 2019, 2022 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file YDraw.cpp |
12 | 12 | \ingroup Service |
13 | 13 | \brief 平台无关的二维图形光栅化。 |
14 | -\version r1118 | |
14 | +\version r1120 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 219 |
17 | 17 | \par 创建时间: |
18 | 18 | 2011-06-16 19:45:33 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2019-01-14 18:54 +0800 | |
20 | + 2022-04-30 21:56 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -149,7 +149,7 @@ | ||
149 | 149 | void |
150 | 150 | FillRect(const Graphics& g, const Rect& r, Color c) |
151 | 151 | { |
152 | - YAssert(bool(g), "Invalid graphics context found."); | |
152 | + YAssert(g, "Invalid graphics context found."); | |
153 | 153 | FillRectRaw(g.GetBufferPtr(), Pixel(c), g.GetSize(), r); |
154 | 154 | } |
155 | 155 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file ChangeLog.V0.9.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 版本更新历史记录 - V0.9 。 |
14 | -\version r9118 | |
14 | +\version r9260 | |
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-04-26 01:15 +0800 | |
20 | + 2022-05-08 21:29 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -32,6 +32,149 @@ | ||
32 | 32 | |
33 | 33 | $now |
34 | 34 | ( |
35 | + / %YBase.YStandardEx $= | |
36 | + ( | |
37 | + * "ill-formed expression" @ "'yconstraint' operand" | |
38 | + @ "static function %call" @ "class template specialization \ | |
39 | + %function_traits for %empty_function_policy::no_check" | |
40 | + @ %YBase.YStandardEx.Function $since b849, | |
41 | + / "constructor#1" @ "class template %prefix_eraser" @ %Container | |
42 | + ^ "first iterator in the range" ~ "last iterator in the range" | |
43 | + // Subsequent insertions would not be guarded by the old behavior. \ | |
44 | + And it is also more natural to construct a no-op guard by \ | |
45 | + default. | |
46 | + ), | |
47 | + / DLDI "simplified 1st operand" @ "%YAssert invocations" !^ 'bool' | |
48 | + $effective @ %(YBase.YStandardEx.CAssert, | |
49 | + YFramework.(Helper.ShellHelper, NPL.(NPLA1, NPLA1Internals), | |
50 | + YCLib.FileSystem, YSLib.Service.(ImageProcessing, TextRenderer, | |
51 | + YBlend))), | |
52 | + // A few exceptions are in %YFramework.YSLib.Service.YGDI, which need \ | |
53 | + casts. | |
54 | + / %YFramework.NPL $= | |
55 | + ( | |
56 | + / @ "class %TermNode" @ %Scontext $= | |
57 | + ( | |
58 | + ( | |
59 | + * "missing swapping tags" @ "function %SetContent#3" | |
60 | + $since b857 ^ "%std::swap"; | |
61 | + // Also to be consistent %SetContnet. Now this is same to the \ | |
62 | + friend function %swap. | |
63 | + / DLDI "simplified friend function %swap" !^ "%std::swap" | |
64 | + ), | |
65 | + ( | |
66 | + + "2 static function %AreEqual"; | |
67 | + + "friend function %operator=="; | |
68 | + + "friend %operator!=" | |
69 | + ^ "private base %ystdex::equality_comparable<TermNode>" | |
70 | + // If a container of list is saved in %Value, it requires '==' of \ | |
71 | + %TermNode to work with %ValueObject. | |
72 | + ), | |
73 | + ( | |
74 | + / "constructors with parameter of 'const TermNode&'" | |
75 | + ^ "allocator from the 1st argument"; | |
76 | + // This is more consistent to the copy constructor. | |
77 | + * $re_add(b916) "missing nested call safety in handling terms from \ | |
78 | + object language" @ (("copy constructor with allocator"; | |
79 | + $comp "copy constructor"), "constructors with pamameter of \ | |
80 | + 'const Container&'") $orig (@ "type %TermNode" $since b674) | |
81 | + $= (/ $impl ^ ("%ystdex::unchecked_function" | |
82 | + @ $dep_from %YBase.YStandardEx.Function)) | |
83 | + ) | |
84 | + ), | |
85 | + / %NPLA1Internals $= | |
86 | + ( | |
87 | + - DLDI "unused variable" @ "member function \ | |
88 | + %TCOAction::CompressFrameList", | |
89 | + // Also to eliminate G++ waraning: [-Wunused-variable]. | |
90 | + / DLDI "simplified one shot guard initialization" | |
91 | + ^ "brace-initializer '{}'", | |
92 | + / DLDI "simplified" @ ("copy constructor", | |
93 | + "function %MakeOneShotChecker") | |
94 | + ^ ('->' ~ ('*', '.'), "cast" ~ "%optional::has_value"), | |
95 | + / "%Action" ^ "%ystdex::unchecked_function" ~ "%function", | |
96 | + + "macro %NPL_Impl_NPLA1_Enable_ThunkedThreshold", | |
97 | + / "function %SetEvaluatedValue" $= | |
98 | + ( | |
99 | + + 'const' @ "3rd parameter", | |
100 | + + DD "'\pre' command" @ "Doxygen comment", | |
101 | + / DLI "optimized for nonnull value" | |
102 | + ^ "explicit %EnvironmentReference construction", | |
103 | + / DLI ^ "allocator" | |
104 | + ) | |
105 | + ), | |
106 | + / %NPLA $= | |
107 | + ( | |
108 | + + "function %LiftSubtermsToReturn with parameter of \ | |
109 | + 'TermNode::Container&'"; | |
110 | + / DLDI "simplified %LiftSubtermsToReturn#2" | |
111 | + ), | |
112 | + / %NPLA1 $= | |
113 | + ( | |
114 | + / @ "constructors %REPLContext" $= | |
115 | + ( | |
116 | + + DLDI "assertion" @ "default %Preprocess", | |
117 | + / DLI "improved nested calls efficiency" | |
118 | + ^ $dep_from ("%NPL_Impl_NPLA1_Enable_ThunkedThreshold" | |
119 | + @ %NPLA1Internals) | |
120 | + ), | |
121 | + / DLDI "simplified function %DefaultEvaluateLeaf" | |
122 | + ^ "%ReduceReturnUnspecified", | |
123 | + / DLDI "simplified function %ReduceReturnUnspecified" | |
124 | + !^ "%TermNode::SetValue", | |
125 | + // To be consistent with other uses. This is also a bit \ | |
126 | + tighter in generated code. | |
127 | + ( | |
128 | + + "enumerator %Pair" @ "enum class %ValueToken"; | |
129 | + + "%ValueToken::Pair support" @ "%to_string" | |
130 | + ) | |
131 | + ), | |
132 | + / @ "namespace %Forms" @ %NPLA1Forms $= | |
133 | + ( | |
134 | + / @ "function %Apply" $= | |
135 | + ( | |
136 | + + DLDI "internal assertion", | |
137 | + * $re_ex(b913) "move-only object not allowed in terms handled \ | |
138 | + by functions as native implemention of applicatives" | |
139 | + @ ("function %Apply" $since b859) | |
140 | + $= (/ $re_ex(b914) "avoided unexpected copy by list \ | |
141 | + initialization via %std::initializer_list instance" | |
142 | + @ "%TermNode construction") | |
143 | + ), | |
144 | + / DLDI "accessed rest list value by container" @ "functions \ | |
145 | + %(LetAsterisk, LetAsteriskRef, RestFwd, RestVal, SetRest, \ | |
146 | + SetRestRef)" $dep_from ("%LiftSubtermsToReturn" @ %NPLA), | |
147 | + - $revert(b943) DLI "redundant %ClearCombiningTags call" | |
148 | + @ "function %Call1CC", | |
149 | + * "missing preserving tags" @ "modified lists" @ "functions \ | |
150 | + %(SetRest, SetRestRef)" $orig (@ %NPLA1 $since b857), | |
151 | + * $comp DLI "missing clearing the container before the calls \ | |
152 | + of the applicative" @ "functions %(AccL, AccR)" $since b942 | |
153 | + $dep_from %YBase.YStadardEx.Container, | |
154 | + // This would not be exposed when the 1st subterm of the \ | |
155 | + combining term is regular. However, it is unreliable. | |
156 | + / DLDI "all %YSLib::in_place_type" -> "%in_place_type", | |
157 | + // The using declaration is already in NPLA.h. | |
158 | + / DLI "setting reference result" @ "%(ListExtractFirst, \ | |
159 | + LetAsterisk, LetAsteriskRef)" ^ "allocator" | |
160 | + ), | |
161 | + / %Dependency $= | |
162 | + ( | |
163 | + * $comp "unexpected copy of initializers on calls" | |
164 | + @ "native implementation" @ "applicative %apply" $since b859 | |
165 | + $dep_from ("%Apply" @ %NPLA1Forms) | |
166 | + * $comp "missing preserving reference property" @ "modified lists" | |
167 | + @ "applicatives ('set-rest!', 'set-rest%!')" | |
168 | + $dep_from ("functions %(SetRest, SetRestRef)" @ %NPLA1Forms) | |
169 | + $since b857 | |
170 | + // The applicatives were introduced in b834, but the \ | |
171 | + %TermTags::Temporary was used since b857. | |
172 | + ) | |
173 | + ) | |
174 | +), | |
175 | + | |
176 | +b943 | |
177 | +( | |
35 | 178 | / %Tools $= |
36 | 179 | ( |
37 | 180 | / %Scripts $= |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Definitions.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 方法和公共域定义与说明。 |
14 | -\version r14440 | |
14 | +\version r14455 | |
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-04-22 19:28 +0800 | |
20 | + 2022-04-30 02:36 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -524,6 +524,11 @@ | ||
524 | 524 | |
525 | 525 | $dir NPL |
526 | 526 | { |
527 | +$unit SContext | |
528 | +{ | |
529 | +NPL_Impl_SContext_Enable_ThunkedActions | |
530 | +#NPL_Impl_SContext_Enable_ThunkedThreshold | |
531 | +} | |
527 | 532 | $unit NPLA |
528 | 533 | { |
529 | 534 | #NPL_NPLA_CheckEnvironmentReferenceCount |
@@ -535,19 +540,24 @@ | ||
535 | 540 | { |
536 | 541 | NPL_NPLA_EnsureInPlaceNativeNumbers |
537 | 542 | #NPL_Impl_NPLAMath_UseQuadMath |
538 | -#NPL_Impl_NPLAMath_Has_UInt128 | |
539 | -} | |
540 | -$unit NPLA1Forms | |
541 | -{ | |
542 | -NPL_NPLA1Forms_CheckContinuationFrames | |
543 | +#NPL_Impl_NPLAMath_has_uint128 | |
543 | 544 | } |
544 | 545 | $internal $unit NPLA1Internals |
545 | 546 | { |
546 | 547 | NPL_Impl_NPLA1_Enable_InlineDirect |
547 | 548 | NPL_Impl_NPLA1_Enable_TCO |
548 | 549 | NPL_Impl_NPLA1_Enable_Thunked |
550 | +#NPL_Impl_NPLA1_Enable_ThunkedThreshold | |
549 | 551 | NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass |
550 | 552 | } |
553 | +$unit NPLA1 | |
554 | +{ | |
555 | +NPL_Impl_NPLA1_AssertParameterMatch | |
556 | +} | |
557 | +$unit NPLA1Forms | |
558 | +{ | |
559 | +NPL_NPLA1Forms_CheckContinuationFrames | |
560 | +} | |
551 | 561 | $unit Dependency |
552 | 562 | { |
553 | 563 | NPL_Impl_NPLA1_Native_Forms |