Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.hpp

    r07d867b r312029a  
    3131
    3232// Must be included in *all* AST classes; should be #undef'd at the end of the file
    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 
     33#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3734
    3835class ConverterOldToNew;
     
    4542struct ParamEntry {
    4643        UniqueId decl;
    47         readonly<Decl> declptr;
     44        ptr<Decl> declptr;
    4845        ptr<Type> actualType;
    4946        ptr<Type> formalType;
     
    6562class Expr : public ParseNode {
    6663public:
    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          */
     64        /// Saves space (~16 bytes) by combining ResnSlots and InferredParams
    7365        struct InferUnion {
    74                 // mode is now unused
    7566                enum { Empty, Slots, Params } mode;
    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                         }
     67                union data_t {
     68                        char def;
     69                        ResnSlots resnSlots;
     70                        InferredParams inferParams;
     71
     72                        data_t() : def('\0') {}
     73                        ~data_t() {}
    8774                } data;
    8875
    8976                /// initializes from other InferUnion
    9077                void init_from( const InferUnion& o ) {
    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);
     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;
    9682                        }
    9783                }
     
    9985                /// initializes from other InferUnion (move semantics)
    10086                void init_from( InferUnion&& o ) {
    101                         data.resnSlots = o.data.resnSlots;
    102                         data.inferParams = o.data.inferParams;
    103                         o.data.resnSlots = nullptr;
    104                         o.data.inferParams = nullptr;
     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                        }
    105102                }
    106103
     
    110107                InferUnion& operator= ( const InferUnion& ) = delete;
    111108                InferUnion& operator= ( InferUnion&& ) = delete;
    112 
    113                 bool hasSlots() const { return data.resnSlots; }
     109                ~InferUnion() { reset(); }
    114110
    115111                ResnSlots& resnSlots() {
    116                         if (!data.resnSlots) {
    117                                 data.resnSlots = new 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();
    118116                        }
    119                         return *data.resnSlots;
     117                        assertf(false, "unreachable");
    120118                }
    121119
    122120                const ResnSlots& resnSlots() const {
    123                         if (data.resnSlots) {
    124                                 return *data.resnSlots;
     121                        if (mode == Slots) {
     122                                return data.resnSlots;
    125123                        }
    126124                        assertf(false, "Mode was not already resnSlots");
     
    129127
    130128                InferredParams& inferParams() {
    131                         if (!data.inferParams) {
    132                                 data.inferParams = new InferredParams();
     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;
    133133                        }
    134                         return *data.inferParams;
     134                        assertf(false, "unreachable");
    135135                }
    136136
    137137                const InferredParams& inferParams() const {
    138                         if (data.inferParams) {
    139                                 return *data.inferParams;
     138                        if (mode == Params) {
     139                                return data.inferParams;
    140140                        }
    141141                        assertf(false, "Mode was not already Params");
     
    143143                }
    144144
    145                 void set_inferParams( InferredParams * ps ) {
    146                         delete data.resnSlots;
    147                         data.resnSlots = nullptr;
    148                         delete data.inferParams;
    149                         data.inferParams = ps;
     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                        }
    150158                }
    151159
     
    153161                /// and the other is in `Params`.
    154162                void splice( InferUnion && o ) {
    155                         if (o.data.resnSlots) {
    156                                 if (data.resnSlots) {
    157                                         data.resnSlots->insert(
    158                                                 data.resnSlots->end(), o.data.resnSlots->begin(), o.data.resnSlots->end() );
    159                                         delete o.data.resnSlots;
     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);
    160173                                }
    161                                 else {
    162                                         data.resnSlots = o.data.resnSlots;
    163                                 }
    164                                 o.data.resnSlots = nullptr;
    165                         }
    166 
    167                         if (o.data.inferParams) {
    168                                 if (data.inferParams) {
    169                                         for ( const auto & p : *o.data.inferParams ) {
    170                                                 (*data.inferParams)[p.first] = std::move(p.second);
    171                                         }
    172                                         delete o.data.inferParams;
    173                                 }
    174                                 else {
    175                                         data.inferParams = o.data.inferParams;
    176                                 }
    177                                 o.data.inferParams = nullptr;
    178                         }
     174                        } else assertf(false, "invalid mode");
    179175                }
    180176        };
     
    189185
    190186        Expr * set_extension( bool ex ) { extension = ex; return this; }
    191         virtual bool get_lvalue() const;
    192187
    193188        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    206201        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    207202
    208         bool get_lvalue() const final;
    209 
    210203        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    211204private:
     
    222215        UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
    223216        : Expr( loc ), func( f ), args( std::move(as) ) {}
    224 
    225         bool get_lvalue() const final;
    226217
    227218        /// Creates a new dereference expression
     
    300291        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    301292
    302         bool get_lvalue() const final;
    303 
    304293        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    305294private:
     
    349338        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    350339
    351         bool get_lvalue() const final;
    352 
    353340        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    354341private:
     
    365352        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    366353
    367         bool get_lvalue() const final;
    368 
    369354        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    370355private:
    371356        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    372357        MUTATE_FRIEND
    373 
    374         // Custructor overload meant only for AST conversion
    375         enum NoOpConstruction { NoOpConstructionChosen };
    376         MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
    377             NoOpConstruction overloadSelector );
    378         friend class ::ConverterOldToNew;
    379         friend class ::ConverterNewToOld;
    380358};
    381359
     
    387365        VariableExpr( const CodeLocation & loc );
    388366        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    389 
    390         bool get_lvalue() const final;
    391367
    392368        /// generates a function pointer for a given function
     
    556532
    557533        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    558         : Expr( loc ), arg1( a1 ), arg2( a2 ) {
    559                 this->result = a2->result;
    560         }
    561 
    562         bool get_lvalue() const final;
     534        : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
    563535
    564536        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    633605        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    634606
    635         bool get_lvalue() const final;
    636 
    637607        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    638608private:
     
    690660
    691661        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
    692 
    693         bool get_lvalue() const final;
    694662
    695663        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
Note: See TracChangeset for help on using the changeset viewer.