diff options
author | Scott Linder <scott@scottlinder.com> | 2018-11-14 19:39:59 +0000 |
---|---|---|
committer | Scott Linder <scott@scottlinder.com> | 2018-11-14 19:39:59 +0000 |
commit | c0830f55779adf07809f6b1af4351c3a2f293dfc (patch) | |
tree | 2e0903f2f91d399847025dea59473c66baf26b9d /llvm/lib/Support/YAMLTraits.cpp | |
parent | 32dc5b9bf134b5a98c1a22395a5cd0ca5c409fe7 (diff) | |
download | bcm5719-llvm-c0830f55779adf07809f6b1af4351c3a2f293dfc.tar.gz bcm5719-llvm-c0830f55779adf07809f6b1af4351c3a2f293dfc.zip |
[Support] Teach YAMLIO about polymorphic types
Add support for "polymorphic" types to YAMLIO.
PolymorphicTraits can dynamically switch between other traits (Scalar, Map, or
Sequence). When inputting, the PolymorphicTraits type is told which type to
become, and when outputting the PolymorphicTraits type is asked which type it
currently is.
Also add support for TaggedScalarTraits to allow dynamically differentiating
between multiple scalar types using YAML tags.
Serialize empty maps as "{}" and empty sequences as "[]", so that types
are preserved when round-tripping PolymorphicTraits. This change has
equivalent semantics, but may break e.g. tests which compare output
verbatim.
Differential Revision: https://reviews.llvm.org/D48144
llvm-svn: 346884
Diffstat (limited to 'llvm/lib/Support/YAMLTraits.cpp')
-rw-r--r-- | llvm/lib/Support/YAMLTraits.cpp | 88 |
1 files changed, 73 insertions, 15 deletions
diff --git a/llvm/lib/Support/YAMLTraits.cpp b/llvm/lib/Support/YAMLTraits.cpp index f8492c96bab..b9bbee7883c 100644 --- a/llvm/lib/Support/YAMLTraits.cpp +++ b/llvm/lib/Support/YAMLTraits.cpp @@ -341,11 +341,25 @@ void Input::scalarString(StringRef &S, QuotingType) { void Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); } +void Input::scalarTag(std::string &Tag) { + Tag = CurrentNode->_node->getVerbatimTag(); +} + void Input::setError(HNode *hnode, const Twine &message) { assert(hnode && "HNode must not be NULL"); setError(hnode->_node, message); } +NodeKind Input::getNodeKind() { + if (isa<ScalarHNode>(CurrentNode)) + return NodeKind::Scalar; + else if (isa<MapHNode>(CurrentNode)) + return NodeKind::Map; + else if (isa<SequenceHNode>(CurrentNode)) + return NodeKind::Sequence; + llvm_unreachable("Unsupported node kind"); +} + void Input::setError(Node *node, const Twine &message) { Strm->printError(node, message); EC = make_error_code(errc::invalid_argument); @@ -436,9 +450,11 @@ bool Output::mapTag(StringRef Tag, bool Use) { // If this tag is being written inside a sequence we should write the start // of the sequence before writing the tag, otherwise the tag won't be // attached to the element in the sequence, but rather the sequence itself. - bool SequenceElement = - StateStack.size() > 1 && (StateStack[StateStack.size() - 2] == inSeq || - StateStack[StateStack.size() - 2] == inFlowSeq); + bool SequenceElement = false; + if (StateStack.size() > 1) { + auto &E = StateStack[StateStack.size() - 2]; + SequenceElement = inSeqAnyElement(E) || inFlowSeqAnyElement(E); + } if (SequenceElement && StateStack.back() == inMapFirstKey) { newLineCheck(); } else { @@ -461,6 +477,9 @@ bool Output::mapTag(StringRef Tag, bool Use) { } void Output::endMapping() { + // If we did not map anything, we should explicitly emit an empty map + if (StateStack.back() == inMapFirstKey) + output("{}"); StateStack.pop_back(); } @@ -524,12 +543,15 @@ void Output::endDocuments() { } unsigned Output::beginSequence() { - StateStack.push_back(inSeq); + StateStack.push_back(inSeqFirstElement); NeedsNewLine = true; return 0; } void Output::endSequence() { + // If we did not emit anything, we should explicitly emit an empty sequence + if (StateStack.back() == inSeqFirstElement) + output("[]"); StateStack.pop_back(); } @@ -538,10 +560,17 @@ bool Output::preflightElement(unsigned, void *&) { } void Output::postflightElement(void *) { + if (StateStack.back() == inSeqFirstElement) { + StateStack.pop_back(); + StateStack.push_back(inSeqOtherElement); + } else if (StateStack.back() == inFlowSeqFirstElement) { + StateStack.pop_back(); + StateStack.push_back(inFlowSeqOtherElement); + } } unsigned Output::beginFlowSequence() { - StateStack.push_back(inFlowSeq); + StateStack.push_back(inFlowSeqFirstElement); newLineCheck(); ColumnAtFlowStart = Column; output("[ "); @@ -680,6 +709,14 @@ void Output::blockScalarString(StringRef &S) { } } +void Output::scalarTag(std::string &Tag) { + if (Tag.empty()) + return; + newLineCheck(); + output(Tag); + output(" "); +} + void Output::setError(const Twine &message) { } @@ -693,7 +730,7 @@ bool Output::canElideEmptySequence() { return true; if (StateStack.back() != inMapFirstKey) return true; - return (StateStack[StateStack.size()-2] != inSeq); + return !inSeqAnyElement(StateStack[StateStack.size() - 2]); } void Output::output(StringRef s) { @@ -703,9 +740,8 @@ void Output::output(StringRef s) { void Output::outputUpToEndOfLine(StringRef s) { output(s); - if (StateStack.empty() || (StateStack.back() != inFlowSeq && - StateStack.back() != inFlowMapFirstKey && - StateStack.back() != inFlowMapOtherKey)) + if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) && + !inFlowMapAnyKey(StateStack.back()))) NeedsNewLine = true; } @@ -725,16 +761,20 @@ void Output::newLineCheck() { outputNewLine(); - assert(StateStack.size() > 0); + if (StateStack.size() == 0) + return; + unsigned Indent = StateStack.size() - 1; bool OutputDash = false; - if (StateStack.back() == inSeq) { + if (StateStack.back() == inSeqFirstElement || + StateStack.back() == inSeqOtherElement) { OutputDash = true; - } else if ((StateStack.size() > 1) && ((StateStack.back() == inMapFirstKey) || - (StateStack.back() == inFlowSeq) || - (StateStack.back() == inFlowMapFirstKey)) && - (StateStack[StateStack.size() - 2] == inSeq)) { + } else if ((StateStack.size() > 1) && + ((StateStack.back() == inMapFirstKey) || + inFlowSeqAnyElement(StateStack.back()) || + (StateStack.back() == inFlowMapFirstKey)) && + inSeqAnyElement(StateStack[StateStack.size() - 2])) { --Indent; OutputDash = true; } @@ -772,6 +812,24 @@ void Output::flowKey(StringRef Key) { output(": "); } +NodeKind Output::getNodeKind() { report_fatal_error("invalid call"); } + +bool Output::inSeqAnyElement(InState State) { + return State == inSeqFirstElement || State == inSeqOtherElement; +} + +bool Output::inFlowSeqAnyElement(InState State) { + return State == inFlowSeqFirstElement || State == inFlowSeqOtherElement; +} + +bool Output::inMapAnyKey(InState State) { + return State == inMapFirstKey || State == inMapOtherKey; +} + +bool Output::inFlowMapAnyKey(InState State) { + return State == inFlowMapFirstKey || State == inFlowMapOtherKey; +} + //===----------------------------------------------------------------------===// // traits for built-in types //===----------------------------------------------------------------------===// |