The YSLib project - main repository
Revisión | 187738900a17fd7873917f3f1eb0a8721a8b5dd3 (tree) |
---|---|
Tiempo | 2022-09-23 21:46:50 |
Autor | FrankHB <frankhb1989@gmai...> |
Commiter | FrankHB |
更新主分支版本: build 956 rev 10 。
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2009-2016, 2019-2020 FrankHB. | |
2 | + © 2009-2016, 2019-2020, 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 Initialization.h |
12 | 12 | \ingroup Helper |
13 | 13 | \brief 框架初始化。 |
14 | -\version r893 | |
14 | +\version r896 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since 早于 build 132 |
17 | 17 | \par 创建时间: |
18 | 18 | 2009-10-21 23:15:08 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-05 09:19 +0800 | |
20 | + 2022-09-23 01:05 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -156,7 +156,7 @@ | ||
156 | 156 | |
157 | 157 | /*! |
158 | 158 | \brief 取值类型根节点。 |
159 | -\pre 断言:已初始化。 | |
159 | +\exception GeneralEvent 异常中立:由 FetchEnvironmnet 抛出。 | |
160 | 160 | \since build 688 |
161 | 161 | */ |
162 | 162 | YF_API ValueNode& |
@@ -172,6 +172,7 @@ | ||
172 | 172 | |
173 | 173 | /*! |
174 | 174 | \brief 取 MIME 类型名和文件扩展名双向映射对象。 |
175 | +\exception GeneralEvent 异常中立:由 FetchEnvironmnet 抛出。 | |
175 | 176 | \since build 450 |
176 | 177 | */ |
177 | 178 | YF_API MIMEBiMapping& |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Configuration.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief 配置设置。 |
14 | -\version r445 | |
14 | +\version r468 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 334 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-08-27 15:15:08 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-09-10 02:11 +0800 | |
20 | + 2022-09-23 01:04 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -30,7 +30,8 @@ | ||
30 | 30 | |
31 | 31 | #include "YModules.h" |
32 | 32 | #include YFM_NPL_NPLA1 // for YSLib::default_allocator, byte, ValueNode, |
33 | -// NoContainer, ystdex::exclude_self_params_t; | |
33 | +// TermNode, ContextState, GlobalState, shared_ptr, Environment, std::istream, | |
34 | +// string_view, ystdex::exclude_self_params_t, NoContainer; | |
34 | 35 | |
35 | 36 | namespace NPL |
36 | 37 | { |
@@ -40,12 +41,30 @@ | ||
40 | 41 | { |
41 | 42 | |
42 | 43 | /*! |
43 | -\brief 加载 NPLA1 翻译单元。 | |
44 | -\throw LoggedEvent 警告:被加载配置中的实体转换失败。 | |
45 | -\since build 955 | |
44 | +\brief 节点加载器。 | |
45 | +\since build 956 | |
46 | 46 | */ |
47 | -YF_API YB_ATTR_nodiscard ValueNode | |
48 | -LoadNode(const TermNode&); | |
47 | +class YF_API NodeLoader | |
48 | +{ | |
49 | +private: | |
50 | + mutable ContextState cs; | |
51 | + | |
52 | +public: | |
53 | + NodeLoader(const GlobalState&); | |
54 | + | |
55 | + YB_ATTR_nodiscard YB_PURE ValueNode | |
56 | + LoadNode(const TermNode&) const; | |
57 | + template<typename _type, | |
58 | + yimpl(typename = ystdex::exclude_self_t<TermNode, _type>)> | |
59 | + YB_ATTR_nodiscard YB_PURE inline ValueNode | |
60 | + LoadNode(_type&& obj) const | |
61 | + { | |
62 | + return LoadNode(cs.Global.get().ReadFrom(GlobalState::LoadOptionTag< | |
63 | + GlobalState::NoSourceInformation>(), yforward(obj), cs)); | |
64 | + } | |
65 | + | |
66 | + DefGetter(const ynothrow, ContextState&, Context, cs) | |
67 | +}; | |
49 | 68 | |
50 | 69 | } // namespace A1; |
51 | 70 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Dependency.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief 依赖管理。 |
14 | -\version r640 | |
14 | +\version r646 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 623 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-08-09 22:12:37 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-09-14 01:32 +0800 | |
20 | + 2022-09-22 20:16 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -29,8 +29,7 @@ | ||
29 | 29 | #define NPL_INC_Dependency_h_ |
30 | 30 | |
31 | 31 | #include "YModules.h" |
32 | -#include YFM_NPL_NPLA1 // for string, vector, GlobalState, YSLib::unique_ptr; | |
33 | -#include <istream> // for std::istream; | |
32 | +#include YFM_NPL_NPLA1 // for string, vector, std::istream, YSLib::unique_ptr; | |
34 | 33 | #include <ystdex/scope_guard.hpp> // for ystdex::guard; |
35 | 34 | |
36 | 35 | namespace NPL |
@@ -185,13 +184,14 @@ | ||
185 | 184 | \brief 加载输入/输出模块。 |
186 | 185 | \pre 断言:第二参数非空。 |
187 | 186 | \note 第二参数指定基础环境。 |
187 | +\since build 956 | |
188 | 188 | |
189 | 189 | 加载输入/输出库操作。 |
190 | 190 | 派生实现依赖模块: |
191 | 191 | 字符串模块 std.strings 。 |
192 | 192 | */ |
193 | 193 | YF_API void |
194 | -LoadModule_std_io(ContextState&, const shared_ptr<Environment>&); | |
194 | +LoadModule_std_io(ContextState&); | |
195 | 195 | |
196 | 196 | /*! |
197 | 197 | \brief 加载系统模块。 |
@@ -208,6 +208,7 @@ | ||
208 | 208 | \brief 加载模块管理模块。 |
209 | 209 | \pre 断言:第二参数非空。 |
210 | 210 | \note 第二参数指定基础环境。 |
211 | +\since build 956 | |
211 | 212 | |
212 | 213 | 加载模块管理操作。 |
213 | 214 | 派生实现依赖模块: |
@@ -217,7 +218,7 @@ | ||
217 | 218 | 系统模块 std.system 。 |
218 | 219 | */ |
219 | 220 | YF_API void |
220 | -LoadModule_std_modules(ContextState&, const shared_ptr<Environment>&); | |
221 | +LoadModule_std_modules(ContextState&); | |
221 | 222 | //@} |
222 | 223 | |
223 | 224 | /*! |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r9807 | |
14 | +\version r9835 | |
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-09-05 08:44 +0800 | |
20 | + 2022-09-17 02:28 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -208,27 +208,6 @@ | ||
208 | 208 | |
209 | 209 | |
210 | 210 | /*! |
211 | -\brief 解析 NPLA 项节点字符串。 | |
212 | -\since build 852 | |
213 | - | |
214 | -以 string 类型访问节点,若失败则结果为空串。 | |
215 | -*/ | |
216 | -YB_ATTR_nodiscard YF_API YB_PURE string | |
217 | -ParseNPLATermString(const TermNode&); | |
218 | - | |
219 | - | |
220 | -/*! | |
221 | -\brief 映射 NPLA 叶节点。 | |
222 | -\return 创建的新节点。 | |
223 | -\sa ParseNPLANodeString | |
224 | -\since build 674 | |
225 | - | |
226 | -创建新节点。若参数为空则返回值为空串的新节点;否则值以 ParseNPLANodeString 取得。 | |
227 | -*/ | |
228 | -YB_ATTR_nodiscard YF_API YB_PURE ValueNode | |
229 | -MapNPLALeafNode(const TermNode&); | |
230 | - | |
231 | -/*! | |
232 | 211 | \brief 变换 NPLA 语法节点为语法分析树的叶节点。 |
233 | 212 | \return 变换得到的节点。 |
234 | 213 | \note 可选参数指定结果名称。 |
@@ -2207,6 +2186,14 @@ | ||
2207 | 2186 | Environment(BindingMap&& m) |
2208 | 2187 | : Bindings(std::move(m)) |
2209 | 2188 | {} |
2189 | + //! \since build 956 | |
2190 | + Environment(const BindingMap& m, allocator_type a) | |
2191 | + : Bindings(m, a) | |
2192 | + {} | |
2193 | + //! \since build 956 | |
2194 | + Environment(BindingMap&& m, allocator_type a) | |
2195 | + : Bindings(std::move(m), a) | |
2196 | + {} | |
2210 | 2197 | //@} |
2211 | 2198 | /*! |
2212 | 2199 | \brief 构造:使用父环境。 |
@@ -3325,6 +3312,10 @@ | ||
3325 | 3312 | |
3326 | 3313 | //! \brief 设置参数指定的父环境弱引用。 |
3327 | 3314 | //@{ |
3315 | +//! \since build 956 | |
3316 | +inline PDefH(void, AssignWeakParent, ValueObject& parent, | |
3317 | + TermNode::allocator_type a, EnvironmentReference r_env) | |
3318 | + ImplExpr(AssignParent(parent, a, std::move(r_env))) | |
3328 | 3319 | inline PDefH(void, AssignWeakParent, ValueObject& parent, |
3329 | 3320 | TermNode::allocator_type a, ContextNode& ctx) |
3330 | 3321 | ImplExpr(AssignParent(parent, a, ctx.WeakenRecord())) |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 公共接口。 |
14 | -\version r10005 | |
14 | +\version r10057 | |
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-09-14 02:53 +0800 | |
20 | + 2022-09-22 20:16 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -50,7 +50,8 @@ | ||
50 | 50 | #include <ystdex/algorithm.hpp> // for ystdex::fast_any_of, ystdex::split; |
51 | 51 | #include <ystdex/cast.hpp> // for ystdex::polymorphic_downcast; |
52 | 52 | #include <ystdex/scope_guard.hpp> // for ystdex::guard; |
53 | -#include <iosfwd> // for std::ostream; | |
53 | +#include <iosfwd> // for std::ostream, std::streambuf; | |
54 | +#include <istream> // for std::istream; | |
54 | 55 | |
55 | 56 | namespace NPL |
56 | 57 | { |
@@ -452,7 +453,7 @@ | ||
452 | 453 | 支持重规约。异步重规约由 ContextNode 支持。 |
453 | 454 | 此处约定的迭代中对节点的具体结构分类默认也适用于其它 NPLA1 实现 API ; |
454 | 455 | 例外情况应单独指定明确的顺序。 |
455 | - 例外情况包括输入节点不是表达式语义结构(而是 AST )的 API ,如 TransformNode 。 | |
456 | + 例外情况包括输入节点不是表达式语义结构(而是 AST )的 API 。 | |
456 | 457 | 规约结果由以下规则确定: |
457 | 458 | 对异步规约,返回 Reduction::Partial ; |
458 | 459 | 否则,对枝节点,返回被调用的规约遍的求值结果; |
@@ -745,43 +746,6 @@ | ||
745 | 746 | |
746 | 747 | |
747 | 748 | /*! |
748 | -\brief 插入 NPLA1 子节点。 | |
749 | -\note 插入后按名称排序顺序。 | |
750 | -\since build 852 | |
751 | - | |
752 | -第一参数指定的变换结果插入第二参数指定的容器。 | |
753 | -若映射操作返回节点名称为空则根据当前容器内子节点数量加前缀 $ 命名以避免重复。 | |
754 | -*/ | |
755 | -YF_API void | |
756 | -InsertChild(ValueNode&&, ValueNode::Container&); | |
757 | - | |
758 | -/*! | |
759 | -\brief 变换 NPLA1 节点 S 表达式抽象语法树为 NPLA1 语义结构。 | |
760 | -\exception std::bad_function_call 第三至五参数为空。 | |
761 | -\return 变换后的新节点(及子节点)。 | |
762 | -\sa InsertChild | |
763 | -\sa MapNPLALeafNode | |
764 | -\sa ParseNPLATermString | |
765 | -\since build 897 | |
766 | - | |
767 | -第一参数指定源节点,其余参数指定部分变换规则。 | |
768 | -当被调用的第三参数不修改传入的节点参数时变换不修改源节点。 | |
769 | -过程如下: | |
770 | -若源节点为叶节点,直接返回使用 MapNPLALeafNode 创建映射的节点。 | |
771 | -若源节点只有一个子节点,直接返回这个子节点的变换结果。 | |
772 | -否则,使用 ParseNPLATermString 从第一个子节点取作为变换结果名称的字符串。 | |
773 | - 若名称非空则忽略第一个子节点,只变换剩余子节点。 | |
774 | - 当剩余一个子节点(即源节点有两个子节点)时,直接递归变换这个节点并返回。 | |
775 | - 若变换后的结果名称非空,则作为结果的值;否则,结果作为容器内单一的值。 | |
776 | - 否则,新建节点容器,遍历并变换剩余的节点插入其中,返回以之构造的节点。 | |
777 | - 调用 InsertChild 插入映射的结果到容器。 | |
778 | -子节点的映射操作使用递归 TransformNode 调用。 | |
779 | -*/ | |
780 | -YF_API ValueNode | |
781 | -TransformNode(const TermNode&); | |
782 | - | |
783 | - | |
784 | -/*! | |
785 | 749 | \ingroup functors |
786 | 750 | \brief 中缀分隔符变换器。 |
787 | 751 | \since build 881 |
@@ -2172,16 +2136,26 @@ | ||
2172 | 2136 | /*! |
2173 | 2137 | \sa ListTermPreprocess |
2174 | 2138 | \sa SetupDefaultInterpretation |
2139 | + \since build 566 | |
2175 | 2140 | */ |
2176 | 2141 | //@{ |
2177 | - /*! | |
2178 | - \brief 构造:使用默认解释、指定的存储资源和默认的叶节点词素转换器。 | |
2179 | - \sa ParseLeaf | |
2180 | - */ | |
2181 | - GlobalState(pmr::memory_resource& = NPL::Deref(pmr::new_delete_resource())); | |
2142 | + //! \sa ParseLeaf | |
2143 | + //@{ | |
2144 | + //! \brief 构造:使用默认解释、指定的分配器和默认的叶节点词素转换器。 | |
2145 | + GlobalState(TermNode::allocator_type a = {}); | |
2146 | + //! \brief 构造:使用默认解释、指定的存储资源和默认的叶节点词素转换器。 | |
2147 | + GlobalState(pmr::memory_resource& rsrc) | |
2148 | + : GlobalState(TermNode::allocator_type(&rsrc)) | |
2149 | + {} | |
2150 | + //@} | |
2151 | + //! \brief 构造:使用默认解释、指定的分配器和叶节点词素转换器。 | |
2152 | + GlobalState(Tokenizer, SourcedTokenizer, TermNode::allocator_type a = {}); | |
2182 | 2153 | //! \brief 构造:使用默认解释、指定的存储资源和叶节点词素转换器。 |
2183 | - GlobalState(Tokenizer, SourcedTokenizer, | |
2184 | - pmr::memory_resource& = NPL::Deref(pmr::new_delete_resource())); | |
2154 | + GlobalState(Tokenizer leaf_conv, | |
2155 | + SourcedTokenizer sourced_leaf_conv, pmr::memory_resource& rsrc) | |
2156 | + : GlobalState(std::move(leaf_conv), std::move(sourced_leaf_conv), | |
2157 | + TermNode::allocator_type(&rsrc)) | |
2158 | + {} | |
2185 | 2159 | //@} |
2186 | 2160 | |
2187 | 2161 | /*! |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2013-2016, 2019-2020 FrankHB. | |
2 | + © 2013-2016, 2019-2020, 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 Loader.h |
12 | 12 | \ingroup UI |
13 | 13 | \brief 动态 GUI 加载。 |
14 | -\version r676 | |
14 | +\version r684 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 433 |
17 | 17 | \par 创建时间: |
18 | 18 | 2013-08-01 20:37:16 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-04-07 00:20 +0800 | |
20 | + 2022-09-22 23:33 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -32,6 +32,7 @@ | ||
32 | 32 | #include YFM_YSLib_UI_YUIContainer |
33 | 33 | #include YFM_YSLib_Core_ValueNode |
34 | 34 | #include <ystdex/cast.hpp> // for ystdex::polymorphic_downcast; |
35 | +#include <ystdex/function.hpp> // for ystdex::unchecked_function; | |
35 | 36 | |
36 | 37 | namespace YSLib |
37 | 38 | { |
@@ -236,6 +237,8 @@ | ||
236 | 237 | class YF_API WidgetLoader |
237 | 238 | { |
238 | 239 | public: |
240 | + //! \since build 956 | |
241 | + ystdex::unchecked_function<ValueNode(string_view)> Convert; | |
239 | 242 | GWidgetRegister<> Default{}; |
240 | 243 | GWidgetRegister<const Rect&> Bounds{}; |
241 | 244 | //! \since build 495 |
@@ -243,6 +246,11 @@ | ||
243 | 246 | //! \since build 555 |
244 | 247 | GWidgetInserterRegister<IWidget&, const ZOrder&> InsertZOrdered{}; |
245 | 248 | |
249 | + //! \since build 956 | |
250 | + WidgetLoader(ystdex::unchecked_function<ValueNode(string_view)> conv) | |
251 | + : Convert(std::move(conv)) | |
252 | + {} | |
253 | + | |
246 | 254 | //! \since build 888 |
247 | 255 | //@{ |
248 | 256 | //! \exception std::out_of_range 异常中立:找不到内部类型节点。 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Environment.cpp |
12 | 12 | \ingroup Helper |
13 | 13 | \brief 环境。 |
14 | -\version r2001 | |
14 | +\version r2004 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 379 |
17 | 17 | \par 创建时间: |
18 | 18 | 2013-02-08 01:27:29 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-09-14 01:34 +0800 | |
20 | + 2022-09-22 00:20 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -59,8 +59,8 @@ | ||
59 | 59 | #endif |
60 | 60 | |
61 | 61 | Environment::Environment(Application& app) |
62 | - : Root(app.get_allocator()), DefaultOutputStream(string( | |
63 | - app.get_allocator())), Global(*app.get_allocator().resource()) | |
62 | + : Root(app.get_allocator()), DefaultOutputStream( | |
63 | + string(app.get_allocator())), Global(app.get_allocator()) | |
64 | 64 | { |
65 | 65 | #if !YF_Hosted |
66 | 66 | // NOTE: This only effects freestanding implementations now, which may need |
@@ -153,6 +153,7 @@ | ||
153 | 153 | # endif |
154 | 154 | ); |
155 | 155 | NPL::A1::Forms::LoadStandardContext(Main); |
156 | + Main.GetRecordRef().Frozen = true; | |
156 | 157 | }, yfsig, " NPLA1 Failure ", |
157 | 158 | " An unexpected error occurs \n" |
158 | 159 | " during the initializaiton.\n"); |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Initialization.cpp |
12 | 12 | \ingroup Helper |
13 | 13 | \brief 框架初始化。 |
14 | -\version r3959 | |
14 | +\version r3970 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since 早于 build 132 |
17 | 17 | \par 创建时间: |
18 | 18 | 2009-10-21 23:15:08 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-01-31 20:02 +0800 | |
20 | + 2022-09-23 01:04 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -41,8 +41,7 @@ | ||
41 | 41 | // platform_ex::WCSToUTF8, platform_ex::UTF8ToWCS; |
42 | 42 | #endif |
43 | 43 | #include YFM_CHRLib_MappingEx // for CHRLib::cp113_lkp; |
44 | -#include YFM_NPL_Configuration // for NPL::Configuration, NPL::Session, | |
45 | -// A1::LoadNode; | |
44 | +#include YFM_NPL_Configuration // for NPL::Configuration, A1::NodeLoader; | |
46 | 45 | #include YFM_YSLib_Service_TextFile // for Text::BOM_UTF_8, Text::CheckBOM; |
47 | 46 | #include <ystdex/string.hpp> // for ystdex::write_literal, ystdex::sfmt; |
48 | 47 | #include <cerrno> // for errno; |
@@ -410,10 +409,10 @@ | ||
410 | 409 | yunused(disp); |
411 | 410 | if(show_info) |
412 | 411 | YTraceDe(Notice, "Found %s '%s'.", Nonnull(disp), path); |
413 | - // XXX: Race condition may cause failure, though file would not be | |
414 | - // corrupted now. | |
412 | + // XXX: Race condition may cause failure, though file would not be corrupted | |
413 | + // now. | |
415 | 414 | // XXX: Exception thrown here would be caught by %TryInvoke in the call to |
416 | - // %LoadNPLA1FileVec or %LoadNPLA1File, so there is no need to attatch the | |
415 | + // %LoadNPLA1FileVec or %LoadNPLA1File, so there is no need to attach the | |
417 | 416 | // additional filename information here. |
418 | 417 | if(SharedInputMappedFileStream sifs{path}) |
419 | 418 | { |
@@ -831,9 +830,8 @@ | ||
831 | 830 | return make_unique<Drawing::FontCache>(); |
832 | 831 | }, [](ValueNode& node, unique_ptr<Drawing::FontCache>& locked) |
833 | 832 | -> Drawing::FontCache&{ |
834 | - InitializeSystemFontCache(*locked, | |
835 | - AccessChild<string>(node, "FontFile"), | |
836 | - AccessChild<string>(node, "FontDirectory")); | |
833 | + InitializeSystemFontCache(*locked, AccessChild<string>(node, | |
834 | + "FontFile"), AccessChild<string>(node, "FontDirectory")); | |
837 | 835 | return *locked.get(); |
838 | 836 | }); |
839 | 837 | } |
@@ -846,10 +844,8 @@ | ||
846 | 844 | }, [](ValueNode& node, MIMEBiMapping& locked) -> MIMEBiMapping&{ |
847 | 845 | AddMIMEItems(locked, LoadNPLA1File("MIME database", (AccessChild<string> |
848 | 846 | (node, "DataDirectory") + "MIMEExtMap.txt").c_str(), []{ |
849 | - NPL::Session sess{}; | |
850 | - | |
851 | - return A1::LoadNode( | |
852 | - SContext::Analyze(sess, sess.Process(TU_MIME))); | |
847 | + return | |
848 | + A1::NodeLoader(FetchEnvironment().Global).LoadNode(TU_MIME); | |
853 | 849 | }, true)); |
854 | 850 | return locked; |
855 | 851 | }); |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Configuration.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief 配置设置。 |
14 | -\version r981 | |
14 | +\version r1048 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 334 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-08-27 15:15:06 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-09-10 02:11 +0800 | |
20 | + 2022-09-23 02:20 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -26,25 +26,94 @@ | ||
26 | 26 | |
27 | 27 | |
28 | 28 | #include "NPL/YModules.h" |
29 | -#include YFM_NPL_Configuration // for PrintNode, LiteralizeEscapeNodeLiteral; | |
30 | -#include YFM_NPL_SContext // for Session, SContext::Analyze; | |
31 | -#include <iterator> // for std::istreambuf_iterator; | |
29 | +#include YFM_NPL_Configuration // for ystdex::value_or, AccessPtr, string, | |
30 | +// ystdex::quote, YSLib::AsNode, Deliteralize, PrintNode, | |
31 | +// LiteralizeEscapeNodeLiteral; | |
32 | +#include YFM_NPL_NPLA1Forms // for A1, Forms, RegisterStrict; | |
33 | +#include YFM_NPL_Dependency // for LoadGroundContext; | |
32 | 34 | #include <ystdex/ios.hpp> // for ystdex::rethrow_badstate, |
33 | 35 | // std::ios_base::failbit; |
34 | 36 | |
35 | 37 | namespace NPL |
36 | 38 | { |
37 | 39 | |
40 | +//! \since build 956 | |
41 | +namespace | |
42 | +{ | |
43 | + | |
44 | +YB_ATTR_nodiscard YB_PURE inline string | |
45 | +ParseNPLATermName(const TermNode& term) | |
46 | +{ | |
47 | + if(const auto p = AccessPtr<string>(term)) | |
48 | + return ystdex::quote(*p); | |
49 | + return ystdex::value_or(AccessPtr<TokenValue>(term)); | |
50 | +} | |
51 | + | |
52 | +YB_ATTR_nodiscard YB_PURE ValueNode | |
53 | +TransformNode(const TermNode& term) | |
54 | +{ | |
55 | + auto s(term.size()); | |
56 | + const ValueNode::allocator_type a(term.get_allocator()); | |
57 | + | |
58 | + if(s == 0) | |
59 | + return YSLib::AsNode(a, string(), | |
60 | + string(Deliteralize(ystdex::value_or(AccessPtr<string>(term))))); | |
61 | + | |
62 | + auto i(term.begin()); | |
63 | + | |
64 | + if(s == 1) | |
65 | + return TransformNode(*i); | |
66 | + | |
67 | + const auto& name(ParseNPLATermName(*i)); | |
68 | + | |
69 | + if(!name.empty()) | |
70 | + yunseq(++i, --s); | |
71 | + if(s == 1) | |
72 | + { | |
73 | + auto&& nd(TransformNode(*i)); | |
74 | + | |
75 | + if(nd.GetName().empty()) | |
76 | + return YSLib::AsNode(a, name, std::move(nd.Value)); | |
77 | + | |
78 | + ValueNode::Container node_con(a); | |
79 | + | |
80 | + node_con.insert(std::move(nd)); | |
81 | + return {ValueNode::Container(std::move(node_con), a), name}; | |
82 | + } | |
83 | + | |
84 | + ValueNode::Container node_con(a); | |
85 | + | |
86 | + std::for_each(i, term.end(), [&](const TermNode& tm){ | |
87 | + auto&& node(TransformNode(tm)); | |
88 | + | |
89 | + node_con.insert(node.GetName().empty() ? YSLib::AsNode( | |
90 | + node.get_allocator(), '$' + MakeIndex(node_con.size()), | |
91 | + std::move(node.Value)) : std::move(node)); | |
92 | + }); | |
93 | + return {std::allocator_arg, a, std::move(node_con), name}; | |
94 | +} | |
95 | + | |
96 | +} // unnamed namespace; | |
97 | + | |
38 | 98 | namespace A1 |
39 | 99 | { |
40 | 100 | |
101 | +NodeLoader::NodeLoader(const GlobalState& global) | |
102 | + : cs(global) | |
103 | +{} | |
104 | + | |
41 | 105 | ValueNode |
42 | -LoadNode(const TermNode& tree) | |
106 | +NodeLoader::LoadNode(const TermNode& tree) const | |
43 | 107 | { |
44 | - TryRet(A1::TransformNode(tree)) | |
45 | - CatchThrow(bad_any_cast& e, LoggedEvent(YSLib::sfmt( | |
46 | - "Bad NPLA1 tree found: cast failed from [%s] to [%s] .", e.from(), | |
47 | - e.to()), YSLib::Warning)) | |
108 | + TryRet(TransformNode(tree)) | |
109 | + CatchThrow(bad_any_cast& e, LoggedEvent(YSLib::sfmt("Bad NPLA1 tree found:" | |
110 | + " cast failed from [%s] to [%s] .", e.from(), e.to()), YSLib::Warning)) | |
111 | + catch(std::exception& e) | |
112 | + { | |
113 | + YTraceDe(YSLib::Err, "Bad NPLA1 tree found: [%s]%s", | |
114 | + typeid(e).name(), e.what()); | |
115 | + throw; | |
116 | + } | |
48 | 117 | } |
49 | 118 | |
50 | 119 | } // namespace A1; |
@@ -59,13 +128,8 @@ | ||
59 | 128 | std::istream& |
60 | 129 | operator>>(std::istream& is, Configuration& conf) |
61 | 130 | { |
62 | - using sb_it_t = std::istreambuf_iterator<char>; | |
63 | - // TODO: Validate for S-expression? | |
64 | - const auto a(conf.get_allocator()); | |
65 | - Session sess(a); | |
66 | - | |
67 | - TryExpr(conf.root = A1::LoadNode(SContext::Analyze(std::allocator_arg, a, | |
68 | - sess, sess.Process(sb_it_t(is), sb_it_t{})))) | |
131 | + TryExpr(conf.root | |
132 | + = A1::NodeLoader(A1::GlobalState(conf.get_allocator())).LoadNode(is)) | |
69 | 133 | CatchExpr(..., ystdex::rethrow_badstate(is, std::ios_base::failbit)) |
70 | 134 | return is; |
71 | 135 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Dependency.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief 依赖管理。 |
14 | -\version r7359 | |
14 | +\version r7396 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 623 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-08-09 22:14:45 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-09-14 01:45 +0800 | |
20 | + 2022-09-17 23:01 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -1401,10 +1401,9 @@ | ||
1401 | 1401 | LoadStandardDerived(ContextState& cs) |
1402 | 1402 | { |
1403 | 1403 | #if NPL_Impl_NPLA1_Native_Forms |
1404 | - auto& renv(cs.GetRecordRef()); | |
1405 | - | |
1406 | - RegisterUnary<Strict, const TokenValue>(renv, "ensigil", Ensigil); | |
1407 | - RegisterForm(renv, "$binds1?", [](TermNode& term, ContextNode& ctx){ | |
1404 | + // XXX: Using %cs instead of 'renv' is occasionally more efficient. | |
1405 | + RegisterUnary<Strict, const TokenValue>(cs, "ensigil", Ensigil); | |
1406 | + RegisterForm(cs, "$binds1?", [](TermNode& term, ContextNode& ctx){ | |
1408 | 1407 | RetainN(term, 2); |
1409 | 1408 | |
1410 | 1409 | auto i(term.begin()); |
@@ -1466,13 +1465,11 @@ | ||
1466 | 1465 | void |
1467 | 1466 | Load(ContextState& cs) |
1468 | 1467 | { |
1469 | - auto& renv(cs.GetRecordRef()); | |
1470 | - | |
1471 | -// LoadObjects(renv); | |
1468 | +// LoadObjects(cs.GetRecordRef()); | |
1472 | 1469 | Primitive::Load(cs); |
1473 | 1470 | Derived::Load(cs); |
1474 | 1471 | // NOTE: Prevent the ground environment from modification. |
1475 | - renv.Frozen = true; | |
1472 | + cs.GetRecordRef().Frozen = true; | |
1476 | 1473 | } |
1477 | 1474 | |
1478 | 1475 | } // namespace Ground; |
@@ -2047,11 +2044,8 @@ | ||
2047 | 2044 | } |
2048 | 2045 | |
2049 | 2046 | void |
2050 | -LoadModule_std_io(ContextState& cs, | |
2051 | - const shared_ptr<Environment>& p_ground) | |
2047 | +LoadModule_std_io(ContextState& cs) | |
2052 | 2048 | { |
2053 | - YAssertNonnull(p_ground); | |
2054 | - | |
2055 | 2049 | auto& renv(cs.GetRecordRef()); |
2056 | 2050 | |
2057 | 2051 | RegisterUnary<Strict, const string>(renv, "readable-file?", |
@@ -2142,9 +2136,8 @@ | ||
2142 | 2136 | YAssert(false, "Invalid state found."); |
2143 | 2137 | } |
2144 | 2138 | ThrowInvalidSyntaxError("Syntax error in get-module."); |
2145 | - }, std::placeholders::_2, EnvironmentReference(p_ground))); | |
2139 | + }, std::placeholders::_2, cs.WeakenRecord())); | |
2146 | 2140 | #else |
2147 | - yunused(p_ground); | |
2148 | 2141 | cs.ShareCurrentSource("<lib:std.io-1>"); |
2149 | 2142 | A1::Perform(cs, R"NPL( |
2150 | 2143 | $defl! get-module (&filename .&opt) |
@@ -2225,11 +2218,8 @@ | ||
2225 | 2218 | } |
2226 | 2219 | |
2227 | 2220 | void |
2228 | -LoadModule_std_modules(ContextState& cs, | |
2229 | - const shared_ptr<Environment>& p_ground) | |
2221 | +LoadModule_std_modules(ContextState& cs) | |
2230 | 2222 | { |
2231 | - YAssertNonnull(p_ground); | |
2232 | - | |
2233 | 2223 | #if NPL_Impl_NPLA1_Native_Forms |
2234 | 2224 | using namespace std::placeholders; |
2235 | 2225 | using YSLib::to_std_string; |
@@ -2287,14 +2277,14 @@ | ||
2287 | 2277 | ystdex::emplace_hint_in_place(registry, pr.first, req, |
2288 | 2278 | std::piecewise_construct, NPL::tuple<>(), |
2289 | 2279 | NPL::forward_as_tuple([&]{ |
2290 | - return CreateEnvironmentWithParent(term.get_allocator(), | |
2291 | - r_ground); | |
2280 | + return | |
2281 | + CreateEnvironmentWithParent(term.get_allocator(), r_ground); | |
2292 | 2282 | }()))->second.second); |
2293 | 2283 | return ReductionStatus::Clean; |
2294 | 2284 | } |
2295 | 2285 | throw NPLException("Requirement '" + to_std_string(req) |
2296 | 2286 | + "' is already registered."); |
2297 | - }, EnvironmentReference(p_ground))); | |
2287 | + }, cs.WeakenRecord())); | |
2298 | 2288 | RegisterUnary<Strict, const string>(renv, "unregister-requirement!", |
2299 | 2289 | trivial_swap, [&](const string& req){ |
2300 | 2290 | CheckRequirement(req); |
@@ -2380,9 +2370,8 @@ | ||
2380 | 2370 | ThrowInvalidSyntaxError("Syntax error in require."); |
2381 | 2371 | } |
2382 | 2372 | return reduce_to_res(pr.first->second.first); |
2383 | - }, _2, EnvironmentReference(p_ground))); | |
2373 | + }, _2, cs.WeakenRecord())); | |
2384 | 2374 | #else |
2385 | - yunused(p_ground); | |
2386 | 2375 | context.ShareCurrentSource("<lib:std.modules>"); |
2387 | 2376 | // XXX: Thread-safety is not respected currently. |
2388 | 2377 | context.Perform(R"NPL( |
@@ -2677,26 +2666,18 @@ | ||
2677 | 2666 | LoadStandardContext(ContextState& cs) |
2678 | 2667 | { |
2679 | 2668 | LoadGroundContext(cs); |
2680 | - | |
2681 | - const auto pfx("std."); | |
2682 | - string mod(pfx, cs.get_allocator()); | |
2683 | - const auto load_std_module( | |
2684 | - [&](string_view module_name, void(&load_module)(ContextState&)){ | |
2685 | - // XXX: Using allocator of the state or %std::string are both a bit less | |
2686 | - // efficient. | |
2687 | - mod += module_name; | |
2688 | - LoadModuleChecked(cs, mod, load_module, cs); | |
2689 | - mod.resize(ystdex::string_length(pfx)); | |
2690 | - }); | |
2691 | - const auto p_ground(cs.ShareRecord()); | |
2692 | - | |
2693 | - load_std_module("continuations", LoadModule_std_continuations), | |
2694 | - load_std_module("promises", LoadModule_std_promises); | |
2695 | - load_std_module("math", LoadModule_std_math), | |
2696 | - load_std_module("strings", LoadModule_std_strings); | |
2697 | - LoadModuleChecked(cs, "std.io", LoadModule_std_io, cs, p_ground); | |
2698 | - load_std_module("system", LoadModule_std_system); | |
2699 | - LoadModuleChecked(cs, "std.modules", LoadModule_std_modules, cs, p_ground); | |
2669 | + // XXX: A lambda-expression is OK and the generated code can be equally | |
2670 | + // efficient, but not succinct as using macro in the invocation sites. | |
2671 | +#define NPL_Impl_LoadStd(_name) \ | |
2672 | + LoadModuleChecked(cs, "std." #_name, LoadModule_std_##_name, cs) | |
2673 | + NPL_Impl_LoadStd(continuations), | |
2674 | + NPL_Impl_LoadStd(promises); | |
2675 | + NPL_Impl_LoadStd(math), | |
2676 | + NPL_Impl_LoadStd(strings); | |
2677 | + NPL_Impl_LoadStd(io); | |
2678 | + NPL_Impl_LoadStd(system); | |
2679 | + NPL_Impl_LoadStd(modules); | |
2680 | +#undef NPL_Impl_LoadStd | |
2700 | 2681 | } |
2701 | 2682 | |
2702 | 2683 | } // namespace Forms; |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r4202 | |
14 | +\version r4213 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 663 |
17 | 17 | \par 创建时间: |
18 | 18 | 2016-01-07 10:32:45 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-08-21 23:32 +0800 | |
20 | + 2022-09-23 01:05 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -137,19 +137,6 @@ | ||
137 | 137 | } |
138 | 138 | |
139 | 139 | |
140 | -string | |
141 | -ParseNPLATermString(const TermNode& term) | |
142 | -{ | |
143 | - return ystdex::value_or(AccessPtr<string>(term)); | |
144 | -} | |
145 | - | |
146 | -ValueNode | |
147 | -MapNPLALeafNode(const TermNode& term) | |
148 | -{ | |
149 | - return YSLib::AsNode(ValueNode::allocator_type(term.get_allocator()), | |
150 | - string(), string(Deliteralize(ParseNPLATermString(term)))); | |
151 | -} | |
152 | - | |
153 | 140 | TermNode |
154 | 141 | TransformToSyntaxNode(ValueNode&& node) |
155 | 142 | { |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 公共接口。 |
14 | -\version r23927 | |
14 | +\version r23965 | |
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-09-14 02:53 +0800 | |
20 | + 2022-09-21 23:46 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -1930,51 +1930,6 @@ | ||
1930 | 1930 | |
1931 | 1931 | |
1932 | 1932 | void |
1933 | -InsertChild(ValueNode&& node, ValueNode::Container& con) | |
1934 | -{ | |
1935 | - con.insert(node.GetName().empty() ? YSLib::AsNode(node.get_allocator(), | |
1936 | - '$' + MakeIndex(con.size()), std::move(node.Value)) : std::move(node)); | |
1937 | -} | |
1938 | - | |
1939 | -ValueNode | |
1940 | -TransformNode(const TermNode& term) | |
1941 | -{ | |
1942 | - auto s(term.size()); | |
1943 | - | |
1944 | - if(s == 0) | |
1945 | - return MapNPLALeafNode(term); | |
1946 | - | |
1947 | - auto i(term.begin()); | |
1948 | - | |
1949 | - if(s == 1) | |
1950 | - return TransformNode(*i); | |
1951 | - | |
1952 | - const auto& name(ParseNPLATermString(*i)); | |
1953 | - | |
1954 | - if(!name.empty()) | |
1955 | - yunseq(++i, --s); | |
1956 | - if(s == 1) | |
1957 | - { | |
1958 | - auto&& nd(TransformNode(*i)); | |
1959 | - | |
1960 | - if(nd.GetName().empty()) | |
1961 | - return YSLib::AsNode(ValueNode::allocator_type( | |
1962 | - term.get_allocator()), name, std::move(nd.Value)); | |
1963 | - return | |
1964 | - {ValueNode::Container({std::move(nd)}, term.get_allocator()), name}; | |
1965 | - } | |
1966 | - | |
1967 | - ValueNode::Container node_con; | |
1968 | - | |
1969 | - std::for_each(i, term.end(), [&](const TermNode& tm){ | |
1970 | - InsertChild(TransformNode(tm), node_con); | |
1971 | - }); | |
1972 | - return | |
1973 | - {std::allocator_arg, term.get_allocator(), std::move(node_con), name}; | |
1974 | -} | |
1975 | - | |
1976 | - | |
1977 | -void | |
1978 | 1933 | ParseLeaf(TermNode& term, string_view id) |
1979 | 1934 | { |
1980 | 1935 | YAssertNonnull(id.data()); |
@@ -2746,7 +2701,7 @@ | ||
2746 | 2701 | } |
2747 | 2702 | |
2748 | 2703 | |
2749 | -GlobalState::GlobalState(pmr::memory_resource& rsrc) | |
2704 | +GlobalState::GlobalState(TermNode::allocator_type a) | |
2750 | 2705 | : GlobalState([this](const GParsedValue<ByteParser>& str){ |
2751 | 2706 | TermNode term(Allocator); |
2752 | 2707 | const auto id(YSLib::make_string_view(str)); |
@@ -2763,11 +2718,11 @@ | ||
2763 | 2718 | ParseLeafWithSourceInformation(term, id, cs.CurrentSource, |
2764 | 2719 | val.first); |
2765 | 2720 | return term; |
2766 | - }, rsrc) | |
2721 | + }, a) | |
2767 | 2722 | {} |
2768 | 2723 | GlobalState::GlobalState(Tokenizer leaf_conv, |
2769 | - SourcedTokenizer sourced_leaf_conv, pmr::memory_resource& rsrc) | |
2770 | - : Allocator(&rsrc), Preprocess(SeparatorPass(Allocator)), | |
2724 | + SourcedTokenizer sourced_leaf_conv, TermNode::allocator_type a) | |
2725 | + : Allocator(a), Preprocess(SeparatorPass(Allocator)), | |
2771 | 2726 | ConvertLeaf(std::move(leaf_conv)), |
2772 | 2727 | ConvertLeafSourced(std::move(sourced_leaf_conv)) |
2773 | 2728 | { |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2013-2016, 2018-2021 FrankHB. | |
2 | + © 2013-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 Loader.cpp |
12 | 12 | \ingroup UI |
13 | 13 | \brief 动态 GUI 加载。 |
14 | -\version r383 | |
14 | +\version r395 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 433 |
17 | 17 | \par 创建时间: |
18 | 18 | 2013-08-01 20:39:49 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2021-12-24 23:56 +0800 | |
20 | + 2022-09-22 23:36 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -26,11 +26,10 @@ | ||
26 | 26 | |
27 | 27 | |
28 | 28 | #include "YSLib/UI/YModules.h" |
29 | -#include "NPL/YModules.h" | |
30 | -#include YFM_YSLib_UI_Loader // for to_std_string, istringtream; | |
29 | +#include YFM_YSLib_UI_Loader // for to_std_string, istringtream, | |
30 | +// std::allocator_arg, shared_ptr; | |
31 | 31 | #include <sstream> // for complete istringtream; |
32 | -#include YFM_YSLib_UI_YPanel | |
33 | -#include YFM_NPL_Configuration // for NPL, Session, A1::LoadNode; | |
32 | +#include <limits> // for std::numeric_limits; | |
34 | 33 | |
35 | 34 | namespace YSLib |
36 | 35 | { |
@@ -53,6 +52,7 @@ | ||
53 | 52 | catch(std::exception& e) |
54 | 53 | { |
55 | 54 | YTraceDe(Warning, "Error: %s", e.what()); |
55 | + YTraceDe(Informative, "The string is: '%s'.", str.c_str()); | |
56 | 56 | throw std::invalid_argument("Parse 'Rect' failed: bad state."); |
57 | 57 | } |
58 | 58 | YTraceDe(Debug, "ParseRect: %s.", to_string(res).c_str()); |
@@ -96,11 +96,7 @@ | ||
96 | 96 | ValueNode |
97 | 97 | WidgetLoader::LoadUILayout(string_view sv) const |
98 | 98 | { |
99 | - using namespace NPL; | |
100 | - Session sess{}; | |
101 | - | |
102 | - return TransformUILayout( | |
103 | - A1::LoadNode(SContext::Analyze(sess, sess.Process(sv)))); | |
99 | + return TransformUILayout(Convert(sv)); | |
104 | 100 | } |
105 | 101 | |
106 | 102 | ValueNode |
@@ -137,8 +133,7 @@ | ||
137 | 133 | const auto |
138 | 134 | r(std::stoul(to_std_string(*p_z))); |
139 | 135 | |
140 | - // TODO: Do not use magic number. | |
141 | - if(r < 0x100) | |
136 | + if(r <= std::numeric_limits<ZOrder>::max()) | |
142 | 137 | z = r; |
143 | 138 | } |
144 | 139 | CatchIgnore(std::invalid_argument&) |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Shells.cpp |
12 | 12 | \ingroup YReader |
13 | 13 | \brief Shell 框架逻辑。 |
14 | -\version r6556 | |
14 | +\version r6565 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since 早于 build 132 |
17 | 17 | \par 创建时间: |
18 | 18 | 2010-03-06 21:38:16 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-09-14 03:06 +0800 | |
20 | + 2022-09-23 00:37 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -25,11 +25,13 @@ | ||
25 | 25 | */ |
26 | 26 | |
27 | 27 | |
28 | -#include "Shells.h" // for std::throw_with_nested; | |
28 | +#include "Shells.h" // for std::throw_with_nested, make_shared, | |
29 | +// FetchEnvironment; | |
29 | 30 | #include "ShlExplorer.h" |
30 | 31 | #include "ShlReader.h" |
31 | -#include <ytest/timing.hpp> | |
32 | -#include YFM_NPL_Dependency // for NPL, A1::Forms::InvokeIn; | |
32 | +#include <ytest/timing.hpp> // for ytest::timing::once; | |
33 | +#include YFM_NPL_Configuration // for NPL::A1::NodeLoader, ystdex::trivial_swap, | |
34 | +// std::bind, string_view, std::placeholders::_1; | |
33 | 35 | #include YFM_Helper_Environment // for complete Environment; |
34 | 36 | |
35 | 37 | namespace YReader |
@@ -126,7 +128,10 @@ | ||
126 | 128 | WidgetLoader& |
127 | 129 | FetchWidgetLoader() |
128 | 130 | { |
129 | - static WidgetLoader wgt_ldr; | |
131 | + static const NPL::A1::NodeLoader loader(FetchEnvironment().Global); | |
132 | + static WidgetLoader wgt_ldr(decltype(WidgetLoader::Convert)( | |
133 | + ystdex::trivial_swap, std::bind(&NPL::A1::NodeLoader::LoadNode< | |
134 | + string_view>, &loader, std::placeholders::_1))); | |
130 | 135 | static const struct Init |
131 | 136 | { |
132 | 137 | Init() |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file ChangeLog.V0.9.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 版本更新历史记录 - V0.9 。 |
14 | -\version r11547 | |
14 | +\version r11673 | |
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-09-14 04:19 +0800 | |
20 | + 2022-09-23 18:50 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -32,6 +32,133 @@ | ||
32 | 32 | |
33 | 33 | $now |
34 | 34 | ( |
35 | + / %YFramework $= | |
36 | + ( | |
37 | + / %YSLib $= | |
38 | + ( | |
39 | + / %UI.Loader $= | |
40 | + ( | |
41 | + + "tracing of the string value with level %Informative after \ | |
42 | + the warning message on failure" @ "function %ParseRect", | |
43 | + / @ "class %WidgetLoader" $= | |
44 | + ( | |
45 | + / DLDI "avoided the use of magic number" | |
46 | + @ "function %TransformUILayout", | |
47 | + ( | |
48 | + + "data member %Convert"; | |
49 | + + "constructor", | |
50 | + / DLI "simplified function %LoadUILayout" ^ "%Convert" | |
51 | + ~ "%NPL" | |
52 | + ) | |
53 | + ), | |
54 | + ), | |
55 | + / "parameter type 'const shared_ptr<Shell>&'" @ "function %Activate" | |
56 | + @ %Core.YApplication -> 'shared_ptr<Shell>' | |
57 | + ), | |
58 | + / "parameter type 'const shared_ptr<Shell>&'" @ "function %NowShellTo" | |
59 | + @ %Helper.ShellHelper -> 'shared_ptr<Shell>', | |
60 | + // As in %YSLib.Core.YApplication. | |
61 | + / %NPL $= | |
62 | + ( | |
63 | + / %Dependency $= | |
64 | + ( | |
65 | + ( | |
66 | + / @ "functions %(LoadModule_std_io, LoadModule_std_modules)" $= | |
67 | + ( | |
68 | + / DLI "simplified" !^ "2nd argument"; | |
69 | + - $revert(b942) "2nd parameter" | |
70 | + ); | |
71 | + / $forced $revert(b942) DLI | |
72 | + "simplified function %LoadStandardContext", | |
73 | + ), | |
74 | + / DLI "several target" @ "function %LoadGroundContext" ^ 'cs' | |
75 | + ~ 'renv', | |
76 | + // Only in a few cases it would be more efficient. | |
77 | + / DLDI ^ 'ynothrow' @ "applicative 'remove-file'" | |
78 | + @ "function %LoadModule_std_system", | |
79 | + - DLDI "inclusion <istream>" @ "header" | |
80 | + $dep_from "NPLA1 inclusion of <istream>" | |
81 | + ), | |
82 | + / %Configuration $= | |
83 | + ( | |
84 | + + "class %NodeLoader"; | |
85 | + // This is like %A1::LoadNode, except that the supported \ | |
86 | + values are already converted by %NPL::A1::ParseLeaf, \ | |
87 | + so both supported format of the keys and non-key leaf \ | |
88 | + values are different. See %Documentation.YFramework. | |
89 | + / DLI "simplified function %operator>>" ^ "%NodeLoader", | |
90 | + // This is a breaking change on the key format as above. | |
91 | + - "function %LoadNode" $dep_from ("%FetchMIMEBiMapping" | |
92 | + @ %Helper.Initialization, %Yeader.Shells) | |
93 | + ), | |
94 | + / %NPLA1 $= | |
95 | + ( | |
96 | + / @ "constructos %GlobalState" $= | |
97 | + ( | |
98 | + + "2 overloads with allocator parameter"; | |
99 | + / "default argument" @ "'pmr::memory_resource&' parameter" | |
100 | + -> ("default argument '{}'" @ "allocator parameter") | |
101 | + ), | |
102 | + * DLDI "missing inclusion <istream>" @ "header" $since b758 | |
103 | + $dep_to "NPLA1 inclusion of <istream>", | |
104 | + // This was needed for %(std::istream, streambuf). It was \ | |
105 | + fixed for %std::streambuf but not %std::istream by the \ | |
106 | + inclusion of <iosfwd> since b901 because the complete \ | |
107 | + type %std::istream was used since b891. This bug was \ | |
108 | + not shown due to the inclusion of <istream> in \ | |
109 | + %YBase.YStandardEx.String, but this should not been \ | |
110 | + relied on. | |
111 | + - "functions %(TransformNode; InsertChild)" | |
112 | + $dep_from ("%A1::LoadNode" @ %Configuration) | |
113 | + ), | |
114 | + / @ %NPLA $= | |
115 | + ( | |
116 | + + "overload %AssignWeakParent with %EnvironmentReference \ | |
117 | + parameter", | |
118 | + + "2 constructor with %allocator_type parameter" | |
119 | + @ "class %Environment", | |
120 | + ( | |
121 | + - "function %ParseNPLATermString"; | |
122 | + - "function %MapNPLALeafNode" | |
123 | + $dep_from ("%TranformNode" @ %NPLA1) | |
124 | + ) | |
125 | + ) | |
126 | + ), | |
127 | + / %Helper $= | |
128 | + ( | |
129 | + / @ "constructor %Environment" @ %Environment $= | |
130 | + ( | |
131 | + / "froze the current environment after the call to \ | |
132 | + %NPL::A1::Forms::LoadStandardContext", | |
133 | + / DLI "simplified" | |
134 | + $dep_from ("constructors %GlobalState" @ %NPL.NPLA1) | |
135 | + ), | |
136 | + / %Initialization $= | |
137 | + ( | |
138 | + * DD "wrong precondition" @ "Doxygen comment" | |
139 | + @ "function %FetchRoot" $since b550 | |
140 | + $= (/ "'\pre' command" -> "'exception' command"), | |
141 | + / @ "function %FetchMIMEBiMapping" $= | |
142 | + ( | |
143 | + / "simplified" | |
144 | + ^ $dep_from ("%NodeLoader" @ %NPL.Configuration); | |
145 | + // This changes the precondition and it is not fully \ | |
146 | + compatible to the old version. This also a \ | |
147 | + breaking change, see %NPL::A1::NodeLoader. | |
148 | + + DD "'\exception' command" @ "Doxygen comment" | |
149 | + ) | |
150 | + ) | |
151 | + ) | |
152 | + ), | |
153 | + / $forced DLDI "function %FetchWidgetLoader" @ %YReader.Shells | |
154 | + $dep_from ("constructor %WidgetLoader" @ %YFramework.UI.Loader) | |
155 | + ^ $dep_from ("%NodeLoader" @ %YFramework.NPL.Configuration) | |
156 | + // This is a breaking change as %NPL::A1::NoadLoader. See also \ | |
157 | + %Documentation.Test. | |
158 | +), | |
159 | + | |
160 | +b955 | |
161 | +( | |
35 | 162 | * "missing refinement on Clang++ version" @ "#pragma directive" |
36 | 163 | @ "member function %monotonic_buffer_resource::do_allocate" |
37 | 164 | @ %YBase.YStandardEx.MemoryResource $since b948, |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPL.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief NPL 规范和实现规格说明。 |
14 | -\version r29695 | |
14 | +\version r29760 | |
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 | - 2022-09-14 01:23 +0800 | |
20 | + 2022-09-23 01:05 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -340,7 +340,7 @@ | ||
340 | 340 | 无限制的特例要求指定更多的附加规则,而违反这个要求。 |
341 | 341 | **原理** |
342 | 342 | 在语言设计上,这类似 [RnRK] 的设计原则 G1 : |
343 | -G1a 对象状态(object status) :语言操作一等对象(@4.1); | |
343 | +G1a 对象状态(object status) :语言操作一等对象(@4.1) ; | |
344 | 344 | G1b 可扩展性(extensibility) :用户定义的设施能重现内建特性的能力(capability) 。 |
345 | 345 | 以上原则在 NPL 中略有变化。关于 G1a 的改变,详见一等实体(@4.2) 。 |
346 | 346 | 同 [RnRK] ,被 G1b 重现能力的特性是内建的(built-in) 。这不同于如 [RnRK] G2 指定的基本的(primitive) 特性。 |
@@ -992,7 +992,7 @@ | ||
992 | 992 | 使整体设计直接违反 @1.5.2.2 ; |
993 | 993 | 要求局部所有权以和全局默认机制的不一致的方式表达,造成接口抽象泄漏(@1.5.3.4)(这首先来放弃局域性(@1.5.2.4) 和需求的冲突)。 |
994 | 994 | 此外,即便使用时不要求区分对象的局部所有权关系,全局的分配释放机制也比局部的机制有更大的实现复杂性和约束。为实现对内部有限的资源的有效管理,局部所有权在实现中仍是必要的。 |
995 | -在使用全局所有者如全局的垃圾回收(GC, garbage collection) 的实现中,这种必要性被隐藏在全局所有者内部实现,语言的整体设计不会更简单。 | |
995 | +在使用全局所有者如全局的垃圾回收(GC, garbage collection) 的实现中,这种必要性被隐藏在全局所有者内部实现,语言的整体设计不会更简单(@1.5.3.2) 。 | |
996 | 996 | 使用全局所有者的资源管理假定启发式(heuristic) 策略以节约现实中无法接受的非预期性开销。这仍无法保证总是对不同的场景同样有效,以至于存在以下问题: |
997 | 997 | 设计至少违反 @1.5.2.1 和 @1.5.3.2 之一; |
998 | 998 | 在不引入支持用户配置策略的扩充设计时,违反 @1.5.2.1 总是无法避免的; |
@@ -1662,7 +1662,7 @@ | ||
1662 | 1662 | 过程实体(@4.5.2) 决定函数表达式(@4.5.2) 关联的上下文。 |
1663 | 1663 | 本节以外其它具体规则由派生实现定义。 |
1664 | 1664 | **注释** |
1665 | -参数化的子项可在语法上被表示为一个洞(hole) 。 | |
1665 | +参数化的子项可在(元语言的)语法上被表示为一个洞(hole) 。 | |
1666 | 1666 | |
1667 | 1667 | @4.6.1 求值环境: |
1668 | 1668 | 求值环境(evaluation environment) 是在求值(@4.1) 时可访问的隐式上下文,提供可通过名称解析(@4.3.3) 访问的变量的绑定(@4.1) 。 |
@@ -1829,6 +1829,15 @@ | ||
1829 | 1829 | 但这不足以涵盖一般的形式定义;特别地,调用(@4.5.2.2) 是仅仅关于过程这类实体的互操作,而种类适合一般实体的静态类型。例如,在不考虑进一步地实现时,多变多态(@4.2.3.5.5) 的类型不需要限定过程(函数)。 |
1830 | 1830 | 种类也可扩展到特定的计算作用的作用系统(effect system) 上,此处从略。 |
1831 | 1831 | |
1832 | +@4.7.10 一等类型: | |
1833 | +一等对象(@4.2) 的类型是一等类型(first-class type) 。 | |
1834 | +非一等类型的居留(@4.7.6) 不在乎对象语言中可表达,即对象语言中无法构造这些类型的值。 | |
1835 | +非一等类型仅用于构造其它类型(可能是一等类型)和类型检查等依赖类型的推理。 | |
1836 | +**注释** | |
1837 | +一个典型的非一等类型的例子是 ISO C 、ISO C++ 和 .NET 等支持的类型 void 。 | |
1838 | +在语义的角度上,void 可视为依赖翻译阶段(@2.4.1) 把求值时得到 void 居留的表示替换为语义错误的单元类型,但这种居留在对象语言中始终不可取得。 | |
1839 | +若不限制翻译阶段,可通过在传递(@4.4.6.5) 时始终限制正常控制(@4.8) 的值实现类似的效果,例如不考虑类型消除时 ISO C++ 中在复制或转移构造函数始终抛出异常的类类型。 | |
1840 | + | |
1832 | 1841 | @4.8 程序的控制执行条件(execution condition) : |
1833 | 1842 | 和过程的调用(@4.5.2.2) 类似,程序的控制状态(@4.1) 决定求值使用的续延。 |
1834 | 1843 | 更一般地,规约规则指定语言的实现决定程序行为时使用的(对程序不保证可见的)续延,这种在实现中对应的控制状态称为控制执行条件。 |
@@ -2004,6 +2013,10 @@ | ||
2004 | 2013 | 宿主语言实现在宿主语言的尾上下文可能支持宿主 TCO(@5.10.4.2) 而使递归调用满足嵌套调用安全,但这并不是语言提供的保证,不应在可移植的实现中依赖。 |
2005 | 2014 | 非嵌套调用安全的情形在过程嵌套调用深度过大时,可因为宿主语言的存储资源消耗导致的宿主语言实现的未定义行为,典型地包括实现中的栈溢出(stack overflow) 。 |
2006 | 2015 | |
2016 | +@5.4.3 并发访问: | |
2017 | +当前所有 NPLA1 实现中都没有显式的并发访问控制。 | |
2018 | +一般地,为避免并发访问引起的宿主语言的未定义行为,需要通过本机实现(@5.3.4) 在外部使用不同的资源实例或附加适当的同步。 | |
2019 | + | |
2007 | 2020 | @5.5 一等对象类型: |
2008 | 2021 | 除类型映射(@5.3.1) ,NPLA 约定能作为一等对象的类型支持的抽象的类型,作为实现的做小要求的一部分。 |
2009 | 2022 | 以下章节扩充 NPLA 的其它类型,这些类型中的一部分可能作为一等对象。 |
@@ -4283,7 +4296,8 @@ | ||
4283 | 4296 | |
4284 | 4297 | @6.15.1 NPLA1 应用实例: |
4285 | 4298 | 在对象语言(@7) 外,NPLA1 的实现也被用于其它应用。 |
4286 | -NPLA1 当前加入特定的序列化和反序列化作为配置文件,参见 NPL::Configuration 。 | |
4299 | +NPLA1 当前加入特定的序列化和反序列化作为配置文件,参见模块 NPL::Configuration : | |
4300 | +A1::NodeLoader 加载(@1.2.4) NPLA1 翻译单元(另见 @6.1.6.3 )。 | |
4287 | 4301 | NPLA1 的上述配置文件加入特定的匹配和初始化机制作为 YSLib::UI::Loader([Documenatation::YSLib @@6.15.9]) 在运行时读取用户界面布局和配置的脚本。 |
4288 | 4302 | NPLA1 用于 MIME 类型和文件名映射([Documentation::YSLib @@4.5.3]) 的实现,上述配置文件对应的外部配置格式。 |
4289 | 4303 | 注意这些应用不直接使用 NPLA1 的语义,其中使用的 TermNode 类型中名称直接表示上下文(@4.6) 中的实体名称。 |
@@ -4623,15 +4637,7 @@ | ||
4623 | 4637 | @7.5 NPLA1 节点处理 API : |
4624 | 4638 | NPLA1 提供了对节点作为树形数据结构和整体处理的处理 API 。 |
4625 | 4639 | |
4626 | -@7.5.1 直接节点操作: | |
4627 | -以下 API 主要用于兼容历史实现。 | |
4628 | -A1::InsertChild 插入 NPLA1 子节点。 | |
4629 | -A1::TransformNode 变换 NPLA1 节点 S 表达式抽象语法树为 NPLA1 语义结构。 | |
4630 | -通过 ValueNode 变换实现解释,参数指定映射例程,结果是变换的序列语义结构。 | |
4631 | -复合表达式中的经过节点到字符串的映射例程被解释为序列语义结构的名称,余下的项一一映射为子节点。 | |
4632 | -A1::LoadNode 加载(@1.2.4) NPLA1 翻译单元(另见 @6.1.6.3 )。 | |
4633 | - | |
4634 | -@7.5.2 中缀变换: | |
4640 | +@7.5.1 中缀变换: | |
4635 | 4641 | NPLA1 提供符合特定谓词指定的过滤条件的中缀分隔项替换为特定名称表达式(@4.5.1) 指定的前缀操作形式的列表。 |
4636 | 4642 | 这些中缀变换作为预处理操作,可识别和接受 NPL-GA 语法外的记号,即转换扩展的 NPL-GA 文法输入为严格的 NPL-GA 语法(@3.4.4) 要求的源语言。 |
4637 | 4643 | 这些操作以函数对象类型 SeparatorTransformer 提供。 |
@@ -4640,7 +4646,7 @@ | ||
4640 | 4646 | 变换结果可被进一步规约。 |
4641 | 4647 | 另见异步规约实现(@7.9.2) 。 |
4642 | 4648 | |
4643 | -@7.5.3 叶节点分析 : | |
4649 | +@7.5.2 叶节点分析 : | |
4644 | 4650 | 叶节点(@6.2.1) 分析 API 作为标记器(@7.8) 的实现转换词素到包含记号的项,包括: |
4645 | 4651 | 函数 A1::ParseLeaf |
4646 | 4652 | 函数 A1::ParseLeafWithSourceInformation |
@@ -5118,7 +5124,7 @@ | ||
5118 | 5124 | 类 A1::GlobalState 提供全局状态,可直接作为 REPL 原型。 |
5119 | 5125 | 其中,数据成员 EvaluateLeaf 、EvaluateList 、EvaluateLiteral 是全局公共遍(@7.4.3) ,分别为叶遍、列表遍和字面量求值遍。 |
5120 | 5126 | A1::GlobalState 以 ContextNode::EvaluateList(@6.11.3.1) 为第二参数调用 A1::SetupDefaultInterpretation 初始化,之后默认解释配置 ContextNode 具有以下能在 A1::ReduceOnce(@7.4.4) 运行的规约算法: |
5121 | -A1::GlobalState 使用 @7.5.3 的 API 实现标记器。 | |
5127 | +A1::GlobalState 使用 @7.5.2 的 API 实现标记器。 | |
5122 | 5128 | 若项是具有一个子项的列表节点,则规约为这个子项; |
5123 | 5129 | 若项是具有多个子项的列表节点,依次调用 NPL::ReduceHeadEmptyList(@6.10.7.1) 、A1::ReduceFirst(@7.4.6) 和 A1::ReduceCombined(@7.6.4.2) 规约列表项; |
5124 | 5130 | 否则调用 A1::ReduceLeafToken(@7.6.4) 规约叶节点。 |
@@ -5212,7 +5218,7 @@ | ||
5212 | 5218 | @7.9.2 异步规约 API 支持: |
5213 | 5219 | 部分 NPLA1 API 提供同步和异步的不同实现。一些 API 明确支持异步规约。 |
5214 | 5220 | 启用异步规约的实现定义为实现选项(@7.1) NPL_Impl_NPLA1_Enable_Thunked 。 |
5215 | -此外,启用分隔符中缀变换(@7.5.2) 的异步的实现定义为实现选项 NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass ,使用单独的异步实现保证嵌套调用安全(@6.1.4.1) 。 | |
5221 | +此外,启用分隔符中缀变换(@7.5.1) 的异步的实现定义为实现选项 NPL_Impl_NPLA1_Enable_ThunkedSeparatorPass ,使用单独的异步实现保证嵌套调用安全(@6.1.4.1) 。 | |
5216 | 5222 | NPL::NPLA1Forms(@8.1) 等同时支持同步和异步规约的 API 可基于这些 API 实现。 |
5217 | 5223 | |
5218 | 5224 | @7.9.2.1 异步规约基本支持: |
@@ -5681,7 +5687,7 @@ | ||
5681 | 5687 | 当前实现显式包含保证嵌套调用安全(@5.4.2) 机制的异步调用 API 包括: |
5682 | 5688 | NPL::SContext 中的递归遍历 API(@6.1.6.4) ; |
5683 | 5689 | 环境数据结构(@6.11.1) 的可重入 API ; |
5684 | -中缀变换(@7.5.2) ; | |
5690 | +中缀变换(@7.5.1) ; | |
5685 | 5691 | 递归绑定支持 API(@7.7.4) 。 |
5686 | 5692 | 例外参见: |
5687 | 5693 | NPLA 安全保证例外(@6.1.4) 。 |
@@ -6008,23 +6014,26 @@ | ||
6008 | 6014 | |
6009 | 6015 | @8.5.2 对象语言加载 API |
6010 | 6016 | 函数 Forms::LoadGroundContext 提供 SHBuild 初始 REPL 环境(包含的上下文称为基础上下文(ground context) ),其中支持: |
6011 | -使用 A1::SeparatorTransformer(@7.5.2) 启用预处理的分号和逗号转换,分别为有序和无序列表求值的语法糖。 | |
6012 | -上述语法糖实现为 REPL 对象内部的无状态的预处理器求值遍,仅包含中缀变换(@7.5.2) ,不需要向环境中添加名称。 | |
6017 | +使用 A1::SeparatorTransformer(@7.5.1) 启用预处理的分号和逗号转换,分别为有序和无序列表求值的语法糖。 | |
6018 | +上述语法糖实现为 REPL 对象内部的无状态的预处理器求值遍,仅包含中缀变换(@7.5.1) ,不需要向环境中添加名称。 | |
6013 | 6019 | 变换后仍然具有 WHNF(@4.4.5.1) 形式,其中第一个子项是一个合并子右值,具有以下性质: |
6014 | 6020 | 对之后的子项构成的序列有序或无序列表求值; |
6015 | 6021 | 若存在操作数,有序求值保证最后一项是尾上下文(实现同 @8.4.9 ); |
6016 | 6022 | 不保证是真合并子(@4.5.3.2) 。 |
6017 | 6023 | 在对象语言中的对应接口参见 NPLA1 参考实现环境(@10) 。 |
6018 | -模块 NPL::Dependency 还提供其它一些接口,调用函数 Forms::LoadGroundContext 初始化上下文后继续调用,初始化特定操作的环境: | |
6019 | -函数 Forms::LoadModule_std_continuations 提供一等续延(@4.5.3.3) 相关操作(@12.1) ; | |
6020 | -函数 Forms::LoadModule_std_promises 提供延迟求值等操作(@12.2) ; | |
6021 | -函数 Forms::LoadModule_std_math 提供数学功能相关操作(@12.3) ; | |
6022 | -函数 Forms::LoadModule_std_strings 提供字符串操作(@12.4) ; | |
6023 | -函数 Forms::LoadModule_std_io 提供输入/输出操作(@12.5) ; | |
6024 | -函数 Forms::LoadModule_std_modules 提供模块管理操作(@12.7) ; | |
6025 | -函数 Forms::LoadModule_std_system 提供系统操作(@12.6) ; | |
6026 | -函数 Forms::LoadModule_SHBuild 提供其它一些供 SHBuild 间接调用的操作(@13.1.1) 。 | |
6027 | -函数 Forms::LoadStandardContext 调用 Forms::LoadGroundContext 并加载基础上下文中提供的库模块(@10.2) ;另见 NPLA1 参考实现扩展环境(@12) 。 | |
6024 | +模块 NPL::Dependency 还提供其它一些函数。 | |
6025 | +调用函数 Forms::LoadGroundContext 初始化上下文后继续调用。这蕴含调用以下函数初始化特定操作的环境: | |
6026 | +Forms::LoadModule_std_continuations 提供一等续延(@4.5.3.3) 相关操作(@12.1) ; | |
6027 | +Forms::LoadModule_std_promises 提供延迟求值等操作(@12.2) ; | |
6028 | +Forms::LoadModule_std_math 提供数学功能相关操作(@12.3) ; | |
6029 | +Forms::LoadModule_std_strings 提供字符串操作(@12.4) ; | |
6030 | +Forms::LoadModule_std_io 提供输入/输出操作(@12.5) ; | |
6031 | +Forms::LoadModule_std_modules 提供模块管理操作(@12.7) ; | |
6032 | +Forms::LoadModule_std_system 提供系统操作(@12.6) ; | |
6033 | +Forms::LoadModule_SHBuild 提供其它一些供 SHBuild 间接调用的操作(@13.1.1) 。 | |
6034 | +Forms::LoadStandardContext 调用 Forms::LoadGroundContext 并加载基础上下文中提供的库模块(@10.2) ;另见 NPLA1 参考实现扩展环境(@12) 。 | |
6035 | +当前实现中,以下情形可能修改共享的资源,因此需要附加宿主实现机制以避免宿主语言的未定义行为: | |
6036 | +Forms::LoadModule_std_modules 可修改保存在环境对象(@5.7.1) 中的共享资源。 | |
6028 | 6037 | |
6029 | 6038 | @8.6 实现注记: |
6030 | 6039 | 本节指定当前实现的一些非公开接口性质。 |
@@ -6118,7 +6127,7 @@ | ||
6118 | 6127 | **注释** |
6119 | 6128 | klisp 的 equal? 直接使用自动机实现,在比较操作中没有对应的续延。NPLA1 支持互操作(@5.3) 允许相等的子对象以异步规约实现,不能使用这种方式而排除续延。 |
6120 | 6129 | klisp 的 $vau 不具有应保证被求值的实际参数,不需要异步调用(@6.11.3) ,没有 eval-vau-parent 对应的续延。 |
6121 | -import-bindings 和 Forms::Provide 使用的 provide-let-return 共用部分本机实现。 | |
6130 | +import-bindings 和 Forms::Provide 使用的 provide-let-return 共用部分本机实现(@5.3.4) 。 | |
6122 | 6131 | klisp 的 call/cc 直接捕获当前续延而不进行其它操作。控制作用(@4.1) 对续延的调用在本机函数 kcall_cont 实现,并被 apply-continuation 的本机实现调用,其中可调用本机函数 do_interception ,但没有指派具体的续延名称。 |
6123 | 6132 | 和 klisp 不同,Forms::Call1CC 需检查一次续延调用的约束,在不修改宿主类型 A1::Continuation(@7.4.2) 时,不能单独把控制作用的实现放在调用处,而是和 Scheme 这样直接把续延具现为过程的方式,在内部的 A1::ContextHandler(@7.4.2) 中指定其实现。 |
6124 | 6133 | 这样的实现方式在捕获时单独指定不同的特性(包括续延名称)而不是在其它位置(如应用或扩展续延)时指定信息,同时不需要修改 A1::Continuation 的实现。这些信息原则上是可选的,减少 A1::Continuation 的实现意味着减小实现开销(但 TCO 实现当前仍然无法避免类似的开销)。 |
@@ -6149,7 +6158,7 @@ | ||
6149 | 6158 | |
6150 | 6159 | @9.1.1 外部环境(@1.2.4) : |
6151 | 6160 | 基于 @5.2 约定,由 @2.7.1 ,NPLA 的实现不假定存在多线程执行环境。 |
6152 | -但是,宿主语言可支持多线程环境执行,在没有适当同步下可引起宿主语言的未定义行为(@5.4) 。 | |
6161 | +但是,宿主语言可支持多线程环境执行,可引起宿主语言的未定义行为(@5.4.3) 。 | |
6153 | 6162 | 作为 NPLA 的派生,NPLA1 对象语言程序也具有相同的性质,除非另行指定需要和外部环境交互的特定操作,不需要假定 NPLA1 引入存在多线程执行环境。 |
6154 | 6163 | |
6155 | 6164 | @9.1.2 附加元数据(extra metadata) : |
@@ -6262,7 +6271,7 @@ | ||
6262 | 6271 | <boolean> :布尔值(@4.1),即取值为 #t 或 #f 的集合,是 NPLA 类型映射(@5.3.1) 指定的用于条件判断的单一值的类型。 |
6263 | 6272 | 推论:<boolean> 对应的宿主类型是 bool 。 |
6264 | 6273 | <test> :类似 <object> ,通常预期为 <boolean> ,作为条件。 |
6265 | -和 Scheme 类似但和 Kenerl 不同,非 #t 的值在决定分支时视同 #f ,以允许在 <boolean> 外自然扩展的逻辑代数操作。 | |
6274 | +和 Scheme 类似但和 Kernel 不同,非 #t 的值在决定分支时视同 #f ,以允许在 <boolean> 外自然扩展的逻辑代数操作。 | |
6266 | 6275 | 和 Common Lisp 不同,不使用空列表(或符号 nil )代替 #f ,以避免需要特设的规则以特定的其它类型的值(如 Common Lisp 的符号 t )表示逻辑真(这在逻辑非操作中不可避免)。 |
6267 | 6276 | <combiner> :合并子。 |
6268 | 6277 | <applicative> :应用子(@4.5.3.2) 。 |
@@ -6566,7 +6575,7 @@ | ||
6566 | 6575 | |
6567 | 6576 | @9.7.1 求值算法: |
6568 | 6577 | 除非另行指定,NPLA1 对象语言的求值总是使用规范求值算法(@7.8.2) 。 |
6569 | -在 REPL(@7.8) 中输入求值算法接受的语法形式之前,求值可使用基于中缀变换(@7.5.2) 识别的 ; 和 , 分隔符,分别表示对被分隔的序列参数进行有序和无序列表求值(替换后合并子功能对应参考实现环境中函数 $sequence(@11.4.1) 和 list%(@11.3.5) 求值后的合并子)。 | |
6578 | +在 REPL(@7.8) 中输入求值算法接受的语法形式之前,求值可使用基于中缀变换(@7.5.1) 识别的 ; 和 , 分隔符,分别表示对被分隔的序列参数进行有序和无序列表求值(替换后合并子功能对应参考实现环境中函数 $sequence(@11.4.1) 和 list%(@11.3.5) 求值后的合并子)。 | |
6570 | 6579 | 其中,分隔符 , 优先组合。 |
6571 | 6580 | 对分隔符的处理使用和组合顺序相反的两遍分别对 ; 和 , 遍历替换,实现参见 @8.5 。 |
6572 | 6581 | 由此引起的其它语法差异参见绑定构造(@9.7.3) 。 |
@@ -7623,6 +7632,16 @@ | ||
7623 | 7632 | 未指定值可等于 #inert(@9.3.1.3) 或其它值,但满足忽略值时不引起可观察行为(@4.1.3) 的改变(这排除了引入 volatile 类型或非平凡析构的宿主值)。 |
7624 | 7633 | 若操作(@10.3.1) 在 Kernel 或 klisp 中存在结果是 #inert 的对应的操作,且未指定作为函数值的结果,则返回等于 #inert 的右值。 |
7625 | 7634 | 操作中隐式分配的和按接口约定转移所有权给操作实现的资源不存在资源泄漏(@5.6.4) 。这包括抛出异常(@9.5.2) 时,操作的实现提供基本异常安全保证(basic exception safety) 。 |
7635 | +**原理** | |
7636 | +#inert(@4.7) 是单元类型的值。但是,未指定值并不依赖单元类型的性质,而只是需要一种可在对象语言中判断是否为实现(如 [RnRK] 的 inert? ),而避免使用特设的规则。 | |
7637 | +取而代之,一些语言或运行时支持非一等的特设返回类型:void(@4.7.10) ,在对象语言中无法构造其值。这种特性引起一些实用上的困难而被考虑改进,替换成一等类型,如: | |
7638 | +https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0146r1.html | |
7639 | +https://github.com/dotnet/csharplang/discussions/1603 | |
7640 | +即便被改进,这通常只是单元类型,而不够清晰地反映未指定的意图。 | |
7641 | +未指定值蕴含的不确定性在对象语言中难以建模,因此直接作为内建的支持特性能使语言的设计更简单(@1.5.3.2) 。 | |
7642 | +未指定值的未指定性在接口意义上仍然不是一等实体,因为当前不提供如 inert? 这样的谓词(提供 inert? 也仅仅是判断值是否为 #inert 而不是任意的未指定值)。 | |
7643 | +相对 inert? ,这类谓词可能是有用的,例如元语言可能需要判断未指定性质以简化其派生实现。但这类需求和实现细节相关,且当前缺乏实例显示在对象语言中无条件提供的必要性。更重要的是,若要求提供这种谓词,限制派生实现在未指定值的类型上维持开放类型(@5.3.1) 设计。 | |
7644 | +未指定值作为内建特性时,用户也无法直接提供这类谓词的派生(而不符合可扩展性(@1.5.5.1) )。在需要这类谓词时,派生语言设计可能视具体实现需要满足的条件补充。 | |
7626 | 7645 | |
7627 | 7646 | @10.9.2 操作符合性: |
7628 | 7647 | 除非另行指定,以下关于操作实现的行为未指定。 |
@@ -7669,8 +7688,8 @@ | ||
7669 | 7688 | 除操作外,特定名称的对象以变量的形式在库中初始化,直接提供具有预设目的的可编程特性。 |
7670 | 7689 | |
7671 | 7690 | @10.9.4 操作实现注记: |
7672 | -通过派生实现的操作不依赖非真合并子(@9.9.5) ,因此以合并子实现操作时,其中不使用分隔符(@9.7.1) ,也不需要实现在初始化(@10.1.1) 时支持中缀变换(@7.5.2) 。 | |
7673 | -但是,不同操作之间的定义可能使用分隔符。因为不需依赖 $sequence(@11.4.1) ,这种实现也更简单。 | |
7691 | +通过派生实现的操作不依赖非真合并子(@9.9.5) ,因此以合并子实现操作时,其中不使用分隔符(@9.7.1) ,也不需要实现在初始化(@10.1.1) 时支持中缀变换(@7.5.1) 。 | |
7692 | +但是,不同操作之间的定义可能使用分隔符。因为不需依赖 $sequence(@11.4.1) ,这种实现也更简单(@1.5.3.2) 。 | |
7674 | 7693 | 除非另行指定,当前实现中,操作引发错误对象(@9.5.2) 以抛出异常实现(@10.6.4) ,涉及具体的异常类型未指定。 |
7675 | 7694 | **注释** |
7676 | 7695 | 这允许引起错误处理(@10.6.4) 的使用引发错误对象的派生实现。 |
@@ -7971,10 +7990,12 @@ | ||
7971 | 7990 | 若省略 <alternative> 且 <test> 求值为 #f ,则结果未指定(@10.9) 。 |
7972 | 7991 | **注释** |
7973 | 7992 | 对 <test> 的处理的主要原理和 Kernel 的 $and 不要求尾上下文的表达式求值检查类型一致。 |
7974 | -若需要检查类型避免误用,可以派生提供其它函数;相反的派生无法利用更简单的实现。 | |
7993 | +若需要检查类型避免误用,可以派生提供其它函数;相反的派生无法利用更简单(@1.5.3.2) 的实现。 | |
7975 | 7994 | **原理** |
7976 | 7995 | 和 R7RS 类似,但和 Racket 及 Kernel 不同,省略 <alternative> 被支持。 |
7977 | 7996 | 这避免用户必须引入 #inert 等具体的值实现相同隐式效果而违反关注点分离原则(@1.5.2.4) 。 |
7997 | +必要时(如派生结果等效 #inert 的操作(@10.9.1) ),#inert 的值仍可被显式使用,但这在接口意义上通常是不必要的。 | |
7998 | +另见关于 #inert 的原理(@10.9.1) 。 | |
7978 | 7999 | 和 [RnRK] 中的相关讨论结论不同,是否省略 <alternative> 的形式应是一致的。这是因为: |
7979 | 8000 | NPLA1 不假设作为基本控制操作的 $if 的作用(仅要 <consequent> 或 <alternative> 求值的结果,或仅为了副作用); |
7980 | 8001 | $if 不假设用户对 <consequent> 和 <alternative> 顺序选择性偏好,以避免限制用户选择否定谓词简化 <test> ,从而支持 @1.5.2.1 。 |
@@ -8960,8 +8981,10 @@ | ||
8960 | 8981 | 同时保存创建的环境,以避免因程序没有保存环境引用而无效化(@9.8.6) ,使访问变量绑定的程序具有未定义行为; |
8961 | 8982 | 结果是加载结果(同 std.io 模块中的 load(@12.5) )而不是 #inert 。 |
8962 | 8983 | **注释** |
8963 | -当前实现依赖可用的 std.strings(@12.4) 、std.io(@12.5) 和 std.system(@12.6) 环境。 | |
8984 | +当前派生实现依赖可用的 std.strings(@12.4) 、std.io(@12.5) 和 std.system(@12.6) 环境。 | |
8964 | 8985 | 通过不经过本模块的操作、重复字符串模板的重复项、符号链接和字符串大小写不敏感的文件名等可能绕过本模块的注册机制而重复加载同一个外部文件。本模块的操作不对这些情形进行任何检查。 |
8986 | +当前使用 Forms::LoadModule_std_modules(@8.5.2) 实现,不对并发访问进行控制。 | |
8987 | +需注意外部环境(@9.1.1) 中不受到控制的并发访问可能引起宿主语言未定义行为(@5.4.3) 。 | |
8965 | 8988 | |
8966 | 8989 | @13 SHBuild 实现环境: |
8967 | 8990 | SHBuild 实现环境是派生 NPLA1 参考实现扩展环境(@12) 的用于 SHBuild 和外部脚本的构建的初始环境。 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2015-2018, 2020-2021 FrankHB. | |
2 | + © 2015-2018, 2020-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 Test.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 测试项目说明。 |
14 | -\version r357 | |
14 | +\version r362 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 597 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-05-09 13:10:21 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2021-10-22 18:05 +0800 | |
20 | + 2022-09-23 02:03 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -243,6 +243,11 @@ | ||
243 | 243 | @4.1.3.7 build 885 起: |
244 | 244 | MinGW64 平台支持同上(@4.1.3.6) 。 |
245 | 245 | |
246 | +@4.1.3.8 build 956 起: | |
247 | +支持格式变更同 [Documentation::YFramework @@5.2.10] 。 | |
248 | +**注释** | |
249 | +书签中的路径使用字符串字面量作为键,不受变更影响。 | |
250 | + | |
246 | 251 | @5 测试注记: |
247 | 252 | 以下注记仅适用提交版本([Documentation::ProjectRules @@3.2.1.2]) ,对已提交的版本为测试记录,未提交的版本为测试计划。 |
248 | 253 | 示例测试项目 YSTest 包含 @3 和 @4 提到的测试。 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file YFramework.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief YFramework 设计和实现说明。 |
14 | -\version r1602 | |
14 | +\version r1625 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since 早于 build 132 |
17 | 17 | \par 创建时间: |
18 | 18 | 2009-12-02 05:14:30 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2022-07-09 12:12 +0800 | |
20 | + 2022-09-23 11:24 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -699,6 +699,7 @@ | ||
699 | 699 | 除 @2.8.2 外,当前取得单态状态的接口包括: |
700 | 700 | FetchRoot :取值类型根节点; |
701 | 701 | FetchDefaultFontCache :取默认字体缓存。 |
702 | +FetchMIMEBiMapping :取 MIME 数据映射。 | |
702 | 703 | |
703 | 704 | @2.8.5 多线程同步: |
704 | 705 | 特定于平台,Helper 可能提供的多线程同步接口。 |
@@ -967,6 +968,17 @@ | ||
967 | 968 | @5.2.9 build 710 起: |
968 | 969 | Linux 框架公共配置文件路径修改为以程序映像所在的目录下的 yconf.txt 的绝对路径(不再是依赖初始化时当前工作目录的相对路径)。 |
969 | 970 | |
971 | +@5.2.10 build 956 起: | |
972 | +配置节点的叶节点的值被 NPL::ParseLeaf([Documentation::NPL @@7.5.2]) 处理,因此: | |
973 | + 配置的键(子节点中第一个叶节点)支持 NPLA1 代码字面量和字符串字面量,不再支持数值和其它构成字面量的词素。 | |
974 | + 配置的非键的值(除键的叶节点)区分不同的字面量,不再支持非字符串字面量的值。 | |
975 | +以上不被支持的值在转换为内部表示时,被视为空值。 | |
976 | +对符号,空值转换为键的 "$"(兼容处理 YSLib::ValueNode([Documentation.YSLib @@3.16]) 的函数 YSLib::IsPrefixedIndex );对字符串,空值转换为空字符串。 | |
977 | +**注释** | |
978 | +构成符号的词素仍被键支持。 | |
979 | +字符串字面量仍被非键的配置值。 | |
980 | +这不影响默认生成的配置,因为这些配置中的键都使用符号,非键的值都使用字符串字面量。 | |
981 | + | |
970 | 982 | @5.3 附加配置: |
971 | 983 | 附加配置是可选的。 |
972 | 984 | build 654 起,Win32 平台支持环境变量 YF_DEBUG_OUTPUT 设置值为 1 时初始化默认日志记录跟踪发送到调试器。 |
@@ -977,6 +989,21 @@ | ||
977 | 989 | 初始化模块 Adaptor::Image 中的 YSLib::Drawing::ImageCodec 对象。 |
978 | 990 | 非框架初始化的内部实现也可能使用类似框架初始化的实现(@2.8.4) 。 |
979 | 991 | |
992 | +@5.5 其它外部数据文件: | |
993 | +其它外部数据文件可能使用类似配置文件(@5.2) 的方式访问。 | |
994 | +当外部数据文件不可用时,可使用内置的默认值。 | |
995 | + | |
996 | +@5.5.1 build 450 起: | |
997 | +外部文件 MIMEExtMap.txt 提供 MIME 数据。 | |
998 | +使用的格式同 yconf.txt(@5.2.2) 。 | |
999 | +**注释** | |
1000 | +解析 MIME 数据的函数 FetchMIMEBiMapping 在初始化模块(@2.8.4) 一并提供,但当前这不依赖框架初始化。 | |
1001 | + | |
1002 | +@5.5.2 build 956 起: | |
1003 | +外部文件 MIMEExtMap.txt 支持格式变更同 @5.2.10 。 | |
1004 | +**注释** | |
1005 | +解析 MIME 数据的函数 FetchMIMEBiMapping 依赖框架初始化。 | |
1006 | + | |
980 | 1007 | */ |
981 | 1008 | //// |
982 | 1009 |