Ignore:
Timestamp:
Oct 19, 2022, 4:43:26 PM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
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.
Message:

Merge branch 'master' into pthread-emulation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Inspect.cpp

    r9cd5bd2 rdf6cc9d  
    1010// Created On       : Fri Jun 24 13:16:31 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun 27 15:35:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Mon Oct  3 11:04:00 2022
     13// Update Count     : 3
    1414//
    1515
    16 #include "AST/Decl.hpp"
    17 #include "AST/Type.hpp"
     16#include "Inspect.hpp"
    1817
    1918#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"
    2127
    2228namespace ast {
     29
     30const 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
     42template<typename CallExpr, typename Ret>
     43static 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
     51static 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
     72const 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.
     85static 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
     108std::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
     119template<typename CallExpr>
     120static 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
     129const 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}
    23147
    24148bool structHasFlexibleArray( const ast::StructDecl * decl ) {
     
    33157}
    34158
     159const 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
    35170} // namespace ast
Note: See TracChangeset for help on using the changeset viewer.