00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "comma/ast/AttribDecl.h"
00010 #include "comma/ast/Expr.h"
00011 #include "comma/ast/KeywordSelector.h"
00012 #include "comma/ast/Stmt.h"
00013 #include "comma/ast/SubroutineCall.h"
00014 #include "comma/basic/PrimitiveOps.h"
00015
00016 using namespace comma;
00017 using llvm::dyn_cast;
00018 using llvm::cast;
00019 using llvm::isa;
00020
00021 SubroutineCall::SubroutineCall(SubroutineRef *connective,
00022 Expr **posArgs, unsigned numPos,
00023 KeywordSelector **keyArgs, unsigned numKeys)
00024 : connective(connective),
00025 numPositional(numPos),
00026 numKeys(numKeys)
00027 {
00028 initializeArguments(posArgs, numPos, keyArgs, numKeys);
00029 }
00030
00031
00032
00033 SubroutineCall::SubroutineCall(SubroutineDecl *connective,
00034 Expr **posArgs, unsigned numPos,
00035 KeywordSelector **keyArgs, unsigned numKeys)
00036 : connective(new SubroutineRef(0, connective)),
00037 numPositional(numPos),
00038 numKeys(numKeys)
00039 {
00040 initializeArguments(posArgs, numPos, keyArgs, numKeys);
00041 }
00042
00043 void
00044 SubroutineCall::initializeArguments(Expr **posArgs, unsigned numPos,
00045 KeywordSelector **keyArgs, unsigned numKeys)
00046 {
00047 unsigned numArgs = numPositional + numKeys;
00048
00049 if (numArgs) {
00050 arguments = new Expr*[numArgs];
00051 std::copy(posArgs, posArgs + numPos, arguments);
00052 std::fill(arguments + numPos, arguments + numArgs, (Expr*)0);
00053 }
00054 else
00055 arguments = 0;
00056
00057 if (numKeys) {
00058 keyedArgs = new KeywordSelector*[numKeys];
00059 std::copy(keyArgs, keyArgs + numKeys, keyedArgs);
00060 }
00061 else
00062 keyedArgs = 0;
00063
00064 if (isUnambiguous())
00065 propagateKeyedArguments();
00066 }
00067
00068 void SubroutineCall::propagateKeyedArguments()
00069 {
00070
00071
00072 for (unsigned i = 0; i < numKeys; ++i) {
00073 KeywordSelector *selector = keyedArgs[i];
00074 IdentifierInfo *key = selector->getKeyword();
00075 Expr *expr = selector->getExpression();
00076 int indexResult = getConnective()->getKeywordIndex(key);
00077
00078 assert(indexResult >= 0 && "Could not resolve keyword index!");
00079
00080 unsigned argIndex = unsigned(indexResult);
00081 assert(argIndex >= numPositional &&
00082 "Keyword resolved to a positional index!");
00083 assert(argIndex < getNumArgs() && "Keyword index too large!");
00084 assert(arguments[argIndex] == 0 && "Duplicate keywords!");
00085
00086 arguments[argIndex] = expr;
00087 }
00088 }
00089
00090 SubroutineCall::~SubroutineCall()
00091 {
00092
00093 delete connective;
00094 delete[] arguments;
00095 delete[] keyedArgs;
00096 }
00097
00098 bool SubroutineCall::isaFunctionCall() const
00099 {
00100 return isa<FunctionCallExpr>(this);
00101 }
00102
00103 bool SubroutineCall::isaProcedureCall() const
00104 {
00105 return isa<ProcedureCallStmt>(this);
00106 }
00107
00108 bool SubroutineCall::denotesOperator() const
00109 {
00110 if (isaFunctionCall() && isUnambiguous()) {
00111 IdentifierInfo *idInfo = getConnective()->getIdInfo();
00112 return PO::denotesOperator(idInfo);
00113 }
00114 return false;
00115 }
00116
00117 FunctionCallExpr *SubroutineCall::asFunctionCall()
00118 {
00119 return dyn_cast<FunctionCallExpr>(this);
00120 }
00121
00122 const FunctionCallExpr *SubroutineCall::asFunctionCall() const
00123 {
00124 return dyn_cast<FunctionCallExpr>(this);
00125 }
00126
00127 ProcedureCallStmt *SubroutineCall::asProcedureCall()
00128 {
00129 return dyn_cast<ProcedureCallStmt>(this);
00130 }
00131
00132 const ProcedureCallStmt *SubroutineCall::asProcedureCall() const
00133 {
00134 return dyn_cast<ProcedureCallStmt>(this);
00135 }
00136
00137 Ast *SubroutineCall::asAst()
00138 {
00139 if (connective->referencesFunctions())
00140 return static_cast<FunctionCallExpr*>(this);
00141 else if (connective->referencesProcedures())
00142 return static_cast<ProcedureCallStmt*>(this);
00143 else {
00144 assert(false && "Cannot infer AST type!");
00145 return 0;
00146 }
00147 }
00148
00149 const Ast *SubroutineCall::asAst() const
00150 {
00151 return const_cast<SubroutineCall*>(this)->asAst();
00152 }
00153
00154 bool SubroutineCall::isCompatible(SubroutineDecl *decl) const
00155 {
00156 if (isa<FunctionDecl>(decl))
00157 return isaFunctionCall();
00158 else
00159 return isaProcedureCall();
00160 }
00161
00162 void SubroutineCall::resolveConnective(SubroutineDecl *decl)
00163 {
00164 assert(isCompatible(decl) &&
00165 "Subroutine not compatible with this kind of call!");
00166 assert(decl->getArity() == getNumArgs() && "Arity mismatch!");
00167
00168 connective->resolve(decl);
00169 propagateKeyedArguments();
00170 }
00171
00172 int SubroutineCall::argExprIndex(Expr *expr) const
00173 {
00174 unsigned numArgs = getNumArgs();
00175 for (unsigned i = 0; i < numArgs; ++i)
00176 if (arguments[i] == expr)
00177 return i;
00178 return -1;
00179 }
00180
00181 int SubroutineCall::keyExprIndex(Expr *expr) const
00182 {
00183 for (unsigned i = 0; i < numKeys; ++i)
00184 if (keyedArgs[i]->getExpression() == expr)
00185 return i;
00186 return -1;
00187 }
00188
00189 void SubroutineCall::setArgument(arg_iterator I, Expr *expr)
00190 {
00191 int index = argExprIndex(*I);
00192 assert(index >= 0 && "Iterator does not point to an argument!");
00193
00194 arguments[index] = expr;
00195
00196 if ((index = keyExprIndex(*I)) >= 0)
00197 keyedArgs[index]->setRHS(expr);
00198 }
00199
00200 void SubroutineCall::setArgument(key_iterator I, Expr *expr)
00201 {
00202 Expr *target = (*I)->getExpression();
00203 int index = keyExprIndex(target);
00204 assert(index >= 0 && "Iterator does not point to an argument!");
00205
00206 keyedArgs[index]->setRHS(expr);
00207
00208 if ((index = argExprIndex(target)) >= 0)
00209 arguments[index] = expr;
00210 }
00211
00212 bool SubroutineCall::isAttributeCall() const
00213 {
00214 return isUnambiguous() && isa<FunctionAttribDecl>(getConnective());
00215 }
00216
00217 bool SubroutineCall::isDirectCall() const
00218 {
00219 if (isAmbiguous())
00220 return false;
00221
00222 const SubroutineDecl *decl = getConnective();
00223 const DeclRegion *region = decl->getDeclRegion();
00224 return isa<DomainInstanceDecl>(region);
00225 }
00226
00227 bool SubroutineCall::isLocalCall() const
00228 {
00229 if (isAmbiguous())
00230 return false;
00231
00232
00233
00234 const SubroutineDecl *decl = getConnective();
00235 const DeclRegion *region = decl->getDeclRegion();
00236 return isa<AddDecl>(region) || isa<PercentDecl>(region);
00237 }
00238
00239 bool SubroutineCall::isAbstractCall() const
00240 {
00241 if (isAmbiguous())
00242 return false;
00243
00244 const SubroutineDecl *decl = getConnective();
00245 const DeclRegion *region = decl->getDeclRegion();
00246 return isa<AbstractDomainDecl>(region);
00247 }
00248
00249 bool SubroutineCall::isForeignCall() const
00250 {
00251 if (isAmbiguous())
00252 return false;
00253
00254 const SubroutineDecl *srDecl = getConnective();
00255 return srDecl->hasPragma(pragma::Import);
00256 }