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/CheckStmt.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 #include "RangeChecker.h" 00010 #include "Scope.h" 00011 #include "TypeCheck.h" 00012 #include "comma/ast/Decl.h" 00013 #include "comma/ast/DSTDefinition.h" 00014 #include "comma/ast/ExceptionRef.h" 00015 #include "comma/ast/Expr.h" 00016 #include "comma/ast/KeywordSelector.h" 00017 #include "comma/ast/Pragma.h" 00018 #include "comma/ast/RangeAttrib.h" 00019 #include "comma/ast/Stmt.h" 00020 #include "comma/ast/Type.h" 00021 00022 #include "llvm/ADT/STLExtras.h" 00023 00024 using namespace comma; 00025 using llvm::dyn_cast_or_null; 00026 using llvm::dyn_cast; 00027 using llvm::cast; 00028 using llvm::isa; 00029 00030 Node TypeCheck::acceptProcedureCall(Node name) 00031 { 00032 // If the name denotes a procedure call, we are happy. 00033 if (lift_node<ProcedureCallStmt>(name)) { 00034 name.release(); 00035 return name; 00036 } 00037 00038 // Otherwise, figure out what kind of name this is and grab its location. 00039 Location loc; 00040 if (Expr *expr = lift_node<Expr>(name)) 00041 loc = expr->getLocation(); 00042 else if (TypeRef *ref = lift_node<TypeRef>(name)) 00043 loc = ref->getLocation(); 00044 00045 report(loc, diag::EXPECTED_PROCEDURE_CALL); 00046 return getInvalidNode(); 00047 } 00048 00049 Node TypeCheck::acceptReturnStmt(Location loc, Node retNode) 00050 { 00051 assert((checkingProcedure() || checkingFunction()) && 00052 "Return statement outside subroutine context!"); 00053 00054 if (checkingFunction()) { 00055 FunctionDecl *fdecl = getCurrentFunction(); 00056 Type *targetType = fdecl->getReturnType(); 00057 Expr *retExpr = ensureExpr(retNode); 00058 00059 if (!retExpr) 00060 return getInvalidNode(); 00061 00062 if ((retExpr = checkExprInContext(retExpr, targetType))) { 00063 retNode.release(); 00064 return getNode(new ReturnStmt(loc, retExpr)); 00065 } 00066 return getInvalidNode(); 00067 } 00068 00069 report(loc, diag::NONEMPTY_RETURN_IN_PROCEDURE); 00070 return getInvalidNode(); 00071 } 00072 00073 Node TypeCheck::acceptEmptyReturnStmt(Location loc) 00074 { 00075 assert((checkingProcedure() || checkingFunction()) && 00076 "Return statement outside subroutine context!"); 00077 00078 if (checkingProcedure()) 00079 return getNode(new ReturnStmt(loc)); 00080 00081 report(loc, diag::EMPTY_RETURN_IN_FUNCTION); 00082 return getInvalidNode(); 00083 } 00084 00085 Node TypeCheck::acceptAssignmentStmt(Node targetNode, Node valueNode) 00086 { 00087 Expr *value = ensureExpr(valueNode); 00088 Expr *target = ensureExpr(targetNode); 00089 Expr *immutable; 00090 00091 if (!(value && target)) 00092 return getInvalidNode(); 00093 00094 if (!target->isMutable(immutable)) { 00095 Location loc = target->getLocation(); 00096 00097 // Diagnose common assignment mistakes. 00098 if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(immutable)) { 00099 if (isa<LoopDecl>(ref->getDeclaration())) { 00100 report(loc, diag::LOOP_PARAM_NOT_VARIABLE); 00101 return getInvalidNode(); 00102 } 00103 } 00104 00105 // Generic diagnostic. 00106 report(loc, diag::INVALID_TARGET_FOR_ASSIGNMENT); 00107 return getInvalidNode(); 00108 } 00109 00110 // Check that the value is compatible with the type of the target. 00111 Type *targetTy = target->getType(); 00112 if (!(value = checkExprInContext(value, targetTy))) 00113 return getInvalidNode(); 00114 00115 valueNode.release(); 00116 targetNode.release(); 00117 value = convertIfNeeded(value, targetTy); 00118 return getNode(new AssignmentStmt(target, value)); 00119 } 00120 00121 Node TypeCheck::acceptIfStmt(Location loc, Node conditionNode, 00122 NodeVector &consequentNodes) 00123 { 00124 typedef NodeCaster<Stmt> caster; 00125 typedef llvm::mapped_iterator<NodeVector::iterator, caster> iterator; 00126 00127 Expr *pred = cast_node<Expr>(conditionNode); 00128 00129 if ((pred = checkExprInContext(pred, resource.getTheBooleanType()))) { 00130 iterator I(consequentNodes.begin(), caster()); 00131 iterator E(consequentNodes.end(), caster()); 00132 StmtSequence *consequents = new StmtSequence(loc, I, E); 00133 00134 conditionNode.release(); 00135 consequentNodes.release(); 00136 return getNode(new IfStmt(loc, pred, consequents)); 00137 } 00138 return getInvalidNode(); 00139 } 00140 00141 Node TypeCheck::acceptElseStmt(Location loc, Node ifNode, 00142 NodeVector &alternateNodes) 00143 { 00144 typedef NodeCaster<Stmt> caster; 00145 typedef llvm::mapped_iterator<NodeVector::iterator, caster> iterator; 00146 00147 IfStmt *cond = cast_node<IfStmt>(ifNode); 00148 assert(!cond->hasAlternate() && "Multiple else component in IfStmt!"); 00149 00150 iterator I(alternateNodes.begin(), caster()); 00151 iterator E(alternateNodes.end(), caster()); 00152 StmtSequence *alternates = new StmtSequence(loc, I, E); 00153 00154 cond->setAlternate(loc, alternates); 00155 alternateNodes.release(); 00156 return ifNode; 00157 } 00158 00159 Node TypeCheck::acceptElsifStmt(Location loc, Node ifNode, Node conditionNode, 00160 NodeVector &consequentNodes) 00161 { 00162 typedef NodeCaster<Stmt> caster; 00163 typedef llvm::mapped_iterator<NodeVector::iterator, caster> iterator; 00164 00165 IfStmt *cond = cast_node<IfStmt>(ifNode); 00166 Expr *pred = cast_node<Expr>(conditionNode); 00167 00168 if ((pred = checkExprInContext(pred, resource.getTheBooleanType()))) { 00169 iterator I(consequentNodes.begin(), caster()); 00170 iterator E(consequentNodes.end(), caster()); 00171 StmtSequence *consequents = new StmtSequence(loc, I, E); 00172 00173 cond->addElsif(loc, pred, consequents); 00174 conditionNode.release(); 00175 consequentNodes.release(); 00176 return ifNode; 00177 } 00178 return getInvalidNode(); 00179 } 00180 00181 // Called when a block statement is about to be parsed. 00182 Node TypeCheck::beginBlockStmt(Location loc, IdentifierInfo *label) 00183 { 00184 // Create a new block node, establish a new declarative region and scope. 00185 DeclRegion *region = currentDeclarativeRegion(); 00186 BlockStmt *block = new BlockStmt(loc, region, label); 00187 00188 declarativeRegion = block; 00189 scope.push(); 00190 return getNode(block); 00191 } 00192 00193 // Once the last statement of a block has been parsed, this method is called 00194 // to inform the client that we are leaving the block context established by 00195 // the last call to beginBlockStmt. 00196 void TypeCheck::endBlockStmt(Node blockNode) 00197 { 00198 declarativeRegion = currentDeclarativeRegion()->getParent(); 00199 scope.pop(); 00200 } 00201 00202 bool TypeCheck::acceptStmt(Node contextNode, Node stmtNode) 00203 { 00204 Stmt *stmt = cast_node<Stmt>(stmtNode); 00205 StmtSequence *seq; 00206 00207 if (BlockStmt *block = lift_node<BlockStmt>(contextNode)) 00208 seq = block; 00209 else if (HandlerStmt *handler = lift_node<HandlerStmt>(contextNode)) 00210 seq = handler; 00211 else { 00212 assert(false && "Invalid context for acceptStmt!"); 00213 return false; 00214 } 00215 00216 // If this sequence of statements is non-empty ensure the next statement 00217 // does not follow a terminator. Unreachable statements are not considered 00218 // an error, so we return true and let the node reclaim the unused 00219 // statement. 00220 if (!seq->isEmpty()) { 00221 Stmt *predecessor = seq->back(); 00222 if (predecessor->isTerminator()) { 00223 report(stmt->getLocation(), diag::UNREACHABLE_STATEMENT); 00224 return true; 00225 } 00226 } 00227 00228 stmtNode.release(); 00229 seq->addStmt(stmt); 00230 return true; 00231 } 00232 00233 Node TypeCheck::acceptWhileStmt(Location loc, Node conditionNode, 00234 NodeVector &stmtNodes) 00235 { 00236 typedef NodeCaster<Stmt> caster; 00237 typedef llvm::mapped_iterator<NodeVector::iterator, caster> iterator; 00238 00239 Expr *pred = cast_node<Expr>(conditionNode); 00240 00241 if (!(pred = checkExprInContext(pred, resource.getTheBooleanType()))) 00242 return getInvalidNode(); 00243 00244 iterator I(stmtNodes.begin(), caster()); 00245 iterator E(stmtNodes.end(), caster()); 00246 StmtSequence *body = new StmtSequence(loc, I, E); 00247 00248 conditionNode.release(); 00249 stmtNodes.release(); 00250 return getNode(new WhileStmt(loc, pred, body)); 00251 } 00252 00253 Node TypeCheck::acceptLoopStmt(Location loc, NodeVector &stmtNodes) 00254 { 00255 typedef NodeCaster<Stmt> caster; 00256 typedef llvm::mapped_iterator<NodeVector::iterator, caster> iterator; 00257 00258 iterator I(stmtNodes.begin(), caster()); 00259 iterator E(stmtNodes.end(), caster()); 00260 StmtSequence *body = new StmtSequence(loc, I, E); 00261 00262 stmtNodes.release(); 00263 return getNode(new LoopStmt(loc, body)); 00264 } 00265 00266 Node TypeCheck::beginForStmt(Location loc, 00267 IdentifierInfo *iterName, Location iterLoc, 00268 Node controlNode, bool isReversed) 00269 { 00270 DSTDefinition *control = cast_node<DSTDefinition>(controlNode); 00271 DiscreteType *iterTy = control->getType(); 00272 LoopDecl *iter = new LoopDecl(iterName, iterTy, iterLoc); 00273 ForStmt *loop = new ForStmt(loc, iter, control); 00274 00275 if (isReversed) 00276 loop->markAsReversed(); 00277 00278 // Push a scope for the for loop and then add the loop parameter. 00279 scope.push(); 00280 scope.addDirectDecl(iter); 00281 controlNode.release(); 00282 return getNode(loop); 00283 } 00284 00285 Node TypeCheck::endForStmt(Node forNode, NodeVector &bodyNodes) 00286 { 00287 // Pop the scope we entered for this loop. 00288 scope.pop(); 00289 00290 // It is possible that the body is empty due to parse/semantic errors. Do 00291 // not construct empty for loops. 00292 if (bodyNodes.empty()) 00293 return getInvalidNode(); 00294 00295 // There is nothing to do but embed the body statements into the for loop. 00296 bodyNodes.release(); 00297 ForStmt *loop = cast_node<ForStmt>(forNode); 00298 StmtSequence *body = loop->getBody(); 00299 00300 NodeVector::iterator I = bodyNodes.begin(); 00301 NodeVector::iterator E = bodyNodes.end(); 00302 for ( ; I != E; ++I) { 00303 Stmt *S = cast_node<Stmt>(*I); 00304 body->addStmt(S); 00305 } 00306 00307 // Just reuse the given forNode as it now references the updated AST. 00308 return forNode; 00309 } 00310 00311 Node TypeCheck::acceptPragmaStmt(IdentifierInfo *name, Location loc, 00312 NodeVector &argNodes) 00313 { 00314 Pragma *pragma = 0; 00315 00316 // The only pragma we currently support is "Assert". 00317 if (name == resource.getIdentifierInfo("Assert")) 00318 pragma = acceptPragmaAssert(loc, argNodes); 00319 else { 00320 // The parser knows all about pragmas, so we should always have a match. 00321 assert(pragma && "Unrecognized pragma!"); 00322 } 00323 00324 if (pragma) { 00325 argNodes.release(); 00326 return getNode(new PragmaStmt(pragma)); 00327 } 00328 else 00329 return getInvalidNode(); 00330 } 00331 00332 Node TypeCheck::acceptRaiseStmt(Location raiseLoc, Node exceptionNode, 00333 Node messageNode) 00334 { 00335 ExceptionRef *ref = lift_node<ExceptionRef>(exceptionNode); 00336 Expr *message = 0; 00337 00338 if (!ref) { 00339 report(getNodeLoc(exceptionNode), diag::NOT_AN_EXCEPTION); 00340 return getInvalidNode(); 00341 } 00342 00343 if (!messageNode.isNull()) { 00344 Expr *expr = ensureExpr(messageNode); 00345 ArrayType *theStringType = resource.getTheStringType(); 00346 if (!expr || !(expr = checkExprInContext(expr, theStringType))) 00347 return getInvalidNode(); 00348 message = expr; 00349 } 00350 00351 exceptionNode.release(); 00352 messageNode.release(); 00353 RaiseStmt *raise = new RaiseStmt(raiseLoc, ref, message); 00354 return getNode(raise); 00355 } 00356 00357 Node TypeCheck::beginHandlerStmt(Location loc, NodeVector &choiceNodes) 00358 { 00359 typedef NodeLifter<ExceptionRef> lifter; 00360 typedef llvm::mapped_iterator<NodeVector::iterator, lifter> iterator; 00361 00362 typedef llvm::SmallVector<ExceptionRef*, 8> ChoiceVec; 00363 ChoiceVec choices; 00364 00365 // Simply ensure that all choices resolve to ExceptionRef's. 00366 bool allOK = true; 00367 iterator I(choiceNodes.begin(), lifter()); 00368 iterator E(choiceNodes.end(), lifter()); 00369 for ( ; I != E; ++I) { 00370 if (ExceptionRef *ref = *I) 00371 choices.push_back(ref); 00372 else { 00373 report(getNodeLoc(*I.getCurrent()), diag::NOT_AN_EXCEPTION); 00374 allOK = false; 00375 } 00376 } 00377 if (!allOK) 00378 return getInvalidNode(); 00379 00380 choiceNodes.release(); 00381 HandlerStmt *handler = new HandlerStmt(loc, choices.data(), choices.size()); 00382 return getNode(handler); 00383 } 00384 00385 void TypeCheck::endHandlerStmt(Node context, Node handlerNode) 00386 { 00387 StmtSequence *handledSequence; 00388 HandlerStmt *handler = cast_node<HandlerStmt>(handlerNode); 00389 00390 // The only valid context for handlers are block and subroutine 00391 // declarations. 00392 if (SubroutineDecl *SR = lift_node<SubroutineDecl>(context)) 00393 handledSequence = SR->getBody(); 00394 else 00395 handledSequence = cast_node<BlockStmt>(context); 00396 00397 handlerNode.release(); 00398 handledSequence->addHandler(handler); 00399 } 00400 00401 Node TypeCheck::acceptNullStmt(Location loc) 00402 { 00403 return getNode(new NullStmt(loc)); 00404 }