00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00013 
00014 
00015 #include "Scope.h"
00016 #include "TypeCheck.h"
00017 #include "comma/ast/Decl.h"
00018 #include "comma/ast/DeclRewriter.h"
00019 #include "comma/ast/TypeRef.h"
00020 
00021 #include "llvm/ADT/DenseMap.h"
00022 
00023 using namespace comma;
00024 using llvm::dyn_cast;
00025 using llvm::dyn_cast_or_null;
00026 using llvm::cast;
00027 using llvm::isa;
00028 
00029 void TypeCheck::beginCapsule()
00030 {
00031     assert(scope.getLevel() == 0 && "Cannot typecheck nested capsules!");
00032 
00033     
00034     scope.push(MODEL_SCOPE);
00035     GenericFormalDecls.clear();
00036     declarativeRegion = 0;
00037     currentModel = 0;
00038 }
00039 
00040 void TypeCheck::endCapsule()
00041 {
00042     if (Domoid *domoid = getCurrentDomoid())
00043         ensureExportConstraints(domoid->getImplementation());
00044 
00045     assert(scope.getKind() == MODEL_SCOPE);
00046     scope.pop();
00047 
00048     ModelDecl *result = getCurrentModel();
00049     if (Decl *conflict = scope.addDirectDecl(result)) {
00050         
00051         report(result->getLocation(), diag::CONFLICTING_DECLARATION)
00052             << result->getIdInfo() << getSourceLoc(conflict->getLocation());
00053     }
00054     else {
00055         
00056         if (Domoid *domoid = dyn_cast<Domoid>(result))
00057             domoid->finalize();
00058         compUnit->addDeclaration(result);
00059     }
00060 }
00061 
00062 void TypeCheck::beginGenericFormals()
00063 {
00064     assert(GenericFormalDecls.empty() && "Formal decls already present!");
00065 }
00066 
00067 void TypeCheck::endGenericFormals() { }
00068 
00069 void TypeCheck::acceptFormalDomain(IdentifierInfo *name, Location loc,
00070                                    Node sigNode)
00071 {
00072     AbstractDomainDecl *decl;
00073 
00074     if (sigNode.isNull())
00075         decl = new AbstractDomainDecl(resource, name, loc);
00076     else {
00077         TypeRef *ref = lift_node<TypeRef>(sigNode);
00078 
00079         if (!ref || !ref->referencesSigInstance()) {
00080             report(getNodeLoc(sigNode), diag::NOT_A_SIGNATURE);
00081             return;
00082         }
00083 
00084         sigNode.release();
00085         delete ref;
00086         SigInstanceDecl *sig = ref->getSigInstanceDecl();
00087         decl = new AbstractDomainDecl(resource, name, loc, sig);
00088     }
00089 
00090 
00091     if (scope.addDirectDecl(decl)) {
00092         
00093         
00094         report(loc, diag::DUPLICATE_FORMAL_PARAM) << name;
00095         delete decl;
00096     }
00097     else
00098         GenericFormalDecls.push_back(decl);
00099 }
00100 
00101 void TypeCheck::beginDomainDecl(IdentifierInfo *name, Location loc)
00102 {
00103     
00104     
00105     unsigned arity = GenericFormalDecls.size();
00106 
00107     if (arity == 0)
00108         currentModel = new DomainDecl(resource, name, loc);
00109     else
00110         currentModel = new FunctorDecl(resource, name, loc,
00111                                        &GenericFormalDecls[0], arity);
00112     initializeForModelDeclaration();
00113 }
00114 
00115 void TypeCheck::beginSignatureDecl(IdentifierInfo *name, Location loc)
00116 {
00117     
00118     
00119     unsigned arity = GenericFormalDecls.size();
00120 
00121     if (arity == 0)
00122         currentModel = new SignatureDecl(resource, name, loc);
00123     else
00124         currentModel = new VarietyDecl(resource, name, loc,
00125                                        &GenericFormalDecls[0], arity);
00126     initializeForModelDeclaration();
00127 }
00128 
00129 void TypeCheck::initializeForModelDeclaration()
00130 {
00131     assert(scope.getKind() == MODEL_SCOPE);
00132 
00133     
00134     
00135     declarativeRegion = currentModel->getPercent();
00136 
00137     
00138     
00139     unsigned arity = currentModel->getArity();
00140     for (unsigned i = 0; i < arity; ++i) {
00141         AbstractDomainDecl *formal = currentModel->getFormalDecl(i);
00142         formal->setDeclRegion(declarativeRegion);
00143     }
00144 
00145     
00146     
00147     scope.addDirectDeclNoConflicts(currentModel);
00148 }
00149 
00150 void TypeCheck::acceptSupersignature(Node typeNode)
00151 {
00152     TypeRef *ref = cast_node<TypeRef>(typeNode);
00153     Location loc = ref->getLocation();
00154     SigInstanceDecl *superSig = ref->getSigInstanceDecl();
00155 
00156     
00157     if (!superSig) {
00158         report(loc, diag::NOT_A_SIGNATURE);
00159         return;
00160     }
00161 
00162     getCurrentModel()->addDirectSignature(superSig);
00163 
00164     
00165     
00166     acquireSignatureDeclarations(superSig, loc);
00167 }
00168 
00169 void TypeCheck::beginSignatureProfile()
00170 {
00171     
00172     
00173     
00174 }
00175 
00176 void TypeCheck::endSignatureProfile()
00177 {
00178     DomainTypeDecl *domain;
00179 
00180     
00181     
00182     if (ModelDecl *model = getCurrentModel())
00183         domain = model->getPercent();
00184     else
00185         domain = cast<AbstractDomainDecl>(declarativeRegion);
00186 }
00187 
00188 void TypeCheck::acquireImplicitDeclarations(Decl *decl)
00189 {
00190     typedef DeclRegion::DeclIter iterator;
00191     DeclRegion *region = 0;
00192 
00193     
00194     
00195     if (EnumerationDecl *eDecl = dyn_cast<EnumerationDecl>(decl))
00196         region = eDecl;
00197     else if (IntegerDecl *iDecl = dyn_cast<IntegerDecl>(decl))
00198         region = iDecl;
00199     else
00200         return;
00201 
00202     iterator E = region->endDecls();
00203     for (iterator I = region->beginDecls(); I != E; ++I)
00204         scope.addDirectDeclNoConflicts(*I);
00205 }
00206 
00207 void TypeCheck::acquireSignatureDeclarations(SigInstanceDecl *sig, Location loc)
00208 {
00209     typedef DeclRegion::DeclIter iterator;
00210     PercentDecl *sigPercent = sig->getSigoid()->getPercent();
00211     DeclRewriter rewrites(resource, declarativeRegion, sigPercent);
00212 
00213     
00214     
00215     
00216     rewrites.installRewrites(sig);
00217     rewrites.addTypeRewrite(sigPercent->getType(), getCurrentPercentType());
00218 
00219     iterator E = sigPercent->endDecls();
00220     for (iterator I = sigPercent->beginDecls(); I != E; ++I) {
00221         
00222         
00223         Decl *candidate = rewrites.rewriteDecl(*I);
00224 
00225         
00226         if (Decl *conflict = scope.addDirectDecl(candidate)) {
00227             
00228             
00229             
00230             
00231             conflict = conflict->resolveOrigin();
00232             candidate = candidate->resolveOrigin();
00233 
00234             
00235             
00236             
00237             
00238             report(loc, diag::CONFLICTING_SIGNATURE_INCLUSION)
00239                 << sig->getIdInfo();
00240 
00241             
00242             SourceLocation sloc = getSourceLoc(conflict->getLocation());
00243             report(candidate->getLocation(), diag::DECLARATION_CONFLICTS)
00244                 << candidate->getIdInfo() << sloc;
00245         }
00246         else {
00247             
00248             
00249             acquireImplicitDeclarations(candidate);
00250             declarativeRegion->addDecl(candidate);
00251         }
00252     }
00253 }
00254 
00255 void TypeCheck::beginAddExpression()
00256 {
00257     Domoid *domoid = getCurrentDomoid();
00258     assert(domoid && "Processing `add' expression outside domain context!");
00259 
00260     
00261     declarativeRegion = domoid->getImplementation();
00262     assert(declarativeRegion && "Domain missing Add declaration node!");
00263 }
00264 
00265 void TypeCheck::endAddExpression()
00266 {
00267     
00268     
00269     declarativeRegion = declarativeRegion->getParent();
00270     assert(declarativeRegion == getCurrentPercent()->asDeclRegion());
00271 }
00272 
00273 void TypeCheck::acceptCarrier(IdentifierInfo *name, Location loc, Node typeNode)
00274 {
00275     
00276     AddDecl *add = cast<AddDecl>(declarativeRegion);
00277 
00278     if (add->hasCarrier()) {
00279         report(loc, diag::MULTIPLE_CARRIER_DECLARATIONS);
00280         return;
00281     }
00282 
00283     TypeDecl *tyDecl = ensureCompleteTypeDecl(typeNode);
00284 
00285     if (!tyDecl)
00286         return;
00287 
00288     if (tyDecl->getType()->involvesPercent()) {
00289         report(loc, diag::SELF_RECURSIVE_TYPE_DECLARATION);
00290         return;
00291     }
00292 
00293     CarrierDecl *carrier;
00294     carrier = new CarrierDecl(resource, name, tyDecl->getType(), loc);
00295     if (Decl *conflict = scope.addDirectDecl(carrier)) {
00296         report(loc, diag::CONFLICTING_DECLARATION)
00297             << name << getSourceLoc(conflict->getLocation());
00298         return;
00299     }
00300     add->setCarrier(carrier);
00301 }
00302 
00303 bool TypeCheck::ensureExportConstraints(AddDecl *add)
00304 {
00305     Domoid *domoid = add->getImplementedDomoid();
00306     IdentifierInfo *domainName = domoid->getIdInfo();
00307     PercentDecl *percent = domoid->getPercent();
00308     Location domainLoc = domoid->getLocation();
00309 
00310     bool allOK = true;
00311 
00312     
00313     
00314     
00315     for (DeclRegion::ConstDeclIter iter = percent->beginDecls();
00316          iter != percent->endDecls(); ++iter) {
00317 
00318         
00319         if (IncompleteTypeDecl *ITD = dyn_cast<IncompleteTypeDecl>(*iter)) {
00320             if (!ITD->hasCompletion()) {
00321                 report(ITD->getLocation(), diag::MISSING_TYPE_COMPLETION)
00322                     << ITD->getIdInfo();
00323                 allOK=false;
00324             }
00325             continue;
00326         }
00327 
00328         
00329         SubroutineDecl *decl = dyn_cast<SubroutineDecl>(*iter);
00330 
00331         if (!decl)
00332             continue;
00333 
00334         
00335         
00336         
00337         
00338         
00339         
00340         if (!decl->getDefiningDeclaration()) {
00341             report(domainLoc, diag::MISSING_EXPORT)
00342                 << domainName << decl->getIdInfo();
00343             allOK = false;
00344         }
00345     }
00346     return allOK;
00347 }