Changeset 58fe85a for src/AST/Expr.hpp


Ignore:
Timestamp:
Jan 7, 2021, 3:27:00 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
2b4daf2, 64aeca0
Parents:
3c64c668 (diff), eef8dfb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into park_unpark

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.hpp

    r3c64c668 r58fe85a  
    3131
    3232// Must be included in *all* AST classes; should be #undef'd at the end of the file
    33 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     33#define MUTATE_FRIEND \
     34    template<typename node_t> friend node_t * mutate(const node_t * node); \
     35        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     36
    3437
    3538class ConverterOldToNew;
     
    4245struct ParamEntry {
    4346        UniqueId decl;
    44         ptr<Decl> declptr;
     47        readonly<Decl> declptr;
    4548        ptr<Type> actualType;
    4649        ptr<Type> formalType;
     
    6265class Expr : public ParseNode {
    6366public:
    64         /// Saves space (~16 bytes) by combining ResnSlots and InferredParams
     67        /*
     68         * NOTE: the union approach is incorrect until the case of
     69         * partial resolution in InferMatcher is eliminated.
     70         * it is reverted to allow unresolved and resolved parameters
     71         * to coexist in an expression node.
     72         */
    6573        struct InferUnion {
     74                // mode is now unused
    6675                enum { Empty, Slots, Params } mode;
    67                 union data_t {
    68                         char def;
    69                         ResnSlots resnSlots;
    70                         InferredParams inferParams;
    71 
    72                         data_t() : def('\0') {}
    73                         ~data_t() {}
     76                struct data_t {
     77                        // char def;
     78                        ResnSlots * resnSlots;
     79                        InferredParams * inferParams;
     80
     81                        data_t(): resnSlots(nullptr), inferParams(nullptr) {}
     82                        data_t(const data_t &other) = delete;
     83                        ~data_t() {
     84                                delete resnSlots;
     85                                delete inferParams;
     86                        }
    7487                } data;
    7588
    7689                /// initializes from other InferUnion
    7790                void init_from( const InferUnion& o ) {
    78                         switch ( o.mode ) {
    79                         case Empty:  return;
    80                         case Slots:  new(&data.resnSlots) ResnSlots{ o.data.resnSlots }; return;
    81                         case Params: new(&data.inferParams) InferredParams{ o.data.inferParams }; return;
     91                        if (o.data.resnSlots) {
     92                                data.resnSlots = new ResnSlots(*o.data.resnSlots);
     93                        }
     94                        if (o.data.inferParams) {
     95                                data.inferParams = new InferredParams(*o.data.inferParams);
    8296                        }
    8397                }
     
    8599                /// initializes from other InferUnion (move semantics)
    86100                void init_from( InferUnion&& o ) {
    87                         switch ( o.mode ) {
    88                         case Empty:  return;
    89                         case Slots:  new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return;
    90                         case Params:
    91                                 new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return;
    92                         }
    93                 }
    94 
    95                 /// clears variant fields
    96                 void reset() {
    97                         switch( mode ) {
    98                         case Empty:  return;
    99                         case Slots:  data.resnSlots.~ResnSlots(); return;
    100                         case Params: data.inferParams.~InferredParams(); return;
    101                         }
     101                        data.resnSlots = o.data.resnSlots;
     102                        data.inferParams = o.data.inferParams;
     103                        o.data.resnSlots = nullptr;
     104                        o.data.inferParams = nullptr;
    102105                }
    103106
     
    107110                InferUnion& operator= ( const InferUnion& ) = delete;
    108111                InferUnion& operator= ( InferUnion&& ) = delete;
    109                 ~InferUnion() { reset(); }
     112
     113                bool hasSlots() const { return data.resnSlots; }
     114                bool hasParams() const { return data.inferParams; }
    110115
    111116                ResnSlots& resnSlots() {
    112                         switch (mode) {
    113                         case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; // fallthrough
    114                         case Slots: return data.resnSlots;
    115                         case Params: assertf(false, "Cannot return to resnSlots from Params"); abort();
     117                        if (!data.resnSlots) {
     118                                data.resnSlots = new ResnSlots();
    116119                        }
    117                         assertf(false, "unreachable");
     120                        return *data.resnSlots;
    118121                }
    119122
    120123                const ResnSlots& resnSlots() const {
    121                         if (mode == Slots) {
    122                                 return data.resnSlots;
     124                        if (data.resnSlots) {
     125                                return *data.resnSlots;
    123126                        }
    124127                        assertf(false, "Mode was not already resnSlots");
     
    127130
    128131                InferredParams& inferParams() {
    129                         switch (mode) {
    130                         case Slots: data.resnSlots.~ResnSlots(); // fallthrough
    131                         case Empty: new(&data.inferParams) InferredParams{}; mode = Params; // fallthrough
    132                         case Params: return data.inferParams;
     132                        if (!data.inferParams) {
     133                                data.inferParams = new InferredParams();
    133134                        }
    134                         assertf(false, "unreachable");
     135                        return *data.inferParams;
    135136                }
    136137
    137138                const InferredParams& inferParams() const {
    138                         if (mode == Params) {
    139                                 return data.inferParams;
     139                        if (data.inferParams) {
     140                                return *data.inferParams;
    140141                        }
    141142                        assertf(false, "Mode was not already Params");
     
    143144                }
    144145
    145                 void set_inferParams( InferredParams && ps ) {
    146                         switch(mode) {
    147                         case Slots:
    148                                 data.resnSlots.~ResnSlots();
    149                                 // fallthrough
    150                         case Empty:
    151                                 new(&data.inferParams) InferredParams{ std::move( ps ) };
    152                                 mode = Params;
    153                                 break;
    154                         case Params:
    155                                 data.inferParams = std::move( ps );
    156                                 break;
    157                         }
     146                void set_inferParams( InferredParams * ps ) {
     147                        delete data.resnSlots;
     148                        data.resnSlots = nullptr;
     149                        delete data.inferParams;
     150                        data.inferParams = ps;
    158151                }
    159152
     
    161154                /// and the other is in `Params`.
    162155                void splice( InferUnion && o ) {
    163                         if ( o.mode == Empty ) return;
    164                         if ( mode == Empty ) { init_from( o ); return; }
    165                         assert( mode == o.mode && "attempt to splice incompatible InferUnion" );
    166 
    167                         if ( mode == Slots ){
    168                                 data.resnSlots.insert(
    169                                         data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() );
    170                         } else if ( mode == Params ) {
    171                                 for ( const auto & p : o.data.inferParams ) {
    172                                         data.inferParams[p.first] = std::move(p.second);
     156                        if (o.data.resnSlots) {
     157                                if (data.resnSlots) {
     158                                        data.resnSlots->insert(
     159                                                data.resnSlots->end(), o.data.resnSlots->begin(), o.data.resnSlots->end() );
     160                                        delete o.data.resnSlots;
    173161                                }
    174                         } else assertf(false, "invalid mode");
     162                                else {
     163                                        data.resnSlots = o.data.resnSlots;
     164                                }
     165                                o.data.resnSlots = nullptr;
     166                        }
     167
     168                        if (o.data.inferParams) {
     169                                if (data.inferParams) {
     170                                        for ( const auto & p : *o.data.inferParams ) {
     171                                                (*data.inferParams)[p.first] = std::move(p.second);
     172                                        }
     173                                        delete o.data.inferParams;
     174                                }
     175                                else {
     176                                        data.inferParams = o.data.inferParams;
     177                                }
     178                                o.data.inferParams = nullptr;
     179                        }
    175180                }
    176181        };
     
    185190
    186191        Expr * set_extension( bool ex ) { extension = ex; return this; }
     192        virtual bool get_lvalue() const;
    187193
    188194        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    201207        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    202208
     209        bool get_lvalue() const final;
     210
    203211        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    204212private:
     
    216224        : Expr( loc ), func( f ), args( std::move(as) ) {}
    217225
     226        bool get_lvalue() const final;
     227
    218228        /// Creates a new dereference expression
    219         static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );
     229        static UntypedExpr * createDeref( const CodeLocation & loc, const Expr * arg );
    220230        /// Creates a new assignment expression
    221         static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs );
     231        static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs );
    222232
    223233        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    241251};
    242252
     253/// A reference to a named variable.
     254class VariableExpr final : public Expr {
     255public:
     256        readonly<DeclWithType> var;
     257
     258        VariableExpr( const CodeLocation & loc );
     259        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
     260
     261        bool get_lvalue() const final;
     262
     263        /// generates a function pointer for a given function
     264        static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
     265
     266        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     267private:
     268        VariableExpr * clone() const override { return new VariableExpr{ *this }; }
     269        MUTATE_FRIEND
     270};
     271
    243272/// Address-of expression `&e`
    244273class AddressExpr final : public Expr {
     
    271300};
    272301
    273 /// Whether a cast existed in the program source or not
     302/// Inidicates whether the cast is introduced by the CFA type system.
     303/// GeneratedCast for casts that the resolver introduces to force a return type
     304/// ExplicitCast for casts from user code
     305/// ExplicitCast for casts from desugaring advanced CFA features into simpler CFA
     306/// example
     307///   int * p;     // declaration
     308///   (float *) p; // use, with subject cast
     309/// subject cast being GeneratedCast means we are considering an interpretation with a type mismatch
     310/// subject cast being ExplicitCast means someone in charge wants it that way
    274311enum GeneratedFlag { ExplicitCast, GeneratedCast };
    275312
     
    291328        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    292329
     330        bool get_lvalue() const final;
     331
    293332        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    294333private:
     
    301340public:
    302341        ptr<Expr> arg;
     342        struct Concrete {
     343                std::string field;
     344                std::string getter;
     345
     346                Concrete() = default;
     347                Concrete(const Concrete &) = default;
     348        };
    303349        ast::AggregateDecl::Aggregate target;
     350        Concrete concrete_target;
     351
    304352
    305353        KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t )
    306354        : Expr( loc ), arg( a ), target( t ) {}
    307355
     356        KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t, const Concrete & ct )
     357        : Expr( loc ), arg( a ), target( t ), concrete_target( ct ) {}
     358
    308359        /// Get a name for the target type
    309360        const char * targetString() const;
     
    338389        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    339390
     391        bool get_lvalue() const final;
     392
    340393        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    341394private:
     
    352405        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    353406
     407        bool get_lvalue() const final;
     408
    354409        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    355410private:
    356411        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    357412        MUTATE_FRIEND
    358 };
    359 
    360 /// A reference to a named variable.
    361 class VariableExpr final : public Expr {
    362 public:
    363         readonly<DeclWithType> var;
    364 
    365         VariableExpr( const CodeLocation & loc );
    366         VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    367 
    368         /// generates a function pointer for a given function
    369         static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
    370 
    371         const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    372 private:
    373         VariableExpr * clone() const override { return new VariableExpr{ *this }; }
    374         MUTATE_FRIEND
     413
     414        // Custructor overload meant only for AST conversion
     415        enum NoOpConstruction { NoOpConstructionChosen };
     416        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     417            NoOpConstruction overloadSelector );
     418        friend class ::ConverterOldToNew;
     419        friend class ::ConverterNewToOld;
    375420};
    376421
     
    386431                const CodeLocation & loc, const Type * ty, const std::string & r,
    387432                        std::optional<unsigned long long> i )
    388         : Expr( loc, ty ), rep( r ), ival( i ) {}
     433        : Expr( loc, ty ), rep( r ), ival( i ), underlyer(ty) {}
    389434
    390435        /// Gets the integer value of this constant, if one is appropriate to its type.
     
    532577
    533578        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    534         : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
     579        : Expr( loc ), arg1( a1 ), arg2( a2 ) {
     580                this->result = a2->result;
     581        }
     582
     583        bool get_lvalue() const final;
    535584
    536585        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    577626
    578627        ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
    579         : Expr( loc, call->result ) { assert( call ); }
     628        : Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); }
    580629
    581630        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    605654        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    606655
     656        bool get_lvalue() const final;
     657
    607658        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    608659private:
     
    660711
    661712        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
     713
     714        bool get_lvalue() const final;
    662715
    663716        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    698751        std::vector<ptr<Expr>> dtors;              ///< destructor(s) for return variable(s)
    699752
     753        readonly<ExprStmt> resultExpr;
     754
    700755        StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
    701756
Note: See TracChangeset for help on using the changeset viewer.