YSTest: Dependency.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

Dependency.cpp
浏览该文件的文档.
1 /*
2 © 2015-2017 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "NPL/YModules.h"
29 #include YFM_NPL_Dependency // for std::placeholders, ystdex::bind1;
30 #include YFM_NPL_SContext
31 #include YFM_YSLib_Service_FileSystem // for YSLib::IO::*;
32 #include <iterator> // for std::istreambuf_iterator;
33 #include <limits> // for std::numeric_limits;
34 #include <cctype> // for std::isdigit, std::tolower;
35 #include <cerrno> // for errno, ERANGE;
36 #include <cstdio> // for std::puts;
37 #include <regex> // for std::regex, std::regex_match;
38 #include <ystdex/string.hpp> // for ystdex::begins_with, ystdex::erase_left;
39
40 using namespace YSLib;
41
42 namespace NPL
43 {
44
45 vector<string>
46 DecomposeMakefileDepList(std::streambuf& sb)
47 {
48 using s_it_t = std::istreambuf_iterator<char>;
49 // NOTE: Escaped spaces would be saved to prevent being used as delimiter.
50 set<size_t> spaces;
51 const auto sbuf(Session(s_it_t(&sb), s_it_t(),
52 [&](LexicalAnalyzer& lexer, char c){
53 lexer.ParseQuoted(c,
54 [&](string& buf, const UnescapeContext& uctx, char) -> bool{
55 const auto& escs(uctx.GetSequence());
56
57 // NOTE: See comments in %munge function of 'mkdeps.c' from libcpp
58 // of GCC.
59 if(escs.length() == 1)
60 {
61 if(uctx.Prefix == "\\")
62 switch(escs[0])
63 {
64 case ' ':
65 spaces.insert(buf.size());
66 YB_ATTR_fallthrough;
67 case '\\':
68 case '#':
69 buf += escs[0];
70 return true;
71 default:
72 ;
73 }
74 if(uctx.Prefix == "$" && escs[0] == '$')
75 {
76 buf += '$';
77 return true;
78 }
79 }
80 return {};
81 }, [](char ch, string& pfx) -> bool{
82 if(ch == '\\')
83 pfx = "\\";
84 else if(ch == '$')
85 pfx = "$";
86 else
87 return {};
88 return true;
89 });
90 }).GetBuffer());
91 vector<string> lst;
92
93 ystdex::split_if(sbuf.begin(), sbuf.end(), static_cast<int(&)(int)>(
94 std::isspace), [&](string::const_iterator b, string::const_iterator e){
95 lst.push_back(string(b, e));
96 }, [&](string::const_iterator i){
97 return !ystdex::exists(spaces, size_t(i - sbuf.cbegin()));
98 });
99 return lst;
100 }
101 vector<string>
102 DecomposeMakefileDepList(std::istream& is)
103 {
104 return ystdex::call_value_or(static_cast<vector<string>(&)(
105 std::streambuf&)>(DecomposeMakefileDepList), is.rdbuf());
106 }
107
108 bool
109 FilterMakefileDependencies(vector<string>& lst)
110 {
111 const auto i_c(std::find_if(lst.cbegin(), lst.cend(),
112 [](const string& dep){
113 return !dep.empty() && dep.back() == ':';
114 }));
115
116 return i_c != lst.cend()
117 && (lst.erase(lst.cbegin(), i_c + 1), !lst.empty());
118 }
119
120
121 void
122 InstallFile(const char* dst, const char* src)
123 {
124 using namespace YSLib::IO;
125
126 // FIXME: Blocked. TOCTTOU access.
127 try
128 {
129 if(HaveSameContents(dst, src))
130 return;
131 }
132 CatchExpr(std::system_error& e, YTraceDe(Err, "Failed accessing file for"
133 " comparison before installing file."), ExtractAndTrace(e, Err))
134 CopyFile(dst, src, PreserveModificationTime);
135 }
136
137 void
138 InstallDirectory(const string& dst, const string& src)
139 {
140 using namespace YSLib::IO;
141
142 TraverseTree([](const Path& dname, const Path& sname){
143 InstallFile(string(dname).c_str(), string(sname).c_str());
144 }, Path(dst), Path(src));
145 }
146
147 void
148 InstallHardLink(const char* dst, const char* src)
149 {
150 using namespace YSLib::IO;
151
152 if(VerifyDirectory(src))
153 throw std::invalid_argument("Source is a directory.");
154 else
155 uremove(dst);
156 TryExpr(CreateHardLink(dst, src))
157 CatchExpr(..., InstallFile(dst, src))
158 }
159
160 void
161 InstallSymbolicLink(const char* dst, const char* src)
162 {
163 using namespace YSLib::IO;
164
165 uremove(dst);
166 TryExpr(CreateSymbolicLink(dst, src))
167 CatchExpr(..., InstallFile(dst, src))
168 }
169
170 void
171 InstallExecutable(const char* dst, const char* src)
172 {
173 InstallFile(dst, src);
174 }
175
176 namespace A1
177 {
178
179 namespace Forms
180 {
181
183 namespace
184 {
185
186 void
187 LoadSequenceSeparators(ContextNode& ctx, EvaluationPasses& passes)
188 {
189 RegisterSequenceContextTransformer(passes, ctx, "$;", TokenValue(";"),
190 true),
191 RegisterSequenceContextTransformer(passes, ctx, "$,", TokenValue(","));
192 }
193
195
196 void
197 CopyEnvironmentDFS(Environment& d, const Environment& e)
198 {
199 // TODO: Support more implementations?
200 const auto copy_parent([&](Environment& dst, const Environment& parent){
201 auto p_env(make_shared<Environment>());
202
203 CopyEnvironmentDFS(*p_env, parent);
204 dst.Parent = std::move(p_env);
205 });
206 const auto copy_parent_ptr(
207 [&](Environment& dst, const ValueObject& vo) -> bool{
208 if(const auto p = AccessPtr<weak_ptr<Environment>>(vo))
209 {
210 if(const auto p_parent = p->lock())
211 copy_parent(dst, *p_parent);
212 // XXX: Failure of locking is ignored.
213 return true;
214 }
215 else if(const auto p_e = AccessPtr<shared_ptr<Environment>>(vo))
216 {
217 if(const auto p_parent = *p_e)
218 copy_parent(dst, *p_parent);
219 // XXX: Empty parent is ignored.
220 return true;
221 }
222 return {};
223 });
224 auto& m(d.GetMapRef());
225
226 copy_parent_ptr(d, e.Parent);
227 for(const auto& b : e.GetMapRef())
228 m.emplace(b.CreateWith([&](const ValueObject& vo) -> ValueObject{
229 Environment dst;
230
231 if(copy_parent_ptr(dst, vo))
232 return ValueObject(std::move(dst));
233 return vo;
234 }), b.GetName(), b.Value);
235 }
236
237 void
238 CopyEnvironment(TermNode& term, ContextNode& ctx)
239 {
240 auto p_env(make_shared<NPL::Environment>());
241
242 CopyEnvironmentDFS(*p_env, ctx.GetRecordRef());
243 term.Value = ValueObject(std::move(p_env));
244 }
246
247 } // unnamed namespace;
248
249 void
250 LoadNPLContextForSHBuild(REPLContext& context)
251 {
252 using namespace std::placeholders;
253 auto& root(context.Root);
254
255 LoadSequenceSeparators(root, context.ListTermPreprocess),
256 AccessLiteralPassesRef(root)
257 = [](TermNode& term, ContextNode&, string_view id) -> ReductionStatus{
258 YAssertNonnull(id.data());
259 if(!id.empty())
260 {
261 const char f(id.front());
262
263 // NOTE: Handling extended literals.
264 if(IsNPLAExtendedLiteralNonDigitPrefix(f) && id.size() > 1)
265 {
266 // TODO: Support numeric literal evaluation passes.
267 if(id == "#t" || id == "#true")
268 term.Value = true;
269 else if(id == "#f" || id == "#false")
270 term.Value = false;
271 else if(id == "#n" || id == "#null")
272 term.Value = nullptr;
273 // XXX: Redundant test?
274 else if(IsNPLAExtendedLiteral(id))
275 throw InvalidSyntax(f == '#' ? "Invalid literal found."
276 : "Unsupported literal prefix found.");
277 else
278 return ReductionStatus::Retrying;
279 }
280 else if(std::isdigit(f))
281 {
282 errno = 0;
283
284 const auto ptr(id.data());
285 char* eptr;
286 const long ans(std::strtol(ptr, &eptr, 10));
287
288 if(size_t(eptr - ptr) == id.size() && errno != ERANGE)
289 // XXX: Conversion to 'int' might be implementation-defined.
290 term.Value = int(ans);
291 // TODO: Supported literal postfix?
292 else
293 throw InvalidSyntax("Literal postfix is unsupported.");
294 }
295 else
296 return ReductionStatus::Retrying;
297 }
298 return ReductionStatus::Clean;
299 };
300 // NOTE: This is named after '#inert' in Kernel, but essentially
301 // unspecified in NPLA.
302 root.GetRecordRef().Define("inert", ValueToken::Unspecified, {});
303 // NOTE: Primitive features, listed as RnRK, except mentioned above.
304 /*
305 The primitives are provided here to maintain acyclic dependencies on derived
306 forms, also for simplicity of semantics.
307 The primitives are listed in order as Chapter 4 of Revised^-1 Report on the
308 Kernel Programming Language. Derived forms are not ordered likewise.
309 There are some difference of listed primitives.
310 See $2017-02 @ %Documentation::Workflow::Annual2017.
311 */
312 RegisterStrict(root, "eqv?", EqualValue);
313 // NOTE: Like Scheme but not Kernel, %'$if' treats non-boolean value as
314 // '#f', for zero overhead principle.
315 RegisterForm(root, "$if", If);
316 RegisterStrictUnary(root, "null?", IsEmpty);
317 // NOTE: Though NPLA does not use cons pairs, corresponding primitives are
318 // still necessary.
319 // NOTE: Since NPL has no con pairs, it only added head to existed list.
320 RegisterStrict(root, "cons", Cons);
321 // NOTE: The applicative 'copy-es-immutable' is unsupported currently due to
322 // different implementation of control primitives.
323 RegisterStrict(root, "eval", Eval);
324 // NOTE: This is now be primitive since in NPL environment capture is more
325 // basic than vau.
326 RegisterStrict(root, "copy-environment", CopyEnvironment);
327 RegisterStrict(root, "make-environment", MakeEnvironment);
328 RegisterStrict(root, "get-current-environment", GetCurrentEnvironment);
329 RegisterStrictUnary<shared_ptr<Environment>>(root, "weaken-environment",
330 [](const shared_ptr<Environment>& p){
331 return make_weak(p);
332 });
333 // NOTE: Environment mutation is optional in Kernel and supported here.
334 // NOTE: Lazy form '$deflazy!' is the basic operation, which may bind
335 // parameter as unevaluated operands. For zero overhead principle, the form
336 // without recursion (named '$def!') is preferred. The recursion variant
337 // (named '$defrec!') is exact '$define!' in Kernel, and is used only when
338 // necessary.
339 RegisterForm(root, "$deflazy!", DefineLazy);
340 RegisterForm(root, "$def!", DefineWithNoRecursion);
341 RegisterForm(root, "$defrec!", DefineWithRecursion);
342 RegisterForm(root, "$lambda", Lambda);
343 RegisterForm(root, "$vau", Vau);
344 RegisterForm(root, "$vaue", VauWithEnvironment);
345 RegisterStrictUnary<ContextHandler>(root, "wrap", Wrap);
346 RegisterStrictUnary<ContextHandler>(root, "unwrap", Unwrap);
347 // NOTE: Derived functions.
348 #if true
349 RegisterStrict(root, "list", ReduceToList);
350 #else
351 context.Perform(u8R"NPL($def! list wrap ($vau x #ignore x))NPL");
352 // context.Perform(u8R"NPL($def! list $lambda x x)NPL");
353 #endif
354 context.Perform(u8R"NPL(
355 $def! $quote $vau (x) #ignore x;
356 $def! $set! $vau (expr1 formals .expr2) env eval
357 (list $def! formals (unwrap eval) expr2 env) (eval expr1 env);
358 $def! $setrec! $vau (expr1 formals .expr2) env eval
359 (list $defrec! formals (unwrap eval) expr2 env) (eval expr1 env);
360 )NPL");
361 #if true
362 // NOTE: Some combiners are provided here as host primitives for
363 // more efficiency and less dependencies.
364 // NOTE: The sequence operator is also available as infix ';' syntax sugar.
365 RegisterForm(root, "$sequence", ReduceOrdered);
366 #else
367 // NOTE: They can be derived as Kernel does.
368 // XXX: The current environment is better to be saved by
369 // '$lambda () () get-current-environment'.
370 // TODO: Avoid redundant environment copy.
371 // TODO: Support move-only types at end.
372 context.Perform(u8R"NPL(
373 $def! $sequence
374 (
375 $lambda (cenv) ($lambda #ignore $vaue cenv body env
376 $if (null? body) inert (eval (cons $aux body) env))
377 ($setrec! cenv $aux $vaue (weaken-environment cenv) (head .tail)
378 env
379 $if (null? tail) (eval head env) (($lambda #ignore
380 (eval (cons $aux tail) env)) (eval head env)))
381 )
382 (
383 make-environment (() get-current-environment)
384 );
385 )NPL");
386 #endif
387 context.Perform(u8R"NPL(
388 $def! first $lambda ((x .)) x;
389 $def! rest $lambda ((#ignore .x)) x;
390 $def! apply $lambda (appv arg .opt)
391 eval (cons () (cons (unwrap appv) arg))
392 ($if (null? opt) (() make-environment) (first opt));
393 $defrec! list* $lambda (head .tail)
394 $if (null? tail) head
395 (cons head (apply list* tail));
396 $defrec! $cond $vau clauses env $sequence
397 (
398 $def! aux $lambda ((test .body) .clauses)
399 $if (eval test env) (eval body env)
400 (apply (wrap $cond) clauses env)
401 )
402 ($if (null? clauses) inert (apply aux clauses));
403 $def! $defl! $vau (f formals .body) env eval
404 (list $set! env f $lambda formals body) env;
405 $def! $defv! $vau ($f formals senv .body) env eval
406 (list $set! env $f $vau formals senv body) env;
407 $def! $defw! $vau (f formals senv .body) env eval
408 (list $set! env f wrap (list* $vau formals senv body)) env;
409 $defl! first-null? (l) null? (first l);
410 $defl! list-rest (x) list (rest x);
411 $defl! accl (l pred? base head tail sum)
412 (
413 $defrec! aux $lambda (l base)
414 $if (pred? l) base (aux (tail l) (sum (head l) base));
415 aux l base
416 );
417 $defl! accr (l pred? base head tail sum)
418 (
419 $defrec! aux $lambda (l)
420 $if (pred? l) base (sum (head l) (aux (tail l)));
421 aux l
422 );
423 $defl! foldr1 (kons knil l) accr l null? knil first rest kons;
424 $defl! list-concat (x y) foldr1 cons y x;
425 $defl! append (.ls) foldr1 list-concat () ls;
426 $defw! map1 (appv l) env foldr1
427 ($lambda (x xs) cons (apply appv (list x) env) xs) () l;
428 $defv! $let (bindings .body) env
429 eval (list* () (list* $lambda (map1 first bindings) body)
430 (map1 list-rest bindings)) env;
431 $defrec! $let* $vau (bindings .body) env
432 eval ($if (null? bindings) (list* $let bindings body)
433 (list $let (list (first bindings))
434 (list* $let* (rest bindings) body))) env;
435 )NPL");
436 // NOTE: Use of 'eqv?' is more efficient than '$if'.
437 context.Perform(u8R"NPL(
438 $defl! not? (x) eqv? x #f;
439 $defv! $when (test .vexpr) env $if (eval test env)
440 (eval (list* $sequence vexpr) env);
441 $defv! $unless (test .vexpr) env $if (not? (eval test env))
442 (eval (list* $sequence vexpr) env);
443 )NPL");
444 RegisterForm(root, "$and?", And);
445 RegisterForm(root, "$or?", Or);
446 context.Perform(u8R"NPL(
447 $defl! unfoldable? (l) accr l null? (first-null? l) first-null? rest
448 $or?;
449 $def! map-reverse wrap
450 (
451 $defl! cxrs (ls cxr) accl ls null? () ($lambda (l) cxr (first l))
452 rest cons;
453 $vau (appv .ls) env accl ls unfoldable? ()
454 ($lambda (ls) cxrs ls first) ($lambda (ls) cxrs ls rest)
455 ($lambda (x xs) cons (apply appv x env) xs)
456 );
457 $defw! for-each-ltr ls env $sequence (apply map-reverse ls env) inert;
458 )NPL");
459 // NOTE: Object interoperation.
460 RegisterStrict(root, "ref", [](TermNode& term){
461 CallUnary([&](TermNode& tm){
462 LiftToReference(term, tm);
463 }, term);
464 return CheckNorm(term);
465 });
466 // NOTE: Environments.
467 RegisterStrictUnary(root, "bound?",
468 [](TermNode& term, const ContextNode& ctx){
469 return ystdex::call_value_or([&](string_view id){
470 return CheckSymbol(id, [&](){
471 return bool(ResolveName(ctx, id));
472 });
473 }, AccessTermPtr<string>(term));
474 });
475 context.Perform(u8R"NPL(
476 $defv! $binds1? (expr s) env
477 eval (list (unwrap bound?) (symbol->string s)) (eval expr env);
478 )NPL");
479 RegisterStrict(root, "value-of", ValueOf);
480 // NOTE: String library.
481 RegisterStrict(root, "++", std::bind(CallBinaryFold<string, ystdex::plus<>>,
482 ystdex::plus<>(), string(), _1));
483 RegisterStrictUnary<const string>(root, "string-empty?",
484 std::mem_fn(&string::empty));
485 RegisterStrictBinary(root, "string<-", [](TermNode& x, const TermNode& y){
486 AccessTerm<string>(x) = AccessTerm<string>(y);
487 return ValueToken::Unspecified;
488 });
489 RegisterStrictBinary<string>(root, "string-contains-ci?",
490 [](string x, string y){
491 // TODO: Extract 'strlwr'.
492 const auto to_lwr([](string& s){
493 for(auto& c : s)
494 c = std::tolower(c);
495 });
496
497 to_lwr(x),
498 to_lwr(y);
499 return x.find(y) != string::npos;
500 });
501 RegisterStrictUnary<const string>(root, "string->symbol", StringToSymbol);
502 RegisterStrictUnary<const TokenValue>(root, "symbol->string",
503 SymbolToString);
504 RegisterStrictUnary<const string>(root, "string->regex",
505 [&](const string& str){
506 return std::regex(str);
507 });
508 RegisterStrict(root, "regex-match?", [](TermNode& term){
509 auto i(std::next(term.begin()));
510 const auto& str(AccessTerm<const string>(Deref(i)));
511 const auto& r(AccessTerm<const std::regex>(Deref(++i)));
512
513 term.ClearTo(std::regex_match(str, r));
514 }, ystdex::bind1(RetainN, 2));
515 // NOTE: I/O library.
516 RegisterStrictUnary<const string>(root, "puts", [&](const string& str){
517 // FIXME: Use %EncodeArg?
518 // XXX: Error is ignored.
519 std::puts(str.c_str());
520 });
521 // NOTE: Interoperation library.
522 RegisterStrictUnary<const string>(root, "env-get", [&](const string& var){
523 string res;
524
525 FetchEnvironmentVariable(res, var.c_str());
526 return res;
527 });
528 context.Perform(u8R"NPL(
529 $defl! env-empty? (n) string-empty? (env-get n);
530 )NPL");
531 RegisterStrict(root, "system", CallSystem);
532 // NOTE: SHBuild builtins.
533 root.GetRecordRef().Define("SHBuild_BaseTerminalHook_",
534 ValueObject(std::function<void(const string&, const string&)>(
535 [](const string& n, const string& val) ynothrow{
536 // XXX: Error from 'std::printf' is ignored.
537 std::printf("%s = \"%s\"\n", n.c_str(), val.c_str());
538 })), {});
539 RegisterStrictUnary<const string>(root, "SHBuild_BuildGCH_existed_",
540 [](const string& str) -> bool{
541 if(IO::UniqueFile
542 file{uopen(str.c_str(), IO::omode_convb(std::ios_base::in))})
543 return file->GetSize() > 0;
544 return {};
545 });
546 RegisterStrictUnary<const string>(root, "SHBuild_EnsureDirectory_",
547 [](const string& str){
548 EnsureDirectory(IO::Path(str));
549 });
550 RegisterStrictUnary<const string>(root, "SHBuild_BuildGCH_mkpdirp_",
551 [](const string& str){
552 IO::Path pth(str);
553
554 if(!pth.empty())
555 {
556 pth.pop_back();
557 EnsureDirectory(pth);
558 }
559 });
560 RegisterStrict(root, "SHBuild_EchoVar", [&](TermNode& term){
561 // XXX: To be overriden if %Terminal is usable (platform specific).
562 CallBinaryAs<const string>([&](const string& n, const string& val){
563 if(const auto p = GetValuePtrOf(root.GetRecordRef().LookupName(
564 "SHBuild_BaseTerminalHook_")))
565 if(const auto p_hook = AccessPtr<
566 std::function<void(const string&, const string&)>>(*p))
567 (*p_hook)(n, val);
568 }, term);
569 });
570 RegisterStrict(root, "SHBuild_Install_HardLink", [&](TermNode& term){
571 CallBinaryAs<const string>([](const string& dst, const string& src){
572 InstallHardLink(dst.c_str(), src.c_str());
573 }, term);
574 });
575 RegisterStrictUnary<const string>(root, "SHBuild_QuoteS_",
576 [](const string& str){
577 if(str.find('\'') == string::npos)
578 return ystdex::quote(str, '\'');
579 throw NPLException("Error in quoted string.");
580 });
581 RegisterStrictUnary<const string>(root, "SHBuild_RaiseError_",
582 [](const string& str) YB_NORETURN{
583 throw LoggedEvent(str);
584 });
585 RegisterStrictBinary<const string>(root, "SHBuild_RemovePrefix_",
586 [&](const string& str, const string& pfx) -> string{
587 if(ystdex::begins_with(str, pfx))
588 return str.substr(pfx.length());
589 return str;
590 });
591 RegisterStrictUnary<const string>(root, "SHBuild_SDot_",
592 [](const string& str){
593 auto res(str);
594
595 for(auto& c : res)
596 if(c == '.')
597 c = '_';
598 return res;
599 });
600 RegisterStrictUnary<const string>(root, "SHBuild_TrimOptions_",
601 [](const string& src){
602 string res;
603
604 for(const auto& str
605 : Session(src, [&](LexicalAnalyzer& lexer, char c){
606 lexer.ParseByte(c, NPLUnescape, IgnorePrefix);
607 }).Lexer.Literalize())
608 {
609 using iter_t = string::const_iterator;
610
611 ystdex::split_l(str.cbegin(), str.cend(), static_cast<int(&)(int)>(
612 std::isspace), [&](iter_t b, iter_t e){
613 string s(b, e);
614
615 ystdex::trim(s);
616 if(!s.empty())
617 {
618 res += s;
619 res += ' ';
620 }
621 });
622 }
623 if(!res.empty())
624 res.pop_back();
625 return res;
626 });
627 // NOTE: Params of %SHBuild_BuildGCH: header = path of header to be copied,
628 // inc = path of header to be included, cmd = tool to build header.
629 context.Perform(u8R"NPL(
630 $defl! SHBuild_EchoVar_N (var) SHBuild_EchoVar var
631 (env-get (SHBuild_SDot_ var));
632 $defl! SHBuild_BuildGCH (header inc cmd)
633 (
634 $def! pch (++ inc ".gch");
635 $if (SHBuild_BuildGCH_existed_ pch)
636 (puts (++ "PCH file \"" pch "\" exists, skipped building."))
637 (
638 SHBuild_BuildGCH_mkpdirp_ pch;
639 puts (++ "Building precompiled file \"" pch "\" ...");
640 SHBuild_Install_HardLink inc header;
641 system (++ cmd " \"" header "\" -o" pch);
642 puts (++ "Building precompiled file \"" pch "\" done.")
643 )
644 );
645 )NPL");
646 }
647
648 } // namespace Forms;
649
650 } // namespace A1;
651
652 } // namespace NPL;
653
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:313
ystdex::bind1
auto bind1(_func &&f, _tParams &&...args) -> decltype(std::bind(std::forward< decltype(f)>(f), std::placeholders::_1, std::forward< decltype(args)>(args)...))
复合调用 std::bind 和 std::placeholders::_1 。
Definition: functional.hpp:623
NPL::A1::RegisterForm
void RegisterForm(ContextNode &ctx, const string &name, _tParams &&...args)
Definition: NPLA1.h:619
NPL::InstallHardLink
YF_API const char src const string const char const char *src void InstallHardLink(const char *, const char *)
NPL::A1::Forms::CallUnary
void CallUnary(_func &&f, TermNode &term, _tParams &&...args)
访问节点并调用一元函数。
Definition: NPLA1.h:1059
NPL::dst
YF_API const char src const string const char * dst
Definition: Dependency.h:95
NPL::A1::Forms::EqualValue
YF_API void EqualValue(TermNode &)
比较两个子项的值相等。
Definition: NPLA1.cpp:1378
NPL::A1::Forms::CallBinaryFold
void CallBinaryFold(_func f, _type val, TermNode &term, _tParams &&...args)
访问节点并以指定的初始值为基础逐项调用二元函数。
Definition: NPLA1.h:1121
ystdex::isdigit
bool isdigit(char c)
区域无关的 std::isdigit 实现。
Definition: cctype.h:122
ystdex::begins_with
bool begins_with(const _tRange1 &input, const _tRange2 &test, _fPred comp)
判断第一个参数指定的串是否以第二个参数起始。
Definition: string.hpp:398
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
NPL::InstallDirectory
YF_API const char src const string InstallDirectory
Definition: Dependency.h:95
NPL::EvaluationPasses
GPasses< TermNode &, ContextNode & > EvaluationPasses
求值合并遍。
Definition: NPLA.h:947
NPL::LiftToReference
void LiftToReference(TermNode &term, TermNode &tm)
Definition: NPLA.cpp:482
YSLib::Environment
应用程序环境。
Definition: Environment.h:62
platform::HaveSameContents
YF_API bool HaveSameContents(UniqueFile, UniqueFile, const char *, const char *)
Definition: FileIO.cpp:1242
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:451
YSLib::UI::y
SPos SPos y
Definition: YWidget.cpp:44
NPL::x
const TermNode &term ynothrow const TermNode &term ynothrow const TermNode &term ynothrow TermNode &term const TermNode &term ValueNode &node const ValueNode &node const _type & x
Definition: SContext.h:94
NPL::A1::Forms::StringToSymbol
YF_API TokenValue StringToSymbol(const string &)
创建等于指定字符串值的记号值。
Definition: NPLA1.cpp:1045
ystdex::tolower
_tChar tolower(_tChar c)
转换大小写字符。
Definition: cctype.h:136
YSLib::Drawing::r
The boundary is out of the const Graphics const Rect const Point const Point Color c const Rect const Rect & r
Definition: YDraw.h:174
ystdex::make_weak
std::weak_ptr< _type > make_weak(const std::shared_ptr< _type > &p)
使用指定的 std::shared_ptr 实例的对象创建对应的 std::weak_ptr 实例的对象。
Definition: memory.hpp:956
NPL::A1::Forms::Wrap
YF_API ContextHandler Wrap(const ContextHandler &)
包装合并子为应用子。
Definition: NPLA1.cpp:1447
YModules.h
CHRLib::f
f(d, s)
YSLib::IO::EnsureDirectory
void EnsureDirectory(const Path &pth)
Definition: YSLib/Service/FileSystem.cpp:106
ystdex::call_value_or
auto call_value_or(_func f, _type &&p) -> decay_t< decltype(f(*std::forward< decltype(p)>(p)))>
调用非空值或取默认值。
Definition: deref_op.hpp:140
NPL::A1::RegisterStrict
void RegisterStrict(ContextNode &ctx, const string &name, _tParams &&...args)
注册严格上下文处理器。
Definition: NPLA1.h:640
NPL::A1::RegisterSequenceContextTransformer
YF_API void RegisterSequenceContextTransformer(EvaluationPasses &, ContextNode &, const TokenValue &, const ValueObject &, bool={})
注册分隔符转换变换和处理例程。
Definition: NPLA1.cpp:787
NPL::A1::Forms::Cons
YF_API ReductionStatus Cons(TermNode &)
接受两个参数，返回以第一个参数作为首项插入第二个参数创建的新的列表。
Definition: NPLA1.cpp:1332
platform::bool
std::FILE *fp bool
Definition: FileIO.h:1280
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:120
ystdex::empty
auto empty(const _tRange &c) -> decltype(c.empty())
Definition: range.hpp:255
NPL::A1::Forms::CallSystem
YF_API void CallSystem(TermNode &)
调用 UTF-8 字符串的系统命令，并保存 int 类型的结果到项的值中。
Definition: NPLA1.cpp:1325
NPL::c_str
YF_API const char src c_str())) YF_API void InstallDirectory(const string &
安装目录：复制目录树。
Definition: Dependency.h:131
YSLib::GetValuePtrOf
observer_ptr< const ValueObject > GetValuePtrOf(observer_ptr< const ValueNode > p_node)
Definition: ValueNode.cpp:150
NPL::A1::Forms::If
YF_API ReductionStatus If(TermNode &, ContextNode &)
条件判断：根据求值的条件取表达式。
Definition: NPLA1.cpp:1236
NPL::ReductionStatus
ReductionStatus
规约状态：一遍规约可能的中间结果。
Definition: NPLA.h:633
platform::UniqueFile
unique_ptr_from< FileDescriptor::Deleter > UniqueFile
Definition: FileIO.h:464
YSLib::LoggedEvent
记录日志的异常事件类。
Definition: YException.h:50
platform::omode_convb
std::ios_base::sync_with_stdio(sync)) YF_API YB_STATELESS int omode_conv(std YF_API YB_STATELESS int omode_convb(std::ios_base::openmode) ynothrow
ISO C++ 标准输入输出接口打开模式转换为 POSIX 文件打开模式。
Definition: FileIO.cpp:840
YSLib::Text::buf
const char * buf
Definition: TextFile.h:81
ystdex::data
auto data(_tRange &c) -> decltype(c.data())
Definition: range.hpp:280
NPL::A1::Forms::MakeEnvironment
YF_API void MakeEnvironment(TermNode &)
创建以参数指定的环境列表作为父环境的新环境。 异常中立：由 Environment 的构造函数抛出。 ...
Definition: NPLA1.cpp:1405
NPL::NPLUnescape
YF_API bool NPLUnescape(string &, const UnescapeContext &, char)
NPL 转义匹配算法。
Definition: Lexical.cpp:58
NPL::DecomposeMakefileDepList
YF_API vector< string > DecomposeMakefileDepList(std::streambuf &)
从内容为 GCC 兼容编译器 -MMD 选项生成的 Makefile 的流中分解路径。
ystdex::split_if
void split_if(_tIn b, _tIn e, _fPred is_delim, _fInsert insert, _func pred)
以满足迭代器谓词的指定分隔符分割序列。
Definition: algorithm.hpp:235
NPL::A1::Forms::CheckSymbol
auto CheckSymbol(string_view n, _func f) -> decltype(f())
检查记号值是符合匹配条件的符号。
Definition: NPLA1.h:970
NPL::A1::Forms::SymbolToString
YF_API const string & SymbolToString(const TokenValue &) ynothrow
取符号对应的名称字符串。
Definition: NPLA1.cpp:1051
NPL::A1::Forms::Lambda
YF_API void Lambda(TermNode &, ContextNode &)
λ 抽象：求值为一个捕获当前上下文的严格求值的函数。
Definition: NPLA1.cpp:1261
platform::uopen
int uopen(const char *filename, int oflag, mode_t pmode) ynothrowv
Definition: FileIO.cpp:873
TryExpr
#define TryExpr(...)
指定表达式在 try 块中求值。
Definition: YBaseMacro.h:120
NPL::A1::Forms::DefineWithRecursion
YF_API void DefineWithRecursion(TermNode &, ContextNode &)
Definition: NPLA1.cpp:1204
platform::CreateSymbolicLink
void CreateSymbolicLink(const char *dst, const char *src, bool is_dir)
Definition: YCLib/FileSystem.cpp:198
NPL::A1::Forms::ValueOf
YF_API ReductionStatus ValueOf(TermNode &, const ContextNode &)
求值标识符得到指称的实体。
Definition: NPLA1.cpp:1434
YSLib::IO::VerifyDirectory
bool VerifyDirectory(const char *path)
Definition: YSLib/Service/FileSystem.cpp:95
ystdex::quote
_tString quote(const _tString &str, typename string_traits< _tString >::value_type c=typename string_traits< _tString >::value_type('"'))
取添加前缀和后缀的字符串。
Definition: string.hpp:801
NPL::ReduceToList
YF_API ReductionStatus ReduceToList(TermNode &) ynothrow
规约为列表：对枝节点移除第一个子项，保留余下的子项作为列表。
Definition: NPLA.cpp:523
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
ystdex::split_l
_tIn split_l(_tIn b, _tIn e, _fPred is_delim, _fInsert insert)
以指定分隔符分割保留起始分隔符的序列。
Definition: algorithm.hpp:263
YSLib::ValueObject
值类型对象类。
Definition: YObject.h:539
NPL::A1::ReduceOrdered
YF_API ReductionStatus ReduceOrdered(TermNode &, ContextNode &)
规约有序序列：顺序规约子项，结果为最后一个子项的规约结果。
Definition: NPLA1.cpp:663
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
ystdex::exists
bool exists(const _tCon &con, const _tKey &key)
判断指定的容器中存在指定的键。
Definition: container.hpp:681
YSLib::IO::TraverseTree
const string &path const String &path class class class class typename _tParams auto TraverseTree(_func f, const Path &dst, const Path &src, _tParams &&...args) -> decltype(f(std::declval< Path & >(), std::declval< Path & >(), std::forward< _tParams >(args)...))
Definition: YSLib/Service/FileSystem.h:673
NPL::TermNode
yimpl(ValueNode) TermNode
项节点：存储语法分析结果的值类型节点。
Definition: SContext.h:51
NPL::FilterMakefileDependencies
YF_API bool FilterMakefileDependencies(vector< string > &)
过滤 GCC 兼容编译器 -MMD 选项生成的 Makefile 项列表并选取依赖项。
YSLib::i
return i
Definition: YCoreUtilities.h:176
NPL::A1::Forms::Vau
YF_API void Vau(TermNode &, ContextNode &)
vau 抽象：求值为一个捕获当前上下文的非严格求值的函数。
Definition: NPLA1.cpp:1277
YSLib::IO::PreserveModificationTime
const auto PreserveModificationTime(ystdex::bind_forward(&FileDescriptor::SetModificationTime,&FileDescriptor::GetModificationTime))
保持修改时间。
NPL::InstallExecutable
src void InstallExecutable(const char *, const char *)
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:168
ystdex::fseq::front
identity< _type > front(empty_base< _type, _types... >)
Definition: variadic.hpp:74
NPL::A1::Forms::Unwrap
YF_API ContextHandler Unwrap(const ContextHandler &)
从应用子中取操作子。
Definition: NPLA1.cpp:1462
string.hpp
ISO C++ 标准字符串扩展。
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:109
NPL::A1::Forms::RegisterStrictBinary
void RegisterStrictBinary(ContextNode &ctx, const string &name, _func f)
注册二元严格求值上下文处理器。
Definition: NPLA1.h:1298
platform::uremove
bool uremove(const char *path) ynothrowv
Definition: FileIO.cpp:1083
YSLib::IO
Definition: YAdaptor.h:391
NPL::A1::ResolveName
YF_API observer_ptr< ValueNode > ResolveName(const ContextNode &, string_view)
解析名称：处理保留名称并查找名称。
Definition: NPLA1.cpp:939
NPL::A1::Forms::DefineWithNoRecursion
YF_API void DefineWithNoRecursion(TermNode &, ContextNode &)
Definition: NPLA1.cpp:1195
NPL
Definition: NPL/Configuration.h:34
YSLib::IO::CopyFile
YF_API void CopyFile(UniqueFile, FileDescriptor)
复制文件。
Definition: YSLib/Service/FileSystem.cpp:137
YB_NORETURN
#define YB_NORETURN
指定无返回值函数。
Definition: ydef.h:504
platform::Descriptions::Err
Definition: YCommon.h:166
NPL::A1::Forms::RetainN
ReductionStatus::Retained YF_API size_t RetainN(const TermNode &, size_t=1)
保留经检查确保具有指定个数参数的项：保留求值。
Definition: NPLA1.cpp:1058
platform::CreateHardLink
void CreateHardLink(const char *dst, const char *src)
Definition: YCLib/FileSystem.cpp:167
YSLib::Text::str
const char const char * str
Definition: TextFile.h:81
CHRLib::c
c
Definition: CharacterProcessing.h:81
NPL::A1::Forms::VauWithEnvironment
YF_API void VauWithEnvironment(TermNode &, ContextNode &)
带环境的 vau 抽象：求值为一个捕获当前上下文的非严格求值的函数。
Definition: NPLA1.cpp:1292
NPL::A1::Forms::And
YF_API ReductionStatus And(TermNode &, ContextNode &)
逻辑与。
Definition: NPLA1.cpp:1312
YSLib::IO::Path
路径。
Definition: YSLib/Service/FileSystem.h:214
CHRLib::d
_tDst * d
Definition: CharacterProcessing.h:139
NPL::A1::Forms::Or
YF_API ReductionStatus Or(TermNode &, ContextNode &)
逻辑或。
Definition: NPLA1.cpp:1318
ystdex::size
auto size(const _tRange &c) -> decltype(c.size())
类容器访问。
Definition: range.hpp:233
YSLib::vo
vo
Definition: YApplication.h:231
YSLib::IO::int
YF_API int
Definition: File.h:51
NPL::A1::Forms::Eval
YF_API ReductionStatus Eval(TermNode &, ContextNode &)
对指定项按指定的环境求值。
Definition: NPLA1.cpp:1384
YB_ATTR_fallthrough
#define YB_ATTR_fallthrough
用于 switch 语句的 fallthrough 属性。
Definition: ydef.h:383
NPL::A1::Forms::DefineLazy
YF_API void DefineLazy(TermNode &, ContextNode &)
定义。 绑定匹配失败。
Definition: NPLA1.cpp:1187
NPL::A1::AccessLiteralPassesRef
YF_API LiteralPasses & AccessLiteralPassesRef(ContextNode &)
访问字面量遍。
Definition: NPLA1.cpp:520
ystdex::trim
_tString && trim(_tString &&str, typename string_traits< _tString >::value_type c)
删除字符串中指定的连续前缀与后缀字符。
Definition: string.hpp:707
NPL::IsEmpty
IsEmpty
Definition: SContext.h:64
NPL::IsNPLAExtendedLiteral
YF_API bool IsNPLAExtendedLiteral(string_view) ynothrowv
判断不是非扩展字面量的词素是否为 NPLA 扩展字面量。
Definition: NPLA.cpp:395
NPL::A1::Forms::RegisterStrictUnary
void RegisterStrictUnary(ContextNode &ctx, const string &name, _func f)
注册一元严格求值上下文处理器。
Definition: NPLA1.h:1279
NPL::A1::Forms::GetCurrentEnvironment
YF_API void GetCurrentEnvironment(TermNode &, ContextNode &)
取包含当前环境的上下文引用。
Definition: NPLA1.cpp:1427
YSLib::ExtractAndTrace
YF_API void ExtractAndTrace(const std::exception &, RecordLevel=Err) ynothrow
使用 TraceException 展开和跟踪异常类型和信息。
ystdex::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:415
NPL::InstallSymbolicLink
src void InstallSymbolicLink(const char *, const char *)
YSLib::FetchEnvironmentVariable
bool FetchEnvironmentVariable(string &res, const char *var)
Definition: YCoreUtilities.cpp:46
CHRLib::p
const auto p(d)