mirror of https://github.com/djcb/mu.git
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.
This commit is contained in:
parent
3624fdd5f3
commit
9bab2a4050
|
@ -93,7 +93,7 @@ validate(const CommandHandler::CommandInfoMap& cmap,
|
||||||
[&](auto&& arg) { return cmdargname == arg.first; }))
|
[&](auto&& arg) { return cmdargname == arg.first; }))
|
||||||
return Err(Error::Code::Command,
|
return Err(Error::Code::Command,
|
||||||
"unknown parameter '%s 'in command '%s'",
|
"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();
|
return Ok();
|
||||||
|
|
|
@ -71,7 +71,7 @@ struct Command: public Sexp {
|
||||||
* @return name
|
* @return name
|
||||||
*/
|
*/
|
||||||
const std::string& name() const {
|
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)
|
if (auto&& val{arg_val(name, Sexp::Type::Symbol)}; !val)
|
||||||
return Nothing;
|
return Nothing;
|
||||||
else
|
else
|
||||||
return val->symbol();
|
return val->symbol().name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -201,7 +201,7 @@ Sexp::to_string(Format fopts) const
|
||||||
else if (numberp())
|
else if (numberp())
|
||||||
sstrm << number();
|
sstrm << number();
|
||||||
else if (symbolp())
|
else if (symbolp())
|
||||||
sstrm << symbol();
|
sstrm << symbol().name;
|
||||||
|
|
||||||
if (typeinfop)
|
if (typeinfop)
|
||||||
sstrm << '<' << Sexp::type_name(type()) << '>';
|
sstrm << '<' << Sexp::type_name(type()) << '>';
|
||||||
|
@ -224,7 +224,7 @@ Sexp::to_json_string(Format fopts) const
|
||||||
auto it{list().begin()};
|
auto it{list().begin()};
|
||||||
bool first{true};
|
bool first{true};
|
||||||
while (it != list().end()) {
|
while (it != list().end()) {
|
||||||
sstrm << (first ? "" : ",") << quote(it->symbol()) << ":";
|
sstrm << (first ? "" : ",") << quote(it->symbol().name) << ":";
|
||||||
++it;
|
++it;
|
||||||
sstrm << it->to_json_string();
|
sstrm << it->to_json_string();
|
||||||
++it;
|
++it;
|
||||||
|
@ -255,7 +255,7 @@ Sexp::to_json_string(Format fopts) const
|
||||||
else if (symbol() == "t")
|
else if (symbol() == "t")
|
||||||
sstrm << "true";
|
sstrm << "true";
|
||||||
else
|
else
|
||||||
sstrm << quote(symbol());
|
sstrm << quote(symbol().name);
|
||||||
break;
|
break;
|
||||||
case Type::Number:
|
case Type::Number:
|
||||||
sstrm << number();
|
sstrm << number();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** Copyright (C) 2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
** Copyright (C) 2020-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
**
|
**
|
||||||
** This program is free software; you can redistribute it and/or modify it
|
** 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
|
** under the terms of the GNU General Public License as published by the
|
||||||
|
@ -33,6 +33,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include <utils/mu-result.hh>
|
#include <utils/mu-result.hh>
|
||||||
|
#include <utils/mu-option.hh>
|
||||||
|
|
||||||
namespace Mu {
|
namespace Mu {
|
||||||
|
|
||||||
|
@ -54,18 +55,21 @@ struct Sexp {
|
||||||
Symbol(std::string_view sv): Symbol(std::string{sv}) {}
|
Symbol(std::string_view sv): Symbol(std::string{sv}) {}
|
||||||
operator const std::string&() const {return name; }
|
operator const std::string&() const {return name; }
|
||||||
std::string 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 };
|
enum struct Type { List, String, Number, Symbol };
|
||||||
using Data = std::variant<List, String, Number, Symbol>;
|
using ValueType = std::variant<List, String, Number, Symbol>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the type of data
|
* Get the type of value
|
||||||
*
|
*
|
||||||
* @return type
|
* @return type
|
||||||
*/
|
*/
|
||||||
constexpr Type type() const { return static_cast<Type>(data.index()); }
|
constexpr Type type() const { return static_cast<Type>(value.index()); }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name for some type
|
* Get the name for some type
|
||||||
*
|
*
|
||||||
|
@ -88,64 +92,65 @@ struct Sexp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr bool stringp() const { return std::holds_alternative<String>(value); }
|
||||||
|
constexpr bool numberp() const { return std::holds_alternative<Number>(value); }
|
||||||
|
constexpr bool listp() const { return std::holds_alternative<List>(value); }
|
||||||
|
constexpr bool symbolp() const { return std::holds_alternative<Symbol>(value); }
|
||||||
|
|
||||||
constexpr bool stringp() const { return std::holds_alternative<String>(data); }
|
constexpr bool symbolp(const Sexp::Symbol& sym) const {return symbolp() && symbol() == sym; }
|
||||||
constexpr bool numberp() const { return std::holds_alternative<Number>(data); }
|
|
||||||
constexpr bool listp() const { return std::holds_alternative<List>(data); }
|
|
||||||
constexpr bool symbolp() const { return std::holds_alternative<Symbol>(data); }
|
|
||||||
|
|
||||||
constexpr bool nilp() const { return symbolp() && symbol() == "nil"; }
|
constexpr bool nilp() const { return symbolp() && symbol() == "nil"; }
|
||||||
static const Sexp& nil() { static const Sexp nilsym(Symbol{"nil"}); return nilsym; }
|
static const Sexp& nil() { static const Sexp nilsym(Symbol{"nil"}); return nilsym; }
|
||||||
static const Sexp& t() { static const Sexp tsym(Symbol{"t"}); return tsym; }
|
static const Sexp& t() { static const Sexp tsym(Symbol{"t"}); return tsym; }
|
||||||
|
|
||||||
// Get the specific variant type.
|
// Get the specific variant type.
|
||||||
const List& list() const { return std::get<List>(data); }
|
const List& list() const { return std::get<List>(value); }
|
||||||
List& list() { return std::get<List>(data); }
|
List& list() { return std::get<List>(value); }
|
||||||
const String& string() const { return std::get<String>(data); }
|
const String& string() const { return std::get<String>(value); }
|
||||||
String& string() { return std::get<String>(data); }
|
String& string() { return std::get<String>(value); }
|
||||||
const Number& number() const { return std::get<Number>(data); }
|
const Number& number() const { return std::get<Number>(value); }
|
||||||
Number& number() { return std::get<Number>(data); }
|
Number& number() { return std::get<Number>(value); }
|
||||||
const String& symbol() const { return std::get<Symbol>(data).name; }
|
const Symbol& symbol() const { return std::get<Symbol>(value); }
|
||||||
String& symbol() { return std::get<Symbol>(data).name; }
|
Symbol& symbol() { return std::get<Symbol>(value); }
|
||||||
|
|
||||||
/// Default ctor
|
/// Default ctor
|
||||||
Sexp():data{List{}} {} // default: an empty list.
|
Sexp():value{List{}} {} // default: an empty list.
|
||||||
|
|
||||||
// Copy & move ctors
|
// Copy & move ctors
|
||||||
Sexp(const Sexp& other):data{other.data}{}
|
Sexp(const Sexp& other):value{other.value}{}
|
||||||
Sexp(Sexp&& other):data{std::move(other.data)}{}
|
Sexp(Sexp&& other):value{std::move(other.value)}{}
|
||||||
|
|
||||||
// Assignment
|
// Assignment
|
||||||
Sexp& operator=(const Sexp& rhs) {
|
Sexp& operator=(const Sexp& rhs) {
|
||||||
if (this != &rhs)
|
if (this != &rhs)
|
||||||
data = rhs.data;
|
value = rhs.value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
Sexp& operator=(Sexp&& rhs) {
|
Sexp& operator=(Sexp&& rhs) {
|
||||||
if (this != &rhs)
|
if (this != &rhs)
|
||||||
data = std::move(rhs.data);
|
value = std::move(rhs.value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type specific ctors
|
/// Type specific ctors
|
||||||
Sexp(const List& lst): data{lst} {}
|
Sexp(const List& lst): value{lst} {}
|
||||||
Sexp(List&& lst): data{std::move(lst)} {}
|
Sexp(List&& lst): value{std::move(lst)} {}
|
||||||
|
|
||||||
Sexp(const String& str): data{str} {}
|
Sexp(const String& str): value{str} {}
|
||||||
Sexp(String&& str): data{std::move(str)} {}
|
Sexp(String&& str): value{std::move(str)} {}
|
||||||
Sexp(const char *str): Sexp{std::string{str}} {}
|
Sexp(const char *str): Sexp{std::string{str}} {}
|
||||||
Sexp(std::string_view sv): Sexp{std::string{sv}} {}
|
Sexp(std::string_view sv): Sexp{std::string{sv}} {}
|
||||||
|
|
||||||
template<typename N, typename = std::enable_if_t<std::is_integral_v<N>> >
|
template<typename N, typename = std::enable_if_t<std::is_integral_v<N>> >
|
||||||
Sexp(N n):data{static_cast<Number>(n)} {}
|
Sexp(N n):value{static_cast<Number>(n)} {}
|
||||||
|
|
||||||
Sexp(const Symbol& sym): data{sym} {}
|
Sexp(const Symbol& sym): value{sym} {}
|
||||||
Sexp(Symbol&& sym): data{std::move(sym)} {}
|
Sexp(Symbol&& sym): value{std::move(sym)} {}
|
||||||
|
|
||||||
///
|
///
|
||||||
template<typename S, typename T, typename... Args>
|
template<typename S, typename T, typename... Args>
|
||||||
Sexp(S&& s, T&& t, Args&&... args): data{List()} {
|
Sexp(S&& s, T&& t, Args&&... args): value{List()} {
|
||||||
auto& l{std::get<List>(data)};
|
auto& l{std::get<List>(value)};
|
||||||
l.emplace_back(Sexp(std::forward<S>(s)));
|
l.emplace_back(Sexp(std::forward<S>(s)));
|
||||||
l.emplace_back(Sexp(std::forward<T>(t)));
|
l.emplace_back(Sexp(std::forward<T>(t)));
|
||||||
(l.emplace_back(Sexp(std::forward<Args>(args))), ...);
|
(l.emplace_back(Sexp(std::forward<Args>(args))), ...);
|
||||||
|
@ -164,6 +169,8 @@ struct Sexp {
|
||||||
/// List specific
|
/// List specific
|
||||||
using iterator = List::iterator;
|
using iterator = List::iterator;
|
||||||
using const_iterator = List::const_iterator;
|
using const_iterator = List::const_iterator;
|
||||||
|
|
||||||
|
|
||||||
iterator begin() { return list().begin(); }
|
iterator begin() { return list().begin(); }
|
||||||
const_iterator begin() const { return list().begin(); }
|
const_iterator begin() const { return list().begin(); }
|
||||||
const_iterator cbegin() const { return list().cbegin(); }
|
const_iterator cbegin() const { return list().cbegin(); }
|
||||||
|
@ -172,6 +179,19 @@ struct Sexp {
|
||||||
const_iterator end() const { return list().end(); }
|
const_iterator end() const { return list().end(); }
|
||||||
const_iterator cend() const { return list().cend(); }
|
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<Sexp&> head() { if (listp()&&!empty()) return front(); else return Nothing; }
|
||||||
|
Option<const Sexp&> head() const { if (listp()&&!empty()) return front(); else return Nothing; }
|
||||||
|
|
||||||
|
Option<Sexp&> tail() {
|
||||||
|
if (listp()&&!empty()&&cbegin()+1!=cend()) return *(begin()+1); else return Nothing; }
|
||||||
|
Option<const Sexp&> tail() const {
|
||||||
|
if (listp()&&!empty()&&cbegin()+1!=cend()) return *(cbegin()+1); else return Nothing; }
|
||||||
|
|
||||||
bool empty() const { return list().empty(); }
|
bool empty() const { return list().empty(); }
|
||||||
size_t size() const { return list().size(); }
|
size_t size() const { return list().size(); }
|
||||||
void clear() { list().clear(); }
|
void clear() { list().clear(); }
|
||||||
|
@ -240,7 +260,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
iterator find_prop(const std::string& s,iterator b,
|
iterator find_prop(const std::string& s,iterator b,
|
||||||
iterator e);
|
iterator e);
|
||||||
Data data;
|
ValueType value;
|
||||||
};
|
};
|
||||||
|
|
||||||
MU_ENABLE_BITOPS(Sexp::Format);
|
MU_ENABLE_BITOPS(Sexp::Format);
|
||||||
|
|
Loading…
Reference in New Issue