14 #include <unordered_set>
18 #include <hilti/ast/doc-string.h>
19 #include <hilti/ast/forward.h>
20 #include <hilti/ast/id.h>
21 #include <hilti/ast/meta.h>
22 #include <hilti/ast/node-range.h>
23 #include <hilti/ast/node-tag.h>
24 #include <hilti/ast/scope.h>
25 #include <hilti/ast/visitor-dispatcher.h>
27 #define __HILTI_NODE_COMMON_final(NS, CLASS) \
28 ::hilti::Node* _clone(::hilti::ASTContext* ctx) const final { return ctx->make<CLASS>(*this); }
30 #define __HILTI_NODE_COMMON_override(NS, CLASS)
32 #define __HILTI_NODE_COMMON(NS, CLASS, override_) \
33 friend class ::NS::builder::NodeBuilder; \
34 friend class hilti::ASTContext; \
35 friend class hilti::Node; \
36 std::string _typename() const override { return hilti::util::typename_(*this); } \
37 __HILTI_NODE_COMMON_##override_(NS, CLASS)
39 #define __HILTI_NODE_0(NS, CLASS, override_) \
40 __HILTI_NODE_COMMON(NS, CLASS, override_) \
42 static constexpr uint16_t NodeLevel = 1; \
43 static constexpr ::hilti::node::Tag NodeTag = ::hilti::node::tag::CLASS; \
44 static constexpr ::hilti::node::Tags NodeTags = {::hilti::node::tag::Node, ::hilti::node::tag::CLASS};
46 #define HILTI_NODE_0(CLASS, override_) \
47 __HILTI_NODE_0(hilti, CLASS, override_) \
49 void dispatch(::hilti::visitor::Dispatcher& v) override_ { \
50 v(static_cast<::hilti::Node*>(this)); \
54 #define __HILTI_NODE_1(NS, CLASS, BASE, override_) \
55 __HILTI_NODE_COMMON(NS, CLASS, override_) \
57 static constexpr uint16_t NodeLevel = 2; \
58 static constexpr ::hilti::node::Tag NodeTag = ::hilti::node::tag::CLASS; \
59 static constexpr ::hilti::node::Tags NodeTags = {::hilti::node::tag::Node, ::hilti::node::tag::BASE, \
60 ::hilti::node::tag::CLASS};
62 #define HILTI_NODE_1(CLASS, BASE, override_) \
63 __HILTI_NODE_1(hilti, CLASS, BASE, override_) \
65 void dispatch(::hilti::visitor::Dispatcher& v) override_ { \
66 v(static_cast<::hilti::Node*>(this)); \
67 v(static_cast<BASE*>(this)); \
71 #define __HILTI_NODE_2(NS, CLASS, BASE1, BASE2, override_) \
72 __HILTI_NODE_COMMON(NS, CLASS, override_) \
74 static constexpr uint16_t NodeLevel = 3; \
75 static constexpr ::hilti::node::Tag NodeTag = ::hilti::node::tag::CLASS; \
76 static constexpr ::hilti::node::Tags NodeTags = {::hilti::node::tag::Node, ::hilti::node::tag::BASE2, \
77 ::hilti::node::tag::BASE1, ::hilti::node::tag::CLASS};
79 #define HILTI_NODE_2(CLASS, BASE1, BASE2, override_) \
80 __HILTI_NODE_2(hilti, CLASS, BASE1, BASE2, override_) \
82 void dispatch(::hilti::visitor::Dispatcher& v) override_ { \
83 v(static_cast<::hilti::Node*>(this)); \
84 v(static_cast<BASE1*>(this)); \
85 v(static_cast<BASE2*>(this)); \
98 Node* deepcopy(ASTContext* ctx, Node* n,
bool force);
111 T* deepcopy(ASTContext* ctx, T* n,
bool force =
false) {
115 return detail::deepcopy(ctx, n, force)->template as<T>();
119 using PropertyValue = std::variant<bool,
const char*, double, int, int64_t,
unsigned int, uint64_t, std::string, ID,
120 std::optional<uint64_t>>;
123 inline std::string to_string(
const PropertyValue& v) {
125 auto operator()(
bool s) {
return std::string(s ?
"true" :
"false"); }
126 auto operator()(
const char* s) {
return util::escapeUTF8(s); }
127 auto operator()(
double d) {
return util::fmt(
"%.6f", d); }
128 auto operator()(
int i) {
return util::fmt(
"%d", i); }
129 auto operator()(int64_t i) {
return util::fmt(
"%" PRId64, i); }
130 auto operator()(
const std::string& s) {
return util::escapeUTF8(s); }
131 auto operator()(
const ID&
id) {
return id.str(); }
132 auto operator()(
const std::optional<uint64_t>& u) {
return u ? util::fmt(
"%" PRIu64, *u) :
"<not set>"; }
133 auto operator()(
unsigned int u) {
return util::fmt(
"%u", u); }
134 auto operator()(uint64_t u) {
return util::fmt(
"%" PRIu64, u); }
137 return std::visit(Visitor(), v);
141 enum class ErrorPriority {
148 inline bool operator<(ErrorPriority x, ErrorPriority y) {
149 return static_cast<std::underlying_type_t<ErrorPriority>
>(x) <
150 static_cast<std::underlying_type_t<ErrorPriority>
>(y);
162 bool operator<(
const Error& other)
const {
172 using Properties = std::map<std::string, node::PropertyValue>;
182 other._node =
nullptr;
189 if (
this == &other )
199 if (
this == &other )
204 other._node =
nullptr;
214 T* operator->()
const {
return _node; }
215 T& operator*()
const {
return *_node; }
216 explicit operator bool()
const {
return _node !=
nullptr; }
217 operator T*()
const {
return _node; }
219 T* get()
const {
return _node; }
247 for (
auto _node_tag : std::ranges::reverse_view(_node_tags) ) {
248 if ( _node_tag != 0 )
269 for ( ; p && i > 1; i-- )
285 else if ( _parent->
isA_<T>() )
286 return static_cast<T*
>(_parent);
288 return _parent->
parent<T>();
298 for (
auto* n =
parent(); n; i++, n = n->parent() )
306 const auto&
meta()
const {
return *_meta; }
309 const auto&
location()
const {
return _meta->location(); }
318 auto scope()
const {
return _scope.get(); }
327 _scope = std::make_unique<Scope>();
375 if ( i >= _children.size() )
378 return _children[i] ? _children[i]->as<T>() :
nullptr;
390 if ( i >= _children.size() )
393 return _children[i] ? _children[i]->tryAs<T>() :
nullptr;
404 if ( i >= _children.size() )
421 auto children(
int begin, std::optional<int> end)
const {
422 end = _normalizeEndIndex(begin, end);
441 end = _normalizeEndIndex(begin, end);
456 typename hilti::node::Set<T> n;
457 for (
auto c = _children.begin(); c != _children.end(); c = std::next(c) ) {
461 if (
auto t = (*c)->tryAs<T>() )
478 if ( std::ranges::find(_children, n) != _children.end() )
484 for (
const auto* c : _children ) {
485 if ( c && c->hasChild(n, recurse) )
500 auto i = std::ranges::find(_children, n);
501 if ( i == _children.end() )
505 if ( ++i == _children.end() )
524 _children.emplace_back(
nullptr);
528 n = _newChild(ctx, n);
530 if ( ! n->
location() && _meta->location() )
533 _children.emplace_back(n);
560 if (
auto i = std::ranges::find(_children, n); i != _children.end() ) {
561 (*i)->_parent =
nullptr;
576 end = _normalizeEndIndex(begin, end);
580 auto end_ = _children.begin() + *end;
581 for (
auto i = _children.begin() + begin; i < end_; i++ ) {
583 (*i)->_parent =
nullptr;
588 _children.erase(_children.begin() + begin, end_);
603 if (
auto* old = _children[idx] ) {
604 old->_parent =
nullptr;
609 _children[idx] =
nullptr;
613 n = _newChild(ctx, n);
617 if ( ! n->
location() && _meta->location() )
650 _checkCast<T>(
false);
652 return (T::NodeLevel < _node_tags.size() && T::NodeTag == _node_tags[T::NodeLevel]);
663 return (T::NodeLevel < _node_tags.size() && T::NodeTag == _node_tags[T::NodeLevel]);
675 return static_cast<const T*
>(
this);
689 return static_cast<T*
>(
this);
699 _checkCast<T>(
false);
703 return static_cast<const T*
>(
this);
715 _checkCast<T>(
false);
718 return static_cast<T*
>(
this);
733 return static_cast<T*
>(
this);
750 void print(std::ostream& out,
bool compact,
bool user_visible)
const;
759 std::string
print()
const;
774 operator std::string()
const {
return print(); }
780 std::string
dump()
const;
789 std::string
renderSelf(
bool include_location =
true)
const;
799 void addError(std::string msg, std::vector<std::string> context = {}) {
812 void addError(std::string msg, node::ErrorPriority priority, std::vector<std::string> context = {}) {
825 addError(std::move(msg),
location(), node::ErrorPriority::Normal, std::move(context));
836 void addError(std::string msg,
Location l, node::ErrorPriority priority, std::vector<std::string> context = {}) {
838 error.message = std::move(msg);
839 error.location = std::move(l);
840 error.context = std::move(context);
841 error.priority = priority;
844 _errors = std::make_unique<std::vector<node::Error>>();
846 _errors->emplace_back(std::move(error));
850 bool hasErrors()
const {
return _errors && ! _errors->empty(); }
854 static std::vector<node::Error> no_errors;
855 return _errors ? *_errors : no_errors;
869 assert(_ref_count != -1);
878 assert(_ref_count != -1);
879 assert(_ref_count > 0);
903 virtual std::string_view
branchTag()
const {
return ""; }
905 Node& operator=(
const Node& other) =
delete;
906 Node& operator=(
Node&& other) noexcept =
delete;
908 static constexpr uint16_t NodeLevel = 0;
909 static constexpr ::hilti::node::Tag NodeTag = ::hilti::node::tag::Node;
910 static constexpr ::hilti::node::Tags NodeTags = {::hilti::node::tag::Node};
923 : _node_tags(node_tags), _meta(
Meta::get(std::move(
meta))) {
924 assert(! _node_tags.empty());
928 c = _newChild(ctx, c);
929 assert(! c->_parent);
934 _children.push_back(c);
940 assert(! _node_tags.empty());
952 Node(
const Node& other) : _node_tags(other._node_tags) {
968 virtual std::string
_typename()
const {
return util::typename_(*
this); }
982 virtual std::string
_dump()
const {
return ""; }
992 std::optional<int> _normalizeEndIndex(
int begin, std::optional<int> end)
const {
993 if ( end && *end < 0 )
994 end =
static_cast<int>(_children.size()) + *end;
997 end = _children.size();
1010 template<
typename T>
1011 void _checkCast(
bool enforce_success)
const {
1014 auto ours = (T::NodeLevel < _node_tags.size() && T::NodeTag == _node_tags[T::NodeLevel]);
1015 auto theirs = (
dynamic_cast<const T*
>(
this) !=
nullptr);
1017 if ( ours != theirs ) {
1018 std::cerr << util::fmt(
"internal error: Node::_checkCast() RTTI mismatch\n")
1019 << util::fmt(
"isA<T=%s>(%s) -> %s but dynamic_cast() says %s\n",
typeid(T).name(),
_typename(),
1020 ours ?
"true" :
"false", theirs ?
"true" :
"false")
1021 << util::fmt(
"T::type_level=%" PRIu16
" T::node_tags={%s} this->types={%s}\n", T::NodeLevel,
1022 node::to_string(T::NodeTags), node::to_string(_node_tags));
1026 if ( enforce_success && ! ours ) {
1027 std::cerr << util::fmt(
"internal error: unexpected type, want %s but have %s\n", util::typename_<T>(),
1037 if ( std::is_base_of_v<UnqualifiedType, T> && ! std::is_same_v<UnqualifiedType, T> )
1038 _checkCastBackend();
1043 void _checkCastBackend()
const;
1045 const node::Tags _node_tags;
1046 int64_t _ref_count = 0;
1048 Node* _parent =
nullptr;
1052 std::unique_ptr<Scope> _scope =
nullptr;
1053 std::unique_ptr<std::vector<node::Error>> _errors;
1055 static uint64_t _instances;
1056 uint64_t _identity = _instances++;
1074 node::Properties
properties()
const {
return {{
"unique_id", _id}}; }
1092 WithUniqueID(
const char* prefix) : _id(util::fmt(
"%s_%" PRIu64, prefix, _id_counter++)) {}
1097 inline static uint64_t _id_counter = 0;
1112 _doc = std::move(doc);
1118 std::optional<DocString> _doc;
1124 void recordSeen(
const Node* n) { _seen.insert(n); }
1125 bool haveSeen(
const Node* n)
const {
return _seen.contains(n); }
1126 void clear() { _seen.clear(); }
1129 std::unordered_set<const Node*> _seen;
1136 template<
typename T>
1137 Nodes flatten(std::vector<T> t) {
1139 v.reserve(t.size());
1140 for (
auto it = std::make_move_iterator(t.begin()); it != std::make_move_iterator(t.end()); ++it )
1141 v.emplace_back(*it);
1150 template<
typename T>
1153 v.reserve(t.size());
1154 for (
const auto& i : t )
1155 v.emplace_back(std::move(i));
1161 template<
typename T = Node*>
1162 inline Nodes flatten(Node* n) {
1167 template<
typename T>
1168 inline Nodes flatten(T* n) {
1169 return {std::move(n)};
1173 template<
typename T = std::
nullptr_t>
1174 inline Nodes flatten(std::nullptr_t) {
1179 inline Nodes flatten() {
return Nodes(); }
1185 template<
typename T,
typename... Ts>
1186 Nodes flatten(T t, Ts... ts)
1187 requires(0 !=
sizeof...(Ts))
1189 return util::concat(std::move(flatten(std::move(t))), flatten(std::move(ts)...));
1196 template<
typename X,
typename F>
1198 hilti::node::Set<X> y;
1199 for (
const auto& i : x ) {
1211 template<
typename X,
typename F>
1212 auto filter(
const hilti::node::Set<X>& x, F f) {
1213 hilti::node::Set<X> y;
1214 for (
const auto& i : x ) {
1226 template<
typename X,
typename F>
1228 using Y = std::invoke_result_t<F, X*>;
1230 y.reserve(x.size());
1231 for (
const auto& i : x )
1241 template<
typename X,
typename F>
1242 auto transform(
const hilti::node::Set<X>& x, F f) {
1243 using Y = std::invoke_result_t<F, X*>;
1245 y.reserve(x.size());
1246 for (
const auto& i : x )
1255 inline std::ostream& operator<<(std::ostream& out,
const Node& n) {
1256 n.print(out,
true,
true);
1262 inline hilti::node::Properties operator+(hilti::node::Properties p1, hilti::node::Properties p2) {
1263 p1.merge(std::move(p2));
Definition: ast-context.h:121
Definition: doc-string.h:15
Definition: location.h:17
Node * sibling(Node *n) const
Definition: node.h:499
T * parent() const
Definition: node.h:282
std::string renderSelf(bool include_location=true) const
Definition: node.cc:41
void clearScope()
Definition: node.h:336
T * tryAs_()
Definition: node.h:731
const T * tryAs() const
Definition: node.h:697
const auto & errors() const
Definition: node.h:853
void addError(std::string msg, std::vector< std::string > context={})
Definition: node.h:799
void setMeta(Meta m)
Definition: node.h:312
T * tryAs()
Definition: node.h:713
auto pathLength() const
Definition: node.h:296
T * as() const
Definition: node.h:671
bool hasErrors() const
Definition: node.h:850
bool isA_() const
Definition: node.h:662
auto children(int begin, std::optional< int > end) const
Definition: node.h:421
std::string print() const
Definition: node.cc:101
virtual Node * _clone(ASTContext *ctx) const =0
T * as()
Definition: node.h:685
Node * parent(int i=1) const
Definition: node.h:264
node::Tag nodeTag() const
Definition: node.h:245
void setChild(ASTContext *ctx, size_t idx, Node *n)
Definition: node.h:602
Node(const Node &other)
Definition: node.h:952
void clearErrors()
Definition: node.h:859
void addChild(ASTContext *ctx, Node *n)
Definition: node.h:522
void removeChild(Node *n)
Definition: node.h:556
virtual std::string _typename() const
Definition: node.h:968
T * childTryAs(unsigned int i) const
Definition: node.h:389
void addError(std::string msg, Location l, node::ErrorPriority priority, std::vector< std::string > context={})
Definition: node.h:836
virtual bool inheritScope() const
Definition: node.h:352
auto children(int begin, std::optional< int > end)
Definition: node.h:440
const auto & location() const
Definition: node.h:309
void release()
Definition: node.h:877
auto scope() const
Definition: node.h:318
const auto & children() const
Definition: node.h:364
auto getOrCreateScope()
Definition: node.h:325
virtual std::string_view branchTag() const
Definition: node.h:903
void replaceChild(ASTContext *ctx, Node *old, Node *new_)
Definition: node.cc:113
Node * child(unsigned int i) const
Definition: node.h:403
void addError(std::string msg, node::ErrorPriority priority, std::vector< std::string > context={})
Definition: node.h:812
uint64_t identity() const
Definition: node.h:361
void replaceChildren(ASTContext *ctx, const Nodes &children)
Definition: node.cc:124
const auto & meta() const
Definition: node.h:306
bool hasChild(const Node *n, bool recurse=false) const
Definition: node.h:474
virtual std::string _dump() const
Definition: node.h:982
Node(ASTContext *ctx, node::Tags node_tags, Nodes children, Meta meta)
Definition: node.h:922
void removeChildren(int begin, std::optional< int > end)
Definition: node.h:575
bool isRetained() const
Definition: node.h:884
T * child(unsigned int i) const
Definition: node.h:374
node::Set< T > childrenOfType() const
Definition: node.h:455
std::string printRaw() const
Definition: node.cc:107
std::string dump() const
Definition: node.cc:34
Node(ASTContext *ctx, node::Tags node_tags, Meta meta)
Definition: node.h:939
void clearChildren()
Definition: node.cc:131
bool hasParent() const
Definition: node.h:256
virtual node::Properties properties() const
Definition: node.h:891
virtual void dispatch(visitor::Dispatcher &v)=0
void addChildren(ASTContext *ctx, const Nodes &children)
Definition: node.h:545
bool isA() const
Definition: node.h:648
void retain()
Definition: node.h:868
Result< std::pair< Declaration *, ID > > lookupID(const ID &id, const std::string_view &what) const
Definition: node.cc:217
std::string typename_() const
Definition: node.h:358
void addError(std::string msg, const Location &l, std::vector< std::string > context={})
Definition: node.h:824
Definition: forward.h:758
Definition: node-range.h:92
void clearDocumentation()
Definition: node.h:1107
const std::optional< DocString > & documentation() const
Definition: node.h:1104
void setDocumentation(DocString doc)
Definition: node.h:1110
ID uniqueID() const
Definition: node.h:1071
node::Properties properties() const
Definition: node.h:1074
WithUniqueID(const char *prefix)
Definition: node.h:1092
Definition: visitor-dispatcher.h:9
auto transform(const C &x, F f)
Definition: util.h:419
std::string message
Definition: node.h:155
ErrorPriority priority
Definition: node.h:158
Location location
Definition: node.h:156
std::vector< std::string > context
Definition: node.h:157