From 9bab2a4050c4c52f17ae57a11315d453adbfcd36 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sun, 4 Jun 2023 14:26:37 +0300 Subject: [PATCH] utils/sexp: add some convenience Add some convenience function for dealing the head/tail Some whitespace / cosmetics Add operators == Add operator != Update command handler for this. --- lib/utils/mu-command-handler.cc | 2 +- lib/utils/mu-command-handler.hh | 4 +- lib/utils/mu-sexp.cc | 6 +-- lib/utils/mu-sexp.hh | 92 ++++++++++++++++++++------------- 4 files changed, 62 insertions(+), 42 deletions(-) diff --git a/lib/utils/mu-command-handler.cc b/lib/utils/mu-command-handler.cc index 1037e8fa..d335d966 100644 --- a/lib/utils/mu-command-handler.cc +++ b/lib/utils/mu-command-handler.cc @@ -93,7 +93,7 @@ validate(const CommandHandler::CommandInfoMap& cmap, [&](auto&& arg) { return cmdargname == arg.first; })) return Err(Error::Code::Command, "unknown parameter '%s 'in command '%s'", - cmdargname.c_str(), cmd.to_string().c_str()); + cmdargname.name.c_str(), cmd.to_string().c_str()); } return Ok(); diff --git a/lib/utils/mu-command-handler.hh b/lib/utils/mu-command-handler.hh index bbd48779..f358cf50 100644 --- a/lib/utils/mu-command-handler.hh +++ b/lib/utils/mu-command-handler.hh @@ -71,7 +71,7 @@ struct Command: public Sexp { * @return name */ const std::string& name() const { - return cbegin()->symbol(); + return cbegin()->symbol().name; } /** @@ -119,7 +119,7 @@ struct Command: public Sexp { if (auto&& val{arg_val(name, Sexp::Type::Symbol)}; !val) return Nothing; else - return val->symbol(); + return val->symbol().name; } /** diff --git a/lib/utils/mu-sexp.cc b/lib/utils/mu-sexp.cc index ecca2b10..a588f7c0 100644 --- a/lib/utils/mu-sexp.cc +++ b/lib/utils/mu-sexp.cc @@ -201,7 +201,7 @@ Sexp::to_string(Format fopts) const else if (numberp()) sstrm << number(); else if (symbolp()) - sstrm << symbol(); + sstrm << symbol().name; if (typeinfop) sstrm << '<' << Sexp::type_name(type()) << '>'; @@ -224,7 +224,7 @@ Sexp::to_json_string(Format fopts) const auto it{list().begin()}; bool first{true}; while (it != list().end()) { - sstrm << (first ? "" : ",") << quote(it->symbol()) << ":"; + sstrm << (first ? "" : ",") << quote(it->symbol().name) << ":"; ++it; sstrm << it->to_json_string(); ++it; @@ -255,7 +255,7 @@ Sexp::to_json_string(Format fopts) const else if (symbol() == "t") sstrm << "true"; else - sstrm << quote(symbol()); + sstrm << quote(symbol().name); break; case Type::Number: sstrm << number(); diff --git a/lib/utils/mu-sexp.hh b/lib/utils/mu-sexp.hh index dde4949d..57ca3607 100644 --- a/lib/utils/mu-sexp.hh +++ b/lib/utils/mu-sexp.hh @@ -1,5 +1,5 @@ /* -** Copyright (C) 2022 Dirk-Jan C. Binnema +** Copyright (C) 2020-2023 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -33,6 +33,7 @@ #include #include +#include namespace Mu { @@ -54,18 +55,21 @@ struct Sexp { Symbol(std::string_view sv): Symbol(std::string{sv}) {} operator const std::string&() const {return name; } std::string name; + + bool operator==(const Symbol& rhs) const { + return this == &rhs ? true : rhs.name == name; + } + bool operator!=(const Symbol& rhs) const { return *this == rhs ? false : true; } }; - enum struct Type { List, String, Number, Symbol }; - using Data = std::variant; + enum struct Type { List, String, Number, Symbol }; + using ValueType = std::variant; /** - * Get the type of data + * Get the type of value * * @return type */ - constexpr Type type() const { return static_cast(data.index()); } - - + constexpr Type type() const { return static_cast(value.index()); } /** * Get the name for some type * @@ -88,64 +92,65 @@ struct Sexp { } } + constexpr bool stringp() const { return std::holds_alternative(value); } + constexpr bool numberp() const { return std::holds_alternative(value); } + constexpr bool listp() const { return std::holds_alternative(value); } + constexpr bool symbolp() const { return std::holds_alternative(value); } - constexpr bool stringp() const { return std::holds_alternative(data); } - constexpr bool numberp() const { return std::holds_alternative(data); } - constexpr bool listp() const { return std::holds_alternative(data); } - constexpr bool symbolp() const { return std::holds_alternative(data); } + constexpr bool symbolp(const Sexp::Symbol& sym) const {return symbolp() && symbol() == sym; } constexpr bool nilp() const { return symbolp() && symbol() == "nil"; } static const Sexp& nil() { static const Sexp nilsym(Symbol{"nil"}); return nilsym; } static const Sexp& t() { static const Sexp tsym(Symbol{"t"}); return tsym; } // Get the specific variant type. - const List& list() const { return std::get(data); } - List& list() { return std::get(data); } - const String& string() const { return std::get(data); } - String& string() { return std::get(data); } - const Number& number() const { return std::get(data); } - Number& number() { return std::get(data); } - const String& symbol() const { return std::get(data).name; } - String& symbol() { return std::get(data).name; } + const List& list() const { return std::get(value); } + List& list() { return std::get(value); } + const String& string() const { return std::get(value); } + String& string() { return std::get(value); } + const Number& number() const { return std::get(value); } + Number& number() { return std::get(value); } + const Symbol& symbol() const { return std::get(value); } + Symbol& symbol() { return std::get(value); } /// Default ctor - Sexp():data{List{}} {} // default: an empty list. + Sexp():value{List{}} {} // default: an empty list. // Copy & move ctors - Sexp(const Sexp& other):data{other.data}{} - Sexp(Sexp&& other):data{std::move(other.data)}{} + Sexp(const Sexp& other):value{other.value}{} + Sexp(Sexp&& other):value{std::move(other.value)}{} // Assignment Sexp& operator=(const Sexp& rhs) { if (this != &rhs) - data = rhs.data; + value = rhs.value; return *this; } Sexp& operator=(Sexp&& rhs) { if (this != &rhs) - data = std::move(rhs.data); + value = std::move(rhs.value); return *this; } /// Type specific ctors - Sexp(const List& lst): data{lst} {} - Sexp(List&& lst): data{std::move(lst)} {} + Sexp(const List& lst): value{lst} {} + Sexp(List&& lst): value{std::move(lst)} {} - Sexp(const String& str): data{str} {} - Sexp(String&& str): data{std::move(str)} {} + Sexp(const String& str): value{str} {} + Sexp(String&& str): value{std::move(str)} {} Sexp(const char *str): Sexp{std::string{str}} {} Sexp(std::string_view sv): Sexp{std::string{sv}} {} template> > - Sexp(N n):data{static_cast(n)} {} + Sexp(N n):value{static_cast(n)} {} - Sexp(const Symbol& sym): data{sym} {} - Sexp(Symbol&& sym): data{std::move(sym)} {} + Sexp(const Symbol& sym): value{sym} {} + Sexp(Symbol&& sym): value{std::move(sym)} {} /// template - Sexp(S&& s, T&& t, Args&&... args): data{List()} { - auto& l{std::get(data)}; + Sexp(S&& s, T&& t, Args&&... args): value{List()} { + auto& l{std::get(value)}; l.emplace_back(Sexp(std::forward(s))); l.emplace_back(Sexp(std::forward(t))); (l.emplace_back(Sexp(std::forward(args))), ...); @@ -162,8 +167,10 @@ struct Sexp { /// List specific - using iterator = List::iterator; - using const_iterator = List::const_iterator; + using iterator = List::iterator; + using const_iterator = List::const_iterator; + + iterator begin() { return list().begin(); } const_iterator begin() const { return list().begin(); } const_iterator cbegin() const { return list().cbegin(); } @@ -172,6 +179,19 @@ struct Sexp { const_iterator end() const { return list().end(); } const_iterator cend() const { return list().cend(); } + + Sexp& front() { return list().front(); } + const Sexp& front() const { return list().front(); } + void pop_front() { list().erase(list().begin()); } + + Option head() { if (listp()&&!empty()) return front(); else return Nothing; } + Option head() const { if (listp()&&!empty()) return front(); else return Nothing; } + + Option tail() { + if (listp()&&!empty()&&cbegin()+1!=cend()) return *(begin()+1); else return Nothing; } + Option tail() const { + if (listp()&&!empty()&&cbegin()+1!=cend()) return *(cbegin()+1); else return Nothing; } + bool empty() const { return list().empty(); } size_t size() const { return list().size(); } void clear() { list().clear(); } @@ -240,7 +260,7 @@ protected: private: iterator find_prop(const std::string& s,iterator b, iterator e); - Data data; + ValueType value; }; MU_ENABLE_BITOPS(Sexp::Format);