1
2
3
4
5
6 #include <sngcm/ast/Enumeration.hpp>
7 #include <sngcm/ast/Identifier.hpp>
8 #include <sngcm/ast/Visitor.hpp>
9 #include <sngcm/ast/AstWriter.hpp>
10 #include <sngcm/ast/AstReader.hpp>
11 #include <sngcm/ast/Literal.hpp>
12 #include <sngcm/ast/Expression.hpp>
13
14 namespace sngcm { namespace ast {
15
16 EnumTypeNode::EnumTypeNode(const Span& span_, const boost::uuids::uuid& moduleId_) : Node(NodeType::enumTypeNode, span_, moduleId_)
17 {
18 }
19
20 EnumTypeNode::EnumTypeNode(const Span& span_, const boost::uuids::uuid& moduleId_, Specifiers specifiers_, IdentifierNode* id_) :
21 Node(NodeType::enumTypeNode, span_, moduleId_), specifiers(specifiers_), id(id_)
22 {
23 id->SetParent(this);
24 }
25
26 Node* EnumTypeNode::Clone(CloneContext& cloneContext) const
27 {
28 EnumTypeNode* clone = new EnumTypeNode(GetSpan(), ModuleId(), specifiers, static_cast<IdentifierNode*>(id->Clone(cloneContext)));
29 int n = constants.Count();
30 for (int i = 0; i < n; ++i)
31 {
32 clone->AddConstant(static_cast<EnumConstantNode*>(constants[i]->Clone(cloneContext)));
33 }
34 clone->SetBeginBraceSpan(beginBraceSpan);
35 clone->SetEndBraceSpan(endBraceSpan);
36 return clone;
37 }
38
39 void EnumTypeNode::Accept(Visitor& visitor)
40 {
41 visitor.Visit(*this);
42 }
43
44 void EnumTypeNode::Write(AstWriter& writer)
45 {
46 Node::Write(writer);
47 writer.Write(specifiers);
48 writer.Write(id.get());
49 bool hasUnderlyingType = underlyingType != nullptr;
50 writer.GetBinaryWriter().Write(hasUnderlyingType);
51 if (hasUnderlyingType)
52 {
53 writer.Write(underlyingType.get());
54 }
55 constants.Write(writer);
56 bool convertExternal = ModuleId() == writer.SpanConversionModuleId();
57 writer.Write(beginBraceSpan, convertExternal);
58 writer.Write(endBraceSpan, convertExternal);
59 }
60
61 void EnumTypeNode::Read(AstReader& reader)
62 {
63 Node::Read(reader);
64 specifiers = reader.ReadSpecifiers();
65 id.reset(reader.ReadIdentifierNode());
66 bool hasUnderlyingType = reader.GetBinaryReader().ReadBool();
67 if (hasUnderlyingType)
68 {
69 underlyingType.reset(reader.ReadNode());
70 }
71 constants.Read(reader);
72 constants.SetParent(this);
73 beginBraceSpan = reader.ReadSpan();
74 endBraceSpan = reader.ReadSpan();
75 }
76 void EnumTypeNode::AddConstant(EnumConstantNode* constant)
77 {
78 constant->SetParent(this);
79 constants.Add(constant);
80 }
81
82 EnumConstantNode* EnumTypeNode::GetLastConstant() const
83 {
84 int n = constants.Count();
85 if (n > 0)
86 {
87 return constants[n - 1];
88 }
89 return nullptr;
90 }
91
92 void EnumTypeNode::SetUnderlyingType(Node* underlyingType_)
93 {
94 underlyingType.reset(underlyingType_);
95 underlyingType->SetParent(this);
96 }
97
98 EnumConstantNode::EnumConstantNode(const Span& span_, const boost::uuids::uuid& moduleId_) :
99 Node(NodeType::enumConstantNode, span_, moduleId_), hasValue(false)
100 {
101 }
102
103 EnumConstantNode::EnumConstantNode(const Span& span_, const boost::uuids::uuid& moduleId_, IdentifierNode* id_, Node* value_) :
104 Node(NodeType::enumConstantNode, span_, moduleId_), id(id_), value(value_), hasValue(false)
105 {
106 id->SetParent(this);
107 if (value)
108 {
109 value->SetParent(this);
110 }
111 }
112
113 Node* EnumConstantNode::Clone(CloneContext& cloneContext) const
114 {
115 EnumConstantNode* clone = new EnumConstantNode(GetSpan(), ModuleId(), static_cast<IdentifierNode*>(id->Clone(cloneContext)), value->Clone(cloneContext));
116 if (hasValue)
117 {
118 clone->SetHasValue();
119 }
120 return clone;
121 }
122
123 void EnumConstantNode::Accept(Visitor& visitor)
124 {
125 visitor.Visit(*this);
126 }
127
128 void EnumConstantNode::Write(AstWriter& writer)
129 {
130 Node::Write(writer);
131 writer.Write(id.get());
132 writer.Write(value.get());
133 writer.GetBinaryWriter().Write(hasValue);
134 writer.GetBinaryWriter().Write(strValue);
135 }
136
137 void EnumConstantNode::Read(AstReader& reader)
138 {
139 Node::Read(reader);
140 id.reset(reader.ReadIdentifierNode());
141 id->SetParent(this);
142 value.reset(reader.ReadNode());
143 value->SetParent(this);
144 hasValue = reader.GetBinaryReader().ReadBool();
145 strValue = reader.GetBinaryReader().ReadUtf32String();
146 }
147
148 Node* MakeNextEnumConstantValue(const Span& span, const boost::uuids::uuid& moduleId, EnumTypeNode* enumType)
149 {
150 EnumConstantNode* lastConstant = enumType->GetLastConstant();
151 if (lastConstant)
152 {
153 Node* lastValue = lastConstant->GetValue();
154 if (lastValue)
155 {
156 CloneContext cloneContext;
157 Node* clonedValue = lastValue->Clone(cloneContext);
158 if (enumType->GetUnderlyingType())
159 {
160 if (enumType->GetUnderlyingType()->IsUnsignedTypeNode())
161 {
162 return new AddNode(span, moduleId, clonedValue, new ByteLiteralNode(span, moduleId, 1u));
163 }
164 }
165 return new AddNode(span, moduleId, clonedValue, new SByteLiteralNode(span, moduleId, 1));
166 }
167 else
168 {
169 throw std::runtime_error("last constant returned null value");
170 }
171 }
172 else
173 {
174 if (enumType->GetUnderlyingType())
175 {
176 if (enumType->GetUnderlyingType()->IsUnsignedTypeNode())
177 {
178 return new ByteLiteralNode(span, moduleId, 0u);
179 }
180 }
181 return new SByteLiteralNode(span, moduleId, 0);
182 }
183 }
184
185 } }