15 #include <type_traits> 24 #include <hilti/ast/meta.h> 25 #include <hilti/ast/node-ref.h> 26 #include <hilti/ast/scope.h> 27 #include <hilti/base/type_erase.h> 28 #include <hilti/base/util.h> 45 using PropertyValue = std::variant<bool, const char*, double, int, int64_t, unsigned int, uint64_t, std::string>;
48 inline std::string to_string(
const PropertyValue& v) {
50 auto operator()(
bool s) {
return std::string(s ?
"true" :
"false"); }
51 auto operator()(
const char* s) {
return util::escapeUTF8(s); }
52 auto operator()(
double d) {
return util::fmt(
"%.6f", d); }
53 auto operator()(
int i) {
return util::fmt(
"%d", i); }
54 auto operator()(int64_t i) {
return util::fmt(
"%" PRId64, i); }
55 auto operator()(
const std::string& s) {
return util::escapeUTF8(s); }
56 auto operator()(
unsigned int u) {
return util::fmt(
"%u", u); }
57 auto operator()(uint64_t u) {
return util::fmt(
"%" PRIu64, u); }
60 return std::visit(Visitor(), v);
74 return static_cast<std::underlying_type_t<ErrorPriority>
>(x) <
75 static_cast<std::underlying_type_t<ErrorPriority>
>(y);
87 bool operator<(
const Error& other)
const {
88 return std::tie(message, location) < std::tie(other.
message, other.
location);
97 using Properties = std::map<std::string, node::detail::PropertyValue>;
100 #include <hilti/autogen/__node.h> 111 class Node final :
public node::detail::Node {
114 template<typename T, typename std::enable_if_t<std::is_base_of<trait::isNode, T>::value>* =
nullptr>
117 Node(
const Node& other) : node::detail::Node::Node(other), _scope(other._scope) {}
120 : node::detail::Node::Node(std::move(other)),
121 _control_ptr(std::move(other._control_ptr)),
122 _scope(std::move(other._scope)),
123 _errors(std::move(other._errors)) {
125 _control_ptr->_node =
this;
132 _control_ptr->_node =
nullptr;
142 uint64_t
rid()
const {
return _control_ptr ? _control_ptr->_rid : 0; }
149 std::string
renderedRid()
const {
return rid() ? util::fmt(
"%%%" PRIu64, rid()) :
"%???"; };
159 _scope = make_intrusive<Scope>();
176 _scope = make_intrusive<Scope>();
180 std::vector<node::Error>
errors()
const {
188 bool hasErrors()
const {
return _errors && _errors->size(); }
204 void addError(std::string msg, std::vector<std::string> context = {}) {
205 addError(std::move(msg),
location(), std::move(context));
218 addError(std::move(msg),
location(), priority, std::move(context));
243 error.
message = std::move(msg);
245 error.
context = std::move(context);
249 _errors = std::make_unique<std::vector<node::Error>>();
251 _errors->push_back(std::move(error));
258 void destroyChildren();
267 std::string render(
bool include_location =
true)
const;
279 void print(std::ostream& out,
bool compact =
false)
const;
285 std::string print()
const;
294 std::cerr <<
"Assertion failure: Node expected to be a " <<
typeid(T).name() <<
" but is a " 295 << typeid_().name() << std::endl;
296 util::abort_with_backtrace();
301 operator std::string()
const {
return print(); }
312 node::detail::ErasedBase::operator=(n);
321 _scope = std::move(n._scope);
322 node::detail::ErasedBase::operator=(std::move(n));
333 node::detail::ErasedBase::operator=(to_node(t));
343 if ( ! _control_ptr )
344 _control_ptr = make_intrusive<node_ref::detail::Control>(
this);
351 std::unique_ptr<std::vector<node::Error>> _errors =
nullptr;
375 for (
auto& c : children )
376 addChild(std::move(c));
390 return _children[i].as<T>();
401 _children[i].template assertIsA<T>();
415 auto end_ = (end < 0) ? _children.end() : _children.begin() + end;
428 auto end_ = (end < 0) ? _children.end() : _children.begin() + end;
430 std::vector<NodeRef> refs;
431 for (
auto c = _children.begin(); c != end_; c = std::next(c) )
432 refs.emplace_back(*c);
454 std::vector<NodeRef> childRefsOfType()
const;
461 if ( _meta.location() && ! n.
location() ) {
463 m.setLocation(_meta.location());
464 n.setMeta(std::move(m));
467 _children.push_back(std::move(n));
475 auto&
meta()
const {
return _meta; }
482 std::vector<::hilti::Node> _children;
515 using BaseIterator = std::vector<Node>::const_iterator;
518 using value_type = BaseIterator::value_type;
519 using difference_type = BaseIterator::difference_type;
520 using pointer = BaseIterator::pointer;
521 using reference = BaseIterator::reference;
522 using iterator_category = BaseIterator::iterator_category;
530 const Node& node()
const {
return *_iter; }
534 const T& operator*()
const {
return value(); }
535 const T* operator->()
const {
return &value(); }
536 bool operator==(
const RangeIterator& other)
const {
return _iter == other._iter; }
537 bool operator!=(
const RangeIterator& other)
const {
return ! (*
this == other); }
560 difference_type operator-(
const RangeIterator& other)
const {
return _iter - other._iter; }
565 const T& value()
const {
return (*_iter).template as<std::remove_const_t<T>>(); }
582 Range(std::vector<Node>::const_iterator begin, std::vector<Node>::const_iterator end) : _begin(begin), _end(end) {}
584 explicit Range(
const std::vector<Node>& nodes) :
Range(nodes.begin(), nodes.end()) {}
590 auto begin()
const {
return const_iterator(_begin); }
591 auto end()
const {
return const_iterator(_end); }
592 size_t size()
const {
return static_cast<size_t>(_end - _begin); }
593 const T& front()
const {
return *_begin; }
594 bool empty()
const {
return _begin == _end; }
602 for (
auto i = _begin; i != _end; i++ )
608 const T& operator[](
size_t i)
const {
609 assert(
static_cast<typename RangeIterator<T>::difference_type
>(i) < std::distance(_begin, _end));
610 return *(_begin + i);
613 bool operator==(
const Range& other)
const {
614 if (
this == &other )
617 if ( size() != other.size() )
621 auto y = other._begin;
622 while ( x != _end ) {
623 if ( ! (*x++ == *y++) )
630 Range& operator=(
const Range& other) =
default;
631 Range& operator=(
Range&& other) noexcept =
default;
646 using BaseIterator =
typename std::vector<std::reference_wrapper<const T>>::const_iterator;
650 using value_type = T;
651 using difference_type =
typename BaseIterator::difference_type;
652 using pointer =
typename BaseIterator::pointer;
653 using reference =
typename BaseIterator::reference;
654 using iterator_category =
typename BaseIterator::iterator_category;
656 explicit SetIterator(BaseIterator i) : _iter(std::move(i)) {}
662 const Node& node()
const {
return *_iter; }
666 const T& operator*()
const {
return value(); }
667 const T* operator->()
const {
return &value(); }
668 bool operator==(
const SetIterator& other)
const {
return _iter == other._iter; }
669 bool operator!=(
const SetIterator& other)
const {
return ! (*
this == other); }
692 difference_type operator-(
const SetIterator& other)
const {
return _iter - other._iter; }
697 const T& value()
const {
return ((*_iter).get()); }
715 Set(
const Set& other) =
default;
716 Set(
Set&& other) noexcept =
default;
719 auto begin()
const {
return const_iterator(_set.begin()); }
720 auto end()
const {
return const_iterator(_set.end()); }
721 size_t size()
const {
return _set.size(); }
722 bool empty()
const {
return _set.empty(); }
723 void insert(
const T& t) { _set.push_back(t); }
731 for (
auto i = begin(); i != end(); i++ )
737 const T& operator[](
size_t i)
const {
return *(begin() + i); }
739 bool operator==(
const Set& other)
const {
740 if (
this == &other )
743 if ( size() != other.size() )
747 auto y = other.begin();
748 while ( x != end() ) {
749 if ( ! (*x++ == *y++) )
756 Set& operator=(
const Set& other) =
default;
757 Set& operator=(
Set&& other) noexcept =
default;
760 std::vector<std::reference_wrapper<const T>> _set;
772 template<
typename T, IF_SAME(T, Node)>
773 inline Node to_node(
const T& n) {
779 Node to_node(std::optional<T> t) {
781 return to_node(std::move(*t));
791 std::vector<Node> nodes(std::vector<T> t) {
794 for (
const auto& i : t )
795 v.emplace_back(std::move(i));
805 std::vector<Node> nodes(std::list<T> t) {
807 for (
const auto& i : t )
808 v.emplace_back(std::move(i));
821 for (
const auto& i : t )
822 v.emplace_back(std::move(i));
829 std::vector<Node> nodes(T t) {
830 return {to_node(std::move(t))};
837 template<
typename T,
typename... Ts>
838 std::vector<Node> nodes(T t, Ts... ts) {
839 return util::concat(std::move(nodes(t)), nodes(std::move(ts)...));
849 template<
typename T,
typename Other, IF_DERIVED_FROM(T, trait::isNode), IF_DERIVED_FROM(Other, trait::isNode)>
850 bool isEqual(
const T* this_,
const Other& other) {
851 if (
const auto o = other.template tryAs<T>() )
861 template<
typename X,
typename F>
864 for (
const auto& i : x ) {
876 template<
typename X,
typename F>
879 for (
const auto& i : x ) {
891 template<
typename X,
typename F>
893 using Y =
typename std::invoke_result_t<F, X&>;
896 for (
const auto& i : x )
906 template<
typename X,
typename F>
908 using Y =
typename std::invoke_result_t<F, X&>;
911 for (
const auto& i : x )
921 inline std::ostream& operator<<(std::ostream& out,
const Node& n) {
929 for (
auto c = _children.begin(); c != _children.end(); c = std::next(c) ) {
930 if (
auto t = c->tryAs<T>() )
939 typename std::vector<NodeRef> n;
940 for (
auto c = _children.begin(); c != _children.end(); c = std::next(c) ) {
960 detail::flattenedChildren(n, &dst);
std::vector< T > copy() const
Definition: node.h:600
ErrorPriority priority
Definition: node.h:83
std::vector< std::string > context
Definition: node.h:82
uint64_t rid() const
Definition: node.h:142
bool pruneWalk() const
Definition: node.h:479
IntrusivePtr< Scope > scope() const
Definition: node.h:157
NodeBase(Meta meta)
Definition: node.h:366
void assertIsA()
Definition: node.h:292
void addError(std::string msg, const Location &l, std::vector< std::string > context={})
Definition: node.h:229
Node & operator=(const T &t)
Definition: node.h:332
const Node none
Definition: node.cc:14
auto filter(const hilti::node::Range< X > &x, F f)
Definition: node.h:862
auto childRefs(int begin, int end)
Definition: node.h:427
bool hasErrors() const
Definition: node.h:188
Definition: optional.h:79
const auto & children() const
Definition: node.h:471
static None create()
Definition: node.h:499
void addChild(Node n)
Definition: node.h:460
void clearScope()
Definition: node.h:170
auto & children()
Definition: node.h:473
void addError(std::string msg, std::vector< std::string > context={})
Definition: node.h:204
void setScope(IntrusivePtr< Scope > new_scope)
Definition: node.h:167
const Location & location() const
Definition: node.h:288
Location location
Definition: node.h:81
Node & operator=(Node &&n) noexcept
Definition: node.h:320
std::vector< NodeRef > childRefsOfType() const
Definition: node.h:938
std::vector< T > copy() const
Definition: node.h:729
std::string renderedRid() const
Definition: node.h:149
void clearErrors()
Definition: node.h:191
void addError(std::string msg, Location l, node::ErrorPriority priority, std::vector< std::string > context={})
Definition: node.h:241
auto properties() const
Definition: node.h:493
std::vector< node::Error > errors() const
Definition: node.h:180
Definition: intrusive-ptr.h:69
auto children(int begin, int end) const
Definition: node.h:414
Definition: type_erase.h:30
void setMeta(Meta m)
Definition: node.h:477
void print(std::ostream &out, bool compact=false) const
Definition: node.cc:103
std::map< std::string, node::detail::PropertyValue > Properties
Definition: node.h:97
std::string message
Definition: node.h:80
hilti::node::Set< T > childrenOfType() const
Definition: node.h:927
const T & child(int i) const
Definition: node.h:389
NodeBase(std::vector< Node > children, Meta meta)
Definition: node.h:374
Definition: node-ref.h:45
Definition: location.h:18
void addError(std::string msg, node::ErrorPriority priority, std::vector< std::string > context={})
Definition: node.h:217
Node & operator=(const Node &n)
Definition: node.h:307
ErrorPriority
Definition: node.h:66
auto & meta() const
Definition: node.h:475
Definition: location.h:94
Node(T t)
Definition: node.h:115
void assertChildIsA(int i)
Definition: node.h:400