1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcm/ast/CompileUnit.hpp>
  7 #include <sngcm/ast/Identifier.hpp>
  8 #include <sngcm/ast/Visitor.hpp>
  9 #include <sngcm/ast/Namespace.hpp>
 10 #include <sngcm/ast/Class.hpp>
 11 #include <soulng/util/Sha1.hpp>
 12 #include <algorithm>
 13 
 14 namespace sngcm { namespace ast {
 15 
 16 CompileUnitNode::CompileUnitNode(const Span& span_) : Node(NodeType::compileUnitNodespan_)globalNs()isSynthesizedUnit(false)
 17 {
 18 }
 19 
 20 CompileUnitNode::CompileUnitNode(const Span& span_const std::string& filePath_) :
 21     Node(NodeType::compileUnitNodespan_)filePath(filePath_)globalNs(new NamespaceNode(span_new IdentifierNode(span_U"")))isSynthesizedUnit(false)
 22 {
 23 }
 24 
 25 Node* CompileUnitNode::Clone(CloneContext& cloneContext) const
 26 {
 27     CompileUnitNode* clone = new CompileUnitNode(GetSpan()filePath);
 28     clone->globalNs.reset(static_cast<NamespaceNode*>(globalNs->Clone(cloneContext)));
 29     return clone;
 30 }
 31 
 32 void CompileUnitNode::Accept(Visitor& visitor)
 33 {
 34     visitor.Visit(*this);
 35 }
 36 
 37 void CompileUnitNode::ResetGlobalNs(NamespaceNode* ns)
 38 {
 39     globalNs.reset(ns);
 40 }
 41 
 42 void CompileUnitNode::ComputeLineStarts(const std::u32string& sourceFileContent)
 43 {
 44     int32_t index = 0;
 45     bool startOfLine = true;
 46     for (const char32_t& c : sourceFileContent)
 47     {
 48         if (startOfLine)
 49         {
 50             lineStarts.push_back(index);
 51             startOfLine = false;
 52         }
 53         if (c == U'\n')
 54         {
 55             startOfLine = true;
 56         }
 57         ++index;
 58     }
 59 }
 60 
 61 const std::string& CompileUnitNode::Id()
 62 {
 63     if (id.empty())
 64     {
 65         id = GetSha1MessageDigest(filePath);
 66     }
 67     return id;
 68 }
 69 
 70 class NamespaceCombiner public Visitor
 71 {
 72 public:
 73     void Visit(CompileUnitNode& compileUnitNode) override;
 74     void Visit(NamespaceNode& namespaceNode) override;
 75 };
 76 
 77 void NamespaceCombiner::Visit(CompileUnitNode& compileUnitNode)
 78 {
 79     compileUnitNode.GlobalNs()->Accept(*this);
 80 }
 81 
 82 void NamespaceCombiner::Visit(NamespaceNode& namespaceNode)
 83 {
 84     int n = namespaceNode.Members().Count();
 85     for (int i = 0; i < n; ++i)
 86     {
 87         namespaceNode.Members()[i]->Accept(*this);
 88     }
 89     if (n == 1 && !namespaceNode.Id()->Str().empty())
 90     {
 91         Node* node = namespaceNode.Members()[0];
 92         if (node->GetNodeType() == NodeType::namespaceNode)
 93         {
 94             std::unique_ptr<NamespaceNode> childNs(static_cast<NamespaceNode*>(namespaceNode.Members().Release(0)));
 95             namespaceNode.Id()->SetStr(namespaceNode.Id()->Str() + U"." + childNs->Id()->Str());
 96             namespaceNode.Members().Clear();
 97             namespaceNode.Members().SetContent(childNs->Members().Content());
 98             namespaceNode.Members().SetParent(&namespaceNode);
 99         }
100     }
101 }
102 
103 void CombineNamespaces(CompileUnitNode& cu)
104 {
105     NamespaceCombiner combiner;
106     cu.Accept(combiner);
107 }
108 
109 class ClassMemberArranger public Visitor
110 {
111 public:
112     void Visit(CompileUnitNode& compileUnitNode) override;
113     void Visit(NamespaceNode& namespaceNode) override;
114     void Visit(ClassNode& classNode) override;
115 };
116 
117 void ClassMemberArranger::Visit(CompileUnitNode& compileUnitNode)
118 {
119     compileUnitNode.GlobalNs()->Accept(*this);
120 }
121 
122 void ClassMemberArranger::Visit(NamespaceNode& namespaceNode)
123 {
124     int n = namespaceNode.Members().Count();
125     for (int i = 0; i < n; ++i)
126     {
127         namespaceNode.Members()[i]->Accept(*this);
128     }
129 }
130 
131 void ClassMemberArranger::Visit(ClassNode& classNode)
132 {
133     int n = classNode.Members().Count();
134     for (int i = 0; i < n; ++i)
135     {
136         classNode.Members()[i]->Accept(*this);
137     }
138     classNode.ArrangeMembers();
139 }
140 
141 void ArrangeClassMembers(CompileUnitNode& cu)
142 {
143     ClassMemberArranger arranger;
144     cu.Accept(arranger);
145 }
146 
147 class UnnamedNamespaceProcessor public Visitor
148 {
149 public:
150     UnnamedNamespaceProcessor();
151     void Visit(CompileUnitNode& compileUnitNode) override;
152     void Visit(NamespaceNode& namespaceNode) override;
153 private:
154     std::vector<NamespaceNode*> unnamedNamespaces;
155 };
156 
157 UnnamedNamespaceProcessor::UnnamedNamespaceProcessor()
158 {
159 }
160 
161 void UnnamedNamespaceProcessor::Visit(CompileUnitNode& compileUnitNode)
162 {
163     compileUnitNode.GlobalNs()->Accept(*this);
164     int index = 0;
165     for (NamespaceNode* unnamedNs : unnamedNamespaces)
166     {
167         CloneContext cloneContext;
168         IdentifierNode* unnamedNsId = static_cast<IdentifierNode*>(unnamedNs->Id()->Clone(cloneContext));
169         NamespaceImportNode* import = new NamespaceImportNode(compileUnitNode.GetSpan()unnamedNsId);
170         compileUnitNode.GlobalNs()->Members().Insert(indeximport);
171         ++index;
172     }
173 }
174 
175 void UnnamedNamespaceProcessor::Visit(NamespaceNode& namespaceNode)
176 {
177     if (namespaceNode.IsUnnamedNs())
178     {
179         unnamedNamespaces.push_back(&namespaceNode);
180     }
181     int n = namespaceNode.Members().Count();
182     for (int i = 0; i < n; ++i)
183     {
184         namespaceNode.Members()[i]->Accept(*this);
185     }
186 }
187 
188 void AddNamespaceImportsForUnnamedNamespaces(CompileUnitNode& cu)
189 {
190     UnnamedNamespaceProcessor processor;
191     cu.Accept(processor);
192 }
193 
194 } } // namespace sngcm::ast