Improvements to namespaces and file inclusion
[shapes.git] / source / environment.cc
blobee98cd44336db4f9d03cacc9eeab65990ab6f676
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 2008, 2013, 2014 Henrik Tidefelt
19 #include <cmath>
20 #include <iomanip>
22 #include "environment.h"
23 #include "shapesexceptions.h"
24 #include "shapescore.h"
25 #include "consts.h"
26 #include "globals.h"
27 #include "shapesvalue.h"
28 #include "classtypes.h"
29 #include "hottypes.h"
30 #include "continuations.h"
31 #include "statetypes.h"
32 #include "multipage.h"
33 #include "errorhandlers.h"
34 #include "debuglog.h"
35 #include "check.h"
37 using namespace Shapes;
40 size_t Kernel::Environment::createdCount = 0;
41 size_t Kernel::Environment::liveCount = 0;
42 Kernel::Environment::LexicalKey Kernel::Environment::theMissingKey( 0, std::numeric_limits< size_t >::max( ) );
43 const Ast::SourceLocation Kernel::Environment::THE_INITIALIZATION_LOCATION( Ast::FileID::build_internal( "< Initialization >" ) );
44 template< class T >
45 class Binary
47 public:
48 T val;
49 Binary( const T & _val ) : val( _val ) { }
52 template< class T >
53 std::ostream &
54 operator << ( std::ostream & os, const Binary< T > & self )
56 for( int i = 8*sizeof( T ) - 1; i >= 0; --i )
58 if( (( self.val & (T(1)<<i) )) != 0 )
60 os << 1 ;
62 else
64 os << '_' ;
67 return os;
72 Kernel::Thunk::Thunk( Kernel::PassedEnv env, Kernel::PassedDyn dyn, Ast::Expression * expr )
73 : env_( env ), dyn_( dyn ), expr_( expr ), forced_( false )
74 { }
76 void
77 Kernel::Thunk::force( Kernel::EvalState * evalState, bool onlyOnce ) const
79 if( onlyOnce )
81 if( forced_ )
83 throw Exceptions::InternalError( "It's unwise to force a thunk twice! It should be deleted right after the first force." );
85 forced_ = true;
88 evalState->expr_ = expr_;
89 evalState->env_ = env_;
90 evalState->dyn_ = dyn_;
92 /* The continuation is not se by the thunk! */
95 Kernel::Thunk *
96 Kernel::Thunk::deepCopy( )
98 return new Thunk( env_, dyn_, expr_ );
102 void
103 Kernel::Thunk::gcMark( Kernel::GCMarkedSet & marked )
105 if( ! forced_ )
107 env_->gcMark( marked );
108 dyn_->gcMark( marked );
112 Ast::Expression *
113 Kernel::Thunk::getExpr( )
115 return expr_;
118 void
119 Kernel::Thunk::printEnv( std::ostream & os ) const
121 env_->print( os );
125 Kernel::Variable::Variable( const RefCountPtr< const Lang::Value > & val )
126 : thunk_( 0 ), val_( val ), state_( Kernel::Variable::COLD )
129 Kernel::Variable::Variable( Kernel::Thunk * thunk )
130 : thunk_( thunk ), val_( NullPtr< const Lang::Value >( ) ), state_( Kernel::Variable::THUNK )
133 Kernel::Variable::~Variable( )
135 if( thunk_ != 0 )
137 delete thunk_;
141 Kernel::State::State( )
142 : alive_( true )
145 Kernel::State::~State( )
148 void
149 Kernel::State::tackOn( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
151 if( ! alive_ )
153 throw Exceptions::DeadStateAccess( );
155 this->tackOnImpl( evalState, piece, callLoc );
158 void
159 Kernel::State::peek( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
161 if( ! alive_ )
163 throw Exceptions::DeadStateAccess( );
165 this->peekImpl( evalState, callLoc );
168 void
169 Kernel::State::freeze( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
171 if( ! alive_ )
173 throw Exceptions::DeadStateAccess( );
175 /* It would make sense to have an intermediate state here.
177 alive_ = false;
179 // Perhaps, it would be smart to use a continuation to erase the implementation once it is used...
180 // evalState->cont_ = Kernel::ContRef( new Kernel::StmtStoreVariableContinuation( selfRef, evalState->cont_, callLoc ) );
182 this->freezeImpl( evalState, callLoc );
185 RefCountPtr< const Lang::Function >
186 Kernel::State::getMutator( const char * mutatorID )
188 return getClass( )->getMutator( mutatorID );
191 RefCountPtr< const char >
192 Kernel::State::getTypeName( ) const
194 return this->getClass( )->getPrettyName( );
197 bool
198 Kernel::State::isAlive( ) const
200 return alive_;
204 void
205 Kernel::Variable::force( const Kernel::VariableHandle & selfRef, Kernel::EvalState * evalState ) const
207 /* The reason that selfRef is passed as const reference is that this is a const method, and it is expected that selfRef actually is a handle to *this. Hence, it does not make sense to not allow the selfRef to be passed by const reference. On the other hand, we actually do need to do some non-const things with selfRef, and therefore we resort to some ugly const_casting this time.
209 if( state_ == Kernel::Variable::THUNK )
211 state_ = Kernel::Variable::FORCING;
212 evalState->cont_ = Kernel::ContRef( new Kernel::StoreVariableContinuation( const_cast< Kernel::VariableHandle & >( selfRef ), evalState->cont_, thunk_->getExpr( )->loc( ) ) );
213 thunk_->force( evalState );
214 delete thunk_;
215 thunk_ = 0;
216 return;
218 if( val_ == NullPtr< const Lang::Value >( ) )
220 if( state_ == Kernel::Variable::FORCING )
222 throw Exceptions::MiscellaneousRequirement( "Cyclic forcing." );
224 throw Exceptions::InternalError( "Force failed. No value, not forcing." );
226 Kernel::ContRef cont = evalState->cont_;
227 cont->takeHandle( const_cast< Kernel::VariableHandle & >( selfRef ), evalState );
230 RefCountPtr< const Lang::Value > &
231 Kernel::Variable::getUntyped( ) const
233 if( val_ == NullPtr< const Lang::Value >( ) )
235 throw Exceptions::InternalError( "The value is not ready to be get without continuation." );
237 return val_;
241 bool
242 Kernel::Variable::isThunk( ) const
244 return ( state_ & Kernel::Variable::FORCING ) != 0;
247 Kernel::Thunk *
248 Kernel::Variable::copyThunk( ) const
250 if( thunk_ == 0 )
252 throw Exceptions::InternalError( "Variable::copyThunk: There was no thunk to copy." );
254 return thunk_->deepCopy( );
257 void
258 Kernel::Variable::gcMark( Kernel::GCMarkedSet & marked )
260 if( thunk_ != 0 )
262 thunk_->gcMark( marked );
263 return;
265 if( val_ != NullPtr< const Lang::Value >( ) )
267 const_cast< Lang::Value * >( val_.getPtr( ) )->gcMark( marked );
271 void
272 Kernel::Variable::setValue( const RefCountPtr< const Lang::Value > & val ) const
274 val_ = val;
275 state_ = Kernel::Variable::COLD;
279 Kernel::DynamicVariableProperties::~DynamicVariableProperties( )
281 /* We do not own id_.
285 Kernel::DynamicStateProperties::~DynamicStateProperties( )
287 /* We do not own id_.
292 void
293 Kernel::Environment::initDefineCoreFunction( Lang::CoreFunction * fun )
295 initDefineHandle( fun->getTitle( ), Kernel::VariableHandle( new Kernel::Variable( RefCountPtr< const Lang::Value >( fun ) ) ) );
298 void
299 Kernel::Environment::initDefineCoreFunction( RefCountPtr< const Lang::CoreFunction > fun )
301 initDefineHandle( fun->getTitle( ), Kernel::VariableHandle( new Kernel::Variable( fun ) ) );
304 void
305 Kernel::Environment::initDefineHandle( const char * simpleId, const Kernel::VariableHandle & val )
307 Ast::PlacedIdentifier id( Lang::THE_CORE_NAMESPACE_PATH, simpleId );
309 if( Interaction::logGlobals )
311 Kernel::theDebugLog.os( ) << "--log-globals> variable: " << simpleId << std::endl ;
314 if( ! bindings_->insert( id, THE_INITIALIZATION_LOCATION ) )
316 /* An error message has already been generated. */
317 return;
319 values_->push_back( val );
321 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
322 if( values_->size( ) != bindings_->size( ) ){
323 throw Exceptions::InternalError( "Kernel::Environment::initDefineHandle: Inconsistent number of values." );
324 } );
327 void
328 Kernel::Environment::initDefine( const char * simpleId, const RefCountPtr< const Lang::Value > & val )
330 initDefineHandle( simpleId, Kernel::VariableHandle( new Kernel::Variable( val ) ) );
333 void
334 Kernel::Environment::initDefine( const char * simpleId, Kernel::StateHandle state )
336 initDefine( Ast::PlacedIdentifier( Lang::THE_CORE_NAMESPACE_PATH, simpleId ), state );
339 void
340 Kernel::Environment::initDefine( const Ast::PlacedIdentifier & id, Kernel::StateHandle state )
342 if( Interaction::logGlobals )
344 std::ostream & os = Kernel::theDebugLog.os( );
345 os << "--log-globals> state: " ;
346 id.show( os, Ast::Identifier::STATE );
347 os << std::endl ;
350 if( ! stateBindings_->insert( id, THE_INITIALIZATION_LOCATION ) )
352 /* An error message has already been generated. */
353 return;
355 states_->push_back( state );
357 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
358 if( states_->size( ) != stateBindings_->size( ) ){
359 throw Exceptions::InternalError( "Kernel::Environment::initDefine: Inconsistent number of states." );
360 } );
363 void
364 Kernel::Environment::initDefineClass( const RefCountPtr< const Lang::Class > & cls )
366 RefCountPtr< const char > idRef = cls->getPrettyName( );
367 const char * simpleId = strdup( idRef.getPtr( ) );
368 charPtrDeletionList_.push_back( simpleId );
369 initDefineHandle( simpleId, Kernel::VariableHandle( new Kernel::Variable( cls ) ) );
372 void
373 Kernel::Environment::initDefineDynamic( DynamicVariableProperties * dynProps )
375 const Ast::PlacedIdentifier & id( dynProps->id( ) );
377 if( Interaction::logGlobals )
379 Kernel::theDebugLog.os( ) << "--log-globals> dynamic: " ;
380 id.show( Kernel::theDebugLog.os( ), Ast::Identifier::DYNAMIC_VARIABLE );
381 Kernel::theDebugLog.os( ) << std::endl ;
384 if( ! dynamicKeyBindings_->insert( id, THE_INITIALIZATION_LOCATION ) )
386 /* An error message has already been generated. */
387 return;
389 dynamicKeyValues_->push_back( dynProps );
391 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
392 if( dynamicKeyValues_->size( ) != dynamicKeyBindings_->size( ) ){
393 throw Exceptions::InternalError( "Kernel::Environment::initDefineDynamic: Inconsistent number of dynamic keys (1 argument)." );
394 } );
397 void
398 Kernel::Environment::initDefineDynamic( const char * simpleId, const RefCountPtr< const Lang::Function > & filter, const Kernel::VariableHandle & defaultVal )
400 initDefineDynamic( newPlacedIdentifier( Lang::THE_CORE_NAMESPACE_PATH, simpleId ), filter, defaultVal );
403 void
404 Kernel::Environment::initDefineDynamic( const Ast::PlacedIdentifier * id, const RefCountPtr< const Lang::Function > & filter, const Kernel::VariableHandle & defaultVal )
406 if( ! dynamicKeyBindings_->insert( *id, THE_INITIALIZATION_LOCATION ) )
408 /* An error message has already been generated. */
409 return;
411 Kernel::DynamicEnvironmentKeyType key = dynamicKeyValues_->size( );
412 dynamicKeyValues_->push_back( new Kernel::UserDynamicVariableProperties( id, key, filter, defaultVal ) );
414 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
415 if( dynamicKeyValues_->size( ) != dynamicKeyBindings_->size( ) ){
416 throw Exceptions::InternalError( "Kernel::Environment::initDefineDynamic: Inconsistent number of dynamic keys (3 arguments)." );
417 } );
420 void
421 Kernel::Environment::initDefineDynamicHandler( const Ast::PlacedIdentifier & id, const char * msg )
423 initDefineDynamic( id.clone( ),
424 Lang::THE_IDENTITY,
425 Helpers::newValHandle( new Lang::ExceptionWrapper< Exceptions::HandlerError >( id, msg ) ) );
428 PtrOwner_back_Access< std::list< const Ast::PlacedIdentifier * > > Kernel::Environment::coreIdentifiers;
430 const Ast::PlacedIdentifier *
431 Kernel::Environment::newPlacedIdentifier( const RefCountPtr< const Ast::NamespacePath > & path, const char * simpleId )
433 const Ast::PlacedIdentifier * id = new Ast::PlacedIdentifier( path, simpleId );
434 coreIdentifiers.push_back( id );
435 return id;
438 Kernel::Environment::Environment( std::list< Kernel::Environment * > & garbageArea, const char * debugName )
439 : parent_( 0 ),
440 bindings_( new Ast::IdentifierTree( NULL, false ) ),
441 values_( new std::vector< Kernel::VariableHandle >( ) ),
442 dynamicKeyBindings_( new Ast::IdentifierTree( NULL, false ) ),
443 dynamicKeyValues_( new std::vector< DynamicVariableProperties * > ),
444 stateBindings_( new Ast::IdentifierTree( NULL, false ) ),
445 states_( new std::vector< Kernel::StateHandle >( ) ),
446 dynamicStateKeyBindings_( new Ast::IdentifierTree( NULL, false ) ),
447 dynamicStateKeyValues_( new std::vector< DynamicStateProperties * > ),
448 debugName_( debugName )
450 garbageArea.push_back( this );
451 ++createdCount;
452 ++liveCount;
455 Kernel::Environment::Environment( std::list< Kernel::Environment * > & garbageArea, Environment * parent, Ast::IdentifierTree * bindings, const RefCountPtr< std::vector< VariableHandle > > & values, Ast::IdentifierTree * stateBindings, const RefCountPtr< std::vector< StateHandle > > & states, const char * debugName )
456 : parent_( parent ),
457 bindings_( bindings ), values_( values ), dynamicKeyBindings_( 0 ),
458 stateBindings_( stateBindings ), states_( states ), dynamicStateKeyBindings_( 0 ),
459 debugName_( debugName )
460 //, unitMap_( NullPtr< Kernel::Environment::UnitMapType >( ) )
462 garbageArea.push_back( this );
463 // if( parent_ != 0 )
464 // {
465 // unitMap_ = parent->unitMap_;
466 // }
467 ++createdCount;
468 ++liveCount;
471 Kernel::Environment::~Environment( )
473 clear( );
474 if( dynamicKeyBindings_ != 0 )
476 if( parent_ == 0 )
478 /* The condition means that this is the global evironment, which created its own map.
480 delete dynamicKeyBindings_;
482 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
484 for( std::vector< DynamicVariableProperties * >::iterator i = dynamicKeyValues_->begin( ); i != dynamicKeyValues_->end( ); ++i )
486 if( *i != 0 )
488 delete *i;
491 delete dynamicKeyValues_;
493 if( stateBindings_ != 0 )
495 if( parent_ == 0 )
497 /* The condition means that this is the global evironment, which created its own map.
499 delete stateBindings_;
501 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
503 for( std::vector< StateHandle >::iterator i = states_->begin( ); i != states_->end( ); ++i )
505 if( *i != 0 )
507 delete *i;
511 if( dynamicStateKeyBindings_ != 0 )
513 if( parent_ == 0 )
515 /* The condition means that this is the global evironment, which created its own map.
517 delete dynamicStateKeyBindings_;
519 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
521 for( std::vector< DynamicStateProperties * >::iterator i = dynamicStateKeyValues_->begin( ); i != dynamicStateKeyValues_->end( ); ++i )
523 if( *i != 0 )
525 delete *i;
528 delete dynamicStateKeyValues_;
530 --liveCount;
533 void
534 Kernel::Environment::setParent( Kernel::Environment * parent )
536 parent_ = parent;
537 // unitMap_ = parent.unitMap_;
540 Kernel::Environment *
541 Kernel::Environment::getParent( )
543 if( isBaseEnvironment( ) )
545 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level environment." );
547 return parent_;
550 const Kernel::Environment *
551 Kernel::Environment::getParent( ) const
553 if( isBaseEnvironment( ) )
555 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level environment." );
557 return parent_;
560 void
561 Kernel::Environment::setupDynamicKeyVariables( Ast::IdentifierTree * dynamicKeyBindings )
563 if( dynamicKeyBindings_ == 0 )
565 dynamicKeyBindings_ = dynamicKeyBindings;
566 dynamicKeyValues_ = new std::vector< DynamicVariableProperties * >;
568 CHECK(
569 else
571 if( dynamicKeyBindings_ != dynamicKeyBindings )
573 throw Exceptions::InternalError( "Kernel::Environment::setupDynamicKeyVariables: dynamicKeyBindings_ != dynamicKeyBindings" );
577 size_t theSize = dynamicKeyBindings_->size( );
578 dynamicKeyValues_->reserve( theSize );
579 while( dynamicKeyValues_->size( ) < theSize )
581 dynamicKeyValues_->push_back( 0 );
585 void
586 Kernel::Environment::setupDynamicStateKeyVariables( Ast::IdentifierTree * dynamicStateKeyBindings )
588 if( dynamicStateKeyBindings_ == 0 )
590 dynamicStateKeyBindings_ = dynamicStateKeyBindings;
591 dynamicStateKeyValues_ = new std::vector< DynamicStateProperties * >;
593 CHECK(
594 else
596 if( dynamicStateKeyBindings_ != dynamicStateKeyBindings )
598 throw Exceptions::InternalError( "Kernel::Environment::setupDynamicStateKeyVariables: dynamicStateKeyBindings_ != dynamicStateKeyBindings" );
602 size_t theSize = dynamicStateKeyBindings_->size( );
603 dynamicStateKeyValues_->reserve( theSize );
604 while( dynamicStateKeyValues_->size( ) < theSize )
606 dynamicStateKeyValues_->push_back( 0 );
610 void
611 Kernel::Environment::extendVectors( )
613 values_->reserve( bindings_->size( ) );
614 while( values_->size( ) < bindings_->size( ) )
616 values_->push_back( NullPtr< Kernel::Variable >( ) );
619 states_->reserve( stateBindings_->size( ) );
620 while( states_->size( ) < stateBindings_->size( ) )
622 states_->push_back( NullPtr< Kernel::State >( ) );
627 void
628 Kernel::Environment::clear( )
630 /* Strange that this is empty...
631 * The idea, though, is that the reference counting of this->values shall take care of deletion.
635 Ast::AnalysisEnvironment *
636 Kernel::Environment::newAnalysisEnvironment( Ast::AnalysisEnvironment * parent ) const
638 Ast::AnalysisEnvironment * res = new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList, parent, bindings_, stateBindings_ );
639 if( dynamicKeyBindings_ != 0 )
641 res->setupDynamicKeyVariables( dynamicKeyBindings_ );
643 if( dynamicStateKeyBindings_ != 0 )
645 res->setupDynamicStateKeyVariables( dynamicStateKeyBindings_ );
648 return res;
651 void
652 Kernel::Environment::gcMark( Kernel::GCMarkedSet & marked )
654 if( gcMarked_ )
656 return;
658 gcMarked_ = true;
659 marked.insert( marked.begin( ), this );
661 values_->clear( );
664 void
665 Kernel::Environment::collect( std::list< Kernel::Environment * > & garbageArea )
667 for( std::list< Kernel::Environment * >::iterator i = garbageArea.begin( ); i != garbageArea.end( ); ++i )
669 (*i)->clear_gcMarked( );
672 Kernel::GCMarkedSet marked;
673 for( std::list< Kernel::Environment * >::iterator i = garbageArea.begin( ); i != garbageArea.end( ); ++i )
675 (*i)->gcMark( marked );
678 for( std::list< Kernel::Environment * >::iterator i = garbageArea.begin( ); i != garbageArea.end( ); )
680 if( (*i)->gcMarked( ) )
682 ++i;
683 continue;
685 std::list< Kernel::Environment * >::iterator tmp = i;
686 ++i;
687 delete *tmp;
688 garbageArea.erase( tmp );
693 const size_t Ast::IdentifierTree::NOT_FOUND = std::numeric_limits< size_t >::max( );
695 Ast::IdentifierTree::IdentifierTree( IdentifierTree * parent, bool encapsulation )
696 : size_( 0 ), root_( ( parent == NULL ) ? this : ( parent->root( ) ) ), encap_( ( encapsulation || parent == NULL ) ? this : ( parent->encap( ) ) ), encapParent_( encapsulation ? parent : NULL )
699 Ast::IdentifierTree::~IdentifierTree( )
701 typedef typeof namespaces_ MapType;
702 for( MapType::iterator i = namespaces_.begin( ); i != namespaces_.end( ); ++i )
704 if( i->second.kind( ) != NamespaceLink::PRIMARY )
705 continue;
706 delete i->second.node( );
710 Ast::IdentifierTree *
711 Ast::IdentifierTree::base( Ast::NamespaceReference::Base b )
713 switch( b ){
714 case Ast::NamespaceReference::ABSOLUTE:
715 return root_;
716 case Ast::NamespaceReference::LOCAL:
717 return encap_;
718 case Ast::NamespaceReference::RELATIVE:
719 return this;
723 const Ast::IdentifierTree *
724 Ast::IdentifierTree::base( Ast::NamespaceReference::Base b ) const
726 switch( b ){
727 case Ast::NamespaceReference::ABSOLUTE:
728 return root_;
729 case Ast::NamespaceReference::LOCAL:
730 return encap_;
731 case Ast::NamespaceReference::RELATIVE:
732 return this;
736 Ast::IdentifierTree *
737 Ast::IdentifierTree::newChild( const char * key, const Ast::SourceLocation & loc )
739 IdentifierTree * tree = new Ast::IdentifierTree( this, Ast::SearchContext::isEncapsulationName( key ) );
740 typedef typeof namespaces_ MapType;
741 namespaces_.insert( MapType::value_type( key, NamespaceLink( NamespaceLink::PRIMARY, tree ) ) );
742 if( encapParent_ != NULL ){
743 encapParent_->insertEncapsulationLink( key, tree, loc );
745 return tree;
748 bool
749 Ast::IdentifierTree::insert( const Ast::PlacedIdentifier & id, const Ast::SourceLocation & loc )
751 return insert( id.absolutePath( ).begin( ), id.absolutePath( ).end( ), id.simpleId( ), size_, loc );
754 bool
755 Ast::IdentifierTree::insertAlias( const Ast::PlacedIdentifier & id, const Ast::NamespaceReference & expansion, const Ast::SourceLocation & loc )
757 return insertAlias( id.absolutePath( ).begin( ), id.absolutePath( ).end( ), id.simpleId( ), expansion, loc );
760 bool
761 Ast::IdentifierTree::insert( Ast::NamespacePath::const_iterator begin, const Ast::NamespacePath::const_iterator & end, const char * simpleId, size_t pos, const Ast::SourceLocation & loc )
763 if( begin == end ){
765 typedef typeof simpleIdentifiers_ MapType;
766 if( simpleIdentifiers_.find( simpleId ) != simpleIdentifiers_.end( ) )
767 return false;
768 simpleIdentifiers_.insert( MapType::value_type( simpleId, pos ) );
769 ++size_;
770 if( encapParent_ != NULL ){
771 encapParent_->insertEncapsulationLink( simpleId, pos, loc );
773 return true;
775 }else{
777 typedef typeof namespaces_ MapType;
778 MapType::iterator j = namespaces_.find( *begin );
779 if( j != namespaces_.end( ) ){
781 bool result = j->second.node( )->insert( ++begin, end, simpleId, pos, loc );
782 if (result)
783 ++size_;
784 return result;
786 }else{
788 IdentifierTree * tree = newChild( *begin, loc );
789 bool result = tree->insert( ++begin, end, simpleId, pos, loc );
790 if (result)
791 ++size_;
792 return result;
799 bool
800 Ast::IdentifierTree::insertAlias( Ast::NamespacePath::const_iterator begin, const Ast::NamespacePath::const_iterator & end, const char * simpleId, const Ast::NamespaceReference & expansion, const Ast::SourceLocation & loc )
802 if( begin == end ){
804 bool found;
805 IdentifierTree * tree = resolveAlias( expansion, & found, loc );
807 typedef typeof namespaces_ MapType;
808 MapType::iterator j = namespaces_.find( simpleId );
809 if( j != namespaces_.end( ) ){
810 Ast::theAnalysisErrorsList.push_back( new Exceptions::NamespaceAliasCollision( loc, this, simpleId ) );
811 }else{
812 namespaces_.insert( MapType::value_type( simpleId, NamespaceLink( NamespaceLink::RESTRICTED, tree ) ) );
815 return found;
817 }else{
819 typedef typeof namespaces_ MapType;
820 MapType::iterator j = namespaces_.find( *begin );
821 if( j != namespaces_.end( ) ){
823 return j->second.node( )->insertAlias( ++begin, end, simpleId, expansion, loc );
825 }else{
827 IdentifierTree * tree = newChild( *begin, loc );
828 return tree->insertAlias( ++begin, end, simpleId, expansion, loc );
835 Ast::IdentifierTree *
836 Ast::IdentifierTree::resolveAlias( const Ast::NamespaceReference & expansion, bool * found, const Ast::SourceLocation & loc )
838 *found = true;
839 return base( expansion.base( ) )->resolveAlias( expansion.path( ).begin( ), expansion.path( ).end( ), found, loc );
842 Ast::IdentifierTree *
843 Ast::IdentifierTree::resolveAlias( const Ast::NamespacePath::const_iterator & begin, const Ast::NamespacePath::const_iterator & end, bool * found, const Ast::SourceLocation & loc )
845 if( begin == end ){
847 return this;
849 }else{
851 Ast::NamespacePath::const_iterator next(begin);
852 ++next;
853 typedef typeof namespaces_ MapType;
854 MapType::const_iterator j = namespaces_.find( *begin );
855 if( j == namespaces_.end( ) ){
856 *found = false;
857 IdentifierTree * tree = newChild( *begin, loc );
858 return tree->resolveAlias( next, end, found, loc );
861 return j->second.node( )->resolveAlias( next, end, found, loc );
866 void
867 Ast::IdentifierTree::insertEncapsulationLink( const char * key, size_t pos, const Ast::SourceLocation & loc )
869 typedef typeof simpleIdentifiers_ MapType;
870 if( simpleIdentifiers_.find( key ) != simpleIdentifiers_.end( ) ){
871 Ast::theAnalysisErrorsList.push_back( new Exceptions::EncapsulationIntroducingExisting( loc, key ) );
872 return;
874 simpleIdentifiers_.insert( MapType::value_type( key, pos ) );
877 void
878 Ast::IdentifierTree::insertEncapsulationLink( const char * key, Ast::IdentifierTree * tree, const Ast::SourceLocation & loc )
880 typedef typeof namespaces_ MapType;
881 if( namespaces_.find( key ) != namespaces_.end( ) ){
882 Ast::theAnalysisErrorsList.push_back( new Exceptions::EncapsulationNamespaceAliasCollision( loc, key ) );
883 return;
885 namespaces_.insert( MapType::value_type( key, NamespaceLink( NamespaceLink::SECONDARY, tree ) ) );
888 size_t
889 Ast::IdentifierTree::lookup( const Ast::Identifier & id ) const
891 const Ast::SearchContext & context = id.searchContext( );
893 switch( id.base( ) ){
894 case Ast::NamespaceReference::ABSOLUTE:
895 return lookupSuffix( false, id.path( ).begin( ), id.path( ).end( ), id.simpleId( ) );
897 case Ast::NamespaceReference::LOCAL:
898 return lookupInside( context.encapsulationPath( )->begin( ), context.encapsulationPath( )->end( ), id );
900 case Ast::NamespaceReference::RELATIVE:
902 size_t pos = lookupPrefix( context.lexicalPath( )->begin( ), context.lexicalPath( )->end( ), context.privateName( ).getPtr( ), id );
903 if( pos != NOT_FOUND )
904 return pos;
906 for( RefCountPtr< const Ast::LookinPathStack > i( context.lookinStack( ) ); i != NullPtr< const Ast::LookinPathStack >( ); i = i->cdr( ) ){
907 size_t pos = lookupInside( i->car( )->begin( ), i->car( )->end( ), id );
908 if( pos != NOT_FOUND )
909 return pos;
911 break;
914 return NOT_FOUND;
917 size_t
918 Ast::IdentifierTree::lookup( const Ast::PlacedIdentifier & id ) const
920 return lookupSuffix( false, id.absolutePath( ).begin( ), id.absolutePath( ).end( ), id.simpleId( ) );
923 size_t
924 Ast::IdentifierTree::lookupPrivateAlias( const Ast::PlacedIdentifier & id, const char * privateName ) const
926 /* Mimic how a relative identifier would be looked up with lookupPrefix, but only consider the private namespace.
928 if( privateName == NULL )
929 return NOT_FOUND;
931 const Ast::IdentifierTree * tree = this;
932 Ast::NamespacePath::const_iterator i = id.absolutePath( ).begin( );
933 Ast::NamespacePath::const_iterator end = id.absolutePath( ).end( );
934 for( ; i != end; ++i ){
935 typedef typeof namespaces_ MapType;
936 MapType::const_iterator j = tree->namespaces_.find( *i );
937 if( j == tree->namespaces_.end( ) )
938 break;
939 tree = j->second.node( );
941 if( i != end )
942 return NOT_FOUND;
944 typedef typeof namespaces_ MapType;
945 MapType::const_iterator j = tree->namespaces_.find( privateName );
946 if( j == tree->namespaces_.end( ) )
947 return NOT_FOUND;
949 /* We must pass an empty NamespacePath range, and id.absolutePath( ).begin( ) .. id.absolutePath( ).begin( )
950 * happens to be available.
952 return j->second.node( )->lookupSuffix( false, id.absolutePath( ).begin( ), id.absolutePath( ).begin( ), id.simpleId( ) );
955 size_t
956 Ast::IdentifierTree::lookupPrefix( const Ast::NamespacePath::const_iterator & begin, const Ast::NamespacePath::const_iterator & end, const char * privateName, const Ast::Identifier & id ) const
958 std::stack< const Ast::IdentifierTree * > path;
960 const Ast::IdentifierTree * tree = this;
961 path.push( tree );
962 Ast::NamespacePath::const_iterator i = begin;
963 for( ; i != end; ++i ){
964 typedef typeof namespaces_ MapType;
965 MapType::const_iterator j = tree->namespaces_.find( *i );
966 if( j == tree->namespaces_.end( ) )
967 break;
968 tree = j->second.node( );
969 path.push( tree );
972 /* Look in local namespace.
973 * Only do this for identifiers with empty relative path, and inside
974 * the current namespace.
976 if( i == end && id.path( ).empty( ) && privateName != NULL ){
977 typedef typeof namespaces_ MapType;
978 MapType::const_iterator j = tree->namespaces_.find( privateName );
979 if( j != tree->namespaces_.end( ) ){
981 size_t pos = j->second.node( )->lookupSuffix( false, id.path( ).begin( ), id.path( ).end( ), id.simpleId( ) );
982 if( pos != NOT_FOUND )
983 return pos;
988 while( ! path.empty( ) ){
989 tree = path.top( );
990 path.pop( );
991 size_t pos = tree->lookupSuffix( true, id.path( ).begin( ), id.path( ).end( ), id.simpleId( ) );
992 if( pos != NOT_FOUND )
993 return pos;
994 if( tree->encapParent_ != NULL )
995 break;
997 return NOT_FOUND;
1000 size_t Ast::IdentifierTree::lookupInside( const Ast::NamespacePath::const_iterator & begin, const Ast::NamespacePath::const_iterator & end, const Ast::Identifier & id ) const
1002 if( begin == end ){
1003 return lookupSuffix( false, id.path( ).begin( ), id.path( ).end( ), id.simpleId( ) );
1006 typedef typeof namespaces_ MapType;
1007 MapType::const_iterator i = namespaces_.find( *begin );
1008 if( i == namespaces_.end( ) )
1009 return NOT_FOUND;
1010 if( i->second.kind( ) != NamespaceLink::PRIMARY )
1011 return NOT_FOUND;
1013 Ast::NamespacePath::const_iterator next = begin;
1014 ++next;
1015 return i->second.node( )->lookupInside( next, end, id );
1018 size_t
1019 Ast::IdentifierTree::lookupSuffix( bool followRestricted, const Ast::NamespacePath::const_iterator & begin, const Ast::NamespacePath::const_iterator & end, const char * simpleId ) const
1021 if( begin == end ){
1023 typedef typeof simpleIdentifiers_ MapType;
1024 MapType::const_iterator i = simpleIdentifiers_.find( simpleId );
1025 if( i == simpleIdentifiers_.end( ) )
1026 return NOT_FOUND;
1028 return i->second;
1030 }else{
1032 const char * front = *begin;
1033 typedef typeof namespaces_ MapType;
1034 MapType::const_iterator i = namespaces_.find( front );
1035 if( i == namespaces_.end( ) )
1036 return NOT_FOUND;
1037 if( ! followRestricted && i->second.kind( ) == NamespaceLink::RESTRICTED )
1038 return NOT_FOUND;
1040 Ast::NamespacePath::const_iterator next(begin);
1041 ++next;
1042 return i->second.node( )->lookupSuffix( false, next, end, simpleId );
1048 Ast::PlacedIdentifier
1049 Ast::IdentifierTree::reverseMap( size_t pos ) const
1051 const char * simpleId;
1052 std::list< const char * > * absolutePath = reverseMapHelper( pos, & simpleId );
1053 if( absolutePath == NULL )
1054 throw Exceptions::InternalError( "Ast::IdentifierTree::reverseMap failure." );
1055 return Ast::PlacedIdentifier( absolutePath, simpleId );
1058 std::list< const char * > *
1059 Ast::IdentifierTree::reverseMapHelper( size_t pos, const char ** simpleIdDst ) const
1062 typedef typeof simpleIdentifiers_ MapType;
1063 for( MapType::const_iterator i = simpleIdentifiers_.begin( ); i != simpleIdentifiers_.end( ); ++i ){
1064 if( i->second == pos )
1066 std::list< const char * > * result( new std::list< const char * > );
1067 *simpleIdDst = i->first;
1068 return result;
1074 typedef typeof namespaces_ MapType;
1075 for( MapType::const_iterator i = namespaces_.begin( ); i != namespaces_.end( ); ++i ){
1076 if( i->second.kind( ) != NamespaceLink::PRIMARY )
1077 continue;
1078 std::list< const char * > * path = i->second.node( )->reverseMapHelper( pos, simpleIdDst );
1079 if( path == NULL )
1080 continue;
1081 path->push_front( i->first );
1082 return path;
1086 return NULL;
1089 void
1090 Ast::IdentifierTree::dumpMap( std::map< Ast::PlacedIdentifier, size_t > * dst ) const
1092 Ast::NamespacePath path;
1093 dumpMap( dst, & path );
1096 void
1097 Ast::IdentifierTree::dumpMap( std::map< Ast::PlacedIdentifier, size_t > * dst, Ast::NamespacePath * path ) const
1100 typedef typeof simpleIdentifiers_ MapType;
1101 typedef typeof *dst DstType;
1102 for( MapType::const_iterator i = simpleIdentifiers_.begin( ); i != simpleIdentifiers_.end( ); ++i ){
1103 dst->insert( DstType::value_type( Ast::PlacedIdentifier( *path, i->first ), i->second ) );
1108 typedef typeof namespaces_ MapType;
1109 for( MapType::const_iterator i = namespaces_.begin( ); i != namespaces_.end( ); ++i ){
1110 path->push_back( i->first );
1111 i->second.node( )->dumpMap( dst, path );
1112 path->pop_back( );
1117 void
1118 Ast::IdentifierTree::showPath( std::ostream & os ) const
1120 typedef std::list< const char * > ListType;
1121 ListType path;
1122 if( ! root_->pushPath( this, & path ) ) {
1123 throw Exceptions::InternalError( "IdentifierTree::showPath failed to find namespace path." );
1125 for (ListType::const_iterator i = path.begin( ); i != path.end( ); ++i ){
1126 os << Interaction::NAMESPACE_SEPARATOR << *i ;
1130 bool
1131 Ast::IdentifierTree::pushPath( const Ast::IdentifierTree * tree, std::list< const char * > * dst ) const
1133 /* Special case for empty path. */
1134 if( tree == this )
1135 return true;
1137 typedef typeof namespaces_ MapType;
1138 for( MapType::const_iterator i = namespaces_.begin( ); i != namespaces_.end( ); ++i ){
1139 if( i->second.kind( ) != NamespaceLink::PRIMARY )
1140 continue;
1141 const Ast::IdentifierTree * node( i->second.node( ) );
1142 if( node == tree ){
1143 if( node->encapParent_ == NULL )
1144 dst->push_front( i->first );
1145 return true;
1147 if( ! node->pushPath( tree, dst ) )
1148 continue;
1149 if( node->encapParent_ == NULL )
1150 dst->push_front( i->first );
1151 return true;
1154 return false;
1158 Ast::StateID Ast::AnalysisEnvironment::nextStateID = 1;
1160 Ast::AnalysisEnvironment::AnalysisEnvironment( PtrOwner_back_Access< std::list< Ast::AnalysisEnvironment * > > & deleter, Ast::AnalysisEnvironment * parent, const Ast::IdentifierTree * bindings, const Ast::IdentifierTree * stateBindings )
1161 : parent_( parent ),
1162 level_( ( parent_ == 0 ) ? 0 : ( parent_->level_ + 1 ) ),
1163 bindings_( bindings ), dynamicKeyBindings_( 0 ),
1164 stateBindings_( stateBindings ), dynamicStateKeyBindings_( 0 ),
1165 functionBoundary_( false )
1167 deleter.push_back( this );
1168 updateBindings( );
1171 Ast::AnalysisEnvironment::~AnalysisEnvironment( )
1174 void
1175 Ast::AnalysisEnvironment::updateBindings( )
1177 states_.reserve( stateBindings_->size( ) );
1178 while( states_.size( ) < stateBindings_->size( ) )
1180 states_.push_back( nextStateID );
1181 ++nextStateID;
1185 Ast::AnalysisEnvironment *
1186 Ast::AnalysisEnvironment::getParent( ) const
1188 if( isBaseEnvironment( ) )
1190 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level analysis environment." );
1192 return parent_;
1195 void
1196 Ast::AnalysisEnvironment::activateFunctionBoundary( )
1198 functionBoundary_ = true;
1201 void
1202 Ast::AnalysisEnvironment::setupDynamicKeyVariables( const Ast::IdentifierTree * dynamicKeyBindings )
1204 dynamicKeyBindings_ = dynamicKeyBindings;
1207 void
1208 Ast::AnalysisEnvironment::setupDynamicStateKeyVariables( const Ast::IdentifierTree * dynamicStateKeyBindings )
1210 dynamicStateKeyBindings_ = dynamicStateKeyBindings;
1213 size_t
1214 Ast::AnalysisEnvironment::findLocalVariablePosition( const Ast::SourceLocation & loc, const Ast::PlacedIdentifier & id ) const
1216 size_t pos = bindings_->lookup( id );
1217 if( pos == Ast::IdentifierTree::NOT_FOUND )
1219 throw Exceptions::InternalError( loc, "Environment::findLocalPosition failed" );
1221 return pos;
1224 void
1225 Kernel::Environment::define( size_t pos, const Kernel::VariableHandle & val )
1227 if( (*values_)[ pos ] != NullPtr< Kernel::Variable >( ) )
1229 throw Exceptions::RedefiningLexical( bindings_->reverseMap( pos ) );
1232 (*values_)[ pos ] = val;
1235 Kernel::Environment::LexicalKey
1236 Ast::AnalysisEnvironment::findLexicalVariableKey( const Ast::SourceLocation & loc, const Ast::Identifier & id ) const
1238 size_t pos = bindings_->lookup( id );
1239 if( pos == Ast::IdentifierTree::NOT_FOUND )
1241 if( isBaseEnvironment( ) )
1243 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknown( loc, id, Ast::Identifier::VARIABLE ) );
1244 return Kernel::Environment::theMissingKey;
1246 return parent_->findLexicalVariableKey( loc, id ).oneAbove( );
1249 return LexicalKey( 0, pos );
1252 Kernel::Environment::LexicalKey
1253 Ast::AnalysisEnvironment::findPrivateAliasVariableKey( const Ast::SourceLocation & loc, const Ast::PlacedIdentifier & id, const char * privateName ) const
1255 size_t pos = bindings_->lookupPrivateAlias( id, privateName );
1256 if( pos == Ast::IdentifierTree::NOT_FOUND ){
1257 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknownPrivateAlias( loc, id, Ast::Identifier::VARIABLE ) );
1258 return Kernel::Environment::theMissingKey;
1261 return LexicalKey( 0, pos );
1264 Ast::PlacedIdentifier
1265 Ast::AnalysisEnvironment::reverseMapLexicalVariable( const LexicalKey & lexKey ) const
1267 const AnalysisEnvironment * env = this;
1268 for( size_t i = lexKey.up_; i > 0; --i )
1270 env = env->getParent( );
1273 return env->bindings_->reverseMap( lexKey.pos_ );
1276 void
1277 Kernel::Environment::lookup( const Kernel::Environment::LexicalKey & lexKey, Kernel::EvalState * evalState ) const
1279 const Environment * env = this;
1280 for( size_t i = lexKey.up_; i > 0; --i )
1282 env = env->getParent( );
1285 env->lookup( lexKey.pos_, evalState );
1288 void
1289 Kernel::Environment::lookup( size_t pos, Kernel::EvalState * evalState ) const
1291 Kernel::VariableHandle res = (*values_)[ pos ];
1292 if( res == NullPtr< Kernel::Variable >( ) )
1294 throw Exceptions::UninitializedAccess( );
1297 Kernel::ContRef cont = evalState->cont_;
1298 cont->takeHandle( res, evalState );
1301 Kernel::VariableHandle
1302 Kernel::Environment::getVarHandle( const Kernel::Environment::LexicalKey & lexKey )
1304 Environment * env = this;
1305 for( size_t i = lexKey.up_; i > 0; --i )
1307 env = env->getParent( );
1310 return env->getVarHandle( lexKey.pos_ );
1313 Kernel::VariableHandle
1314 Kernel::Environment::getVarHandle( size_t pos )
1316 return (*values_)[ pos ];
1319 Kernel::Environment::LexicalKey
1320 Ast::AnalysisEnvironment::findLexicalTypeKey( const Ast::SourceLocation & loc, const Ast::Identifier & id ) const
1322 size_t pos = bindings_->lookup( id );
1323 if( pos == Ast::IdentifierTree::NOT_FOUND )
1325 if( isBaseEnvironment( ) )
1327 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknown( loc, id, Ast::Identifier::TYPE ) );
1328 return Kernel::Environment::theMissingKey;
1330 return parent_->findLexicalTypeKey( loc, id ).oneAbove( );
1333 return LexicalKey( 0, pos );
1337 size_t
1338 Ast::AnalysisEnvironment::findLocalStatePosition( const Ast::SourceLocation & loc, const Ast::PlacedIdentifier & id ) const
1340 size_t pos = stateBindings_->lookup( id );
1341 if( pos == Ast::IdentifierTree::NOT_FOUND )
1343 throw Exceptions::InternalError( loc, "Environment::findLocalStatePosition failed" );
1345 return pos;
1348 Kernel::Environment::LexicalKey
1349 Ast::AnalysisEnvironment::findLexicalStateKey( const Ast::SourceLocation & loc, const Ast::Identifier & id ) const
1351 size_t pos = stateBindings_->lookup( id );
1352 if( pos == Ast::IdentifierTree::NOT_FOUND )
1354 if( isBaseEnvironment( ) )
1356 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknown( loc, id, Ast::Identifier::STATE ) );
1357 return Kernel::Environment::theMissingKey;
1359 if( functionBoundary_ )
1361 // If the state is not found at all, this will throw an error.
1362 parent_->findLexicalStateKey( loc, id ).oneAbove( ); // Ignore the result!
1363 // If no error is thrown, we inform the user that the state is outside a function boundary.
1364 Ast::theAnalysisErrorsList.push_back( new Exceptions::StateBeyondFunctionBoundary( loc, id ) );
1365 return Kernel::Environment::theMissingKey;
1367 return parent_->findLexicalStateKey( loc, id ).oneAbove( );
1370 return LexicalKey( 0, pos );
1373 Ast::StateID
1374 Ast::AnalysisEnvironment::getStateID( const LexicalKey & lexKey ) const
1376 const Ast::AnalysisEnvironment * env = this;
1377 for( size_t i = lexKey.up_; i > 0; --i )
1379 env = env->getParent( );
1382 return env->getStateID( lexKey.pos_ );
1385 Ast::StateID
1386 Ast::AnalysisEnvironment::getStateID( size_t pos ) const
1388 return states_[ pos ];
1391 Ast::StateID
1392 Ast::AnalysisEnvironment::getTheAnyStateID( )
1394 return -1;
1397 void
1398 Kernel::Environment::introduceState( size_t pos, Kernel::State * state )
1400 if( (*states_)[ pos ] != NullPtr< Kernel::State >( ) )
1402 throw Exceptions::InternalError( "Better error message needed when a state is introduced more than once." );
1403 // throw Exceptions::RedefiningLexical( reverseMap( pos ) );
1406 (*states_)[ pos ] = state;
1409 void
1410 Kernel::Environment::freeze( size_t pos, Kernel::EvalState * evalState, const Ast::SourceLocation & loc )
1412 if( (*states_)[ pos ] == NullPtr< Kernel::State >( ) )
1414 // This is a static inconsistency, so it should be detected before we reach here...
1415 throw Exceptions::FreezingUndefined( loc, stateBindings_->reverseMap( pos ) );
1418 Kernel::StateHandle & state = (*states_)[ pos ];
1420 state->freeze( evalState, loc );
1423 void
1424 Kernel::Environment::peek( const LexicalKey & lexKey, Kernel::EvalState * evalState, const Ast::SourceLocation & loc )
1426 getStateHandle( lexKey )->peek( evalState, loc );
1429 void
1430 Kernel::Environment::tackOn( const LexicalKey & lexKey, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
1432 getStateHandle( lexKey )->tackOn( evalState, piece, callLoc );
1435 Kernel::StateHandle
1436 Kernel::Environment::getStateHandle( const LexicalKey & lexKey )
1438 Environment * env = this;
1439 for( size_t i = lexKey.up_; i > 0; --i )
1441 env = env->getParent( );
1444 return env->getStateHandle( lexKey.pos_ );
1447 Kernel::StateHandle
1448 Kernel::Environment::getStateHandle( size_t pos )
1450 Kernel::StateHandle res = (*states_)[ pos ];
1451 if( res == NullPtr< Kernel::State >( ) )
1453 throw Exceptions::UninitializedAccess( );
1455 return res;
1460 size_t
1461 Ast::AnalysisEnvironment::findLocalDynamicPosition( const Ast::SourceLocation & loc, const Ast::PlacedIdentifier & id ) const
1463 if( dynamicKeyBindings_ == 0 )
1465 throw Exceptions::InternalError( "Environment::findLocalDynamicPosition called with dynamicKeyBindings_ == 0." );
1467 size_t pos = dynamicKeyBindings_->lookup( id );
1468 if( pos == Ast::IdentifierTree::NOT_FOUND )
1470 throw Exceptions::InternalError( loc, "Environment::findLocalDynamicPosition failed" );
1472 return pos;
1475 void
1476 Kernel::Environment::defineDynamic( const Ast::PlacedIdentifier * debugId, size_t pos, const RefCountPtr< const Lang::Function > & filter, const Kernel::VariableHandle & defaultVal )
1478 if( dynamicKeyValues_ == 0 )
1480 throw Exceptions::InternalError( "Environment::defineDynamic called with dynamicKeyValues_ == 0." );
1482 if( pos > dynamicKeyValues_->size( ) )
1484 throw Exceptions::InternalError( "Environment::defineDynamic called with pos out of range." );
1486 if( (*dynamicKeyValues_)[ pos ] != 0 )
1488 throw Exceptions::RedefiningDynamic( dynamicKeyBindings_->reverseMap( pos ) );
1491 (*dynamicKeyValues_)[ pos ] = new Kernel::UserDynamicVariableProperties( debugId,
1492 Kernel::DynamicEnvironment::getFreshKey( ),
1493 filter,
1494 defaultVal );
1497 Kernel::Environment::LexicalKey
1498 Ast::AnalysisEnvironment::findLexicalDynamicKey( const Ast::SourceLocation & loc, const Ast::Identifier & id ) const
1500 if( dynamicKeyBindings_ == 0 )
1502 if( isBaseEnvironment( ) )
1504 goto error;
1506 return parent_->findLexicalDynamicKey( loc, id ).oneAbove( );
1509 size_t pos = dynamicKeyBindings_->lookup( id );
1510 if( pos == Ast::IdentifierTree::NOT_FOUND )
1512 if( isBaseEnvironment( ) )
1514 goto error;
1516 return parent_->findLexicalDynamicKey( loc, id ).oneAbove( );
1519 return LexicalKey( 0, pos );
1522 error:
1523 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknown( loc, id, Ast::Identifier::DYNAMIC_VARIABLE ) );
1524 return Kernel::Environment::theMissingKey;
1528 const Kernel::DynamicVariableProperties &
1529 Kernel::Environment::lookupDynamicVariable( const LexicalKey & lexKey ) const
1531 const Environment * env = this;
1532 for( size_t i = lexKey.up_; i > 0; --i )
1534 env = env->getParent( );
1537 return env->lookupDynamicVariable( lexKey.pos_ );
1540 const Kernel::DynamicVariableProperties &
1541 Kernel::Environment::lookupDynamicVariable( size_t pos ) const
1543 const DynamicVariableProperties * res = (*dynamicKeyValues_)[ pos ];
1544 if( res == 0 )
1546 throw Exceptions::UninitializedAccess( );
1548 return *res;
1551 size_t
1552 Ast::AnalysisEnvironment::findLocalDynamicStatePosition( const Ast::SourceLocation & loc, const Ast::PlacedIdentifier & id ) const
1554 if( dynamicStateKeyBindings_ == 0 )
1556 throw Exceptions::InternalError( "Environment::findLocalDynamicStatePosition called with dynamicStateKeyBindings_ == 0." );
1558 size_t pos = dynamicStateKeyBindings_->lookup( id );
1559 if( pos == Ast::IdentifierTree::NOT_FOUND )
1561 throw Exceptions::InternalError( loc, "Environment::findLocalDynamicStatePosition failed" );
1563 return pos;
1566 void
1567 Kernel::Environment::defineDynamicState( const Ast::PlacedIdentifier * debugId, size_t pos, Kernel::EvalState * evalState, Ast::StateReference * defaultState )
1569 if( dynamicStateKeyValues_ == 0 )
1571 throw Exceptions::InternalError( "Environment::defineDynamicState called with dynamicStateKeyValues_ == 0." );
1573 if( pos > dynamicStateKeyValues_->size( ) )
1575 throw Exceptions::InternalError( "Environment::defineDynamicState called with pos out of range." );
1577 if( (*dynamicStateKeyValues_)[ pos ] != 0 )
1579 throw Exceptions::RedefiningDynamic( dynamicStateKeyBindings_->reverseMap( pos ) );
1582 (*dynamicStateKeyValues_)[ pos ] = new Kernel::UserDynamicStateProperties( debugId,
1583 // Kernel::DynamicEnvironment::getFreshKey( ),
1584 evalState->env_,
1585 evalState->dyn_,
1586 defaultState );
1590 Kernel::Environment::LexicalKey
1591 Ast::AnalysisEnvironment::findLexicalDynamicStateKey( const Ast::SourceLocation & loc, const Ast::Identifier & id ) const
1593 if( dynamicStateKeyBindings_ == 0 )
1595 return parent_->findLexicalDynamicStateKey( loc, id ).oneAbove( );
1598 size_t pos = dynamicStateKeyBindings_->lookup( id );
1599 if( pos == Ast::IdentifierTree::NOT_FOUND )
1601 if( isBaseEnvironment( ) )
1603 Ast::theAnalysisErrorsList.push_back( new Exceptions::LookupUnknown( loc, id, Ast::Identifier::DYNAMIC_STATE ) );
1604 return Kernel::Environment::theMissingKey;
1606 return parent_->findLexicalDynamicStateKey( loc, id ).oneAbove( );
1609 return LexicalKey( 0, pos );
1612 const Kernel::DynamicStateProperties &
1613 Kernel::Environment::lookupDynamicState( const LexicalKey & lexKey ) const
1615 const Environment * env = this;
1616 for( size_t i = lexKey.up_; i > 0; --i )
1618 env = env->getParent( );
1621 return env->lookupDynamicState( lexKey.pos_ );
1624 const Kernel::DynamicStateProperties &
1625 Kernel::Environment::lookupDynamicState( size_t pos ) const
1627 const DynamicStateProperties * res = (*dynamicStateKeyValues_)[ pos ];
1628 if( res == 0 )
1630 throw Exceptions::UninitializedAccess( );
1632 return *res;
1636 size_t
1637 Kernel::Environment::size( ) const
1639 return bindings_->size( );
1643 void
1644 Kernel::Environment::print( std::ostream & os ) const
1646 std::set< Ast::PlacedIdentifier > shadowed;
1647 std::set< Ast::PlacedIdentifier > shadowedStates;
1648 recursivePrint( os, & shadowed, & shadowedStates );
1651 size_t
1652 Kernel::Environment::recursivePrint( std::ostream & os, std::set< Ast::PlacedIdentifier > * shadowed, std::set< Ast::PlacedIdentifier > * shadowedStates ) const
1654 typedef std::map< Ast::PlacedIdentifier, size_t > IdMap;
1656 std::set< Ast::PlacedIdentifier > shadowedBefore( *shadowed );
1657 std::set< Ast::PlacedIdentifier > shadowedStatesBefore( *shadowedStates );
1659 size_t depth = 0;
1660 if( ! isBaseEnvironment( ) )
1663 IdMap tmp;
1664 bindings_->dumpMap( & tmp );
1665 for( IdMap::const_iterator i = tmp.begin( ); i != tmp.end( ); ++i ){
1666 shadowed->insert( shadowed->begin( ), i->first );
1670 IdMap tmp;
1671 stateBindings_->dumpMap( & tmp );
1672 for( IdMap::const_iterator i = tmp.begin( ); i != tmp.end( ); ++i ){
1673 shadowedStates->insert( shadowedStates->begin( ), i->first );
1676 depth = parent_->recursivePrint( os, shadowed, shadowedStates ) + 1;
1679 std::string indentation = std::string( depth, ' ' );
1681 size_t width = 1;
1682 for( size_t tmp = bindings_->size( ); tmp >= 10; tmp /= 10, ++width )
1686 size_t tmp = ( 29 - 4 ) - strlen( debugName_ );
1687 if( tmp < 2 || tmp > 29 ) /* the latter case corresponds to an underflow in the subtraction */
1689 tmp = 2;
1691 os << indentation << std::string( tmp / 2, '-' ) << "( " << debugName_ << " )" << std::string( tmp - tmp / 2, '-' ) << std::endl ;
1693 if( ! isBaseEnvironment( ) )
1696 IdMap tmp;
1697 bindings_->dumpMap( & tmp );
1698 for( IdMap::const_iterator i = tmp.begin( ); i != tmp.end( ); ++i ){
1699 os << indentation << std::setw(width) << i->second ;
1700 if( shadowedBefore.find( i->first ) != shadowedBefore.end( ) )
1702 os << "^" ;
1704 else
1706 os << " " ;
1708 os << " " ;
1709 i->first.show( os, Ast::Identifier::VARIABLE );
1710 os << " : " ;
1711 if( (*values_)[ i->second ] == NullPtr< Kernel::Variable >( ) )
1713 os << "< Uninitialized >" ;
1715 else if( (*values_)[ i->second ]->isThunk( ) )
1717 os << "< thunk >" ;
1719 else if( dynamic_cast< const Lang::Instance * >( (*values_)[ i->second ]->getUntyped( ).getPtr( ) ) == 0 )
1721 (*values_)[ i->second ]->getUntyped( )->show( os );
1723 else
1725 os << "..." ;
1727 os << std::endl ;
1731 IdMap tmp;
1732 stateBindings_->dumpMap( & tmp );
1733 for( IdMap::const_iterator i = tmp.begin( ); i != tmp.end( ); ++i ){
1734 os << indentation << std::setw(width) << i->second ;
1735 if( shadowedStatesBefore.find( i->first ) != shadowedStatesBefore.end( ) )
1737 os << "^" ;
1739 else
1741 os << " " ;
1743 os << " " ;
1744 i->first.show( os, Ast::Identifier::STATE );
1745 os << " :: " ;
1746 if( (*states_)[ i->second ] == NullPtr< Kernel::State >( ) )
1748 os << "< Uninitialized >" ;
1750 else
1752 os << (*states_)[ i->second ]->getTypeName( ) ;
1754 os << std::endl ;
1758 else
1760 os << indentation << "<< global env >>" << std::endl ;
1763 os << indentation << "-- -- -- -- -- -- -- -- -- --" << std::endl ;
1765 return depth;