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/Sha1.hpp>
12 #include <algorithm>
13
14 namespace sngcm { namespace ast {
15
16 CompileUnitNode::CompileUnitNode(const Span& span_) : Node(NodeType::compileUnitNode, span_), globalNs(), isSynthesizedUnit(false)
17 {
18 }
19
20 CompileUnitNode::CompileUnitNode(const Span& span_, const std::string& filePath_) :
21 Node(NodeType::compileUnitNode, span_), 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(index, import);
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 } }