From 3c76819687f547ad15a6aead3b52926035c98043 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Fri, 23 Jun 2023 16:54:19 +0200 Subject: [PATCH] Annotations draft --- implementations/cpp/main.cpp | 1 + .../cpp/preserves_binary_reader.hpp | 9 +- implementations/cpp/preserves_impl.hpp | 84 ++++++++++++++++++- implementations/cpp/preserves_value.hpp | 14 +++- 4 files changed, 102 insertions(+), 6 deletions(-) diff --git a/implementations/cpp/main.cpp b/implementations/cpp/main.cpp index 38be6cb..c06f028 100644 --- a/implementations/cpp/main.cpp +++ b/implementations/cpp/main.cpp @@ -27,4 +27,5 @@ TEST(BinaryReader, ReadSamples) { BinaryReader<> r(f, &GenericEmbedded::wrap); auto v = r.next(); ASSERT_TRUE(v); + BinaryWriter(cerr) << *v; } \ No newline at end of file diff --git a/implementations/cpp/preserves_binary_reader.hpp b/implementations/cpp/preserves_binary_reader.hpp index bdae954..1bbc853 100644 --- a/implementations/cpp/preserves_binary_reader.hpp +++ b/implementations/cpp/preserves_binary_reader.hpp @@ -79,7 +79,6 @@ namespace Preserves { } boost::optional> _next(bool& end_sentinel) { - more: end_sentinel = false; auto tag = BinaryTag(i.get()); // std::cout << "tag " << std::hex << int(tag) << " pos " << i.tellg() - 1 << std::endl; @@ -90,9 +89,11 @@ namespace Preserves { case BinaryTag::Float: return next_float().map(Value::from_float); case BinaryTag::Double: return next_double().map(Value::from_double); case BinaryTag::End: end_sentinel = true; return boost::none; - case BinaryTag::Annotation: - if (!next()) return boost::none; - goto more; + case BinaryTag::Annotation: return next().flat_map([&](Value const& ann) -> boost::optional> { + return next().flat_map([&](Value const& v) -> boost::optional> { + return v.annotate(ann); + }); + }); case BinaryTag::Embedded: return BinaryReader(i, &GenericEmbedded::wrap) .next().map(decodeEmbedded).map(Value::from_embedded); diff --git a/implementations/cpp/preserves_impl.hpp b/implementations/cpp/preserves_impl.hpp index 75ea7b9..3c26653 100644 --- a/implementations/cpp/preserves_impl.hpp +++ b/implementations/cpp/preserves_impl.hpp @@ -269,6 +269,88 @@ namespace Preserves { } }; + template + class AnnotatedValue: public ValueImpl { + Value underlying; + std::vector> anns; + + friend class ValueImpl; + + protected: + Value internal_annotate(std::shared_ptr> const& self, Value const &ann) { + if (self.use_count() == 1) { + anns.push_back(ann); + return self; + } else { + auto a = std::make_shared>(underlying); + a->anns.insert(a->anns.end(), anns.begin(), anns.end()); + a->anns.push_back(ann); + return Value(a); + } + } + + public: + AnnotatedValue(Value const& v) : underlying(v) {} + + ValueKind value_kind() const override { return underlying.value_kind(); } + bool is_mutable() const override { return underlying.is_mutable(); } + + boost::optional as_bool() const override { return underlying.as_bool(); } + boost::optional as_float() const override { return underlying.as_float(); } + boost::optional as_double() const override { return underlying.as_double(); } + boost::optional as_unsigned() const override { return underlying.as_unsigned(); } + boost::optional as_signed() const override { return underlying.as_signed(); } + boost::optional const&> as_bignum() const override { return underlying.as_bignum(); } + boost::optional as_string() const override { return underlying.as_string(); } + boost::optional const&> as_bytes() const override { return underlying.as_bytes(); } + boost::optional as_symbol() const override { return underlying.as_symbol(); } + boost::optional const&> as_record() const override { return underlying.as_record(); } + boost::optional> const&> as_sequence() const override { return underlying.as_sequence(); } + boost::optional> const&> as_set() const override { return underlying.as_set(); } + boost::optional,Value> const&> as_dictionary() const override { return underlying.as_dictionary(); } + boost::optional> as_embedded() const override { return underlying.as_embedded(); } + + boost::optional> label() const override { return underlying.label(); } + size_t size() const override { return underlying.size(); } + bool contains(Value const& key) const override { return underlying.contains(key); } + boost::optional> get(Value const& key) const override { return underlying.get(key); } + boost::optional> get(size_t index) const override { return underlying.get(index); } + + bool add(Value const& item) override { + return underlying->add(item); + } + bool set(Value const& key, Value const& value) override { + return underlying->set(key, value); + } + bool set(size_t index, Value const& value) override { + return underlying->set(index, value); + } + bool erase(Value const& key) override { + return underlying->erase(key); + } + + boost::optional> const&> annotations() const override { + return anns; + } + + BinaryWriter& write(BinaryWriter &w) const override { + for (auto& v : anns) { w << BinaryTag::Annotation << v; } + return w << underlying; + } + }; + + template + Value Value::annotate(Value const& ann) const { + return p->internal_annotate(p, ann); + } + + template + Value ValueImpl::internal_annotate(std::shared_ptr> const& self, Value const &ann) { + auto a = std::make_shared>(Value(self)); + a->anns.push_back(ann); + return Value(a); + } + template Value Value::from_bool(bool b) { @@ -312,4 +394,4 @@ namespace Preserves { Value Value::from_embedded(std::shared_ptr const& v) { return Value(new Embedded(v)); } -} \ No newline at end of file +} diff --git a/implementations/cpp/preserves_value.hpp b/implementations/cpp/preserves_value.hpp index 70a46e6..c282d91 100644 --- a/implementations/cpp/preserves_value.hpp +++ b/implementations/cpp/preserves_value.hpp @@ -148,6 +148,9 @@ namespace Preserves { boost::optional> as_embedded() const; std::shared_ptr to_embedded() const { return as_embedded().value(); } + Value annotate(Value const& ann) const; + boost::optional const&> annotations() const; + boost::optional label() const; size_t size() const; bool contains(Value const& key) const; @@ -161,6 +164,10 @@ namespace Preserves { template class ValueImpl { + protected: + virtual Value internal_annotate(std::shared_ptr> const& self, Value const& ann); + + friend class Value; public: virtual ~ValueImpl() {} @@ -201,6 +208,8 @@ namespace Preserves { throw std::runtime_error("Cannot erase item in Preserves value"); } + virtual boost::optional> const&> annotations() const { return boost::none; } + virtual BinaryWriter& write(BinaryWriter& w) const = 0; }; @@ -227,6 +236,9 @@ namespace Preserves { PRESERVES_DELEGATE_CAST(std::shared_ptr, as_embedded); #undef PRESERVES_DELEGATE_CAST + template boost::optional> Value::label() const { return p->label(); } + template bool Value::contains(Value const& key) const { return p->contains(key); } + template boost::optional> Value::get(Value const& key) const { return p->get(key); } template boost::optional> Value::get(size_t index) const { return p->get(index); } template size_t Value::size() const { return p->size(); } @@ -293,4 +305,4 @@ namespace Preserves { default: throw std::runtime_error("Invalid ValueKind"); } } -} \ No newline at end of file +}