Changeset 9e1d485


Ignore:
Timestamp:
May 15, 2019, 3:41:08 PM (5 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
69bafd2
Parents:
264e691
Message:

First draft of ast::Type with subclasses

Location:
src
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Decl.hpp

    r264e691 r9e1d485  
    2626#include "ParseNode.hpp"
    2727#include "StorageClasses.hpp"
    28 #include "Type.hpp"            // for Type, ptr<Type>
     28#include "TypeVar.hpp"
    2929#include "Visitor.hpp"
    3030#include "Parser/ParseNode.h"  // for DeclarationNode::Aggregate
     
    136136class TypeDecl final : public NamedTypeDecl {
    137137public:
    138         /// type variable variants. otype is a specialized dtype
    139         enum Kind { Dtype, Ftype, Ttype, NUMBER_OF_KINDS } kind;
     138        TypeVar::Kind kind;
    140139        bool sized;
    141140        ptr<Type> init;
     
    143142        /// Data extracted from a type decl
    144143        struct Data {
    145                 Kind kind;
     144                TypeVar::Kind kind;
    146145                bool isComplete;
    147146
    148                 Data() : kind( (Kind)-1 ), isComplete( false ) {}
     147                Data() : kind( (TypeVar::Kind)-1 ), isComplete( false ) {}
    149148                Data( TypeDecl* d ) : kind( d->kind ), isComplete( d->sized ) {}
    150                 Data( Kind k, bool c ) : kind( k ), isComplete( c ) {}
     149                Data( TypeVar::Kind k, bool c ) : kind( k ), isComplete( c ) {}
    151150                Data( const Data& d1, const Data& d2 )
    152151                : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {}
     
    159158
    160159        TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b,
    161                 Kind k, bool s, Type* i = nullptr )
    162         : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ), init( i ) {}
     160                TypeVar::Kind k, bool s, Type* i = nullptr )
     161        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
     162          init( i ) {}
    163163
    164164        std::string typeString() const override;
    165165        /// Produces a name for generated code
    166166        std::string genTypeString() const;
     167
     168        /// convenience accessor to match Type::isComplete()
     169        bool isComplete() { return sized; }
    167170
    168171        Decl* accept( Visitor& v ) override { return v.visit( this ); }
  • src/AST/Expr.hpp

    r264e691 r9e1d485  
    119119        Expr(const CodeLocation & loc ) : ParseNode( loc ), result(), env(), inferred() {}
    120120
    121         Expr* set_extension( bool ex ) { extension = ex; return this; }
     121        Expr * set_extension( bool ex ) { extension = ex; return this; }
    122122
    123123        virtual Expr * accept( Visitor & v ) override = 0;
     
    133133        TypeExpr( const CodeLocation & loc, const Type * t ) : Expr(loc), type(t) {}
    134134
    135         Expr* accept( Visitor & v ) override { return v.visit( this ); }
     135        Expr * accept( Visitor & v ) override { return v.visit( this ); }
    136136private:
    137137        TypeExpr * clone() const override { return new TypeExpr{ *this }; }
  • src/AST/FunctionSpec.hpp

    r264e691 r9e1d485  
    4343                };
    4444
    45                 constexpr spec_flags( unsigned int val ) : val(val) {}
     45                constexpr spec_flags( unsigned int val = 0 ) : val(val) {}
    4646        };
    4747
  • src/AST/Fwd.hpp

    r264e691 r9e1d485  
    118118class TupleType;
    119119class TypeofType;
    120 class AttrType;
    121120class VarArgsType;
    122121class ZeroType;
     
    333332inline void increment( const class TypeofType *, Node::ref_type );
    334333inline void decrement( const class TypeofType *, Node::ref_type );
    335 inline void increment( const class AttrType *, Node::ref_type );
    336 inline void decrement( const class AttrType *, Node::ref_type );
    337334inline void increment( const class VarArgsType *, Node::ref_type );
    338335inline void decrement( const class VarArgsType *, Node::ref_type );
  • src/AST/Init.hpp

    r264e691 r9e1d485  
    4242};
    4343
     44/// Flag for whether to construct from initialzier
     45enum ConstructFlag { DoConstruct, MaybeConstruct };
     46
    4447/// Object initializer base class
    4548class Init : public ParseNode {
    4649public:
    47         bool maybeConstructed;
     50        ConstructFlag maybeConstructed;
    4851
    49         Init( const CodeLocation& loc, bool mc ) : ParseNode( loc ), maybeConstructed( mc ) {}
     52        Init( const CodeLocation& loc, ConstructFlag mc ) : ParseNode( loc ), maybeConstructed( mc ) {}
    5053
    5154        virtual Init* accept( Visitor& v ) override = 0;
     
    6063        ptr<Expr> value;
    6164
    62         SingleInit( const CodeLocation& loc, Expr* val, bool mc = false )
     65        SingleInit( const CodeLocation& loc, Expr* val, ConstructFlag mc = DoConstruct )
    6366        : Init( loc, mc ), value( val ) {}
    6467
     
    7881
    7982        ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is,
    80                 std::vector<ptr<Designation>>&& ds = {}, bool mc = false );
     83                std::vector<ptr<Designation>>&& ds = {}, ConstructFlag mc = DoConstruct );
    8184
    8285        using iterator = std::vector<ptr<Init>>::iterator;
     
    104107
    105108        ConstructorInit( const CodeLocation& loc, Stmt* ctor, Stmt* dtor, Init* init )
    106         : Init( loc, true ), ctor( ctor ), dtor( dtor ), init( init ) {}
     109        : Init( loc, DoConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
    107110
    108111        Init* accept( Visitor& v ) override { return v.visit( this ); }
  • src/AST/Node.hpp

    r264e691 r9e1d485  
    9494std::ostream& operator<< ( std::ostream& out, const Node* node );
    9595
    96 // Base class for the smart pointer types
    97 // should never really be used.
    98 template< typename node_t, enum Node::ref_type ref_t>
     96/// Base class for the smart pointer types
     97/// should never really be used.
     98template< typename node_t, enum Node::ref_type ref_t >
    9999class ptr_base {
    100100public:
    101101        ptr_base() : node(nullptr) {}
    102         ptr_base( node_t * n ) : node(n) { if( !node ) node->increment(ref_t); }
     102        ptr_base( const node_t * n ) : node(n) { if( node ) node->increment(ref_t); }
    103103        ~ptr_base() { if( node ) node->decrement(ref_t); }
    104104
    105         template< enum  Node::ref_type o_ref_t >
     105        template< enum Node::ref_type o_ref_t >
    106106        ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
    107                 if( !node ) return;
    108                 node->increment(ref_t);
     107                if( node ) node->increment(ref_t);
    109108        }
    110109
    111         template< enum  Node::ref_type o_ref_t >
     110        template< enum Node::ref_type o_ref_t >
    112111        ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
    113112                if( node ) node->increment(ref_t);
    114113        }
    115114
    116         template< enum  Node::ref_type o_ref_t >
     115        template< enum Node::ref_type o_ref_t >
    117116        ptr_base & operator=( const ptr_base<node_t, o_ref_t> & o ) {
    118117                assign(o.node);
     
    120119        }
    121120
    122         template< enum  Node::ref_type o_ref_t >
     121        template< enum Node::ref_type o_ref_t >
    123122        ptr_base & operator=( ptr_base<node_t, o_ref_t> && o ) {
    124                 if(o.node == node) return *this;
    125123                assign(o.node);
    126124                return *this;
     
    134132
    135133        template<typename o_node_t>
    136         const o_node_t * as() const { return dynamic_cast<o_node_t *>(node); }
     134        const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
    137135
    138136        using ptr = const node_t *;
    139137
    140138private:
    141         void assign(node_t * other ) {
     139        void assign( const node_t * other ) {
    142140                if( other ) other->increment(ref_t);
    143141                if( node  ) node ->decrement(ref_t);
     
    146144
    147145protected:
    148         node_t * node;
     146        const node_t * node;
    149147};
    150148
  • src/AST/Pass.hpp

    r264e691 r9e1d485  
    161161        virtual Type *             visit( const TupleType            * ) override final;
    162162        virtual Type *             visit( const TypeofType           * ) override final;
    163         virtual Type *             visit( const AttrType             * ) override final;
    164163        virtual Type *             visit( const VarArgsType          * ) override final;
    165164        virtual Type *             visit( const ZeroType             * ) override final;
  • src/AST/StorageClasses.hpp

    r264e691 r9e1d485  
    4747                };
    4848
    49                 constexpr class_flags( unsigned int val ) : val(val) {}
     49                constexpr class_flags( unsigned int val = 0 ) : val(val) {}
    5050        };
    5151
  • src/AST/Type.hpp

    r264e691 r9e1d485  
    1616#pragma once
    1717
    18 #include "Node.hpp"
     18#include <cassert>
     19#include <cstddef>           // for nullptr_t
     20#include <cstdint>           // for uintptr_t
     21#include <utility>           // for move
     22#include <vector>
     23
     24#include "CVQualifiers.hpp"
     25#include "Fwd.hpp"
     26#include "Node.hpp"          // for Node, ptr
     27#include "TypeVar.hpp"
     28#include "Visitor.hpp"
    1929
    2030namespace ast {
    2131
    2232class Type : public Node {
    23 
    24 };
    25 
    26 
     33        CV::Qualifiers tq;
     34public:
     35        Type( CV::Qualifiers q = {} ) : tq(q) {}
     36
     37        CV::Qualifiers qualifiers() const { return tq; }
     38        bool is_const() const { return tq.is_const; }
     39        bool is_volatile() const { return tq.is_volatile; }
     40        bool is_restrict() const { return tq.is_restrict; }
     41        bool is_lvalue() const { return tq.is_lvalue; }
     42        bool is_mutex() const { return tq.is_mutex; }
     43        bool is_atomic() const { return tq.is_atomic; }
     44
     45        void set_qualifiers( CV::Qualifiers q ) { tq = q; }
     46        void set_const( bool v ) { tq.is_const = v; }
     47        void set_restrict( bool v ) { tq.is_restrict = v; }
     48        void set_lvalue( bool v ) { tq.is_lvalue = v; }
     49        void set_mutex( bool v ) { tq.is_mutex = v; }
     50        void set_atomic( bool v ) { tq.is_atomic = v; }
     51
     52        /// How many elemental types are represented by this type
     53        virtual unsigned size() const { return 1; }
     54        /// Is this a void type?
     55        virtual bool isVoid() const { return size() == 0; }
     56        /// Get the i'th component of this type
     57        virtual const Type * getComponent( unsigned i );
     58
     59        /// type without outer pointers and arrays
     60        const Type * stripDeclarator();
     61        /// type without outer references
     62        const Type * stripReferences();
     63        /// number of reference occuring consecutively on the outermost layer of this type
     64        /// (i.e. do not count references nested within other types)
     65        virtual unsigned referenceDepth() const { return 0; }
     66        /// true iff type is complete type (i.e. compiler knows the size, alignment, and layout)
     67        virtual bool isComplete() const { return true; }
     68
     69        virtual Type * accept( Visitor & v ) override = 0;
     70private:
     71        virtual Type * clone() const override = 0;
     72};
     73
     74/// `void`
     75class VoidType final : public Type {
     76public:
     77        VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
     78       
     79        unsigned size() const override { return 0; }
     80        bool isVoid() const override { return true; }
     81        bool isComplete() const override { return false; }
     82
     83        Type * accept( Visitor & v ) override { return v.visit( this ); }
     84private:
     85        VoidType * clone() const override { return new VoidType{ *this }; }
     86};
     87
     88/// Built-in arithmetic type
     89class BasicType final : public Type {
     90public:
     91        // GENERATED START, DO NOT EDIT
     92        // GENERATED BY BasicTypes-gen.cc
     93        enum Kind {
     94                Bool,
     95                Char,
     96                SignedChar,
     97                UnsignedChar,
     98                ShortSignedInt,
     99                ShortUnsignedInt,
     100                SignedInt,
     101                UnsignedInt,
     102                LongSignedInt,
     103                LongUnsignedInt,
     104                LongLongSignedInt,
     105                LongLongUnsignedInt,
     106                SignedInt128,
     107                UnsignedInt128,
     108                uFloat16,
     109                uFloat16Complex,
     110                uFloat32,
     111                uFloat32Complex,
     112                Float,
     113                FloatComplex,
     114                uFloat32x,
     115                uFloat32xComplex,
     116                uFloat64,
     117                uFloat64Complex,
     118                Double,
     119                DoubleComplex,
     120                uFloat64x,
     121                uFloat64xComplex,
     122                uuFloat80,
     123                uFloat128,
     124                uFloat128Complex,
     125                uuFloat128,
     126                LongDouble,
     127                LongDoubleComplex,
     128                uFloat128x,
     129                uFloat128xComplex,
     130                NUMBER_OF_BASIC_TYPES
     131        } kind;
     132        // GENERATED END
     133
     134        /// xxx -- MAX_INTEGER_TYPE should probably be in BasicTypes-gen.cc, rather than hardcoded here
     135        enum { MAX_INTEGER_TYPE = UnsignedInt128 };
     136
     137        /// string names of basic types; generated to match with Kind
     138        static const char *typeNames[];
     139
     140        BasicType( Kind k, CV::Qualifiers q = {} ) : Type(q), kind(k) {}
     141
     142        /// Check if this type represents an integer type
     143        bool isInteger() const { return kind <= MAX_INTEGER_TYPE; }
     144
     145        Type * accept( Visitor & v ) override { return v.visit( this ); }
     146private:
     147        BasicType * clone() const override { return new BasicType{ *this }; }
     148};
     149
     150/// Pointer/array variable length?
     151enum LengthFlag { FixedLen, VariableLen };
     152
     153/// Pointer/array static dimension?
     154enum DimensionFlag { DynamicDim, StaticDim };
     155
     156/// Pointer type `T*`
     157class PointerType final : public Type {
     158public:
     159        ptr<Type> base;
     160
     161        // In C99, pointer types can be qualified in many ways, e.g. `int a[ static 3 ]`
     162        ptr<Expr> dimension;
     163        LengthFlag isVarLen = FixedLen;
     164        DimensionFlag isStatic = DynamicDim;
     165
     166        PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
     167        PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
     168                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
     169
     170        // true if this pointer is actually an array
     171        bool isArray() const { return isVarLen || isStatic || dimension; }
     172
     173        bool isComplete() const override { return ! isVarLen; }
     174
     175        Type * accept( Visitor & v ) override { return v.visit( this ); }
     176private:
     177        PointerType * clone() const override { return new PointerType{ *this }; }
     178};
     179
     180/// Array type `T[]`
     181class ArrayType final : public Type {
     182public:
     183        ptr<Type> base;
     184        ptr<Expr> dimension;
     185        LengthFlag isVarLen;
     186        DimensionFlag isStatic;
     187
     188        ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
     189                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
     190
     191        // array types are complete if they have a dimension expression or are
     192        // VLAs ('*' in parameter declaration), and incomplete otherwise.
     193        // See 6.7.6.2
     194        bool isComplete() const override { return dimension || isVarLen; }
     195
     196        Type * accept( Visitor & v ) override { return v.visit( this ); }
     197private:
     198        ArrayType * clone() const override { return new ArrayType{ *this }; }
     199};
     200
     201/// Reference type `T&`
     202class ReferenceType final : public Type {
     203public:
     204        ptr<Type> base;
     205
     206        ReferenceType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
     207
     208        unsigned referenceDepth() const override { return base->referenceDepth() + 1; }
     209
     210        // Since reference types act like value types, their size is the size of the base.
     211        // This makes it simple to cast the empty tuple to a reference type, since casts that increase
     212        // the number of values are disallowed.
     213        unsigned size() const override { return base->size(); }
     214
     215        Type * accept( Visitor & v ) override { return v.visit( this ); }
     216private:
     217        ReferenceType * clone() const override { return new ReferenceType{ *this }; }
     218};
     219
     220/// Qualified type `P.C`
     221class QualifiedType final : public Type {
     222public:
     223        ptr<Type> parent;
     224        ptr<Type> child;
     225
     226        QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
     227        : Type(q), parent(p), child(c) {}
     228
     229        Type * accept( Visitor & v ) override { return v.visit( this ); }
     230private:
     231        QualifiedType * clone() const override { return new QualifiedType{ *this }; }
     232};
     233
     234/// Base type for potentially forall-qualified types
     235class ParameterizedType : public Type {
     236public:
     237        using ForallList = std::vector<ptr<TypeDecl>>;
     238
     239        ForallList forall;
     240
     241        ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {} )
     242        : Type(q), forall(std::move(fs)) {}
     243        ParameterizedType( CV::Qualifiers q ) : Type(q), forall() {}
     244
     245private:
     246        virtual ParameterizedType * clone() const override = 0;
     247};
     248
     249/// Function variable arguments flag
     250enum ArgumentFlag { FixedArgs, VariableArgs };
     251
     252/// Type of a function `[R1, R2](*)(P1, P2, P3)`
     253class FunctionType final : public ParameterizedType {
     254public:
     255        std::vector<ptr<DeclWithType>> returnVals;
     256        std::vector<ptr<DeclWithType>> parameters;
     257
     258        /// Does the function accept a variable number of arguments following the arguments specified
     259        /// in the parameters list.
     260        /// This could be because of
     261        /// - an ellipsis in a prototype declaration
     262        /// - an unprototyped declaration
     263        ArgumentFlag isVarArgs;
     264
     265        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
     266        : ParameterizedType(q), returnVals(), parameters(), isVarArgs(va) {}
     267
     268        /// true if either the parameters or return values contain a tttype
     269        bool isTtype() const;
     270        /// true if function parameters are unconstrained by prototype
     271        bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
     272
     273        Type * accept( Visitor & v ) override { return v.visit( this ); }
     274private:
     275        FunctionType * clone() const override { return new FunctionType{ *this }; }
     276};
     277
     278/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
     279class ReferenceToType : public ParameterizedType {
     280public:
     281        std::vector<ptr<Expr>> parameters;
     282        std::vector<ptr<Attribute>> attributes;
     283        std::string name;
     284        bool hoistType = false;
     285
     286        ReferenceToType( const std::string& n, CV::Qualifiers q = {},
     287                std::vector<ptr<Attribute>> && as = {} )
     288        : ParameterizedType(q), parameters(), attributes(std::move(as)), name(n) {}
     289
     290        /// Gets aggregate declaration this type refers to
     291        virtual const AggregateDecl * aggr() const = 0;
     292        /// Looks up member declarations with given name
     293        std::vector<readonly<Decl>> lookup( const std::string & name ) const;
     294
     295private:
     296        virtual ReferenceToType * clone() const override = 0;
     297
     298protected:
     299        /// Name for the kind of type this is
     300        virtual std::string typeString() const = 0;
     301};
     302
     303/// instance of struct type
     304class StructInstType final : public ReferenceToType {
     305public:
     306        readonly<StructDecl> base;
     307
     308        StructInstType( const std::string& n, CV::Qualifiers q = {},
     309                std::vector<ptr<Attribute>> && as = {} )
     310        : ReferenceToType( n, q, std::move(as) ), base() {}
     311        StructInstType( const StructDecl * b, CV::Qualifiers q = {},
     312                std::vector<ptr<Attribute>> && as = {} );
     313       
     314        bool isComplete() const override;
     315
     316        const StructDecl * aggr() const override { return base; }
     317
     318        Type * accept( Visitor & v ) override { return v.visit( this ); }
     319private:
     320        StructInstType * clone() const override { return new StructInstType{ *this }; }
     321
     322        std::string typeString() const override { return "struct"; }
     323};
     324
     325/// instance of union type
     326class UnionInstType final : public ReferenceToType {
     327public:
     328        readonly<UnionDecl> base;
     329
     330        UnionInstType( const std::string& n, CV::Qualifiers q = {},
     331                std::vector<ptr<Attribute>> && as = {} )
     332        : ReferenceToType( n, q, std::move(as) ), base() {}
     333        UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
     334                std::vector<ptr<Attribute>> && as = {} );
     335       
     336        bool isComplete() const override;
     337
     338        const UnionDecl * aggr() const override { return base; }
     339
     340        Type * accept( Visitor & v ) override { return v.visit( this ); }
     341private:
     342        UnionInstType * clone() const override { return new UnionInstType{ *this }; }
     343
     344        std::string typeString() const override { return "union"; }
     345};
     346
     347/// instance of enum type
     348class EnumInstType final : public ReferenceToType {
     349public:
     350        readonly<EnumDecl> base;
     351
     352        EnumInstType( const std::string& n, CV::Qualifiers q = {},
     353                std::vector<ptr<Attribute>> && as = {} )
     354        : ReferenceToType( n, q, std::move(as) ), base() {}
     355        EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
     356                std::vector<ptr<Attribute>> && as = {} );
     357       
     358        bool isComplete() const override;
     359
     360        const EnumDecl * aggr() const override { return base; }
     361
     362        Type * accept( Visitor & v ) override { return v.visit( this ); }
     363private:
     364        EnumInstType * clone() const override { return new EnumInstType{ *this }; }
     365
     366        std::string typeString() const override { return "enum"; }
     367};
     368
     369/// instance of trait type
     370class TraitInstType final : public ReferenceToType {
     371public:
     372        readonly<TraitDecl> base;
     373
     374        TraitInstType( const std::string& n, CV::Qualifiers q = {},
     375                std::vector<ptr<Attribute>> && as = {} )
     376        : ReferenceToType( n, q, std::move(as) ), base() {}
     377        TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
     378                std::vector<ptr<Attribute>> && as = {} );
     379       
     380        // not meaningful for TraitInstType
     381        bool isComplete() const override { assert(false); }
     382
     383        const TraitDecl * aggr() const override { return base; }
     384
     385        Type * accept( Visitor & v ) override { return v.visit( this ); }
     386private:
     387        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
     388
     389        std::string typeString() const override { return "trait"; }
     390};
     391
     392/// instance of named type alias (typedef or variable)
     393class TypeInstType final : public ReferenceToType {
     394public:
     395        readonly<TypeDecl> base;
     396        TypeVar::Kind kind;
     397
     398        TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     399                std::vector<ptr<Attribute>> && as = {} )
     400        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     401        TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
     402                std::vector<ptr<Attribute>> && as = {} )
     403        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
     404
     405        /// sets `base`, updating `kind` correctly
     406        void set_base( const TypeDecl * );
     407
     408        bool isComplete() const override;
     409
     410        // not meaningful for TypeInstType
     411        const AggregateDecl * aggr() const override { assert(false); }
     412
     413        Type * accept( Visitor & v ) override { return v.visit( this ); }
     414private:
     415        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
     416
     417        std::string typeString() const override { return "type"; }
     418};
     419
     420/// tuple type e.g. `[int, char]`
     421class TupleType final : public Type {
     422public:
     423        std::vector<ptr<Type>> types;
     424        std::vector<ptr<Decl>> members;
     425
     426        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
     427
     428        // collection simulation
     429        using iterator = std::vector<ptr<Type>>::const_iterator;
     430        iterator begin() const { return types.begin(); }
     431        iterator end() const { return types.end(); }
     432       
     433        unsigned size() const override { return types.size(); }
     434
     435        const Type * getComponent( unsigned i ) override {
     436                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
     437                        i, size() );
     438                return *(begin()+i);
     439        }
     440
     441        Type * accept( Visitor & v ) override { return v.visit( this ); }
     442private:
     443        TupleType * clone() const override { return new TupleType{ *this }; }
     444};
     445
     446/// Type of unresolved `typeof()` expression
     447class TypeofType : public Type {
     448public:
     449        ptr<Expr> expr;
     450        enum Kind { Typeof, Basetypeof } kind;
     451
     452        TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
     453        : Type(q), expr(e), kind(k) {}
     454
     455        Type * accept( Visitor & v ) override { return v.visit( this ); }
     456private:
     457        TypeofType * clone() const override { return new TypeofType{ *this }; }
     458};
     459
     460/// GCC built-in varargs type
     461class VarArgsType final : public Type {
     462public:
     463        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
     464       
     465        Type * accept( Visitor & v ) override { return v.visit( this ); }
     466private:
     467        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
     468};
     469
     470/// Type of zero constant `0`
     471class ZeroType final : public Type {
     472public:
     473        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
     474       
     475        Type * accept( Visitor & v ) override { return v.visit( this ); }
     476private:
     477        ZeroType * clone() const override { return new ZeroType{ *this }; }     
     478};
     479
     480/// Type of one constant `1`
     481class OneType final : public Type {
     482public:
     483        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
     484
     485        Type * accept( Visitor & v ) override { return v.visit( this ); }
     486private:
     487        OneType * clone() const override { return new OneType{ *this }; }
     488};
     489
     490/// Parent type for scope-qualified types at global scope
     491class GlobalScopeType final : public Type {
     492public:
     493        GlobalScopeType( CV::Qualifiers q = {} ) : Type( q ) {}
     494
     495        Type * accept( Visitor & v ) override { return v.visit( this ); }
     496private:
     497        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
     498};
    27499
    28500//=================================================================================================
    29501/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
    30 /// remove only if there is a better solution
     502/// remove only if there is a better solution.
    31503/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
    32504/// forward declarations
     
    63535inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); }
    64536inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); }
    65 inline void increment( const class AttrType * node, Node::ref_type ref ) { node->increment( ref ); }
    66 inline void decrement( const class AttrType * node, Node::ref_type ref ) { node->decrement( ref ); }
    67537inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); }
    68538inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); }
  • src/AST/Visitor.hpp

    r264e691 r9e1d485  
    104104    virtual Type *             visit( const TupleType            * ) = 0;
    105105    virtual Type *             visit( const TypeofType           * ) = 0;
    106     virtual Type *             visit( const AttrType             * ) = 0;
    107106    virtual Type *             visit( const VarArgsType          * ) = 0;
    108107    virtual Type *             visit( const ZeroType             * ) = 0;
  • src/AST/porting.md

    r264e691 r9e1d485  
    3232* allows compiler to optimize virtual calls to static calls if given static type
    3333
    34 Pulled `FuncSpecifiers` and `StorageClasses` out of `Type` into their own headers
     34Pulled `FuncSpecifiers`, `StorageClasses`, `CVQualifiers` out of `Type` into their own headers
    3535* Made `BFCommon` a `MakeBitfield` macro in its own header
    3636  * added default and field-init constructors to macro
     
    6666        * `Initializer` => `ast::Init`
    6767    * `Statement` => `ast::Stmt`
     68        * any field names should follow a similar renaming
    6869  * because they don't really belong to `Type` (and for consistency with `Linkage::Spec`):
    6970    * `Type::StorageClasses` => `ast::Storage::Classes`
    7071          * `Type::Extern` etc. => `ast::Storage::Extern` etc.
     72        * `Type::FuncSpecifiers` => `ast::Function::Specs`
     73          * `Type::Inline` etc. => `ast::Function::Inline` etc.
     74        * `Type::Qualifiers` => `ast::CV::Qualifiers`
     75          * `Type::Const` etc. => `ast::CV::Const`
     76          * couldn't break name-dependency loop without pulling `Qualifiers` out of `Type`
    7177        * `LinkageSpec::Spec` => `ast::Linkage::Spec`
    7278          * `LinkageSpec::Mangle` etc. => `ast::Linkage::Mangle` etc.
     
    7581          * `LinkageSpec::isMangled(Spec)` etc. => `Spec.is_mangled` etc.
    7682          * `LinkageSpec::Intrinsic` etc. => `ast::Linkage::Intrinsic` etc.
     83* Boolean constructor parameters get replaced with a dedicated flag enum:
     84  * e.g. `bool isVarLen;` => `enum LengthFlag { FixedLen, VariableLen };` `LengthFlag isVarLen;`
     85  * field can be *read* in the existing boolean contexts, but requires documentation to write
     86  * suggest naming all flag enums `FooFlag` to hint at boolean nature
    7787
    7888## Specific Nodes ##
     
    93103
    94104`TypeDecl`
    95 * stripped `isComplete()` accessor in favour of direct access to `sized`
     105* moved `TypeDecl::Kind` to `ast::TypeVar::Kind`
    96106
    97107`EnumDecl`
     
    102112  * does imply get_/set_ API, and some care about moving backward
    103113
     114`Init`
     115* `bool maybeConstruct` => `enum ConstructFlag { DoConstruct, MaybeConstruct }`
     116
    104117`Label`
    105118* `get_statement()` exclusively used for code location, replaced with `CodeLocation` field
     
    108121* **TODO** port copy operator
    109122  * Needs to be an almost-shallow clone, where the declarations are cloned only if needed
    110   * **TODO** port DeclReplacer
     123  * **TODO** port `DeclReplacer`
    111124* Still a `std::list` for children, rather than `std::vector`
    112125  * allows more-efficient splicing for purposes of later code generation
    113126
    114127`Type`
     128* `CV::Qualifiers` moved to end of constructor parameter list, defaulted to `{}`
     129  * `ReferenceToType` puts a defaulted list of attributes after qualifiers
    115130* `forall` field split off into `ParameterizedType` subclass
    116131  * any type that needs it can inherit from `ParameterizedType`
     132    * currently `FunctionType`, `ReferenceToType`
    117133* `get_qualifiers()` replaced with accessor `qualifiers()` and mutator `set_qualifiers()`
    118   * `get_CV()` replaced with `is_CV()` variants
     134  * `get_const()` etc. replaced with `is_const()` etc. variants
     135* `referenceDepth()` now returns `unsigned` rather than `int`
    119136* A number of features only supported on aggregates pushed down to `ReferenceToType`:
    120137  * `attributes`: per docs [1] GCC only supports type attributes on aggregates and typedefs
    121138    * suggest adding a `TypeWithAttributes` wrapper type if this proves insufficient
    122   * `getAggr()`
    123   * `genericSubstitution()`
     139  * `getAggr()` => `aggr()`
     140    * also now returns `const AggregateDecl *`
     141* `genericSubstitution()` moved to own visitor **TODO** write
    124142
    125143`BasicType`
    126 * does not inherit from `Type` to allow pointer inlining
    127 * moved `Kind` before qualifiers in constructor to allow for default
    128144* **TODO** move `kind`, `typeNames` into code generator
     145
     146`ReferenceToType`
     147* deleted `get_baseParameters()` from children
     148  * replace with `aggr() ? aggr()->parameters : nullptr`
     149* hoisted `lookup` implementation into parent, made non-virtual
     150  * also changed to return vector rather than filling; change back if any great win for reuse
     151* `baseStruct` etc. renamed to `base`
     152
     153`PointerType`/`ArrayType`
     154* `is_array()` => `isArray()`
     155* `bool isVarLen;` => `enum LengthFlag { FixedLen, VariableLen }; LengthFlag isVarLen;`
     156* `bool isStatic;` => `enum DimensionFlag { DynamicDim, StaticDim }; DimensionFlag isStatic;`
     157
     158`FunctionType`
     159* `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
     160
     161`TypeInstType`
     162* `bool isFtype` => `TypeVar::Kind kind`
     163
     164`TypeofType`
     165* `bool is_basetypeof` => `enum Kind { Typeof, Basetypeof } kind;`
     166
     167`TupleType`
     168* removed `value_type` typedef due to likely error
     169  * if readded, should be `const Type *`
     170
     171`AttrType`
     172* did not port due to (likely) disuse
     173  * best guess at use (from printing code) is deprecated handling for attributes
    129174
    130175[1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
  • src/InitTweak/InitTweak.cc

    r264e691 r9e1d485  
    55#include <memory>                  // for __shared_ptr
    66
     7#include "AST/Type.hpp"
    78#include "Common/PassVisitor.h"
    89#include "Common/SemanticError.h"  // for SemanticError
     
    513514                }
    514515        }
     516        const ast::Type* getPointerBase( const ast::Type* t ) {
     517                if ( const ast::PointerType* p = dynamic_cast< const ast::PointerType* >( t ) ) {
     518                        return p->base;
     519                } else if ( const ast::ArrayType* a = dynamic_cast< const ast::ArrayType* >( t ) ) {
     520                        return a->base;
     521                } else if ( const ast::ReferenceType* r = dynamic_cast< const ast::ReferenceType* >( t ) ) {
     522                        return r->base;
     523                } else return nullptr;
     524        }
    515525
    516526        Type * isPointerType( Type * type ) {
  • src/InitTweak/InitTweak.h

    r264e691 r9e1d485  
    2020#include <string>             // for string, allocator
    2121
     22#include "AST/Fwd.hpp"        // for AST nodes
    2223#include "SynTree/SynTree.h"  // for Visitor Nodes
    2324
     
    8384        /// returns the base type of a PointerType or ArrayType, else returns NULL
    8485        Type * getPointerBase( Type * );
     86        const ast::Type* getPointerBase( const ast::Type* );
    8587
    8688        /// returns the argument if it is a PointerType or ArrayType, else returns NULL
Note: See TracChangeset for help on using the changeset viewer.