1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcm/ast/Namespace.hpp>
  7 #include <sngcm/ast/Identifier.hpp>
  8 #include <sngcm/ast/Visitor.hpp>
  9 #include <sngcm/ast/Function.hpp>
 10 #include <soulng/util/Unicode.hpp>
 11 #include <soulng/util/Sha1.hpp>
 12 #include <boost/uuid/random_generator.hpp>
 13 
 14 namespace sngcm { namespace ast {
 15 
 16 using namespace soulng::unicode;
 17 using namespace soulng::util;
 18 
 19 NamespaceNode::NamespaceNode(const Span& span_) : Node(NodeType::namespaceNodespan_)id()flags()
 20 {
 21 }
 22 
 23 NamespaceNode::NamespaceNode(const Span& span_IdentifierNode* id_) : Node(NodeType::namespaceNodespan_)id(id_)flags()
 24 {
 25     if (id == nullptr)
 26     {
 27         SetUnnamedNs();
 28         Sha1 sha1;
 29         boost::uuids::uuid randomUuid = boost::uuids::random_generator()();
 30         for (uint8_t x : randomUuid)
 31         {
 32             sha1.Process(x);
 33         }
 34         id.reset(new IdentifierNode(span_U"unnamed_ns_" + ToUtf32(sha1.GetDigest())));
 35     }
 36     id->SetParent(this);
 37 }
 38 
 39 IdentifierNode* NamespaceNode::Id() const
 40 {
 41     return id.get();
 42 }
 43 
 44 Node* NamespaceNode::Clone(CloneContext& cloneContext) const
 45 {
 46     NamespaceNode* clone = nullptr;
 47     if (IsUnnamedNs())
 48     {
 49         clone = new NamespaceNode(GetSpan()nullptr);
 50     }
 51     else
 52     {
 53         clone = new NamespaceNode(GetSpan()static_cast<IdentifierNode*>(id->Clone(cloneContext)));
 54     }
 55     clone->flags = flags;
 56     int n = members.Count();
 57     for (int i = 0; i < n; ++i)
 58     {
 59         Node* member = members[i];
 60         if (cloneContext.MakeTestUnits() && member->GetNodeType() == NodeType::functionNode&&(  static_cast<FunctionNode*>(member)->GetSpecifiers() & Specifiers::unit_test_) != Specifiers::none)
 61         {
 62             FunctionNode* unitTestFunction = static_cast<FunctionNode*>(member->Clone(cloneContext));
 63             unitTestFunction->SetParent(const_cast<NamespaceNode*>(this));
 64             cloneContext.AddUnitTestFunction(unitTestFunction);
 65         }
 66         else
 67         {
 68             clone->AddMember(member->Clone(cloneContext));
 69         }
 70     }
 71     return clone;
 72 }
 73 
 74 void NamespaceNode::Accept(Visitor& visitor)
 75 {
 76     visitor.Visit(*this);
 77 }
 78 
 79 void NamespaceNode::Write(AstWriter& writer)
 80 {
 81     Node::Write(writer);
 82     writer.Write(id.get());
 83     writer.GetBinaryWriter().Write(static_cast<int8_t>(flags));
 84     members.Write(writer);
 85 }
 86 
 87 void NamespaceNode::Read(AstReader& reader)
 88 {
 89     Node::Read(reader);
 90     id.reset(reader.ReadIdentifierNode());
 91     id->SetParent(this);
 92     flags = static_cast<NsFlags>(reader.GetBinaryReader().ReadSByte());
 93     members.Read(reader);
 94     members.SetParent(this);
 95 }
 96 
 97 void NamespaceNode::AddMember(Node* member)
 98 {
 99     member->SetParent(this);
100     members.Add(member);
101     if (member->GetNodeType() == NodeType::namespaceNode)
102     {
103         NamespaceNode* ns = static_cast<NamespaceNode*>(member);
104         if (ns->IsUnnamedNs() || ns->HasUnnamedNs())
105         {
106             SetHasUnnamedNs();
107         }
108     }
109 }
110 
111 AliasNode::AliasNode(const Span& span_) : Node(NodeType::aliasNodespan_)id()qid()
112 {
113 }
114 
115 AliasNode::AliasNode(const Span& span_IdentifierNode* id_IdentifierNode* qid_) : Node(NodeType::aliasNodespan_)id(id_)qid(qid_)
116 {
117     id->SetParent(this);
118     qid->SetParent(this);
119 }
120 
121 Node* AliasNode::Clone(CloneContext& cloneContext) const
122 {
123     return new AliasNode(GetSpan()static_cast<IdentifierNode*>(id->Clone(cloneContext))static_cast<IdentifierNode*>(qid->Clone(cloneContext)));
124 }
125 
126 void AliasNode::Accept(Visitor& visitor)
127 {
128     visitor.Visit(*this);
129 }
130 
131 void AliasNode::Write(AstWriter& writer)
132 {
133     Node::Write(writer);
134     writer.Write(id.get());
135     writer.Write(qid.get());
136 }
137 
138 void AliasNode::Read(AstReader& reader)
139 {
140     Node::Read(reader);
141     id.reset(reader.ReadIdentifierNode());
142     id->SetParent(this);
143     qid.reset(reader.ReadIdentifierNode());
144     qid->SetParent(this);
145 }
146 
147 IdentifierNode* AliasNode::Id() const
148 {
149     return id.get();
150 }
151 
152 IdentifierNode* AliasNode::Qid() const
153 {
154     return qid.get();
155 }
156 
157 NamespaceImportNode::NamespaceImportNode(const Span& span_) : Node(NodeType::namespaceImportNodespan_)ns()
158 {
159 }
160 
161 NamespaceImportNode::NamespaceImportNode(const Span& span_IdentifierNode* ns_) : Node(NodeType::namespaceImportNodespan_)ns(ns_)
162 {
163     ns->SetParent(this);
164 }
165 
166 Node* NamespaceImportNode::Clone(CloneContext& cloneContext) const
167 {
168     return new NamespaceImportNode(GetSpan()static_cast<IdentifierNode*>(ns->Clone(cloneContext)));
169 }
170 
171 void NamespaceImportNode::Accept(Visitor& visitor)
172 {
173     visitor.Visit(*this);
174 }
175 
176 void NamespaceImportNode::Write(AstWriter& writer)
177 {
178     Node::Write(writer);
179     writer.Write(ns.get());
180 }
181 
182 void NamespaceImportNode::Read(AstReader& reader)
183 {
184     Node::Read(reader);
185     ns.reset(reader.ReadIdentifierNode());
186     ns->SetParent(this);
187 }
188 
189 IdentifierNode* NamespaceImportNode::Ns() const
190 {
191     return ns.get();
192 }
193 
194 } } // namespace sngcm::ast