source: src/AST/Expr.hpp @ d7a02ae

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since d7a02ae was 60aaa51d, checked in by Aaron Moss <a3moss@…>, 5 years ago

More resolver porting; mostly CurrentObject?

  • Property mode set to 100644
File size: 24.9 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Expr.hpp --
8//
9// Author           : Aaron B. Moss
10// Created On       : Fri May 10 10:30:00 2019
11// Last Modified By : Aaron B. Moss
12// Created On       : Fri May 10 10:30:00 2019
13// Update Count     : 1
14//
15
16#pragma once
17
18#include <cassert>
19#include <deque>
20#include <map>
21#include <string>
22#include <utility>        // for move
23#include <vector>
24
25#include "Fwd.hpp"        // for UniqueId
26#include "Label.hpp"
27#include "ParseNode.hpp"
28#include "Visitor.hpp"
29
30// Must be included in *all* AST classes; should be #undef'd at the end of the file
31#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
32
33class ConverterOldToNew;
34
35namespace ast {
36
37/// Contains the ID of a declaration and a type that is derived from that declaration,
38/// but subject to decay-to-pointer and type parameter renaming
39struct ParamEntry {
40        UniqueId decl;
41        ptr<Type> actualType;
42        ptr<Type> formalType;
43        ptr<Expr> expr;
44
45        ParamEntry() : decl( 0 ), actualType( nullptr ), formalType( nullptr ), expr( nullptr ) {}
46        ParamEntry( UniqueId id, Type* actual, Type* formal, Expr* e )
47        : decl( id ), actualType( actual ), formalType( formal ), expr( e ) {}
48};
49
50/// Pre-resolution list of parameters to infer
51using ResnSlots = std::vector<UniqueId>;
52/// Post-resolution map of inferred parameters
53using InferredParams = std::map< UniqueId, ParamEntry >;
54
55/// Base node for expressions
56class Expr : public ParseNode {
57public:
58        /// Saves space (~16 bytes) by combining ResnSlots and InferredParams
59        struct InferUnion {
60                enum { Empty, Slots, Params } mode;
61                union data_t {
62                        char def;
63                        ResnSlots resnSlots;
64                        InferredParams inferParams;
65
66                        data_t() : def('\0') {}
67                        ~data_t() {}
68                } data;
69
70                /// initializes from other InferUnion
71                void init_from( const InferUnion& o ) {
72                        switch ( o.mode ) {
73                        case Empty:  return;
74                        case Slots:  new(&data.resnSlots) ResnSlots{ o.data.resnSlots }; return;
75                        case Params: new(&data.inferParams) InferredParams{ o.data.inferParams }; return;
76                        }
77                }
78
79                /// initializes from other InferUnion (move semantics)
80                void init_from( InferUnion&& o ) {
81                        switch ( o.mode ) {
82                        case Empty:  return;
83                        case Slots:  new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return;
84                        case Params:
85                                new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return;
86                        }
87                }
88
89                /// clears variant fields
90                void reset() {
91                        switch( mode ) {
92                        case Empty:  return;
93                        case Slots:  data.resnSlots.~ResnSlots(); return;
94                        case Params: data.inferParams.~InferredParams(); return;
95                        }
96                }
97
98                InferUnion() : mode(Empty), data() {}
99                InferUnion( const InferUnion& o ) : mode( o.mode ), data() { init_from( o ); }
100                InferUnion( InferUnion&& o ) : mode( o.mode ), data() { init_from( std::move(o) ); }
101                InferUnion& operator= ( const InferUnion& ) = delete;
102                InferUnion& operator= ( InferUnion&& ) = delete;
103                ~InferUnion() { reset(); }
104
105                ResnSlots& resnSlots() {
106                        switch (mode) {
107                        case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; // fallthrough
108                        case Slots: return data.resnSlots;
109                        case Params: assert(!"Cannot return to resnSlots from Params");
110                        }
111                        return *((ResnSlots*)nullptr);
112                }
113
114                const ResnSlots& resnSlots() const {
115                        if (mode == Slots) {
116                                return data.resnSlots;
117                        }
118                        assert(!"Mode was not already resnSlots");
119                        return *((ResnSlots*)nullptr);
120                }
121
122                InferredParams& inferParams() {
123                        switch (mode) {
124                        case Slots: data.resnSlots.~ResnSlots(); // fallthrough
125                        case Empty: new(&data.inferParams) InferredParams{}; mode = Params; // fallthrough
126                        case Params: return data.inferParams;
127                        }
128                        return *((InferredParams*)nullptr);
129                }
130
131                const InferredParams& inferParams() const {
132                        if (mode == Params) {
133                                return data.inferParams;
134                        }
135                        assert(!"Mode was not already Params");
136                        return *((InferredParams*)nullptr);
137                }
138
139                /// splices other InferUnion into this one. Will fail if one union is in `Slots` mode
140                /// and the other is in `Params`.
141                void splice( InferUnion && o ) {
142                        if ( o.mode == Empty ) return;
143                        if ( mode == Empty ) { init_from( o ); return; }
144                        assert( mode == o.mode && "attempt to splice incompatible InferUnion" );
145
146                        if ( mode == Slots ){
147                                data.resnSlots.insert( 
148                                        data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() );
149                        } else if ( mode == Params ) {
150                                for ( const auto & p : o.data.inferParams ) {
151                                        data.inferParams[p.first] = std::move(p.second);
152                                }
153                        } else assert(!"invalid mode");
154                }
155        };
156
157        ptr<Type> result;
158        ptr<TypeSubstitution> env;
159        InferUnion inferred;
160        bool extension = false;
161
162        Expr( const CodeLocation & loc, const Type * res = nullptr )
163        : ParseNode( loc ), result( res ), env(), inferred() {}
164
165        Expr * set_extension( bool ex ) { extension = ex; return this; }
166
167        virtual const Expr * accept( Visitor & v ) const override = 0;
168private:
169        Expr * clone() const override = 0;
170        MUTATE_FRIEND
171};
172
173/// The application of a function to a set of parameters.
174/// Post-resolver form of `UntypedExpr`
175class ApplicationExpr final : public Expr {
176public:
177        ptr<Expr> func;
178        std::vector<ptr<Expr>> args;
179
180        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
181
182        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
183private:
184        ApplicationExpr * clone() const override { return new ApplicationExpr{ *this }; }
185        MUTATE_FRIEND
186};
187
188/// The application of a function to a set of parameters, pre-overload resolution.
189class UntypedExpr final : public Expr {
190public:
191        ptr<Expr> func;
192        std::vector<ptr<Expr>> args;
193
194        UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
195        : Expr( loc ), func( f ), args( std::move(as) ) {}
196
197        /// Creates a new dereference expression
198        static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );
199        /// Creates a new assignment expression
200        static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs );
201
202        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
203private:
204        UntypedExpr * clone() const override { return new UntypedExpr{ *this }; }
205        MUTATE_FRIEND
206};
207
208/// A name whose name is as-yet undetermined.
209/// May also be used to avoid name mangling in codegen phase.
210class NameExpr final : public Expr {
211public:
212        std::string name;
213
214        NameExpr( const CodeLocation & loc, const std::string & n ) : Expr( loc ), name( n ) {}
215
216        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
217private:
218        NameExpr * clone() const override { return new NameExpr{ *this }; }
219        MUTATE_FRIEND
220};
221
222/// Address-of expression `&e`
223class AddressExpr final : public Expr {
224public:
225        ptr<Expr> arg;
226
227        AddressExpr( const CodeLocation & loc, const Expr * a );
228
229        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
230private:
231        AddressExpr * clone() const override { return new AddressExpr{ *this }; }
232        MUTATE_FRIEND
233};
234
235/// GCC &&label
236/// https://gcc.gnu.org/onlinedocs/gcc-3.4.2/gcc/Labels-as-Values.html
237class LabelAddressExpr final : public Expr {
238public:
239        Label arg;
240
241        LabelAddressExpr( const CodeLocation & loc, Label && a );
242
243        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
244private:
245        LabelAddressExpr * clone() const override { return new LabelAddressExpr{ *this }; }
246        MUTATE_FRIEND
247};
248
249/// Whether a cast existed in the program source or not
250enum GeneratedFlag { ExplicitCast, GeneratedCast };
251
252/// A type cast, e.g. `(int)e`
253class CastExpr final : public Expr {
254public:
255        ptr<Expr> arg;
256        GeneratedFlag isGenerated;
257
258        CastExpr( const CodeLocation & loc, const Expr * a, const Type * to,
259                GeneratedFlag g = GeneratedCast ) : Expr( loc, to ), arg( a ), isGenerated( g ) {}
260        /// Cast-to-void
261        CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast );
262
263        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
264private:
265        CastExpr * clone() const override { return new CastExpr{ *this }; }
266        MUTATE_FRIEND
267};
268
269/// A cast to "keyword types", e.g. `(thread &)t`
270class KeywordCastExpr final : public Expr {
271public:
272        ptr<Expr> arg;
273        enum Target { Coroutine, Thread, Monitor, NUMBER_OF_TARGETS } target;
274
275        KeywordCastExpr( const CodeLocation & loc, const Expr * a, Target t )
276        : Expr( loc ), arg( a ), target( t ) {}
277
278        /// Get a name for the target type
279        const std::string& targetString() const;
280
281        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
282private:
283        KeywordCastExpr * clone() const override { return new KeywordCastExpr{ *this }; }
284        MUTATE_FRIEND
285};
286
287/// A virtual dynamic cast, e.g. `(virtual exception)e`
288class VirtualCastExpr final : public Expr {
289public:
290        ptr<Expr> arg;
291
292        VirtualCastExpr( const CodeLocation & loc, const Expr * a, const Type * to )
293        : Expr( loc, to ), arg( a ) {}
294
295        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
296private:
297        VirtualCastExpr * clone() const override { return new VirtualCastExpr{ *this }; }
298        MUTATE_FRIEND
299};
300
301/// A member selection operation before expression resolution, e.g. `q.p`
302class UntypedMemberExpr final : public Expr {
303public:
304        ptr<Expr> member;
305        ptr<Expr> aggregate;
306
307        UntypedMemberExpr( const CodeLocation & loc, const Expr * mem, const Expr * agg )
308        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
309
310        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
311private:
312        UntypedMemberExpr * clone() const override { return new UntypedMemberExpr{ *this }; }
313        MUTATE_FRIEND
314};
315
316/// A member selection operation after expression resolution, e.g. `q.p`
317class MemberExpr final : public Expr {
318public:
319        readonly<DeclWithType> member;
320        ptr<Expr> aggregate;
321
322        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
323
324        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
325private:
326        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
327        MUTATE_FRIEND
328};
329
330/// A reference to a named variable.
331class VariableExpr final : public Expr {
332public:
333        readonly<DeclWithType> var;
334
335        VariableExpr( const CodeLocation & loc );
336        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
337
338        /// generates a function pointer for a given function
339        static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
340
341        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
342private:
343        VariableExpr * clone() const override { return new VariableExpr{ *this }; }
344        MUTATE_FRIEND
345};
346
347/// A compile-time constant
348class ConstantExpr final : public Expr {
349        union Val {
350                unsigned long long ival;
351                double dval;
352
353                Val( unsigned long long i ) : ival( i ) {}
354                Val( double d ) : dval( d ) {}
355        } val;
356public:
357        std::string rep;
358        enum Kind { Integer, FloatingPoint, String } kind;
359
360        ConstantExpr(
361                const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v,
362                Kind k = Integer )
363        : Expr( loc, ty ), val( v ), rep( r ), kind( k ) {}
364        ConstantExpr( const CodeLocation & loc, const Type * ty, const std::string & r, double v )
365        : Expr( loc, ty ), val( v ), rep( r ), kind( FloatingPoint ) {}
366
367        /// Gets the value of this constant as an integer
368        long long int intValue() const;
369        /// Gets the value of this constant as floating point
370        double floatValue() const;
371
372        /// generates a boolean constant of the given bool
373        static ConstantExpr * from_bool( const CodeLocation & loc, bool b );
374        /// generates a char constant of the given char
375        static ConstantExpr * from_char( const CodeLocation & loc, char c );
376        /// generates an integer constant of the given int
377        static ConstantExpr * from_int( const CodeLocation & loc, int i );
378        /// generates an integer constant of the given unsigned long int
379        static ConstantExpr * from_ulong( const CodeLocation & loc, unsigned long i );
380        /// generates a floating point constant of the given double
381        static ConstantExpr * from_double( const CodeLocation & loc, double d );
382        /// generates an array of chars constant of the given string
383        static ConstantExpr * from_string( const CodeLocation & loc, const std::string & s );
384        /// generates a null pointer value for the given type. void * if omitted.
385        static ConstantExpr * null( const CodeLocation & loc, const Type * ptrType = nullptr );
386
387        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
388private:
389        ConstantExpr * clone() const override { return new ConstantExpr{ *this }; }
390        MUTATE_FRIEND
391};
392
393/// sizeof expression, e.g. `sizeof(int)`, `sizeof 3+4`
394class SizeofExpr final : public Expr {
395public:
396        ptr<Expr> expr;
397        ptr<Type> type;
398
399        SizeofExpr( const CodeLocation & loc, const Expr * e );
400        SizeofExpr( const CodeLocation & loc, const Type * t );
401        // deliberately no disambiguating overload for nullptr_t
402
403        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
404private:
405        SizeofExpr * clone() const override { return new SizeofExpr{ *this }; }
406        MUTATE_FRIEND
407};
408
409/// alignof expression, e.g. `alignof(int)`, `alignof 3+4`
410class AlignofExpr final : public Expr {
411public:
412        ptr<Expr> expr;
413        ptr<Type> type;
414
415        AlignofExpr( const CodeLocation & loc, const Expr * e );
416        AlignofExpr( const CodeLocation & loc, const Type * t );
417        // deliberately no disambiguating overload for nullptr_t
418
419        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
420private:
421        AlignofExpr * clone() const override { return new AlignofExpr{ *this }; }
422        MUTATE_FRIEND
423};
424
425/// offsetof expression before resolver determines field, e.g. `offsetof(MyStruct, myfield)`
426class UntypedOffsetofExpr final : public Expr {
427public:
428        ptr<Type> type;
429        std::string member;
430
431        UntypedOffsetofExpr( const CodeLocation & loc, const Type * ty, const std::string & mem )
432        : Expr( loc ), type( ty ), member( mem ) {}
433
434        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
435private:
436        UntypedOffsetofExpr * clone() const override { return new UntypedOffsetofExpr{ *this }; }
437        MUTATE_FRIEND
438};
439
440/// offsetof expression after resolver determines field, e.g. `offsetof(MyStruct, myfield)`
441class OffsetofExpr final : public Expr {
442public:
443        ptr<Type> type;
444        readonly<DeclWithType> member;
445
446        OffsetofExpr( const CodeLocation & loc, const Type * ty, const DeclWithType * mem );
447
448        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
449private:
450        OffsetofExpr * clone() const override { return new OffsetofExpr{ *this }; }
451        MUTATE_FRIEND
452};
453
454/// a pack of field-offsets for a generic type
455class OffsetPackExpr final : public Expr {
456public:
457        ptr<StructInstType> type;
458
459        OffsetPackExpr( const CodeLocation & loc, const StructInstType * ty );
460
461        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
462private:
463        OffsetPackExpr * clone() const override { return new OffsetPackExpr{ *this }; }
464        MUTATE_FRIEND
465};
466
467/// Variants of short-circuiting logical expression
468enum LogicalFlag { OrExpr, AndExpr };
469
470/// Short-circuiting boolean expression (`&&` or `||`)
471class LogicalExpr final : public Expr {
472public:
473        ptr<Expr> arg1;
474        ptr<Expr> arg2;
475        LogicalFlag isAnd;
476
477        LogicalExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia );
478
479        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
480private:
481        LogicalExpr * clone() const override { return new LogicalExpr{ *this }; }
482        MUTATE_FRIEND
483};
484
485/// Three-argument conditional e.g. `p ? a : b`
486class ConditionalExpr final : public Expr {
487public:
488        ptr<Expr> arg1;
489        ptr<Expr> arg2;
490        ptr<Expr> arg3;
491
492        ConditionalExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2, const Expr * a3 )
493        : Expr( loc ), arg1( a1 ), arg2( a2 ), arg3( a3 ) {}
494
495        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
496private:
497        ConditionalExpr * clone() const override { return new ConditionalExpr{ *this }; }
498        MUTATE_FRIEND
499};
500
501/// Comma expression e.g. `( a , b )`
502class CommaExpr final : public Expr {
503public:
504        ptr<Expr> arg1;
505        ptr<Expr> arg2;
506
507        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
508        : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
509
510        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
511private:
512        CommaExpr * clone() const override { return new CommaExpr{ *this }; }
513        MUTATE_FRIEND
514};
515
516/// A type used as an expression (e.g. a type generator parameter)
517class TypeExpr final : public Expr {
518public:
519        ptr<Type> type;
520
521        TypeExpr( const CodeLocation & loc, const Type * t ) : Expr(loc), type(t) {}
522
523        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
524private:
525        TypeExpr * clone() const override { return new TypeExpr{ *this }; }
526        MUTATE_FRIEND
527};
528
529/// A GCC "asm constraint operand" used in an asm statement, e.g. `[output] "=f" (result)`.
530/// https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
531class AsmExpr final : public Expr {
532public:
533        ptr<Expr> inout;
534        ptr<Expr> constraint;
535        ptr<Expr> operand;
536
537        AsmExpr( const CodeLocation & loc, const Expr * io, const Expr * con, const Expr * op )
538        : Expr( loc ), inout( io ), constraint( con ), operand( op ) {}
539
540        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
541private:
542        AsmExpr * clone() const override { return new AsmExpr{ *this }; }
543        MUTATE_FRIEND
544};
545
546/// The application of a function to a set of parameters, along with a set of copy constructor
547/// calls, one for each argument
548class ImplicitCopyCtorExpr final : public Expr {
549public:
550        ptr<ApplicationExpr> callExpr;
551
552        ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
553        : Expr( loc, call->result ) { assert( call ); }
554
555        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
556private:
557        ImplicitCopyCtorExpr * clone() const override { return new ImplicitCopyCtorExpr{ *this }; }
558        MUTATE_FRIEND
559};
560
561/// Constructor in expression context, e.g. `int * x = alloc() { 42 };`
562class ConstructorExpr final : public Expr {
563public:
564        ptr<Expr> callExpr;
565
566        ConstructorExpr( const CodeLocation & loc, const Expr * call );
567
568        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
569private:
570        ConstructorExpr * clone() const override { return new ConstructorExpr{ *this }; }
571        MUTATE_FRIEND
572};
573
574/// A C99 compound literal, e.g. `(MyType){ a, b, c }`
575class CompoundLiteralExpr final : public Expr {
576public:
577        ptr<Init> init;
578
579        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
580
581        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
582private:
583        CompoundLiteralExpr * clone() const override { return new CompoundLiteralExpr{ *this }; }
584        MUTATE_FRIEND
585};
586
587/// A range, e.g. `3 ... 5` or `1~10`
588class RangeExpr final : public Expr {
589public:
590        ptr<Expr> low;
591        ptr<Expr> high;
592
593        RangeExpr( const CodeLocation & loc, const Expr * l, const Expr * h )
594        : Expr( loc ), low( l ), high( h ) {}
595
596        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
597private:
598        RangeExpr * clone() const override { return new RangeExpr{ *this }; }
599        MUTATE_FRIEND
600};
601
602/// A tuple expression before resolution, e.g. `[a, b, c]`
603class UntypedTupleExpr final : public Expr {
604public:
605        std::vector<ptr<Expr>> exprs;
606
607        UntypedTupleExpr( const CodeLocation & loc, std::vector<ptr<Expr>> && xs )
608        : Expr( loc ), exprs( std::move(xs) ) {}
609
610        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
611private:
612        UntypedTupleExpr * clone() const override { return new UntypedTupleExpr{ *this }; }
613        MUTATE_FRIEND
614};
615
616/// A tuple expression after resolution, e.g. `[a, b, c]`
617class TupleExpr final : public Expr {
618public:
619        std::vector<ptr<Expr>> exprs;
620
621        TupleExpr( const CodeLocation & loc, std::vector<ptr<Expr>> && xs );
622
623        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
624private:
625        TupleExpr * clone() const override { return new TupleExpr{ *this }; }
626        MUTATE_FRIEND
627};
628
629/// An element selection operation on a tuple value, e.g. `t.3` after analysis
630class TupleIndexExpr final : public Expr {
631public:
632        ptr<Expr> tuple;
633        unsigned index;
634
635        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
636
637        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
638private:
639        TupleIndexExpr * clone() const override { return new TupleIndexExpr{ *this }; }
640        MUTATE_FRIEND
641};
642
643/// A multiple- or mass-assignment operation, or a tuple ctor/dtor expression.
644/// multiple-assignment: both sides of the assignment have tuple type,
645///     e.g. `[a, b, c] = [d, e, f];`
646/// mass-assignment: left-hand side has tuple type and right-hand side does not:
647///     e.g. `[a, b, c] = 42;`
648class TupleAssignExpr final : public Expr {
649public:
650        ptr<StmtExpr> stmtExpr;
651
652        TupleAssignExpr(
653                const CodeLocation & loc, std::vector<ptr<Expr>> && assigns,
654                std::vector<ptr<ObjectDecl>> && tempDecls );
655
656        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
657
658        friend class ::ConverterOldToNew;
659
660private:
661        TupleAssignExpr * clone() const override { return new TupleAssignExpr{ *this }; }
662    TupleAssignExpr( const CodeLocation & loc, const Type * result, const StmtExpr * s );
663
664        MUTATE_FRIEND
665};
666
667/// A GCC "statement expression", e.g. `({ int x = 5; x })`
668class StmtExpr final : public Expr {
669public:
670        ptr<CompoundStmt> stmts;
671        std::vector<ptr<ObjectDecl>> returnDecls;  ///< return variable(s) for statement expression
672        std::vector<ptr<Expr>> dtors;              ///< destructor(s) for return variable(s)
673
674        StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
675
676        /// Set the result type of this StmtExpr based on its body
677        void computeResult();
678
679        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
680private:
681        StmtExpr * clone() const override { return new StmtExpr{ *this }; }
682        MUTATE_FRIEND
683};
684
685/// An expression which must only be evaluated once
686class UniqueExpr final : public Expr {
687        static unsigned long long nextId;
688public:
689        ptr<Expr> expr;
690        ptr<ObjectDecl> object;
691        ptr<VariableExpr> var;
692        unsigned long long id;
693
694        UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i = -1 );
695
696        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
697private:
698        UniqueExpr * clone() const override { return new UniqueExpr{ *this }; }
699        MUTATE_FRIEND
700};
701
702/// One option for resolving an initializer expression
703struct InitAlternative {
704        ptr<Type> type;
705        ptr<Designation> designation;
706
707        InitAlternative() = default;
708        InitAlternative( const Type * ty, const Designation * des ) : type( ty ), designation( des ) {}
709};
710
711/// Pre-resolution initializer expression
712class UntypedInitExpr final : public Expr {
713public:
714        ptr<Expr> expr;
715        std::deque<InitAlternative> initAlts;
716
717        UntypedInitExpr( const CodeLocation & loc, const Expr * e, std::deque<InitAlternative> && as )
718        : Expr( loc ), expr( e ), initAlts( std::move(as) ) {}
719
720        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
721private:
722        UntypedInitExpr * clone() const override { return new UntypedInitExpr{ *this }; }
723        MUTATE_FRIEND
724};
725
726/// Post-resolution initializer expression
727class InitExpr final : public Expr {
728public:
729        ptr<Expr> expr;
730        ptr<Designation> designation;
731
732        InitExpr( const CodeLocation & loc, const Expr * e, const Designation * des )
733        : Expr( loc, e->result ), expr( e ), designation( des ) {}
734
735        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
736private:
737        InitExpr * clone() const override { return new InitExpr{ *this }; }
738        MUTATE_FRIEND
739};
740
741/// Expression containing a deleted identifier.
742/// Internal to resolver.
743class DeletedExpr final : public Expr {
744public:
745        ptr<Expr> expr;
746        readonly<Node> deleteStmt;
747
748        DeletedExpr( const CodeLocation & loc, const Expr * e, const Node * del )
749        : Expr( loc, e->result ), expr( e ), deleteStmt( del ) { assert( expr->result ); }
750
751        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
752private:
753        DeletedExpr * clone() const override { return new DeletedExpr{ *this }; }
754        MUTATE_FRIEND
755};
756
757/// Use of a default argument.
758/// Internal to resolver.
759class DefaultArgExpr final : public Expr {
760public:
761        ptr<Expr> expr;
762
763        DefaultArgExpr( const CodeLocation & loc, const Expr * e )
764        : Expr( loc, e->result ), expr( e ) { assert( e->result ); }
765
766        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
767private:
768        DefaultArgExpr * clone() const override { return new DefaultArgExpr{ *this }; }
769        MUTATE_FRIEND
770};
771
772/// C11 _Generic expression
773class GenericExpr final : public Expr {
774public:
775        /// One arm of the _Generic expr
776        struct Association {
777                ptr<Type> type;
778                ptr<Expr> expr;
779
780                Association() = default;
781                // default case
782                Association( const Expr * e ) : type(), expr( e ) {}
783                // non-default case
784                Association( const Type * t, const Expr * e ) : type( t ), expr( e ) {}
785        };
786
787        ptr<Expr> control;
788        std::vector<Association> associations;
789
790        GenericExpr( const CodeLocation & loc, const Expr * ctrl, std::vector<Association> && assns )
791        : Expr( loc ), control( ctrl ), associations( std::move(assns) ) {}
792
793        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
794private:
795        GenericExpr * clone() const override { return new GenericExpr{ *this }; }
796        MUTATE_FRIEND
797};
798
799
800}
801
802#undef MUTATE_FRIEND
803
804// Local Variables: //
805// tab-width: 4 //
806// mode: c++ //
807// compile-command: "make install" //
808// End: //
Note: See TracBrowser for help on using the repository browser.