00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "IdentifierResolver.h"
00010 #include "DeclProducer.h"
00011 #include "comma/ast/Decl.h"
00012 #include "comma/ast/Expr.h"
00013 #include "comma/ast/Stmt.h"
00014 #include "comma/ast/Type.h"
00015 #include "comma/typecheck/TypeCheck.h"
00016
00017 #include "llvm/Support/Casting.h"
00018
00019 using namespace comma;
00020 using llvm::dyn_cast;
00021 using llvm::cast;
00022 using llvm::isa;
00023
00024 Node TypeCheck::acceptProcedureName(IdentifierInfo *name,
00025 Location loc,
00026 Node qualNode)
00027 {
00028 if (!qualNode.isNull()) {
00029 Qualifier *qualifier = cast_node<Qualifier>(qualNode);
00030 DeclRegion *region = qualifier->resolve();
00031
00032
00033
00034
00035 typedef DeclRegion::PredRange PredRange;
00036 typedef DeclRegion::PredIter PredIter;
00037 PredRange range = region->findDecls(name);
00038 llvm::SmallVector<SubroutineDecl*, 8> decls;
00039
00040
00041 for (PredIter iter = range.first; iter != range.second; ++iter) {
00042 ProcedureDecl *candidate = dyn_cast<ProcedureDecl>(*iter);
00043 if (candidate)
00044 decls.push_back(candidate);
00045 }
00046
00047 if (decls.empty()) {
00048 report(loc, diag::NAME_NOT_VISIBLE);
00049 return getInvalidNode();
00050 }
00051
00052 if (decls.size() == 1)
00053 return getNode(decls.front());
00054
00055 return getNode(new OverloadedDeclName(&decls[0], decls.size()));
00056 }
00057
00058 IdentifierResolver resolver;
00059
00060 if (!resolver.resolve(name) || resolver.hasDirectValue()) {
00061 report(loc, diag::NAME_NOT_VISIBLE) << name;
00062 return getInvalidNode();
00063 }
00064
00065 llvm::SmallVector<SubroutineDecl *, 8> overloads;
00066 unsigned numOverloads = 0;
00067 resolver.filterFunctionals();
00068
00069
00070 {
00071 typedef IdentifierResolver::DirectOverloadIter iterator;
00072 iterator E = resolver.endDirectOverloads();
00073 for (iterator I = resolver.beginDirectOverloads(); I != E; ++I)
00074 overloads.push_back(cast<ProcedureDecl>(*I));
00075 }
00076
00077
00078
00079 if (!resolver.hasIndirectValues()) {
00080 typedef IdentifierResolver::IndirectOverloadIter iterator;
00081 iterator E = resolver.endIndirectOverloads();
00082 for (iterator I = resolver.beginIndirectOverloads(); I != E; ++I)
00083 overloads.push_back(cast<ProcedureDecl>(*I));
00084 numOverloads = overloads.size();
00085 if (numOverloads == 1)
00086 return getNode(overloads.front());
00087 else if (numOverloads > 1)
00088 return getNode(new OverloadedDeclName(&overloads[0], numOverloads));
00089 else {
00090 report(loc, diag::NAME_NOT_VISIBLE) << name;
00091 return getInvalidNode();
00092 }
00093 }
00094
00095
00096
00097 numOverloads = overloads.size();
00098 if (numOverloads == 1)
00099 return getNode(overloads.front());
00100 else if (numOverloads > 1)
00101 return getNode(new OverloadedDeclName(&overloads[0], numOverloads));
00102
00103
00104 report(loc, diag::NAME_NOT_VISIBLE) << name;
00105 return getInvalidNode();
00106 }
00107
00108 Node TypeCheck::acceptProcedureCall(Node connective,
00109 Location loc,
00110 NodeVector &args)
00111 {
00112 std::vector<SubroutineDecl*> decls;
00113 unsigned targetArity = args.size();
00114
00115 connective.release();
00116
00117 if (ProcedureDecl *pdecl = lift_node<ProcedureDecl>(connective)) {
00118 if (pdecl->getArity() == targetArity)
00119 decls.push_back(pdecl);
00120 else {
00121 report(loc, diag::WRONG_NUM_ARGS_FOR_SUBROUTINE)
00122 << pdecl->getIdInfo();
00123 return getInvalidNode();
00124 }
00125 }
00126 else {
00127 OverloadedDeclName *odn = cast_node<OverloadedDeclName>(connective);
00128 for (OverloadedDeclName::iterator iter = odn->begin();
00129 iter != odn->end(); ++iter) {
00130 if (ProcedureDecl *pdecl = dyn_cast<ProcedureDecl>(*iter)) {
00131 if (pdecl->getArity() == targetArity)
00132 decls.push_back(pdecl);
00133 }
00134 }
00135
00136 delete odn;
00137
00138
00139
00140 if (decls.empty()) {
00141 report(loc, diag::NAME_NOT_VISIBLE) << odn->getIdInfo();
00142 return getInvalidNode();
00143 }
00144 }
00145
00146 return acceptSubroutineCall(decls, loc, args);
00147 }
00148
00149 Node TypeCheck::acceptReturnStmt(Location loc, Node retNode)
00150 {
00151 assert((checkingProcedure() || checkingFunction()) &&
00152 "Return statement outside subroutine context!");
00153
00154 if (checkingFunction()) {
00155 FunctionDecl *fdecl = getCurrentFunction();
00156 Expr *retExpr = cast_node<Expr>(retNode);
00157 Type *targetType = fdecl->getReturnType();
00158
00159 if (checkExprInContext(retExpr, targetType)) {
00160 retNode.release();
00161 return getNode(new ReturnStmt(loc, retExpr));
00162 }
00163 return getInvalidNode();
00164 }
00165
00166 report(loc, diag::NONEMPTY_RETURN_IN_PROCEDURE);
00167 return getInvalidNode();
00168 }
00169
00170 Node TypeCheck::acceptEmptyReturnStmt(Location loc)
00171 {
00172 assert((checkingProcedure() || checkingFunction()) &&
00173 "Return statement outside subroutine context!");
00174
00175 if (checkingProcedure())
00176 return getNode(new ReturnStmt(loc));
00177
00178 report(loc, diag::EMPTY_RETURN_IN_FUNCTION);
00179 return getInvalidNode();
00180 }
00181
00182 Node TypeCheck::acceptAssignmentStmt(Location loc,
00183 IdentifierInfo *name,
00184 Node valueNode)
00185 {
00186 Expr *value = cast_node<Expr>(valueNode);
00187 Homonym *homonym = name->getMetadata<Homonym>();
00188 ValueDecl *targetDecl = 0;
00189
00190 if (!homonym || homonym->empty()) {
00191 report(loc, diag::NAME_NOT_VISIBLE) << name;
00192 return getInvalidNode();
00193 }
00194
00195
00196
00197 for (Homonym::DirectIterator iter = homonym->beginDirectDecls();
00198 iter != homonym->endDirectDecls(); ++iter) {
00199 if ((targetDecl = dyn_cast<ValueDecl>(*iter)))
00200 break;
00201 }
00202
00203 if (!targetDecl) {
00204 report(loc, diag::NAME_NOT_VISIBLE) << name;
00205 return getInvalidNode();
00206 }
00207
00208
00209 if (ParamValueDecl *param = dyn_cast<ParamValueDecl>(targetDecl)) {
00210 if (param->getParameterMode() == PM::MODE_IN) {
00211 report(loc, diag::ASSIGNMENT_TO_MODE_IN) << name;
00212 return getInvalidNode();
00213 }
00214 }
00215
00216 if (checkExprInContext(value, targetDecl->getType())) {
00217 valueNode.release();
00218 DeclRefExpr *ref = new DeclRefExpr(targetDecl, loc);
00219 return getNode(new AssignmentStmt(ref, value));
00220 }
00221
00222 return getInvalidNode();
00223 }
00224
00225 Node TypeCheck::acceptIfStmt(Location loc,
00226 Node conditionNode,
00227 Node *consequentNodes,
00228 unsigned numConsequents)
00229 {
00230 Expr *condition = cast_node<Expr>(conditionNode);
00231
00232 if (checkExprInContext(condition, declProducer->getBoolType())) {
00233 StmtSequence *consequents = new StmtSequence();
00234
00235 for (unsigned i = 0; i < numConsequents; ++i) {
00236 consequents->addStmt(cast_node<Stmt>(consequentNodes[i]));
00237 consequentNodes[i].release();
00238 }
00239 conditionNode.release();
00240 return getNode(new IfStmt(loc, condition, consequents));
00241 }
00242 return getInvalidNode();
00243 }
00244
00245 Node TypeCheck::acceptElseStmt(Location loc, Node ifNode,
00246 Node *alternateNodes, unsigned numAlternates)
00247 {
00248 IfStmt *cond = cast_node<IfStmt>(ifNode);
00249 StmtSequence *alternates = new StmtSequence();
00250
00251 assert(!cond->hasAlternate() && "Multiple else component in IfStmt!");
00252
00253 for (unsigned i = 0; i < numAlternates; ++i) {
00254 alternates->addStmt(cast_node<Stmt>(alternateNodes[i]));
00255 alternateNodes[i].release();
00256 }
00257
00258 cond->setAlternate(loc, alternates);
00259 return ifNode;
00260 }
00261
00262 Node TypeCheck::acceptElsifStmt(Location loc,
00263 Node ifNode,
00264 Node conditionNode,
00265 Node *consequentNodes,
00266 unsigned numConsequents)
00267 {
00268 IfStmt *cond = cast_node<IfStmt>(ifNode);
00269 Expr *condition = cast_node<Expr>(conditionNode);
00270
00271 if (checkExprInContext(condition, declProducer->getBoolType())) {
00272 StmtSequence *consequents = new StmtSequence();
00273 for (unsigned i = 0; i < numConsequents; ++i) {
00274 consequents->addStmt(cast_node<Stmt>(consequentNodes[i]));
00275 consequentNodes[i].release();
00276 }
00277 conditionNode.release();
00278 cond->addElsif(loc, condition, consequents);
00279 return ifNode;
00280 }
00281 return getInvalidNode();
00282 }
00283
00284
00285 Node TypeCheck::beginBlockStmt(Location loc, IdentifierInfo *label)
00286 {
00287
00288 DeclRegion *region = currentDeclarativeRegion();
00289 BlockStmt *block = new BlockStmt(loc, region, label);
00290
00291 declarativeRegion = block;
00292 scope.push();
00293 return getNode(block);
00294 }
00295
00296
00297 void TypeCheck::acceptBlockStmt(Node blockNode, Node stmtNode)
00298 {
00299 BlockStmt *block = cast_node<BlockStmt>(blockNode);
00300 Stmt *stmt = cast_node<Stmt>(stmtNode);
00301 block->addStmt(stmt);
00302 stmtNode.release();
00303 }
00304
00305
00306
00307
00308 void TypeCheck::endBlockStmt(Node blockNode)
00309 {
00310 declarativeRegion = currentDeclarativeRegion()->getParent();
00311 scope.pop();
00312 }