YSTest: NPLA1.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

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

- 文件列表
- 文件成员

NPLA1.cpp
浏览该文件的文档.
1 /*
2 © 2014-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_NPLA1 // for ystdex::bind1, unordered_map, ystdex::pvoid,
30 // ystdex::call_value_or, ystdex::as_const, ystdex::ref;
31 #include <ystdex/cast.hpp> // for ystdex::polymorphic_downcast;
32 #include <ystdex/scope_guard.hpp> // for ystdex::unique_guard;
33 #include YFM_NPL_SContext // for Session;
34
35 using namespace YSLib;
36
37 namespace NPL
38 {
39
40 namespace A1
41 {
42
43 string
44 to_string(ValueToken vt)
45 {
46 switch(vt)
47 {
48 case ValueToken::Null:
49 return "null";
50 case ValueToken::Undefined:
51 return "undefined";
52 case ValueToken::Unspecified:
53 return "unspecified";
54 case ValueToken::GroupingAnchor:
55 return "grouping";
56 case ValueToken::OrderedAnchor:
57 return "ordered";
58 }
59 throw std::invalid_argument("Invalid value token found.");
60 }
61
62 void
63 InsertChild(TermNode&& term, TermNode::Container& con)
64 {
65 con.insert(term.GetName().empty() ? AsNode('$' + MakeIndex(con),
66 std::move(term.Value)) : std::move(MapToValueNode(term)));
67 }
68
69 void
70 InsertSequenceChild(TermNode&& term, NodeSequence& con)
71 {
72 con.emplace_back(std::move(MapToValueNode(term)));
73 }
74
75 ValueNode
76 TransformNode(const TermNode& term, NodeMapper mapper, NodeMapper map_leaf_node,
77 NodeToString node_to_str, NodeInserter insert_child)
78 {
79 auto s(term.size());
80
81 if(s == 0)
82 return map_leaf_node(term);
83
84 auto i(term.begin());
85 const auto nested_call(ystdex::bind1(TransformNode, mapper, map_leaf_node,
86 node_to_str, insert_child));
87
88 if(s == 1)
89 return nested_call(*i);
90
91 const auto& name(node_to_str(*i));
92
93 if(!name.empty())
94 yunseq(++i, --s);
95 if(s == 1)
96 {
97 auto&& nd(nested_call(*i));
98
99 if(nd.GetName().empty())
100 return AsNode(name, std::move(nd.Value));
101 return {ValueNode::Container{std::move(nd)}, name};
102 }
103
104 ValueNode::Container node_con;
105
106 std::for_each(i, term.end(), [&](const TermNode& tm){
107 insert_child(mapper ? mapper(tm) : nested_call(tm), node_con);
108 });
109 return {std::move(node_con), name};
110 }
111
112 ValueNode
113 TransformNodeSequence(const TermNode& term, NodeMapper mapper, NodeMapper
114 map_leaf_node, NodeToString node_to_str, NodeSequenceInserter insert_child)
115 {
116 auto s(term.size());
117
118 if(s == 0)
119 return map_leaf_node(term);
120
121 auto i(term.begin());
122 auto nested_call(ystdex::bind1(TransformNodeSequence, mapper,
123 map_leaf_node, node_to_str, insert_child));
124
125 if(s == 1)
126 return nested_call(*i);
127
128 const auto& name(node_to_str(*i));
129
130 if(!name.empty())
131 yunseq(++i, --s);
132 if(s == 1)
133 {
134 auto&& n(nested_call(*i));
135
136 return AsNode(name, n.GetName().empty() ? std::move(n.Value)
137 : ValueObject(NodeSequence{std::move(n)}));
138 }
139
140 NodeSequence node_con;
141
142 std::for_each(i, term.end(), [&](const TermNode& tm){
143 insert_child(mapper ? mapper(tm) : nested_call(tm), node_con);
144 });
145 return AsNode(name, std::move(node_con));
146 }
147
148
150 namespace
151 {
152
154 template<typename _func>
155 TermNode
156 TransformForSeparatorTmpl(_func f, const TermNode& term, const ValueObject& pfx,
157 const ValueObject& delim, const string& name)
158 {
159 using namespace std::placeholders;
160 // NOTE: Explicit type 'TermNode' is intended.
161 TermNode res(AsNode(name, term.Value));
162
163 if(IsBranch(term))
164 {
165 // NOTE: Explicit type 'TermNode' is intended.
166 res += TermNode(AsIndexNode(res, pfx));
167 ystdex::split(term.begin(), term.end(),
168 ystdex::bind1(HasValue<ValueObject>, std::ref(delim)),
169 std::bind(f, std::ref(res), _1, _2));
170 }
171 return res;
172 }
173
175 ReductionStatus
176 AndOr(TermNode& term, ContextNode& ctx, bool is_and)
177 {
178 Forms::Retain(term);
179
180 auto i(term.begin());
181
182 if(++i != term.end())
183 {
184 if(std::next(i) == term.end())
185 LiftTerm(term, *i);
186 else
187 {
188 ReduceChecked(*i, ctx);
189 if(ystdex::value_or(AccessTermPtr<bool>(*i), is_and) == is_and)
190 term.Remove(i);
191 else
192 {
193 if(is_and)
194 term.Value = false;
195 else
196 // TODO: Support preserving subterms.
197 LiftTerm(term, i->Value);
198 // NOTE: The following is not memory safe.
199 // LiftTerm(term, *i);
200 term.Remove(i);
201 return ReductionStatus::Clean;
202 }
203 }
204 return ReductionStatus::Retrying;
205 }
206 term.Value = is_and;
207 return ReductionStatus::Clean;
208 }
209
211 template<typename _func>
212 void
213 EqualTerm(TermNode& term, _func f)
214 {
215 Forms::RetainN(term, 2);
216
217 auto i(term.begin());
218 const auto& x(Deref(++i));
219
220 term.Value = f(ReferenceTerm(x).Value, ReferenceTerm(Deref(++i)).Value);
221 }
222
223
225 class RecursiveThunk final
226 : private yimpl(noncopyable), private yimpl(nonmovable)
227 {
228 private:
230
231 using shared_ptr_t = shared_ptr<ContextHandler>;
232 unordered_map<string, shared_ptr_t> store{};
233 shared_ptr_t
234 p_defualt{make_shared<ContextHandler>(ThrowInvalidCyclicReference)};
236
237 public:
239 Environment& Record;
241 const TermNode& Term;
242
244
245 RecursiveThunk(Environment& env, const TermNode& t)
246 : Record(env), Term(t)
247 {
248 Fix(Record, Term, p_defualt);
249 }
250
251 private:
252 void
253 Fix(Environment& env, const TermNode& t, const shared_ptr_t& p_d)
254 {
255 if(IsBranch(t))
256 for(const auto& tm : t)
257 Fix(env, tm, p_d);
258 else if(const auto p = AccessPtr<TokenValue>(t))
259 {
260 const auto& n(*p);
261
262 // XXX: This is served as addtional static environment.
263 Forms::CheckParameterLeafToken(n, [&]{
264 // TODO: The symbol can be rebound?
265 env.GetMapRef()[n].SetContent(TermNode::Container(),
266 ValueObject(ystdex::any_ops::use_holder, ystdex::in_place<
267 HolderFromPointer<weak_ptr<ContextHandler>>>,
268 store[n] = p_d));
269 });
270 }
271 }
272
273 void
274 Restore(Environment& env, const TermNode& t)
275 {
276 if(IsBranch(t))
277 for(const auto& tm : t)
278 Restore(env, tm);
279 else if(const auto p = AccessPtr<TokenValue>(t))
280 FilterExceptions([&]{
281 const auto& n(*p);
282 auto& v(env.GetMapRef()[n].Value);
283
284 if(v.type() == ystdex::type_id<ContextHandler>())
285 {
286 // XXX: The element should exist.
287 auto& p_strong(store.at(n));
288
289 Deref(p_strong) = std::move(v.GetObject<ContextHandler>());
290 v = ValueObject(ystdex::any_ops::use_holder,
291 ystdex::in_place<HolderFromPointer<shared_ptr_t>>,
292 std::move(p_strong));
293 }
294 });
295 }
297
299 YB_NORETURN static ReductionStatus
300 ThrowInvalidCyclicReference(TermNode&, ContextNode&)
301 {
302 throw NPLException("Invalid cyclic reference found.");
303 }
304
305 public:
306 PDefH(void, Commit, )
307 ImplExpr(Restore(Record, Term))
308 };
309
310
312 template<typename _func>
313 void
314 DoDefine(TermNode& term, _func f)
315 {
316 Forms::Retain(term);
317 if(term.size() > 2)
318 {
319 RemoveHead(term);
320
321 auto formals(std::move(Deref(term.begin())));
322
323 RemoveHead(term);
324 LiftToSelf(formals);
325 f(formals);
326 }
327 else
328 throw InvalidSyntax("Insufficient terms in definition.");
329 term.Value = ValueToken::Unspecified;
330 }
331
332
334 YB_NONNULL(2) void
335 CheckVauSymbol(const TokenValue& s, const char* target)
336 {
337 if(s != "#ignore")
338 {
339 if(!IsNPLASymbol(s))
340 throw InvalidSyntax(ystdex::sfmt("Token '%s' is not a symbol or"
341 " '#ignore' expected for %s.", s.data(), target));
342 }
343 }
344
346 YB_NORETURN YB_NONNULL(2) void
347 ThrowInvalidSymbolType(const TermNode& term, const char* n)
348 {
349 throw InvalidSyntax(ystdex::sfmt("Invalid %s type '%s' found.", n,
350 term.Value.type().name()));
351 }
352
354 string
355 CheckEnvFormal(const TermNode& term)
356 {
357 if(const auto p = TermToNamePtr(term))
358 {
359 CheckVauSymbol(*p, "environment formal parameter");
360 return *p;
361 }
362 else
363 ThrowInvalidSymbolType(term, "environment formal parameter");
364 return {};
365 }
366
368 string
369 ReferenceEnvFormal(TermNode& term)
370 {
371 LiftToSelf(term);
372 return CheckEnvFormal(term);
373 }
374
375
377 class VauHandler final
378 {
379 private:
384 string eformal{};
390 shared_ptr<TermNode> p_formals;
396 ContextNode local_prototype;
403 weak_ptr<Environment> p_parent;
406 shared_ptr<Environment> p_static;
408 shared_ptr<TermNode> p_closure;
410
411 public:
416 VauHandler(string&& ename, shared_ptr<TermNode>&& p_fm,
417 shared_ptr<Environment>&& p_env, bool owning,
418 const ContextNode& ctx, TermNode& term)
419 : eformal(std::move(ename)), p_formals((LiftToSelf(Deref(p_fm)),
420 std::move(p_fm))),
421 local_prototype(ctx, make_shared<Environment>()), p_parent(p_env),
422 p_static(owning ? std::move(p_env) : nullptr),
423 p_closure(share_move(term))
424 {
425 CheckParameterTree(*p_formals);
426 }
427
429 ReductionStatus
430 operator()(TermNode& term, ContextNode& ctx) const
431 {
432 if(IsBranch(term))
433 {
434 using namespace Forms;
435 const auto& formals(Deref(p_formals));
436 // NOTE: Local context: active record frame with outer scope
437 // bindings.
438 // XXX: Referencing escaped variables (now only parameters need
439 // to be cared) form the context would cause undefined behavior
440 // (e.g. returning a reference to automatic object in the host
441 // language). See %BindParameter.
442 ContextNode local(local_prototype, make_shared<Environment>());
443 auto& local_m(local.GetBindingsRef());
444
445 // NOTE: Bound dynamic context.
446 if(!eformal.empty())
447 local_m.AddValue(eformal, ValueObject(ctx.WeakenRecord()));
448 // NOTE: Since first term is expected to be saved (e.g. by
449 // %ReduceCombined), it is safe to reduce directly.
450 RemoveHead(term);
451 BindParameter(local, formals, term);
452 YTraceDe(Debug, "Function called, with %ld shared term(s), %ld %s"
453 " shared static environment(s), %zu parameter(s).",
454 p_closure.use_count(), p_parent.use_count(),
455 p_static.use_count() != 0 ? "owning" : "nonowning",
456 formals.size());
457 // NOTE: Static environment is bound as base of local context by
458 // setting parent environment pointer.
459 local.GetRecordRef().Parent = p_parent;
460 // NOTE: Beta reduction.
461 // TODO: Implement accurate lifetime analysis rather than
462 // 'p_closure.unique()'.
463 ReduceCheckedClosure(term, local, {}, *p_closure);
464 return CheckNorm(term);
465 }
466 else
467 throw LoggedEvent("Invalid composition found.", Alert);
468 }
469
471 static void
472 CheckParameterTree(const TermNode& term)
473 {
474 for(const auto& child : term)
475 CheckParameterTree(child);
476 if(term.Value)
477 {
478 if(const auto p = TermToNamePtr(term))
479 CheckVauSymbol(*p, "parameter in a parameter tree");
480 else
481 ThrowInvalidSymbolType(term, "parameter tree node");
482 }
483 }
484 };
485
486
488 template<typename _func>
489 void
490 CreateFunction(TermNode& term, _func f, size_t n)
491 {
492 Forms::Retain(term);
493 if(term.size() > n)
494 term.Value = ContextHandler(f(term.GetContainerRef()));
495 else
496 throw InvalidSyntax("Insufficient terms in function abstraction.");
497 }
498
499 } // unnamed namespace;
500
501 GuardPasses&
502 AccessGuardPassesRef(ContextNode& ctx)
503 {
504 return ctx.Guard;
505 }
506
507 EvaluationPasses&
508 AccessLeafPassesRef(ContextNode& ctx)
509 {
510 return ctx.EvaluateLeaf;
511 }
512
513 EvaluationPasses&
514 AccessListPassesRef(ContextNode& ctx)
515 {
516 return ctx.EvaluateList;
517 }
518
519 LiteralPasses&
520 AccessLiteralPassesRef(ContextNode& ctx)
521 {
522 return ctx.EvaluateLiteral;
523 }
524
525 Guard
526 InvokeGuard(TermNode& term, ContextNode& ctx)
527 {
528 return ctx.Guard(term, ctx);
529 }
530
531 ReductionStatus
532 InvokeLeaf(TermNode& term, ContextNode& ctx)
533 {
534 return ctx.EvaluateLeaf(term, ctx);
535 }
536
537 ReductionStatus
538 InvokeList(TermNode& term, ContextNode& ctx)
539 {
540 return ctx.EvaluateList(term, ctx);
541 }
542
543 ReductionStatus
544 InvokeLiteral(TermNode& term, ContextNode& ctx, string_view id)
545 {
546 YAssertNonnull(id.data());
547 return ctx.EvaluateLiteral(term, ctx, id);
548 }
549
550
551 ReductionStatus
552 Reduce(TermNode& term, ContextNode& ctx)
553 {
554 const auto gd(InvokeGuard(term, ctx));
555
556 // NOTE: Rewriting loop until the normal form is got.
557 return ystdex::retry_on_cond(CheckReducible, [&]() -> ReductionStatus{
558 if(IsBranch(term))
559 {
560 YAssert(term.size() != 0, "Invalid node found.");
561 if(term.size() != 1)
562 // NOTE: List evaluation.
563 return InvokeList(term, ctx);
564 else
565 {
566 // NOTE: List with single element shall be reduced as the
567 // element.
568 LiftFirst(term);
569 return Reduce(term, ctx);
570 }
571 }
572
573 const auto& tp(term.Value.type());
574
575 // NOTE: Empty list or special value token has no-op to do with.
576 // TODO: Handle special value token?
577 return tp != ystdex::type_id<void>() && tp != ystdex::type_id<
578 ValueToken>() ? InvokeLeaf(term, ctx) : ReductionStatus::Clean;
579 });
580 }
581
582 void
583 ReduceArguments(TNIter first, TNIter last, ContextNode& ctx)
584 {
585 if(first != last)
586 // NOTE: The order of evaluation is unspecified by the language
587 // specification. It should not be depended on.
588 ReduceChildren(++first, last, ctx);
589 else
590 throw InvalidSyntax("Invalid function application found.");
591 }
592
593 void
594 ReduceChecked(TermNode& term, ContextNode& ctx)
595 {
596 CheckedReduceWith(Reduce, term, ctx);
597 }
598
599 void
600 ReduceCheckedClosure(TermNode& term, ContextNode& ctx, bool move,
601 TermNode& closure)
602 {
603 TermNode comp_term(NoContainer, term.GetName());
604
605 if(move)
606 LiftTerm(comp_term, closure);
607 else
608 comp_term.SetContent(closure);
609 // TODO: Test for normal form?
610 // XXX: Term reused.
611 ReduceChecked(comp_term, ctx);
612 // TODO: Detect lifetime escape to perform copy elision.
613 #if true
614 // NOTE: To keep lifetime of objects referenced by references introduced in
615 // %EvaluateIdentifier sane, %ValueObject::MakeMoveCopy is not enough
616 // because it will not copy object referenced in holders of
617 // %YSLib::RefHolder instances). On the other hand, the references captured
618 // by vau handlers (which requries recursive copy of vau handler members if
619 // forced) are not blessed here to avoid leak abstraction of detailed
620 // implementation of vau handlers; it can be checked by the vau handler
621 // itself, if necessary.
622 LiftToSelf(comp_term);
623 term.SetContent(comp_term.CreateWith(&ValueObject::MakeMoveCopy),
624 comp_term.Value.MakeMoveCopy());
625 #else
626 // NOTE: The raw returning of term is the copy elision (unconditionally).
627 // It is equivalent to returning by reference, which can be dangerous.
628 term.SetContent(std::move(comp_term));
629 #endif
630 }
631
632 void
633 ReduceChildren(TNIter first, TNIter last, ContextNode& ctx)
634 {
635 // NOTE: Separators or other sequence constructs are not handled here. The
636 // evaluation can be potentionally parallel, though the simplest one is
637 // left-to-right.
638 // TODO: Use excetion policies to be evaluated concurrently?
639 std::for_each(first, last, ystdex::bind1(Reduce, std::ref(ctx)));
640 }
641
642 ReductionStatus
643 ReduceChildrenOrdered(TNIter first, TNIter last, ContextNode& ctx)
644 {
645 const auto tr([&](TNIter iter){
646 return ystdex::make_transform(iter, [&](TNIter i){
647 return Reduce(*i, ctx);
648 });
649 });
650
651 return ystdex::default_last_value<ReductionStatus>()(tr(first), tr(last),
652 ReductionStatus::Clean);
653 }
654
655 ReductionStatus
656 ReduceFirst(TermNode& term, ContextNode& ctx)
657 {
658 return IsBranch(term) ? Reduce(Deref(term.begin()), ctx)
659 : ReductionStatus::Clean;
660 }
661
662 ReductionStatus
663 ReduceOrdered(TermNode& term, ContextNode& ctx)
664 {
665 const auto res(ReduceChildrenOrdered(term, ctx));
666
667 if(IsBranch(term))
668 {
669 if(term.size() > 1)
670 LiftTerm(term, *term.rbegin());
671 else
672 term.Value = ValueToken::Unspecified;
673 }
674 return res;
675 }
676
677 ReductionStatus
678 ReduceTail(TermNode& term, ContextNode& ctx, TNIter i)
679 {
680 auto& con(term.GetContainerRef());
681
682 con.erase(con.begin(), i);
683 return Reduce(term, ctx);
684 }
685
686
687 void
688 SetupTraceDepth(ContextNode& root, const string& name)
689 {
690 yunseq(
691 root.GetBindingsRef().Place<size_t>(name),
692 AccessGuardPassesRef(root) = [name](TermNode& term, ContextNode& ctx){
693 using ystdex::pvoid;
694 auto& depth(AccessChild<size_t>(ctx.GetBindingsRef(), name));
695
696 YTraceDe(Informative, "Depth = %zu, context = %p, semantics = %p.",
697 depth, pvoid(&ctx), pvoid(&term));
698 ++depth;
699 return ystdex::unique_guard([&]() ynothrow{
700 --depth;
701 });
702 }
703 );
704 }
705
706
707 TermNode
708 TransformForSeparator(const TermNode& term, const ValueObject& pfx,
709 const ValueObject& delim, const TokenValue& name)
710 {
711 return TransformForSeparatorTmpl([&](TermNode& res, TNCIter b, TNCIter e){
712 // NOTE: Explicit type 'TermNode' is intended.
713 TermNode child(AsIndexNode(res));
714
715 while(b != e)
716 {
717 child.emplace(b->GetContainer(), MakeIndex(child), b->Value);
718 ++b;
719 }
720 res += std::move(child);
721 }, term, pfx, delim, name);
722 }
723
724 TermNode
725 TransformForSeparatorRecursive(const TermNode& term, const ValueObject& pfx,
726 const ValueObject& delim, const TokenValue& name)
727 {
728 return TransformForSeparatorTmpl([&](TermNode& res, TNCIter b, TNCIter e){
729 while(b != e)
730 res += TransformForSeparatorRecursive(*b++, pfx, delim,
731 MakeIndex(res));
732 }, term, pfx, delim, name);
733 }
734
735 ReductionStatus
736 ReplaceSeparatedChildren(TermNode& term, const ValueObject& name,
737 const ValueObject& delim)
738 {
739 if(std::find_if(term.begin(), term.end(),
740 ystdex::bind1(HasValue<ValueObject>, std::ref(delim))) != term.end())
741 term = TransformForSeparator(term, name, delim,
742 TokenValue(term.GetName()));
743 return ReductionStatus::Clean;
744 }
745
746
747 ReductionStatus
748 FormContextHandler::operator()(TermNode& term, ContextNode& ctx) const
749 {
750 // TODO: Is it worth matching specific builtin special forms here?
751 try
752 {
753 if(!Check || Check(term))
754 return Handler(term, ctx);
755 // TODO: Use more specific exception type?
756 throw std::invalid_argument("Term check failed.");
757 }
758 CatchExpr(NPLException&, throw)
759 // TODO: Use semantic exceptions.
760 CatchThrow(ystdex::bad_any_cast& e, LoggedEvent(ystdex::sfmt(
761 "Mismatched types ('%s', '%s') found.", e.from(), e.to()), Warning))
762 // TODO: Use nested exceptions?
763 CatchThrow(std::exception& e, LoggedEvent(e.what(), Err))
764 // XXX: Use distinct status for failure?
765 return ReductionStatus::Clean;
766 }
767
768
769 ReductionStatus
770 StrictContextHandler::operator()(TermNode& term, ContextNode& ctx) const
771 {
772 // NOTE: This implementes arguments evaluation in applicative order.
773 ReduceArguments(term, ctx);
774 YAssert(IsBranch(term), "Invalid state found.");
775 // NOTE: Matching function calls.
776 return Handler(term, ctx);
777 #if false
778 // TODO: Use other exception type with more precise information for this
779 // error? Also consider capture of contextual information in error.
780 throw ListReductionFailure(ystdex::sfmt("Invalid list form with"
781 " %zu term(s) not reduced found.", n), YSLib::Warning);
782 #endif
783 }
784
785
786 void
787 RegisterSequenceContextTransformer(EvaluationPasses& passes, ContextNode& node,
788 const TokenValue& name, const ValueObject& delim, bool ordered)
789 {
790 passes += ystdex::bind1(ReplaceSeparatedChildren, name, delim);
791 RegisterForm(node, name,
792 ordered ? ReduceOrdered : [](TermNode& term, ContextNode& ctx){
793 ReduceChildren(term, ctx);
794 return ReductionStatus::Retained;
795 });
796 }
797
798
799 ReductionStatus
800 EvaluateDelayed(TermNode& term)
801 {
802 return ystdex::call_value_or([&](DelayedTerm& delayed){
803 return EvaluateDelayed(term, delayed);
804 }, AccessPtr<DelayedTerm>(term), ReductionStatus::Clean);
805 }
806 ReductionStatus
807 EvaluateDelayed(TermNode& term, DelayedTerm& delayed)
808 {
809 // NOTE: The referenced term is lived through the envaluation, which is
810 // guaranteed by the evaluated parent term.
811 LiftDelayed(term, delayed);
812 // NOTE: To make it work with %DetectReducible.
813 return ReductionStatus::Retrying;
814 }
815
816 ReductionStatus
817 EvaluateIdentifier(TermNode& term, const ContextNode& ctx, string_view id)
818 {
819 if(const auto p = ResolveName(ctx, id))
820 {
821 // NOTE: This is conversion of lvalue in object to value of expression.
822 // The referenced term is lived through the evaluation, which is
823 // guaranteed by the context. This is necessary since the ownership of
824 // objects which are not temporaries in evaluated terms needs to be
825 // always in the environment, rather than in the tree. It would be safe
826 // if not passed directly and without rebinding. Note access of objects
827 // denoted by invalid reference after rebinding would cause undefined
828 // behavior in the object language.
829 // NOTE: %Reference term is necessary here to implement reference
830 // collapsing.
831 auto& sterm(ReferenceTerm(*p));
832
833 // TODO: Use other intermediate type to allow symbol in modifiable
834 // reference?
835 if(sterm.empty() && (!sterm.Value
836 || sterm.Value.type() == ystdex::type_id<TokenValue>()))
837 term.Value = sterm.Value;
838 else
839 term.Value = TermReference(sterm);
840 // NOTE: This is not guaranteed to be saved as %ContextHandler in
841 // %ReduceCombined.
842 if(const auto p_handler = AccessTermPtr<LiteralHandler>(term))
843 return (*p_handler)(ctx);
844 // NOTE: Unevaluated term shall be detected and evaluated. See also
845 // $2017-05 @ %Documentation::Workflow::Annual2017.
846 return IsLeaf(term) ? (term.Value.type()
847 != ystdex::type_id<TokenValue>() ? EvaluateDelayed(term)
848 : ReductionStatus::Clean) : ReductionStatus::Retained;
849 }
850 throw BadIdentifier(id);
851 }
852
853 ReductionStatus
854 EvaluateLeafToken(TermNode& term, ContextNode& ctx, string_view id)
855 {
856 YAssertNonnull(id.data());
857 // NOTE: Only string node of identifier is tested.
858 if(!id.empty())
859 {
860 // NOTE: The term would be normalized by %ReduceCombined.
861 // If necessary, there can be inserted some additional cleanup to
862 // remove empty tokens, returning %ReductionStatus::Retrying.
863 // Separators should have been handled in appropriate preprocessing
864 // passes.
865 const auto lcat(CategorizeBasicLexeme(id));
866
867 switch(lcat)
868 {
869 case LexemeCategory::Code:
870 // TODO: When do code literals need to be evaluated?
871 id = DeliteralizeUnchecked(id);
872 if(YB_UNLIKELY(id.empty()))
873 break;
874 YB_ATTR_fallthrough;
875 case LexemeCategory::Symbol:
876 return CheckReducible(InvokeLiteral(term, ctx, id))
877 ? EvaluateIdentifier(term, ctx, id) : ReductionStatus::Clean;
878 // XXX: Empty token is ignored.
879 // XXX: Remained reducible?
880 case LexemeCategory::Data:
881 // XXX: This should be prevented being passed to second pass in
882 // %TermToNamePtr normally. This is guarded by normal form handling
883 // in the loop in %Reduce.
884 term.Value.emplace<string>(Deliteralize(id));
885 YB_ATTR_fallthrough;
886 default:
887 break;
888 // TODO: Handle other categories of literal.
889 }
890 }
891 return ReductionStatus::Clean;
892 }
893
894 ReductionStatus
895 ReduceCombined(TermNode& term, ContextNode& ctx)
896 {
897 if(IsBranch(term))
898 {
899 const auto& fm(Deref(ystdex::as_const(term).begin()));
900 const auto ret([&](ReductionStatus res){
901 // NOTE: Normalization: Cleanup if necessary.
902 if(res == ReductionStatus::Clean)
903 term.ClearContainer();
904 return res;
905 });
906
907 if(const auto p_handler = AccessPtr<ContextHandler>(fm))
908 {
909 const auto handler(std::move(*p_handler));
910
911 return ret(handler(term, ctx));
912 }
913 if(const auto p_handler = AccessTermPtr<ContextHandler>(fm))
914 return ret((*p_handler)(term, ctx));
915 else
916 // TODO: Capture contextual information in error.
917 // TODO: Extract general form information extractor function.
918 throw ListReductionFailure(
919 ystdex::sfmt("No matching combiner '%s' for operand with %zu"
920 " argument(s) found.", [&](observer_ptr<const string> p){
921 return p ? *p : ystdex::sfmt("#<unknown:%s>",
922 fm.Value.type().name());
923 }(TermToNamePtr(fm)).c_str(), FetchArgumentN(term)));
924 }
925 return ReductionStatus::Clean;
926 }
927
928 ReductionStatus
929 ReduceLeafToken(TermNode& term, ContextNode& ctx)
930 {
931 return ystdex::call_value_or([&](string_view id){
932 return EvaluateLeafToken(term, ctx, id);
933 // XXX: A term without token is ignored.
934 }, TermToNamePtr(term), ReductionStatus::Clean);
935 }
936
937
938 observer_ptr<ValueNode>
939 ResolveName(const ContextNode& ctx, string_view id)
940 {
941 YAssertNonnull(id.data());
942 return ctx.GetRecordRef().Resolve(id);
943 }
944
945 pair<shared_ptr<Environment>, bool>
946 ResolveEnvironment(ValueObject& vo)
947 {
948 if(const auto p = vo.AccessPtr<weak_ptr<Environment>>())
949 return {p->lock(), {}};
950 if(const auto p = vo.AccessPtr<shared_ptr<Environment>>())
951 return {*p, true};
952 // TODO: Merge with %Environment::CheckParent?
953 Environment::ThrowForInvalidType(vo.type());
954 }
955
956
957 void
958 SetupDefaultInterpretation(ContextNode& root, EvaluationPasses passes)
959 {
960 passes += ReduceHeadEmptyList;
961 passes += ReduceFirst;
962 // TODO: Insert more optional optimized lifted form evaluation passes:
963 // macro expansion, etc.
964 passes += ReduceCombined;
965 AccessListPassesRef(root) = std::move(passes);
966 AccessLeafPassesRef(root) = ReduceLeafToken;
967 }
968
969
970 REPLContext::REPLContext(bool trace)
971 {
972 using namespace std::placeholders;
973
974 SetupDefaultInterpretation(Root,
975 std::bind(std::ref(ListTermPreprocess), _1, _2));
976 if(trace)
977 SetupTraceDepth(Root);
978 }
979
980 void
981 REPLContext::LoadFrom(std::istream& is)
982 {
983 if(is)
984 {
985 if(const auto p = is.rdbuf())
986 LoadFrom(*p);
987 else
988 throw std::invalid_argument("Invalid stream buffer found.");
989 }
990 else
991 throw std::invalid_argument("Invalid stream found.");
992 }
993 void
994 REPLContext::LoadFrom(std::streambuf& buf)
995 {
996 using s_it_t = std::istreambuf_iterator<char>;
997
998 Process(Session(s_it_t(&buf), s_it_t()));
999 }
1000
1001 TermNode
1002 REPLContext::Perform(string_view unit)
1003 {
1004 YAssertNonnull(unit.data());
1005 if(!unit.empty())
1006 return Process(Session(unit));
1007 throw LoggedEvent("Empty token list found.", Alert);
1008 }
1009
1010 void
1011 REPLContext::Process(TermNode& term)
1012 {
1013 TokenizeTerm(term);
1014 Preprocess(term);
1015 Reduce(term, Root);
1016 }
1017 TermNode
1018 REPLContext::Process(const TokenList& token_list)
1019 {
1020 auto term(SContext::Analyze(token_list));
1021
1022 Process(term);
1023 return term;
1024 }
1025 TermNode
1026 REPLContext::Process(const Session& session)
1027 {
1028 auto term(SContext::Analyze(session));
1029
1030 Process(term);
1031 return term;
1032 }
1033
1034
1035 namespace Forms
1036 {
1037
1038 bool
1039 IsSymbol(const string& id) ynothrow
1040 {
1041 return IsNPLASymbol(id);
1042 }
1043
1044 TokenValue
1045 StringToSymbol(const string& s)
1046 {
1047 return s;
1048 }
1049
1050 const string&
1051 SymbolToString(const TokenValue& s) ynothrow
1052 {
1053 return s;
1054 }
1055
1056
1057 size_t
1058 RetainN(const TermNode& term, size_t m)
1059 {
1060 const auto n(FetchArgumentN(term));
1061
1062 if(n != m)
1063 throw ArityMismatch(m, n);
1064 return n;
1065 }
1066
1067
1068 void
1069 BindParameter(ContextNode& ctx, const TermNode& t, TermNode& o)
1070 {
1071 auto& m(ctx.GetBindingsRef());
1072
1073 LiftToSelf(o);
1074 MatchParameter(t, o, [&](TNIter first, TNIter last, string_view id){
1075 YAssert(ystdex::begins_with(id, "."), "Invalid symbol found.");
1076 id.remove_prefix(1);
1077 if(!id.empty())
1078 {
1079 TermNode::Container con;
1080
1081 for(; first != last; ++first)
1082 {
1083 auto& b(Deref(first));
1084
1085 #if true
1086 con.emplace(b.CreateWith(&ValueObject::MakeMoveCopy),
1087 MakeIndex(con), b.Value.MakeMoveCopy());
1088 #else
1089 // XXX: Moved. This is copy elision in object language.
1090 con.emplace(std::move(b.GetContainerRef()), MakeIndex(con),
1091 std::move(b.Value));
1092 #endif
1093 }
1094 m[id].SetContent(ValueNode(std::move(con)));
1095 }
1096 }, [&](const TokenValue& n, TermNode&& b){
1097 CheckParameterLeafToken(n, [&]{
1098 #if true
1099 // NOTE: The operands should have been evaluated. Children nodes in
1100 // arguments retained are also transferred.
1101 m[n].SetContent(b.CreateWith(&ValueObject::MakeMoveCopy),
1102 b.Value.MakeMoveCopy());
1103 #else
1104 // NOTE: The symbol can be rebound.
1105 // FIXME: Correct key of node when not bound?
1106 // XXX: Moved. This is copy elision in object language.
1107 m[n].SetContent(std::move(b.GetContainerRef()), std::move(b.Value));
1108 #endif
1109 });
1110 });
1111 }
1112
1113 void
1114 MatchParameter(const TermNode& t, TermNode& o,
1115 std::function<void(TNIter, TNIter, const TokenValue&)> bind_trailing_seq,
1116 std::function<void(const TokenValue&, TermNode&&)> bind_value)
1117 {
1118 // TODO: Binding of reference support?
1119 LiftToSelf(o);
1120 if(IsBranch(t))
1121 {
1122 const auto n_p(t.size());
1123 const auto n_o(o.size());
1124 auto last(t.end());
1125
1126 if(n_p > 0)
1127 {
1128 const auto& back(Deref(std::prev(last)));
1129
1130 if(IsLeaf(back))
1131 {
1132 if(const auto p = AccessPtr<TokenValue>(back))
1133 {
1134 YAssert(!p->empty(), "Invalid token value found.");
1135 if(p->front() == '.')
1136 --last;
1137 }
1138 else
1139 // TODO: Merge with %CheckParameterLeafToken?
1140 throw ParameterMismatch(
1141 "Invalid token found for symbol parameter.");
1142 }
1143 }
1144 if(n_p == n_o || (last != t.end() && n_o >= n_p - 1))
1145 {
1146 auto j(o.begin());
1147
1148 for(auto i(t.begin()); i != last; yunseq(++i, ++j))
1149 {
1150 YAssert(j != o.end(), "Invalid state of operand found.");
1151 MatchParameter(Deref(i), Deref(j), bind_trailing_seq,
1152 bind_value);
1153 }
1154 if(last != t.end())
1155 {
1156 const auto& lastv(Deref(last).Value);
1157
1158 YAssert(lastv.type() == ystdex::type_id<TokenValue>(),
1159 "Invalid ellipsis sequence token found.");
1160 bind_trailing_seq(j, o.end(), lastv.GetObject<TokenValue>());
1161 YAssert(++last == t.end(), "Invalid state found.");
1162 }
1163 }
1164 else if(last == t.end())
1165 throw ArityMismatch(n_p, n_o);
1166 else
1167 throw ParameterMismatch(
1168 "Insufficient term found for list parameter.");
1169 }
1170 else if(!t.Value)
1171 {
1172 if(o)
1173 throw ParameterMismatch(ystdex::sfmt(
1174 "Invalid nonempty operand found for empty list parameter,"
1175 " with %zu subterm(s) and value '#<unknown:%s>'.", o.size(),
1176 o.Value.type().name()));
1177 }
1178 else if(const auto p = AccessPtr<TokenValue>(t))
1179 bind_value(*p, std::move(o));
1180 else
1181 throw ParameterMismatch(ystdex::sfmt("Invalid parameter value found"
1182 " with value '#<unknown:%s>'.", t.Value.type().name()));
1183 }
1184
1185
1186 void
1187 DefineLazy(TermNode& term, ContextNode& ctx)
1188 {
1189 DoDefine(term, [&](TermNode& formals){
1190 BindParameter(ctx, formals, term);
1191 });
1192 }
1193
1194 void
1195 DefineWithNoRecursion(TermNode& term, ContextNode& ctx)
1196 {
1197 DoDefine(term, [&](TermNode& formals){
1198 ReduceChecked(term, ctx);
1199 BindParameter(ctx, formals, term);
1200 });
1201 }
1202
1203 void
1204 DefineWithRecursion(TermNode& term, ContextNode& ctx)
1205 {
1206 DoDefine(term, [&](TermNode& formals){
1207 RecursiveThunk gd(ctx.GetRecordRef(), formals);
1208
1209 ReduceChecked(term, ctx);
1210 BindParameter(ctx, formals, term);
1211 gd.Commit();
1212 });
1213 }
1214
1215 void
1216 Undefine(TermNode& term, ContextNode& ctx, bool forced)
1217 {
1218 Retain(term);
1219 if(term.size() == 2)
1220 {
1221 const auto& n(Access<TokenValue>(Deref(std::next(term.begin()))));
1222
1223 if(IsNPLASymbol(n))
1224 term.Value = ctx.GetRecordRef().Remove(n, forced);
1225 else
1226 throw InvalidSyntax(ystdex::sfmt("Invalid token '%s' found as name"
1227 " to be undefined.", n.c_str()));
1228 }
1229 else
1230 throw
1231 InvalidSyntax("Expected exact one term as name to be undefined.");
1232 }
1233
1234
1235 ReductionStatus
1236 If(TermNode& term, ContextNode& ctx)
1237 {
1238 Retain(term);
1239
1240 const auto size(term.size());
1241
1242 if(size == 3 || size == 4)
1243 {
1244 auto i(term.begin());
1245
1246 ReduceChecked(Deref(++i), ctx);
1247 if(!ystdex::value_or(AccessTermPtr<bool>(*i)))
1248 ++i;
1249 if(++i != term.end())
1250 {
1251 LiftTerm(term, *i);
1252 return ReductionStatus::Retrying;
1253 }
1254 }
1255 else
1256 throw InvalidSyntax("Syntax error in conditional form.");
1257 return ReductionStatus::Clean;
1258 }
1259
1260 void
1261 Lambda(TermNode& term, ContextNode& ctx)
1262 {
1263 CreateFunction(term, [&](TermNode::Container& con){
1264 auto p_env(ctx.ShareRecord());
1265 auto i(con.begin());
1266 auto formals(share_move(Deref(++i)));
1267
1268 con.erase(con.cbegin(), ++i);
1269 // NOTE: %ToContextHandler implies strict evaluation of arguments in
1270 // %StrictContextHandler::operator().
1271 return ToContextHandler(VauHandler({}, std::move(formals),
1272 std::move(p_env), {}, ctx, term));
1273 }, 1);
1274 }
1275
1276 void
1277 Vau(TermNode& term, ContextNode& ctx)
1278 {
1279 CreateFunction(term, [&](TermNode::Container& con){
1280 auto p_env(ctx.ShareRecord());
1281 auto i(con.begin());
1282 auto formals(share_move(Deref(++i)));
1283 string eformal(ReferenceEnvFormal(Deref(++i)));
1284
1285 con.erase(con.cbegin(), ++i);
1286 return FormContextHandler(VauHandler(std::move(eformal),
1287 std::move(formals), std::move(p_env), {}, ctx, term));
1288 }, 2);
1289 }
1290
1291 void
1292 VauWithEnvironment(TermNode& term, ContextNode& ctx)
1293 {
1294 CreateFunction(term, [&](TermNode::Container& con){
1295 auto i(con.begin());
1296
1297 ReduceChecked(Deref(++i), ctx);
1298
1299 // XXX: List components are ignored.
1300 auto p_env_pr(ResolveEnvironment(Deref(i)));
1301 auto formals(share_move(Deref(++i)));
1302 string eformal(ReferenceEnvFormal(Deref(++i)));
1303
1304 con.erase(con.cbegin(), ++i);
1305 return FormContextHandler(VauHandler(std::move(eformal), std::move(
1306 formals), std::move(p_env_pr.first), p_env_pr.second, ctx, term));
1307 }, 3);
1308 }
1309
1310
1311 ReductionStatus
1312 And(TermNode& term, ContextNode& ctx)
1313 {
1314 return AndOr(term, ctx, true);
1315 }
1316
1317 ReductionStatus
1318 Or(TermNode& term, ContextNode& ctx)
1319 {
1320 return AndOr(term, ctx, {});
1321 }
1322
1323
1324 void
1325 CallSystem(TermNode& term)
1326 {
1327 CallUnaryAs<const string>(
1328 ystdex::compose(usystem, std::mem_fn(&string::c_str)), term);
1329 }
1330
1331 ReductionStatus
1332 Cons(TermNode& term)
1333 {
1334 RetainN(term, 2);
1335
1336 auto i(std::next(term.begin(), 2));
1337 const auto get_ins_idx([&]{
1338 term.erase(i);
1339 return GetLastIndexOf(term);
1340 });
1341 const auto ret([&]{
1342 RemoveHead(term);
1343 return ReductionStatus::Retained;
1344 });
1345
1346 // TODO: Simplify?
1347 if(const auto p = AccessPtr<TermReference>(Deref(i)))
1348 {
1349 if(IsList(*p))
1350 {
1351 const auto& tail(p->get());
1352 auto idx(get_ins_idx());
1353
1354 for(auto& tm : tail)
1355 term.AddChild(MakeIndex(++idx), tm);
1356 return ret();
1357 }
1358 }
1359 else if(IsList(Deref(i)))
1360 {
1361 auto tail(std::move(Deref(i)));
1362 auto idx(get_ins_idx());
1363
1364 for(auto& tm : tail)
1365 term.AddChild(MakeIndex(++idx), std::move(tm));
1366 return ret();
1367 }
1368 throw InvalidSyntax("The tail argument shall be a list.");
1369 }
1370
1371 void
1372 EqualReference(TermNode& term)
1373 {
1374 EqualTerm(term, YSLib::HoldSame);
1375 }
1376
1377 void
1378 EqualValue(TermNode& term)
1379 {
1380 EqualTerm(term, ystdex::equal_to<>());
1381 }
1382
1383 ReductionStatus
1384 Eval(TermNode& term, ContextNode& ctx)
1385 {
1386 RetainN(term, 2);
1387
1388 const auto i(std::next(term.begin()));
1389 // TODO: Support more environment types?
1390 ContextNode c(ctx, ResolveEnvironment(Deref(std::next(i))).first);
1391
1392 LiftToOther(term, Deref(i));
1393 return Reduce(term, c);
1394 }
1395
1396 void
1397 EvaluateUnit(TermNode& term, const REPLContext& ctx)
1398 {
1399 CallUnaryAs<const string>([ctx](const string& unit){
1400 REPLContext(ctx).Perform(unit);
1401 }, term);
1402 }
1403
1404 void
1405 MakeEnvironment(TermNode& term)
1406 {
1407 Retain(term);
1408
1409 if(term.size() > 1)
1410 {
1411 ValueObject parent;
1412 const auto tr([&](TNCIter iter){
1413 return ystdex::make_transform(iter, [&](TNCIter i){
1414 return i->Value;
1415 });
1416 });
1417
1418 parent.emplace<EnvironmentList>(tr(std::next(term.begin())),
1419 tr(term.end()));
1420 term.Value = make_shared<Environment>(std::move(parent));
1421 }
1422 else
1423 term.Value = make_shared<Environment>();
1424 }
1425
1426 void
1427 GetCurrentEnvironment(TermNode& term, ContextNode& ctx)
1428 {
1429 RetainN(term, 0);
1430 term.Value = ValueObject(ctx.WeakenRecord());
1431 }
1432
1433 ReductionStatus
1434 ValueOf(TermNode& term, const ContextNode& ctx)
1435 {
1436 RetainN(term);
1437 LiftToOther(term, Deref(std::next(term.begin())));
1438 if(const auto p_id = AccessPtr<string>(term))
1439 TryRet(EvaluateIdentifier(term, ctx, *p_id))
1440 CatchIgnore(BadIdentifier&)
1441 term.Value = ValueToken::Null;
1442 return ReductionStatus::Clean;
1443 }
1444
1445
1446 ContextHandler
1447 Wrap(const ContextHandler& h)
1448 {
1449 return ToContextHandler(h);
1450 }
1451
1452 ContextHandler
1453 WrapOnce(const ContextHandler& h)
1454 {
1455 if(const auto p = h.target<FormContextHandler>())
1456 return ToContextHandler(*p);
1457 throw NPLException(ystdex::sfmt("Wrapping failed with type '%s'.",
1458 h.target_type().name()));
1459 }
1460
1461 ContextHandler
1462 Unwrap(const ContextHandler& h)
1463 {
1464 if(const auto p = h.target<StrictContextHandler>())
1465 return ContextHandler(p->Handler);
1466 throw NPLException(ystdex::sfmt("Unwrapping failed with type '%s'.",
1467 h.target_type().name()));
1468 }
1469
1470 } // namespace Forms;
1471
1472 } // namesapce A1;
1473
1474 } // namespace NPL;
1475
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:313
NPL::A1::EvaluateIdentifier
YF_API ReductionStatus EvaluateIdentifier(TermNode &, const ContextNode &, string_view)
求值标识符。
Definition: NPLA1.cpp:817
NPL::ContextNode::WeakenRecord
Environment::BindingMap Environment *p_record WeakenRecord
Definition: NPLA.h:1213
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::CategorizeBasicLexeme
YF_API LexemeCategory CategorizeBasicLexeme(string_view) ynothrowv
对排除扩展字面量的词素分类。
ystdex::derived_entity
派生类实体。
Definition: base.h:177
NPL::ReferenceTerm
YF_API TermNode & ReferenceTerm(TermNode &)
访问项并取解析 TermReference 间接值后的引用。
Definition: NPLA.cpp:424
NPL::A1::Forms::Undefine
YF_API void Undefine(TermNode &, ContextNode &, bool)
移除名称绑定。 非强制时移除不存在的名称。
Definition: NPLA1.cpp:1216
NPL::A1::RegisterForm
void RegisterForm(ContextNode &ctx, const string &name, _tParams &&...args)
Definition: NPLA1.h:619
platform::Descriptions::Debug
Definition: YCommon.h:170
NPL::A1::InvokeLiteral
YF_API ReductionStatus InvokeLiteral(TermNode &, ContextNode &, string_view)
调用字面量遍。
Definition: NPLA1.cpp:544
CatchThrow
#define CatchThrow(_ex,...)
指定抛出指定异常作为异常处理器。
Definition: YBaseMacro.h:141
NPL::A1::ReduceCheckedClosure
YF_API void ReduceCheckedClosure(TermNode &, ContextNode &, bool, TermNode &)
规约闭包。
Definition: NPLA1.cpp:600
NPL::A1::FormContextHandler
形式上下文处理器。
Definition: NPLA1.h:515
NPL::A1::Forms::EqualValue
YF_API void EqualValue(TermNode &)
比较两个子项的值相等。
Definition: NPLA1.cpp:1378
YSLib::GEvent
事件模板。
Definition: YEvent.hpp:306
NPL::A1::EvaluateLeafToken
YF_API ReductionStatus EvaluateLeafToken(TermNode &, ContextNode &, string_view)
求值叶节点记号。
Definition: NPLA1.cpp:854
NPL::A1::TransformNode
YF_API ValueNode TransformNode(const TermNode &, NodeMapper={}, NodeMapper=MapNPLALeafNode, NodeToString=ParseNPLANodeString, NodeInserter=InsertChild)
变换 NPLA1 节点 S 表达式抽象语法树为 NPLA1 语义结构。 第三至五参数为空。
Definition: NPLA1.cpp:76
platform::Descriptions::Alert
Definition: YCommon.h:164
v
byte v
Definition: CharRenderer.cpp:75
YSLib::GetLastIndexOf
size_t GetLastIndexOf(const ValueNode::Container &con)
Definition: ValueNode.cpp:199
NPL::A1::Forms::CheckParameterLeafToken
auto CheckParameterLeafToken(string_view n, _func f) -> decltype(f())
检查记号值是符合匹配条件的参数符号。
Definition: NPLA1.h:982
NPL::A1::ReduceTail
YF_API ReductionStatus ReduceTail(TermNode &, ContextNode &, TNIter)
移除容器第一个子项到指定迭代器的项后规约。
Definition: NPLA1.cpp:678
ystdex::begins_with
bool begins_with(const _tRange1 &input, const _tRange2 &test, _fPred comp)
判断第一个参数指定的串是否以第二个参数起始。
Definition: string.hpp:398
NPL::IsList
const TermNode &term ynothrow const TermNode &term ynothrow IsList
Definition: SContext.h:71
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
cast.hpp
C++ 转换模板。
YSLib::Environment
应用程序环境。
Definition: Environment.h:62
NPL::ContextNode
上下文节点。
Definition: NPLA.h:1174
NPL::A1::InsertChild
YF_API void InsertChild(TermNode &&, TermNode::Container &)
插入 NPLA1 子节点。
Definition: NPLA1.cpp:63
Term
const TermNode & Term
Definition: NPLA1.cpp:241
platform::tail
_tString ystdex::string_traits< _tString >::const_pointer tail
Definition: YCLib/FileSystem.h:286
NPL::A1::InsertSequenceChild
YF_API void InsertSequenceChild(TermNode &&, NodeSequence &)
Definition: NPLA1.cpp:70
NPL::ContextNode::EvaluateLiteral
LiteralPasses EvaluateLiteral
Definition: NPLA.h:1186
YSLib::ValueObject::type
friend type
Definition: YObject.h:914
YSLib::MakeIndex
MakeIndex
Definition: ValueNode.h:1202
NPL::A1::REPLContext::Perform
TermNode Perform(string_view)
执行循环：对非空输入进行翻译。
Definition: NPLA1.cpp:1002
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:451
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
NPL::A1::Forms::EvaluateUnit
YF_API void EvaluateUnit(TermNode &, const REPLContext &)
创建参数指定的 REPL 的副本并在其中对翻译单元规约以求值。
Definition: NPLA1.cpp:1397
NPL::NodeToString
std::function< string(const ValueNode &)> NodeToString
Definition: NPLA.h:114
NPL::LiftToSelf
PDefH(void, LiftTermRef, TermNode &term, const TermNode &tm) ImplExpr(YSLib YF_API void LiftToSelf(TermNode &)
提升项引用：使用第二个参数指定的项的内容引用替换第一个项的内容。
Definition: NPLA.h:840
NPL::NodeMapper
std::function< ValueNode(const TermNode &)> NodeMapper
节点映射操作类型：变换节点为另一个节点。
Definition: NPLA.h:110
NPL::A1::Forms::Wrap
YF_API ContextHandler Wrap(const ContextHandler &)
包装合并子为应用子。
Definition: NPLA1.cpp:1447
YModules.h
CHRLib::f
f(d, s)
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::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
NPL::Session
会话：分析指定 NPL 代码。
Definition: SContext.h:103
ystdex::compose
composed< _func, _func2 > compose(_func f, _func2 g)
函数复合。
Definition: functional.hpp:686
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:120
NPL::ListReductionFailure
列表规约失败。
Definition: NPLA.h:431
NPL::A1::Forms::CallSystem
YF_API void CallSystem(TermNode &)
调用 UTF-8 字符串的系统命令，并保存 int 类型的结果到项的值中。
Definition: NPLA1.cpp:1325
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:464
NPL::c_str
YF_API const char src c_str())) YF_API void InstallDirectory(const string &
安装目录：复制目录树。
Definition: Dependency.h:131
NPL::ContextNode::EvaluateList
EvaluationPasses EvaluateList
Definition: NPLA.h:1185
NPL::A1::Forms::If
YF_API ReductionStatus If(TermNode &, ContextNode &)
条件判断：根据求值的条件取表达式。
Definition: NPLA1.cpp:1236
NPL::ReductionStatus
ReductionStatus
规约状态：一遍规约可能的中间结果。
Definition: NPLA.h:633
YSLib::LoggedEvent
记录日志的异常事件类。
Definition: YException.h:50
NPL::A1::to_string
string to_string(ValueToken vt)
Definition: NPLA1.cpp:44
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
ystdex::make_shared
std::shared_ptr< _type > make_shared(std::initializer_list< _tValue > il)
使用指定类型的初始化列表构造指定类型的 std::shared_ptr 对象。
Definition: memory.hpp:945
ystdex::nullptr
const class ystdex::nullptr_t nullptr
CatchIgnore
#define CatchIgnore(_ex)
指定异常处理器忽略指定异常。
Definition: YBaseMacro.h:133
YSLib::Text::buf
const char * buf
Definition: TextFile.h:81
CHRLib::CharSet::Null
空字符集。
Definition: Encoding.h:63
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
YSLib::NoContainer
yconstexpr const struct YSLib::NoContainerTag NoContainer
NPL::A1::SetupDefaultInterpretation
void SetupDefaultInterpretation(ContextNode &root, EvaluationPasses passes)
Definition: NPLA1.cpp:958
NPL::A1::REPLContext
Definition: NPLA1.h:839
YSLib::YAssert
YAssert(!(v< Deref(a)),"Value less than lower bound found.")
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:1022
NPL::A1::AccessListPassesRef
YF_API EvaluationPasses & AccessListPassesRef(ContextNode &)
访问列表遍。
Definition: NPLA1.cpp:514
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
NPL::ContextHandler
YSLib::GHEvent< ReductionStatus(TermNode &, ContextNode &)> ContextHandler
上下文处理器类型。
Definition: NPLA.h:1230
NPL::A1::ReduceFirst
con ctx ctx YF_API ReductionStatus ReduceFirst(TermNode &, ContextNode &)
规约第一个子项。
Definition: NPLA1.cpp:656
NPL::A1::ReduceCombined
YF_API ReductionStatus ReduceCombined(TermNode &, ContextNode &)
规约合并项：检查项的第一个子项尝试作为操作符进行函数应用，并规范化。
Definition: NPLA1.cpp:895
NPL::A1::ValueToken
ValueToken
值记号：节点中的值的占位符。
Definition: NPLA1.h:59
NPL::A1::Forms::DefineWithRecursion
YF_API void DefineWithRecursion(TermNode &, ContextNode &)
Definition: NPLA1.cpp:1204
NPL::A1::Forms::ValueOf
YF_API ReductionStatus ValueOf(TermNode &, const ContextNode &)
求值标识符得到指称的实体。
Definition: NPLA1.cpp:1434
NPL::ArityMismatch
元数不匹配错误。
Definition: NPLA.h:474
YSLib::PDefH
PDefH(Environment &, FetchEnvironment,) ImplRet(FetchGlobalInstance().GetEnvironmentRef()) inline PDefH(GUIHost &
取单一环境对象引用。
ystdex::any
基于类型擦除的动态泛型对象。
Definition: any.h:845
YSLib::AsNode
typename _tParams ValueNode AsNode(_tString &&str, _tParams &&...args)
Definition: ValueNode.h:1065
NPL::ContextNode::EvaluateLeaf
EvaluationPasses EvaluateLeaf
Definition: NPLA.h:1184
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
YSLib::ValueObject
值类型对象类。
Definition: YObject.h:539
platform::usystem
YF_API int usystem(const char *)
执行 UTF-8 字符串的环境命令。
Definition: YCommon.cpp:58
YSLib::FilterExceptions
bool FilterExceptions(_func f, const char *desc={}, RecordLevel lv=Alert, ExceptionTracer trace=ExtractAndTrace) ynothrow
调用函数并过滤宿主异常。
Definition: YException.h:203
NPL::A1::ReduceOrdered
YF_API ReductionStatus ReduceOrdered(TermNode &, ContextNode &)
规约有序序列：顺序规约子项，结果为最后一个子项的规约结果。
Definition: NPLA1.cpp:663
YSLib::AsIndexNode
const ValueNode &node ImplRet(MakeIndex(node.GetContainer())) YF_API size_t GetLastIndexOf(const ValueNode typename _tParams ValueNode AsIndexNode(_tParam &&arg, _tParams &&...args)
Definition: ValueNode.h:1227
NPL::NodeInserter
GNodeInserter< TermNode::Container & > NodeInserter
Definition: NPLA.h:119
NPL::ContextNode::GetRecordRef
Environment::BindingMap GetRecordRef().GetMapRef()) DefGetter(const ynothrow
NPL::A1::Forms::MatchParameter
YF_API void MatchParameter(const TermNode &, TermNode &, std::function< void(TNIter, TNIter, const TokenValue &)>, std::function< void(const TokenValue &, TermNode &&)>)
匹配参数。 异常中立：参数指定的处理器为空。
Definition: NPLA1.cpp:1114
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
ystdex::sfmt
auto sfmt(const _tChar *fmt,...) -> decltype(vsfmt(fmt, std::declval< std::va_list >()))
以 C 标准输出格式的输出 std::basic_string 实例的对象。
Definition: string.hpp:1200
ystdex
特性测试宏。
Definition: ydef.h:822
Record
Environment & Record
Definition: NPLA1.cpp:239
NPL::CheckedReduceWith
PDefH(ReductionStatus, CheckNorm, const TermNode &term) ynothrow ImplRet(IsBranch(term)?ReductionStatus void CheckedReduceWith(_func f, _tParams &&...args)
检查视为范式的节点并提取规约状态。
Definition: NPLA.h:762
NPL::TermNode
yimpl(ValueNode) TermNode
项节点：存储语法分析结果的值类型节点。
Definition: SContext.h:51
YSLib::i
return i
Definition: YCoreUtilities.h:176
NPL::A1::InvokeLeaf
YF_API ReductionStatus InvokeLeaf(TermNode &term, ContextNode &)
调用叶遍。
Definition: NPLA1.cpp:532
NPL::BadIdentifier
标识符错误。
Definition: NPLA.h:500
NPL::TermToNamePtr
YF_API observer_ptr< const TokenValue > TermToNamePtr(const TermNode &)
访问项的值作为记号。
Definition: NPLA.cpp:408
NPL::A1::ReplaceSeparatedChildren
YF_API ReductionStatus ReplaceSeparatedChildren(TermNode &, const ValueObject &, const ValueObject &)
查找项中的指定分隔符，若找到则替换项为去除分隔符并添加替换前缀的形式。
Definition: NPLA1.cpp:736
NPL::A1::ReduceChildrenOrdered
con ctx ctx YF_API ReductionStatus ReduceChildrenOrdered(TNIter, TNIter, ContextNode &)
有序规约子项。
Definition: NPLA1.cpp:643
NPL::A1::AccessLeafPassesRef
YF_API EvaluationPasses & AccessLeafPassesRef(ContextNode &)
访问叶遍。
Definition: NPLA1.cpp:508
YSLib::yimpl
YF_API yimpl(GUIApplication &) FetchGlobalInstance()
取全局应用程序实例。
NPL::A1::Forms::Vau
YF_API void Vau(TermNode &, ContextNode &)
vau 抽象：求值为一个捕获当前上下文的非严格求值的函数。
Definition: NPLA1.cpp:1277
ystdex::in_place
in_place_tag in_place(empty_base<>)
原地标记函数。
Definition: placement.hpp:85
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:168
ystdex::default_last_value
合并值序列。
Definition: functional.hpp:1217
NPL::A1::Forms::IsSymbol
YF_API bool IsSymbol(const string &) ynothrow
判断字符串值是否可构成符号。
Definition: NPLA1.cpp:1039
NPL::TNCIter
TermNode::const_iterator TNCIter
Definition: SContext.h:54
NPL::A1::Forms::Unwrap
YF_API ContextHandler Unwrap(const ContextHandler &)
从应用子中取操作子。
Definition: NPLA1.cpp:1462
NPL::A1::ReduceChecked
con ctx ctx YF_API void ReduceChecked(TermNode &, ContextNode &)
规约并检查成功：调用 Reduce 并检查结果。
Definition: NPLA1.cpp:594
YSLib::RemoveHead
YF_API void RemoveHead(ValueNode::Container &) ynothrowv
移除首个子节点。
Definition: ValueNode.cpp:164
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:109
YSLib::UI::Styles::Handler
std::function< void(PaintEventArgs &&)> Handler
样式处理器。
Definition: YStyle.h:380
NPL::A1::Reduce
YF_API ReductionStatus Reduce(TermNode &, ContextNode &)
NPLA1 表达式节点规约：调用至少一次求值例程规约子表达式。
Definition: NPLA1.cpp:552
YSLib::ValueNode::Remove
Remove
Definition: ValueNode.h:539
YSLib::ValueNode
值类型节点。
Definition: ValueNode.h:58
NPL::ReduceHeadEmptyList
ReductionStatus ReduceHeadEmptyList(TermNode &term) ynothrow
Definition: NPLA.cpp:515
NPL::TokenList
list< string > TokenList
Definition: SContext.h:42
YSLib::YB_NONNULL
YF_API YB_NONNULL(1, 2) ValueNode LoadNPLA1File(const char *disp
载入 NPLA1 配置文件。
NPL::A1::TransformForSeparator
YF_API TermNode TransformForSeparator(const TermNode &, const ValueObject &, const ValueObject &, const TokenValue &={})
变换分隔符中缀表达式为前缀表达式。
Definition: NPLA1.cpp:708
NPL::InvalidSyntax
语法错误。
Definition: NPLA.h:444
std
Definition: memory.hpp:1183
p_defualt
shared_ptr_t p_defualt
Definition: NPLA1.cpp:234
NPL::GuardPasses
YSLib::GEvent< Guard(TermNode &, ContextNode &), YSLib::GDefaultLastValueInvoker< Guard >> GuardPasses
作用域守护遍：用于需在规约例程的入口和出口关联执行的操作。
Definition: NPLA.h:964
NPL::A1::ResolveName
YF_API observer_ptr< ValueNode > ResolveName(const ContextNode &, string_view)
解析名称：处理保留名称并查找名称。
Definition: NPLA1.cpp:939
YSLib::NodeSequence
yimpl(YSLib::vector)< ValueNode > NodeSequence
节点序列容器。
Definition: ValueNode.h:1239
ystdex::type_id
const type_info & type_id()
Definition: typeinfo.h:149
ystdex::value_or
auto value_or(_type &&p) -> decay_t< decltype(*std::forward< decltype(p)>(p))>
取非空值或默认值。
Definition: deref_op.hpp:116
NPL::A1::Forms::DefineWithNoRecursion
YF_API void DefineWithNoRecursion(TermNode &, ContextNode &)
Definition: NPLA1.cpp:1195
NPL
Definition: NPL/Configuration.h:34
ystdex::mapped_set
允许指定不同于值类型的键的集合。
Definition: set.hpp:160
ystdex::any_ops::use_holder
const struct ystdex::any_ops::use_holder_t use_holder
NPL::IsLeaf
const TermNode &term ynothrow IsLeaf
Definition: SContext.h:67
NPL::A1::StrictContextHandler
严格上下文处理器。
Definition: NPLA1.h:574
platform::Descriptions::Warning
Definition: YCommon.h:167
YB_NORETURN
#define YB_NORETURN
指定无返回值函数。
Definition: ydef.h:504
platform::Descriptions::Err
Definition: YCommon.h:166
NPL::CheckReducible
bool CheckReducible(ReductionStatus status)
Definition: NPLA.cpp:442
NPL::A1::Forms::RetainN
ReductionStatus::Retained YF_API size_t RetainN(const TermNode &, size_t=1)
保留经检查确保具有指定个数参数的项：保留求值。
Definition: NPLA1.cpp:1058
ystdex::split
void split(_tIn b, _tIn e, _fPred is_delim, _fInsert insert)
以指定分隔符分割序列。
Definition: algorithm.hpp:215
scope_guard.hpp
作用域守护。
NPL::A1::TransformForSeparatorRecursive
YF_API TermNode TransformForSeparatorRecursive(const TermNode &, const ValueObject &, const ValueObject &, const TokenValue &={})
Definition: NPLA1.cpp:725
NPL::TNIter
TermNode::iterator TNIter
Definition: SContext.h:53
NPL::A1::Forms::BindParameter
YF_API void BindParameter(ContextNode &, const TermNode &, TermNode &)
使用操作数结构化匹配并绑定参数。
Definition: NPLA1.cpp:1069
YSLib::UI::name
yconstfn const string & name
Definition: Loader.h:130
platform::Descriptions::Informative
Definition: YCommon.h:169
NPL::Deliteralize
YF_API string_view Deliteralize(string_view) ynothrowv
去除字面量边界分隔符。
Definition: Lexical.cpp:249
ystdex::pvoid
enable_if_t< or_< is_object< _type >, is_void< _type > >::value, void * > pvoid(_type *p)
取 void* 类型的指针。
Definition: addressof.hpp:101
CHRLib::c
c
Definition: CharacterProcessing.h:81
NPL::A1::Forms::WrapOnce
YF_API ContextHandler WrapOnce(const ContextHandler &)
类型不符合要求。
Definition: NPLA1.cpp:1453
NPL::A1::Forms::VauWithEnvironment
YF_API void VauWithEnvironment(TermNode &, ContextNode &)
带环境的 vau 抽象：求值为一个捕获当前上下文的非严格求值的函数。
Definition: NPLA1.cpp:1292
ystdex::retry_on_cond
result_of_t< _fCallable &&(_tParams &&...)> retry_on_cond(_fCond cond, _fCallable &&f, _tParams &&...args)
循环重复调用：代替直接使用 do-while 语句以避免过多引入作用域外的变量。
Definition: functional.hpp:1152
NPL::A1::ToContextHandler
ContextHandler ToContextHandler(_tParams &&...args)
转换上下文处理器。
Definition: NPLA1.h:628
NPL::A1::Forms::And
YF_API ReductionStatus And(TermNode &, ContextNode &)
逻辑与。
Definition: NPLA1.cpp:1312
NPL::A1::ReduceArguments
YF_API void ReduceArguments(TNIter, TNIter, ContextNode &)
对范围内的第二项开始逐项规约。
Definition: NPLA1.cpp:583
NPL::NodeSequenceInserter
GNodeInserter< NodeSequence > NodeSequenceInserter
Definition: NPLA.h:121
NPL::A1::TransformNodeSequence
YF_API ValueNode TransformNodeSequence(const TermNode &, NodeMapper={}, NodeMapper=MapNPLALeafNode, NodeToString=ParseNPLANodeString, NodeSequenceInserter=InsertSequenceChild)
变换 NPLA1 节点 S 表达式抽象语法树为 NPLA1 序列语义结构。 第三至五参数为空。
Definition: NPLA1.cpp:113
NPL::A1::InvokeGuard
YF_API Guard InvokeGuard(TermNode &term, ContextNode &)
调用守护遍。
Definition: NPLA1.cpp:526
NPL::TokenizeTerm
YF_API void TokenizeTerm(TermNode &term)
标记记号节点：递归变换节点，转换其中的词素为记号值。
Definition: NPLA.cpp:414
NPL::A1::EvaluateDelayed
ReductionStatus EvaluateDelayed(TermNode &term)
Definition: NPLA1.cpp:800
ystdex::as_const
add_const_t< _type > & as_const(_type &t)
转换 const 引用。
Definition: utility.hpp:51
ystdex::cpp2011::begin
_type * begin(_type(&&array)[_vN])
Definition: range.hpp:46
NPL::A1::Forms::Or
YF_API ReductionStatus Or(TermNode &, ContextNode &)
逻辑或。
Definition: NPLA1.cpp:1318
NPL::A1::SetupTraceDepth
YF_API void SetupTraceDepth(ContextNode &ctx, const string &name=yimpl("$__depth"))
设置跟踪深度节点：调用规约时显示深度和上下文等信息。
Definition: NPLA1.cpp:688
NPL::A1::FetchArgumentN
FetchArgumentN
Definition: NPLA1.h:679
NPL::NPLException
NPL 异常基类。
Definition: NPLA.h:409
NPL::MapToValueNode
const TermNode &term ynothrow const TermNode &term ynothrow const TermNode &term ynothrow TermNode &term const TermNode &term MapToValueNode
Definition: SContext.h:80
NPL::ParameterMismatch
参数匹配失败。
Definition: NPLA.h:459
ystdex::size
auto size(const _tRange &c) -> decltype(c.size())
类容器访问。
Definition: range.hpp:233
NPL::A1::InvokeList
YF_API ReductionStatus InvokeList(TermNode &term, ContextNode &)
调用列表遍。
Definition: NPLA1.cpp:538
NPL::A1::ReduceChildren
YF_API void ReduceChildren(TNIter, TNIter, ContextNode &)
规约子项。
Definition: NPLA1.cpp:633
YSLib::vo
vo
Definition: YApplication.h:231
NPL::A1::AccessGuardPassesRef
YF_API GuardPasses & AccessGuardPassesRef(ContextNode &)
访问守护遍。
Definition: NPLA1.cpp:502
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::Forms::EqualReference
YF_API void EqualReference(TermNode &)
比较两个子项的值相等。
Definition: NPLA1.cpp:1372
NPL::ContextNode::Guard
GuardPasses Guard
Definition: NPLA.h:1187
NPL::A1::ReduceLeafToken
YF_API ReductionStatus ReduceLeafToken(TermNode &, ContextNode &)
规约提取名称的叶节点记号。 标识符未声明。
Definition: NPLA1.cpp:929
NPL::A1::AccessLiteralPassesRef
YF_API LiteralPasses & AccessLiteralPassesRef(ContextNode &)
访问字面量遍。
Definition: NPLA1.cpp:520
NPL::TermReference
项引用。
Definition: NPLA.h:667
ystdex::ref
lref< _type > ref(_type &t)
构造引用包装。
Definition: ref.hpp:132
store
unordered_map< string, shared_ptr_t > store
Definition: NPLA1.cpp:232
YSLib::ValueObject::emplace
void emplace(_type *p, PointerTag)
Definition: YObject.h:894
NPL::A1::Forms::GetCurrentEnvironment
YF_API void GetCurrentEnvironment(TermNode &, ContextNode &)
取包含当前环境的上下文引用。
Definition: NPLA1.cpp:1427
YSLib::ValueObject::AccessPtr
observer_ptr< _type > AccessPtr() ynothrow
访问指定类型对象指针。
Definition: YObject.h:773
ystdex::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:415
NPL::LiftToOther
YF_API void LiftToOther(TermNode &, TermNode &)
递归提升项及其子项或递归创建项和子项对应的包含间接值的引用项到其它项。
Definition: NPLA.cpp:507
NPL::SContext::Analyze
YF_API void Analyze(TermNode &, const TokenList &)
分析指定源，取抽象语法树储存至指定值类型节点。
Definition: SContext.cpp:92
ystdex::share_move
std::shared_ptr< decay_t< _type > > share_move(_tValue &&v)
转移值创建对应的 std::shared_ptr 实例的对象。
Definition: memory.hpp:991
NPL::A1::ResolveEnvironment
YF_API pair< shared_ptr< Environment >, bool > ResolveEnvironment(ValueObject &)
解析环境。
Definition: NPLA1.cpp:946
CHRLib::p
const auto p(d)
NPL::EnvironmentList
vector< ValueObject > EnvironmentList
环境列表。
Definition: NPLA.h:974
NPL::LiftTerm
YF_API void LiftTerm(TermNode &, TermNode &)
提升项：使用第二个参数指定的项的内容替换第一个项的内容。
Definition: NPLA.cpp:454