Changes in / [83b52f1:96ac72c0]


Ignore:
Files:
6 added
1 deleted
35 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    r83b52f1 r96ac72c0  
    5151        template<typename node_t>
    5252        friend node_t * mutate(const node_t * node);
     53        template<typename node_t>
     54    friend node_t * shallowCopy(const node_t * node);
    5355};
    5456
  • src/AST/Convert.cpp

    r83b52f1 r96ac72c0  
    608608
    609609                tgt->result = get<Type>().accept1(src->result);
     610                // Unconditionally use a clone of the result type.
     611                // We know this will leak some objects: much of the immediate conversion result.
     612                // In some cases, using the conversion result directly gives unintended object sharing.
     613                // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
     614                // But tgt->result must be fully owned privately by tgt.
     615                // Applying these conservative copies here means
     616                // - weak references point at the declaration's copy, not these expr.result copies (good)
     617                // - we copy more objects than really needed (bad, tolerated)
     618                if (tgt->result) {
     619                        tgt->result = tgt->result->clone();
     620                }
    610621                return visitBaseExpr_skipResultType(src, tgt);
    611622        }
  • src/AST/Decl.cpp

    r83b52f1 r96ac72c0  
    5252
    5353const Type * FunctionDecl::get_type() const { return type.get(); }
    54 void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); }
     54void FunctionDecl::set_type( const Type * t ) {
     55        type = strict_dynamic_cast< const FunctionType * >( t );
     56}
    5557
    5658// --- TypeDecl
  • src/AST/Decl.hpp

    r83b52f1 r96ac72c0  
    3232
    3333// Must be included in *all* AST classes; should be #undef'd at the end of the file
    34 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     34#define MUTATE_FRIEND \
     35    template<typename node_t> friend node_t * mutate(const node_t * node); \
     36        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3537
    3638namespace ast {
     
    8789        virtual const Type * get_type() const = 0;
    8890        /// Set type of this declaration. May be verified by subclass
    89         virtual void set_type(Type *) = 0;
     91        virtual void set_type( const Type * ) = 0;
    9092
    9193        const DeclWithType * accept( Visitor & v ) const override = 0;
     
    110112
    111113        const Type* get_type() const override { return type; }
    112         void set_type( Type * ty ) override { type = ty; }
     114        void set_type( const Type * ty ) override { type = ty; }
    113115
    114116        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
     
    132134
    133135        const Type * get_type() const override;
    134         void set_type(Type * t) override;
     136        void set_type( const Type * t ) override;
    135137
    136138        bool has_body() const { return stmts; }
     
    149151        std::vector<ptr<DeclWithType>> assertions;
    150152
    151         NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
    152                 Type* b, Linkage::Spec spec = Linkage::Cforall )
     153        NamedTypeDecl(
     154                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
     155                const Type * b, Linkage::Spec spec = Linkage::Cforall )
    153156        : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {}
    154157
     
    185188        };
    186189
    187         TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b,
    188                 TypeVar::Kind k, bool s, Type* i = nullptr )
     190        TypeDecl(
     191                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
     192                const Type * b, TypeVar::Kind k, bool s, const Type * i = nullptr )
    189193        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
    190194          init( i ) {}
  • src/AST/Expr.cpp

    r83b52f1 r96ac72c0  
    2020#include <vector>
    2121
     22#include "Eval.hpp"                // for call
    2223#include "GenericSubstitution.hpp"
    2324#include "Stmt.hpp"
     
    5152        assert( arg );
    5253
    53         UntypedExpr * ret = new UntypedExpr{
    54                 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
    55         };
     54        UntypedExpr * ret = call( loc, "*?", arg );
    5655        if ( const Type * ty = arg->result ) {
    5756                const Type * base = InitTweak::getPointerBase( ty );
     
    7473        assert( lhs && rhs );
    7574
    76         UntypedExpr * ret = new UntypedExpr{
    77                 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
    78         };
     75        UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
    7976        if ( lhs->result && rhs->result ) {
    8077                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
  • src/AST/Expr.hpp

    r83b52f1 r96ac72c0  
    3030
    3131// Must be included in *all* AST classes; should be #undef'd at the end of the file
    32 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     32#define MUTATE_FRIEND \
     33    template<typename node_t> friend node_t * mutate(const node_t * node); \
     34        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     35
    3336
    3437class ConverterOldToNew;
  • src/AST/Init.hpp

    r83b52f1 r96ac72c0  
    2525
    2626// Must be included in *all* AST classes; should be #undef'd at the end of the file
    27 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     27#define MUTATE_FRIEND \
     28    template<typename node_t> friend node_t * mutate(const node_t * node); \
     29        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    2830
    2931namespace ast {
  • src/AST/Node.cpp

    r83b52f1 r96ac72c0  
    1717#include "Fwd.hpp"
    1818
     19#include <csignal>  // MEMORY DEBUG -- for raise
    1920#include <iostream>
    2021
     
    2930#include "Print.hpp"
    3031
    31 template< typename node_t, enum ast::Node::ref_type ref_t >
    32 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); }
    33 
    34 template< typename node_t, enum ast::Node::ref_type ref_t >
    35 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
    36 
    37 template< typename node_t, enum ast::Node::ref_type ref_t >
    38 void ast::ptr_base<node_t, ref_t>::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); }
     32/// MEMORY DEBUG -- allows breaking on ref-count changes of dynamically chosen object.
     33/// Process to use in GDB:
     34///   break ast::Node::_trap()
     35///   run
     36///   set variable MEM_TRAP_OBJ = <target>
     37///   disable <first breakpoint>
     38///   continue
     39void * MEM_TRAP_OBJ = nullptr;
     40
     41void _trap( const void * node ) {
     42        if ( node == MEM_TRAP_OBJ ) std::raise(SIGTRAP);
     43}
     44
     45template< typename node_t, enum ast::Node::ref_type ref_t >
     46void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) {
     47        node->increment(ref_t);
     48        _trap( node );
     49}
     50
     51template< typename node_t, enum ast::Node::ref_type ref_t >
     52void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node, bool do_delete ) {
     53        _trap( node );
     54        node->decrement(ref_t, do_delete );
     55}
     56
     57template< typename node_t, enum ast::Node::ref_type ref_t >
     58void ast::ptr_base<node_t, ref_t>::_check() const {
     59        // if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
     60}
    3961
    4062template< typename node_t, enum ast::Node::ref_type ref_t >
  • src/AST/Node.hpp

    r83b52f1 r96ac72c0  
    3838        Node& operator= (const Node&) = delete;
    3939        Node& operator= (Node&&) = delete;
    40         virtual ~Node() = default;
     40        virtual ~Node() {}
    4141
    4242        virtual const Node * accept( Visitor & v ) const = 0;
     
    5757        template<typename node_t>
    5858        friend node_t * mutate(const node_t * node);
     59        template<typename node_t>
     60        friend node_t * shallowCopy(const node_t * node);
    5961
    6062        mutable size_t strong_count = 0;
     
    6971        }
    7072
    71         void decrement(ast::Node::ref_type ref) const {
     73        void decrement(ast::Node::ref_type ref, bool do_delete = true) const {
    7274                switch (ref) {
    7375                        case ref_type::strong: strong_count--; break;
     
    7577                }
    7678
    77                 if(!strong_count && !weak_count) {
     79                if( do_delete && !strong_count && !weak_count) {
    7880                        delete this;
    7981                }
     
    123125        (ret->*field)[i] = std::forward< field_t >( val );
    124126        return ret;
     127}
     128
     129/// Mutate an entire indexed collection by cloning to accepted value
     130template<typename node_t, typename parent_t, typename coll_t>
     131const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {
     132        for ( unsigned i = 0; i < (node->*field).size(); ++i ) {
     133                node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) );
     134        }
     135        return node;
    125136}
    126137
     
    219230        operator const node_t * () const { _check(); return node; }
    220231
     232        const node_t * release() {
     233                const node_t * ret = node;
     234                if ( node ) {
     235                        _dec(node, false);
     236                        node = nullptr;
     237                }
     238                return ret;
     239        }
     240
    221241        /// wrapper for convenient access to dynamic_cast
    222242        template<typename o_node_t>
     
    244264
    245265        void _inc( const node_t * other );
    246         void _dec( const node_t * other );
     266        void _dec( const node_t * other, bool do_delete = true );
    247267        void _check() const;
    248268
  • src/AST/Pass.hpp

    r83b52f1 r96ac72c0  
    3535#include "AST/SymbolTable.hpp"
    3636
     37#include "AST/ForallSubstitutionTable.hpp"
     38
    3739// Private prelude header, needed for some of the magic tricks this class pulls off
    3840#include "AST/Pass.proto.hpp"
     
    4648//
    4749// Several additional features are available through inheritance
    48 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the
    49 //                          current expression
    50 // | WithStmtsToAdd       - provides the ability to insert statements before or after the current
    51 //                          statement by adding new statements into stmtsToAddBefore or
    52 //                          stmtsToAddAfter respectively.
    53 // | WithDeclsToAdd       - provides the ability to insert declarations before or after the current
    54 //                          declarations by adding new DeclStmt into declsToAddBefore or
    55 //                          declsToAddAfter respectively.
    56 // | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children
    57 //                          to false in pre{visit,visit} to skip visiting children
    58 // | WithGuards           - provides the ability to save/restore data like a LIFO stack; to save,
    59 //                          call GuardValue with the variable to save, the variable will
    60 //                          automatically be restored to its previous value after the corresponding
    61 //                          postvisit/postmutate teminates.
    62 // | WithVisitorRef       - provides an pointer to the templated visitor wrapper
    63 // | WithSymbolTable      - provides symbol table functionality
     50// | WithTypeSubstitution  - provides polymorphic const TypeSubstitution * env for the
     51//                           current expression
     52// | WithStmtsToAdd        - provides the ability to insert statements before or after the current
     53//                           statement by adding new statements into stmtsToAddBefore or
     54//                           stmtsToAddAfter respectively.
     55// | WithDeclsToAdd        - provides the ability to insert declarations before or after the
     56//                           current declarations by adding new DeclStmt into declsToAddBefore or
     57//                           declsToAddAfter respectively.
     58// | WithShortCircuiting   - provides the ability to skip visiting child nodes; set visit_children
     59//                           to false in pre{visit,visit} to skip visiting children
     60// | WithGuards            - provides the ability to save/restore data like a LIFO stack; to save,
     61//                           call GuardValue with the variable to save, the variable will
     62//                           automatically be restored to its previous value after the
     63//                           corresponding postvisit/postmutate teminates.
     64// | WithVisitorRef        - provides an pointer to the templated visitor wrapper
     65// | WithSymbolTable       - provides symbol table functionality
     66// | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation
    6467//-------------------------------------------------------------------------------------------------
    6568template< typename pass_t >
     
    201204        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    202205
     206        /// Mutate forall-list, accounting for presence of type substitution map
     207        template<typename node_t>
     208        void mutate_forall( const node_t *& );
     209
    203210public:
    204211        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     
    209216        /// Internal RAII guard for symbol table features
    210217        struct guard_symtab {
    211                 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
    212                 ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
     218                guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.pass, 0); }
     219                ~guard_symtab()                                   { __pass::symtab::leave(pass.pass, 0); }
    213220                Pass<pass_t> & pass;
    214221        };
     
    216223        /// Internal RAII guard for scope features
    217224        struct guard_scope {
    218                 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
    219                 ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
     225                guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass.pass, 0); }
     226                ~guard_scope()                                   { __pass::scope::leave(pass.pass, 0); }
    220227                Pass<pass_t> & pass;
     228        };
     229
     230        /// Internal RAII guard for forall substitutions
     231        struct guard_forall_subs {
     232                guard_forall_subs( Pass<pass_t> & pass, const ParameterizedType * type )
     233                : pass( pass ), type( type ) { __pass::forall::enter(pass.pass, 0, type ); }
     234                ~guard_forall_subs()         { __pass::forall::leave(pass.pass, 0, type ); }
     235                Pass<pass_t> & pass;
     236                const ParameterizedType * type;
    221237        };
    222238
     
    313329        SymbolTable symtab;
    314330};
     331
     332/// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
     333struct WithForallSubstitutor {
     334        ForallSubstitutionTable subs;
     335};
     336
    315337}
    316338
  • src/AST/Pass.impl.hpp

    r83b52f1 r96ac72c0  
    127127                        , decltype( node->accept(*this) )
    128128                >::type
    129 
    130129        {
    131130                __pedantic_pass_assert( __visit_children() );
    132                 __pedantic_pass_assert( expr );
     131                __pedantic_pass_assert( node );
    133132
    134133                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     
    323322        }
    324323
     324
     325        template< typename pass_t >
     326        template< typename node_t >
     327        void ast::Pass< pass_t >::mutate_forall( const node_t *& node ) {
     328                if ( auto subs = __pass::forall::subs( pass, 0 ) ) {
     329                        // tracking TypeDecl substitution, full clone
     330                        if ( node->forall.empty() ) return;
     331
     332                        node_t * mut = mutate( node );
     333                        mut->forall = subs->clone( node->forall, *this );
     334                        node = mut;
     335                } else {
     336                        // not tracking TypeDecl substitution, just mutate
     337                        maybe_accept( node, &node_t::forall );
     338                }
     339        }
    325340}
    326341
     
    429444                        guard_symtab guard { *this };
    430445                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    431                         static ast::ObjectDecl func(
    432                                 node->location, "__func__",
    433                                 new ast::ArrayType(
    434                                         new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
     446                        static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{
     447                                CodeLocation{}, "__func__",
     448                                new ast::ArrayType{
     449                                        new ast::BasicType{ ast::BasicType::Char, ast::CV::Const },
    435450                                        nullptr, VariableLen, DynamicDim
    436                                 )
    437                         );
    438                         __pass::symtab::addId( pass, 0, &func );
     451                                }
     452                        } };
     453                        __pass::symtab::addId( pass, 0, func );
    439454                        VISIT(
    440455                                maybe_accept( node, &FunctionDecl::type );
     
    610625        VISIT({
    611626                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    612                 auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
    613                         if ( ! inFunction ) __pass::symtab::enter(pass, 0);
    614                 }, [this, inFunction = this->inFunction]() {
    615                         if ( ! inFunction ) __pass::symtab::leave(pass, 0);
     627                auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
     628                        if ( ! inFunctionCpy ) __pass::symtab::enter(pass, 0);
     629                }, [this, inFunctionCpy = this->inFunction]() {
     630                        if ( ! inFunctionCpy ) __pass::symtab::leave(pass, 0);
    616631                });
    617632                ValueGuard< bool > guard2( inFunction );
     
    16671682        VISIT_START( node );
    16681683
    1669         VISIT(
    1670                 maybe_accept( node, &FunctionType::forall  );
     1684        VISIT({
     1685                guard_forall_subs forall_guard { *this, node };
     1686                mutate_forall( node );
    16711687                maybe_accept( node, &FunctionType::returns );
    16721688                maybe_accept( node, &FunctionType::params  );
    1673         )
     1689        })
    16741690
    16751691        VISIT_END( Type, node );
     
    16861702        VISIT({
    16871703                guard_symtab guard { *this };
    1688                 maybe_accept( node, &StructInstType::forall );
     1704                guard_forall_subs forall_guard { *this, node };
     1705                mutate_forall( node );
    16891706                maybe_accept( node, &StructInstType::params );
    16901707        })
     
    16991716        VISIT_START( node );
    17001717
    1701         __pass::symtab::addStruct( pass, 0, node->name );
    1702 
    1703         {
     1718        __pass::symtab::addUnion( pass, 0, node->name );
     1719
     1720        VISIT({
    17041721                guard_symtab guard { *this };
    1705                 maybe_accept( node, &UnionInstType::forall );
     1722                guard_forall_subs forall_guard { *this, node };
     1723                mutate_forall( node );
    17061724                maybe_accept( node, &UnionInstType::params );
    1707         }
     1725        })
    17081726
    17091727        VISIT_END( Type, node );
     
    17161734        VISIT_START( node );
    17171735
    1718         VISIT(
    1719                 maybe_accept( node, &EnumInstType::forall );
     1736        VISIT({
     1737                guard_forall_subs forall_guard { *this, node };
     1738                mutate_forall( node );
    17201739                maybe_accept( node, &EnumInstType::params );
    1721         )
     1740        })
    17221741
    17231742        VISIT_END( Type, node );
     
    17301749        VISIT_START( node );
    17311750
    1732         VISIT(
    1733                 maybe_accept( node, &TraitInstType::forall );
     1751        VISIT({
     1752                guard_forall_subs forall_guard { *this, node };
     1753                mutate_forall( node );
    17341754                maybe_accept( node, &TraitInstType::params );
    1735         )
     1755        })
    17361756
    17371757        VISIT_END( Type, node );
     
    17451765
    17461766        VISIT(
    1747                 maybe_accept( node, &TypeInstType::forall );
    1748                 maybe_accept( node, &TypeInstType::params );
     1767                {
     1768                        guard_forall_subs forall_guard { *this, node };
     1769                        mutate_forall( node );
     1770                        maybe_accept( node, &TypeInstType::params );
     1771                }
     1772                // ensure that base re-bound if doing substitution
     1773                __pass::forall::replace( pass, 0, node );
    17491774        )
    17501775
     
    18951920                                guard_symtab guard { *this };
    18961921                                auto new_node = p.second->accept( *this );
    1897                                 if (new_node != p.second) mutated = false;
     1922                                if (new_node != p.second) mutated = true;
    18981923                                new_map.insert({ p.first, new_node });
    18991924                        }
     
    19111936                                guard_symtab guard { *this };
    19121937                                auto new_node = p.second->accept( *this );
    1913                                 if (new_node != p.second) mutated = false;
     1938                                if (new_node != p.second) mutated = true;
    19141939                                new_map.insert({ p.first, new_node });
    19151940                        }
  • src/AST/Pass.proto.hpp

    r83b52f1 r96ac72c0  
    263263                template<typename pass_t>
    264264                static inline void leave( pass_t &, long ) {}
    265         };
    266 
    267         // Finally certain pass desire an up to date symbol table automatically
     265        } // namespace scope
     266
     267        // Certain passes desire an up to date symbol table automatically
    268268        // detect the presence of a member name `symtab` and call all the members appropriately
    269269        namespace symtab {
    270270                // Some simple scoping rules
    271271                template<typename pass_t>
    272                 static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) {
     272                static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab, void() ) {
    273273                        pass.symtab.enterScope();
    274274                }
     
    278278
    279279                template<typename pass_t>
    280                 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) {
     280                static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab, void() ) {
    281281                        pass.symtab.leaveScope();
    282282                }
     
    356356                #undef SYMTAB_FUNC1
    357357                #undef SYMTAB_FUNC2
    358         };
    359 };
    360 };
     358        } // namespace symtab
     359
     360        // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
     361        // Detect the presence of a member name `subs` and call all members appropriately
     362        namespace forall {
     363                // Some simple scoping rules
     364                template<typename pass_t>
     365                static inline auto enter( pass_t & pass, int, const ast::ParameterizedType * type )
     366                -> decltype( pass.subs, void() ) {
     367                        if ( ! type->forall.empty() ) pass.subs.beginScope();
     368                }
     369
     370                template<typename pass_t>
     371                static inline auto enter( pass_t &, long, const ast::ParameterizedType * ) {}
     372
     373                template<typename pass_t>
     374                static inline auto leave( pass_t & pass, int, const ast::ParameterizedType * type )
     375                -> decltype( pass.subs, void() ) {
     376                        if ( ! type->forall.empty() ) { pass.subs.endScope(); }
     377                }
     378
     379                template<typename pass_t>
     380                static inline auto leave( pass_t &, long, const ast::ParameterizedType * ) {}
     381
     382                // Get the substitution table, if present
     383                template<typename pass_t>
     384                static inline auto subs( pass_t & pass, int ) -> decltype( &pass.subs ) {
     385                        return &pass.subs;
     386                }
     387               
     388                template<typename pass_t>
     389                static inline ast::ForallSubstitutionTable * subs( pass_t &, long ) { return nullptr; }
     390
     391                // Replaces a TypeInstType's base TypeDecl according to the table
     392                template<typename pass_t>
     393                static inline auto replace( pass_t & pass, int, const ast::TypeInstType *& inst )
     394                -> decltype( pass.subs, void() ) {
     395                        inst = ast::mutate_field(
     396                                inst, &ast::TypeInstType::base, pass.subs.replace( inst->base ) );
     397                }
     398
     399                template<typename pass_t>
     400                static inline auto replace( pass_t &, long, const ast::TypeInstType *& ) {}
     401
     402        } // namespace forall
     403} // namespace __pass
     404} // namespace ast
  • src/AST/Stmt.hpp

    r83b52f1 r96ac72c0  
    2727
    2828// Must be included in *all* AST classes; should be #undef'd at the end of the file
    29 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     29#define MUTATE_FRIEND \
     30    template<typename node_t> friend node_t * mutate(const node_t * node); \
     31        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3032
    3133namespace ast {
  • src/AST/Type.cpp

    r83b52f1 r96ac72c0  
    2121
    2222#include "Decl.hpp"
     23#include "ForallSubstitutor.hpp" // for substituteForall
    2324#include "Init.hpp"
     25#include "Common/utility.h"      // for copy, move
    2426#include "InitTweak/InitTweak.h" // for getPointerBase
    2527#include "Tuples/Tuples.h"       // for isTtype
     
    9193);
    9294
     95// --- ParameterizedType
     96
     97void ParameterizedType::initWithSub(
     98        const ParameterizedType & o, Pass< ForallSubstitutor > & sub
     99) {
     100        forall = sub.pass( o.forall );
     101}
     102
    93103// --- FunctionType
     104
     105FunctionType::FunctionType( const FunctionType & o )
     106: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     107  isVarArgs( o.isVarArgs ) {
     108        Pass< ForallSubstitutor > sub;
     109        initWithSub( o, sub );           // initialize substitution map
     110        returns = sub.pass( o.returns ); // apply to return and parameter types
     111        params = sub.pass( o.params );
     112}
    94113
    95114namespace {
     
    107126
    108127// --- ReferenceToType
     128
     129void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
     130        ParameterizedType::initWithSub( o, sub ); // initialize substitution
     131        params = sub.pass( o.params );            // apply to parameters
     132}
     133
     134ReferenceToType::ReferenceToType( const ReferenceToType & o )
     135: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
     136  hoistType( o.hoistType ) {
     137        Pass< ForallSubstitutor > sub;
     138        initWithSub( o, sub );
     139}
     140
    109141std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
    110142        assertf( aggr(), "Must have aggregate to perform lookup" );
     
    119151// --- StructInstType
    120152
    121 StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
    122         std::vector<ptr<Attribute>>&& as )
    123 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     153StructInstType::StructInstType(
     154        const StructDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     155: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    124156
    125157bool StructInstType::isComplete() const { return base ? base->body : false; }
     
    127159// --- UnionInstType
    128160
    129 UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
    130         std::vector<ptr<Attribute>>&& as )
    131 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     161UnionInstType::UnionInstType(
     162        const UnionDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     163: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    132164
    133165bool UnionInstType::isComplete() const { return base ? base->body : false; }
     
    135167// --- EnumInstType
    136168
    137 EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
    138         std::vector<ptr<Attribute>>&& as )
    139 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     169EnumInstType::EnumInstType(
     170        const EnumDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     171: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    140172
    141173bool EnumInstType::isComplete() const { return base ? base->body : false; }
     
    143175// --- TraitInstType
    144176
    145 TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
    146         std::vector<ptr<Attribute>>&& as )
    147 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     177TraitInstType::TraitInstType(
     178        const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     179: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    148180
    149181// --- TypeInstType
     182
     183TypeInstType::TypeInstType( const TypeInstType & o )
     184: ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
     185        Pass< ForallSubstitutor > sub;
     186        initWithSub( o, sub );      // initialize substitution
     187        base = sub.pass( o.base );  // apply to base type
     188}
    150189
    151190void TypeInstType::set_base( const TypeDecl * b ) {
     
    159198
    160199TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    161 : Type( q ), types( std::move(ts) ), members() {
     200: Type( q ), types( move(ts) ), members() {
    162201        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    163202        // named, but members without initializer nodes end up getting constructors, which breaks
  • src/AST/Type.hpp

    r83b52f1 r96ac72c0  
    3030
    3131// Must be included in *all* AST classes; should be #undef'd at the end of the file
    32 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     32#define MUTATE_FRIEND \
     33    template<typename node_t> friend node_t * mutate(const node_t * node); \
     34        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3335
    3436namespace ast {
     37
     38template< typename T > class Pass;
     39
     40struct ForallSubstitutor;
    3541
    3642class Type : public Node {
     
    164170        static const char *typeNames[];
    165171
    166         BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 
     172        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    167173        : Type(q, std::move(as)), kind(k) {}
    168174
     
    266272/// Base type for potentially forall-qualified types
    267273class ParameterizedType : public Type {
     274protected:
     275        /// initializes forall with substitutor
     276        void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
    268277public:
    269278        using ForallList = std::vector<ptr<TypeDecl>>;
     
    277286        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    278287        : Type(q, std::move(as)), forall() {}
     288
     289        // enforce use of ForallSubstitutor to copy parameterized type
     290        ParameterizedType( const ParameterizedType & ) = delete;
     291
     292        ParameterizedType( ParameterizedType && ) = default;
     293
     294        // no need to change destructor, and operator= deleted in Node
    279295
    280296private:
     
    302318        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
    303319
     320        FunctionType( const FunctionType & o );
     321
    304322        /// true if either the parameters or return values contain a tttype
    305323        bool isTtype() const;
     
    315333/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    316334class ReferenceToType : public ParameterizedType {
     335protected:
     336        /// Initializes forall and parameters based on substitutor
     337        void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
    317338public:
    318339        std::vector<ptr<Expr>> params;
     
    320341        bool hoistType = false;
    321342
    322         ReferenceToType( const std::string& n, CV::Qualifiers q = {},
    323                 std::vector<ptr<Attribute>> && as = {} )
     343        ReferenceToType(
     344                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    324345        : ParameterizedType(q, std::move(as)), params(), name(n) {}
     346
     347        ReferenceToType( const ReferenceToType & o );
    325348
    326349        /// Gets aggregate declaration this type refers to
     
    339362        readonly<StructDecl> base;
    340363
    341         StructInstType( const std::string& n, CV::Qualifiers q = {},
    342                 std::vector<ptr<Attribute>> && as = {} )
     364        StructInstType(
     365                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    343366        : ReferenceToType( n, q, std::move(as) ), base() {}
    344         StructInstType( const StructDecl * b, CV::Qualifiers q = {},
    345                 std::vector<ptr<Attribute>> && as = {} );
     367
     368        StructInstType(
     369                const StructDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    346370
    347371        bool isComplete() const override;
     
    360384        readonly<UnionDecl> base;
    361385
    362         UnionInstType( const std::string& n, CV::Qualifiers q = {},
    363                 std::vector<ptr<Attribute>> && as = {} )
     386        UnionInstType(
     387                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    364388        : ReferenceToType( n, q, std::move(as) ), base() {}
    365         UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
    366                 std::vector<ptr<Attribute>> && as = {} );
     389
     390        UnionInstType(
     391                const UnionDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    367392
    368393        bool isComplete() const override;
     
    381406        readonly<EnumDecl> base;
    382407
    383         EnumInstType( const std::string& n, CV::Qualifiers q = {},
    384                 std::vector<ptr<Attribute>> && as = {} )
     408        EnumInstType(
     409                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    385410        : ReferenceToType( n, q, std::move(as) ), base() {}
    386         EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
    387                 std::vector<ptr<Attribute>> && as = {} );
     411
     412        EnumInstType(
     413                const EnumDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    388414
    389415        bool isComplete() const override;
     
    402428        readonly<TraitDecl> base;
    403429
    404         TraitInstType( const std::string& n, CV::Qualifiers q = {},
    405                 std::vector<ptr<Attribute>> && as = {} )
     430        TraitInstType(
     431                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    406432        : ReferenceToType( n, q, std::move(as) ), base() {}
    407         TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
    408                 std::vector<ptr<Attribute>> && as = {} );
     433
     434        TraitInstType(
     435                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    409436
    410437        // not meaningful for TraitInstType
     
    425452        TypeVar::Kind kind;
    426453
    427         TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     454        TypeInstType(
     455                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    428456                std::vector<ptr<Attribute>> && as = {} )
    429457        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
    430         TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
     458
     459        TypeInstType(
     460                const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
    431461                std::vector<ptr<Attribute>> && as = {} )
    432462        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
     463
     464        TypeInstType( const TypeInstType & o );
    433465
    434466        /// sets `base`, updating `kind` correctly
  • src/AST/TypeSubstitution.cpp

    r83b52f1 r96ac72c0  
    9292namespace {
    9393        struct EnvTrimmer {
    94                 ptr<TypeSubstitution> env;
     94                const TypeSubstitution * env;
    9595                TypeSubstitution * newEnv;
    9696                EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
     
    108108        if ( env ) {
    109109                TypeSubstitution * newEnv = new TypeSubstitution();
    110 #if TIME_TO_CONVERT_PASSES
    111110                Pass<EnvTrimmer> trimmer( env, newEnv );
    112111                expr->accept( trimmer );
    113 #else
    114                 (void)expr;
    115                 (void)env;
    116 #endif
    117112                return newEnv;
    118113        }
     
    121116
    122117void TypeSubstitution::normalize() {
    123 #if TIME_TO_CONVERT_PASSES
    124         PassVisitor<Substituter> sub( *this, true );
     118        Pass<Substituter> sub( *this, true );
    125119        do {
    126120                sub.pass.subCount = 0;
    127121                sub.pass.freeOnly = true;
    128122                for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    129                         i->second = i->second->acceptMutator( sub );
     123                        i->second = i->second->accept( sub );
    130124                }
    131125        } while ( sub.pass.subCount );
    132 #endif
    133 }
    134 
    135 #if TIME_TO_CONVERT_PASSES
    136 
    137 Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
     126}
     127
     128const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
    138129        BoundVarsType::const_iterator bound = boundVars.find( inst->name );
    139130        if ( bound != boundVars.end() ) return inst;
     
    146137                // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
    147138                // TODO: investigate preventing type variables from being bound to themselves in the first place.
    148                 if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {
     139                if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) {
    149140                        if ( inst->name == replacement->name ) {
    150141                                return inst;
     
    153144                // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
    154145                subCount++;
    155                 Type * newtype = i->second->clone();
    156                 newtype->get_qualifiers() |= inst->get_qualifiers();
    157                 delete inst;
    158                 // Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
    159                 return newtype->acceptMutator( *visitor );
    160         } // if
    161 }
    162 
    163 Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
     146                ptr<Type> newType = i->second; // force clone if needed
     147                add_qualifiers( newType, inst->qualifiers );
     148                // Note: need to recursively apply substitution to the new type because normalize does not
     149                // substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
     150                newType = newType->accept( *visitor );
     151                return newType.release();
     152        } // if
     153}
     154
     155const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) {
    164156        VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
    165157        if ( i == sub.varEnv.end() ) {
     
    168160                subCount++;
    169161                delete nameExpr;
    170                 return i->second->clone();
    171         } // if
    172 }
    173 
    174 void TypeSubstitution::Substituter::premutate( Type * type ) {
     162                return i->second;
     163        } // if
     164}
     165
     166void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) {
    175167        GuardValue( boundVars );
    176168        // bind type variables from forall-qualifiers
    177169        if ( freeOnly ) {
    178                 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    179                         boundVars.insert( (*tyvar)->name );
     170                for ( const TypeDecl * tyvar : ptype->forall ) {
     171                                boundVars.insert( tyvar->name );
    180172                } // for
    181173        } // if
    182174}
    183175
    184 template< typename TypeClass >
    185 void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
     176void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
    186177        GuardValue( boundVars );
    187178        // bind type variables from forall-qualifiers
    188179        if ( freeOnly ) {
    189                 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    190                         boundVars.insert( (*tyvar)->name );
     180                for ( const TypeDecl * tyvar : type->forall ) {
     181                        boundVars.insert( tyvar->name );
    191182                } // for
    192183                // bind type variables from generic type instantiations
    193                 std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
    194                 if ( baseParameters && ! type->parameters.empty() ) {
    195                         for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
    196                                 boundVars.insert( (*tyvar)->name );
    197                         } // for
    198                 } // if
    199         } // if
    200 }
    201 
    202 void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
     184                if ( auto decl = type->aggr() ) {
     185                        if ( ! type->params.empty() ) {
     186                                for ( const TypeDecl * tyvar : decl->params ) {
     187                                        boundVars.insert( tyvar->name );
     188                                } // for
     189                        } // if
     190                }
     191        } // if
     192}
     193
     194void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) {
    203195        handleAggregateType( aggregateUseType );
    204196}
    205197
    206 void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
     198void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) {
    207199        handleAggregateType( aggregateUseType );
    208200}
    209 
    210 #endif
    211201
    212202} // namespace ast
  • src/AST/TypeSubstitution.hpp

    r83b52f1 r96ac72c0  
    155155                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    156156
    157 #if TIME_TO_CONVERT_PASSES
    158 
    159                 Type * postmutate( TypeInstType * aggregateUseType );
    160                 Expression * postmutate( NameExpr * nameExpr );
     157                const Type * postvisit( const TypeInstType * aggregateUseType );
     158                const Expr * postvisit( const NameExpr * nameExpr );
    161159
    162160                /// Records type variable bindings from forall-statements
    163                 void premutate( Type * type );
     161                void previsit( const ParameterizedType * type );
    164162                /// Records type variable bindings from forall-statements and instantiations of generic types
    165                 template< typename TypeClass > void handleAggregateType( TypeClass * type );
    166 
    167                 void premutate( StructInstType * aggregateUseType );
    168                 void premutate( UnionInstType * aggregateUseType );
    169 
    170 #endif
     163                void handleAggregateType( const ReferenceToType * type );
     164
     165                void previsit( const StructInstType * aggregateUseType );
     166                void previsit( const UnionInstType * aggregateUseType );
    171167
    172168                const TypeSubstitution & sub;
  • src/AST/module.mk

    r83b52f1 r96ac72c0  
    2222        AST/DeclReplacer.cpp \
    2323        AST/Expr.cpp \
     24        AST/ForallSubstitutionTable.cpp \
    2425        AST/GenericSubstitution.cpp \
    2526        AST/Init.cpp \
  • src/Common/ScopedMap.h

    r83b52f1 r96ac72c0  
    249249
    250250        /// Gets the note at the given scope
     251        Note& getNote() { return scopes.back().note; }
     252        const Note& getNote() const { return scopes.back().note; }
    251253        Note& getNote( size_type i ) { return scopes[i].note; }
    252254        const Note& getNote( size_type i ) const { return scopes[i].note; }
  • src/Makefile.in

    r83b52f1 r96ac72c0  
    168168        AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \
    169169        AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \
     170        AST/ForallSubstitutionTable.$(OBJEXT) \
    170171        AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \
    171172        AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
     
    585586        AST/DeclReplacer.cpp \
    586587        AST/Expr.cpp \
     588        AST/ForallSubstitutionTable.cpp \
    587589        AST/GenericSubstitution.cpp \
    588590        AST/Init.cpp \
     
    759761        AST/$(DEPDIR)/$(am__dirstamp)
    760762AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     763AST/ForallSubstitutionTable.$(OBJEXT): AST/$(am__dirstamp) \
     764        AST/$(DEPDIR)/$(am__dirstamp)
    761765AST/GenericSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
    762766        AST/$(DEPDIR)/$(am__dirstamp)
     
    12121216@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/DeclReplacer.Po@am__quote@
    12131217@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Expr.Po@am__quote@
     1218@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/ForallSubstitutionTable.Po@am__quote@
    12141219@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/GenericSubstitution.Po@am__quote@
    12151220@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Init.Po@am__quote@
  • src/ResolvExpr/AdjustExprType.cc

    r83b52f1 r96ac72c0  
    100100
    101101namespace {
    102         struct AdjustExprType_new final : public ast::WithShortCircuiting {
     102        class AdjustExprType_new final : public ast::WithShortCircuiting {
     103                const ast::SymbolTable & symtab;
     104        public:
    103105                const ast::TypeEnvironment & tenv;
    104                 const ast::SymbolTable & symtab;
    105106
    106107                AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
    107                 : tenv( e ), symtab( syms ) {}
     108                : symtab( syms ), tenv( e ) {}
    108109
    109                 void premutate( const ast::VoidType * ) { visit_children = false; }
    110                 void premutate( const ast::BasicType * ) { visit_children = false; }
    111                 void premutate( const ast::PointerType * ) { visit_children = false; }
    112                 void premutate( const ast::ArrayType * ) { visit_children = false; }
    113                 void premutate( const ast::FunctionType * ) { visit_children = false; }
    114                 void premutate( const ast::StructInstType * ) { visit_children = false; }
    115                 void premutate( const ast::UnionInstType * ) { visit_children = false; }
    116                 void premutate( const ast::EnumInstType * ) { visit_children = false; }
    117                 void premutate( const ast::TraitInstType * ) { visit_children = false; }
    118                 void premutate( const ast::TypeInstType * ) { visit_children = false; }
    119                 void premutate( const ast::TupleType * ) { visit_children = false; }
    120                 void premutate( const ast::VarArgsType * ) { visit_children = false; }
    121                 void premutate( const ast::ZeroType * ) { visit_children = false; }
    122                 void premutate( const ast::OneType * ) { visit_children = false; }
     110                void previsit( const ast::VoidType * ) { visit_children = false; }
     111                void previsit( const ast::BasicType * ) { visit_children = false; }
     112                void previsit( const ast::PointerType * ) { visit_children = false; }
     113                void previsit( const ast::ArrayType * ) { visit_children = false; }
     114                void previsit( const ast::FunctionType * ) { visit_children = false; }
     115                void previsit( const ast::StructInstType * ) { visit_children = false; }
     116                void previsit( const ast::UnionInstType * ) { visit_children = false; }
     117                void previsit( const ast::EnumInstType * ) { visit_children = false; }
     118                void previsit( const ast::TraitInstType * ) { visit_children = false; }
     119                void previsit( const ast::TypeInstType * ) { visit_children = false; }
     120                void previsit( const ast::TupleType * ) { visit_children = false; }
     121                void previsit( const ast::VarArgsType * ) { visit_children = false; }
     122                void previsit( const ast::ZeroType * ) { visit_children = false; }
     123                void previsit( const ast::OneType * ) { visit_children = false; }
    123124
    124                 const ast::Type * postmutate( const ast::ArrayType * at ) {
     125                const ast::Type * postvisit( const ast::ArrayType * at ) {
    125126                        return new ast::PointerType{ at->base, at->qualifiers };
    126127                }
    127128
    128                 const ast::Type * postmutate( const ast::FunctionType * ft ) {
     129                const ast::Type * postvisit( const ast::FunctionType * ft ) {
    129130                        return new ast::PointerType{ ft };
    130131                }
    131132
    132                 const ast::Type * postmutate( const ast::TypeInstType * inst ) {
     133                const ast::Type * postvisit( const ast::TypeInstType * inst ) {
    133134                        // replace known function-type-variables with pointer-to-function
    134135                        if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
  • src/ResolvExpr/CandidateFinder.cpp

    r83b52f1 r96ac72c0  
    370370                                                        // push empty tuple expression
    371371                                                        newResult.parent = i;
    372                                                         std::vector< ast::ptr< ast::Expr > > emptyList;
    373                                                         newResult.expr =
    374                                                                 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
     372                                                        newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    375373                                                        argType = newResult.expr->result;
    376374                                                } else {
     
    548546                genStart = genEnd;
    549547
    550                 return genEnd != results.size();
     548                return genEnd != results.size();  // were any new results added?
    551549        }
    552550
     
    594592
    595593        /// Actually visits expressions to find their candidate interpretations
    596         struct Finder final : public ast::WithShortCircuiting {
     594        class Finder final : public ast::WithShortCircuiting {
     595                const ast::SymbolTable & symtab;
     596        public:
    597597                CandidateFinder & selfFinder;
    598                 const ast::SymbolTable & symtab;
    599598                CandidateList & candidates;
    600599                const ast::TypeEnvironment & tenv;
     
    602601
    603602                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     603                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605604                  targetType( f.targetType ) {}
    606605               
     
    676675                        ast::TypeEnvironment funcEnv{ func->env };
    677676                        makeUnifiableVars( funcType, funcOpen, funcNeed );
    678                         // add all type variables as open variables now so that those not used in the parameter
    679                         // list are still considered open
     677                        // add all type variables as open variables now so that those not used in the
     678                        // parameter list are still considered open
    680679                        funcEnv.add( funcType->forall );
    681680
     
    15581557                std::vector< std::string > errors;
    15591558                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1559                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611560                }
    15621561
     
    16131612                        r->expr = ast::mutate_field(
    16141613                                r->expr.get(), &ast::Expr::result,
    1615                                 adjustExprType( r->expr->result, r->env, symtab ) );
     1614                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161615                }
    16171616        }
     
    16311630
    16321631        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1632                out.emplace_back( localSyms, env );
    16341633                out.back().find( x, ResolvMode::withAdjustment() );
    16351634               
  • src/ResolvExpr/CandidateFinder.hpp

    r83b52f1 r96ac72c0  
    2828struct CandidateFinder {
    2929        CandidateList candidates;          ///< List of candidate resolutions
    30         const ast::SymbolTable & symtab;   ///< Symbol table to lookup candidates
     30        const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
    3131        const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
    3232        ast::ptr< ast::Type > targetType;  ///< Target type for resolution
    3333
    3434        CandidateFinder(
    35                 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     35                const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
    3636                const ast::Type * tt = nullptr )
    37         : candidates(), symtab( symtab ), env( env ), targetType( tt ) {}
     37        : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
    3838
    3939        /// Fill candidates with feasible resolutions for `expr`
  • src/ResolvExpr/CommonType.cc

    r83b52f1 r96ac72c0  
    939939                        ast::ptr< ast::Type > result;
    940940                        const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
    941                         const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
     941                        const ast::ReferenceType * ref2 = type2.as< ast::ReferenceType >();
    942942
    943943                        if ( depth1 > depth2 ) {
  • src/ResolvExpr/ConversionCost.cc

    r83b52f1 r96ac72c0  
    1010// Created On       : Sun May 17 07:06:19 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun 24 13:33:00 2019
    13 // Update Count     : 26
     12// Last Modified On : Thr Jul  4 10:56:00 2019
     13// Update Count     : 27
    1414//
    1515
     
    764764                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    765765                }
     766        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
     767                cost = Cost::zero;
     768                // +1 for zero_t ->, +1 for disambiguation
     769                cost.incSafe( maxIntCost + 2 );
    766770        }
    767771}
     
    781785                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    782786                }
    783         } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    784                 cost = Cost::zero;
    785                 cost.incSafe( maxIntCost + 2 );
    786787        }
    787788}
  • src/ResolvExpr/PolyCost.cc

    r83b52f1 r96ac72c0  
    5858
    5959// TODO: When the old PolyCost is torn out get rid of the _new suffix.
    60 struct PolyCost_new {
     60class PolyCost_new {
     61        const ast::SymbolTable &symtab;
     62public:
    6163        int result;
    62         const ast::SymbolTable &symtab;
    6364        const ast::TypeEnvironment &env_;
    6465
    65         PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) :
    66                 result( 0 ), symtab( symtab ), env_( env ) {}
     66        PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env )
     67        : symtab( symtab ), result( 0 ), env_( env ) {}
    6768
    6869        void previsit( const ast::TypeInstType * type ) {
  • src/ResolvExpr/RenameVars.cc

    r83b52f1 r96ac72c0  
    1919#include <utility>                 // for pair
    2020
     21#include "AST/ForallSubstitutionTable.hpp"
    2122#include "AST/Pass.hpp"
    2223#include "AST/Type.hpp"
     
    3031#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
    3132
     33#include "AST/Copy.hpp"
     34
    3235namespace ResolvExpr {
    3336
     
    3740                int resetCount = 0;
    3841                ScopedMap< std::string, std::string > nameMap;
     42        public:
     43                ast::ForallSubstitutionTable subs;
    3944
    40         public:
    4145                void reset() {
    4246                        level = 0;
     
    4448                }
    4549
    46                 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
    47 
    4850                void rename( TypeInstType * type ) {
    49                         mapConstIterator it = nameMap.find( type->name );
     51                        auto it = nameMap.find( type->name );
    5052                        if ( it != nameMap.end() ) {
    5153                                type->name = it->second;
     
    6567                                        // ditto for assertion names, the next level in
    6668                                        level++;
    67                                         // acceptAll( td->assertions, *this );
    68                                 } // for
    69                         } // if
     69                                }
     70                        }
    7071                }
    7172
     
    7778
    7879                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
    79                         mapConstIterator it = nameMap.find( type->name );
     80                        // re-linking of base type handled by WithForallSubstitutor
     81
     82                        // rename
     83                        auto it = nameMap.find( type->name );
    8084                        if ( it != nameMap.end() ) {
    81                                 ast::TypeInstType * mutType = ast::mutate( type );
    82                                 mutType->name = it->second;
    83                     type = mutType;
     85                                // unconditionally mutate because map will *always* have different name,
     86                                // if this mutates, will *always* have been mutated by ForallSubstitutor above
     87                                ast::TypeInstType * mut = ast::mutate( type );
     88                                mut->name = it->second;
     89                    type = mut;
    8490                        }
     91
    8592                        return type;
    8693                }
     
    8895                template<typename NodeT>
    8996                const NodeT * openLevel( const NodeT * type ) {
    90                         if ( !type->forall.empty() ) {
    91                                 nameMap.beginScope();
    92                                 // Load new names from this forall clause and perform renaming.
    93                                 NodeT * mutType = ast::mutate( type );
    94                                 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
    95                                         std::ostringstream output;
    96                                         output << "_" << resetCount << "_" << level << "_" << td->name;
    97                                         std::string newname( output.str() );
    98                                         nameMap[ td->name ] = newname;
    99                                         ++level;
     97                        if ( type->forall.empty() ) return type;
     98                       
     99                        nameMap.beginScope();
    100100
    101                                         ast::TypeDecl * decl = ast::mutate( td.get() );
    102                                         decl->name = newname;
    103                                         td = decl;
    104                                 }
     101                        // Load new names from this forall clause and perform renaming.
     102                        NodeT * mutType = ast::mutate( type );
     103                        assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
     104                        for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
     105                                std::ostringstream output;
     106                                output << "_" << resetCount << "_" << level << "_" << td->name;
     107                                std::string newname =  output.str();
     108                                nameMap[ td->name ] = newname;
     109                                ++level;
     110
     111                                ast::TypeDecl * mutDecl = ast::mutate( td.get() );
     112                                assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
     113                                mutDecl->name = newname;
     114                                // assertion above means `td = mutDecl;` is unnecessary
    105115                        }
     116                        // assertion above means `type = mutType;` is unnecessary
     117
    106118                        return type;
    107119                }
    108120
    109                 template<typename NodeT>
    110                 const NodeT * closeLevel( const NodeT * type ) {
    111                         if ( !type->forall.empty() ) {
    112                                 nameMap.endScope();
    113                         }
    114                         return type;
     121                void closeLevel( const ast::ParameterizedType * type ) {
     122                        if ( type->forall.empty() ) return;
     123                       
     124                        nameMap.endScope();
    115125                }
    116126        };
     
    119129        RenamingData renaming;
    120130
    121         struct RenameVars {
     131        struct RenameVars_old {
    122132                void previsit( TypeInstType * instType ) {
    123133                        renaming.openLevel( (Type*)instType );
     
    130140                        renaming.closeLevel( type );
    131141                }
     142        };
     143       
     144        struct RenameVars_new /*: public ast::WithForallSubstitutor*/ {
     145                #warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor
     146                ast::ForallSubstitutionTable & subs = renaming.subs;
    132147
    133148                const ast::FunctionType * previsit( const ast::FunctionType * type ) {
     
    146161                        return renaming.rename( renaming.openLevel( type ) );
    147162                }
    148                 const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
    149                         return renaming.closeLevel( type );
     163                void postvisit( const ast::ParameterizedType * type ) {
     164                        renaming.closeLevel( type );
    150165                }
    151166        };
     
    154169
    155170void renameTyVars( Type * t ) {
    156         PassVisitor<RenameVars> renamer;
     171        PassVisitor<RenameVars_old> renamer;
    157172        t->accept( renamer );
    158173}
    159174
    160175const ast::Type * renameTyVars( const ast::Type * t ) {
    161         ast::Pass<RenameVars> renamer;
    162         return t->accept( renamer );
     176        ast::Type *tc = ast::deepCopy(t);
     177        ast::Pass<RenameVars_new> renamer;
     178//      return t->accept( renamer );
     179        return tc->accept( renamer );
    163180}
    164181
  • src/ResolvExpr/ResolveTypeof.cc

    r83b52f1 r96ac72c0  
    153153                        }
    154154
    155                         return newType;
     155                        return newType.release();
    156156                }
    157157        };
  • src/ResolvExpr/Resolver.cc

    r83b52f1 r96ac72c0  
    11081108
    11091109                // set up and resolve expression cast to void
    1110                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
     1110                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11111111                CandidateRef choice = findUnfinishedKindExpression(
    11121112                        untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     
    12471247        };
    12481248
    1249         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
     1249        void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
    12501250                ast::Pass< Resolver_new > resolver;
    12511251                accept_all( translationUnit, resolver );
     
    12811281                ast::ptr< ast::FunctionDecl > ret = functionDecl;
    12821282                for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    1283                         const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
     1283                        const ast::ptr< ast::DeclWithType > & d = functionDecl->type->params[i];
    12841284
    12851285                        if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
     
    12981298                        }
    12991299                }
    1300                 return ret.get();
     1300                return ret.release();
    13011301        }
    13021302
  • src/ResolvExpr/SpecCost.cc

    r83b52f1 r96ac72c0  
    1010// Created On       : Tue Oct 02 15:50:00 2018
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jun 19 10:43:00 2019
    13 // Update Count     : 2
    14 //
    15 
     12// Last Modified On : Wed Jul  3 11:07:00 2019
     13// Update Count     : 3
     14//
     15
     16#include <cassert>
    1617#include <limits>
    1718#include <list>
     
    129130                        typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type;
    130131
     132                #warning Should use a standard maybe_accept
     133                void maybe_accept( ast::Type const * type ) {
     134                        if ( type ) {
     135                                auto node = type->accept( *visitor );
     136                                assert( node == nullptr || node == type );
     137                        }
     138                }
     139
    131140                // Update the minimum to the new lowest non-none value.
    132141                template<typename T>
     
    134143                        for ( const auto & node : list ) {
    135144                                count = -1;
    136                                 mapper( node )->accept( *visitor );
     145                                maybe_accept( mapper( node ) );
    137146                                if ( count != -1 && count < minimum ) minimum = count;
    138147                        }
  • src/SymTab/Autogen.h

    r83b52f1 r96ac72c0  
    2121
    2222#include "AST/Decl.hpp"
     23#include "AST/Eval.hpp"
    2324#include "AST/Expr.hpp"
    2425#include "AST/Init.hpp"
     
    264265                }
    265266
    266                 ast::ptr< ast::Expr > begin, end, cmp, update;
     267                ast::ptr< ast::Expr > begin, end;
     268                std::string cmp, update;
    267269
    268270                if ( forward ) {
     
    270272                        begin = ast::ConstantExpr::from_int( loc, 0 );
    271273                        end = array->dimension;
    272                         cmp = new ast::NameExpr{ loc, "?<?" };
    273                         update = new ast::NameExpr{ loc, "++?" };
     274                        cmp = "?<?";
     275                        update = "++?";
    274276                } else {
    275277                        // generate: for ( int i = N-1; i >= 0; --i )
    276                         begin = new ast::UntypedExpr{
    277                                 loc, new ast::NameExpr{ loc, "?-?" },
    278                                 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
     278                        begin = ast::call(
     279                                loc, "?-?", array->dimension, ast::ConstantExpr::from_int( loc, 1 ) );
    279280                        end = ast::ConstantExpr::from_int( loc, 0 );
    280                         cmp = new ast::NameExpr{ loc, "?>=?" };
    281                         update = new ast::NameExpr{ loc, "--?" };
     281                        cmp = "?>=?";
     282                        update = "--?";
    282283                }
    283284
     
    285286                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
    286287                        new ast::SingleInit{ loc, begin } };
    287                
    288                 ast::ptr< ast::Expr > cond = new ast::UntypedExpr{
    289                         loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
    290                
    291                 ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
    292                         loc, update, { new ast::VariableExpr{ loc, index } } };
    293                
    294                 ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
    295                         loc, new ast::NameExpr{ loc, "?[?]" },
    296                         { dstParam, new ast::VariableExpr{ loc, index } } };
     288                ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
     289               
     290                ast::ptr< ast::Expr > cond = ast::call( loc, cmp, indexVar, end );
     291               
     292                ast::ptr< ast::Expr > inc = ast::call( loc, update, indexVar );
     293               
     294                ast::ptr< ast::Expr > dstIndex = ast::call( loc, "?[?]", dstParam, indexVar );
    297295               
    298296                // srcParam must keep track of the array indices to build the source parameter and/or
    299297                // array list initializer
    300                 srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
     298                srcParam.addArrayIndex( indexVar, array->dimension );
    301299
    302300                // for stmt's body, eventually containing call
     
    384382                if ( isUnnamedBitfield( obj ) ) return {};
    385383
    386                 ast::ptr< ast::Type > addCast = nullptr;
     384                ast::ptr< ast::Type > addCast;
    387385                if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
    388386                        assert( dstParam->result );
  • src/Tuples/Explode.cc

    r83b52f1 r96ac72c0  
    129129                        for ( const ast::Expr * expr : tupleExpr->exprs ) {
    130130                                exprs.emplace_back( applyCast( expr, false ) );
    131                                 //exprs.emplace_back( ast::ptr< ast::Expr >( applyCast( expr, false ) ) );
    132131                        }
    133132                        if ( first ) {
  • src/Tuples/Explode.h

    r83b52f1 r96ac72c0  
    210210                        }
    211211                        // Cast a reference away to a value-type to allow further explosion.
    212                         if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) {
     212                        if ( local->result.as< ast::ReferenceType >() ) {
    213213                                local = new ast::CastExpr{ local, tupleType };
    214214                        }
     
    220220                                // delete idx;
    221221                        }
    222                         // delete local;
    223222                }
    224223        } else {
  • src/Tuples/TupleAssignment.cc

    r83b52f1 r96ac72c0  
    465465                                        // resolve ctor/dtor for the new object
    466466                                        ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
    467                                                         InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );
     467                                                        InitTweak::genCtorInit( location, ret ), spotter.crntFinder.localSyms );
    468468                                        // remove environments from subexpressions of stmtExpr
    469469                                        ast::Pass< EnvRemover > rm{ env };
     
    560560                                        // resolve the cast expression so that rhsCand return type is bound by the cast
    561561                                        // type as needed, and transfer the resulting environment
    562                                         ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };
     562                                        ResolvExpr::CandidateFinder finder{ spotter.crntFinder.localSyms, env };
    563563                                        finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
    564564                                        assert( finder.candidates.size() == 1 );
     
    609609                                        // explode the LHS so that each field of a tuple-valued expr is assigned
    610610                                        ResolvExpr::CandidateList lhs;
    611                                         explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );
     611                                        explode( *lhsCand, crntFinder.localSyms, back_inserter(lhs), true );
    612612                                        for ( ResolvExpr::CandidateRef & cand : lhs ) {
    613613                                                // each LHS value must be a reference - some come in with a cast, if not
     
    629629                                                        if ( isTuple( rhsCand->expr ) ) {
    630630                                                                // multiple assignment
    631                                                                 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );
     631                                                                explode( *rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
    632632                                                                matcher.reset(
    633633                                                                        new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    648648                                                        // multiple assignment
    649649                                                        ResolvExpr::CandidateList rhs;
    650                                                         explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
     650                                                        explode( rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
    651651                                                        matcher.reset(
    652652                                                                new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    678678                                )
    679679
    680                                 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env };
     680                                ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
    681681
    682682                                try {
  • src/main.cc

    r83b52f1 r96ac72c0  
    2929#include <string>                           // for char_traits, operator<<
    3030
     31#include "AST/Convert.hpp"
    3132#include "CompilationState.h"
    3233#include "../config.h"                      // for CFA_LIBDIR
     
    302303                } // if
    303304
    304                 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     305                // PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     306                {
     307                        auto transUnit = convert( move( translationUnit ) );
     308                        PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
     309                        translationUnit = convert( move( transUnit ) );
     310                }
    305311                if ( exprp ) {
    306312                        dump( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.