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