13 #include <unordered_set>
17 #include <hilti/ast/doc-string.h>
18 #include <hilti/ast/forward.h>
19 #include <hilti/ast/id.h>
20 #include <hilti/ast/meta.h>
21 #include <hilti/ast/node-range.h>
22 #include <hilti/ast/node-tag.h>
23 #include <hilti/ast/scope.h>
24 #include <hilti/ast/visitor-dispatcher.h>
26 #define __HILTI_NODE_COMMON_final(NS, CLASS) \
27 ::hilti::Node* _clone(::hilti::ASTContext* ctx) const final { return ctx->make<CLASS>(*this); }
29 #define __HILTI_NODE_COMMON_override(NS, CLASS)
31 #define __HILTI_NODE_COMMON(NS, CLASS, override_) \
32 friend class ::NS::builder::NodeBuilder; \
33 friend class hilti::ASTContext; \
34 friend class hilti::Node; \
35 std::string _typename() const override { return hilti::util::typename_(*this); } \
36 __HILTI_NODE_COMMON_##override_(NS, CLASS)
38 #define __HILTI_NODE_0(NS, CLASS, override_) \
39 __HILTI_NODE_COMMON(NS, CLASS, override_) \
41 static constexpr uint16_t NodeLevel = 1; \
42 static constexpr ::hilti::node::Tag NodeTag = ::hilti::node::tag::CLASS; \
43 static constexpr ::hilti::node::Tags NodeTags = {::hilti::node::tag::Node, ::hilti::node::tag::CLASS};
45 #define HILTI_NODE_0(CLASS, override_) \
46 __HILTI_NODE_0(hilti, CLASS, override_) \
48 void dispatch(::hilti::visitor::Dispatcher& v) override_ { \
49 v(static_cast<::hilti::Node*>(this)); \
53 #define __HILTI_NODE_1(NS, CLASS, BASE, override_) \
54 __HILTI_NODE_COMMON(NS, CLASS, override_) \
56 static constexpr uint16_t NodeLevel = 2; \
57 static constexpr ::hilti::node::Tag NodeTag = ::hilti::node::tag::CLASS; \
58 static constexpr ::hilti::node::Tags NodeTags = {::hilti::node::tag::Node, ::hilti::node::tag::BASE, \
59 ::hilti::node::tag::CLASS};
61 #define HILTI_NODE_1(CLASS, BASE, override_) \
62 __HILTI_NODE_1(hilti, CLASS, BASE, override_) \
64 void dispatch(::hilti::visitor::Dispatcher& v) override_ { \
65 v(static_cast<::hilti::Node*>(this)); \
66 v(static_cast<BASE*>(this)); \
70 #define __HILTI_NODE_2(NS, CLASS, BASE1, BASE2, override_) \
71 __HILTI_NODE_COMMON(NS, CLASS, override_) \
73 static constexpr uint16_t NodeLevel = 3; \
74 static constexpr ::hilti::node::Tag NodeTag = ::hilti::node::tag::CLASS; \
75 static constexpr ::hilti::node::Tags NodeTags = {::hilti::node::tag::Node, ::hilti::node::tag::BASE2, \
76 ::hilti::node::tag::BASE1, ::hilti::node::tag::CLASS};
78 #define HILTI_NODE_2(CLASS, BASE1, BASE2, override_) \
79 __HILTI_NODE_2(hilti, CLASS, BASE1, BASE2, override_) \
81 void dispatch(::hilti::visitor::Dispatcher& v) override_ { \
82 v(static_cast<::hilti::Node*>(this)); \
83 v(static_cast<BASE1*>(this)); \
84 v(static_cast<BASE2*>(this)); \
97 Node* deepcopy(ASTContext* ctx, Node* n,
bool force);
110 T* deepcopy(ASTContext* ctx, T* n,
bool force =
false) {
114 return detail::deepcopy(ctx, n, force)->template as<T>();
118 using PropertyValue = std::variant<bool,
const char*, double, int, int64_t,
unsigned int, uint64_t, std::string, ID,
119 std::optional<uint64_t>>;
122 inline std::string to_string(
const PropertyValue& v) {
124 auto operator()(
bool s) {
return std::string(s ?
"true" :
"false"); }
125 auto operator()(
const char* s) {
return util::escapeUTF8(s); }
126 auto operator()(
double d) {
return util::fmt(
"%.6f", d); }
127 auto operator()(
int i) {
return util::fmt(
"%d", i); }
128 auto operator()(int64_t i) {
return util::fmt(
"%" PRId64, i); }
129 auto operator()(
const std::string& s) {
return util::escapeUTF8(s); }
130 auto operator()(
const ID&
id) {
return id.str(); }
131 auto operator()(
const std::optional<uint64_t>& u) {
return u ? util::fmt(
"%" PRIu64, *u) :
"<not set>"; }
132 auto operator()(
unsigned int u) {
return util::fmt(
"%u", u); }
133 auto operator()(uint64_t u) {
return util::fmt(
"%" PRIu64, u); }
136 return std::visit(Visitor(), v);
140 enum class ErrorPriority {
147 inline bool operator<(ErrorPriority x, ErrorPriority y) {
148 return static_cast<std::underlying_type_t<ErrorPriority>
>(x) <
149 static_cast<std::underlying_type_t<ErrorPriority>
>(y);
161 bool operator<(
const Error& other)
const {
171 using Properties = std::map<std::string, node::PropertyValue>;
181 other._node =
nullptr;
188 if (
this == &other )
198 if (
this == &other )
203 other._node =
nullptr;
213 T* operator->()
const {
return _node; }
214 T& operator*()
const {
return *_node; }
215 explicit operator bool()
const {
return _node !=
nullptr; }
216 operator T*()
const {
return _node; }
218 T* get()
const {
return _node; }
246 for (
auto it = _node_tags.rbegin(); it != _node_tags.rend(); it++ ) {
268 for ( ; p && i > 1; i-- )
284 else if ( _parent->
isA_<T>() )
285 return static_cast<T*
>(_parent);
287 return _parent->
parent<T>();
297 for (
auto n =
parent(); n; i++, n = n->parent() )
305 const auto&
meta()
const {
return *_meta; }
308 const auto&
location()
const {
return _meta->location(); }
317 auto scope()
const {
return _scope.get(); }
326 _scope = std::make_unique<Scope>();
360 uintptr_t
identity()
const {
return reinterpret_cast<uintptr_t
>(
this); }
374 if ( i >= _children.size() )
377 return _children[i] ? _children[i]->as<T>() :
nullptr;
389 if ( i >= _children.size() )
392 return _children[i] ? _children[i]->tryAs<T>() :
nullptr;
403 if ( i >= _children.size() )
420 auto children(
int begin, std::optional<int> end)
const {
421 end = _normalizeEndIndex(begin, end);
440 end = _normalizeEndIndex(begin, end);
455 typename hilti::node::Set<T> n;
456 for (
auto c = _children.begin(); c != _children.end(); c = std::next(c) ) {
460 if (
auto t = (*c)->tryAs<T>() )
475 auto i = std::find(_children.begin(), _children.end(), n);
476 if ( i == _children.end() )
480 if ( ++i == _children.end() )
499 _children.emplace_back(
nullptr);
503 n = _newChild(ctx, n);
505 if ( ! n->
location() && _meta->location() )
508 _children.emplace_back(n);
535 if (
auto i = std::find(_children.begin(), _children.end(), n); i != _children.end() ) {
536 (*i)->_parent =
nullptr;
551 end = _normalizeEndIndex(begin, end);
555 auto end_ = _children.begin() + *end;
556 for (
auto i = _children.begin() + begin; i < end_; i++ ) {
558 (*i)->_parent =
nullptr;
563 _children.erase(_children.begin() + begin, end_);
578 if (
auto old = _children[idx] ) {
579 old->_parent =
nullptr;
584 _children[idx] =
nullptr;
588 n = _newChild(ctx, n);
592 if ( ! n->
location() && _meta->location() )
625 _checkCast<T>(
false);
627 return (T::NodeLevel < _node_tags.size() && T::NodeTag == _node_tags[T::NodeLevel]);
638 return (T::NodeLevel < _node_tags.size() && T::NodeTag == _node_tags[T::NodeLevel]);
650 return static_cast<const T*
>(
this);
664 return static_cast<T*
>(
this);
674 _checkCast<T>(
false);
678 return static_cast<const T*
>(
this);
690 _checkCast<T>(
false);
693 return static_cast<T*
>(
this);
708 return static_cast<T*
>(
this);
725 void print(std::ostream& out,
bool compact,
bool user_visible)
const;
734 std::string
print()
const;
749 operator std::string()
const {
return print(); }
755 std::string
dump()
const;
764 std::string
renderSelf(
bool include_location =
true)
const;
774 void addError(std::string msg, std::vector<std::string> context = {}) {
787 void addError(std::string msg, node::ErrorPriority priority, std::vector<std::string> context = {}) {
800 addError(std::move(msg),
location(), node::ErrorPriority::Normal, std::move(context));
811 void addError(std::string msg,
Location l, node::ErrorPriority priority, std::vector<std::string> context = {}) {
813 error.message = std::move(msg);
814 error.location = std::move(l);
815 error.context = std::move(context);
816 error.priority = priority;
819 _errors = std::make_unique<std::vector<node::Error>>();
821 _errors->emplace_back(std::move(error));
825 bool hasErrors()
const {
return _errors && ! _errors->empty(); }
829 static std::vector<node::Error> no_errors;
830 return _errors ? *_errors : no_errors;
844 assert(_ref_count != -1);
853 assert(_ref_count != -1);
854 assert(_ref_count > 0);
878 virtual std::string_view
branchTag()
const {
return ""; }
880 Node& operator=(
const Node& other) =
delete;
881 Node& operator=(
Node&& other) noexcept =
delete;
883 static constexpr uint16_t NodeLevel = 0;
884 static constexpr ::hilti::node::Tag NodeTag = ::hilti::node::tag::Node;
885 static constexpr ::hilti::node::Tags NodeTags = {::hilti::node::tag::Node};
898 : _node_tags(node_tags), _meta(
Meta::get(std::move(
meta))) {
899 assert(! _node_tags.empty());
903 c = _newChild(ctx, c);
904 assert(! c->_parent);
909 _children.push_back(c);
915 assert(! _node_tags.empty());
927 Node(
const Node& other) : _node_tags(other._node_tags) {
943 virtual std::string
_typename()
const {
return util::typename_(*
this); }
957 virtual std::string
_dump()
const {
return ""; }
967 std::optional<int> _normalizeEndIndex(
int begin, std::optional<int> end)
const {
968 if ( end && *end < 0 )
969 end =
static_cast<int>(_children.size()) + *end;
972 end = _children.size();
981 #pragma GCC diagnostic push
982 #pragma GCC diagnostic ignored "-Wpragmas"
983 #pragma GCC diagnostic ignored "-Wunknown-warning-option"
984 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
986 #pragma GCC diagnostic pop
995 void _checkCast(
bool enforce_success)
const {
998 auto ours = (T::NodeLevel < _node_tags.size() && T::NodeTag == _node_tags[T::NodeLevel]);
999 auto theirs = (
dynamic_cast<const T*
>(
this) !=
nullptr);
1001 if ( ours != theirs ) {
1002 std::cerr << util::fmt(
"internal error: Node::_checkCast() RTTI mismatch\n")
1003 << util::fmt(
"isA<T=%s>(%s) -> %s but dynamic_cast() says %s\n",
typeid(T).name(),
_typename(),
1004 ours ?
"true" :
"false", theirs ?
"true" :
"false")
1005 << util::fmt(
"T::type_level=%" PRIu16
" T::node_tags={%s} this->types={%s}\n", T::NodeLevel,
1006 node::to_string(T::NodeTags), node::to_string(_node_tags));
1010 if ( enforce_success && ! ours ) {
1011 std::cerr << util::fmt(
"internal error: unexpected type, want %s but have %s\n", util::typename_<T>(),
1021 if ( std::is_base_of_v<UnqualifiedType, T> && ! std::is_same_v<UnqualifiedType, T> )
1022 _checkCastBackend();
1027 void _checkCastBackend()
const;
1029 const node::Tags _node_tags;
1030 int64_t _ref_count = 0;
1032 Node* _parent =
nullptr;
1036 std::unique_ptr<Scope> _scope =
nullptr;
1037 std::unique_ptr<std::vector<node::Error>> _errors;
1055 node::Properties
properties()
const {
return {{
"unique_id", _id}}; }
1073 WithUniqueID(
const char* prefix) : _id(util::fmt(
"%s_%" PRIu64, prefix, _id_counter++)) {}
1078 inline static uint64_t _id_counter = 0;
1093 _doc = std::move(doc);
1099 std::optional<DocString> _doc;
1105 void recordSeen(
const Node* n) { _seen.insert(n); }
1106 bool haveSeen(
const Node* n)
const {
return _seen.find(n) != _seen.end(); }
1107 void clear() { _seen.clear(); }
1110 std::unordered_set<const Node*> _seen;
1117 template<
typename T>
1118 Nodes flatten(std::vector<T> t) {
1120 v.reserve(t.size());
1121 for (
auto it = std::make_move_iterator(t.begin()); it != std::make_move_iterator(t.end()); ++it )
1122 v.emplace_back(*it);
1131 template<
typename T>
1134 v.reserve(t.size());
1135 for (
const auto& i : t )
1136 v.emplace_back(std::move(i));
1142 template<
typename T = Node*>
1143 inline Nodes flatten(Node* n) {
1148 template<
typename T>
1149 inline Nodes flatten(T* n) {
1150 return {std::move(n)};
1154 template<
typename T = std::
nullptr_t>
1155 inline Nodes flatten(std::nullptr_t) {
1160 inline Nodes flatten() {
return Nodes(); }
1166 template<
typename T,
typename... Ts, std::enable_if_t<(0 !=
sizeof...(Ts))>* =
nullptr>
1167 Nodes flatten(T t, Ts... ts) {
1168 return util::concat(std::move(flatten(std::move(t))), flatten(std::move(ts)...));
1175 template<
typename X,
typename F>
1177 hilti::node::Set<X> y;
1178 for (
const auto& i : x ) {
1190 template<
typename X,
typename F>
1191 auto filter(
const hilti::node::Set<X>& x, F f) {
1192 hilti::node::Set<X> y;
1193 for (
const auto& i : x ) {
1205 template<
typename X,
typename F>
1207 using Y = std::invoke_result_t<F, X*>;
1209 y.reserve(x.size());
1210 for (
const auto& i : x )
1220 template<
typename X,
typename F>
1221 auto transform(
const hilti::node::Set<X>& x, F f) {
1222 using Y = std::invoke_result_t<F, X*>;
1224 y.reserve(x.size());
1225 for (
const auto& i : x )
1234 inline std::ostream& operator<<(std::ostream& out,
const Node& n) {
1235 n.print(out,
true,
true);
1241 inline hilti::node::Properties operator+(hilti::node::Properties p1, hilti::node::Properties p2) {
1242 p1.merge(std::move(p2));
Definition: ast-context.h:121
Definition: doc-string.h:13
Definition: location.h:17
Node * sibling(Node *n) const
Definition: node.h:474
T * parent() const
Definition: node.h:281
std::string renderSelf(bool include_location=true) const
Definition: node.cc:38
void clearScope()
Definition: node.h:335
T * tryAs_()
Definition: node.h:706
const T * tryAs() const
Definition: node.h:672
const auto & errors() const
Definition: node.h:828
void addError(std::string msg, std::vector< std::string > context={})
Definition: node.h:774
void setMeta(Meta m)
Definition: node.h:311
T * tryAs()
Definition: node.h:688
auto pathLength() const
Definition: node.h:295
T * as() const
Definition: node.h:646
bool hasErrors() const
Definition: node.h:825
bool isA_() const
Definition: node.h:637
auto children(int begin, std::optional< int > end) const
Definition: node.h:420
std::string print() const
Definition: node.cc:98
virtual Node * _clone(ASTContext *ctx) const =0
T * as()
Definition: node.h:660
Node * parent(int i=1) const
Definition: node.h:263
node::Tag nodeTag() const
Definition: node.h:244
void setChild(ASTContext *ctx, size_t idx, Node *n)
Definition: node.h:577
Node(const Node &other)
Definition: node.h:927
void clearErrors()
Definition: node.h:834
void addChild(ASTContext *ctx, Node *n)
Definition: node.h:497
void removeChild(Node *n)
Definition: node.h:531
virtual std::string _typename() const
Definition: node.h:943
T * childTryAs(unsigned int i) const
Definition: node.h:388
void addError(std::string msg, Location l, node::ErrorPriority priority, std::vector< std::string > context={})
Definition: node.h:811
virtual bool inheritScope() const
Definition: node.h:351
auto children(int begin, std::optional< int > end)
Definition: node.h:439
uintptr_t identity() const
Definition: node.h:360
const auto & location() const
Definition: node.h:308
void release()
Definition: node.h:852
auto scope() const
Definition: node.h:317
const auto & children() const
Definition: node.h:363
auto getOrCreateScope()
Definition: node.h:324
virtual std::string_view branchTag() const
Definition: node.h:878
void replaceChild(ASTContext *ctx, Node *old, Node *new_)
Definition: node.cc:110
Node * child(unsigned int i) const
Definition: node.h:402
void addError(std::string msg, node::ErrorPriority priority, std::vector< std::string > context={})
Definition: node.h:787
void replaceChildren(ASTContext *ctx, const Nodes &children)
Definition: node.cc:121
const auto & meta() const
Definition: node.h:305
virtual std::string _dump() const
Definition: node.h:957
Node(ASTContext *ctx, node::Tags node_tags, Nodes children, Meta meta)
Definition: node.h:897
void removeChildren(int begin, std::optional< int > end)
Definition: node.h:550
bool isRetained() const
Definition: node.h:859
T * child(unsigned int i) const
Definition: node.h:373
node::Set< T > childrenOfType() const
Definition: node.h:454
std::string printRaw() const
Definition: node.cc:104
std::string dump() const
Definition: node.cc:31
Node(ASTContext *ctx, node::Tags node_tags, Meta meta)
Definition: node.h:914
void clearChildren()
Definition: node.cc:128
bool hasParent() const
Definition: node.h:255
virtual node::Properties properties() const
Definition: node.h:866
virtual void dispatch(visitor::Dispatcher &v)=0
void addChildren(ASTContext *ctx, const Nodes &children)
Definition: node.h:520
bool isA() const
Definition: node.h:623
void retain()
Definition: node.h:843
Result< std::pair< Declaration *, ID > > lookupID(const ID &id, const std::string_view &what) const
Definition: node.cc:214
std::string typename_() const
Definition: node.h:357
void addError(std::string msg, const Location &l, std::vector< std::string > context={})
Definition: node.h:799
Definition: forward.h:758
Definition: node-range.h:92
void clearDocumentation()
Definition: node.h:1088
const std::optional< DocString > & documentation() const
Definition: node.h:1085
void setDocumentation(DocString doc)
Definition: node.h:1091
ID uniqueID() const
Definition: node.h:1052
node::Properties properties() const
Definition: node.h:1055
WithUniqueID(const char *prefix)
Definition: node.h:1073
Definition: visitor-dispatcher.h:9
auto transform(const C &x, F f)
Definition: util.h:417
std::string message
Definition: node.h:154
ErrorPriority priority
Definition: node.h:157
Location location
Definition: node.h:155
std::vector< std::string > context
Definition: node.h:156