Update procedures
[shapes.git] / source / identifier.cc
blob63392a5b23ee7f2ef6b0e50d3c310b446ac61800
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 #include "identifier.h"
20 #include "sourcelocation.h"
21 #include "consts.h"
22 #include "check.h"
23 #include "globals.h"
24 #include "environment.h"
25 #include "shapesexceptions.h"
27 using namespace Shapes;
30 const RefCountPtr< const Ast::NamespacePath > Ast::THE_EMPTY_NAMESPACE_PATH( new Ast::NamespacePath( ) );
31 const RefCountPtr< const Ast::SearchContext > Ast::THE_EMPTY_SEARCH_CONTEXT( new Ast::SearchContext( Ast::THE_EMPTY_NAMESPACE_PATH, RefCountPtr< const char >( NullPtr< const char >( ) ) ) );
34 int
35 Ast::compare( const Ast::NamespacePath & path1, const Ast::NamespacePath & path2 )
37 if( path1.size( ) < path2.size( ) )
38 return -1;
39 if( path1.size( ) > path2.size( ) )
40 return 1;
42 Ast::NamespacePath::const_iterator i1 = path1.begin( );
43 Ast::NamespacePath::const_iterator i2 = path2.begin( );
44 Ast::NamespacePath::const_iterator end1 = path1.end( );
45 for( ; i1 != end1; ++i1, ++i2 ){
46 int cmp = strcmp( *i1, *i2 );
47 if( cmp < 0 )
48 return -1;
49 if( cmp > 0 )
50 return 1;
52 return 0;
56 //bool
57 //Ast::operator < ( const Ast::NamespacePath & path1, const Ast::NamespacePath & path2 )
58 //{
59 // return compare( path1, path2 ) < 0;
60 //}
63 void
64 Ast::NamespaceReference::show( std::ostream & os, bool showAbsoluteMark ) const
66 switch( base_ ){
67 case ABSOLUTE:
68 if( showAbsoluteMark )
69 os << Interaction::NAMESPACE_SEPARATOR ;
70 break;
71 case LOCAL:
72 os << Interaction::ENCAPSULATION_MARK ;
73 break;
74 case RELATIVE:
75 break;
78 Ast::NamespacePath::const_iterator i = path_->begin( );
79 for( ; i != path_->end( ) && Ast::SearchContext::isEncapsulationName( *i ); ++i )
81 if( i != path_->end( ) ){
82 os << *i ;
83 for( ++i; i != path_->end( ); ++i ){
84 if( ! Ast::SearchContext::isEncapsulationName( *i ) )
85 os << Interaction::NAMESPACE_SEPARATOR << *i ;
91 bool
92 Ast::SearchContext::insideEncapsulationNamespace( ) const
94 if( lexicalPath_->empty( ) )
95 return false;
96 /* An alternative condition that could be used below:
97 * lexicalPath_.size( ) == encapsulationPath_.size( )
98 * However, list<>::size is not constant time, so a name-based condition is used instead.
100 return isEncapsulationName( lexicalPath_->back( ) );
104 RefCountPtr< const char >
105 Ast::SearchContext::makePrivateName( size_t i )
107 std::ostringstream oss;
108 oss << i ;
109 return strrefdup( oss );
113 RefCountPtr< const char >
114 Ast::SearchContext::makeEncapsulationName( size_t i )
116 std::ostringstream oss;
117 oss << "^" << i ;
118 return strrefdup( oss );
122 bool
123 Ast::SearchContext::isEncapsulationName( const char * name )
125 return name[0] == '^';
129 Ast::Identifier::Identifier( const RefCountPtr< const SearchContext > & searchContext, Ast::NamespaceReference::Base base, Ast::NamespacePath * path, const char * simpleId )
130 : searchContext_( searchContext ), namespaceRef_( base, path ), simpleId_( simpleId )
133 Ast::Identifier::Identifier( const RefCountPtr< const SearchContext > & searchContext, Ast::NamespaceReference::Base base, const RefCountPtr< const Ast::NamespacePath > & path, const char * simpleId )
134 : searchContext_( searchContext ), namespaceRef_( base, path ), simpleId_( simpleId )
137 Ast::Identifier::Identifier( const RefCountPtr< const SearchContext > & searchContext, const NamespaceReference & namespaceRef, const char * simpleId )
138 : searchContext_( searchContext ), namespaceRef_( namespaceRef ), simpleId_( simpleId )
141 Ast::Identifier::Identifier( const Ast::Identifier & orig )
142 : searchContext_( orig.searchContext_ ), namespaceRef_( orig.namespaceRef_ ), simpleId_( orig.simpleId_ )
145 Ast::Identifier::~Identifier( )
147 /* Note that we intentionally allow simpleId_ to leak here, see memory management note in identifier.h.
151 Ast::PlacedIdentifier *
152 Ast::Identifier::place( const Ast::SourceLocation & loc )
154 if( namespaceRef_.base( ) != Ast::NamespaceReference::RELATIVE || namespaceRef_.path( ).size( ) != 0 ){
155 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( loc, strrefdup( "Expected simple identifier." ) ) );
157 Ast::PlacedIdentifier * res = new Ast::PlacedIdentifier( searchContext_->lexicalPath( ), simpleId_ );
158 simpleId_ = NULL;
159 return res;
162 const char *
163 Ast::Identifier::strip( const Ast::SourceLocation & loc )
165 if( namespaceRef_.base( ) != Ast::NamespaceReference::RELATIVE || namespaceRef_.path( ).size( ) != 0 ){
166 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( loc, strrefdup( "Expected simple identifier." ) ) );
168 const char * res = simpleId_;
169 simpleId_ = NULL;
170 return res;
173 RefCountPtr< const char >
174 Ast::Identifier::refstrip( const Ast::SourceLocation & loc )
176 if( namespaceRef_.base( ) != Ast::NamespaceReference::RELATIVE || namespaceRef_.path( ).size( ) != 0 ){
177 Ast::theAnalysisErrorsList.push_back( new Exceptions::ScannerError( loc, strrefdup( "Expected simple identifier." ) ) );
179 RefCountPtr< const char > res( simpleId_ );
180 simpleId_ = NULL;
181 return res;
184 void
185 Ast::Identifier::show( std::ostream & os, Type type, bool showAbsoluteMark ) const
187 namespaceRef_.show( os, showAbsoluteMark );
188 if( ! namespaceRef_.path( ).empty( ) )
189 os << Interaction::NAMESPACE_SEPARATOR ;
190 os << identifierPrefix( type ) << simpleId_ ;
193 void
194 Ast::Identifier::debugShow( std::ostream & os ) const
196 os << "Identifier: " ;
197 if( namespaceRef_.base( ) == Ast::NamespaceReference::ABSOLUTE ){
198 os << Interaction::NAMESPACE_SEPARATOR ;
199 } else {
200 os << "(" ;
201 for( Ast::NamespacePath::const_iterator i = searchContext_->lexicalPath( )->begin( ); i != searchContext_->lexicalPath( )->end( ); ++i ){
202 os << *i << Interaction::NAMESPACE_SEPARATOR ;
204 os << ") " ;
207 if( namespaceRef_.base( ) == Ast::NamespaceReference::LOCAL )
208 os << Interaction::ENCAPSULATION_MARK ;
210 for( Ast::NamespacePath::const_iterator i = namespaceRef_.path( ).begin( ); i != namespaceRef_.path( ).end( ); ++i ){
211 os << *i << Interaction::NAMESPACE_SEPARATOR ;
214 os << simpleId_ ;
218 bool
219 Ast::Identifier::operator < ( const Ast::Identifier & other ) const
221 if( base( ) < other.base( ) ){
222 return true;
224 if( base( ) > other.base( ) ){
225 return false;
228 Ast::NamespacePath::const_iterator i1 = namespaceRef_.path( ).begin( );
229 Ast::NamespacePath::const_iterator end1 = namespaceRef_.path( ).end( );
230 Ast::NamespacePath::const_iterator i2 = other.namespaceRef_.path( ).begin( );
231 Ast::NamespacePath::const_iterator end2 = other.namespaceRef_.path( ).end( );
233 while( i1 != end1 && i2 != end2 )
235 int cmp = strcmp( *i1, *i2 );
236 if( cmp < 0 )
237 return true;
238 if( cmp > 0 )
239 return false;
240 ++i1;
241 ++i2;
244 if( i1 != end1 )
245 return false;
246 if( i2 != end2 )
247 return true;
249 return strcmp( simpleId_, other.simpleId_ ) < 0;
252 const char *
253 Ast::Identifier::identifierPrefix( Type type )
255 switch( type )
257 case VARIABLE:
258 return "";
259 case STATE:
260 return Interaction::STATE_PREFIX;
261 case DYNAMIC_VARIABLE:
262 return Interaction::DYNAMIC_VARIABLE_PREFIX;
263 case DYNAMIC_STATE:
264 return Interaction::DYNAMIC_STATE_PREFIX;
265 case TYPE:
266 return "";
272 Ast::PlacedIdentifier::PlacedIdentifier( const RefCountPtr< const NamespacePath > & absolutePath, const char * simpleId )
273 : absolutePath_( absolutePath ), simpleId_( simpleId )
276 Ast::PlacedIdentifier::PlacedIdentifier( Ast::NamespacePath * absolutePath, const char * simpleId )
277 : absolutePath_( absolutePath ), simpleId_( simpleId )
280 Ast::PlacedIdentifier::PlacedIdentifier( const Ast::NamespacePath & absolutePath, const char * simpleId )
281 : absolutePath_( absolutePath ), simpleId_( simpleId )
284 Ast::PlacedIdentifier::PlacedIdentifier( const Ast::PlacedIdentifier & orig )
285 : absolutePath_( orig.absolutePath_ ), simpleId_( orig.simpleId_ )
288 Ast::PlacedIdentifier::~PlacedIdentifier( )
290 /* Note that we intentionally allow simpleId_ to leak here, see memory management note in identifier.h.
294 Ast::PlacedIdentifier *
295 Ast::PlacedIdentifier::clone( ) const
297 /* Here we use that the simpleId_ is not going to be deallocated, so we can share with the constructed object.
299 return new Ast::PlacedIdentifier( absolutePath_, simpleId_ );
302 Ast::Identifier *
303 Ast::PlacedIdentifier::newAbsolute( ) const
305 /* Here we use that the simpleId_ is not going to be deallocated, so we can share with the constructed object.
307 return new Ast::Identifier( Ast::THE_EMPTY_SEARCH_CONTEXT, Ast::NamespaceReference::ABSOLUTE, absolutePath_, simpleId_ );
310 const char *
311 Ast::PlacedIdentifier::strip( )
313 const char * res = simpleId_;
314 simpleId_ = NULL;
315 return res;
318 RefCountPtr< const char >
319 Ast::PlacedIdentifier::refstrip( )
321 RefCountPtr< const char > res( simpleId_ );
322 simpleId_ = NULL;
323 return res;
326 void
327 Ast::PlacedIdentifier::show( std::ostream & os, Ast::Identifier::Type type ) const
329 for( Ast::NamespacePath::const_iterator i = absolutePath( ).begin( ); i != absolutePath( ).end( ); ++i ){
330 if( ! Ast::SearchContext::isEncapsulationName( *i ) )
331 os << *i << Interaction::NAMESPACE_SEPARATOR ;
334 os << Ast::Identifier::identifierPrefix( type ) << simpleId_ ;
337 bool
338 Ast::PlacedIdentifier::operator < ( const Ast::PlacedIdentifier & other ) const
340 Ast::NamespacePath::const_iterator i1 = absolutePath( ).begin( );
341 Ast::NamespacePath::const_iterator end1 = absolutePath( ).end( );
342 Ast::NamespacePath::const_iterator i2 = other.absolutePath( ).begin( );
343 Ast::NamespacePath::const_iterator end2 = other.absolutePath( ).end( );
345 while( i1 != end1 && i2 != end2 )
347 int cmp = strcmp( *i1, *i2 );
348 if( cmp < 0 )
349 return true;
350 if( cmp > 0 )
351 return false;
352 ++i1;
353 ++i2;
356 if( i1 != end1 )
357 return false;
358 if( i2 != end2 )
359 return true;
361 return strcmp( simpleId_, other.simpleId_ ) < 0;