1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  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::constantSymbolspan_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(readerthistypeId0);
 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* typeSymbolint 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& emitterbool 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(arrayObjectGlobalarrayValue->IrValue(emitter));
243     }
244     return irArrayObject;
245 }
246 
247 void* ConstantSymbol::StructureIrObject(Emitter& emitterbool 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(structureObjectGlobalstructuredValue->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 } } // namespace cmajor::symbols