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 }