1
2
3
4
5
6 #include <cmajor/symbols/ConstantSymbol.hpp>
7 #include <cmajor/symbols/TypeSymbol.hpp>
8 #include <cmajor/symbols/SymbolTable.hpp>
9 #include <cmajor/symbols/SymbolWriter.hpp>
10 #include <cmajor/symbols/SymbolReader.hpp>
11 #include <cmajor/symbols/Exception.hpp>
12 #include <cmajor/symbols/SymbolCollector.hpp>
13 #include <cmajor/symbols/Module.hpp>
14 #include <cmajor/ir/Emitter.hpp>
15 #include <soulng/util/Unicode.hpp>
16
17 namespace cmajor { namespace symbols {
18
19 using namespace soulng::unicode;
20
21 ConstantSymbol::ConstantSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
22 Symbol(SymbolType::constantSymbol, span_, sourceModuleId_, name_), type(), evaluating(false), sizeOfValue(0), valuePos(0)
23 {
24 }
25
26 void ConstantSymbol::Write(SymbolWriter& writer)
27 {
28 Symbol::Write(writer);
29 writer.GetBinaryWriter().Write(type->TypeId());
30 bool hasComplexValue = value->IsComplexValue();
31 writer.GetBinaryWriter().Write(hasComplexValue);
32 if (hasComplexValue)
33 {
34 uint32_t sizePos = writer.GetBinaryWriter().Pos();
35 uint32_t sizeOfValue = 0;
36 writer.GetBinaryWriter().Write(sizeOfValue);
37 uint32_t startPos = writer.GetBinaryWriter().Pos();
38 value->Write(writer.GetBinaryWriter());
39 uint32_t endPos = writer.GetBinaryWriter().Pos();
40 sizeOfValue = endPos - startPos;
41 writer.GetBinaryWriter().Seek(sizePos);
42 writer.GetBinaryWriter().Write(sizeOfValue);
43 writer.GetBinaryWriter().Seek(endPos);
44 }
45 else
46 {
47 WriteValue(value.get(), writer.GetBinaryWriter());
48 }
49 writer.GetBinaryWriter().Write(strValue);
50 }
51
52 void ConstantSymbol::Read(SymbolReader& reader)
53 {
54 Symbol::Read(reader);
55 boost::uuids::uuid typeId;
56 reader.GetBinaryReader().ReadUuid(typeId);
57 reader.GetSymbolTable()->EmplaceTypeRequest(reader, this, typeId, 0);
58 bool hasComplexValue = reader.GetBinaryReader().ReadBool();
59 if (hasComplexValue)
60 {
61 sizeOfValue = reader.GetBinaryReader().ReadUInt();
62 valuePos = reader.GetBinaryReader().Pos();
63 reader.GetBinaryReader().Skip(sizeOfValue);
64 filePathReadFrom = reader.GetBinaryReader().FileName();
65 }
66 else
67 {
68 value = ReadValue(reader.GetBinaryReader(), GetSpan(), SourceModuleId());
69 }
70 strValue = reader.GetBinaryReader().ReadUtf32String();
71 }
72
73 Value* ConstantSymbol::GetValue()
74 {
75 if (!value)
76 {
77 if (filePathReadFrom.empty())
78 {
79 throw Exception("internal error: could not read value: value file name not set", GetSpan(), SourceModuleId());
80 }
81 BinaryReader reader(filePathReadFrom);
82 reader.Skip(valuePos);
83 value.reset(type->MakeValue());
84 if (!value)
85 {
86 throw Exception("internal error: could not read value because could not create value of type '" + ToUtf8(type->FullName()) + "'", GetSpan(), SourceModuleId());
87 }
88 value->Read(reader);
89 }
90 return value.get();
91 }
92
93 void ConstantSymbol::EmplaceType(TypeSymbol* typeSymbol, int index)
94 {
95 Assert(index == 0, "invalid emplace type index");
96 type = typeSymbol;
97 }
98
99 void ConstantSymbol::Accept(SymbolCollector* collector)
100 {
101 if (IsProject() && Access() == SymbolAccess::public_)
102 {
103 collector->AddConstant(this);
104 }
105 }
106
107 void ConstantSymbol::Dump(CodeFormatter& formatter)
108 {
109 formatter.WriteLine(ToUtf8(Name()));
110 formatter.WriteLine("full name: " + ToUtf8(FullNameWithSpecifiers()));
111 formatter.WriteLine("mangled name: " + ToUtf8(MangledName()));
112 formatter.WriteLine("type: " + ToUtf8(type->FullName()));
113 formatter.WriteLine("value: " + value->ToString());
114 }
115
116 void ConstantSymbol::SetSpecifiers(Specifiers specifiers)
117 {
118 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
119 SetAccess(accessSpecifiers);
120 if ((specifiers & Specifiers::static_) != Specifiers::none)
121 {
122 throw Exception("constant cannot be static", GetSpan(), SourceModuleId());
123 }
124 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
125 {
126 throw Exception("constant cannot be virtual", GetSpan(), SourceModuleId());
127 }
128 if ((specifiers & Specifiers::override_) != Specifiers::none)
129 {
130 throw Exception("constant cannot be override", GetSpan(), SourceModuleId());
131 }
132 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
133 {
134 throw Exception("constant cannot be abstract", GetSpan(), SourceModuleId());
135 }
136 if ((specifiers & Specifiers::inline_) != Specifiers::none)
137 {
138 throw Exception("constant cannot be inline", GetSpan(), SourceModuleId());
139 }
140 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
141 {
142 throw Exception("constant cannot be explicit", GetSpan(), SourceModuleId());
143 }
144 if ((specifiers & Specifiers::external_) != Specifiers::none)
145 {
146 throw Exception("constant cannot be external", GetSpan(), SourceModuleId());
147 }
148 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
149 {
150 throw Exception("constant cannot be suppressed", GetSpan(), SourceModuleId());
151 }
152 if ((specifiers & Specifiers::default_) != Specifiers::none)
153 {
154 throw Exception("constant cannot be default", GetSpan(), SourceModuleId());
155 }
156 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
157 {
158 throw Exception("constant cannot be constexpr", GetSpan(), SourceModuleId());
159 }
160 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
161 {
162 throw Exception("constant cannot be cdecl", GetSpan(), SourceModuleId());
163 }
164 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
165 {
166 throw Exception("constant cannot be nothrow", GetSpan(), SourceModuleId());
167 }
168 if ((specifiers & Specifiers::throw_) != Specifiers::none)
169 {
170 throw Exception("constant cannot be throw", GetSpan(), SourceModuleId());
171 }
172 if ((specifiers & Specifiers::new_) != Specifiers::none)
173 {
174 throw Exception("constant cannot be new", GetSpan(), SourceModuleId());
175 }
176 if ((specifiers & Specifiers::const_) != Specifiers::none)
177 {
178 throw Exception("constant cannot be const", GetSpan(), SourceModuleId());
179 }
180 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
181 {
182 throw Exception("constant cannot be unit_test", GetSpan(), SourceModuleId());
183 }
184 }
185
186 void ConstantSymbol::ComputeMangledName()
187 {
188 Symbol::ComputeMangledName();
189 }
190
191
192 std::string ConstantSymbol::Syntax() const
193 {
194 std::string syntax = GetSpecifierStr();
195 if (!syntax.empty())
196 {
197 syntax.append(1, ' ');
198 }
199 syntax.append("const ");
200 syntax.append(ToUtf8(GetType()->DocName()));
201 syntax.append(1, ' ');
202 syntax.append(ToUtf8(DocName()));
203 if (value)
204 {
205 syntax.append(" = ");
206 std::string valueStr = value->ToString();
207 if (GetType()->IsUnsignedType())
208 {
209 valueStr.append(1, 'u');
210 }
211 syntax.append(valueStr);
212 }
213 syntax.append(1, ';');
214 return syntax;
215 }
216
217 void ConstantSymbol::SetValue(Value* value_)
218 {
219 value.reset(value_);
220 }
221
222 void* ConstantSymbol::ArrayIrObject(Emitter& emitter, bool create)
223 {
224 if (!type->IsArrayType())
225 {
226 throw Exception("internal error: array object expected", GetSpan(), SourceModuleId());
227 }
228 if (!value)
229 {
230 throw Exception("internal error: array value missing", GetSpan(), SourceModuleId());
231 }
232 if (value->GetValueType() != ValueType::arrayValue)
233 {
234 throw Exception("internal error: array value expected", GetSpan(), SourceModuleId());
235 }
236 ArrayValue* arrayValue = static_cast<ArrayValue*>(value.get());
237 void* irArrayType = type->IrType(emitter);
238 void* irArrayObject = emitter.GetOrInsertGlobal(ToUtf8(MangledName()), irArrayType);
239 if (create)
240 {
241 void* arrayObjectGlobal = irArrayObject;
242 emitter.SetInitializer(arrayObjectGlobal, arrayValue->IrValue(emitter));
243 }
244 return irArrayObject;
245 }
246
247 void* ConstantSymbol::StructureIrObject(Emitter& emitter, bool create)
248 {
249 if (!type->IsClassTypeSymbol())
250 {
251 throw Exception("internal error: class type object expected", GetSpan(), SourceModuleId());
252 }
253 if (!value)
254 {
255 throw Exception("internal error: structured value missing", GetSpan(), SourceModuleId());
256 }
257 if (value->GetValueType() != ValueType::structuredValue)
258 {
259 throw Exception("internal error: structured value expected", GetSpan(), SourceModuleId());
260 }
261 StructuredValue* structuredValue = static_cast<StructuredValue*>(value.get());
262 void* irStructureType = type->IrType(emitter);
263 void* irStructureObject = emitter.GetOrInsertGlobal(ToUtf8(MangledName()), irStructureType);
264 if (create)
265 {
266 void* structureObjectGlobal = irStructureObject;
267 emitter.SetInitializer(structureObjectGlobal, structuredValue->IrValue(emitter));
268 }
269 return irStructureObject;
270 }
271
272 void ConstantSymbol::Check()
273 {
274 Symbol::Check();
275 if (!type)
276 {
277 throw SymbolCheckException("constant symbol has no type", GetSpan(), SourceModuleId());
278 }
279 }
280
281 std::string ConstantSymbol::GetSymbolHelp() const
282 {
283 std::string help = "(";
284 help.append(GetSymbolCategoryDescription()).append(") ");
285 help.append(ToUtf8(GetType()->FullName())).append(" ").append(ToUtf8(FullName()));
286 return help;
287 }
288
289 } }