48 using namespace analysis;
52 static const unsigned int MAX_INSTANTIATION_DEPTH = 1000;
57 struct ComponentContent {
58 std::vector<Own<ast::Type>>
types;
61 std::vector<Own<Clause>>
clauses;
63 void add(Own<ast::Type>&
type, ErrorReport& report) {
65 auto foundItem = std::find_if(
types.begin(),
types.end(), [&](
const Own<ast::Type>& element) {
66 return (element->getQualifiedName() == type->getQualifiedName());
68 if (foundItem !=
types.end()) {
71 "Redefinition of type " +
toString(
type->getQualifiedName()),
type->getSrcLoc()),
72 {DiagnosticMessage(
"Previous definition", (*foundItem)->getSrcLoc())});
73 report.addDiagnostic(
err);
78 void add(Own<Relation>&
rel, ErrorReport& report) {
80 auto foundItem = std::find_if(
relations.begin(),
relations.end(), [&](
const Own<Relation>& element) {
81 return (element->getQualifiedName() == rel->getQualifiedName());
85 DiagnosticMessage(
"Redefinition of relation " +
toString(
rel->getQualifiedName()),
87 {DiagnosticMessage(
"Previous definition", (*foundItem)->getSrcLoc())});
88 report.addDiagnostic(
err);
93 void add(Own<Clause>& clause, ErrorReport& ) {
94 clauses.push_back(std::move(clause));
97 void add(Own<Directive>& newDirective, ErrorReport& report) {
101 return directive->getQualifiedName() == newDirective->getQualifiedName();
105 auto type = (*foundItem)->getType();
109 "Redefinition I/O operation " +
toString(newDirective->getQualifiedName()),
110 newDirective->getSrcLoc()),
111 {DiagnosticMessage(
"Previous definition", (*foundItem)->getSrcLoc())});
112 report.addDiagnostic(
err);
116 directives.push_back(std::move(newDirective));
124 ComponentContent getInstantiatedContent(Program& program,
const ComponentInit& componentInit,
125 const Component* enclosingComponent,
const ComponentLookupAnalysis& componentLookup,
126 std::vector<Own<Clause>>& orphans, ErrorReport& report,
127 const TypeBinding& binding = analysis::TypeBinding(),
128 unsigned int maxDepth = MAX_INSTANTIATION_DEPTH);
133 void collectContent(Program& program,
const Component& component,
const TypeBinding& binding,
134 const Component* enclosingComponent,
const ComponentLookupAnalysis& componentLookup,
135 ComponentContent& res, std::vector<Own<Clause>>& orphans,
const std::set<std::string>& overridden,
136 ErrorReport& report,
unsigned int maxInstantiationDepth) {
138 for (
const auto&
base : component.getBaseComponents()) {
139 const Component* comp = componentLookup.getComponent(enclosingComponent,
base->getName(), binding);
140 if (comp !=
nullptr) {
142 const auto& formalParams = comp->getComponentType()->getTypeParameters();
143 const auto& actualParams =
base->getTypeParameters();
146 TypeBinding activeBinding = binding.extend(formalParams, actualParams);
148 for (
const auto& cur : comp->getInstantiations()) {
150 ComponentContent content = getInstantiatedContent(program, *cur, enclosingComponent,
151 componentLookup, orphans, report, activeBinding, maxInstantiationDepth - 1);
154 for (
auto&
type : content.types) {
155 res.add(
type, report);
159 for (
auto&
rel : content.relations) {
160 res.add(
rel, report);
164 for (
auto& clause : content.clauses) {
165 res.add(clause, report);
169 for (
auto& directive : content.directives) {
170 res.add(directive, report);
175 std::set<std::string> superOverridden;
176 superOverridden.insert(overridden.begin(), overridden.end());
177 superOverridden.insert(component.getOverridden().begin(), component.getOverridden().end());
178 collectContent(program, *comp, activeBinding, comp, componentLookup, res, orphans,
179 superOverridden, report, maxInstantiationDepth);
184 for (
const auto& cur : component.getTypes()) {
186 Own<ast::Type>
type(cur->clone());
190 for (
const auto& name :
type.getTypes()) {
191 QualifiedName newName = binding.find(name);
192 if (!newName.empty()) {
193 const_cast<QualifiedName&>(name) = newName;
200 for (
const auto& field :
type.getFields()) {
201 auto&& newName = binding.find(field->getTypeName());
202 if (!newName.empty()) {
203 const_cast<Attribute&>(*field).setTypeName(newName);
209 res.add(
type, report);
213 for (
const auto& cur : component.getRelations()) {
215 Own<Relation>
rel(cur->clone());
218 for (Attribute* attr :
rel->getAttributes()) {
219 QualifiedName forward = binding.find(attr->getTypeName());
220 if (!forward.empty()) {
221 attr->setTypeName(forward);
226 res.add(
rel, report);
230 for (
const auto& directive : component.getDirectives()) {
232 Own<Directive> instantiatedIO(directive->clone());
234 res.add(instantiatedIO, report);
238 std::map<QualifiedName, Relation*> index;
239 for (
const auto& cur : res.relations) {
240 index[cur->getQualifiedName()] = cur.get();
245 for (
const auto& cur : component.getClauses()) {
246 if (overridden.count(cur->getHead()->getQualifiedName().getQualifiers()[0]) == 0) {
247 Relation*
rel = index[cur->getHead()->getQualifiedName()];
248 if (
rel !=
nullptr) {
249 Own<Clause> instantiatedClause(cur->clone());
250 res.add(instantiatedClause, report);
252 orphans.emplace_back(cur->clone());
258 for (
auto iter = orphans.begin(); iter != orphans.end();) {
260 Relation*
rel = index[cur->getHead()->getQualifiedName()];
261 if (
rel !=
nullptr) {
263 Own<Clause> instantiatedClause(cur->clone());
264 res.add(instantiatedClause, report);
265 iter = orphans.erase(iter);
272 ComponentContent getInstantiatedContent(Program& program,
const ComponentInit& componentInit,
273 const Component* enclosingComponent,
const ComponentLookupAnalysis& componentLookup,
274 std::vector<Own<Clause>>& orphans, ErrorReport& report,
const TypeBinding& binding,
275 unsigned int maxDepth) {
277 ComponentContent res;
280 report.addError(
"Component instantiation limit reached", componentInit.getSrcLoc());
285 const Component* component = componentLookup.getComponent(
286 enclosingComponent, componentInit.getComponentType()->getName(), binding);
287 if (component ==
nullptr) {
293 const auto& formalParams = component->getComponentType()->getTypeParameters();
294 const auto& actualParams = componentInit.getComponentType()->getTypeParameters();
295 TypeBinding activeBinding = binding.extend(formalParams, actualParams);
298 for (
const auto& cur : component->getInstantiations()) {
300 ComponentContent nestedContent = getInstantiatedContent(
301 program, *cur, component, componentLookup, orphans, report, activeBinding, maxDepth - 1);
304 for (
auto&
type : nestedContent.types) {
305 res.add(
type, report);
309 for (
auto&
rel : nestedContent.relations) {
310 res.add(
rel, report);
314 for (
auto& clause : nestedContent.clauses) {
315 res.add(clause, report);
319 for (
auto& directive : nestedContent.directives) {
320 res.add(directive, report);
325 std::set<std::string> overridden;
326 collectContent(program, *component, activeBinding, enclosingComponent, componentLookup, res, orphans,
327 overridden, report, maxDepth);
330 std::map<QualifiedName, QualifiedName> typeNameMapping;
331 for (
const auto& cur : res.types) {
332 auto newName = componentInit.getInstanceName() + cur->getQualifiedName();
333 typeNameMapping[cur->getQualifiedName()] = newName;
334 cur->setQualifiedName(newName);
338 std::map<QualifiedName, QualifiedName> relationNameMapping;
339 for (
const auto& cur : res.relations) {
340 auto newName = componentInit.getInstanceName() + cur->getQualifiedName();
341 relationNameMapping[cur->getQualifiedName()] = newName;
342 cur->setQualifiedName(newName);
346 auto fixNames = [&](
const Node& node) {
349 auto pos = typeNameMapping.find(attr.getTypeName());
350 if (pos != typeNameMapping.end()) {
351 const_cast<Attribute&>(attr).setTypeName(pos->second);
357 auto pos = relationNameMapping.find(atom.getQualifiedName());
358 if (pos != relationNameMapping.end()) {
359 const_cast<Atom&>(atom).setQualifiedName(pos->second);
365 auto pos = relationNameMapping.find(directive.getQualifiedName());
366 if (pos != relationNameMapping.end()) {
367 const_cast<Directive&>(directive).setQualifiedName(pos->second);
373 auto&& fields = recordType.getFields();
374 for (
size_t i = 0;
i < fields.size();
i++) {
375 auto& field = fields[
i];
376 auto pos = typeNameMapping.find(field->getTypeName());
377 if (pos != typeNameMapping.end()) {
378 const_cast<ast::RecordType&>(recordType).setFieldType(i, pos->second);
385 auto& variants = unionType.getTypes();
386 for (
size_t i = 0;
i < variants.size();
i++) {
387 auto pos = typeNameMapping.find(variants[
i]);
388 if (pos != typeNameMapping.end()) {
389 const_cast<ast::UnionType&>(unionType).setType(i, pos->second);
396 auto pos = typeNameMapping.find(cast.getType());
397 if (pos != typeNameMapping.end()) {
398 const_cast<ast::TypeCast&>(cast).setType(pos->second);
404 for (
const auto& cur : res.relations) {
409 for (
const auto& cur : res.clauses) {
414 for (
const auto& cur : orphans) {
419 for (
const auto& cur : res.directives) {
424 for (
const auto& cur : res.types) {
432 bool ComponentInstantiationTransformer::transform(TranslationUnit& translationUnit) {
433 Program& program = translationUnit.getProgram();
434 auto& report = translationUnit.getErrorReport();
436 auto* componentLookup = translationUnit.getAnalysis<ComponentLookupAnalysis>();
438 for (
const auto* cur : program.getComponentInstantiations()) {
439 std::vector<Own<Clause>> orphans;
441 auto content = getInstantiatedContent(program, *cur,
nullptr, *componentLookup, orphans, report);
442 if (report.getNumErrors() != 0)
continue;
444 for (
auto&
type : content.types) {
445 program.addType(std::move(
type));
447 for (
auto&
rel : content.relations) {
448 program.addRelation(std::move(
rel));
450 for (
auto& clause : content.clauses) {
451 program.addClause(std::move(clause));
453 for (
auto& orphan : orphans) {
454 program.addClause(std::move(orphan));
456 for (
auto& directive : content.directives) {
457 program.addDirective(std::move(directive));
462 program.clearComponents();