00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00013 
00014 
00015 #ifndef COMMA_AST_SUBROUTINECALL_HDR_GUARD
00016 #define COMMA_AST_SUBROUTINECALL_HDR_GUARD
00017 
00018 #include "comma/ast/AstBase.h"
00019 #include "comma/ast/SubroutineRef.h"
00020 
00021 namespace comma {
00022 
00028 class SubroutineCall {
00029 
00030 public:
00040     SubroutineCall(SubroutineRef *connective,
00041                    Expr **positionalArgs, unsigned numPositional,
00042                    KeywordSelector **keyedArgs, unsigned numKeys);
00043 
00046     SubroutineCall(SubroutineDecl *connective,
00047                    Expr **positionalArgs, unsigned numPositional,
00048                    KeywordSelector **keyedArgs, unsigned numKeys);
00049 
00050     virtual ~SubroutineCall();
00051 
00053     bool isaFunctionCall() const;
00054 
00056     bool isaProcedureCall() const;
00057 
00059     bool denotesOperator() const;
00060 
00062 
00063     FunctionCallExpr *asFunctionCall();
00064     const FunctionCallExpr *asFunctionCall() const;
00066 
00068 
00069     ProcedureCallStmt *asProcedureCall();
00070     const ProcedureCallStmt *asProcedureCall() const;
00072 
00074     virtual Location getLocation() const = 0;
00075 
00077     bool isAmbiguous() const {
00078         return connective->isOverloaded() || connective->empty();
00079     }
00080 
00082     bool isUnambiguous() const { return !isAmbiguous(); }
00083 
00089     bool isPrimitive() const {
00090         return isUnambiguous() && getConnective()->isPrimitive();
00091     }
00092 
00094     bool isAttributeCall() const;
00095 
00102 
00103 
00109     bool isLocalCall() const;
00110 
00115     bool isDirectCall() const;
00116 
00121     bool isAbstractCall() const;
00122 
00127     bool isForeignCall() const;
00129 
00146     virtual void resolveConnective(SubroutineDecl *connective);
00147 
00150     unsigned getNumArgs() const { return numPositional + numKeys; }
00151 
00153     unsigned getNumPositionalArgs() const { return numPositional; }
00154 
00156     unsigned getNumKeyedArgs() const { return numKeys; }
00157 
00159     bool containsConnective(SubroutineType *srTy) const {
00160         return connective->contains(srTy);
00161     }
00162 
00164     unsigned numConnectives() const { return connective->numDeclarations(); }
00165 
00167 
00168     const SubroutineDecl *getConnective(unsigned i) const {
00169         return connective->getDeclaration(i);
00170     }
00171     SubroutineDecl *getConnective(unsigned i) {
00172         return connective->getDeclaration(i);
00173     }
00175 
00177 
00178 
00179 
00180     SubroutineDecl *getConnective() {
00181         assert(isUnambiguous() &&
00182                "No unique connective associated with this call!");
00183         return connective->getDeclaration(0);
00184     }
00185 
00186     const SubroutineDecl *getConnective() const {
00187         assert(isUnambiguous() &&
00188                "No unique connective associated with this call!");
00189         return connective->getDeclaration(0);
00190     }
00192 
00194 
00195 
00196     typedef SubroutineRef::iterator connective_iterator;
00197     connective_iterator begin_connectives() { return connective->begin(); }
00198     connective_iterator end_connectives() { return connective->end(); }
00199 
00200     typedef SubroutineRef::const_iterator const_connective_iterator;
00201     const_connective_iterator begin_connectives() const {
00202         return connective->begin();
00203     }
00204     const_connective_iterator end_connectives() const {
00205         return connective->end();
00206     }
00208 
00221 
00222     typedef Expr **arg_iterator;
00223     arg_iterator begin_arguments() {
00224         assert(isUnambiguous() &&
00225                "Cannot iterate over the arguments of an ambiguous call expr!");
00226         return arguments ? &arguments[0] : 0;
00227     }
00228     arg_iterator end_arguments() {
00229         assert(isUnambiguous() &&
00230                "Cannot iterate over the arguments of an ambiguous call expr!");
00231         return arguments ? &arguments[getNumArgs()] : 0;
00232     }
00233 
00234     typedef const Expr *const *const_arg_iterator;
00235     const_arg_iterator begin_arguments() const {
00236         assert(isUnambiguous() &&
00237                "Cannot iterate over the arguments of an ambiguous call expr!");
00238         return arguments ? &arguments[0] : 0;
00239     }
00240     const_arg_iterator end_arguments() const {
00241         assert(isUnambiguous() &&
00242                "Cannot iterate over the arguments of an ambiguous call expr!");
00243         return arguments ? &arguments[getNumArgs()] : 0;
00244     }
00246 
00253 
00254     arg_iterator begin_positional() {
00255         return numPositional ? &arguments[0] : 0;
00256     }
00257     arg_iterator end_positional() {
00258         return numPositional ? &arguments[numPositional] : 0;
00259     }
00260 
00261     const_arg_iterator begin_positional() const {
00262         return numPositional ? &arguments[0] : 0;
00263     }
00264     const_arg_iterator end_positional() const {
00265         return numPositional ? &arguments[numPositional] : 0;
00266     }
00268 
00276 
00277     typedef KeywordSelector **key_iterator;
00278     key_iterator begin_keys() { return numKeys ? &keyedArgs[0] : 0; }
00279     key_iterator end_keys() { return numKeys ? &keyedArgs[numKeys] : 0; }
00280 
00281     typedef KeywordSelector *const *const_key_iterator;
00282     const_key_iterator begin_keys() const {
00283         return numKeys ? &keyedArgs[0] : 0;
00284     }
00285     const_key_iterator end_keys() const {
00286         return numKeys ? &keyedArgs[numKeys] : 0;
00287     }
00289 
00291 
00292     void setArgument(arg_iterator I, Expr *expr);
00293     void setArgument(key_iterator I, Expr *expr);
00295 
00297     Ast *asAst();
00298     const Ast *asAst() const;
00299 
00300     
00301     static bool classof(const Ast *node) {
00302         Ast::AstKind kind = node->getKind();
00303         return (kind == Ast::AST_FunctionCallExpr ||
00304                 kind == Ast::AST_ProcedureCallStmt);
00305     }
00306     static bool classof(const FunctionCallExpr *node) { return true; }
00307     static bool classof(const ProcedureCallStmt *node) { return true; }
00308 
00309 protected:
00310     SubroutineRef *connective;
00311     Expr **arguments;
00312     KeywordSelector **keyedArgs;
00313     unsigned numPositional;
00314     unsigned numKeys;
00315 
00318     bool isCompatible(SubroutineDecl *decl) const;
00319 
00322     int argExprIndex(Expr *expr) const;
00323 
00326     int keyExprIndex(Expr *expr) const;
00327 
00328 private:
00330     void initializeArguments(Expr **posArgs, unsigned numPos,
00331                              KeywordSelector **keyArgs, unsigned numKeys);
00332 
00334     void propagateKeyedArguments();
00335 };
00336 
00337 } 
00338 
00339 namespace llvm {
00340 
00341 
00342 template<class To>
00343 struct isa_impl_wrap<To,
00344                      const comma::SubroutineCall, const comma::SubroutineCall> {
00345     static bool doit(const comma::SubroutineCall &val) {
00346         return To::classof(val.asAst());
00347     }
00348 };
00349 
00350 template<class To>
00351 struct isa_impl_wrap<To, comma::SubroutineCall, comma::SubroutineCall>
00352   : public isa_impl_wrap<To,
00353                          const comma::SubroutineCall,
00354                          const comma::SubroutineCall> { };
00355 
00356 
00357 template<class From>
00358 struct cast_convert_val<comma::SubroutineCall, From, From> {
00359     static comma::SubroutineCall &doit(const From &val) {
00360         const From *ptr = &val;
00361         return (dyn_cast<comma::FunctionCallExpr>(ptr) ||
00362                 dyn_cast<comma::ProcedureCallStmt>(ptr));
00363     }
00364 };
00365 
00366 template<class From>
00367 struct cast_convert_val<comma::SubroutineCall, From*, From*> {
00368     static comma::SubroutineCall *doit(const From *val) {
00369         return (dyn_cast<comma::FunctionCallExpr>(val) ||
00370                 dyn_cast<comma::ProcedureCallStmt>(val));
00371     }
00372 };
00373 
00374 template<class From>
00375 struct cast_convert_val<const comma::SubroutineCall, From, From> {
00376     static const comma::SubroutineCall &doit(const From &val) {
00377         const From *ptr = &val;
00378         return (dyn_cast<comma::FunctionCallExpr>(ptr) ||
00379                 dyn_cast<comma::ProcedureCallStmt>(ptr));
00380     }
00381 };
00382 
00383 template<class From>
00384 struct cast_convert_val<const comma::SubroutineCall, From*, From*> {
00385     static const comma::SubroutineCall *doit(const From *val) {
00386         return (dyn_cast<comma::FunctionCallExpr>(val) ||
00387                 dyn_cast<comma::ProcedureCallStmt>(val));
00388     }
00389 };
00390 
00391 
00392 template<class To>
00393 struct cast_convert_val<To,
00394                         const comma::SubroutineCall,
00395                         const comma::SubroutineCall> {
00396     static To &doit(const comma::SubroutineCall &val) {
00397         return *reinterpret_cast<To*>(
00398             const_cast<comma::Ast*>(val.asAst()));
00399     }
00400 };
00401 
00402 template<class To>
00403 struct cast_convert_val<To, comma::SubroutineCall, comma::SubroutineCall>
00404     : public cast_convert_val<To,
00405                               const comma::SubroutineCall,
00406                               const comma::SubroutineCall> { };
00407 
00408 template<class To>
00409 struct cast_convert_val<To,
00410                         const comma::SubroutineCall*,
00411                         const comma::SubroutineCall*> {
00412     static To *doit(const comma::SubroutineCall *val) {
00413         return reinterpret_cast<To*>(
00414             const_cast<comma::Ast*>(val->asAst()));
00415     }
00416 };
00417 
00418 template<class To>
00419 struct cast_convert_val<To, comma::SubroutineCall*, comma::SubroutineCall*>
00420     : public cast_convert_val<To,
00421                               const comma::SubroutineCall*,
00422                               const comma::SubroutineCall*> { };
00423 
00424 } 
00425 
00426 
00427 #endif