Update procedures
[shapes.git] / source / identifier.h
blob7650e65704b7c3aa6c6fcc86382fcb9167bec63b
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2014 Henrik Tidefelt
19 #pragma once
21 #include "refcount.h"
22 #include "charptrless.h"
23 #include "Shapes_Ast_decls.h"
25 #include <list>
26 #include <map>
27 #include <iostream>
29 namespace Shapes
31 namespace Ast
34 /* Memory management notice: The const char * strings used in NamespacePath, Identifier, and PlacedIdentifier
35 * will not be deallocated when no longer in use. This is by design, since the number of such strings should be remain
36 * fixed once the AST has been built up. Duplication of strings is avoided to some extent by the reference-counted
37 * NamespacePath objects.
39 * If memory leaking turns out to be a problem, one should consider replacing const char * by std::string or
40 * RefCountPtr< const char * >.
43 typedef std::list< const char * > NamespacePath;
44 extern const RefCountPtr< const Ast::NamespacePath > THE_EMPTY_NAMESPACE_PATH;
46 int compare( const Ast::NamespacePath & path1, const Ast::NamespacePath & path2 );
47 // bool operator < ( const Ast::NamespacePath & path1, const Ast::NamespacePath & path2 );
49 class NamespaceReference
51 public:
52 enum Base { ABSOLUTE, LOCAL, RELATIVE };
53 private:
54 Base base_;
55 RefCountPtr< const Ast::NamespacePath > path_;
56 public:
57 NamespaceReference( )
58 : base_( ABSOLUTE ), path_( NullPtr< const Ast::NamespacePath >( ) )
59 { }
60 NamespaceReference( Base base, const RefCountPtr< const Ast::NamespacePath > & path )
61 : base_( base ), path_( path )
62 { }
63 NamespaceReference( Base base, Ast::NamespacePath * path ) /* Transfers ownership. */
64 : base_( base ), path_( path )
65 { }
66 Base base( ) const { return base_; }
67 const Ast::NamespacePath & path( ) const { return *path_; }
68 RefCountPtr< const Ast::NamespacePath > pathRef( ) const { return path_; }
69 void show( std::ostream & os, bool showAbsoluteMark = true ) const;
72 /* A LookinPathStack holds the namespaces that have been explicitly listed to be looked in when looking up identifiers.
73 * The stack is to be traversed from top to bottom when looking up identifiers.
75 class LookinPathStack
77 RefCountPtr< const Ast::NamespacePath > car_; /* Resolved at the point where the look-in is added. */
78 RefCountPtr< const LookinPathStack > cdr_;
79 public:
80 LookinPathStack( const RefCountPtr< const Ast::NamespacePath > & car, const RefCountPtr< const LookinPathStack > & cdr )
81 : car_( car ), cdr_( cdr )
82 { }
83 RefCountPtr< const Ast::NamespacePath > car( ) const { return car_; }
84 RefCountPtr< const LookinPathStack > cdr( ) const { return cdr_; }
87 class SearchContext
89 RefCountPtr< const NamespacePath > lexicalPath_;
90 RefCountPtr< const NamespacePath > encapsulationPath_;
91 RefCountPtr< const LookinPathStack > lookinStack_;
92 RefCountPtr< const char > privateName_;
93 public:
94 SearchContext( const RefCountPtr< const NamespacePath > & lexicalPath, const RefCountPtr< const NamespacePath > & encapsulationPath, const RefCountPtr< const LookinPathStack > & lookinStack, const RefCountPtr< const char > & privateName )
95 : lexicalPath_( lexicalPath ), encapsulationPath_( encapsulationPath ), lookinStack_( lookinStack ), privateName_( privateName )
96 { }
97 SearchContext( const RefCountPtr< const NamespacePath > & lexicalPath, const RefCountPtr< const char > & privateName )
98 : lexicalPath_( lexicalPath ), encapsulationPath_( Ast::THE_EMPTY_NAMESPACE_PATH ), lookinStack_( NullPtr< const LookinPathStack >( ) ), privateName_( privateName )
99 { }
100 const RefCountPtr< const NamespacePath > & lexicalPath( ) const { return lexicalPath_; }
101 const RefCountPtr< const NamespacePath > & encapsulationPath( ) const { return encapsulationPath_; }
102 const RefCountPtr< const LookinPathStack > & lookinStack( ) const { return lookinStack_; }
103 const RefCountPtr< const char > & privateName( ) const { return privateName_; }
104 bool insidePrivateNamespace( ) const { return privateName_ == NullPtr< const char >( ); }
105 bool insideEncapsulationNamespace( ) const;
107 static RefCountPtr< const char > makePrivateName( size_t i );
108 static RefCountPtr< const char > makeEncapsulationName( size_t i );
109 static bool isEncapsulationName( const char * name );
112 extern const RefCountPtr< const Ast::SearchContext > THE_EMPTY_SEARCH_CONTEXT;
114 class PlacedIdentifier;
116 class Identifier
118 public:
119 /* The type of identifier is not stored in the identifier, as that would have a substantial impact on the
120 * memory consumption considering the uniquitous use of identifiers in a program. The identifier type only
121 * matters when displaying the identifier back to the user, and then the type has to be provided by the caller.
123 enum Type{ VARIABLE, STATE, DYNAMIC_VARIABLE, DYNAMIC_STATE, TYPE };
125 private:
126 RefCountPtr< const SearchContext > searchContext_; /* Used also for absolute identifiers, in case they use a namespace alias that expands to a relative path. */
127 NamespaceReference namespaceRef_;
128 const char * simpleId_; /* Will not be deallocated, see memory management note above! */
130 public:
131 Identifier( const RefCountPtr< const SearchContext > & searchContext, Ast::NamespaceReference::Base base, NamespacePath * path, const char * simpleId ); /* Transfers ownership of path. */
132 Identifier( const RefCountPtr< const SearchContext > & searchContext, Ast::NamespaceReference::Base base, const RefCountPtr< const Ast::NamespacePath > & path, const char * simpleId );
133 Identifier( const RefCountPtr< const SearchContext > & searchContext, const NamespaceReference & namespaceRef, const char * simpleId );
134 Identifier( const Identifier & orig );
135 ~Identifier( );
137 const SearchContext & searchContext( ) const { return *searchContext_; }
138 NamespaceReference::Base base( ) const { return namespaceRef_.base( ); }
139 const NamespacePath & path( ) const { return namespaceRef_.path( ); }
140 const char * simpleId( ) const { return simpleId_; }
142 /* Be careful when using the following destructive conversion functions!
143 * *this will be unusable after calling these, and should be destroyed.
145 Ast::PlacedIdentifier * place( const Ast::SourceLocation & loc ); /* Reinterprets the identifier as a placed (LHS) identifier. Always returns a new PlacedIdentifier, but will report an error if the conversion is unnatural. */
146 const char * strip( const Ast::SourceLocation & loc ); /* Extracts the simple identifier. */
147 RefCountPtr< const char > refstrip( const Ast::SourceLocation & loc ); /* Warning! This will pass ownership to the reference counted result. Must not be used if there exist other references to the simpleId_ memory! */
149 void show( std::ostream & os, Ast::Identifier::Type type, bool showAbsoluteMark = true ) const;
150 void debugShow( std::ostream & os ) const;
152 /* Warning! Comparison only takes the explicit part of the identifier into account. The search path
153 * is not used in the comparison, but absolute paths will precede relative paths.
155 bool operator < ( const Identifier & other ) const;
157 static const char * identifierPrefix( Type type );
160 class IdentifierPtrLess
162 public:
163 bool operator () ( const Ast::Identifier * id1, const Ast::Identifier * id2 ) const
165 return *id1 < *id2;
169 /* A placed identifier belongs to the current environment, expressed using only a simple identifier.
170 * That is, it is an absolute identifier, but looks like a relative identifier. Due to the risk
171 * of initial misinterpretation of a simple identifier in the scanner, there are methods that the parser
172 * can use for converting to the other possible types of token values.
173 * It is typically the left hand side of a binding statement.
175 class PlacedIdentifier
177 RefCountPtr< const NamespacePath > absolutePath_;
178 const char * simpleId_; /* Will not be deallocated, see memory management note above! */
179 public:
180 PlacedIdentifier( const RefCountPtr< const NamespacePath > & absolutePath, const char * simpleId );
181 PlacedIdentifier( NamespacePath * absolutePath, const char * simpleId ); /* Transfers ownership of absolutePath. */
182 PlacedIdentifier( const NamespacePath & absolutePath, const char * simpleId );
183 PlacedIdentifier( const PlacedIdentifier & orig );
184 ~PlacedIdentifier( );
186 const NamespacePath & absolutePath( ) const { return *absolutePath_; }
187 const RefCountPtr< const NamespacePath > & absolutePathRef( ) const { return absolutePath_; }
188 const char * simpleId( ) const { return simpleId_; }
190 Ast::PlacedIdentifier * clone( ) const;
191 Ast::Identifier * newAbsolute( ) const;
193 /* Be careful when using the following destructive conversion functions!
194 * *this will be unusable after calling these, and should be destroyed.
196 const char * strip( ); /* Extracts the simple identifier. */
197 RefCountPtr< const char > refstrip( ); /* Warning! This will pass ownership to the reference counted result. Must not be used if there exist other references to the simpleId_ memory! */
199 /* Since it should be clear from the context that this is a placed identifier, a leading "::" is _not_ shown to reduce clutter.
201 void show( std::ostream & os, Ast::Identifier::Type type ) const;
203 bool operator < ( const PlacedIdentifier & other ) const;
206 class PlacedIdentifierPtrLess
208 public:
209 bool operator () ( const Ast::PlacedIdentifier * id1, const Ast::PlacedIdentifier * id2 ) const
211 return *id1 < *id2;