00001
00002
00003
00004
00005
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
00033 if (lift_node<ProcedureCallStmt>(name)) {
00034 name.release();
00035 return name;
00036 }
00037
00038
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
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
00106 report(loc, diag::INVALID_TARGET_FOR_ASSIGNMENT);
00107 return getInvalidNode();
00108 }
00109
00110
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
00182 Node TypeCheck::beginBlockStmt(Location loc, IdentifierInfo *label)
00183 {
00184
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
00194
00195
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
00217
00218
00219
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
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
00288 scope.pop();
00289
00290
00291
00292 if (bodyNodes.empty())
00293 return getInvalidNode();
00294
00295
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
00308 return forNode;
00309 }
00310
00311 Node TypeCheck::acceptPragmaStmt(IdentifierInfo *name, Location loc,
00312 NodeVector &argNodes)
00313 {
00314 Pragma *pragma = 0;
00315
00316
00317 if (name == resource.getIdentifierInfo("Assert"))
00318 pragma = acceptPragmaAssert(loc, argNodes);
00319 else {
00320
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
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
00391
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 }