source: src/AST/Decl.cpp @ 0cb3479

Last change on this file since 0cb3479 was 90be0cf, checked in by Andrew Beach <ajbeach@…>, 3 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: 6.7 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.cpp --
8//
9// Author           : Aaron B. Moss
10// Created On       : Thu May 9 10:00:00 2019
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Sat Dec  9 16:28:51 2023
13// Update Count     : 31
14//
15
16#include "Decl.hpp"
17
18#include <cassert>             // for assert, strict_dynamic_cast
19#include <iostream>
20#include <unordered_map>
21
22#include "Common/Eval.hpp"     // for eval
23#include "Common/SemanticError.hpp"
24
25#include "Fwd.hpp"             // for UniqueId
26#include "Init.hpp"
27#include "Node.hpp"            // for readonly
28#include "Type.hpp"            // for readonly
29#include "Expr.hpp"
30
31namespace ast {
32
33// To canonicalize declarations
34static UniqueId lastUniqueId = 0;
35
36void Decl::fixUniqueId() {
37        if ( uniqueId ) return;  // ensure only set once
38        uniqueId = ++lastUniqueId;
39}
40
41// --- FunctionDecl
42
43FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name,
44        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
45        CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
46        std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs )
47: FunctionDecl( loc, name, {}, {}, std::move(params), std::move(returns),
48                stmts, storage, linkage, std::move(attrs), fs, isVarArgs ) {
49}
50
51FunctionDecl::FunctionDecl( const CodeLocation & location, const std::string & name,
52        std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions,
53        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
54        CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
55        std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs )
56: DeclWithType( location, name, storage, linkage, std::move(attrs), fs ),
57                type_params( std::move( forall) ), assertions( std::move( assertions ) ),
58                params( std::move(params) ), returns( std::move(returns) ),
59                type( nullptr ), stmts( stmts ) {
60        FunctionType * type = new FunctionType( isVarArgs );
61        for ( auto & param : this->params ) {
62                type->params.emplace_back( param->get_type() );
63        }
64        for ( auto & ret : this->returns ) {
65                type->returns.emplace_back( ret->get_type() );
66        }
67        for ( auto & param : this->type_params ) {
68                type->forall.emplace_back( new TypeInstType( param ) );
69        }
70        for ( auto & assertion : this->assertions ) {
71                type->assertions.emplace_back(
72                        new VariableExpr( assertion->location, assertion ) );
73        }
74        this->type = type;
75}
76
77
78const Type * FunctionDecl::get_type() const { return type.get(); }
79void FunctionDecl::set_type( const Type * t ) {
80        type = strict_dynamic_cast< const FunctionType * >( t );
81}
82
83// --- TypeDecl
84
85const char * TypeDecl::typeString() const {
86        static const char * kindNames[] = { "sized data type", "sized data type", "sized object type", "sized function type", "sized tuple type", "sized length value" };
87        static_assert( sizeof(kindNames) / sizeof(kindNames[0]) == TypeDecl::NUMBER_OF_KINDS, "typeString: kindNames is out of sync." );
88        assertf( kind < TypeDecl::NUMBER_OF_KINDS, "TypeDecl kind is out of bounds." );
89        // sizeof("sized") includes '\0' and gives the offset to remove "sized ".
90        return sized ? kindNames[ kind ] : &kindNames[ kind ][ sizeof("sized") ];
91}
92
93const char * TypeDecl::genTypeString() const {
94        static const char * kindNames[] = { "T &", "T *", "T", "(*)", "T ...", "[T]" };
95        static_assert( sizeof(kindNames) / sizeof(kindNames[0]) == TypeDecl::NUMBER_OF_KINDS, "genTypeString: kindNames is out of sync." );
96        assertf( kind < TypeDecl::NUMBER_OF_KINDS, "TypeDecl kind is out of bounds." );
97        return kindNames[ kind ];
98}
99
100std::ostream & operator<< ( std::ostream & out, const TypeData & data ) {
101        return out << data.kind << ", " << data.isComplete;
102}
103
104// --- AggregateDecl
105
106// These must harmonize with the corresponding AggregateDecl::Aggregate enumerations.
107static const char * aggregateNames[] = { "struct", "union", "enum", "exception", "trait", "generator", "coroutine", "monitor", "thread", "NoAggregateName" };
108
109const char * AggregateDecl::aggrString( AggregateDecl::Aggregate aggr ) {
110        return aggregateNames[aggr];
111}
112
113// --- EnumDecl
114
115bool EnumDecl::valueOf( const Decl * enumerator, long long & value ) const {
116        if ( enumValues.empty() ) {
117                Evaluation crntVal = {0, true, true};  // until expression is given, we know to start counting from 0
118                for ( const Decl * member : members ) {
119                        const ObjectDecl * field = strict_dynamic_cast< const ObjectDecl * >( member );
120                        if ( field->init ) {
121                                const SingleInit * init = strict_dynamic_cast< const SingleInit * >( field->init.get() );
122                                crntVal = eval( init->value );
123                                if ( ! crntVal.isEvaluableInGCC ) {
124                                        SemanticError( init->location, "Non-constexpr in initialization of enumerator %s", field->name.c_str() );
125                                }
126                        }
127                        if ( enumValues.count( field->name ) != 0 ) {
128                                SemanticError( location, "Enum %s has multiple members with %s", name.c_str(), field->name.c_str() );
129                        }
130                        if (crntVal.hasKnownValue) {
131                                enumValues[ field->name ] = crntVal.knownValue;
132                        }
133                        ++crntVal.knownValue;
134                }
135        }
136
137        auto it = enumValues.find( enumerator->name );
138
139        if ( it != enumValues.end() ) {
140
141                // Handle typed enum by casting the value in (C++) compiler
142                // if ( base ) { // A typed enum
143                //      if ( const BasicType * bt = dynamic_cast<const BasicType *>(base) ) {
144                //              switch( bt->kind ) {
145                //                      case BasicType::Kind::Bool:     value = (bool) it->second; break;
146                //                      case BasicType::Kind::Char: value = (char) it->second; break;
147                //                      case BasicType::Kind::SignedChar: value = (signed char) it->second; break;
148                //                      case BasicType::Kind::UnsignedChar: value = (unsigned char) it->second; break;
149                //                      case BasicType::Kind::ShortSignedInt: value = (short signed int) it->second; break;
150                //                      case BasicType::Kind::SignedInt: value = (signed int) it->second; break;
151                //                      case BasicType::Kind::UnsignedInt: value = (unsigned int) it->second; break;
152                //                      case BasicType::Kind::LongSignedInt: value = (long signed int) it->second; break;
153                //                      case BasicType::Kind::LongUnsignedInt: value = (long unsigned int) it->second; break;
154                //                      case BasicType::Kind::LongLongSignedInt: value = (long long signed int) it->second; break;
155                //                      case BasicType::Kind::LongLongUnsignedInt: value = (long long unsigned int) it->second; break;
156                //                      // TODO: value should be able to handle long long unsigned int
157
158                //                      default:
159                //                      value = it->second;
160                //              }
161                //      }
162                // } else {
163                        value = it->second;
164                //}
165
166                return true;
167        }
168        return false;
169}
170
171bool EnumDecl::isTyped() const { return base; }
172
173bool EnumDecl::isOpaque() const { return isCfa && !isTyped(); }
174
175}
176
177// Local Variables: //
178// tab-width: 4 //
179// mode: c++ //
180// compile-command: "make install" //
181// End: //
Note: See TracBrowser for help on using the repository browser.