source: src/AST/Decl.hpp @ 10a9479d

Last change on this file since 10a9479d was 90be0cf, checked in by Andrew Beach <ajbeach@…>, 8 weeks ago

Moved some methods out of EnumDecl?. These were calculations and the ast types are supposed to be data focused so they should either go with utility functions or to their use site. I tried the use site.

  • Property mode set to 100644
File size: 15.0 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// Decl.hpp --
8//
9// Author           : Aaron B. Moss
10// Created On       : Thu May 9 10:00:00 2019
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Apr  5 10:42:00 2023
13// Update Count     : 35
14//
15
16#pragma once
17
18#include <iosfwd>
19#include <string>              // for string, to_string
20#include <unordered_map>
21#include <vector>
22#include <algorithm>
23
24#include "FunctionSpec.hpp"
25#include "Fwd.hpp"             // for UniqueId
26#include "LinkageSpec.hpp"
27#include "Node.hpp"            // for ptr, readonly
28#include "ParseNode.hpp"
29#include "StorageClasses.hpp"
30#include "Visitor.hpp"
31
32// 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
37namespace ast {
38
39/// Base declaration class
40class Decl : public ParseNode {
41public:
42        std::string name;
43        Storage::Classes storage;
44        Linkage::Spec linkage;
45        UniqueId uniqueId = 0;
46        bool extension = false;
47
48        Decl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
49                Linkage::Spec linkage )
50        : ParseNode( loc ), name( name ), storage( storage ), linkage( linkage ) {}
51
52        /// Ensures this node has a unique ID
53        void fixUniqueId();
54
55        const Decl * accept( Visitor & v ) const override = 0;
56private:
57        Decl * clone() const override = 0;
58        MUTATE_FRIEND
59};
60
61/// Typed declaration base class
62class DeclWithType : public Decl {
63public:
64        /// Represents the type with all types and typedefs expanded.
65        std::string mangleName;
66        /// Stores the scope level at which the variable was declared.
67        /// Used to access shadowed identifiers.
68        int scopeLevel = 0;
69
70        std::vector<ptr<Attribute>> attributes;
71        Function::Specs funcSpec;
72        ptr<Expr> asmName;
73        bool isDeleted = false;
74        bool isTypeFixed = false;
75        bool isHidden = false;
76
77        DeclWithType( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
78                Linkage::Spec linkage, std::vector<ptr<Attribute>>&& attrs, Function::Specs fs )
79        : Decl( loc, name, storage, linkage ), mangleName(), attributes( std::move(attrs) ),
80                funcSpec(fs), asmName() {}
81
82        std::string scopedMangleName() const { return mangleName + "_" + std::to_string(scopeLevel); }
83
84        /// Get type of this declaration. May be generated by subclass
85        virtual const Type * get_type() const = 0;
86        /// Set type of this declaration. May be verified by subclass
87        virtual void set_type( const Type * ) = 0;
88
89        const DeclWithType * accept( Visitor & v ) const override = 0;
90private:
91        DeclWithType * clone() const override = 0;
92        MUTATE_FRIEND
93};
94
95/// Object declaration `Foo foo = 42;`
96class ObjectDecl final : public DeclWithType {
97public:
98        ptr<Type> type;
99        ptr<Init> init;
100        ptr<Expr> bitfieldWidth;
101
102        ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type,
103                const Init * init = nullptr, Storage::Classes storage = {},
104                Linkage::Spec linkage = Linkage::Cforall, const Expr * bitWd = nullptr,
105                std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {} )
106        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
107          init( init ), bitfieldWidth( bitWd ) {}
108
109        const Type* get_type() const override { return type; }
110        void set_type( const Type * ty ) override { type = ty; }
111
112        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
113private:
114        ObjectDecl * clone() const override { return new ObjectDecl{ *this }; }
115        MUTATE_FRIEND
116};
117
118/// Function variable arguments flag
119enum ArgumentFlag { FixedArgs, VariableArgs };
120
121/// Function declaration `int foo()`
122class FunctionDecl final : public DeclWithType {
123public:
124        std::vector<ptr<TypeDecl>> type_params;
125        std::vector<ptr<DeclWithType>> assertions;
126        std::vector<ptr<DeclWithType>> params;
127        std::vector<ptr<DeclWithType>> returns;
128        // declared type, derived from parameter declarations
129        ptr<FunctionType> type;
130        /// Null for the forward declaration of a function.
131        ptr<CompoundStmt> stmts;
132        std::vector< ptr<Expr> > withExprs;
133
134        /// Monomorphic Function Constructor:
135        FunctionDecl( const CodeLocation & locaction, const std::string & name,
136                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
137                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
138                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
139
140        /// Polymorphic Function Constructor:
141        FunctionDecl( const CodeLocation & location, const std::string & name,
142                std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions,
143                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
144                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
145                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
146
147        const Type * get_type() const override;
148        void set_type( const Type * t ) override;
149
150        bool has_body() const { return stmts; }
151
152        const DeclWithType * accept( Visitor & v ) const override { return v.visit( this ); }
153private:
154        FunctionDecl * clone() const override { return new FunctionDecl( *this ); }
155        MUTATE_FRIEND
156};
157
158/// Base class for named type aliases
159class NamedTypeDecl : public Decl {
160public:
161        ptr<Type> base;
162        std::vector<ptr<DeclWithType>> assertions;
163
164        NamedTypeDecl(
165                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
166                const Type * b, Linkage::Spec spec = Linkage::Cforall )
167        : Decl( loc, name, storage, spec ), base( b ), assertions() {}
168
169        /// Produces a name for the kind of alias
170        virtual const char * typeString() const = 0;
171
172private:
173        NamedTypeDecl* clone() const override = 0;
174        MUTATE_FRIEND
175};
176
177/// Cforall type variable: `dtype T`
178class TypeDecl final : public NamedTypeDecl {
179  public:
180        enum Kind { Dtype, DStype, Otype, Ftype, Ttype, Dimension, NUMBER_OF_KINDS };
181
182        Kind kind;
183        bool sized;
184        ptr<Type> init;
185
186        TypeDecl(
187                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
188                const Type * b, TypeDecl::Kind k, bool s, const Type * i = nullptr )
189        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeDecl::Ttype || s ),
190          init( i ) {}
191
192        const char * typeString() const override;
193        /// Produces a name for generated code
194        const char * genTypeString() const;
195
196        /// convenience accessor to match Type::isComplete()
197        bool isComplete() const { return sized; }
198
199        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
200  private:
201        TypeDecl * clone() const override { return new TypeDecl{ *this }; }
202        MUTATE_FRIEND
203};
204
205/// Data extracted from a TypeDecl.
206struct TypeData {
207        TypeDecl::Kind kind;
208        bool isComplete;
209
210        TypeData() : kind( TypeDecl::NUMBER_OF_KINDS ), isComplete( false ) {}
211        TypeData( const TypeDecl * d ) : kind( d->kind ), isComplete( d->sized ) {}
212        TypeData( TypeDecl::Kind k, bool c ) : kind( k ), isComplete( c ) {}
213        TypeData( const TypeData & d1, const TypeData & d2 )
214                : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {}
215
216        bool operator==( const TypeData & o ) const { return kind == o.kind && isComplete == o.isComplete; }
217        bool operator!=( const TypeData & o ) const { return !(*this == o); }
218};
219
220std::ostream & operator<< ( std::ostream &, const TypeData & );
221
222/// C-style typedef `typedef Foo Bar`
223class TypedefDecl final : public NamedTypeDecl {
224public:
225        TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
226                Type* b, Linkage::Spec spec = Linkage::Cforall )
227        : NamedTypeDecl( loc, name, storage, b, spec ) {}
228
229        const char * typeString() const override { return "typedef"; }
230
231        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
232private:
233        TypedefDecl * clone() const override { return new TypedefDecl{ *this }; }
234        MUTATE_FRIEND
235};
236
237/// Aggregate type declaration base class
238class AggregateDecl : public Decl {
239public:
240        enum Aggregate { Struct, Union, Enum, Exception, Trait, Generator, Coroutine, Monitor, Thread, NoAggregate };
241        static const char * aggrString( Aggregate aggr );
242
243        std::vector<ptr<Decl>> members;
244        std::vector<ptr<TypeDecl>> params;
245        std::vector<ptr<Attribute>> attributes;
246        bool body = false;
247        readonly<AggregateDecl> parent = {};
248
249        AggregateDecl( const CodeLocation& loc, const std::string& name,
250                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
251        : Decl( loc, name, Storage::Classes{}, linkage ), members(), params(),
252          attributes( std::move(attrs) ) {}
253
254        AggregateDecl* set_body( bool b ) { body = b; return this; }
255
256        /// Produces a name for the kind of aggregate
257        virtual const char * typeString() const = 0;
258
259private:
260        AggregateDecl * clone() const override = 0;
261        MUTATE_FRIEND
262};
263
264/// struct declaration `struct Foo { ... };`
265class StructDecl final : public AggregateDecl {
266public:
267        Aggregate kind;
268
269        StructDecl( const CodeLocation& loc, const std::string& name,
270                Aggregate kind = Struct,
271                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
272        : AggregateDecl( loc, name, std::move(attrs), linkage ), kind( kind ) {}
273
274        bool is_coroutine() const { return kind == Coroutine; }
275        bool is_generator() const { return kind == Generator; }
276        bool is_monitor  () const { return kind == Monitor  ; }
277        bool is_thread   () const { return kind == Thread   ; }
278
279        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
280
281        const char * typeString() const override { return aggrString( kind ); }
282
283private:
284        StructDecl * clone() const override { return new StructDecl{ *this }; }
285        MUTATE_FRIEND
286};
287
288/// union declaration `union Foo { ... };`
289class UnionDecl final : public AggregateDecl {
290public:
291        UnionDecl( const CodeLocation& loc, const std::string& name,
292                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
293        : AggregateDecl( loc, name, std::move(attrs), linkage ) {}
294
295        const Decl * accept( Visitor& v ) const override { return v.visit( this ); }
296
297        const char * typeString() const override { return aggrString( Union ); }
298
299private:
300        UnionDecl * clone() const override { return new UnionDecl{ *this }; }
301        MUTATE_FRIEND
302};
303
304/// Enumeration attribute kind.
305enum class EnumAttribute{ Value, Posn, Label };
306
307/// enum declaration `enum Foo { ... };`
308class EnumDecl final : public AggregateDecl {
309public:
310        // isCfa indicated if the enum has a declaration like:
311        // enum (type_optional) Name {...}
312        bool isCfa;
313        // if isCfa == true && base.get() == nullptr, it is a "opaque" enum
314        ptr<Type> base;
315        enum class EnumHiding { Visible, Hide } hide;
316        std::vector< ast::ptr<ast::EnumInstType>> inlinedDecl; // child enums
317
318        EnumDecl( const CodeLocation& loc, const std::string& name, bool isCfa = false,
319                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
320                Type const * base = nullptr, EnumHiding hide = EnumHiding::Hide,
321                std::unordered_map< std::string, long long > enumValues = std::unordered_map< std::string, long long >() )
322        : AggregateDecl( loc, name, std::move(attrs), linkage ), isCfa(isCfa), base(base), hide(hide), enumValues(enumValues) {}
323
324        /// gets the integer value for this enumerator, returning true iff value found
325        // Maybe it is not used in producing the enum value
326        bool valueOf( const Decl * enumerator, long long& value ) const;
327
328        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
329
330        const char * typeString() const override { return aggrString( Enum ); }
331
332        bool isTyped() const;
333        bool isOpaque() const;
334private:
335        EnumDecl * clone() const override { return new EnumDecl{ *this }; }
336        MUTATE_FRIEND
337
338        /// Map from names to enumerator values; kept private for lazy initialization
339        mutable std::unordered_map< std::string, long long > enumValues;
340};
341
342/// trait declaration `trait Foo( ... ) { ... };`
343class TraitDecl final : public AggregateDecl {
344public:
345        TraitDecl( const CodeLocation& loc, const std::string& name,
346                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
347        : AggregateDecl( loc, name, std::move(attrs), linkage ) {}
348
349        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
350
351        const char * typeString() const override { return "trait"; }
352
353private:
354        TraitDecl * clone() const override { return new TraitDecl{ *this }; }
355        MUTATE_FRIEND
356};
357
358/// With statement `with (...) ...`
359/// This is a statement lexically, but a Decl is needed for the SymbolTable.
360class WithStmt final : public Decl {
361public:
362        std::vector<ptr<Expr>> exprs;
363        ptr<Stmt> stmt;
364
365        WithStmt( const CodeLocation & loc, std::vector<ptr<Expr>> && exprs, const Stmt * stmt )
366        : Decl(loc, "", Storage::Auto, Linkage::Cforall), exprs(std::move(exprs)), stmt(stmt) {}
367
368        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
369private:
370        WithStmt * clone() const override { return new WithStmt{ *this }; }
371        MUTATE_FRIEND
372};
373
374/// Assembly declaration: `asm ... ( "..." : ... )`
375class AsmDecl final : public Decl {
376public:
377        ptr<AsmStmt> stmt;
378
379        AsmDecl( const CodeLocation & loc, AsmStmt * stmt )
380        : Decl( loc, "", {}, Linkage::C ), stmt(stmt) {}
381
382        const AsmDecl * accept( Visitor & v ) const override { return v.visit( this ); }
383private:
384        AsmDecl * clone() const override { return new AsmDecl( *this ); }
385        MUTATE_FRIEND
386};
387
388/// C-preprocessor directive `#...`
389class DirectiveDecl final : public Decl {
390public:
391        ptr<DirectiveStmt> stmt;
392
393        DirectiveDecl( const CodeLocation & loc, DirectiveStmt * stmt )
394        : Decl( loc, "", {}, Linkage::C ), stmt(stmt) {}
395
396        const DirectiveDecl * accept( Visitor & v ) const override { return v.visit( this ); }
397private:
398        DirectiveDecl * clone() const override { return new DirectiveDecl( *this ); }
399        MUTATE_FRIEND
400};
401
402/// Static Assertion `_Static_assert( ... , ... );`
403class StaticAssertDecl final : public Decl {
404public:
405        ptr<Expr> cond;
406        ptr<ConstantExpr> msg;   // string literal
407
408        StaticAssertDecl( const CodeLocation & loc, const Expr * condition, const ConstantExpr * msg )
409        : Decl( loc, "", {}, Linkage::C ), cond( condition ), msg( msg ) {}
410
411        const StaticAssertDecl * accept( Visitor & v ) const override { return v.visit( this ); }
412private:
413        StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
414        MUTATE_FRIEND
415};
416
417/// Inline Member Declaration `inline TypeName;`
418class InlineMemberDecl final : public DeclWithType {
419public:
420        ptr<Type> type;
421
422        InlineMemberDecl( const CodeLocation & loc, const std::string & name, const Type * type,
423                Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
424                std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {} )
425        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ) {}
426
427        const Type * get_type() const override { return type; }
428        void set_type( const Type * ty ) override { type = ty; }
429
430        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
431private:
432        InlineMemberDecl * clone() const override { return new InlineMemberDecl{ *this }; }
433        MUTATE_FRIEND
434};
435
436}
437
438#undef MUTATE_FRIEND
439
440// Local Variables: //
441// tab-width: 4 //
442// mode: c++ //
443// compile-command: "make install" //
444// End: //
Note: See TracBrowser for help on using the repository browser.