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 }