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();