This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- ast/SubroutineCall.cpp -------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009-2010, Stephen Wilson 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 // FIXME: It would be nice to have a representation where a resolved call 00032 // disposes of the reference node and replaces it directly with the declaration. 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 // Fill in the argument vector with any keyed expressions, sorted so that 00071 // they match what the connective requires. 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 // FIXME: Traverse the argument list and free each expression. 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 // If the declarative region maps to an add or a percent decl then this is a 00233 // local call. 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 }