Changeset df6cc9d for src/AST/Inspect.cpp
- Timestamp:
- Oct 19, 2022, 4:43:26 PM (3 years ago)
- Branches:
- ADT, ast-experimental, master
- Children:
- 1a45263
- Parents:
- 9cd5bd2 (diff), 135143ba (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Inspect.cpp
r9cd5bd2 rdf6cc9d 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jun 27 15:35:00 202213 // Update Count : 112 // Last Modified On : Mon Oct 3 11:04:00 2022 13 // Update Count : 3 14 14 // 15 15 16 #include "AST/Decl.hpp" 17 #include "AST/Type.hpp" 16 #include "Inspect.hpp" 18 17 19 18 #include <iostream> 20 #include <AST/Print.hpp> 19 #include <iterator> 20 21 #include "AST/Decl.hpp" 22 #include "AST/Expr.hpp" 23 #include "AST/Print.hpp" 24 #include "AST/Stmt.hpp" 25 #include "AST/Type.hpp" 26 #include "CodeGen/OperatorTable.h" 21 27 22 28 namespace ast { 29 30 const Type * getPointerBase( const Type * type ) { 31 if ( const auto * p = dynamic_cast< const PointerType * >( type ) ) { 32 return p->base; 33 } else if ( auto a = dynamic_cast< const ArrayType * >( type ) ) { 34 return a->base; 35 } else if ( auto r = dynamic_cast< const ReferenceType * >( type ) ) { 36 return r->base; 37 } else { 38 return nullptr; 39 } 40 } 41 42 template<typename CallExpr, typename Ret> 43 static Ret throughDeref( const CallExpr * expr, Ret(*func)( const Expr * ) ) { 44 // In `(*f)(x)` the function we want is `f`. 45 std::string name = getFunctionName( expr ); 46 assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() ); 47 assertf( !expr->args.empty(), "Cannot pass through dereference with no arguments." ); 48 return func( expr->args.front() ); 49 } 50 51 static const DeclWithType * getCalledFunction( const Expr * expr ) { 52 assert( expr ); 53 if ( const auto * varExpr = dynamic_cast< const VariableExpr * >( expr ) ) { 54 return varExpr->var; 55 } else if ( auto memberExpr = dynamic_cast< const MemberExpr * >( expr ) ) { 56 return memberExpr->member; 57 } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) { 58 return getCalledFunction( castExpr->arg ); 59 } else if ( auto untypedExpr = dynamic_cast< const UntypedExpr * >( expr ) ) { 60 return throughDeref( untypedExpr, getCalledFunction ); 61 } else if ( auto appExpr = dynamic_cast< const ApplicationExpr * > ( expr ) ) { 62 return throughDeref( appExpr, getCalledFunction ); 63 } else if ( auto addrExpr = dynamic_cast< const AddressExpr * >( expr ) ) { 64 return getCalledFunction( addrExpr->arg ); 65 } else if ( auto commaExpr = dynamic_cast< const CommaExpr * >( expr ) ) { 66 return getCalledFunction( commaExpr->arg2 ); 67 } else { 68 return nullptr; 69 } 70 } 71 72 const DeclWithType * getFunction( const Expr * expr ) { 73 if ( auto app = dynamic_cast< const ApplicationExpr * >( expr ) ) { 74 return getCalledFunction( app->func ); 75 } else if ( auto untyped = dynamic_cast< const UntypedExpr * >( expr ) ) { 76 return getCalledFunction( untyped->func ); 77 } else { 78 assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() ); 79 } 80 } 81 82 // There is a lot of overlap with getCalledFunction. Ideally it would use 83 // it as a helper function and return the name of the DeclWithType. But the 84 // NameExpr and UntypedMemberExpr only work on this version. 85 static std::string funcName( const Expr * func ) { 86 assert( func ); 87 if ( const auto * nameExpr = dynamic_cast< const NameExpr * >( func ) ) { 88 return nameExpr->name; 89 } else if ( auto varExpr = dynamic_cast< const VariableExpr * >( func ) ) { 90 return varExpr->var->name; 91 } else if ( auto castExpr = dynamic_cast< const CastExpr * >( func ) ) { 92 return funcName( castExpr->arg ); 93 } else if ( auto memberExpr = dynamic_cast< const MemberExpr * >( func ) ) { 94 return memberExpr->member->name; 95 } else if ( auto memberExpr = dynamic_cast< const UntypedMemberExpr * >( func ) ) { 96 return funcName( memberExpr->member ); 97 } else if ( auto untypedExpr = dynamic_cast< const UntypedExpr * >( func ) ) { 98 return throughDeref( untypedExpr, funcName ); 99 } else if ( auto appExpr = dynamic_cast< const ApplicationExpr * >( func ) ) { 100 return throughDeref( appExpr, funcName ); 101 } else if ( auto ctorExpr = dynamic_cast< const ConstructorExpr * >( func ) ) { 102 return funcName( getCallArg( ctorExpr->callExpr, 0 ) ); 103 } else { 104 assertf( false, "Unexpected expression type being called as a function in call expression: %s", toString( func ).c_str() ); 105 } 106 } 107 108 std::string getFunctionName( const Expr * expr ) { 109 // There's some unforunate overlap here with getFunction. See above. 110 if ( auto app = dynamic_cast< const ApplicationExpr * >( expr ) ) { 111 return funcName( app->func ); 112 } else if ( auto untyped = dynamic_cast< const UntypedExpr * >( expr ) ) { 113 return funcName( untyped->func ); 114 } else { 115 assertf( false, "getFunctionName received unknown expression: %s", toString( expr ).c_str() ); 116 } 117 } 118 119 template<typename CallExpr> 120 static const Expr * callArg( const CallExpr * call, unsigned int pos ) { 121 assertf( pos < call->args.size(), 122 "callArg for argument that doesn't exist: (%u); %s.", 123 pos, toString( call ).c_str() ); 124 auto it = call->args.begin(); 125 std::advance( it, pos ); 126 return *it; 127 } 128 129 const Expr * getCallArg( const Expr * call, unsigned int pos ) { 130 if ( auto app = dynamic_cast< const ApplicationExpr * >( call ) ) { 131 return callArg( app, pos ); 132 } else if ( auto untyped = dynamic_cast< const UntypedExpr * >( call ) ) { 133 return callArg( untyped, pos ); 134 } else if ( auto tupleAssn = dynamic_cast< const TupleAssignExpr * >( call ) ) { 135 const std::list<ptr<Stmt>>& stmts = tupleAssn->stmtExpr->stmts->kids; 136 assertf( !stmts.empty(), "TupleAssignExpr missing statements." ); 137 auto stmt = stmts.back().strict_as< ExprStmt >(); 138 auto tuple = stmt->expr.strict_as< TupleExpr >(); 139 assertf( !tuple->exprs.empty(), "TupleAssignExpr has empty tuple expr." ); 140 return getCallArg( tuple->exprs.front(), pos ); 141 } else if ( auto ctor = dynamic_cast< const ImplicitCopyCtorExpr * >( call ) ) { 142 return getCallArg( ctor->callExpr, pos ); 143 } else { 144 assertf( false, "Unexpected expression type passed to getCallArg: %s", toString( call ).c_str() ); 145 } 146 } 23 147 24 148 bool structHasFlexibleArray( const ast::StructDecl * decl ) { … … 33 157 } 34 158 159 const ApplicationExpr * isIntrinsicCallExpr( const Expr * expr ) { 160 auto appExpr = dynamic_cast< const ApplicationExpr * >( expr ); 161 if ( !appExpr ) return nullptr; 162 163 const DeclWithType * func = getCalledFunction( appExpr->func ); 164 assertf( func, "getCalledFunction returned nullptr: %s", 165 toString( appExpr->func ).c_str() ); 166 167 return func->linkage == Linkage::Intrinsic ? appExpr : nullptr; 168 } 169 35 170 } // namespace ast
Note:
See TracChangeset
for help on using the changeset viewer.