The YSLib project - main repository
Revision | a0edf9d1c9a2ea1c7d864087c57556f7cf0e7ff2 (tree) |
---|---|
Zeit | 2021-11-19 07:25:50 |
Autor | FrankHB <frankhb1989@gmai...> |
Commiter | FrankHB |
更新主分支版本: build 931 rev 10 。
@@ -19,14 +19,14 @@ | ||
19 | 19 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'" Label="Configuration"> |
20 | 20 | <ConfigurationType>Application</ConfigurationType> |
21 | 21 | <UseDebugLibraries>true</UseDebugLibraries> |
22 | - <PlatformToolset>v142</PlatformToolset> | |
22 | + <PlatformToolset>v143</PlatformToolset> | |
23 | 23 | </PropertyGroup> |
24 | 24 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration"> |
25 | 25 | <ConfigurationType>Application</ConfigurationType> |
26 | 26 | <UseDebugLibraries>false</UseDebugLibraries> |
27 | 27 | <WholeProgramOptimization>true</WholeProgramOptimization> |
28 | 28 | <CharacterSet>NotSet</CharacterSet> |
29 | - <PlatformToolset>v142</PlatformToolset> | |
29 | + <PlatformToolset>v143</PlatformToolset> | |
30 | 30 | </PropertyGroup> |
31 | 31 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
32 | 32 | <ImportGroup Label="ExtensionSettings"> |
@@ -20,14 +20,14 @@ | ||
20 | 20 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'" Label="Configuration"> |
21 | 21 | <ConfigurationType>Application</ConfigurationType> |
22 | 22 | <UseDebugLibraries>true</UseDebugLibraries> |
23 | - <PlatformToolset>v142</PlatformToolset> | |
23 | + <PlatformToolset>v143</PlatformToolset> | |
24 | 24 | </PropertyGroup> |
25 | 25 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration"> |
26 | 26 | <ConfigurationType>Application</ConfigurationType> |
27 | 27 | <UseDebugLibraries>false</UseDebugLibraries> |
28 | 28 | <WholeProgramOptimization>true</WholeProgramOptimization> |
29 | 29 | <CharacterSet>Unicode</CharacterSet> |
30 | - <PlatformToolset>v142</PlatformToolset> | |
30 | + <PlatformToolset>v143</PlatformToolset> | |
31 | 31 | </PropertyGroup> |
32 | 32 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
33 | 33 | <ImportGroup Label="ExtensionSettings"> |
@@ -23,13 +23,13 @@ | ||
23 | 23 | <ConfigurationType>Application</ConfigurationType> |
24 | 24 | <UseDebugLibraries>true</UseDebugLibraries> |
25 | 25 | <OutDir>$(SolutionDir)build\Win32\$(ProjectName)\$(Configuration)\</OutDir> |
26 | - <PlatformToolset>v142</PlatformToolset> | |
26 | + <PlatformToolset>v143</PlatformToolset> | |
27 | 27 | </PropertyGroup> |
28 | 28 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration"> |
29 | 29 | <ConfigurationType>Application</ConfigurationType> |
30 | 30 | <UseDebugLibraries>false</UseDebugLibraries> |
31 | 31 | <OutDir>$(SolutionDir)build\Win32\$(ProjectName)\$(Configuration)\</OutDir> |
32 | - <PlatformToolset>v142</PlatformToolset> | |
32 | + <PlatformToolset>v143</PlatformToolset> | |
33 | 33 | <WholeProgramOptimization>true</WholeProgramOptimization> |
34 | 34 | </PropertyGroup> |
35 | 35 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
@@ -21,12 +21,12 @@ | ||
21 | 21 | </PropertyGroup> |
22 | 22 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
23 | 23 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|ARM'" Label="Configuration"> |
24 | - <PlatformToolset>v142</PlatformToolset> | |
24 | + <PlatformToolset>v143</PlatformToolset> | |
25 | 25 | <ConfigurationType>Makefile</ConfigurationType> |
26 | 26 | <UseDebugLibraries>true</UseDebugLibraries> |
27 | 27 | </PropertyGroup> |
28 | 28 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|ARM'" Label="Configuration"> |
29 | - <PlatformToolset>v142</PlatformToolset> | |
29 | + <PlatformToolset>v143</PlatformToolset> | |
30 | 30 | <ConfigurationType>Makefile</ConfigurationType> |
31 | 31 | <UseDebugLibraries>false</UseDebugLibraries> |
32 | 32 | </PropertyGroup> |
@@ -21,12 +21,12 @@ | ||
21 | 21 | </PropertyGroup> |
22 | 22 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
23 | 23 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|ARM'" Label="Configuration"> |
24 | - <PlatformToolset>v142</PlatformToolset> | |
24 | + <PlatformToolset>v143</PlatformToolset> | |
25 | 25 | <ConfigurationType>Makefile</ConfigurationType> |
26 | 26 | <UseDebugLibraries>true</UseDebugLibraries> |
27 | 27 | </PropertyGroup> |
28 | 28 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|ARM'" Label="Configuration"> |
29 | - <PlatformToolset>v142</PlatformToolset> | |
29 | + <PlatformToolset>v143</PlatformToolset> | |
30 | 30 | <ConfigurationType>Makefile</ConfigurationType> |
31 | 31 | <UseDebugLibraries>false</UseDebugLibraries> |
32 | 32 | </PropertyGroup> |
@@ -125,13 +125,13 @@ | ||
125 | 125 | <ConfigurationType>StaticLibrary</ConfigurationType> |
126 | 126 | <UseDebugLibraries>true</UseDebugLibraries> |
127 | 127 | <OutDir>$(SolutionDir)build\Win32\$(ProjectName)\$(Configuration)\</OutDir> |
128 | - <PlatformToolset>v142</PlatformToolset> | |
128 | + <PlatformToolset>v143</PlatformToolset> | |
129 | 129 | </PropertyGroup> |
130 | 130 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration"> |
131 | 131 | <ConfigurationType>StaticLibrary</ConfigurationType> |
132 | 132 | <UseDebugLibraries>false</UseDebugLibraries> |
133 | 133 | <OutDir>$(SolutionDir)build\Win32\$(ProjectName)\$(Configuration)\</OutDir> |
134 | - <PlatformToolset>v142</PlatformToolset> | |
134 | + <PlatformToolset>v143</PlatformToolset> | |
135 | 135 | </PropertyGroup> |
136 | 136 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
137 | 137 | <ImportGroup Label="ExtensionSettings"> |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2010-2020 FrankHB. | |
2 | + © 2010-2021 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 functor.hpp |
12 | 12 | \ingroup YStandardEx |
13 | 13 | \brief 通用仿函数。 |
14 | -\version r987 | |
14 | +\version r996 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 588 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-03-29 00:35:44 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-07-17 01:19 +0800 | |
20 | + 2021-11-11 20:31 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -78,7 +78,6 @@ | ||
78 | 78 | |
79 | 79 | /*! \defgroup functors General Functors |
80 | 80 | \brief 仿函数。 |
81 | -\warning 可能非虚析构。 | |
82 | 81 | \note 函数对象包含函数指针和仿函数。 |
83 | 82 | \warning 其中的类类型一般可被继承但非虚析构。 |
84 | 83 | \since build 243 |
@@ -385,11 +384,18 @@ | ||
385 | 384 | \ |
386 | 385 | YB_Impl_Functor_Ops_Spec_Ptr(_n) |
387 | 386 | |
387 | +#if YB_IMPL_GNUCPP || YB_IMPL_CLANGPP | |
388 | + YB_Diag_Push | |
389 | + YB_Diag_Ignore(float-equal) | |
390 | +#endif | |
388 | 391 | //! \brief 等于关系仿函数。 |
389 | 392 | YB_Impl_Functor_bool(equal_to, ==) |
390 | 393 | |
391 | 394 | //! \brief 不等于关系仿函数。 |
392 | 395 | YB_Impl_Functor_bool(not_equal_to, !=) |
396 | +#if YB_IMPL_GNUCPP || YB_IMPL_CLANGPP | |
397 | + YB_Diag_Pop | |
398 | +#endif | |
393 | 399 | |
394 | 400 | //! \brief 大于关系仿函数。 |
395 | 401 | YB_Impl_Functor_bool_Ordered(greater, >) |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2011-2019 FrankHB. | |
2 | + © 2011-2019, 2021 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 type_traits.hpp |
12 | 12 | \ingroup YStandardEx |
13 | 13 | \brief ISO C++ 类型特征扩展。 |
14 | -\version r2030 | |
14 | +\version r2038 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 201 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-11-04 09:34:17 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2019-09-13 13:43 +0800 | |
20 | + 2021-11-11 20:32 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -91,11 +91,18 @@ | ||
91 | 91 | template<typename _type, typename _type2> |
92 | 92 | using subscript_t = decltype(std::declval<_type>()[std::declval<_type2>()]); |
93 | 93 | |
94 | +#if YB_IMPL_GNUCPP || YB_IMPL_CLANGPP | |
95 | + YB_Diag_Push | |
96 | + YB_Diag_Ignore(float-equal) | |
97 | +#endif | |
94 | 98 | template<typename _type, typename _type2 = _type> |
95 | 99 | using equal_t = decltype(std::declval<_type>() == std::declval<_type2>()); |
96 | 100 | |
97 | 101 | template<typename _type, typename _type2 = _type> |
98 | 102 | using not_equal_t = decltype(std::declval<_type>() != std::declval<_type2>()); |
103 | +#if YB_IMPL_GNUCPP || YB_IMPL_CLANGPP | |
104 | + YB_Diag_Pop | |
105 | +#endif | |
99 | 106 | //@} |
100 | 107 | |
101 | 108 |
@@ -31,12 +31,12 @@ | ||
31 | 31 | </PropertyGroup> |
32 | 32 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
33 | 33 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|ARM'" Label="Configuration"> |
34 | - <PlatformToolset>v142</PlatformToolset> | |
34 | + <PlatformToolset>v143</PlatformToolset> | |
35 | 35 | <ConfigurationType>Makefile</ConfigurationType> |
36 | 36 | <UseDebugLibraries>true</UseDebugLibraries> |
37 | 37 | </PropertyGroup> |
38 | 38 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|ARM'" Label="Configuration"> |
39 | - <PlatformToolset>v142</PlatformToolset> | |
39 | + <PlatformToolset>v143</PlatformToolset> | |
40 | 40 | <ConfigurationType>Makefile</ConfigurationType> |
41 | 41 | <UseDebugLibraries>false</UseDebugLibraries> |
42 | 42 | </PropertyGroup> |
@@ -24,12 +24,12 @@ | ||
24 | 24 | </PropertyGroup> |
25 | 25 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
26 | 26 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|ARM'" Label="Configuration"> |
27 | - <PlatformToolset>v142</PlatformToolset> | |
27 | + <PlatformToolset>v143</PlatformToolset> | |
28 | 28 | <ConfigurationType>Makefile</ConfigurationType> |
29 | 29 | <UseDebugLibraries>true</UseDebugLibraries> |
30 | 30 | </PropertyGroup> |
31 | 31 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|ARM'" Label="Configuration"> |
32 | - <PlatformToolset>v142</PlatformToolset> | |
32 | + <PlatformToolset>v143</PlatformToolset> | |
33 | 33 | <ConfigurationType>Makefile</ConfigurationType> |
34 | 34 | <UseDebugLibraries>false</UseDebugLibraries> |
35 | 35 | </PropertyGroup> |
@@ -19,13 +19,13 @@ | ||
19 | 19 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'" Label="Configuration"> |
20 | 20 | <ConfigurationType>Makefile</ConfigurationType> |
21 | 21 | <UseDebugLibraries>true</UseDebugLibraries> |
22 | - <PlatformToolset>v142</PlatformToolset> | |
22 | + <PlatformToolset>v143</PlatformToolset> | |
23 | 23 | <CharacterSet>MultiByte</CharacterSet> |
24 | 24 | </PropertyGroup> |
25 | 25 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration"> |
26 | 26 | <ConfigurationType>Makefile</ConfigurationType> |
27 | 27 | <UseDebugLibraries>false</UseDebugLibraries> |
28 | - <PlatformToolset>v142</PlatformToolset> | |
28 | + <PlatformToolset>v143</PlatformToolset> | |
29 | 29 | <WholeProgramOptimization>true</WholeProgramOptimization> |
30 | 30 | <CharacterSet>MultiByte</CharacterSet> |
31 | 31 | </PropertyGroup> |
@@ -483,13 +483,13 @@ | ||
483 | 483 | <ConfigurationType>StaticLibrary</ConfigurationType> |
484 | 484 | <UseDebugLibraries>true</UseDebugLibraries> |
485 | 485 | <OutDir>$(SolutionDir)build\Win32\$(ProjectName)\$(Configuration)\</OutDir> |
486 | - <PlatformToolset>v142</PlatformToolset> | |
486 | + <PlatformToolset>v143</PlatformToolset> | |
487 | 487 | </PropertyGroup> |
488 | 488 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration"> |
489 | 489 | <ConfigurationType>StaticLibrary</ConfigurationType> |
490 | 490 | <UseDebugLibraries>false</UseDebugLibraries> |
491 | 491 | <OutDir>$(SolutionDir)build\Win32\$(ProjectName)\$(Configuration)\</OutDir> |
492 | - <PlatformToolset>v142</PlatformToolset> | |
492 | + <PlatformToolset>v143</PlatformToolset> | |
493 | 493 | </PropertyGroup> |
494 | 494 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
495 | 495 | <ImportGroup Label="ExtensionSettings"> |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r8648 | |
14 | +\version r8656 | |
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 | - 2021-10-21 18:09 +0800 | |
20 | + 2021-11-11 20:32 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -721,7 +721,7 @@ | ||
721 | 721 | //! \sa LexemeCategory |
722 | 722 | //@{ |
723 | 723 | /*! |
724 | -\pre 断言:字符串参数的数据指针非空。 | |
724 | +\pre 间接断言:字符串参数的数据指针非空。 | |
725 | 725 | \return 判断的非扩展字面量分类。 |
726 | 726 | */ |
727 | 727 | //@{ |
@@ -742,7 +742,7 @@ | ||
742 | 742 | |
743 | 743 | /*! |
744 | 744 | \brief 判断不是非扩展字面量的词素是否为 NPLA 扩展字面量。 |
745 | -\pre 断言:字符串参数的数据指针非空且字符串非空。 | |
745 | +\pre 断言:字符串参数的数据指针非空。 | |
746 | 746 | \pre 词素不是代码字面量或数据字面量。 |
747 | 747 | \since build 771 |
748 | 748 | */ |
@@ -3492,7 +3492,12 @@ | ||
3492 | 3492 | namespace ystdex |
3493 | 3493 | { |
3494 | 3494 | |
3495 | -//! \relates NPL::A1::Continuation | |
3495 | +//! \relates NPL::EnvironmentReference | |
3496 | +template<> | |
3497 | +struct is_bitwise_swappable<NPL::EnvironmentReference> : true_ | |
3498 | +{}; | |
3499 | + | |
3500 | +//! \relates NPL::EnvironmentSwitcher | |
3496 | 3501 | template<> |
3497 | 3502 | struct is_bitwise_swappable<NPL::EnvironmentSwitcher> : true_ |
3498 | 3503 | {}; |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Forms.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 语法形式。 |
14 | -\version r8559 | |
14 | +\version r8563 | |
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 | - 2021-10-21 18:09 +0800 | |
20 | + 2021-11-11 20:32 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -49,6 +49,8 @@ | ||
49 | 49 | |
50 | 50 | /*! |
51 | 51 | \brief 判断字符串值是否可构成符号。 |
52 | +\note 不依赖具体字符集。 | |
53 | +\note 不排除假阴性结果。 | |
52 | 54 | \since build 779 |
53 | 55 | */ |
54 | 56 | YB_ATTR_nodiscard YF_API YB_PURE bool |
@@ -72,7 +74,7 @@ | ||
72 | 74 | \since build 786 |
73 | 75 | |
74 | 76 | 参考调用文法: |
75 | -<pre>symbol-string? \<object></pre> | |
77 | +<pre>symbol->string \<object></pre> | |
76 | 78 | */ |
77 | 79 | YB_ATTR_nodiscard YF_API YB_STATELESS const string& |
78 | 80 | SymbolToString(const TokenValue&) ynothrow; |
@@ -1319,7 +1321,6 @@ | ||
1319 | 1321 | /*! |
1320 | 1322 | \throw InvalidSyntax 标识符不是符号。 |
1321 | 1323 | \throw TypeError 当前环境被冻结。 |
1322 | -\sa IsNPLASymbol | |
1323 | 1324 | \sa RemoveIdentifier |
1324 | 1325 | \since build 867 |
1325 | 1326 | */ |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r3658 | |
14 | +\version r3669 | |
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 | - 2021-10-30 09:10 +0800 | |
20 | + 2021-11-14 20:51 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -391,25 +391,26 @@ | ||
391 | 391 | // XXX: Use other type without overhead of check on call of %operator()? |
392 | 392 | using Redirector = function<observer_ptr<const ValueObject>()>; |
393 | 393 | |
394 | -//! \since build 884 | |
394 | +//! \since build 931 | |
395 | 395 | observer_ptr<const ValueObject> |
396 | -RedirectEnvironmentList(EnvironmentList::const_iterator first, | |
397 | - EnvironmentList::const_iterator last, string_view id, Redirector& cont) | |
396 | +RedirectEnvironmentList(Environment::allocator_type a, Redirector& cont, | |
397 | + EnvironmentList::const_iterator first, EnvironmentList::const_iterator last) | |
398 | 398 | { |
399 | 399 | if(first != last) |
400 | 400 | { |
401 | - cont = std::bind( | |
401 | + cont = ystdex::make_obj_using_allocator<Redirector>(a, | |
402 | + any_ops::trivial_swap, std::bind( | |
402 | 403 | [=, &cont](EnvironmentList::const_iterator i, Redirector& c){ |
403 | 404 | cont = std::move(c); |
404 | - return RedirectEnvironmentList(i, last, id, cont); | |
405 | - }, std::next(first), std::move(cont)); | |
405 | + return RedirectEnvironmentList(a, cont, i, last); | |
406 | + }, std::next(first), std::move(cont))); | |
406 | 407 | return NPL::make_observer(&*first); |
407 | 408 | } |
408 | 409 | return {}; |
409 | 410 | } |
410 | 411 | |
411 | 412 | //! \since build 857 |
412 | -YB_ATTR_nodiscard YB_PURE TermTags | |
413 | +YB_ATTR_nodiscard YB_STATELESS TermTags | |
413 | 414 | MergeTermTags(TermTags x, TermTags y) ynothrow |
414 | 415 | { |
415 | 416 | return (((x & ~TermTags::Temporary) | y) & ~TermTags::Unique) |
@@ -1259,8 +1260,9 @@ | ||
1259 | 1260 | { |
1260 | 1261 | auto& envs(parent.GetObject<EnvironmentList>()); |
1261 | 1262 | |
1262 | - p_next = RedirectEnvironmentList(envs.cbegin(), | |
1263 | - envs.cend(), id, cont); | |
1263 | + p_next = RedirectEnvironmentList( | |
1264 | + p_env->Bindings.get_allocator(), cont, | |
1265 | + envs.cbegin(), envs.cend()); | |
1264 | 1266 | } |
1265 | 1267 | while(!p_next && bool(cont)) |
1266 | 1268 | p_next = ystdex::exchange(cont, Redirector())(); |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLAMath.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 数学功能。 |
14 | -\version r24396 | |
14 | +\version r24519 | |
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 | - 2021-11-11 12:02 +0800 | |
20 | + 2021-11-19 05:47 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -1017,31 +1017,128 @@ | ||
1017 | 1017 | return {}; |
1018 | 1018 | } |
1019 | 1019 | |
1020 | +//! \since build 931 | |
1021 | +//@{ | |
1022 | +// XXX: Keeping the type of numeric literals without sign 'int' is also more | |
1023 | +// compatible to old operations. | |
1024 | +using ReadIntType = int; | |
1025 | +using ReadExtIntType = long long; | |
1026 | +using ReadCommonType = ystdex::common_type_t<ReadExtIntType, std::uint64_t>; | |
1027 | + | |
1028 | +YB_ATTR_nodiscard YB_STATELESS yconstfn PDefH(bool, IsDecimalPoint, char c) | |
1029 | + ynothrow | |
1030 | + ImplRet(c == '.') | |
1031 | + | |
1032 | +YB_ATTR_nodiscard YB_STATELESS yconstfn PDefH(bool, IsExponent, char c) ynothrow | |
1033 | + ImplRet(c == 'e' || c == 'E') | |
1034 | + | |
1035 | +YB_ATTR_nodiscard YB_PURE inline double | |
1036 | +ScaleDecimalFlonum(char sign, double ans, ptrdiff_t scale) | |
1037 | +{ | |
1038 | + return (sign != '-' ? double(ans) : -double(ans)) * std::pow(10, scale); | |
1039 | +} | |
1040 | + | |
1041 | +YB_ATTR_nodiscard YB_PURE ptrdiff_t | |
1042 | +ReadDecimalExponent(string_view::const_iterator first, string_view id) | |
1043 | +{ | |
1044 | + bool minus = {}; | |
1045 | + | |
1046 | + switch(*first) | |
1047 | + { | |
1048 | + case '-': | |
1049 | + minus = true; | |
1050 | + YB_ATTR_fallthrough; | |
1051 | + case '+': | |
1052 | + ++first; | |
1053 | + YB_ATTR_fallthrough; | |
1054 | + default: | |
1055 | + break; | |
1056 | + } | |
1057 | + if(first != id.end()) | |
1058 | + { | |
1059 | + ptrdiff_t res(0); | |
1060 | + | |
1061 | + ystdex::retry_on_cond(ystdex::id<>(), [&]() -> bool{ | |
1062 | + if(ystdex::isdigit(*first)) | |
1063 | + { | |
1064 | + if(DecimalAccumulate(res, *first)) | |
1065 | + return ++first != id.end(); | |
1066 | + // XXX: Assume the values (with or without the minus sign) are | |
1067 | + // out of the range of the supported exponents. | |
1068 | + res = std::numeric_limits<ptrdiff_t>::max(); | |
1069 | + return {}; | |
1070 | + } | |
1071 | + throw InvalidSyntax(ystdex::sfmt("Invalid character '%c' found in" | |
1072 | + " the exponent of '%s'.", *first, id.data())); | |
1073 | + }); | |
1074 | + return minus ? -res : res; | |
1075 | + } | |
1076 | + throw | |
1077 | + InvalidSyntax(ystdex::sfmt("Empty exponent found in '%s'.", id.data())); | |
1078 | +} | |
1079 | + | |
1080 | +// XXX: This assumes %ReadCommonType can save more digits than %double. | |
1020 | 1081 | void |
1021 | 1082 | ReadDecimalInexact(ValueObject& vo, string_view::const_iterator first, |
1022 | - string_view id, double ans, size_t shift = 0) | |
1083 | + string_view id, ReadCommonType ans, string_view::const_iterator dpos) | |
1023 | 1084 | { |
1024 | 1085 | YAssert(!id.empty(), "Invalid lexeme found."); |
1025 | - YAssert(shift <= id.size(), "Invalid pointer position found."); | |
1086 | + | |
1087 | + // NOTE: This is the beginning position known to ignore the subsequent | |
1088 | + // digits after. Digits after this position are checked but then ignored. | |
1089 | + auto cut(id.end()); | |
1090 | + | |
1026 | 1091 | ystdex::retry_on_cond(ystdex::id<>(), [&]() -> bool{ |
1092 | + const auto ret([&](ptrdiff_t scale) YB_FLATTEN{ | |
1093 | + vo = ScaleDecimalFlonum(id[0], ans, scale); | |
1094 | + return false; | |
1095 | + }); | |
1096 | + | |
1027 | 1097 | if(ystdex::isdigit(*first)) |
1028 | - ans = DecimalCarryAddDigit(ans, *first); | |
1029 | - else if(*first == '.') | |
1030 | 1098 | { |
1031 | - if(shift == 0) | |
1032 | - shift = size_t(id.end() - first); | |
1099 | + if(cut == id.end()) | |
1100 | + { | |
1101 | + // NOTE: The intermediate result cannot save more digits, do | |
1102 | + // rounding. | |
1103 | + if(!DecimalAccumulate(ans, *first)) | |
1104 | + { | |
1105 | + ans += *first >= '5' ? 1 : 0; | |
1106 | + cut = first; | |
1107 | + } | |
1108 | + } | |
1109 | + } | |
1110 | + else if(IsDecimalPoint(*first)) | |
1111 | + { | |
1112 | + if(dpos == id.end()) | |
1113 | + // NOTE: No exponent part has been found. | |
1114 | + dpos = first; | |
1033 | 1115 | else |
1034 | 1116 | throw InvalidSyntax(ystdex::sfmt( |
1035 | 1117 | "More than one decimal points found in '%s'.", id.data())); |
1036 | 1118 | } |
1119 | + else if(IsExponent(*first)) | |
1120 | + { | |
1121 | + const auto el(id.end() - first); | |
1122 | + | |
1123 | + // NOTE: If a decimal point in the representation of the cut digits | |
1124 | + // is found, it is also shifted as one digit. | |
1125 | + return ret((cut == id.end() ? 0 : id.end() - cut - el | |
1126 | + - (dpos != id.end() && dpos > cut ? 1 : 0)) | |
1127 | + - (dpos == id.end() ? 0 : id.end() - dpos - el - 1) | |
1128 | + + ReadDecimalExponent(first + 1, id)); | |
1129 | + } | |
1037 | 1130 | else |
1038 | 1131 | ThrowForInvalidLiteralSuffix(&*first, id.data()); |
1039 | 1132 | if(++first != id.end()) |
1040 | 1133 | return true; |
1041 | - vo = (id[0] != '-' ? ans : -ans) * std::pow(10, shift); | |
1042 | - return {}; | |
1134 | + // NOTE: Similar to above without the exponent, so %el is always equals | |
1135 | + // to 0. | |
1136 | + return ret((cut == id.end() ? 0 : id.end() - cut | |
1137 | + - (dpos != id.end() && dpos > cut ? 1 : 0)) | |
1138 | + - (dpos == id.end() ? 0 : id.end() - dpos - 1)); | |
1043 | 1139 | }); |
1044 | 1140 | } |
1141 | +//@} | |
1045 | 1142 | |
1046 | 1143 | template<typename _tInt> |
1047 | 1144 | YB_ATTR_nodiscard bool |
@@ -1061,10 +1158,15 @@ | ||
1061 | 1158 | if(ystdex::isdigit(*first)) |
1062 | 1159 | return DecimalAccumulate(ans, *first) ? ReductionStatus::Retrying |
1063 | 1160 | : ReductionStatus::Partial; |
1064 | - if(*first == '.') | |
1161 | + if(IsDecimalPoint(*first)) | |
1065 | 1162 | { |
1066 | - ReadDecimalInexact(vo, first + 1, id, ans, | |
1067 | - size_t(id.end() - first)); | |
1163 | + ReadDecimalInexact(vo, first + 1, id, ReadCommonType(ans), first); | |
1164 | + return ReductionStatus::Clean; | |
1165 | + } | |
1166 | + if(IsExponent(*first)) | |
1167 | + { | |
1168 | + vo = ScaleDecimalFlonum(id[0], double(ans), | |
1169 | + ReadDecimalExponent(first + 1, id)); | |
1068 | 1170 | return ReductionStatus::Clean; |
1069 | 1171 | } |
1070 | 1172 | ThrowForInvalidLiteralSuffix(&*first, id.data()); |
@@ -1304,37 +1406,40 @@ | ||
1304 | 1406 | // unsigned types, operations like minus would result in different types |
1305 | 1407 | // depending on types, and the type of negative values computed from |
1306 | 1408 | // unsinged values by these operations would be promoted too quick. |
1307 | - // XXX: Keeping the type of numeric literals without sign 'int' is also more | |
1308 | - // compatible to old operations. | |
1309 | - using int_type = int; | |
1310 | - using ext_int_type = long long; | |
1311 | 1409 | YAssert(!id.empty(), "Invalid lexeme found."); |
1312 | 1410 | YAssert(first >= id.begin() && size_t(first - id.begin()) < id.size(), |
1313 | 1411 | "Invalid first iterator found."); |
1314 | 1412 | |
1315 | 1413 | // NOTE: Skip leading zeros. |
1316 | 1414 | while(YB_UNLIKELY(*first == '0')) |
1317 | - if(YB_UNLIKELY(++first == id.end())) | |
1415 | + if(first + 1 != id.end()) | |
1416 | + ++first; | |
1417 | + else | |
1318 | 1418 | break; |
1319 | - yconstexpr_if(std::numeric_limits<int_type>::max() | |
1320 | - != std::numeric_limits<ext_int_type>::max()) | |
1419 | + yconstexpr_if(std::numeric_limits<ReadIntType>::max() | |
1420 | + != std::numeric_limits<ReadExtIntType>::max()) | |
1321 | 1421 | { |
1322 | - int_type ans(0); | |
1422 | + ReadIntType ans(0); | |
1323 | 1423 | |
1324 | 1424 | if(YB_UNLIKELY(ReadDecimalExact(vo, id, first, ans))) |
1325 | 1425 | { |
1326 | - ext_int_type lans(ans); | |
1426 | + ReadExtIntType lans(ans); | |
1327 | 1427 | |
1328 | 1428 | if(YB_UNLIKELY(ReadDecimalExact(vo, id, first, lans))) |
1329 | - ReadDecimalInexact(vo, first, id, lans); | |
1429 | + // NOTE: The cast is safe even when %ReadCommonType is unsigned | |
1430 | + // because %ReadDecimalExact may only add the minus sign on a | |
1431 | + // complete parse. | |
1432 | + ReadDecimalInexact(vo, first, id, ReadCommonType(lans), | |
1433 | + id.end()); | |
1330 | 1434 | } |
1331 | 1435 | } |
1332 | 1436 | else |
1333 | 1437 | { |
1334 | - int_type ans(0); | |
1438 | + ReadIntType ans(0); | |
1335 | 1439 | |
1336 | 1440 | if(YB_UNLIKELY(ReadDecimalExact(vo, id, first, ans))) |
1337 | - ReadDecimalInexact(vo, first, id, ans); | |
1441 | + // NOTE: Ditto. | |
1442 | + ReadDecimalInexact(vo, first, id, ReadCommonType(ans), id.end()); | |
1338 | 1443 | } |
1339 | 1444 | } |
1340 | 1445 |
@@ -20,13 +20,13 @@ | ||
20 | 20 | <ConfigurationType>Makefile</ConfigurationType> |
21 | 21 | <CharacterSet>MultiByte</CharacterSet> |
22 | 22 | <WholeProgramOptimization>true</WholeProgramOptimization> |
23 | - <PlatformToolset>v142</PlatformToolset> | |
23 | + <PlatformToolset>v143</PlatformToolset> | |
24 | 24 | </PropertyGroup> |
25 | 25 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|ARM'" Label="Configuration"> |
26 | 26 | <ConfigurationType>Makefile</ConfigurationType> |
27 | 27 | <CharacterSet>MultiByte</CharacterSet> |
28 | 28 | <WholeProgramOptimization>true</WholeProgramOptimization> |
29 | - <PlatformToolset>v142</PlatformToolset> | |
29 | + <PlatformToolset>v143</PlatformToolset> | |
30 | 30 | </PropertyGroup> |
31 | 31 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
32 | 32 | <ImportGroup Label="ExtensionSettings"> |
@@ -17,12 +17,6 @@ | ||
17 | 17 | </Filter> |
18 | 18 | </ItemGroup> |
19 | 19 | <ItemGroup> |
20 | - <None Include="data\logo.bmp"> | |
21 | - <Filter>data</Filter> | |
22 | - </None> | |
23 | - <None Include="data\logo_wifi.bmp"> | |
24 | - <Filter>data</Filter> | |
25 | - </None> | |
26 | 20 | <None Include="Makefile" /> |
27 | 21 | </ItemGroup> |
28 | 22 | <ItemGroup> |
@@ -20,13 +20,13 @@ | ||
20 | 20 | <ConfigurationType>Makefile</ConfigurationType> |
21 | 21 | <CharacterSet>MultiByte</CharacterSet> |
22 | 22 | <WholeProgramOptimization>true</WholeProgramOptimization> |
23 | - <PlatformToolset>v142</PlatformToolset> | |
23 | + <PlatformToolset>v143</PlatformToolset> | |
24 | 24 | </PropertyGroup> |
25 | 25 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|ARM'" Label="Configuration"> |
26 | 26 | <ConfigurationType>Makefile</ConfigurationType> |
27 | 27 | <CharacterSet>MultiByte</CharacterSet> |
28 | 28 | <WholeProgramOptimization>true</WholeProgramOptimization> |
29 | - <PlatformToolset>v142</PlatformToolset> | |
29 | + <PlatformToolset>v143</PlatformToolset> | |
30 | 30 | </PropertyGroup> |
31 | 31 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
32 | 32 | <ImportGroup Label="ExtensionSettings"> |
@@ -24,12 +24,12 @@ | ||
24 | 24 | </PropertyGroup> |
25 | 25 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
26 | 26 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|ARM'" Label="Configuration"> |
27 | - <PlatformToolset>v142</PlatformToolset> | |
27 | + <PlatformToolset>v143</PlatformToolset> | |
28 | 28 | <ConfigurationType>Makefile</ConfigurationType> |
29 | 29 | <UseDebugLibraries>true</UseDebugLibraries> |
30 | 30 | </PropertyGroup> |
31 | 31 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|ARM'" Label="Configuration"> |
32 | - <PlatformToolset>v142</PlatformToolset> | |
32 | + <PlatformToolset>v143</PlatformToolset> | |
33 | 33 | <ConfigurationType>Makefile</ConfigurationType> |
34 | 34 | <UseDebugLibraries>false</UseDebugLibraries> |
35 | 35 | </PropertyGroup> |
@@ -48,12 +48,12 @@ | ||
48 | 48 | </PropertyGroup> |
49 | 49 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
50 | 50 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|ARM'" Label="Configuration"> |
51 | - <PlatformToolset>v142</PlatformToolset> | |
51 | + <PlatformToolset>v143</PlatformToolset> | |
52 | 52 | <ConfigurationType>Makefile</ConfigurationType> |
53 | 53 | <UseDebugLibraries>true</UseDebugLibraries> |
54 | 54 | </PropertyGroup> |
55 | 55 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|ARM'" Label="Configuration"> |
56 | - <PlatformToolset>v142</PlatformToolset> | |
56 | + <PlatformToolset>v143</PlatformToolset> | |
57 | 57 | <ConfigurationType>Makefile</ConfigurationType> |
58 | 58 | <UseDebugLibraries>false</UseDebugLibraries> |
59 | 59 | </PropertyGroup> |
@@ -47,13 +47,13 @@ | ||
47 | 47 | <ConfigurationType>Application</ConfigurationType> |
48 | 48 | <UseDebugLibraries>true</UseDebugLibraries> |
49 | 49 | <OutDir>$(SolutionDir)build\Win32\$(ProjectName)\$(Configuration)\</OutDir> |
50 | - <PlatformToolset>v142</PlatformToolset> | |
50 | + <PlatformToolset>v143</PlatformToolset> | |
51 | 51 | </PropertyGroup> |
52 | 52 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration"> |
53 | 53 | <ConfigurationType>Application</ConfigurationType> |
54 | 54 | <UseDebugLibraries>false</UseDebugLibraries> |
55 | 55 | <OutDir>$(SolutionDir)build\Win32\$(ProjectName)\$(Configuration)\</OutDir> |
56 | - <PlatformToolset>v142</PlatformToolset> | |
56 | + <PlatformToolset>v143</PlatformToolset> | |
57 | 57 | <WholeProgramOptimization>true</WholeProgramOptimization> |
58 | 58 | </PropertyGroup> |
59 | 59 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2010-2016, 2019 FrankHB. | |
2 | + © 2010-2016, 2019, 2021 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 DSReader.cpp |
12 | 12 | \ingroup YReader |
13 | 13 | \brief 适用于 DS 的双屏阅读器。 |
14 | -\version r3291 | |
14 | +\version r3383 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since 早于 build 132 |
17 | 17 | \par 创建时间: |
18 | 18 | 2010-01-05 14:04:05 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2019-01-14 18:55 +0800 | |
20 | + 2021-11-12 18:20 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -25,10 +25,11 @@ | ||
25 | 25 | */ |
26 | 26 | |
27 | 27 | |
28 | -#include "DSReader.h" // for ystdex::max; | |
28 | +#include "DSReader.h" // for ptrdiff_t, ystdex::max; | |
29 | 29 | #include <algorithm> // for std::copy_n; |
30 | 30 | #include YFM_YSLib_UI_YWindow |
31 | 31 | #include YFM_YSLib_Service_TextLayout |
32 | +#include <limits> // for std::numeric_limits; | |
32 | 33 | |
33 | 34 | namespace YSLib |
34 | 35 | { |
@@ -167,11 +168,11 @@ | ||
167 | 168 | { |
168 | 169 | // XXX: Conversion to 'SPos' might be implementation-defined. |
169 | 170 | YAssert(SPos(area_up.GetHeight()) - area_up.Margin.Bottom - SPos(n) > 0, |
170 | - "No enough space of areas found."); | |
171 | + "No enough space of the up area for scrolling found."); | |
171 | 172 | |
172 | 173 | const SDst up_btm(SDst(ystdex::max<SPos>(area_up.Margin.Bottom, 0))); |
173 | 174 | |
174 | - if(YB_UNLIKELY(area_up.GetHeight() <= up_btm + n)) | |
175 | + if(area_up.GetHeight() > up_btm + n) | |
175 | 176 | { |
176 | 177 | auto src_off(SDst(ystdex::max<SPos>(area_dn.Margin.Top, 0))), |
177 | 178 | dst_off(SDst(area_up.GetHeight() - up_btm - n)); |
@@ -319,64 +320,73 @@ | ||
319 | 320 | bool |
320 | 321 | DualScreenReader::Execute(Command cmd) |
321 | 322 | { |
322 | - if(YB_UNLIKELY(!p_text || p_text->GetTextSize() == 0)) | |
323 | - return {}; | |
324 | - if(YB_UNLIKELY(~cmd & Scroll)) | |
325 | - return {}; | |
326 | - if(AdjustScrollOffset() != 0) | |
327 | - return {}; | |
328 | - if(cmd & Up) | |
323 | + if(p_text && p_text->GetTextSize() != 0 && bool(cmd & Scroll) | |
324 | + && AdjustScrollOffset() == 0) | |
329 | 325 | { |
330 | - if(YB_UNLIKELY(IsTextTop())) | |
331 | - return {}; | |
332 | - } | |
333 | - else if(YB_UNLIKELY(IsTextBottom())) | |
334 | - return {}; | |
335 | - YAssert(area_up.LineGap == area_dn.LineGap, "Distinct line gaps found."); | |
336 | - // TODO: Assert the fonts are same. | |
337 | - cmd &= ~Scroll; | |
338 | - if(cmd & Line) | |
339 | - { | |
340 | - const FontSize h(area_up.Font.GetHeight()), hx(h + GetLineGap()); | |
326 | + const bool up(cmd & Up); | |
341 | 327 | |
342 | - if(cmd & Up) | |
328 | + if((up && !IsTextTop()) || (!up && !IsTextBottom())) | |
343 | 329 | { |
344 | - MoveScrollArea(area_up, area_dn, hx, SDst(h)); | |
345 | - SetCurrentTextLineNOf(area_up, 0); | |
346 | - AdjustForPrevNewline(); | |
347 | - CarriageReturn(area_up); | |
348 | - PutLine(area_up, next_if_eq(i_top, '\n'), p_text->end(), '\n'); | |
349 | - if(overread_line_n > 0) | |
350 | - --overread_line_n; | |
330 | + YAssert(area_up.LineGap == area_dn.LineGap, | |
331 | + "Distinct line gaps found."); | |
332 | + // TODO: Assert the fonts are same. | |
333 | + // XXX: %Scroll is not used currently. | |
334 | + if(cmd & Line) | |
335 | + { | |
336 | + const size_t h(area_up.Font.GetHeight()), hx(h + GetLineGap()); | |
337 | + | |
338 | + if(hx >= h && h <= std::numeric_limits<ptrdiff_t>::max()) | |
339 | + { | |
340 | + if(up) | |
341 | + { | |
342 | + MoveScrollArea(area_up, area_dn, ptrdiff_t(hx), | |
343 | + SDst(h)); | |
344 | + SetCurrentTextLineNOf(area_up, 0); | |
345 | + AdjustForPrevNewline(); | |
346 | + CarriageReturn(area_up); | |
347 | + PutLine(area_up, next_if_eq(i_top, '\n'), p_text->end(), | |
348 | + '\n'); | |
349 | + if(overread_line_n > 0) | |
350 | + --overread_line_n; | |
351 | + else | |
352 | + AdjustPrevious(area_up, i_btm, *p_text); | |
353 | + } | |
354 | + else | |
355 | + { | |
356 | + MoveUpForLastLine(-ptrdiff_t(hx), h); | |
357 | + // NOTE: The buffer is not ensured with null character | |
358 | + // at end. | |
359 | + CarriageReturn(area_dn); | |
360 | + i_btm = PutLastLine(); | |
361 | + AdjustForFirstNewline(); | |
362 | + } | |
363 | + Invalidate(); | |
364 | + } | |
365 | + else | |
366 | + { | |
367 | + ShowError(u"字形大小溢出,渲染失败!"); | |
368 | + return {}; | |
369 | + } | |
370 | + } | |
351 | 371 | else |
352 | - AdjustPrevious(area_up, i_btm, *p_text); | |
353 | - } | |
354 | - else | |
355 | - { | |
356 | - MoveUpForLastLine(-hx, h); | |
357 | - // NOTE: The buffer is not ensured with null character at end. | |
358 | - CarriageReturn(area_dn); | |
359 | - i_btm = PutLastLine(); | |
360 | - AdjustForFirstNewline(); | |
372 | + { | |
373 | + auto ln(area_up.GetTextLineNEx() + area_dn.GetTextLineNEx()); | |
374 | + | |
375 | + if(up) | |
376 | + while(ln--) | |
377 | + AdjustForPrevNewline(); | |
378 | + else | |
379 | + while(ln-- && !IsTextBottom()) | |
380 | + { | |
381 | + AdjustForNewline(area_dn, i_btm, *p_text); | |
382 | + AdjustForFirstNewline(); | |
383 | + } | |
384 | + UpdateView(); | |
385 | + } | |
386 | + return true; | |
361 | 387 | } |
362 | - Invalidate(); | |
363 | 388 | } |
364 | - else | |
365 | - { | |
366 | - auto ln(area_up.GetTextLineNEx() + area_dn.GetTextLineNEx()); | |
367 | - | |
368 | - if(cmd & Up) | |
369 | - while(ln--) | |
370 | - AdjustForPrevNewline(); | |
371 | - else | |
372 | - while(ln-- && !IsTextBottom()) | |
373 | - { | |
374 | - AdjustForNewline(area_dn, i_btm, *p_text); | |
375 | - AdjustForFirstNewline(); | |
376 | - } | |
377 | - UpdateView(); | |
378 | - } | |
379 | - return true; | |
389 | + return {}; | |
380 | 390 | } |
381 | 391 | |
382 | 392 | void |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file ChangeLog.V0.9.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 版本更新历史记录 - V0.9 。 |
14 | -\version r6182 | |
14 | +\version r6281 | |
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 | - 2021-11-11 18:37 +0800 | |
20 | + 2021-11-19 05:50 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -32,6 +32,105 @@ | ||
32 | 32 | |
33 | 33 | $now |
34 | 34 | ( |
35 | + / $re_ex(b773) $build "updated to Microsoft VC++ 2022" ~ "Microsoft VC++ \ | |
36 | + 2019" @ "Microsoft VC++ projects" $effective @ %(YBase, YFramework, | |
37 | + Tools.(CreationTimeManager, PredefinedMacroDetector, SHBuild)) | |
38 | + $= (/ $re_ex(b862) "retargeted platform toolset" -> 'v143' ~ 'v142'), | |
39 | + + $re_add(b928) $dev $lib "#pragma directive" @ ('YB_IMPL_GNUCPP \ | |
40 | + || YB_IMPL_CLANGPP' @ "alias templates %(equal_t, not_equal_t)" | |
41 | + @ %TypeTraits, "functors %(equal_to, not_equal_to)" @ %Functor) | |
42 | + @ %YBase.YStandardEx, | |
43 | + // To elimiante Clang++ warning: [-Wfloat-equal]. | |
44 | + / %YFramework.NPL $= | |
45 | + ( | |
46 | + / %NPLA $= | |
47 | + ( | |
48 | + * DD "wrong precondition" @ "'\pre' command" @ "Doxygen comment" | |
49 | + @ "function %IsNPLAExtendedLiteral" $since b822, | |
50 | + / DLI "list environment redirection" | |
51 | + @ "static member function %ContextNode::DefaultResolve" $= | |
52 | + ( | |
53 | + / "simplified" !^ "identifier", | |
54 | + // This does not perform better without the allocator. | |
55 | + / ^ ("allocator", 'any_ops::trivial_swap_t') | |
56 | + ), | |
57 | + / DLI "term tag merge" ^ 'YB_STATELESS' ~ 'YB_PURE', | |
58 | + / @ "namespace %ystdex" $= | |
59 | + ( | |
60 | + * "wrong '\relates' command" @ "Doxygen comment" | |
61 | + @ "class template specialization \ | |
62 | + %is_bitwise_swapple<NPL::EnvironmentSwitcher>" $since b926, | |
63 | + + $re_add(b927) $lib "class template specializations \ | |
64 | + %is_bitwise_swappable for %NPL::EnvironmentReference" | |
65 | + ) | |
66 | + ), | |
67 | + * DD "wrong syntax" @ "Doxygen comment" @ "function %SymbolToString" | |
68 | + @ %NPLA1Forms $since b924, | |
69 | + / @ "function %ReadDecimal" @ %NPLAMath $= | |
70 | + ( | |
71 | + * "wrong parsing result of flonums with '.' caused by wrong factor \ | |
72 | + adjustment used" $since b930, | |
73 | + // Both exact and inexact number parsing were wrong. | |
74 | + * "wrongly rejected number literals with '.' at the end and in \ | |
75 | + the range of fixnums" $since b930, | |
76 | + // There would be an error of unsupported literal suffix \ | |
77 | + '' if the value is acceptable by the largest integer \ | |
78 | + type, or the wrong value for flonums (see ablove). | |
79 | + * "wrongly treated integer zero lexeme prefixed with a sign as \ | |
80 | + empty lexemes" $since b930, | |
81 | + // The wrong results were caused by the trailing zeros \ | |
82 | + removal. | |
83 | + ( | |
84 | + * "too lossy intermediate results" $since b930 $= | |
85 | + ( | |
86 | + / "saved internal data for ineacxt results" | |
87 | + ^ "common type of internally used extended integer \ | |
88 | + type (i.e. 'long long') and %std::uint64_t" ~ "%double"; | |
89 | + // With some changes on the call sitees, this also to \ | |
90 | + eliminate Microsoft VC++ warning: C4244. | |
91 | + / $impl "converted to %double at last" | |
92 | + ^ "signed shift on the final result" | |
93 | + ); | |
94 | + * $comp "wrong infinite values caused by the overflow fraction \ | |
95 | + even after the decimal point has occurred" $since b930, | |
96 | + // This should not overflow to infinite. | |
97 | + ), | |
98 | + + "support of exponents syntaxes on inexact numbers" | |
99 | + ) | |
100 | + ), | |
101 | + / @ "class %DualScreenReader" @ %YReader.DSReader $= | |
102 | + ( | |
103 | + / "moving scrolling area" | |
104 | + @ "functions %(Execute, (MoveUpForLastLine; ScrollByPixel))" $= | |
105 | + ( | |
106 | + / $lib $design ^ "more precise assertion message" | |
107 | + @ "space checking for scrolling", | |
108 | + * "missing scrolling of the old text area caused by negated \ | |
109 | + condition of scrolling check" $since b850 | |
110 | + ), | |
111 | + / @ "function %Execute" $= | |
112 | + ( | |
113 | + / DLDI "simplified condition checks", | |
114 | + / DLI "simplified command selection", | |
115 | + // The %Scroll bit in the command parameter is just ignored now. | |
116 | + / @ "the scrolling up command execution" $= | |
117 | + ( | |
118 | + / $revert_ex(b292) | |
119 | + "extended allowed line height to %size_t" ~ "%FontSize"; | |
120 | + // %FontSize is effectively %std::uint8_t, which is too \ | |
121 | + small in some cases. Originally (before b292) it was \ | |
122 | + 'u32' as the type of the total height and there was \ | |
123 | + no implicit limitation of the height of a line. | |
124 | + / "showed error on the size too large"; | |
125 | + * $comp "missing the check to prevent the use of the wrongly \ | |
126 | + wrapped size as the line height" $since b292 | |
127 | + ) | |
128 | + ) | |
129 | + ) | |
130 | +), | |
131 | + | |
132 | +b930 | |
133 | +( | |
35 | 134 | + "'-fno-semantic-interposition' after '-fPIC' except for platform %Android" |
36 | 135 | $effective @ ("%SHBuild-common-options.sh", "%SHBuild-YSLib-common.txt") |
37 | 136 | @ %Tools.Scripts, |
@@ -44,6 +143,7 @@ | ||
44 | 143 | ( |
45 | 144 | / %YDefinition $= |
46 | 145 | ( |
146 | + * DD "typo" @ "comment" @ "Doxygen group %traits" $since b845, | |
47 | 147 | / $resolve(#39) $dev "cleared substitution list" @ "macros \ |
48 | 148 | %(ynoexcept_param, ynoexcept_qual)" @ 'YB_IMPL_MSCPP', |
49 | 149 | / $re_add(b927) DLDI "all 'yconstexpr const'" @ "namespace scope" |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPL.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief NPL 规范和实现规格说明。 |
14 | -\version r25545 | |
14 | +\version r25665 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 304 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-04-25 10:34:20 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2021-11-11 18:35 +0800 | |
20 | + 2021-11-19 01:06 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -139,6 +139,10 @@ | ||
139 | 139 | PicoLisp :https://software-lab.de/doc/faq.html#lambda |
140 | 140 | newLISP :http://www.newlisp.org/downloads/newlisp_manual.html#define-macro |
141 | 141 | 和 Kernel 以及本设计不同,这两个例子的设计使用动态作用域(@4.6.1.2) ;在主要的特性中存在一些关键的不同而在形式模型的适用性上有显著的区别。 |
142 | +**注释** | |
143 | +Kernel 语言的原始参考实现是 SINK ,在 https://web.cs.wpi.edu/~jshutt/kernel.html 上取得,是依赖 MzScheme version 103 的解释器实现,和 [RnRK] 有一定差异。例如,字面量 #ignore 和 #inert 用 %ignore 和 %inert 代替。 | |
144 | +klisp (http://klisp.org) 是 Kernel 语言的另一个更完善的实现。 | |
145 | +有些特性(如复数支持)都没有在这两个中实现提供,而仅在 [RnRK] 中指定。 | |
142 | 146 | |
143 | 147 | @1.5 领域设计原则: |
144 | 148 | 本节描述适用于满足通用目的的语言(@1.3) 的设计。 |
@@ -1986,8 +1990,9 @@ | ||
1986 | 1990 | 当宿主语言提供函数调用支持 PTC 时,可直接使用宿主语言的 PTC 调用,否则,需要使用其它替代实现机制确保 PTC 。 |
1987 | 1991 | 注意非对象语言的调用的上下文中,若被调用时间接使用,也仍需要保证 PTC 。 |
1988 | 1992 | PTC 确保仅有一个活动(@4.5.3.1) 的调用。不满足 PTC 的情形下,语言没有提供用户访问非活动记录帧(@4.5.3.4) 资源的手段,因此可以认为是资源泄漏。但为简化语义规则,NPLA 不要求避免相关的弱内存泄漏(5.2.2.2) 。 |
1989 | -NPL 不保证一般对象存在引用(@4.2.3) ,NPLA 也不添加保证活动记录的帧(@4.5.3.4) 中保存引用,销毁活动记录的帧可能影响环境中的变量生存期而改变语义;因此 NPLA 不保证 PTC 支持,实现一般的 PTC 依赖派生实现定义的附加规则。 | |
1990 | -为满足 PTC ,在 @5.9 的基础上,尾上下文内的可以确定(@5.9) 并调整对象生存期结束时机: | |
1993 | +NPL 不保证一般对象存在引用(@4.2.3) ,NPLA 也不添加保证活动记录的帧(@4.5.3.4) 中保存引用,销毁活动记录的帧可能影响环境中的变量生存期而改变语义。 | |
1994 | +因此,除非依赖本节中以下的规则,NPLA 不保证 PTC 支持;实现更一般的 PTC 依赖派生实现定义的附加规则。 | |
1995 | +为满足 PTC ,在生存期附加约定(@5.9) 的基础上,尾上下文内的可以确定(@5.9) 并调整对象生存期结束时机: | |
1991 | 1996 | 作为临时对象(@5.8.5) 的合并子及其参数可以延长生存期至多到尾上下文结束; |
1992 | 1997 | 被证明不再需要之后引用的对象,或未被绑定到活动记录上的项中的对象,可以缩短生存期; |
1993 | 1998 | 被延长生存期的对象生存期起始和结束的相对顺序保持不变; |
@@ -1995,7 +2000,9 @@ | ||
1995 | 2000 | 推论:被缩短生存期和延长生存期的对象的生存期结束的相对顺序保持不变。这由没有被调整生存期的对象与被调整生存期对象之间的生存期结束的顺序关系(@5.10) 的传递性保证。 |
1996 | 2001 | 延长临时对象生存期和宿主语言中允许扩展非完全表达式内的临时对象的效果类似,但条件不同。 |
1997 | 2002 | **注释** |
1998 | -理论上 PTC 不要求延长生存期,仅要求特定情形下缩短生存期,且其它情形被释放的对象生存期不延长到尾上下文外;延长生存期是 @5.9 的推论。 | |
2003 | +以上规则中被调整生存期的对象一般仅是参数和函数体内创建的对象。因此,不保证理论上允许的尾上下文的都满足 PTC 。一个例子是合并子中可以保存动态环境(@4.6.1.2) ,这个环境可能被递归的调用引用,而无法提前释放。 | |
2004 | +理论上 PTC 不要求延长生存期,仅要求特定情形下缩短生存期,且其它情形被释放的对象生存期不延长到尾上下文外; | |
2005 | +允许延长生存期是生存期附加约定(@5.9) 的结果。 | |
1999 | 2006 | |
2000 | 2007 | @5.10.3 PTR(proper tail recursion ,真尾递归): |
2001 | 2008 | PTC 的活动记录性质也在一般的递归规约时体现,被称为 PTR 。 |
@@ -2590,7 +2597,7 @@ | ||
2590 | 2597 | Environment::EnsureValid(@6.8.1) ,失败时抛出异常; |
2591 | 2598 | shared_ptr<Environment> 值作为当前环境(@5.7.3) 的来源,同时提供指定为断言和具有异常的接口,参见上下文类(@6.11.3.1) ; |
2592 | 2599 | 由 NPL_NPLA_CheckParentEnvironment(@6.1.2.1) 配置的可选的附加检查,失败时同 Environment::EnsureValid 。 |
2593 | -对象语言的动态类型的值需要进行环境类型的类型检查时,只区分对象语言中的类型,不特别排除具有宿主类型的非宿主值,因此不断言失败; | |
2600 | +对象语言的动态类型的值需要进行环境类型的类型检查(@4.7.3) 时,只区分对象语言中的类型,不特别排除具有宿主类型的非宿主值,因此不断言失败; | |
2594 | 2601 | 其余情形可能静态确定不存在来自可能通过互操作(@5.3) 来源取得的非空值,此时一般使用断言而不是异常。 |
2595 | 2602 | |
2596 | 2603 | @6.8.2.2 循环环境引用和环境引用所有权: |
@@ -3067,10 +3074,10 @@ | ||
3067 | 3074 | NPLA 上下文中,被激活的动作被移除。因为没有全局的垃圾回收(@4.2.2.3) ,这保证激活的动作在执行后能保证其中直接或间接捕获的资源被及时释放。 |
3068 | 3075 | 若需通过重复使用动作(实现非正常控制(@4.8) 等),需在动作被激活前进行处理(例如,复制或另行构造动作)。 |
3069 | 3076 | 以循环实现重写(@4.1.2) 时,有效的当前动作可用于作为保持重写循环的条件。当不存在有效的当前动作时,规约在完成已激活的规约操作后终止。 |
3070 | -以抽象机描述操作语义(@2.2.3) 时,定界动在尾上下文外提供剩余的动作,作为一个序列,称为尾部动作(trailing actions) ,是当前动作的后继动作(subsequent action) 。另见 http://www.brics.dk/RS/03/41/BRICS-RS-03-41.pdf 。 | |
3077 | +以抽象机描述操作语义(@2.2.3) 时,定界动在尾上下文(@4.4.8) 外提供剩余的动作,作为一个序列,称为尾部动作(trailing actions) ,是当前动作的后继动作(subsequent action) 。另见 http://www.brics.dk/RS/03/41/BRICS-RS-03-41.pdf 。 | |
3071 | 3078 | 当前动作起始的当前动作序列表示语言实现中(不作为一等对象(@4.1) 的)未被捕获的当前续延(@4.5.2.1) 。 |
3072 | 3079 | 动作和尾部动作整体构成求值上下文(@4.4.8) 的实现。后者在元语言中提供操作,又称为元上下文(meta-context) 。另见 http://www.brics.dk/RS/05/16/BRICS-RS-05-16.pdf 。 |
3073 | -当前动作可作为尾上下文(@4.4.8) 的实现,称为尾动作(tail action) 。特定的尾动作可实现符合 PTC 的尾调用(@5.10.2) 。 | |
3080 | +当前动作可作为尾上下文的实现,称为尾动作(tail action) 。特定的尾动作可实现符合 PTC 的尾调用(@5.10.2) 。 | |
3074 | 3081 | 配合重写循环提供基于尾动作的循环 API 可实现 CPS(contiuation passing style) 风格的异步调用。相关 API 参见 @6.11.4 。 |
3075 | 3082 | |
3076 | 3083 | @6.11.3.1 上下文类: |
@@ -3203,33 +3210,46 @@ | ||
3203 | 3210 | 精确数和不精确数在数值上可能相等,而类型不同。 |
3204 | 3211 | 宿主类型中的本机整数和浮点数是数值类型的子类型,分别称为 fixnum 和 flonum 。这些类型在项的内部表示(在值数据成员(@6.2) 中)预期直接占据本机存储而不需要动态分配。 |
3205 | 3212 | Fixnum 总是精确数;flonum 总是不精确数。 |
3206 | -**注释** 当前实现中,所有数值是 fixnum 或 flonum 之一。 | |
3213 | +**注释** 当前实现中,所有数值是 fixnum 或 flonum 之一。两者分别是宿主的整数类型(排除字符和 bool 类型)以及浮点数类型。 | |
3214 | +Flonum 支持带符号的无限大值,以及 NaN(not-a-number) 值作为特殊数值。其它值都是有限值。特殊数值可能具有不唯一的内部表示,但和有限值的表示都不同。 | |
3215 | +Flonum 中可存在小的非零数,可能具有不唯一的内部表示。 | |
3216 | +**注释** 宿主类型中的非规格化(denormalized) 浮点数是具有不唯一的内部表示的小的非零数值。 | |
3207 | 3217 | 整数值的数值具有整数类型。这包括所有的 fixnum ,以及 flonum 中是整数的数值。这不和宿主类型直接对应。 |
3208 | 3218 | **注释** 一个 flonum 是整数,当且仅当它的值取 std::round 、std::floor 或 std::ceil 后结果和原值相等。[R7RS] 对不精确数有类似的定义(仅使用 round )。 |
3209 | -如其它大多数类型,NPLA1 数值类型(@6.14.1) 符合正规表示(@6.10.7) ,只使用值数据成员(@6.2) 表示有效的数据。 | |
3219 | +如其它大多数类型,数值类型符合正规表示(@6.10.7) ,只使用值数据成员(@6.2) 表示有效的数据。 | |
3210 | 3220 | **注释** |
3211 | 3221 | 精确性、fixnum 和 flonum 等区分同 [R6RS] ,但具体实现要求不尽相同。 |
3212 | 3222 | 和 [RnRK] 不同,本文档没有指定可选的模块,也没有指定精确的 ±∞ 值。 |
3213 | 3223 | |
3214 | 3224 | @6.14.2 数值操作约定: |
3215 | -在对象语言中,数值操作是使用数值类型作为输入的值的操作。NPLA1 提供本机 API 支持这些操作的实现。 | |
3225 | +在对象语言中,数值操作是可使用数值作为算法输入的值的操作。NPLA1 提供本机 API 支持这些操作的实现。 | |
3226 | +数值操作蕴含对应的数值计算,具有数值或者非数值类型的操作数和计算结果(@4.5.2.1) 。计算结果依赖影响计算结果的操作数。计算结果依赖至少一个数值类型的操作数。 | |
3227 | +数值操作接受至少一个操作数,其中至少一个操作数被对应的数值计算的计算结果依赖。 | |
3216 | 3228 | 除非另行指定: |
3217 | -在数学上有意义的前提下,数值操作同时支持以上尽可能多的类型作为输入; | |
3218 | -数值操作预期输入的类型是数值类型,否则出错,抛出 NPL::TypeError 异常(@6.5) ; | |
3219 | -除数值操作不区分输入的数值上等价的精确数或不精确数; | |
3220 | -若数值操作的所有输入都是精确数,除非不能表示计算结果的范围,结果不是不精确数; | |
3229 | +在数学上有意义的前提下,数值操作同时支持以上尽可能多的数值类型的操作数; | |
3230 | +对预期是数值类型的操作数,数值操作进行类型检查(@4.7.3) ,失败时出错,抛出 NPL::TypeError 异常(@6.5) ; | |
3231 | +数值操作不区分数值类型的操作数中数值上等价的精确数或不精确数; | |
3232 | +若数值操作的所有数值类型的操作数都是精确数,除非不能表示计算结果的范围,结果不是不精确数; | |
3221 | 3233 | 除非不能表示计算结果的范围,数值操作不损失结果的精度; |
3234 | +若计算结果是数值,则对应的数值操作的结果是不超过所有数值操作数结果的数值类型; | |
3222 | 3235 | 数值操作的输出的类型是能表示操作结果的数,其类型的值域能表示操作结果,具体类型未指定; |
3223 | -实现假定输入和计算过程中不出现 SNaN(signaling NaN) 值。 | |
3236 | +若计算结果是小于最小可唯一表示的数值的不精确数,则对应的数值操作结果是不精确数 0 ; | |
3237 | +若计算结果中无限大数值不能通过数学上有意义的方式确定符号,则对应的数值操作结果是无限大值或 NaN 之一,具体选择未指定; | |
3238 | +可假定数值计算的操作数和计算过程中不出现 SNaN(signaling NaN) 值; | |
3239 | +若被计算结果依赖的任一操作数中具有 NaN 值,则依赖这个操作数的数值操作结果也是 NaN 值。 | |
3224 | 3240 | **注释** |
3241 | +数值操作可能允许非数值的操作数,这些操作数也可被计算结果依赖。 | |
3242 | +因为 Flonum 能表示所有实数数值范围,所以实数范围以内的操作不会引入操作数以外的其它 flonum 类型。 | |
3225 | 3243 | 数值操作抛出异常的要求不一定在每一个实现数值操作的 API 中蕴含,因为这些 API 不一定是数值操作的完整实现。 |
3244 | +计算结果中 NaN 值的符号实际由宿主实现决定。 | |
3245 | +若数值操作指定非数值计算结果(如布尔值(@4.1) )或者不能表示的 NaN 值的计算结果,则即使依赖 NaN 数值操作数,也不是 NaN 值。 | |
3226 | 3246 | |
3227 | 3247 | @6.14.3 标签类型: |
3228 | 3248 | 以下类型具有 NPL::TypedValueAccessor(@6.9.6) 的相关特化。 |
3229 | 3249 | NumberLeaf |
3230 | 3250 | NumberNode |
3231 | -相关的特化检查数值类型输入,若失败则抛出异常。 | |
3232 | -**注释** 使用这种方式访问的 API 可直接以输入表示数值类型作为前置条件,而不需要在内部检查输入的值是否具有数值类型。 | |
3251 | +相关的特化检查数值类型的操作数,若失败则抛出异常。 | |
3252 | +**注释** 使用这种方式访问的 API 可直接以操作数表示数值类型作为前置条件,而不需要在内部检查操作数的值是否具有数值类型。 | |
3233 | 3253 | 对应的特化决定这些类型的不同。 |
3234 | 3254 | NumberLeaf 直接传递数值类型中的值数据成员; |
3235 | 3255 | NumberNode 传递 NPL::ResolvedArg<>(@6.9.6) ,包含被 NPL::ResolveTerm(@6.9.6) 解析后的节点和访问引用的指针( NPL::ResolvedTermReferencePtr(@6.9.6) 类型的值)。 |
@@ -3276,24 +3296,37 @@ | ||
3276 | 3296 | @6.14.6 数值表示: |
3277 | 3297 | 以下函数提供和数值表示相关的操作: |
3278 | 3298 | ReadDecimal |
3279 | -支持的数值以字符串作为表示,包括: | |
3280 | -支持的表示具体包括: | |
3281 | -匹配正则表达式 (+|-)?[0-9]+ :精确数数值。 | |
3299 | +支持的数值以字符串作为表示。 | |
3300 | +支持的表示具体包括(优先匹配较长的模式): | |
3301 | +匹配正则表达式 (+|-)?[0-9]+ :十进制精确数数值。 | |
3282 | 3302 | 不论符号,当前精确数数值字面量默认都具有宿主类型(@5.5) int ,除非其绝对值太大而无法被表示,使用其它类型代替。 |
3283 | 3303 | 除非精确数字面量的数值超过所有 fixnum 的可表示范围,都具有 fixnum 值。 |
3284 | -除非精确数字面量的数值超过所有支持的精确数的可表示范围,都具有精确数类型。(这可能会在以后改变。) | |
3285 | -匹配正则表达式 (+|-)?[0-9]+\.[0-9]+? :不精确数数值。 | |
3304 | +除非精确数字面量的数值超过所有支持的精确数的可表示范围,都是精确数。 | |
3305 | +**注释** 当前精确数的表示范围是 fixnum 中宿主类型的值域的并集,因此超过 fixnum 可表示范围的数值不是精确数。 | |
3306 | +匹配正则表达式 (+|-)?[0-9]+\.[0-9]* 或 (+|-)?[0-9]+(\.[0-9]*)?(E|e)(+|-)?[0-9]+ :十进制不精确数数值。 | |
3286 | 3307 | 若不精确数数值不能以规格化范围内的数值表示,则结果是对应符号的无限大值。 |
3287 | -不精确数数值字面量的解析误差不大于最后一个在规格化范围内表示的十进制小数位为 1 时的绝对值的真值大小,以任意可能符合宿主语言要求的舍入模式下的最大值计。 | |
3308 | +不精确数数值字面量的解析使用宿主语言允许的未指定的浮点数舍入模式,其误差不大于最后一个在规格化范围内表示的十进制小数位为 1 时的绝对值的真值大小(以任意可能符合宿主语言要求的舍入模式下的最大值计)。 | |
3309 | +第二种形式是科学记数法,其中的 E 和 e 的含义是等价的,之后是指数。 | |
3288 | 3310 | **原理** |
3289 | -浮点数解析存在误差不大于 1ULP(unit in the last place) 的精确算法,但对宿主实现的要求较高,且性能可能明显较低,故不作要求。 | |
3290 | -和宿主语言的 std::strtod 不同,不要求考虑宿主语言实现中的具体浮点数舍入模式。 | |
3311 | +浮点数解析存在不同精度的算法。 | |
3312 | +若以二进制浮点数和经过舍入的十进制表示相互转换不损失精度为前提,宿主语言的 std::numeric_limits 的 max_digits10 位十进制数字足够表示。 | |
3313 | +(对 IEEE-754 的二进制浮点数情形的证明,参见 https://www.itu.dk/~sestoft/bachelor/IEEE754_article.pdf Theorem 15 。) | |
3314 | +但是,对任意有效输入的结果误差都不大于 1ULP(unit in the last place) 的不经舍入的值完全精确值(full precision) 的精确解析算法,对实现的要求较高,且性能可能明显较低,故不作要求。 | |
3315 | +(对 IEEE-754 的二进制浮点数的情形,需要数十倍的中间存储,参见 https://stackoverflow.com/questions/554063/62542806#62542806 。) | |
3316 | +和宿主语言的 std::strtod 不同,允许使用宿主语言中的任意浮点数舍入模式,而不要求不同浮点数舍入模式下的结果一致性。 | |
3291 | 3317 | **注释** |
3292 | -串模式 (+|-) 表示带有可选前缀符号(仅限一个),影响值的数值。对 fixnum ,+0 和 -0 是相等的数值,但 flonum 不同符号的零值不同。 | |
3318 | +串模式 (+|-) 表示带有可选前缀符号(仅限一个),影响值的数值。对 fixnum ,+0 和 -0 是相等的数值。Flonum 不同符号的零值在值的表示中可以不同,但不要求实现表现这种不同。 | |
3293 | 3319 | 同 klisp 而不同于 [RnRS] 的字面量词法,小数点不能出现在词素中符号以外的第一个字符;但 klisp 的 string->number 没有这个限制。 |
3320 | +同 [RnRS] 而不同于 klisp(两者包括字面量词法和 string->number ),小数点允许出现在词素的结尾。 | |
3321 | +当前不精确数数值都具有宿主类型 double 。即便 long double 可能具有更大的数值范围,也不能通过解析数值表示直接取得。 | |
3322 | +类似地,[Racket] 默认不启用 extflonum(关于数值操作也类似,参见数值操作约定(@6.14.2) )。 | |
3323 | +当前允许在宿主值不能完全存储不精确数的字面量数字时,解析十进制不精确数字面量存储的值可能和字面量的数值的真值之间具有超过 1ULP 的误差。这可能影响和精确数之间的比较。 | |
3324 | +当前实现使用四舍五入。 | |
3294 | 3325 | 关于宿主语言中 std::strtod(同 ISO C 标准库的 strtod )舍入要求的一些问题,参见: |
3295 | 3326 | https://www.exploringbinary.com/incorrectly-rounded-conversions-in-gcc-and-glibc/ |
3296 | 3327 | https://www.sourceware.org/bugzilla/show_bug.cgi?id=3479 |
3328 | +[RnRK] 没有明确指定字面量词法规则。 | |
3329 | +当前 klisp 的实现不允许 E 和 e 之前没有小数点,且在存在 E 或 e 时省略之后的指数的任意部分,和 SINK 以及 [RnRS] 都不同。本设计遵循后者。 | |
3297 | 3330 | |
3298 | 3331 | @6.15 派生实现和应用实例: |
3299 | 3332 | 除 NPLA 公共实现和派生实现 NPLA1 外,NPLA API 还具有一些其它应用实例。 |
@@ -4081,7 +4114,7 @@ | ||
4081 | 4114 | 当前未支持宿主栈展开(stack unwinding) 的互操作(@5.3) 。 |
4082 | 4115 | C++ 异常调用重写循环(@6.11.3) 内资源对象的析构函数顺序是未指定的。但是,对 C++ API 异常安全保证的要求(@7.4.1.4) 仍然不变。 |
4083 | 4116 | 在 NPLA1 API 中同时提供对应的异步规约但不使用 TCO 的实现,不满足本节要求,仅供参考。 |
4084 | -TCO 应能支持实现 PTC(@5.10.2) 。 | |
4117 | +TCO 应能按 NPLA 尾上下文约定(@5.10) ,支持在尾上下文(@4.4.8) 实现 PTC(@5.10.2) 。 | |
4085 | 4118 | 在启用异步规约实现(@7.9.2) 的基础上,启用 TCO 的实现定义为实现选项(@7.1) NPL_Impl_NPLA1_Enable_TCO 。 |
4086 | 4119 | 以下指定当前对 TCO 的有限支持。没有明确指出的情形不保证支持 TCO 。 |
4087 | 4120 |
@@ -4101,7 +4134,7 @@ | ||
4101 | 4134 | 基于异步重规约和 TCO 的互操作提供目标 TCO 。 |
4102 | 4135 | |
4103 | 4136 | @7.10.2 整体设计约束: |
4104 | -TCO 要求尾上下文(@4.4.8) 的续延(@4.5.2.1) 保持等效。考虑到计算资源的限制,排除构造相同的外部的求值环境(@4.6.1.2) 的实现方式,这蕴含同一性。 | |
4137 | +TCO 要求尾上下文的续延(@4.5.2.1) 保持等效。考虑到计算资源的限制,排除构造相同的外部的求值环境(@4.6.1.2) 的实现方式,这蕴含同一性。 | |
4105 | 4138 | NPLA 的 TCO 基于异步规约(@7.9) ,基本方式是尾调用合并(@7.10) 。TCO 动作(@7.10.3) 是支持了尾调用合并的动作。 |
4106 | 4139 | 考虑到当前动作(@6.11.3) 预期直接构成当前续延(@6.11.3.1) ,对 NPLA1 ,这需要限制尾动作(@6.11.3) 的下一动作(@6.12.2) 不是 TCO 动作。 |
4107 | 4140 |
@@ -4179,7 +4212,7 @@ | ||
4179 | 4212 | 但注意调整语义规则或通过区分出非平凡析构等方式证明可观察行为不变后,减少父环境被隐藏的变量而完全实现 PTC 是可能的。 |
4180 | 4213 | 基于语义规则的许可,实现应支持部分非幂等操作的被合并,以支持 PTC : |
4181 | 4214 | 若设置前的环境是被设置的环境的直接或间接父环境,其中可能影响可观察行为的变量都被新的环境隐藏,可确定父环境不再使用且不影响可观察行为,则仍然合并操作,并释放该父环境的资源。 |
4182 | -NPLA 规则 @5.10 允许可合并临时对象分配的非幂等操作实现 PTC ,即若存在已在 TCO 动作中分配的相等(以宿主环境(@2.7.1) 约定,参见 @7.11.5)的临时对象,则不再分配。 | |
4215 | +NPLA 尾上下文约定允许可合并临时对象分配的非幂等操作实现 PTC ,即若存在已在 TCO 动作中分配的相等(以宿主环境(@2.7.1) 约定,参见 @7.11.5)的临时对象,则不再分配。 | |
4183 | 4216 | |
4184 | 4217 | @7.10.4.2 非幂等操作合并约束: |
4185 | 4218 | 同一个 TCO 动作内,以下尾调用合并的效果仍然有效: |
@@ -4320,45 +4353,74 @@ | ||
4320 | 4353 | |
4321 | 4354 | @7.11.2 动作组合: |
4322 | 4355 | 动作组合通过调用 NPL::RelaySwitched(@6.12.7) 。 |
4323 | -这和通过续延并保证异步调用(如 klisp 中 kapply_cc )不同,不把维护状态的操作放在待组合的后续操作中。 | |
4356 | +这和通过续延并保证异步调用不同,不把维护状态的操作放在待组合的后续操作中。 | |
4324 | 4357 | 这能同时支持同步和异步实现,同时在当前动作以序列表示时,不需要无效化被组合的动作的宿主对象。 |
4358 | +**注释** klisp 实现的 kapply_cc 是通过续延并保证异步调用的一个例子。 | |
4325 | 4359 | |
4326 | 4360 | @7.11.3 函数合并(@4.5.3) 的实现: |
4327 | 4361 | NPLA1 规范求值算法(@7.8.2) 相对 Kernel 更简单以支持函数合并的 TCO 实现(@7.11.5) 。 |
4328 | -对应地,函数合并和 klisp 的 eval 实现略有不同:在处理器调用(@7.6.1.2) 实现参数列表中参数的求值。 | |
4362 | +对应地,函数合并在处理器调用(@7.6.1.2) 实现参数列表中参数的求值。 | |
4363 | +**注释** 这和 klisp 的 eval 实现略有不同。 | |
4329 | 4364 | NPLA1 使用包装数(@7.6.1.1) 处理包装调用,支持多重包装(这在 [RnRK] 被求值算法蕴含);而当前 klisp 的实现没有正确地支持多重包装调用,参见:https://bitbucket.org/AndresNavarro/klisp/issues/11 。 |
4330 | -和 klisp 类似,参数列表求值前检查不存在实际参数(而无需求值)的情形进行优化。 | |
4365 | +**注释** 和 klisp 类似,参数列表求值前检查不存在实际参数(而无需求值)的情形进行优化。 | |
4331 | 4366 | |
4332 | 4367 | @7.11.4 PTC 和尾调用本机实现: |
4333 | 4368 | 符合 PTC 的尾调用通过 TCO 动作(@7.10.3) 实现。 |
4334 | 4369 | TCO 动作(@7.10.3) 作为 NPLA 续延和之后在 PLDI 2020 公开的论文 https://doi.org/10.1145/3385412.3385981 中的 extra continuation frame 类似。 |
4335 | 4370 | TCO 动作可扩展实现类似 SRFI-157 的续延标记(continuation mark) 的特性。 |
4336 | 4371 | 在 NPLA1 规范求值算法(@7.8.2) 的 PTC 通过显式构造 TCO 动作以及在此基础上的操作压缩(@7.10.4) 实现。 |
4337 | -这对应 klisp 的 ktail_call 实现 Kernel 的默认求值算法(包括 [RnRK] 的 eval 应用子的底层的操作子);但和后者依赖 GC 不同,TCO 动作可对环境有所有权(@7.10.6) 。 | |
4338 | -klisp 还使用 ktail_call 提供本机实现。NPLA1 也可使用类似的实现。 | |
4339 | -其它更一般的情况下,在求值上下文(@4.4.8) 中隐含已构造 TCO 动作为前提,通过直接或间接调用 A1::ReduceOnce(@7.4.4) 提供 PTC 保证。 | |
4340 | -这对应 klisp 的 ktail_eval ;但和后者不同,A1::ReduceOnce 调用确切地只对应不显式引入新的环境的操作。 | |
4341 | 4372 | 可能引入新的环境的操作,如 [RnRK] 的 eval(对应 NPLA1 对象语言函数 eval 和 eval% 等,参见 @11.3.7 ),需要另行调用比 A1::ReduceOnce 更复杂的操作压缩。 |
4342 | 4373 | 和 Kernel 要求以外,因为维护资源(@7.10.5) 的需要,TCO 动作在函数合并的底层操作子合并前被构造,因此进入参数求值时在资源管理的意义上也在所在函数合并的同一个尾上下文(@4.4.8) 。 |
4343 | 4374 | 另见 TCO 实现(@7.11.5) 。 |
4344 | - | |
4345 | -@7.11.5 TCO 动作(@7.10.3) 实现和限制: | |
4375 | +**注释** | |
4376 | +PTC 实现对应 klisp 的 ktail_call 实现 Kernel 的默认求值算法(包括 [RnRK] 的 eval 应用子的底层的操作子);但和后者依赖 GC 不同,TCO 动作可对环境有所有权(@7.10.6) 。 | |
4377 | +klisp 还使用 ktail_call 提供本机实现。NPLA1 也可使用类似的实现。 | |
4378 | +其它更一般的情况下,在求值上下文(@4.4.8) 中隐含已构造 TCO 动作为前提,通过直接或间接调用 A1::ReduceOnce(@7.4.4) 提供 PTC 保证。 | |
4379 | +这对应 klisp 的 ktail_eval ;但和后者不同,A1::ReduceOnce 调用确切地只对应不显式引入新的环境的操作。 | |
4380 | + | |
4381 | +@7.11.A 资源回收限制: | |
4382 | +当前 TCO 操作压缩不保证回收(通过 #ignore 指定)被忽略外的动态环境(@4.6.1.2) 。 | |
4383 | +注意 [RnRK] §3.3 仅保证的应用子调用是尾上下文(@4.4.8) ,使用任意环境作为动态环境的操作子调用时不需要满足 PTC 。 | |
4384 | +这可能有误,因为造成应用子的底层合并子和不作为底层操作子的其它操作子不一致,并且和这里的操作压缩限制一样,实际无法总是保证具有动态环境的应用子在动态环境被用用时能满足的调用 PTC 。 | |
4385 | +**注释** | |
4386 | +事实上,Kernel 语言的实际实现一般无法保证回收非 #ignore 的动态环境,即便动态环境只被用于尾调用中。 | |
4387 | +上述无法 TCO 的情形在其它语言中因为可达性分析等可能具有实现缺陷也不会释放存储,如以下 Kernel 程序在 klisp 中实测不支持 PTC : | |
4388 | +($sequence ($define! f ($lambda (n) ((($vau (x y) e (eval ($sequence x y) e)) n (f n))))) (f 1)) | |
4389 | +而当前实现中,对应上述 Kernel 程序的 NPLA1 程序支持 PTC : | |
4390 | +$sequence ($def! f ($lambda (n) ((($vau (x y) e (eval ($sequence x y) e)) n (f n))))) (f 1) | |
4391 | +以下 Kernel 程序和对应的 NPLA1 程序支持 PTC : | |
4392 | +($sequence ($define! $f ($vau () #ignore (($f)))) ($f)) | |
4393 | +$sequence ($def! $f ($vau () #ignore (() $f))) (() $f) | |
4394 | +但替换动态环境不被忽略,则都不支持 PTC(对 NPLA1 ,因为 e 没有在尾上下文中被引用,而无法被压缩): | |
4395 | +($sequence ($define! $f ($vau () e (($f)))) ($f)) | |
4396 | +$sequence ($def! $f ($vau () e (() $f))) (() $f) | |
4397 | +以上 Kernel 程序使用 klisp 和 SINK 中(后者需替换 #ignore 为 %ignore ),效果一致。 | |
4398 | + | |
4399 | +@7.11.5 TCO 动作(@7.10.3) 实现和其它限制: | |
4346 | 4400 | 因为维护资源(@7.10.5) 的需要,NPLA1 规范求值算法(@7.8.2) 不处理 WHNF(@4.4.5.1) 以外的操作数且允许宿主类型的调用(@7.6.1.2) 处理 WHNF 的第一项。 |
4347 | 4401 | 当前在 TCO 动作中被分配的临时对象(@5.8.5) 的操作都针对作为 WHNF 的第一项的合并子(@4.5.3.2) ,其中合并子的相等关系由相等性(@8.4.5.5) 或不影响可观察行为的其它宿主实现提供的 == 操作确定。 |
4348 | 4402 | 由相等性(@8.4.5.5) ,捕获不同环境的 vau 合并子不相等;不论是否具有相等的外部表示(@1.2.4) 和来源,其右值不会被直接操作压缩(@7.10.4) 避免多次添加而被 TCO ;若其嵌套调用因为捕获不同的存在引用关系的环境,不支持其它形式的 TCO ;因此,不支持 PTC 。 |
4349 | -注意上述情形在其它语言中因为可达性分析等可能具有实现缺陷也不会释放存储,如 Kernel 程序 ($sequence ($define! f ($lambda (n) ((($vau (x y) e (eval ($sequence x y) e)) n (f n))))) (f 1)) 在 klisp 中实测不支持 PTC 。 | |
4350 | -当前 TCO 操作压缩不支持回收(通过 #ignore )指定忽略外的动态环境(@4.6.1.2) 。这实际上较 [RnRK] 的保证弱。但 klisp 同样没有很好地支持此特性,如 Kernel 程序 ($sequence ($define! $f ($vau () #ignore (($f)))) ($f)) 在 klisp 中实测不支持 PTC 。 | |
4351 | -(关于以上 klisp 的问题,参见 https://bitbucket.org/AndresNavarro/klisp/issues/12 。) | |
4352 | -但是当前实现中,对应的 NPLA1 程序支持 PTC : | |
4353 | -$sequence ($def! f ($lambda (n) ((($vau (x y) e (eval ($sequence x y) e)) n (f n))))) (f 1) | |
4354 | 4403 | 实现依赖 Environment::IsOrphan(@6.11.1.1) 等判断确保内存安全(@5.6.3) 。 |
4355 | 4404 | 忽略非平凡析构判断(假定所有对象都可平凡析构),允许移除可证明不被继续引用(@5.10) (如被总是新的环境隐藏)的变量。 |
4356 | 4405 | 被移除的对象生存期提前结束(@5.10) 。 |
4357 | 4406 | 除被隐藏的变量被单独移除外,若一个活动记录帧(环境)内存在任意不满足可证明幂等的操作的情形,整个帧的剩余部分都被保持存储(因为不支持对 NPL::TermReference(@6.8.3) 分别保存引用计数)。 |
4358 | 4407 | 当前实现并没有显式支持 evlis tail recursion(@5.10.3) ,但因为调用前切换环境时已提前进行了收集,所以以 TCO 动作为边界,保存的帧应与之等效。 |
4359 | 4408 | 尽管可能有更优的渐进复杂度,所需空间的大小仍取决 TCO 活动记录最终保留帧前分配对象和碎片所占空间大小之和的最大值;实现应该不依赖这项特性。 |
4360 | -回收使函数对象在表达式求值外完毕之前结束,这仍然符合 @5.10 的要求。 | |
4409 | +回收使函数对象在表达式求值外完毕之前结束,这仍然符合尾上下文约定(@5.10) 的要求。 | |
4361 | 4410 | 当前 NPL::LiftToReturn(@6.9.7.3) 的调用非嵌套调用安全(@6.1.3) 。在项的嵌套深度依赖调用深度时,不满足 PTC 。 |
4411 | +**注释** | |
4412 | +需要注意,在 WHNF 的第一项嵌套调用时,Kernel 不保证递归调用的 PTC ,因为这不是尾上下文: | |
4413 | +($sequence ($define! $f ($vau () #ignore (($f)))) ($f)) | |
4414 | +($sequence ($define! f (wrap ($vau () #ignore ((f))))) (f)) | |
4415 | +($sequence ($define! f ($lambda () ((f)))) (f)) | |
4416 | +(关于以上 klisp 在没有支持 PTC 的情形的第一个例子的疑问,另见 https://bitbucket.org/AndresNavarro/klisp/issues/12 。) | |
4417 | +类似地,对应的 NPLA1 程序同样不保证 PTC : | |
4418 | +$sequence ($def! $f ($vau () #ignore (() $f))) (() $f) | |
4419 | +$sequence ($def! f (wrap ($vau () #ignore (() f)))) (() f) | |
4420 | +$sequence ($def! f ($lambda () (() f))) (() f) | |
4421 | +应用子递归调用对应的 Scheme 程序也类似: | |
4422 | +(begin (define f (lambda () ((f)))) ((f))) | |
4423 | +(begin (define f (lambda () (f))) (f)) | |
4362 | 4424 | |
4363 | 4425 | @7.11.6 续延名称: |
4364 | 4426 | 模块 NPL::NPLA1 提供特定可由函数 A1::QueryContinuationName(@7.8) 查询得到的续延名称。 |
@@ -4898,7 +4960,7 @@ | ||
4898 | 4960 | <reference> :对象引用值。 |
4899 | 4961 | <list> :列表。参见 @9.9.4 。 |
4900 | 4962 | <lists> :元素都是列表的列表。 |
4901 | -<boolean> :布尔(boolean) 值,即取值为 #t 或 #f 的集合,是 NPLA 类型映射(@5.5) 指定的用于条件判断的单一值的类型。 | |
4963 | +<boolean> :布尔值(@4.1),即取值为 #t 或 #f 的集合,是 NPLA 类型映射(@5.5) 指定的用于条件判断的单一值的类型。 | |
4902 | 4964 | 推论:<boolean> 对应的宿主类型(@5.5) 是 bool 。 |
4903 | 4965 | <test> :类似 <object> ,通常预期为 <boolean> ,作为条件。 |
4904 | 4966 | 和 Scheme 类似但和 Kenerl 不同,非 #t 的值在决定分支时视同 #f ,以允许在 <boolean> 外自然扩展的逻辑代数操作。 |
@@ -5228,13 +5290,17 @@ | ||
5228 | 5290 | 形式参数树的子节点绑定的副作用先序(@4.4.3) 枝节点的副作用。 |
5229 | 5291 | |
5230 | 5292 | @9.7.4 一般 TCO/PTC(@7.10) 保证和限制: |
5231 | -参见一般实现策略(@7.10.1) 和部分实现限制(@7.11.5) 。 | |
5232 | -当前实现的规约(如 A1::Reduce(@7.4.4) )直接递归规约子表达式支持的尾上下文(@4.4.8) 较少(详见 @9.7.4.1) ,和 Scheme 对大量特定的形式提供明确的尾上下文上的 PTC 保证不同。 | |
5233 | -和 Kernel 类似,这是由于缺少针对特定的特殊形式(@5.2) 的特设规则。但因为程序实现(@9.1) 等限制,当前设计和实现支持的非调用的上下文(@9.7.4.3) 较 Kernel 少。 | |
5234 | -虽然不保证在所有情形下支持 PTC ,当前的实现一般支持使用自由存储分配,以尽可能地避免宿主语言的未定义行为(@5.4) : | |
5293 | +NPLA1 使用 NPLA 的规则(@5.10.2) ,不保证在所有理论允许的情形下支持明确尾上下文以支持 PTC : | |
5294 | +调用位于尾上下文,当且仅当所有的对象都可被调整生存期而支持 PTC 。 | |
5295 | +满足实现行为(@4.1.3) 要求的前提下,实现可支持比这里的要求更多的 TCO 和 PTC 尾上下文。 | |
5296 | +**注释** | |
5297 | +当前实现一般支持使用自由存储分配,以尽可能地避免宿主语言的未定义行为(@5.4) : | |
5235 | 5298 | 其中,异步规约(@7.9) 实现使分配以环境(@6.11.1) 表示的活动记录失败时满足常规宿主资源分配要求(@5.4.1) 。 |
5236 | 5299 | 另见语法分析(@6.1.6) 和绑定支持 API(@7.7.4) 的类似的资源分配失败的约定。 |
5237 | -满足实现行为(@4.1.3) 要求的前提下,实现可能实际支持更多的 TCO 和 PTC 尾上下文。 | |
5300 | +具体实现方式参见一般实现策略(@7.10.1) 和部分实现限制(@7.11.5) 。 | |
5301 | +当前实现的规约(如 A1::Reduce(@7.4.4) )直接递归规约子表达式支持的尾上下文(@4.4.8) 较少(详见 @9.7.4.1) ,和 Scheme 对大量特定的形式提供明确的尾上下文上的 PTC 保证不同。 | |
5302 | +和 Kernel 类似,这是由于缺少针对特定的特殊形式(@5.2) 的特设规则。 | |
5303 | +因为程序实现(@9.1) 等限制,当前设计和实现支持的合并子调用以外的上下文(@9.7.4.3) 较 Kernel 也更少,但实际涵盖范围却可能更大(@7.11.5) 。 | |
5238 | 5304 | |
5239 | 5305 | @9.7.4.1 支持 PTC 的尾调用尾上下文: |
5240 | 5306 | 当允许忽略非平凡析构(@7.10.4) 时,可以在尾上下文求值中进行 TCO 并支持 PTC 。 |
@@ -5252,7 +5318,7 @@ | ||
5252 | 5318 | 名称解析可能是尾上下文。 |
5253 | 5319 | |
5254 | 5320 | @9.7.4.3 未绑定对象: |
5255 | -按 @5.10 的约定,项上未被绑定到活动记录上的项中的对象生存期可提前结束。 | |
5321 | +按尾上下文约定(@5.10) ,项上未被绑定到活动记录上的项中的对象生存期可提前结束。 | |
5256 | 5322 | 实现 PTC 时被规约时替换结果的清理(@6.4.6) 若实现支持 TCO(@7.4) 且没有实现保存未绑定操作数引起这种情形。 |
5257 | 5323 | 当前通过参考实现环境(@10) 引入的合并子已经支持了保存操作数,但若互操作(@5.3) 没有保存操作数,则可能产生问题。 |
5258 | 5324 | 应注意合并子的参数绑定引用值(@7.7.3) 在同一个尾上下文求值引起清理导致悬空引用(@9.4.3.2) 破坏内存安全(@9.4) 。 |
@@ -6295,7 +6361,7 @@ | ||
6295 | 6361 | 未指定 eq? 的比较结果可允许实现复用存储右值的驻留(@9.8.4) 对象。 |
6296 | 6362 | eql? 实际比较宿主值的相等。允许 eqv? 和 eql? 的不同可允许一对多的类型映射(@5.5.1) 下比较对象语言中的值的相等。(而多对一的类型映射 eql? 和 eqv? 可一致地比较。) |
6297 | 6363 | 但是,当前实现中,大多数一对多映射的类型(如环境)都没有引起使 eql? 和 eqv? 不同的比较实现,因为不同宿主值类型的对象具有足够显著的差异,在大多数上下文不通过一些具有不可忽略开销的转换机制(如锁定环境弱引用转换为环境强引用),无法直接相互替换而保证行为差异可被忽略,因此逻辑上不适合定义为相等的。 |
6298 | -而基于性能等理由,等其它一对多映射的类型(特别是可能基于宿主类型的值的子集的,如数值类型(@6.14.1) 中的 <integer> )的值的比较也没有特别的处理,而引起 eqv? 和 eql? 的不同。 | |
6364 | +而基于性能等理由,等其它一对多映射的类型(特别是可能基于宿主类型的值的子集的,如 NPLA 数值类型(@6.14.1) 中的 <integer> )的值的比较也没有特别的处理,而引起 eqv? 和 eql? 的不同。 | |
6299 | 6365 | 这些类型可能需要其它针对特定类型的等价谓词(如 =?(@12.2) )进行相等性的比较。 |
6300 | 6366 | **注释** |
6301 | 6367 | 实现中,值数据成员的相等由 ValueObject 的 == 操作定义。这对应 C++ 意义上的对象相等。 |