1
2
3
4
5
6 #include <cmajor/binder/JsonAttributeProcessor.hpp>
7 #include <cmajor/binder/StatementBinder.hpp>
8 #include <cmajor/binder/TypeBinder.hpp>
9 #include <cmajor/binder/BoundNode.hpp>
10 #include <cmajor/binder/BoundStatement.hpp>
11 #include <cmajor/binder/BoundFunction.hpp>
12 #include <cmajor/binder/BoundClass.hpp>
13 #include <cmajor/binder/TypeResolver.hpp>
14 #include <cmajor/symbols/Exception.hpp>
15 #include <cmajor/symbols/ClassTypeSymbol.hpp>
16 #include <cmajor/symbols/SymbolTable.hpp>
17 #include <cmajor/symbols/Warning.hpp>
18 #include <cmajor/symbols/SymbolCreatorVisitor.hpp>
19 #include <cmajor/symbols/Module.hpp>
20 #include <sngcm/ast/Expression.hpp>
21 #include <sngcm/ast/Identifier.hpp>
22 #include <sngcm/ast/Literal.hpp>
23 #include <soulng/util/Unicode.hpp>
24
25 namespace cmajor { namespace binder {
26
27 using namespace soulng::unicode;
28 using namespace cmajor::symbols;
29
30 JsonAttributeProcessor::JsonAttributeProcessor(Module* module_) : AttributeProcessor(U"json"), module(module_)
31 {
32 }
33
34 void JsonAttributeProcessor::TypeCheck(AttributeNode* attribute, Symbol* symbol)
35 {
36 switch (symbol->GetSymbolType())
37 {
38 case SymbolType::classTypeSymbol: case SymbolType::classTemplateSpecializationSymbol: case SymbolType::memberVariableSymbol:
39 {
40 if (attribute->Value() == U"true" || attribute->Value() == U"false")
41 {
42 if (symbol->IsClassTypeSymbol())
43 {
44 ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(symbol);
45 ClassTypeSymbol* baseClass = classTypeSymbol->BaseClass();
46 if (baseClass)
47 {
48 bool baseClassHasJsonAttribute = false;
49 AttributesNode* baseClassAttributes = baseClass->GetAttributes();
50 if (baseClassAttributes)
51 {
52 AttributeNode* jsonAttribute = baseClassAttributes->GetAttribute(U"json");
53 if (jsonAttribute)
54 {
55 baseClassHasJsonAttribute = true;
56 }
57 }
58 if (!baseClassHasJsonAttribute)
59 {
60 Warning warning(module->GetCurrentProjectName(), "base class '" + ToUtf8(baseClass->FullName()) + "' of json-attributed class '" +
61 ToUtf8(classTypeSymbol->FullName()) + "' does not explicitly declare 'json' attribute value to \"true\" or \"false\"");
62 warning.SetDefined(classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
63 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
64 references.push_back(std::make_pair(baseClass->GetSpan(), baseClass->SourceModuleId()));
65 warning.SetReferences(references);
66 module->WarningCollection().AddWarning(warning);
67 }
68 }
69 }
70 return;
71 }
72 else
73 {
74 throw Exception("unknown attribute value '" + ToUtf8(attribute->Value()) + "' for attribute '" + ToUtf8(attribute->Name()) + "'", attribute->GetSpan(), attribute->ModuleId());
75 }
76 }
77 }
78 AttributeProcessor::TypeCheck(attribute, symbol);
79 }
80
81 void JsonAttributeProcessor::GenerateSymbols(AttributeNode* attribute, Symbol* symbol, BoundCompileUnit& boundCompileUnit, ContainerScope* containerScope)
82 {
83 if (symbol->IsClassTypeSymbol())
84 {
85 ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(symbol);
86 if (attribute->Value() == U"true")
87 {
88 GenerateMemberVariableJsonFieldNames(classTypeSymbol);
89 std::map<std::u32string, AttributeNode*> memberVariableFieldNames;
90 CheckMemberVariableJsonFieldNames(classTypeSymbol, memberVariableFieldNames);
91 GenerateJsonCreatorFunctionSymbol(attribute, classTypeSymbol);
92 GenerateJsonConstructorSymbol(attribute, classTypeSymbol);
93 GenerateToJsonJsonObjectSymbol(attribute, classTypeSymbol);
94 GenerateToJsonSymbol(attribute, classTypeSymbol, boundCompileUnit, containerScope);
95 }
96 }
97 }
98
99 void JsonAttributeProcessor::CheckMemberVariableJsonFieldNames(ClassTypeSymbol* classTypeSymbol, std::std::map<std::u32string, AttributeNode*>&memberVariableFieldNames)
100 {
101 if (classTypeSymbol->BaseClass())
102 {
103 AttributesNode* attributes = classTypeSymbol->BaseClass()->GetAttributes();
104 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
105 if (jsonAttribute && jsonAttribute->Value() != U"false")
106 {
107 CheckMemberVariableJsonFieldNames(classTypeSymbol->BaseClass(), memberVariableFieldNames);
108 }
109 }
110 for (MemberVariableSymbol* memberVariableSymbol : classTypeSymbol->MemberVariables())
111 {
112 AttributesNode* attributes = memberVariableSymbol->GetAttributes();
113 if (attributes)
114 {
115 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
116 if (jsonAttribute)
117 {
118 if (jsonAttribute->Value() == U"false")
119 {
120 continue;
121 }
122 }
123 AttributeNode* jsonFieldNameAttribute = attributes->GetAttribute(U"jsonFieldName");
124 if (jsonFieldNameAttribute)
125 {
126 auto it = memberVariableFieldNames.find(jsonFieldNameAttribute->Value());
127 if (it != memberVariableFieldNames.cend())
128 {
129 AttributeNode* prev = it->second;
130 throw Exception("error in JSON field name generation: 'jsonFieldName' attribute not unique among member variable names of the current class and its base classes",
131 jsonFieldNameAttribute->GetSpan(), jsonFieldNameAttribute->ModuleId(), prev->GetSpan(), prev->ModuleId());
132 }
133 memberVariableFieldNames[jsonFieldNameAttribute->Value()] = jsonFieldNameAttribute;
134 }
135 else
136 {
137 throw Exception("internal error in JSON field name generation: 'jsonFieldName' attribute not found", memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId());
138 }
139 }
140 else
141 {
142 throw Exception("internal error in JSON field name generation: attributes not found", memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId());
143 }
144 }
145 }
146
147 void JsonAttributeProcessor::GenerateMemberVariableJsonFieldNames(ClassTypeSymbol* classTypeSymbol)
148 {
149 for (MemberVariableSymbol* memberVariableSymbol : classTypeSymbol->MemberVariables())
150 {
151 bool hasJsonFieldAttribute = false;
152 AttributesNode* attributes = memberVariableSymbol->GetAttributes();
153 if (attributes)
154 {
155 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
156 if (jsonAttribute)
157 {
158 if (jsonAttribute->Value() == U"false")
159 {
160 continue;
161 }
162 }
163 AttributeNode* jsonFieldNameAttribute = attributes->GetAttribute(U"jsonFieldName");
164 if (jsonFieldNameAttribute)
165 {
166 hasJsonFieldAttribute = true;
167 }
168 }
169 else
170 {
171 memberVariableSymbol->SetAttributes(std::unique_ptr<AttributesNode>(new AttributesNode(classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId())));
172 attributes = memberVariableSymbol->GetAttributes();
173 }
174 if (!hasJsonFieldAttribute)
175 {
176 attributes->AddAttribute(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), U"jsonFieldName", memberVariableSymbol->Name());
177 }
178 }
179 }
180
181 void JsonAttributeProcessor::GenerateJsonCreatorFunctionSymbol(AttributeNode* attribute, ClassTypeSymbol* classTypeSymbol)
182 {
183 MemberFunctionSymbol* jsonCreatorFunctionSymbol = new MemberFunctionSymbol(attribute->GetSpan(), attribute->ModuleId(), U"Create");
184 jsonCreatorFunctionSymbol->SetGroupName(U"Create");
185 jsonCreatorFunctionSymbol->SetModule(module);
186 module->GetSymbolTable().SetFunctionIdFor(jsonCreatorFunctionSymbol);
187 jsonCreatorFunctionSymbol->SetAccess(SymbolAccess::public_);
188 jsonCreatorFunctionSymbol->SetStatic();
189 Symbol* jsonValue = classTypeSymbol->GetModule()->GetSymbolTable().GlobalNs().GetContainerScope()->Lookup(U"System.Json.JsonValue");
190 if (!jsonValue || jsonValue->GetSymbolType() != SymbolType::classGroupTypeSymbol)
191 {
192 throw Exception("System.Json.JsonValue class not found from the symbol table", attribute->GetSpan(), attribute->ModuleId(), classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
193 }
194 ClassGroupTypeSymbol* jsonValueGroup = static_cast<ClassGroupTypeSymbol*>(jsonValue);
195 ClassTypeSymbol* jsonValueClass = jsonValueGroup->GetClass(0);
196 if (!jsonValueClass)
197 {
198 throw Exception("System.Json.JsonValue class not found from the symbol table", attribute->GetSpan(), attribute->ModuleId(), classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
199 }
200 ParameterSymbol* jsonValueParam = new ParameterSymbol(attribute->GetSpan(), attribute->ModuleId(), U"@value");
201 jsonValueParam->SetType(jsonValueClass->AddPointer(attribute->GetSpan(), attribute->ModuleId()));
202 jsonCreatorFunctionSymbol->AddMember(jsonValueParam);
203 jsonCreatorFunctionSymbol->SetReturnType(module->GetSymbolTable().GetTypeByName(U"void")->AddPointer(attribute->GetSpan(), attribute->ModuleId()));
204 classTypeSymbol->AddMember(jsonCreatorFunctionSymbol);
205 jsonCreatorFunctionSymbol->ComputeName();
206 jsonCreatorMap[classTypeSymbol] = jsonCreatorFunctionSymbol;
207 }
208
209 void JsonAttributeProcessor::GenerateJsonConstructorSymbol(AttributeNode* attribute, ClassTypeSymbol* classTypeSymbol)
210 {
211 ConstructorSymbol* jsonConstructorSymbol = new ConstructorSymbol(attribute->GetSpan(), attribute->ModuleId(), U"@constructor");
212 jsonConstructorSymbol->SetModule(module);
213 module->GetSymbolTable().SetFunctionIdFor(jsonConstructorSymbol);
214 ParameterSymbol* thisParam = new ParameterSymbol(attribute->GetSpan(), attribute->ModuleId(), U"this");
215 thisParam->SetType(classTypeSymbol->AddPointer(attribute->GetSpan(), attribute->ModuleId()));
216 ParameterSymbol* jsonValueParam = new ParameterSymbol(attribute->GetSpan(), attribute->ModuleId(), U"@value");
217 Symbol* jsonValue = classTypeSymbol->GetModule()->GetSymbolTable().GlobalNs().GetContainerScope()->Lookup(U"System.Json.JsonValue");
218 if (!jsonValue || jsonValue->GetSymbolType() != SymbolType::classGroupTypeSymbol)
219 {
220 throw Exception("System.Json.JsonValue class not found from the symbol table", attribute->GetSpan(), attribute->ModuleId(), classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
221 }
222 ClassGroupTypeSymbol* jsonValueGroup = static_cast<ClassGroupTypeSymbol*>(jsonValue);
223 ClassTypeSymbol* jsonValueClass = jsonValueGroup->GetClass(0);
224 if (!jsonValueClass)
225 {
226 throw Exception("System.Json.JsonValue class not found from the symbol table", attribute->GetSpan(), attribute->ModuleId(), classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
227 }
228 jsonValueParam->SetType(jsonValueClass->AddPointer(attribute->GetSpan(), attribute->ModuleId()));
229 jsonConstructorSymbol->SetAccess(SymbolAccess::public_);
230 jsonConstructorSymbol->SetExplicit();
231 jsonConstructorSymbol->AddMember(thisParam);
232 jsonConstructorSymbol->AddMember(jsonValueParam);
233 classTypeSymbol->AddMember(jsonConstructorSymbol);
234 jsonConstructorSymbol->ComputeName();
235 jsonConstructorMap[classTypeSymbol] = jsonConstructorSymbol;
236 }
237
238 void JsonAttributeProcessor::GenerateToJsonJsonObjectSymbol(AttributeNode* attribute, ClassTypeSymbol* classTypeSymbol)
239 {
240 MemberFunctionSymbol* toJsonJsonObjectMemberFunctionSymbol = new MemberFunctionSymbol(attribute->GetSpan(), attribute->ModuleId(), U"ToJson");
241 toJsonJsonObjectMemberFunctionSymbol->SetModule(module);
242 toJsonJsonObjectMemberFunctionSymbol->SetGroupName(U"ToJson");
243 ClassTypeSymbol* baseClass = classTypeSymbol->BaseClass();
244 bool jsonBase = false;
245 if (baseClass)
246 {
247 AttributesNode* attributes = baseClass->GetAttributes();
248 if (attributes)
249 {
250 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
251 if (jsonAttribute)
252 {
253 if (jsonAttribute->Value() == U"true")
254 {
255 jsonBase = true;
256 }
257 }
258 }
259 }
260 if (!jsonBase)
261 {
262 toJsonJsonObjectMemberFunctionSymbol->SetVirtual();
263 }
264 else
265 {
266 toJsonJsonObjectMemberFunctionSymbol->SetOverride();
267 }
268 GetRootModuleForCurrentThread()->GetSymbolTable().SetFunctionIdFor(toJsonJsonObjectMemberFunctionSymbol);
269 ParameterSymbol* thisParam = new ParameterSymbol(attribute->GetSpan(), attribute->ModuleId(), U"this");
270 thisParam->SetType(classTypeSymbol->AddPointer(attribute->GetSpan(), attribute->ModuleId()));
271 ParameterSymbol* jsonObjectParam = new ParameterSymbol(attribute->GetSpan(), attribute->ModuleId(), U"@object");
272 Symbol* jsonObject = GetRootModuleForCurrentThread()->GetSymbolTable().GlobalNs().GetContainerScope()->Lookup(U"System.Json.JsonObject");
273 if (!jsonObject || jsonObject->GetSymbolType() != SymbolType::classGroupTypeSymbol)
274 {
275 throw Exception("System.Json.JsonObject class not found from the symbol table", attribute->GetSpan(), attribute->ModuleId(), classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
276 }
277 ClassGroupTypeSymbol* jsonObjectGroup = static_cast<ClassGroupTypeSymbol*>(jsonObject);
278 ClassTypeSymbol* jsonObjectClass = jsonObjectGroup->GetClass(0);
279 if (!jsonObjectClass)
280 {
281 throw Exception("System.Json.JsonObject class not found from the symbol table", attribute->GetSpan(), attribute->ModuleId(), classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
282 }
283 jsonObjectParam->SetType(jsonObjectClass->AddPointer(attribute->GetSpan(), attribute->ModuleId()));
284 toJsonJsonObjectMemberFunctionSymbol->SetReturnType(module->GetSymbolTable().GetTypeByName(U"void"));
285 toJsonJsonObjectMemberFunctionSymbol->SetAccess(SymbolAccess::public_);
286 toJsonJsonObjectMemberFunctionSymbol->AddMember(thisParam);
287 toJsonJsonObjectMemberFunctionSymbol->AddMember(jsonObjectParam);
288 classTypeSymbol->AddMember(toJsonJsonObjectMemberFunctionSymbol);
289 toJsonJsonObjectMemberFunctionSymbol->ComputeName();
290 toJsonJsonObjectMemberFunctionSymbolMap[classTypeSymbol] = toJsonJsonObjectMemberFunctionSymbol;
291 }
292
293 void JsonAttributeProcessor::GenerateToJsonSymbol(AttributeNode* attribute, ClassTypeSymbol* classTypeSymbol, BoundCompileUnit& boundCompileUnit, ContainerScope* containerScope)
294 {
295 MemberFunctionSymbol* toJsonMemberFunctionSymbol = new MemberFunctionSymbol(attribute->GetSpan(), attribute->ModuleId(), U"ToJson");
296 toJsonMemberFunctionSymbol->SetModule(module);
297 toJsonMemberFunctionSymbol->SetGroupName(U"ToJson");
298 ClassTypeSymbol* baseClass = classTypeSymbol->BaseClass();
299 bool jsonBase = false;
300 if (baseClass)
301 {
302 AttributesNode* attributes = baseClass->GetAttributes();
303 if (attributes)
304 {
305 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
306 if (jsonAttribute)
307 {
308 if (jsonAttribute->Value() == U"true")
309 {
310 jsonBase = true;
311 }
312 }
313 }
314 }
315 if (!jsonBase)
316 {
317 toJsonMemberFunctionSymbol->SetVirtual();
318 }
319 else
320 {
321 toJsonMemberFunctionSymbol->SetOverride();
322 }
323 GetRootModuleForCurrentThread()->GetSymbolTable().SetFunctionIdFor(toJsonMemberFunctionSymbol);
324 ParameterSymbol* thisParam = new ParameterSymbol(attribute->GetSpan(), attribute->ModuleId(), U"this");
325 thisParam->SetType(classTypeSymbol->AddPointer(attribute->GetSpan(), attribute->ModuleId()));
326 TemplateIdNode templateId(attribute->GetSpan(), attribute->ModuleId(), new IdentifierNode(attribute->GetSpan(), attribute->ModuleId(), U"System.UniquePtr"));
327 templateId.AddTemplateArgument(new IdentifierNode(attribute->GetSpan(), attribute->ModuleId(), U"System.Json.JsonValue"));
328 TypeSymbol* uniquePtrJsonValueType = ResolveType(&templateId, boundCompileUnit, containerScope);
329 toJsonMemberFunctionSymbol->SetReturnType(uniquePtrJsonValueType);
330 ParameterSymbol* returnParam = new ParameterSymbol(attribute->GetSpan(), attribute->ModuleId(), U"@return");
331 returnParam->SetParent(toJsonMemberFunctionSymbol);
332 returnParam->SetType(uniquePtrJsonValueType->AddPointer(attribute->GetSpan(), attribute->ModuleId()));
333 toJsonMemberFunctionSymbol->SetReturnParam(returnParam);
334 toJsonMemberFunctionSymbol->SetAccess(SymbolAccess::public_);
335 toJsonMemberFunctionSymbol->AddMember(thisParam);
336 classTypeSymbol->AddMember(toJsonMemberFunctionSymbol);
337 toJsonMemberFunctionSymbol->ComputeName();
338 toJsonObjectMemberFunctionSymbolMap[classTypeSymbol] = toJsonMemberFunctionSymbol;
339 }
340
341 void JsonAttributeProcessor::GenerateImplementation(AttributeNode* attribute, Symbol* symbol, StatementBinder* statementBinder)
342 {
343 if (symbol->IsClassTypeSymbol())
344 {
345 ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(symbol);
346 auto it = jsonConstructorMap.find(symbol);
347 if (it != jsonConstructorMap.cend())
348 {
349 ConstructorSymbol* jsonConstructorSymbol = it->second;
350 GenerateJsonConstructorImplementation(attribute, classTypeSymbol, jsonConstructorSymbol, statementBinder);
351 }
352 else
353 {
354 throw Exception("internal error in JSON attribute implementation: constructor symbol for symbol '" + ToUtf8(symbol->FullName()) + "' not found", attribute->GetSpan(), attribute->ModuleId());
355 }
356 auto it1 = jsonCreatorMap.find(symbol);
357 if (it1 != jsonCreatorMap.cend())
358 {
359 MemberFunctionSymbol* jsonCreatorSymbol = it1->second;
360 GenerateJsonCreatorImplementation(attribute, classTypeSymbol, jsonCreatorSymbol, statementBinder);
361 }
362 else
363 {
364 throw Exception("internal error in JSON attribute implementation: Creator function symbol for symbol '" + ToUtf8(symbol->FullName()) + "' not found", attribute->GetSpan(), attribute->ModuleId());
365 }
366 auto it2 = toJsonJsonObjectMemberFunctionSymbolMap.find(symbol);
367 if (it2 != toJsonJsonObjectMemberFunctionSymbolMap.cend())
368 {
369 MemberFunctionSymbol* toJsonJsonObjectMemberFunctionSymbol = it2->second;
370 GenerateToJsonJsonObjectImplementation(attribute, classTypeSymbol, toJsonJsonObjectMemberFunctionSymbol, statementBinder);
371 }
372 else
373 {
374 throw Exception("internal error in JSON attribute implementation: member function 'ToJson' symbol for symbol '" + ToUtf8(symbol->FullName()) + "' not found", attribute->GetSpan(), attribute->ModuleId());
375 }
376 auto it3 = toJsonObjectMemberFunctionSymbolMap.find(symbol);
377 if (it3 != toJsonObjectMemberFunctionSymbolMap.cend())
378 {
379 MemberFunctionSymbol* toJsonMemberFunctionSymbol = it3->second;
380 GenerateToJsonImplementation(attribute, classTypeSymbol, toJsonMemberFunctionSymbol, statementBinder);
381 }
382 else
383 {
384 throw Exception("internal error in JSON attribute implementation: member function 'ToJson' symbol for symbol '" + ToUtf8(symbol->FullName()) + "' not found", attribute->GetSpan(), attribute->ModuleId());
385 }
386 SymbolTable& symbolTable = module->GetSymbolTable();
387 symbolTable.AddJsonClass(classTypeSymbol->FullName());
388 }
389 }
390
391 void JsonAttributeProcessor::GenerateJsonCreatorImplementation(AttributeNode* attribute, ClassTypeSymbol* classTypeSymbol, MemberFunctionSymbol* jsonCreatorFunctionSymbol, StatementBinder* statementBinder)
392 {
393 try
394 {
395 FileScope* fileScope = new FileScope();
396 Symbol* jsonValue = classTypeSymbol->GetModule()->GetSymbolTable().GlobalNs().GetContainerScope()->Lookup(U"System.Json.JsonValue");
397 if (jsonValue)
398 {
399 fileScope->AddContainerScope(jsonValue->Ns()->GetContainerScope());
400 }
401 statementBinder->GetBoundCompileUnit().AddFileScope(fileScope);
402 std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&statementBinder->GetBoundCompileUnit(), jsonCreatorFunctionSymbol));
403 Span span = attribute->GetSpan();
404 boost::uuids::uuid moduleId = attribute->ModuleId();
405 CompoundStatementNode compoundStatementNode(span, moduleId);
406 compoundStatementNode.SetEndBraceSpan(span);
407 NewNode* newNode = new NewNode(span, moduleId, new IdentifierNode(span, moduleId, classTypeSymbol->FullName()));
408 newNode->AddArgument(new IdentifierNode(span, moduleId, U"@value"));
409 ReturnStatementNode* returnStatementNode = new ReturnStatementNode(span, moduleId, newNode);
410 compoundStatementNode.AddStatement(returnStatementNode);
411 SymbolTable& symbolTable = statementBinder->GetBoundCompileUnit().GetSymbolTable();
412 symbolTable.BeginContainer(jsonCreatorFunctionSymbol);
413 SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
414 compoundStatementNode.Accept(symbolCreatorVisitor);
415 symbolTable.EndContainer();
416 TypeBinder typeBinder(statementBinder->GetBoundCompileUnit());
417 ContainerScope* containerScope = statementBinder->GetContainerScope();
418 typeBinder.SetContainerScope(containerScope);
419 statementBinder->SetContainerScope(jsonCreatorFunctionSymbol->GetContainerScope());
420 typeBinder.SetCurrentFunctionSymbol(jsonCreatorFunctionSymbol);
421 compoundStatementNode.Accept(typeBinder);
422 BoundFunction* prevFunction = statementBinder->CurrentFunction();
423 statementBinder->SetCurrentFunction(boundFunction.get());
424 compoundStatementNode.Accept(*statementBinder);
425 statementBinder->SetContainerScope(containerScope);
426 BoundStatement* boundStatement = statementBinder->ReleaseStatement();
427 Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement, "bound compound statement expected");
428 BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
429 boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
430 statementBinder->CurrentClass()->AddMember(std::move(boundFunction));
431 statementBinder->SetCurrentFunction(prevFunction);
432 statementBinder->GetBoundCompileUnit().RemoveLastFileScope();
433 }
434 catch (const Exception& ex;)
435 {
436 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
437 references.push_back(std::make_pair(ex.Defined(), ex.DefinedModuleId()));
438 references.insert(references.end(), ex.References().begin(), ex.References().end());
439 throw Exception("error in JSON attribute generation: could not create JSON Create() function for class '" + ToUtf8(classTypeSymbol->FullName()) + "': " + ex.Message(),
440 classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId(), references);
441 }
442 }
443
444 void JsonAttributeProcessor::GenerateJsonConstructorImplementation(AttributeNode* attribute, ClassTypeSymbol* classTypeSymbol, ConstructorSymbol* jsonConstructorSymbol, StatementBinder* statementBinder)
445 {
446 try
447 {
448 FileScope* fileScope = new FileScope();
449 Symbol* jsonValue = classTypeSymbol->GetModule()->GetSymbolTable().GlobalNs().GetContainerScope()->Lookup(U"System.Json.JsonValue");
450 if (jsonValue)
451 {
452 fileScope->AddContainerScope(jsonValue->Ns()->GetContainerScope());
453 }
454 statementBinder->GetBoundCompileUnit().AddFileScope(fileScope);
455 std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&statementBinder->GetBoundCompileUnit(), jsonConstructorSymbol));
456 Span span = attribute->GetSpan();
457 boost::uuids::uuid moduleId = attribute->ModuleId();
458 ConstructorNode constructorNode(span, moduleId);
459 CompoundStatementNode compoundStatementNode(span, moduleId);
460 compoundStatementNode.SetEndBraceSpan(span);
461 ClassTypeSymbol* baseClass = classTypeSymbol->BaseClass();
462 if (baseClass)
463 {
464 AttributesNode* attributes = baseClass->GetAttributes();
465 if (attributes)
466 {
467 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
468 if (jsonAttribute)
469 {
470 if (jsonAttribute->Value() == U"true")
471 {
472 BaseInitializerNode* baseInitializer = new BaseInitializerNode(span, moduleId);
473 baseInitializer->AddArgument(new IdentifierNode(span, moduleId, U"@value"));
474 constructorNode.AddInitializer(baseInitializer);
475 }
476 }
477 }
478 }
479 for (MemberVariableSymbol* memberVariableSymbol : classTypeSymbol->MemberVariables())
480 {
481 std::u32string jsonFieldName = memberVariableSymbol->Name();
482 AttributesNode* attributes = memberVariableSymbol->GetAttributes();
483 if (attributes)
484 {
485 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
486 if (jsonAttribute)
487 {
488 if (jsonAttribute->Value() == U"false")
489 {
490 continue;
491 }
492 }
493 AttributeNode* jsonFieldNameAttribute = attributes->GetAttribute(U"jsonFieldName");
494 if (jsonFieldNameAttribute)
495 {
496 jsonFieldName = jsonFieldNameAttribute->Value();
497 }
498 }
499 InvokeNode* invokeNode = new InvokeNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), new IdentifierNode(span, moduleId, U"FromJson"));
500 invokeNode->AddArgument(new IdentifierNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), U"@value"));
501 invokeNode->AddArgument(new UStringLiteralNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), jsonFieldName));
502 invokeNode->AddArgument(new IdentifierNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), memberVariableSymbol->Name()));
503 ExpressionStatementNode* fromJsonStatement = new ExpressionStatementNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), invokeNode);
504 compoundStatementNode.AddStatement(fromJsonStatement);
505 }
506 SymbolTable& symbolTable = statementBinder->GetBoundCompileUnit().GetSymbolTable();
507 symbolTable.BeginContainer(jsonConstructorSymbol);
508 SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
509 compoundStatementNode.Accept(symbolCreatorVisitor);
510 symbolTable.EndContainer();
511 TypeBinder typeBinder(statementBinder->GetBoundCompileUnit());
512 ContainerScope* containerScope = statementBinder->GetContainerScope();
513 typeBinder.SetContainerScope(containerScope);
514 statementBinder->SetContainerScope(jsonConstructorSymbol->GetContainerScope());
515 typeBinder.SetCurrentFunctionSymbol(jsonConstructorSymbol);
516 compoundStatementNode.Accept(typeBinder);
517 BoundFunction* prevFunction = statementBinder->CurrentFunction();
518 statementBinder->SetCurrentFunction(boundFunction.get());
519 ConstructorSymbol* prevConstructorSymbol = statementBinder->CurrentConstructorSymbol();
520 ConstructorNode* prevConstructorNode = statementBinder->CurrentConstructorNode();
521 statementBinder->SetCurrentConstructor(jsonConstructorSymbol, &constructorNode);
522 compoundStatementNode.Accept(*statementBinder);
523 statementBinder->SetContainerScope(containerScope);
524 BoundStatement* boundStatement = statementBinder->ReleaseStatement();
525 Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement, "bound compound statement expected");
526 BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
527 boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
528 statementBinder->CurrentClass()->AddMember(std::move(boundFunction));
529 statementBinder->SetCurrentConstructor(prevConstructorSymbol, prevConstructorNode);
530 statementBinder->SetCurrentFunction(prevFunction);
531 statementBinder->GetBoundCompileUnit().RemoveLastFileScope();
532 }
533 catch (const Exception& ex;)
534 {
535 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
536 references.push_back(std::make_pair(ex.Defined(), ex.DefinedModuleId()));
537 references.insert(references.end(), ex.References().begin(), ex.References().end());
538 throw Exception("error in JSON attribute generation: could not create JSON constructor for class '" + ToUtf8(classTypeSymbol->FullName()) + "': " + ex.Message(),
539 classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId(), references);
540 }
541 }
542
543 void JsonAttributeProcessor::GenerateToJsonJsonObjectImplementation(AttributeNode* attribute, ClassTypeSymbol* classTypeSymbol, MemberFunctionSymbol* toJsonJsonObjectMemberFunctionSymbol, StatementBinder* statementBinder)
544 {
545 try
546 {
547 FileScope* fileScope = new FileScope();
548 Symbol* jsonObject = GetRootModuleForCurrentThread()->GetSymbolTable().GlobalNs().GetContainerScope()->Lookup(U"System.Json.JsonObject");
549 if (jsonObject)
550 {
551 fileScope->AddContainerScope(jsonObject->Ns()->GetContainerScope());
552 }
553 statementBinder->GetBoundCompileUnit().AddFileScope(fileScope);
554 std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&statementBinder->GetBoundCompileUnit(), toJsonJsonObjectMemberFunctionSymbol));
555 Span span = attribute->GetSpan();
556 boost::uuids::uuid moduleId = attribute->ModuleId();
557 CompoundStatementNode compoundStatementNode(span, moduleId);
558 compoundStatementNode.SetEndBraceSpan(span);
559 ClassTypeSymbol* baseClass = classTypeSymbol->BaseClass();
560 if (baseClass)
561 {
562 AttributesNode* attributes = baseClass->GetAttributes();
563 if (attributes)
564 {
565 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
566 if (jsonAttribute)
567 {
568 if (jsonAttribute->Value() == U"true")
569 {
570 BaseNode* baseNode = new BaseNode(span, moduleId);
571 ArrowNode* arrowNode = new ArrowNode(span, moduleId, baseNode, new IdentifierNode(span, moduleId, U"ToJson"));
572 InvokeNode* toJsonInvokeNode = new InvokeNode(span, moduleId, arrowNode);
573 toJsonInvokeNode->AddArgument(new IdentifierNode(span, moduleId, U"@object"));
574 ExpressionStatementNode* toJsonStatement = new ExpressionStatementNode(span, moduleId, toJsonInvokeNode);
575 compoundStatementNode.AddStatement(toJsonStatement);
576 }
577 }
578 }
579 }
580 for (MemberVariableSymbol* memberVariableSymbol : classTypeSymbol->MemberVariables())
581 {
582 std::u32string jsonFieldName = memberVariableSymbol->Name();
583 AttributesNode* attributes = memberVariableSymbol->GetAttributes();
584 if (attributes)
585 {
586 AttributeNode* jsonAttribute = attributes->GetAttribute(U"json");
587 if (jsonAttribute)
588 {
589 if (jsonAttribute->Value() == U"false")
590 {
591 continue;
592 }
593 }
594 AttributeNode* jsonFieldNameAttribute = attributes->GetAttribute(U"jsonFieldName");
595 if (jsonFieldNameAttribute)
596 {
597 jsonFieldName = jsonFieldNameAttribute->Value();
598 }
599 }
600 InvokeNode* toJsonInvokeNode = new InvokeNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), new IdentifierNode(span, moduleId, U"ToJson"));
601 toJsonInvokeNode->AddArgument(new IdentifierNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), memberVariableSymbol->Name()));
602 ArrowNode* arrowNode = new ArrowNode(span, moduleId, new IdentifierNode(span, moduleId, U"@object"), new IdentifierNode(span, moduleId, U"AddField"));
603 InvokeNode* addFieldInvokeNode = new InvokeNode(span, moduleId, arrowNode);
604 addFieldInvokeNode->AddArgument(new UStringLiteralNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), jsonFieldName));
605 addFieldInvokeNode->AddArgument(toJsonInvokeNode);
606 ExpressionStatementNode* addFieldStatement = new ExpressionStatementNode(memberVariableSymbol->GetSpan(), memberVariableSymbol->SourceModuleId(), addFieldInvokeNode);
607 compoundStatementNode.AddStatement(addFieldStatement);
608 }
609 SymbolTable& symbolTable = statementBinder->GetBoundCompileUnit().GetSymbolTable();
610 symbolTable.BeginContainer(toJsonJsonObjectMemberFunctionSymbol);
611 SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
612 compoundStatementNode.Accept(symbolCreatorVisitor);
613 symbolTable.EndContainer();
614 TypeBinder typeBinder(statementBinder->GetBoundCompileUnit());
615 ContainerScope* containerScope = statementBinder->GetContainerScope();
616 typeBinder.SetContainerScope(containerScope);
617 statementBinder->SetContainerScope(toJsonJsonObjectMemberFunctionSymbol->GetContainerScope());
618 typeBinder.SetCurrentFunctionSymbol(toJsonJsonObjectMemberFunctionSymbol);
619 compoundStatementNode.Accept(typeBinder);
620 BoundFunction* prevFunction = statementBinder->CurrentFunction();
621 statementBinder->SetCurrentFunction(boundFunction.get());
622 compoundStatementNode.Accept(*statementBinder);
623 statementBinder->SetContainerScope(containerScope);
624 BoundStatement* boundStatement = statementBinder->ReleaseStatement();
625 Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement, "bound compound statement expected");
626 BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
627 boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
628 statementBinder->CurrentClass()->AddMember(std::move(boundFunction));
629 statementBinder->SetCurrentFunction(prevFunction);
630 statementBinder->GetBoundCompileUnit().RemoveLastFileScope();
631 }
632 catch (const Exception& ex;)
633 {
634 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
635 references.push_back(std::make_pair(ex.Defined(), ex.DefinedModuleId()));
636 references.insert(references.end(), ex.References().begin(), ex.References().end());
637 throw Exception("error in JSON attribute generation: could not create 'void ToJson(JsobObject*)' member function for class '" + ToUtf8(classTypeSymbol->FullName()) + "': " + ex.Message(),
638 classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId(), references);
639 }
640 }
641
642 void JsonAttributeProcessor::GenerateToJsonImplementation(AttributeNode* attribute, ClassTypeSymbol* classTypeSymbol, MemberFunctionSymbol* toJsonMemberFunctionSymbol, StatementBinder* statementBinder)
643 {
644 try
645 {
646 FileScope* fileScope = new FileScope();
647 Symbol* jsonObject = GetRootModuleForCurrentThread()->GetSymbolTable().GlobalNs().GetContainerScope()->Lookup(U"System.Json.JsonObject");
648 if (jsonObject)
649 {
650 fileScope->AddContainerScope(jsonObject->Ns()->GetContainerScope());
651 }
652 statementBinder->GetBoundCompileUnit().AddFileScope(fileScope);
653 std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&statementBinder->GetBoundCompileUnit(), toJsonMemberFunctionSymbol));
654 Span span = attribute->GetSpan();
655 boost::uuids::uuid moduleId = attribute->ModuleId();
656 CompoundStatementNode compoundStatementNode(span, moduleId);
657 compoundStatementNode.SetEndBraceSpan(span);
658 TemplateIdNode* uniquePtrJsonObject = new TemplateIdNode(span, moduleId, new IdentifierNode(span, moduleId, U"UniquePtr"));
659 uniquePtrJsonObject->AddTemplateArgument(new IdentifierNode(span, moduleId, U"JsonObject"));
660 ConstructionStatementNode* constructJsonObjectStatement = new ConstructionStatementNode(span, moduleId, uniquePtrJsonObject, new IdentifierNode(span, moduleId, U"@object"));
661 constructJsonObjectStatement->AddArgument(new NewNode(span, moduleId, new IdentifierNode(span, moduleId, U"JsonObject")));
662 compoundStatementNode.AddStatement(constructJsonObjectStatement);
663 InvokeNode* invokeToJson = new InvokeNode(span, moduleId, new IdentifierNode(span, moduleId, U"ToJson"));
664 invokeToJson->AddArgument(new InvokeNode(span, moduleId, new DotNode(span, moduleId, new IdentifierNode(span, moduleId, U"@object"), new IdentifierNode(span, moduleId, U"Get"))));
665 ExpressionStatementNode* callToJsonStatement = new ExpressionStatementNode(span, moduleId, invokeToJson);
666 compoundStatementNode.AddStatement(callToJsonStatement);
667 TemplateIdNode* uniquePtrJsonValue = new TemplateIdNode(span, moduleId, new IdentifierNode(span, moduleId, U"UniquePtr"));
668 uniquePtrJsonValue->AddTemplateArgument(new IdentifierNode(span, moduleId, U"JsonValue"));
669 InvokeNode* invokeJsonValue = new InvokeNode(span, moduleId, uniquePtrJsonValue);
670 invokeJsonValue->AddArgument(new InvokeNode(span, moduleId, new DotNode(span, moduleId, new IdentifierNode(span, moduleId, U"@object"), new IdentifierNode(span, moduleId, U"Release"))));
671 ReturnStatementNode* returnStatement = new ReturnStatementNode(span, moduleId, invokeJsonValue);
672 compoundStatementNode.AddStatement(returnStatement);
673 SymbolTable& symbolTable = statementBinder->GetBoundCompileUnit().GetSymbolTable();
674 symbolTable.BeginContainer(toJsonMemberFunctionSymbol);
675 SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
676 compoundStatementNode.Accept(symbolCreatorVisitor);
677 symbolTable.EndContainer();
678 TypeBinder typeBinder(statementBinder->GetBoundCompileUnit());
679 ContainerScope* containerScope = statementBinder->GetContainerScope();
680 typeBinder.SetContainerScope(containerScope);
681 statementBinder->SetContainerScope(toJsonMemberFunctionSymbol->GetContainerScope());
682 typeBinder.SetCurrentFunctionSymbol(toJsonMemberFunctionSymbol);
683 compoundStatementNode.Accept(typeBinder);
684 BoundFunction* prevFunction = statementBinder->CurrentFunction();
685 statementBinder->SetCurrentFunction(boundFunction.get());
686 compoundStatementNode.Accept(*statementBinder);
687 statementBinder->SetContainerScope(containerScope);
688 BoundStatement* boundStatement = statementBinder->ReleaseStatement();
689 Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement, "bound compound statement expected");
690 BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
691 boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
692 statementBinder->CurrentClass()->AddMember(std::move(boundFunction));
693 statementBinder->SetCurrentFunction(prevFunction);
694 statementBinder->GetBoundCompileUnit().RemoveLastFileScope();
695 }
696 catch (const Exception& ex;)
697 {
698 std::vector<std::std::pair<Span, boost::uuids::uuid>>references;
699 references.push_back(std::make_pair(ex.Defined(), ex.DefinedModuleId()));
700 references.insert(references.end(), ex.References().begin(), ex.References().end());
701 throw Exception("error in JSON attribute generation: could not create 'UniquePtr<JsonValue> ToJson()' member function for class '" + ToUtf8(classTypeSymbol->FullName()) + "': " + ex.Message(),
702 classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId(), references);
703 }
704 }
705
706 JsonFieldNameAttributeProcessor::JsonFieldNameAttributeProcessor() : AttributeProcessor(U"jsonFieldName")
707 {
708 }
709
710 void JsonFieldNameAttributeProcessor::TypeCheck(AttributeNode* attribute, Symbol* symbol)
711 {
712 if (symbol->GetSymbolType() == SymbolType::memberVariableSymbol)
713 {
714 if (attribute->Value().empty())
715 {
716 throw Exception("attribute value '" + ToUtf8(attribute->Value()) + "' for attribute '" + ToUtf8(attribute->Name()) + "' cannot be empty string", attribute->GetSpan(), attribute->ModuleId());
717 }
718 return;
719 }
720 AttributeProcessor::TypeCheck(attribute, symbol);
721 }
722
723 } }