source: src/AST/Expr.hpp@ a62749f

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since a62749f was 60aaa51d, checked in by Aaron Moss <a3moss@…>, 6 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.