Ignore:
Timestamp:
Sep 22, 2022, 2:23:18 PM (21 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, master
Children:
5d8dae7
Parents:
0bd46fd
Message:

Moved some functions from InitTweak? to Inspect.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Inspect.cpp

    r0bd46fd re01eb4a  
    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 : Wed Sep 22 13:50:00 2022
     13// Update Count     : 2
    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
     20#include "AST/Decl.hpp"
     21#include "AST/Expr.hpp"
     22#include "AST/Print.hpp"
     23#include "AST/Stmt.hpp"
     24#include "AST/Type.hpp"
     25#include "CodeGen/OperatorTable.h"
    2126
    2227namespace ast {
     28
     29const Type * getPointerBase( const Type * t ) {
     30        if ( const auto * p = dynamic_cast< const PointerType * >( t ) ) {
     31                return p->base;
     32        } else if ( const auto * a = dynamic_cast< const ArrayType * >( t ) ) {
     33                return a->base;
     34        } else if ( const auto * r = dynamic_cast< const ReferenceType * >( t ) ) {
     35                return r->base;
     36        } else {
     37                return nullptr;
     38        }
     39}
     40
     41template<typename CallExpr>
     42static const Expr * callArg( const CallExpr * call, unsigned int pos ) {
     43        assertf( pos < call->args.size(),
     44                "getCallArg for argument that doesn't exist: (%u); %s.",
     45                pos, toString( call ).c_str() );
     46        for ( const Expr * arg : call->args ) {
     47                if ( 0 == pos ) return arg;
     48                --pos;
     49        }
     50        assert( false );
     51}
     52
     53template<typename CallExpr, typename Ret>
     54static Ret throughDeref( const CallExpr * expr, Ret(*func)( const Expr * ) ) {
     55        // In `(*f)(x)` the function we want is `f`.
     56        std::string name = getFunctionName( expr );
     57        assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
     58        assertf( !expr->args.empty(), "Cannot get function name from dereference with no arguments" );
     59        return func( expr->args.front() );
     60}
     61
     62static const DeclWithType * getCalledFunction( const Expr * expr ) {
     63        assert( expr );
     64        if ( const ast::VariableExpr * varExpr = dynamic_cast< const ast::VariableExpr * >( expr ) ) {
     65                return varExpr->var;
     66        } else if ( const ast::MemberExpr * memberExpr = dynamic_cast< const ast::MemberExpr * >( expr ) ) {
     67                return memberExpr->member;
     68        } else if ( const ast::CastExpr * castExpr = dynamic_cast< const ast::CastExpr * >( expr ) ) {
     69                return getCalledFunction( castExpr->arg );
     70        } else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * >( expr ) ) {
     71                return throughDeref( untypedExpr, getCalledFunction );
     72        } else if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * > ( expr ) ) {
     73                return throughDeref( appExpr, getCalledFunction );
     74        } else if ( const ast::AddressExpr * addrExpr = dynamic_cast< const ast::AddressExpr * >( expr ) ) {
     75                return getCalledFunction( addrExpr->arg );
     76        } else if ( const ast::CommaExpr * commaExpr = dynamic_cast< const ast::CommaExpr * >( expr ) ) {
     77                return getCalledFunction( commaExpr->arg2 );
     78        }
     79        return nullptr;
     80}
     81
     82const DeclWithType * getFunction( const Expr * expr ) {
     83        if ( auto app = dynamic_cast< const ApplicationExpr * >( expr ) ) {
     84                return getCalledFunction( app->func );
     85        } else if ( auto untyped = dynamic_cast< const UntypedExpr * >( expr ) ) {
     86                return getCalledFunction( untyped->func );
     87        }
     88        assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
     89}
     90
     91// There is a lot of overlap with getCalledFunction. Ideally it would use
     92// it as a helper function and return the name of the DeclWithType. But the
     93// NameExpr and UntypedMemberExpr only work on this version.
     94static std::string funcName( const Expr * func ) {
     95        assert( func );
     96        if ( const ast::NameExpr * nameExpr = dynamic_cast< const ast::NameExpr * >( func ) ) {
     97                return nameExpr->name;
     98        } else if ( const ast::VariableExpr * varExpr = dynamic_cast< const ast::VariableExpr * >( func ) ) {
     99                return varExpr->var->name;
     100        } else if ( const ast::CastExpr * castExpr = dynamic_cast< const ast::CastExpr * >( func ) ) {
     101                return funcName( castExpr->arg );
     102        } else if ( const ast::MemberExpr * memberExpr = dynamic_cast< const ast::MemberExpr * >( func ) ) {
     103                return memberExpr->member->name;
     104        } else if ( const ast::UntypedMemberExpr * memberExpr = dynamic_cast< const ast::UntypedMemberExpr * > ( func ) ) {
     105                return funcName( memberExpr->member );
     106        } else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * >( func ) ) {
     107                return throughDeref( untypedExpr, funcName );
     108        } else if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * >( func ) ) {
     109                return throughDeref( appExpr, funcName );
     110        } else if ( const ast::ConstructorExpr * ctorExpr = dynamic_cast< const ast::ConstructorExpr * >( func ) ) {
     111                return funcName( getCallArg( ctorExpr->callExpr, 0 ) );
     112        } else {
     113                assertf( false, "Unexpected expression type being called as a function in call expression: %s", toString( func ).c_str() );
     114        }
     115}
     116
     117std::string getFunctionName( const Expr * expr ) {
     118        // There's some unforunate overlap here with getCalledFunction. Ideally
     119        // this would be able to use getCalledFunction and return the name of the
     120        // DeclWithType, but this needs to work for NameExpr and UntypedMemberExpr,
     121        // where getCalledFunction can't possibly do anything reasonable.
     122        if ( auto app = dynamic_cast< const ApplicationExpr * >( expr ) ) {
     123                return funcName( app->func );
     124        } else if ( auto untyped = dynamic_cast< const UntypedExpr * >( expr ) ) {
     125                return funcName( untyped->func );
     126        } else {
     127                assertf( false, "Unexpected expression type passed to getFunctionName: %s", toString( expr ).c_str() );
     128        }
     129}
     130
     131const Expr * getCallArg( const Expr * call, unsigned int pos ) {
     132        if ( auto app = dynamic_cast< const ApplicationExpr * >( call ) ) {
     133                return callArg( app, pos );
     134        } else if ( auto untyped = dynamic_cast< const UntypedExpr * >( call ) ) {
     135                return callArg( untyped, pos );
     136        } else if ( auto tupleAssn = dynamic_cast< const TupleAssignExpr * >( call ) ) {
     137                const std::list<ptr<Stmt>>& stmts = tupleAssn->stmtExpr->stmts->kids;
     138                assertf( !stmts.empty(), "TupleAssignExpr missing statements." );
     139                auto stmt  = strict_dynamic_cast< const ExprStmt * >( stmts.back().get() );
     140                auto tuple = strict_dynamic_cast< const TupleExpr * >( stmt->expr.get() );
     141                assertf( !tuple->exprs.empty(), "TupleAssignExpr has empty tuple expr." );
     142                return getCallArg( tuple->exprs.front(), pos );
     143        } else if ( auto ctor = dynamic_cast< const ImplicitCopyCtorExpr * >( call ) ) {
     144                return getCallArg( ctor->callExpr, pos );
     145        } else {
     146                assertf( false, "Unexpected expression type passed to getCallArg: %s",
     147                        toString( call ).c_str() );
     148        }
     149}
    23150
    24151bool structHasFlexibleArray( const ast::StructDecl * decl ) {
     
    33160}
    34161
     162const ApplicationExpr * isIntrinsicCallExpr( const Expr * expr ) {
     163        auto appExpr = dynamic_cast< const ApplicationExpr * >( expr );
     164        if ( !appExpr ) return nullptr;
     165
     166        const DeclWithType * func = getCalledFunction( appExpr->func );
     167        assertf( func,
     168                "getCalledFunction returned nullptr: %s", toString( appExpr->func ).c_str() );
     169
     170        return func->linkage == ast::Linkage::Intrinsic ? appExpr : nullptr;
     171}
     172
    35173} // namespace ast
Note: See TracChangeset for help on using the changeset viewer.