1
2
3
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/Path.hpp>
12 #include <soulng/util/Sha1.hpp>
13 #include <algorithm>
14
15 namespace sngcm { namespace ast {
16
17 CompileUnitNode::CompileUnitNode(const Span& span_, const boost::uuids::uuid& moduleId_) : Node(NodeType::compileUnitNode, span_, moduleId_), globalNs(), isSynthesizedUnit(false), isProgramMainUnit(false)
18 {
19 }
20
21 CompileUnitNode::CompileUnitNode(const Span& span_, const boost::uuids::uuid& moduleId_, const std::string& filePath_) :
22 Node(NodeType::compileUnitNode, span_, moduleId_), filePath(filePath_), globalNs(new NamespaceNode(span_, moduleId_, new IdentifierNode(span_, moduleId_, U""))), isSynthesizedUnit(false), isProgramMainUnit(false)
23 {
24 }
25
26 Node* CompileUnitNode::Clone(CloneContext& cloneContext) const
27 {
28 CompileUnitNode* clone = new CompileUnitNode(GetSpan(), ModuleId(), filePath);
29 clone->globalNs.reset(static_cast<NamespaceNode*>(globalNs->Clone(cloneContext)));
30 return clone;
31 }
32
33 void CompileUnitNode::Accept(Visitor& visitor)
34 {
35 visitor.Visit(*this);
36 }
37
38 void CompileUnitNode::ResetGlobalNs(NamespaceNode* ns)
39 {
40 globalNs.reset(ns);
41 }
42
43 void CompileUnitNode::ComputeLineStarts(const std::u32string& sourceFileContent)
44 {
45 int32_t index = 0;
46 bool startOfLine = true;
47 for (const char32_t& c : sourceFileContent)
48 {
49 if (startOfLine)
50 {
51 lineStarts.push_back(index);
52 startOfLine = false;
53 }
54 if (c == U'\n')
55 {
56 startOfLine = true;
57 }
58 ++index;
59 }
60 }
61
62 int CompileUnitNode::GetColumn(const Span& span) const
63 {
64 if (span.Valid())
65 {
66 int32_t pos = span.start;
67 auto it = std::lower_bound(lineStarts.cbegin(), lineStarts.cend(), pos);
68 if (it != lineStarts.cend())
69 {
70 int32_t start = *it;
71 if (start != pos && it != lineStarts.cbegin())
72 {
73 --it;
74 start = *it;
75 }
76 int column = 1 + pos - start;
77 return column;
78 }
79 }
80 return 1;
81 }
82
83 const std::string& CompileUnitNode::Id()
84 {
85 if (id.empty())
86 {
87 std::string baseName = Path::GetFileNameWithoutExtension(filePath);
88 for (char& c : baseName)
89 {
90 if (!std::isalnum(c))
91 {
92 c = '_';
93 }
94 }
95 id = baseName + "_" + GetSha1MessageDigest(filePath);
96 }
97 return id;
98 }
99
100 class NamespaceCombiner : public Visitor
101 {
102 public:
103 void Visit(CompileUnitNode& compileUnitNode) override;
104 void Visit(NamespaceNode& namespaceNode) override;
105 };
106
107 void NamespaceCombiner::Visit(CompileUnitNode& compileUnitNode)
108 {
109 compileUnitNode.GlobalNs()->Accept(*this);
110 }
111
112 void NamespaceCombiner::Visit(NamespaceNode& namespaceNode)
113 {
114 int n = namespaceNode.Members().Count();
115 for (int i = 0; i < n; ++i)
116 {
117 namespaceNode.Members()[i]->Accept(*this);
118 }
119 if (n == 1 && !namespaceNode.Id()->Str().empty())
120 {
121 Node* node = namespaceNode.Members()[0];
122 if (node->GetNodeType() == NodeType::namespaceNode)
123 {
124 std::unique_ptr<NamespaceNode> childNs(static_cast<NamespaceNode*>(namespaceNode.Members().Release(0)));
125 namespaceNode.Id()->SetStr(namespaceNode.Id()->Str() + U"." + childNs->Id()->Str());
126 namespaceNode.Members().Clear();
127 namespaceNode.Members().SetContent(childNs->Members().Content());
128 namespaceNode.Members().SetParent(&namespaceNode);
129 }
130 }
131 }
132
133 void CombineNamespaces(CompileUnitNode& cu)
134 {
135 NamespaceCombiner combiner;
136 cu.Accept(combiner);
137 }
138
139 class ClassMemberArranger : public Visitor
140 {
141 public:
142 void Visit(CompileUnitNode& compileUnitNode) override;
143 void Visit(NamespaceNode& namespaceNode) override;
144 void Visit(ClassNode& classNode) override;
145 };
146
147 void ClassMemberArranger::Visit(CompileUnitNode& compileUnitNode)
148 {
149 compileUnitNode.GlobalNs()->Accept(*this);
150 }
151
152 void ClassMemberArranger::Visit(NamespaceNode& namespaceNode)
153 {
154 int n = namespaceNode.Members().Count();
155 for (int i = 0; i < n; ++i)
156 {
157 namespaceNode.Members()[i]->Accept(*this);
158 }
159 }
160
161 void ClassMemberArranger::Visit(ClassNode& classNode)
162 {
163 int n = classNode.Members().Count();
164 for (int i = 0; i < n; ++i)
165 {
166 classNode.Members()[i]->Accept(*this);
167 }
168 classNode.ArrangeMembers();
169 }
170
171 void ArrangeClassMembers(CompileUnitNode& cu)
172 {
173 ClassMemberArranger arranger;
174 cu.Accept(arranger);
175 }
176
177 class UnnamedNamespaceProcessor : public Visitor
178 {
179 public:
180 UnnamedNamespaceProcessor();
181 void Visit(CompileUnitNode& compileUnitNode) override;
182 void Visit(NamespaceNode& namespaceNode) override;
183 private:
184 std::vector<NamespaceNode*> unnamedNamespaces;
185 };
186
187 UnnamedNamespaceProcessor::UnnamedNamespaceProcessor()
188 {
189 }
190
191 void UnnamedNamespaceProcessor::Visit(CompileUnitNode& compileUnitNode)
192 {
193 compileUnitNode.GlobalNs()->Accept(*this);
194 int index = 0;
195 for (NamespaceNode* unnamedNs : unnamedNamespaces)
196 {
197 CloneContext cloneContext;
198 IdentifierNode* unnamedNsId = static_cast<IdentifierNode*>(unnamedNs->Id()->Clone(cloneContext));
199 NamespaceImportNode* import = new NamespaceImportNode(compileUnitNode.GetSpan(), compileUnitNode.ModuleId(), unnamedNsId);
200 compileUnitNode.GlobalNs()->Members().Insert(index, import);
201 ++index;
202 }
203 }
204
205 void UnnamedNamespaceProcessor::Visit(NamespaceNode& namespaceNode)
206 {
207 if (namespaceNode.IsUnnamedNs())
208 {
209 unnamedNamespaces.push_back(&namespaceNode);
210 }
211 int n = namespaceNode.Members().Count();
212 for (int i = 0; i < n; ++i)
213 {
214 namespaceNode.Members()[i]->Accept(*this);
215 }
216 }
217
218 void AddNamespaceImportsForUnnamedNamespaces(CompileUnitNode& cu)
219 {
220 UnnamedNamespaceProcessor processor;
221 cu.Accept(processor);
222 }
223
224 } }