Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.hpp

    rb3a0df6 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; }
    114                 bool hasParams() const { return data.inferParams; }
     109                ~InferUnion() { reset(); }
    115110
    116111                ResnSlots& resnSlots() {
    117                         if (!data.resnSlots) {
    118                                 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();
    119116                        }
    120                         return *data.resnSlots;
     117                        assertf(false, "unreachable");
    121118                }
    122119
    123120                const ResnSlots& resnSlots() const {
    124                         if (data.resnSlots) {
    125                                 return *data.resnSlots;
     121                        if (mode == Slots) {
     122                                return data.resnSlots;
    126123                        }
    127124                        assertf(false, "Mode was not already resnSlots");
     
    130127
    131128                InferredParams& inferParams() {
    132                         if (!data.inferParams) {
    133                                 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;
    134133                        }
    135                         return *data.inferParams;
     134                        assertf(false, "unreachable");
    136135                }
    137136
    138137                const InferredParams& inferParams() const {
    139                         if (data.inferParams) {
    140                                 return *data.inferParams;
     138                        if (mode == Params) {
     139                                return data.inferParams;
    141140                        }
    142141                        assertf(false, "Mode was not already Params");
     
    144143                }
    145144
    146                 void set_inferParams( InferredParams * ps ) {
    147                         delete data.resnSlots;
    148                         data.resnSlots = nullptr;
    149                         delete data.inferParams;
    150                         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                        }
    151158                }
    152159
     
    154161                /// and the other is in `Params`.
    155162                void splice( InferUnion && o ) {
    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;
     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);
    161173                                }
    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                         }
     174                        } else assertf(false, "invalid mode");
    180175                }
    181176        };
     
    190185
    191186        Expr * set_extension( bool ex ) { extension = ex; return this; }
    192         virtual bool get_lvalue() const;
    193187
    194188        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    207201        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    208202
    209         bool get_lvalue() const final;
    210 
    211203        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    212204private:
     
    224216        : Expr( loc ), func( f ), args( std::move(as) ) {}
    225217
    226         bool get_lvalue() const final;
    227 
    228218        /// Creates a new dereference expression
    229         static UntypedExpr * createDeref( const CodeLocation & loc, const Expr * arg );
     219        static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );
    230220        /// Creates a new assignment expression
    231         static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs );
     221        static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs );
    232222
    233223        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    251241};
    252242
    253 /// A reference to a named variable.
    254 class VariableExpr final : public Expr {
    255 public:
    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 ); }
    267 private:
    268         VariableExpr * clone() const override { return new VariableExpr{ *this }; }
    269         MUTATE_FRIEND
    270 };
    271 
    272243/// Address-of expression `&e`
    273244class AddressExpr final : public Expr {
     
    300271};
    301272
    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
     273/// Whether a cast existed in the program source or not
    311274enum GeneratedFlag { ExplicitCast, GeneratedCast };
    312275
     
    328291        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    329292
    330         bool get_lvalue() const final;
    331 
    332293        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    333294private:
     
    340301public:
    341302        ptr<Expr> arg;
    342         struct Concrete {
    343                 std::string field;
    344                 std::string getter;
    345 
    346                 Concrete() = default;
    347                 Concrete(const Concrete &) = default;
    348         };
    349303        ast::AggregateDecl::Aggregate target;
    350         Concrete concrete_target;
    351 
    352304
    353305        KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t )
    354306        : Expr( loc ), arg( a ), target( t ) {}
    355307
    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 
    359308        /// Get a name for the target type
    360309        const char * targetString() const;
     
    389338        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    390339
    391         bool get_lvalue() const final;
    392 
    393340        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    394341private:
     
    405352        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    406353
    407         bool get_lvalue() const final;
    408 
    409354        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    410355private:
    411356        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    412357        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;
     358};
     359
     360/// A reference to a named variable.
     361class VariableExpr final : public Expr {
     362public:
     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 ); }
     372private:
     373        VariableExpr * clone() const override { return new VariableExpr{ *this }; }
     374        MUTATE_FRIEND
    420375};
    421376
     
    431386                const CodeLocation & loc, const Type * ty, const std::string & r,
    432387                        std::optional<unsigned long long> i )
    433         : Expr( loc, ty ), rep( r ), ival( i ), underlyer(ty) {}
     388        : Expr( loc, ty ), rep( r ), ival( i ) {}
    434389
    435390        /// Gets the integer value of this constant, if one is appropriate to its type.
     
    577532
    578533        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    579         : Expr( loc ), arg1( a1 ), arg2( a2 ) {
    580                 this->result = a2->result;
    581         }
    582 
    583         bool get_lvalue() const final;
     534        : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
    584535
    585536        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    626577
    627578        ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
    628         : Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); }
     579        : Expr( loc, call->result ) { assert( call ); }
    629580
    630581        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    654605        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    655606
    656         bool get_lvalue() const final;
    657 
    658607        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    659608private:
     
    711660
    712661        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
    713 
    714         bool get_lvalue() const final;
    715662
    716663        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    751698        std::vector<ptr<Expr>> dtors;              ///< destructor(s) for return variable(s)
    752699
    753         readonly<ExprStmt> resultExpr;
    754 
    755700        StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
    756701
Note: See TracChangeset for help on using the changeset viewer.