This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- typecheck/CheckCapsule.cpp ---------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2008-2010, Stephen Wilson 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 // Push a scope for the upcoming capsule and reset our per-capsule state. 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 // NOTE: The result model could be freed here. 00051 report(result->getLocation(), diag::CONFLICTING_DECLARATION) 00052 << result->getIdInfo() << getSourceLoc(conflict->getLocation()); 00053 } 00054 else { 00055 // Finalize all domoids. 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 // The only conflict possible is with respect to a previous generic 00093 // parameter. 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 // If we have processed generic arguments, construct a functor, else a 00104 // domain. 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 // If we have processed generic arguments, construct a variety, else a 00118 // signature. 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 // Set the current declarative region to be the percent node of the current 00134 // model. 00135 declarativeRegion = currentModel->getPercent(); 00136 00137 // For each generic formal, set its declarative region to be that the new 00138 // models percent node. 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 // Bring the model itself into the current scope. This should never result 00146 // in a conflict. 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 // Check that the node denotes a signature. 00157 if (!superSig) { 00158 report(loc, diag::NOT_A_SIGNATURE); 00159 return; 00160 } 00161 00162 getCurrentModel()->addDirectSignature(superSig); 00163 00164 // Bring all of the declarations defined by this super signature into scope 00165 // and add them to the current declarative region. 00166 acquireSignatureDeclarations(superSig, loc); 00167 } 00168 00169 void TypeCheck::beginSignatureProfile() 00170 { 00171 // Nothing to do. The declarative region and scope of the current model or 00172 // formal domain is the destination of all declarations in a with 00173 // expression. 00174 } 00175 00176 void TypeCheck::endSignatureProfile() 00177 { 00178 DomainTypeDecl *domain; 00179 00180 // Ensure that all ambiguous declarations are redeclared. For now, the only 00181 // ambiguity that can arise is wrt conflicting argument keyword sets. 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 // Resolve the decl by cases. We do not use Decl::asDeclRegion() here since 00194 // since only primitive types implicitly export operations. 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 // Map the formal arguments of the signature to the actual arguments of the 00214 // instance, and map the percent type of the instance to the percent type of 00215 // the current model. 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 // Apply the rewrite rules, constructing a new declaration node in the 00222 // process. 00223 Decl *candidate = rewrites.rewriteDecl(*I); 00224 00225 // Ensure there are no conflicts. 00226 if (Decl *conflict = scope.addDirectDecl(candidate)) { 00227 // If either the conflict or candidate is not immediate, resolve the 00228 // original declaration. Non-immediate declarations are implicitly 00229 // generated and we want our diagnostics to point at the relevant 00230 // item in the source. 00231 conflict = conflict->resolveOrigin(); 00232 candidate = candidate->resolveOrigin(); 00233 00234 // FIXME: Improve the diagnostics here. We could look at the origin 00235 // of the conflicting declaration and provide a qualified name. 00236 // 00237 // Report which signature provided the conflict. 00238 report(loc, diag::CONFLICTING_SIGNATURE_INCLUSION) 00239 << sig->getIdInfo(); 00240 00241 // Report which declarations conflict. 00242 SourceLocation sloc = getSourceLoc(conflict->getLocation()); 00243 report(candidate->getLocation(), diag::DECLARATION_CONFLICTS) 00244 << candidate->getIdInfo() << sloc; 00245 } 00246 else { 00247 // Bring any implicit declarations into scope, and add the candidate 00248 // to the current region. 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 // Switch to the declarative region which this domains AddDecl provides. 00261 declarativeRegion = domoid->getImplementation(); 00262 assert(declarativeRegion && "Domain missing Add declaration node!"); 00263 } 00264 00265 void TypeCheck::endAddExpression() 00266 { 00267 // Switch back to the declarative region of the defining domains percent 00268 // node. 00269 declarativeRegion = declarativeRegion->getParent(); 00270 assert(declarativeRegion == getCurrentPercent()->asDeclRegion()); 00271 } 00272 00273 void TypeCheck::acceptCarrier(IdentifierInfo *name, Location loc, Node typeNode) 00274 { 00275 // We should always be in an add declaration. 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 // The domoid contains all of the declarations inherited from the super 00313 // signatures and any associated with expression. Traverse the set of 00314 // declarations and ensure that the AddDecl provides a definition. 00315 for (DeclRegion::ConstDeclIter iter = percent->beginDecls(); 00316 iter != percent->endDecls(); ++iter) { 00317 00318 // Ensure incomplete type declarations have a completion. 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 // Otherwise, check that all subroutine decls all have a completion. 00329 SubroutineDecl *decl = dyn_cast<SubroutineDecl>(*iter); 00330 00331 if (!decl) 00332 continue; 00333 00334 // Check that a defining declaration was processed. 00335 // 00336 // FIXME: We need a better diagnostic here. In particular, we should be 00337 // reporting which signature(s) demand the missing export. One solution 00338 // is to use the origin link in the declaration node to locate the 00339 // original signature definition. 00340 if (!decl->getDefiningDeclaration()) { 00341 report(domainLoc, diag::MISSING_EXPORT) 00342 << domainName << decl->getIdInfo(); 00343 allOK = false; 00344 } 00345 } 00346 return allOK; 00347 }