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
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
22 #include "environment.h"
23 #include "shapesexceptions.h"
24 #include "shapescore.h"
27 #include "shapesvalue.h"
28 #include "classtypes.h"
30 #include "continuations.h"
31 #include "statetypes.h"
32 #include "multipage.h"
33 #include "errorhandlers.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 >" ) );
49 Binary( const T
& _val
) : val( _val
) { }
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 )
72 Kernel::Thunk::Thunk( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
, Ast::Expression
* expr
)
73 : env_( env
), dyn_( dyn
), expr_( expr
), forced_( false )
77 Kernel::Thunk::force( Kernel::EvalState
* evalState
, bool onlyOnce
) const
83 throw Exceptions::InternalError( "It's unwise to force a thunk twice! It should be deleted right after the first force." );
88 evalState
->expr_
= expr_
;
89 evalState
->env_
= env_
;
90 evalState
->dyn_
= dyn_
;
92 /* The continuation is not se by the thunk! */
96 Kernel::Thunk::deepCopy( )
98 return new Thunk( env_
, dyn_
, expr_
);
103 Kernel::Thunk::gcMark( Kernel::GCMarkedSet
& marked
)
107 env_
->gcMark( marked
);
108 dyn_
->gcMark( marked
);
113 Kernel::Thunk::getExpr( )
119 Kernel::Thunk::printEnv( std::ostream
& os
) const
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( )
141 Kernel::State::State( )
145 Kernel::State::~State( )
149 Kernel::State::tackOn( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
, const Ast::SourceLocation
& callLoc
)
153 throw Exceptions::DeadStateAccess( );
155 this->tackOnImpl( evalState
, piece
, callLoc
);
159 Kernel::State::peek( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
163 throw Exceptions::DeadStateAccess( );
165 this->peekImpl( evalState
, callLoc
);
169 Kernel::State::freeze( Kernel::EvalState
* evalState
, const Ast::SourceLocation
& callLoc
)
173 throw Exceptions::DeadStateAccess( );
175 /* It would make sense to have an intermediate state here.
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( );
198 Kernel::State::isAlive( ) const
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
);
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." );
242 Kernel::Variable::isThunk( ) const
244 return ( state_
& Kernel::Variable::FORCING
) != 0;
248 Kernel::Variable::isThunk( Ast::Expression
* expr
) const
250 return state_
== Kernel::Variable::THUNK
&& thunk_
->getExpr( ) == expr
;
254 Kernel::Variable::copyThunk( ) const
258 throw Exceptions::InternalError( "Variable::copyThunk: There was no thunk to copy." );
260 return thunk_
->deepCopy( );
264 Kernel::Variable::gcMark( Kernel::GCMarkedSet
& marked
)
268 thunk_
->gcMark( marked
);
271 if( val_
!= NullPtr
< const Lang::Value
>( ) )
273 const_cast< Lang::Value
* >( val_
.getPtr( ) )->gcMark( marked
);
278 Kernel::Variable::setValue( const RefCountPtr
< const Lang::Value
> & val
) const
280 if( state_
!= Kernel::Variable::FORCING
)
281 throw Exceptions::BadSetValueState( );
283 state_
= Kernel::Variable::COLD
;
287 Kernel::DynamicVariableProperties::~DynamicVariableProperties( )
289 /* We do not own id_.
293 Kernel::DynamicStateProperties::~DynamicStateProperties( )
295 /* We do not own id_.
301 Kernel::Environment::initDefineHandle( const Ast::PlacedIdentifier
& id
, const Kernel::VariableHandle
& val
)
303 if( Interaction::logGlobals
)
305 std::ostream
& os
= Kernel::theDebugLog
.os( );
306 os
<< "--log-globals> variable: " ;
307 id
.show( os
, Ast::Identifier::VARIABLE
);
311 if( ! bindings_
->insert( id
, THE_INITIALIZATION_LOCATION
) )
313 /* An error message has already been generated. */
316 values_
->push_back( val
);
318 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
319 if( values_
->size( ) != bindings_
->size( ) ){
320 throw Exceptions::InternalError( "Kernel::Environment::initDefineHandle: Inconsistent number of values." );
325 Kernel::Environment::initDefineCoreFunction( Lang::CoreFunction
* fun
)
327 initDefineHandle( fun
->id( ), Kernel::VariableHandle( new Kernel::Variable( RefCountPtr
< const Lang::Value
>( fun
) ) ) );
331 Kernel::Environment::initDefineCoreFunction( RefCountPtr
< const Lang::CoreFunction
> fun
)
333 initDefineHandle( fun
->id( ), Kernel::VariableHandle( new Kernel::Variable( fun
) ) );
337 Kernel::Environment::initDefine( const Ast::PlacedIdentifier
& id
, const RefCountPtr
< const Lang::Value
> & val
)
339 initDefineHandle( id
, Kernel::VariableHandle( new Kernel::Variable( val
) ) );
343 Kernel::Environment::initDefine( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
, const RefCountPtr
< const Lang::Value
> & val
)
345 Ast::PlacedIdentifier
id( ns
, name
);
346 initDefineHandle( id
, Kernel::VariableHandle( new Kernel::Variable( val
) ) );
350 Kernel::Environment::initDefine( const Ast::PlacedIdentifier
& id
, Kernel::StateHandle state
)
352 if( Interaction::logGlobals
)
354 std::ostream
& os
= Kernel::theDebugLog
.os( );
355 os
<< "--log-globals> state: " ;
356 id
.show( os
, Ast::Identifier::STATE
);
360 if( ! stateBindings_
->insert( id
, THE_INITIALIZATION_LOCATION
) )
362 /* An error message has already been generated. */
365 states_
->push_back( state
);
367 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
368 if( states_
->size( ) != stateBindings_
->size( ) ){
369 throw Exceptions::InternalError( "Kernel::Environment::initDefine: Inconsistent number of states." );
374 Kernel::Environment::initDefine( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
, Kernel::StateHandle state
)
376 Ast::PlacedIdentifier
id( ns
, name
);
377 initDefine( id
, state
);
381 Kernel::Environment::initDefineClass( const RefCountPtr
< const Lang::Class
> & cls
)
383 RefCountPtr
< const char > idRef
= cls
->getPrettyName( );
384 const char * simpleId
= strdup( idRef
.getPtr( ) );
385 charPtrDeletionList_
.push_back( simpleId
);
386 initDefineHandle( Ast::PlacedIdentifier( Lang::THE_NAMESPACE_Shapes_Data_Type
, simpleId
), Kernel::VariableHandle( new Kernel::Variable( cls
) ) );
390 Kernel::Environment::initDefineDynamic( DynamicVariableProperties
* dynProps
)
392 const Ast::PlacedIdentifier
& id( dynProps
->id( ) );
394 if( Interaction::logGlobals
)
396 Kernel::theDebugLog
.os( ) << "--log-globals> dynamic: " ;
397 id
.show( Kernel::theDebugLog
.os( ), Ast::Identifier::DYNAMIC_VARIABLE
);
398 Kernel::theDebugLog
.os( ) << std::endl
;
401 if( ! dynamicKeyBindings_
->insert( id
, THE_INITIALIZATION_LOCATION
) )
403 /* An error message has already been generated. */
406 dynamicKeyValues_
->push_back( dynProps
);
408 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
409 if( dynamicKeyValues_
->size( ) != dynamicKeyBindings_
->size( ) ){
410 throw Exceptions::InternalError( "Kernel::Environment::initDefineDynamic: Inconsistent number of dynamic keys (1 argument)." );
415 Kernel::Environment::initDefineDynamic( const Ast::PlacedIdentifier
& id
, const RefCountPtr
< const Lang::Function
> & filter
, const Kernel::VariableHandle
& defaultVal
)
417 initDefineDynamic( newPlacedIdentifier( id
), filter
, defaultVal
);
421 Kernel::Environment::initDefineDynamic( const Ast::PlacedIdentifier
* id
, const RefCountPtr
< const Lang::Function
> & filter
, const Kernel::VariableHandle
& defaultVal
)
423 if( Interaction::logGlobals
)
425 Kernel::theDebugLog
.os( ) << "--log-globals> dynamic: " ;
426 id
->show( Kernel::theDebugLog
.os( ), Ast::Identifier::DYNAMIC_VARIABLE
);
427 Kernel::theDebugLog
.os( ) << std::endl
;
430 if( ! dynamicKeyBindings_
->insert( *id
, THE_INITIALIZATION_LOCATION
) )
432 /* An error message has already been generated. */
435 Kernel::DynamicEnvironmentKeyType key
= dynamicKeyValues_
->size( );
436 dynamicKeyValues_
->push_back( new Kernel::UserDynamicVariableProperties( id
, key
, filter
, defaultVal
) );
438 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
439 if( dynamicKeyValues_
->size( ) != dynamicKeyBindings_
->size( ) ){
440 throw Exceptions::InternalError( "Kernel::Environment::initDefineDynamic: Inconsistent number of dynamic keys (3 arguments)." );
445 Kernel::Environment::initDefineDynamicHandler( const Ast::PlacedIdentifier
& id
, const char * msg
)
447 initDefineDynamic( id
.clone( ),
449 Helpers::newValHandle( new Lang::ExceptionWrapper
< Exceptions::HandlerError
>( id
, msg
) ) );
452 PtrOwner_back_Access
< std::list
< const Ast::PlacedIdentifier
* > > Kernel::Environment::coreIdentifiers
;
454 const Ast::PlacedIdentifier
*
455 Kernel::Environment::newPlacedIdentifier( const RefCountPtr
< const Ast::NamespacePath
> & path
, const char * simpleId
)
457 const Ast::PlacedIdentifier
* id
= new Ast::PlacedIdentifier( path
, simpleId
);
458 coreIdentifiers
.push_back( id
);
462 const Ast::PlacedIdentifier
*
463 Kernel::Environment::newPlacedIdentifier( const Ast::PlacedIdentifier
& id
)
465 return newPlacedIdentifier( id
.absolutePathRef( ), id
.simpleId( ) );
468 Kernel::Environment::Environment( std::list
< Kernel::Environment
* > & garbageArea
, const char * debugName
)
470 bindings_( new Ast::IdentifierTree( NULL
, false ) ),
471 values_( new std::vector
< Kernel::VariableHandle
>( ) ),
472 dynamicKeyBindings_( new Ast::IdentifierTree( NULL
, false ) ),
473 dynamicKeyValues_( new std::vector
< DynamicVariableProperties
* > ),
474 stateBindings_( new Ast::IdentifierTree( NULL
, false ) ),
475 states_( new std::vector
< Kernel::StateHandle
>( ) ),
476 dynamicStateKeyBindings_( new Ast::IdentifierTree( NULL
, false ) ),
477 dynamicStateKeyValues_( new std::vector
< DynamicStateProperties
* > ),
478 debugName_( debugName
)
480 garbageArea
.push_back( this );
485 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
)
487 bindings_( bindings
), values_( values
), dynamicKeyBindings_( NULL
),
488 stateBindings_( stateBindings
), states_( states
), dynamicStateKeyBindings_( NULL
),
489 debugName_( debugName
)
490 //, unitMap_( NullPtr< Kernel::Environment::UnitMapType >( ) )
492 garbageArea
.push_back( this );
493 // if( parent_ != NULL )
495 // unitMap_ = parent->unitMap_;
501 Kernel::Environment::~Environment( )
504 if( dynamicKeyBindings_
!= NULL
)
506 if( parent_
== NULL
)
508 /* The condition means that this is the global evironment, which created its own map.
510 delete dynamicKeyBindings_
;
512 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings_ != NULL
514 for( std::vector
< DynamicVariableProperties
* >::iterator i
= dynamicKeyValues_
->begin( ); i
!= dynamicKeyValues_
->end( ); ++i
)
521 delete dynamicKeyValues_
;
523 if( stateBindings_
!= NULL
)
525 if( parent_
== NULL
)
527 /* The condition means that this is the global evironment, which created its own map.
529 delete stateBindings_
;
531 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings_ != NULL
533 for( std::vector
< StateHandle
>::iterator i
= states_
->begin( ); i
!= states_
->end( ); ++i
)
541 if( dynamicStateKeyBindings_
!= NULL
)
543 if( parent_
== NULL
)
545 /* The condition means that this is the global evironment, which created its own map.
547 delete dynamicStateKeyBindings_
;
549 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings_ != NULL
551 for( std::vector
< DynamicStateProperties
* >::iterator i
= dynamicStateKeyValues_
->begin( ); i
!= dynamicStateKeyValues_
->end( ); ++i
)
558 delete dynamicStateKeyValues_
;
564 Kernel::Environment::setParent( Kernel::Environment
* parent
)
567 // unitMap_ = parent.unitMap_;
570 Kernel::Environment
*
571 Kernel::Environment::getParent( )
573 if( isBaseEnvironment( ) )
575 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level environment." );
580 const Kernel::Environment
*
581 Kernel::Environment::getParent( ) const
583 if( isBaseEnvironment( ) )
585 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level environment." );
591 Kernel::Environment::setupDynamicKeyVariables( Ast::IdentifierTree
* dynamicKeyBindings
)
593 if( dynamicKeyBindings_
== NULL
)
595 dynamicKeyBindings_
= dynamicKeyBindings
;
596 dynamicKeyValues_
= new std::vector
< DynamicVariableProperties
* >;
601 if( dynamicKeyBindings_
!= dynamicKeyBindings
)
603 throw Exceptions::InternalError( "Kernel::Environment::setupDynamicKeyVariables: dynamicKeyBindings_ != dynamicKeyBindings" );
607 size_t theSize
= dynamicKeyBindings_
->size( );
608 dynamicKeyValues_
->reserve( theSize
);
609 while( dynamicKeyValues_
->size( ) < theSize
)
611 dynamicKeyValues_
->push_back( 0 );
616 Kernel::Environment::setupDynamicStateKeyVariables( Ast::IdentifierTree
* dynamicStateKeyBindings
)
618 if( dynamicStateKeyBindings_
== NULL
)
620 dynamicStateKeyBindings_
= dynamicStateKeyBindings
;
621 dynamicStateKeyValues_
= new std::vector
< DynamicStateProperties
* >;
626 if( dynamicStateKeyBindings_
!= dynamicStateKeyBindings
)
628 throw Exceptions::InternalError( "Kernel::Environment::setupDynamicStateKeyVariables: dynamicStateKeyBindings_ != dynamicStateKeyBindings" );
632 size_t theSize
= dynamicStateKeyBindings_
->size( );
633 dynamicStateKeyValues_
->reserve( theSize
);
634 while( dynamicStateKeyValues_
->size( ) < theSize
)
636 dynamicStateKeyValues_
->push_back( 0 );
641 Kernel::Environment::extendVectors( )
643 values_
->reserve( bindings_
->size( ) );
644 while( values_
->size( ) < bindings_
->size( ) )
646 values_
->push_back( NullPtr
< Kernel::Variable
>( ) );
649 states_
->reserve( stateBindings_
->size( ) );
650 while( states_
->size( ) < stateBindings_
->size( ) )
652 states_
->push_back( NullPtr
< Kernel::State
>( ) );
658 Kernel::Environment::clear( )
660 /* Strange that this is empty...
661 * The idea, though, is that the reference counting of this->values shall take care of deletion.
665 Ast::AnalysisEnvironment
*
666 Kernel::Environment::newAnalysisEnvironment( Ast::AnalysisEnvironment
* parent
) const
668 Ast::AnalysisEnvironment
* res
= new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList
, parent
, bindings_
, stateBindings_
);
669 if( dynamicKeyBindings_
!= NULL
)
671 res
->setupDynamicKeyVariables( dynamicKeyBindings_
);
673 if( dynamicStateKeyBindings_
!= NULL
)
675 res
->setupDynamicStateKeyVariables( dynamicStateKeyBindings_
);
682 Kernel::Environment::gcMark( Kernel::GCMarkedSet
& marked
)
689 marked
.insert( marked
.begin( ), this );
695 Kernel::Environment::collect( std::list
< Kernel::Environment
* > & garbageArea
)
697 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); ++i
)
699 (*i
)->clear_gcMarked( );
702 Kernel::GCMarkedSet marked
;
703 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); ++i
)
705 (*i
)->gcMark( marked
);
708 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); )
710 if( (*i
)->gcMarked( ) )
715 std::list
< Kernel::Environment
* >::iterator tmp
= i
;
718 garbageArea
.erase( tmp
);
723 const size_t Ast::IdentifierTree::NOT_FOUND
= std::numeric_limits
< size_t >::max( );
725 Ast::IdentifierTree::IdentifierTree( IdentifierTree
* parent
, bool encapsulation
)
726 : size_( 0 ), root_( ( parent
== NULL
) ? this : ( parent
->root( ) ) ), encap_( ( encapsulation
|| parent
== NULL
) ? this : ( parent
->encap( ) ) ), encapParent_( encapsulation
? parent
: NULL
)
729 Ast::IdentifierTree::~IdentifierTree( )
731 typedef typeof namespaces_ MapType
;
732 for( MapType::iterator i
= namespaces_
.begin( ); i
!= namespaces_
.end( ); ++i
)
734 if( i
->second
.kind( ) != NamespaceLink::PRIMARY
)
736 delete i
->second
.node( );
740 Ast::IdentifierTree
*
741 Ast::IdentifierTree::base( Ast::NamespaceReference::Base b
)
744 case Ast::NamespaceReference::ABSOLUTE
:
746 case Ast::NamespaceReference::LOCAL
:
748 case Ast::NamespaceReference::RELATIVE
:
753 const Ast::IdentifierTree
*
754 Ast::IdentifierTree::base( Ast::NamespaceReference::Base b
) const
757 case Ast::NamespaceReference::ABSOLUTE
:
759 case Ast::NamespaceReference::LOCAL
:
761 case Ast::NamespaceReference::RELATIVE
:
766 Ast::IdentifierTree
*
767 Ast::IdentifierTree::newChild( const char * key
, const Ast::SourceLocation
& loc
)
769 IdentifierTree
* tree
= new Ast::IdentifierTree( this, Ast::SearchContext::isEncapsulationName( key
) );
770 typedef typeof namespaces_ MapType
;
771 namespaces_
.insert( MapType::value_type( key
, NamespaceLink( NamespaceLink::PRIMARY
, tree
) ) );
772 if( encapParent_
!= NULL
){
773 encapParent_
->insertEncapsulationLink( key
, tree
, loc
);
779 Ast::IdentifierTree::insert( const Ast::PlacedIdentifier
& id
, const Ast::SourceLocation
& loc
)
781 return insert( id
.absolutePath( ).begin( ), id
.absolutePath( ).end( ), id
.simpleId( ), size_
, loc
);
785 Ast::IdentifierTree::insertAlias( const Ast::PlacedIdentifier
& id
, const Ast::NamespaceReference
& expansion
, const Ast::SourceLocation
& loc
)
787 return insertAlias( id
.absolutePath( ).begin( ), id
.absolutePath( ).end( ), id
.simpleId( ), expansion
, loc
);
791 Ast::IdentifierTree::insert( Ast::NamespacePath::const_iterator begin
, const Ast::NamespacePath::const_iterator
& end
, const char * simpleId
, size_t pos
, const Ast::SourceLocation
& loc
)
795 typedef typeof simpleIdentifiers_ MapType
;
796 if( simpleIdentifiers_
.find( simpleId
) != simpleIdentifiers_
.end( ) )
798 simpleIdentifiers_
.insert( MapType::value_type( simpleId
, pos
) );
800 if( encapParent_
!= NULL
){
801 encapParent_
->insertEncapsulationLink( simpleId
, pos
, loc
);
807 typedef typeof namespaces_ MapType
;
808 MapType::iterator j
= namespaces_
.find( *begin
);
809 if( j
!= namespaces_
.end( ) ){
811 bool result
= j
->second
.node( )->insert( ++begin
, end
, simpleId
, pos
, loc
);
818 IdentifierTree
* tree
= newChild( *begin
, loc
);
819 bool result
= tree
->insert( ++begin
, end
, simpleId
, pos
, loc
);
830 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
)
835 IdentifierTree
* tree
= resolveAlias( expansion
, & found
, loc
);
837 typedef typeof namespaces_ MapType
;
838 MapType::iterator j
= namespaces_
.find( simpleId
);
839 if( j
!= namespaces_
.end( ) ){
840 Ast::theAnalysisErrorsList
.push_back( new Exceptions::NamespaceAliasCollision( loc
, this, simpleId
) );
842 namespaces_
.insert( MapType::value_type( simpleId
, NamespaceLink( NamespaceLink::RESTRICTED
, tree
) ) );
849 typedef typeof namespaces_ MapType
;
850 MapType::iterator j
= namespaces_
.find( *begin
);
851 if( j
!= namespaces_
.end( ) ){
853 return j
->second
.node( )->insertAlias( ++begin
, end
, simpleId
, expansion
, loc
);
857 IdentifierTree
* tree
= newChild( *begin
, loc
);
858 return tree
->insertAlias( ++begin
, end
, simpleId
, expansion
, loc
);
865 Ast::IdentifierTree
*
866 Ast::IdentifierTree::resolveAlias( const Ast::NamespaceReference
& expansion
, bool * found
, const Ast::SourceLocation
& loc
)
869 return base( expansion
.base( ) )->resolveAlias( expansion
.path( ).begin( ), expansion
.path( ).end( ), found
, loc
);
872 Ast::IdentifierTree
*
873 Ast::IdentifierTree::resolveAlias( const Ast::NamespacePath::const_iterator
& begin
, const Ast::NamespacePath::const_iterator
& end
, bool * found
, const Ast::SourceLocation
& loc
)
881 Ast::NamespacePath::const_iterator
next(begin
);
883 typedef typeof namespaces_ MapType
;
884 MapType::const_iterator j
= namespaces_
.find( *begin
);
885 if( j
== namespaces_
.end( ) ){
887 IdentifierTree
* tree
= newChild( *begin
, loc
);
888 return tree
->resolveAlias( next
, end
, found
, loc
);
891 return j
->second
.node( )->resolveAlias( next
, end
, found
, loc
);
897 Ast::IdentifierTree::insertEncapsulationLink( const char * key
, size_t pos
, const Ast::SourceLocation
& loc
)
899 typedef typeof simpleIdentifiers_ MapType
;
900 if( simpleIdentifiers_
.find( key
) != simpleIdentifiers_
.end( ) ){
901 Ast::theAnalysisErrorsList
.push_back( new Exceptions::EncapsulationIntroducingExisting( loc
, key
) );
904 simpleIdentifiers_
.insert( MapType::value_type( key
, pos
) );
908 Ast::IdentifierTree::insertEncapsulationLink( const char * key
, Ast::IdentifierTree
* tree
, const Ast::SourceLocation
& loc
)
910 typedef typeof namespaces_ MapType
;
911 if( namespaces_
.find( key
) != namespaces_
.end( ) ){
912 Ast::theAnalysisErrorsList
.push_back( new Exceptions::EncapsulationNamespaceAliasCollision( loc
, key
) );
915 namespaces_
.insert( MapType::value_type( key
, NamespaceLink( NamespaceLink::SECONDARY
, tree
) ) );
919 Ast::IdentifierTree::lookup( const Ast::Identifier
& id
) const
921 const Ast::SearchContext
& context
= id
.searchContext( );
923 switch( id
.base( ) ){
924 case Ast::NamespaceReference::ABSOLUTE
:
925 return lookupSuffix( false, id
.path( ).begin( ), id
.path( ).end( ), id
.simpleId( ) );
927 case Ast::NamespaceReference::LOCAL
:
928 return lookupInside( context
.encapsulationPath( )->begin( ), context
.encapsulationPath( )->end( ), id
);
930 case Ast::NamespaceReference::RELATIVE
:
932 size_t pos
= lookupPrefix( context
.lexicalPath( )->begin( ), context
.lexicalPath( )->end( ), context
.privateName( ).getPtr( ), id
);
933 if( pos
!= NOT_FOUND
)
936 for( RefCountPtr
< const Ast::LookinPathStack
> i( context
.lookinStack( ) ); i
!= NullPtr
< const Ast::LookinPathStack
>( ); i
= i
->cdr( ) ){
937 size_t pos
= lookupInside( i
->car( )->begin( ), i
->car( )->end( ), id
);
938 if( pos
!= NOT_FOUND
)
948 Ast::IdentifierTree::lookup( const Ast::PlacedIdentifier
& id
) const
950 return lookupSuffix( false, id
.absolutePath( ).begin( ), id
.absolutePath( ).end( ), id
.simpleId( ) );
954 Ast::IdentifierTree::lookupPrivateAlias( const Ast::PlacedIdentifier
& id
, const char * privateName
) const
956 /* Mimic how a relative identifier would be looked up with lookupPrefix, but only consider the private namespace.
958 if( privateName
== NULL
)
961 const Ast::IdentifierTree
* tree
= this;
962 Ast::NamespacePath::const_iterator i
= id
.absolutePath( ).begin( );
963 Ast::NamespacePath::const_iterator end
= id
.absolutePath( ).end( );
964 for( ; i
!= end
; ++i
){
965 typedef typeof namespaces_ MapType
;
966 MapType::const_iterator j
= tree
->namespaces_
.find( *i
);
967 if( j
== tree
->namespaces_
.end( ) )
969 tree
= j
->second
.node( );
974 typedef typeof namespaces_ MapType
;
975 MapType::const_iterator j
= tree
->namespaces_
.find( privateName
);
976 if( j
== tree
->namespaces_
.end( ) )
979 /* We must pass an empty NamespacePath range, and id.absolutePath( ).begin( ) .. id.absolutePath( ).begin( )
980 * happens to be available.
982 return j
->second
.node( )->lookupSuffix( false, id
.absolutePath( ).begin( ), id
.absolutePath( ).begin( ), id
.simpleId( ) );
986 Ast::IdentifierTree::lookupPrefix( const Ast::NamespacePath::const_iterator
& begin
, const Ast::NamespacePath::const_iterator
& end
, const char * privateName
, const Ast::Identifier
& id
) const
988 std::stack
< const Ast::IdentifierTree
* > path
;
990 const Ast::IdentifierTree
* tree
= this;
992 Ast::NamespacePath::const_iterator i
= begin
;
993 for( ; i
!= end
; ++i
){
994 typedef typeof namespaces_ MapType
;
995 MapType::const_iterator j
= tree
->namespaces_
.find( *i
);
996 if( j
== tree
->namespaces_
.end( ) )
998 tree
= j
->second
.node( );
1002 /* Look in local namespace.
1003 * Only do this for identifiers with empty relative path, and inside
1004 * the current namespace.
1006 if( i
== end
&& id
.path( ).empty( ) && privateName
!= NULL
){
1007 typedef typeof namespaces_ MapType
;
1008 MapType::const_iterator j
= tree
->namespaces_
.find( privateName
);
1009 if( j
!= tree
->namespaces_
.end( ) ){
1011 size_t pos
= j
->second
.node( )->lookupSuffix( false, id
.path( ).begin( ), id
.path( ).end( ), id
.simpleId( ) );
1012 if( pos
!= NOT_FOUND
)
1018 while( ! path
.empty( ) ){
1021 size_t pos
= tree
->lookupSuffix( true, id
.path( ).begin( ), id
.path( ).end( ), id
.simpleId( ) );
1022 if( pos
!= NOT_FOUND
)
1024 if( tree
->encapParent_
!= NULL
)
1030 size_t Ast::IdentifierTree::lookupInside( const Ast::NamespacePath::const_iterator
& begin
, const Ast::NamespacePath::const_iterator
& end
, const Ast::Identifier
& id
) const
1033 return lookupSuffix( false, id
.path( ).begin( ), id
.path( ).end( ), id
.simpleId( ) );
1036 typedef typeof namespaces_ MapType
;
1037 MapType::const_iterator i
= namespaces_
.find( *begin
);
1038 if( i
== namespaces_
.end( ) )
1040 if( i
->second
.kind( ) != NamespaceLink::PRIMARY
)
1043 Ast::NamespacePath::const_iterator next
= begin
;
1045 return i
->second
.node( )->lookupInside( next
, end
, id
);
1049 Ast::IdentifierTree::lookupSuffix( bool followRestricted
, const Ast::NamespacePath::const_iterator
& begin
, const Ast::NamespacePath::const_iterator
& end
, const char * simpleId
) const
1053 typedef typeof simpleIdentifiers_ MapType
;
1054 MapType::const_iterator i
= simpleIdentifiers_
.find( simpleId
);
1055 if( i
== simpleIdentifiers_
.end( ) )
1062 const char * front
= *begin
;
1063 typedef typeof namespaces_ MapType
;
1064 MapType::const_iterator i
= namespaces_
.find( front
);
1065 if( i
== namespaces_
.end( ) )
1067 if( ! followRestricted
&& i
->second
.kind( ) == NamespaceLink::RESTRICTED
)
1070 Ast::NamespacePath::const_iterator
next(begin
);
1072 return i
->second
.node( )->lookupSuffix( false, next
, end
, simpleId
);
1078 Ast::PlacedIdentifier
1079 Ast::IdentifierTree::reverseMap( size_t pos
) const
1081 const char * simpleId
;
1082 std::list
< const char * > * absolutePath
= reverseMapHelper( pos
, & simpleId
);
1083 if( absolutePath
== NULL
)
1084 throw Exceptions::InternalError( "Ast::IdentifierTree::reverseMap failure." );
1085 return Ast::PlacedIdentifier( absolutePath
, simpleId
);
1088 std::list
< const char * > *
1089 Ast::IdentifierTree::reverseMapHelper( size_t pos
, const char ** simpleIdDst
) const
1092 typedef typeof simpleIdentifiers_ MapType
;
1093 for( MapType::const_iterator i
= simpleIdentifiers_
.begin( ); i
!= simpleIdentifiers_
.end( ); ++i
){
1094 if( i
->second
== pos
)
1096 std::list
< const char * > * result( new std::list
< const char * > );
1097 *simpleIdDst
= i
->first
;
1104 typedef typeof namespaces_ MapType
;
1105 for( MapType::const_iterator i
= namespaces_
.begin( ); i
!= namespaces_
.end( ); ++i
){
1106 if( i
->second
.kind( ) != NamespaceLink::PRIMARY
)
1108 std::list
< const char * > * path
= i
->second
.node( )->reverseMapHelper( pos
, simpleIdDst
);
1111 path
->push_front( i
->first
);
1120 Ast::IdentifierTree::dumpMap( std::map
< Ast::PlacedIdentifier
, size_t > * dst
) const
1122 Ast::NamespacePath path
;
1123 dumpMap( dst
, & path
);
1127 Ast::IdentifierTree::dumpMap( std::map
< Ast::PlacedIdentifier
, size_t > * dst
, Ast::NamespacePath
* path
) const
1130 typedef typeof simpleIdentifiers_ MapType
;
1131 typedef typeof *dst DstType
;
1132 for( MapType::const_iterator i
= simpleIdentifiers_
.begin( ); i
!= simpleIdentifiers_
.end( ); ++i
){
1133 dst
->insert( DstType::value_type( Ast::PlacedIdentifier( *path
, i
->first
), i
->second
) );
1138 typedef typeof namespaces_ MapType
;
1139 for( MapType::const_iterator i
= namespaces_
.begin( ); i
!= namespaces_
.end( ); ++i
){
1140 path
->push_back( i
->first
);
1141 i
->second
.node( )->dumpMap( dst
, path
);
1148 Ast::IdentifierTree::showPath( std::ostream
& os
) const
1150 typedef std::list
< const char * > ListType
;
1152 if( ! root_
->pushPath( this, & path
) ) {
1153 throw Exceptions::InternalError( "IdentifierTree::showPath failed to find namespace path." );
1155 for (ListType::const_iterator i
= path
.begin( ); i
!= path
.end( ); ++i
){
1156 os
<< Interaction::NAMESPACE_SEPARATOR
<< *i
;
1161 Ast::IdentifierTree::pushPath( const Ast::IdentifierTree
* tree
, std::list
< const char * > * dst
) const
1163 /* Special case for empty path. */
1167 typedef typeof namespaces_ MapType
;
1168 for( MapType::const_iterator i
= namespaces_
.begin( ); i
!= namespaces_
.end( ); ++i
){
1169 if( i
->second
.kind( ) != NamespaceLink::PRIMARY
)
1171 const Ast::IdentifierTree
* node( i
->second
.node( ) );
1173 if( node
->encapParent_
== NULL
)
1174 dst
->push_front( i
->first
);
1177 if( ! node
->pushPath( tree
, dst
) )
1179 if( node
->encapParent_
== NULL
)
1180 dst
->push_front( i
->first
);
1188 Ast::StateID
Ast::AnalysisEnvironment::nextStateID
= 1;
1190 Ast::AnalysisEnvironment::AnalysisEnvironment( PtrOwner_back_Access
< std::list
< Ast::AnalysisEnvironment
* > > & deleter
, Ast::AnalysisEnvironment
* parent
, const Ast::IdentifierTree
* bindings
, const Ast::IdentifierTree
* stateBindings
)
1191 : parent_( parent
),
1192 level_( ( parent_
== NULL
) ? 0 : ( parent_
->level_
+ 1 ) ),
1193 bindings_( bindings
), dynamicKeyBindings_( NULL
),
1194 stateBindings_( stateBindings
), dynamicStateKeyBindings_( NULL
),
1195 functionBoundary_( false )
1197 deleter
.push_back( this );
1201 Ast::AnalysisEnvironment::~AnalysisEnvironment( )
1205 Ast::AnalysisEnvironment::updateBindings( )
1207 states_
.reserve( stateBindings_
->size( ) );
1208 while( states_
.size( ) < stateBindings_
->size( ) )
1210 states_
.push_back( nextStateID
);
1214 statesFirstUse_
.resize( stateBindings_
->size( ), NULL
);
1217 Ast::AnalysisEnvironment
*
1218 Ast::AnalysisEnvironment::getParent( ) const
1220 if( isBaseEnvironment( ) )
1222 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level analysis environment." );
1228 Ast::AnalysisEnvironment::activateFunctionBoundary( )
1230 functionBoundary_
= true;
1234 Ast::AnalysisEnvironment::setupDynamicKeyVariables( const Ast::IdentifierTree
* dynamicKeyBindings
)
1236 dynamicKeyBindings_
= dynamicKeyBindings
;
1240 Ast::AnalysisEnvironment::setupDynamicStateKeyVariables( const Ast::IdentifierTree
* dynamicStateKeyBindings
)
1242 dynamicStateKeyBindings_
= dynamicStateKeyBindings
;
1246 Ast::AnalysisEnvironment::findLocalVariablePosition( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
) const
1248 size_t pos
= bindings_
->lookup( id
);
1249 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1251 throw Exceptions::InternalError( loc
, "Environment::findLocalPosition failed" );
1257 Kernel::Environment::define( size_t pos
, const Kernel::VariableHandle
& val
)
1259 if( (*values_
)[ pos
] != NullPtr
< Kernel::Variable
>( ) )
1261 throw Exceptions::RedefiningLexical( bindings_
->reverseMap( pos
) );
1264 (*values_
)[ pos
] = val
;
1267 Kernel::Environment::LexicalKey
1268 Ast::AnalysisEnvironment::findLexicalVariableKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1270 size_t pos
= bindings_
->lookup( id
);
1271 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1273 if( isBaseEnvironment( ) )
1275 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::VARIABLE
) );
1276 return Kernel::Environment::theMissingKey
;
1278 return parent_
->findLexicalVariableKey( loc
, id
).oneAbove( );
1281 return LexicalKey( 0, pos
);
1284 Kernel::Environment::LexicalKey
1285 Ast::AnalysisEnvironment::findPrivateAliasVariableKey( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
, const char * privateName
) const
1287 size_t pos
= bindings_
->lookupPrivateAlias( id
, privateName
);
1288 if( pos
== Ast::IdentifierTree::NOT_FOUND
){
1289 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknownPrivateAlias( loc
, id
, Ast::Identifier::VARIABLE
) );
1290 return Kernel::Environment::theMissingKey
;
1293 return LexicalKey( 0, pos
);
1296 Ast::PlacedIdentifier
1297 Ast::AnalysisEnvironment::reverseMapLexicalVariable( const LexicalKey
& lexKey
) const
1299 const AnalysisEnvironment
* env
= this;
1300 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1302 env
= env
->getParent( );
1305 return env
->bindings_
->reverseMap( lexKey
.pos_
);
1309 Kernel::Environment::lookup( const Kernel::Environment::LexicalKey
& lexKey
, Kernel::EvalState
* evalState
) const
1311 const Environment
* env
= this;
1312 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1314 env
= env
->getParent( );
1317 env
->lookup( lexKey
.pos_
, evalState
);
1321 Kernel::Environment::lookup( size_t pos
, Kernel::EvalState
* evalState
) const
1323 Kernel::VariableHandle res
= (*values_
)[ pos
];
1324 if( res
== NullPtr
< Kernel::Variable
>( ) )
1326 throw Exceptions::UninitializedAccess( );
1329 Kernel::ContRef cont
= evalState
->cont_
;
1330 cont
->takeHandle( res
, evalState
);
1333 Kernel::VariableHandle
1334 Kernel::Environment::getVarHandle( const Kernel::Environment::LexicalKey
& lexKey
)
1336 Environment
* env
= this;
1337 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1339 env
= env
->getParent( );
1342 return env
->getVarHandle( lexKey
.pos_
);
1345 Kernel::VariableHandle
1346 Kernel::Environment::getVarHandle( size_t pos
)
1348 return (*values_
)[ pos
];
1351 Kernel::Environment::LexicalKey
1352 Ast::AnalysisEnvironment::findLexicalTypeKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1354 size_t pos
= bindings_
->lookup( id
);
1355 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1357 if( isBaseEnvironment( ) )
1359 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::TYPE
) );
1360 return Kernel::Environment::theMissingKey
;
1362 return parent_
->findLexicalTypeKey( loc
, id
).oneAbove( );
1365 return LexicalKey( 0, pos
);
1370 Ast::AnalysisEnvironment::findLocalStatePosition( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
) const
1372 size_t pos
= stateBindings_
->lookup( id
);
1373 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1375 throw Exceptions::InternalError( loc
, "Environment::findLocalStatePosition failed" );
1380 Kernel::Environment::LexicalKey
1381 Ast::AnalysisEnvironment::findLexicalStateKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
, const Ast::Node
* node
)
1383 size_t pos
= stateBindings_
->lookup( id
);
1384 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1386 if( isBaseEnvironment( ) )
1388 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::STATE
) );
1389 return Kernel::Environment::theMissingKey
;
1391 if( functionBoundary_
)
1393 // If the state is not found at all, this will throw an error.
1394 parent_
->findLexicalStateKey( loc
, id
, node
).oneAbove( ); // Ignore the result!
1395 // If no error is thrown, we inform the user that the state is outside a function boundary.
1396 Ast::theAnalysisErrorsList
.push_back( new Exceptions::StateBeyondFunctionBoundary( loc
, id
) );
1397 return Kernel::Environment::theMissingKey
;
1399 return parent_
->findLexicalStateKey( loc
, id
, node
).oneAbove( );
1402 if( statesFirstUse_
[ pos
] == NULL
){
1403 statesFirstUse_
[ pos
] = node
;
1406 return LexicalKey( 0, pos
);
1410 Ast::AnalysisEnvironment::getStateID( const LexicalKey
& lexKey
) const
1412 const Ast::AnalysisEnvironment
* env
= this;
1413 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1415 env
= env
->getParent( );
1418 return env
->getStateID( lexKey
.pos_
);
1422 Ast::AnalysisEnvironment::getStateID( size_t pos
) const
1424 return states_
[ pos
];
1428 Ast::AnalysisEnvironment::getTheAnyStateID( )
1434 Ast::AnalysisEnvironment::getStateFirstUse( size_t pos
) const
1436 return statesFirstUse_
[ pos
];
1440 Kernel::Environment::introduceState( size_t pos
, Kernel::State
* state
)
1442 if( (*states_
)[ pos
] != NullPtr
< Kernel::State
>( ) )
1444 throw Exceptions::InternalError( "Better error message needed when a state is introduced more than once." );
1445 // throw Exceptions::RedefiningLexical( reverseMap( pos ) );
1448 (*states_
)[ pos
] = state
;
1452 Kernel::Environment::freeze( size_t pos
, Kernel::EvalState
* evalState
, const Ast::SourceLocation
& loc
)
1454 if( (*states_
)[ pos
] == NullPtr
< Kernel::State
>( ) )
1456 /* This is a static inconsistency, so it should be detected before we reach here... */
1457 throw Exceptions::FreezingUndefined( loc
, stateBindings_
->reverseMap( pos
) );
1460 Kernel::StateHandle
& state
= (*states_
)[ pos
];
1462 state
->freeze( evalState
, loc
);
1466 Kernel::Environment::peek( const LexicalKey
& lexKey
, Kernel::EvalState
* evalState
, const Ast::SourceLocation
& loc
)
1468 getStateHandle( lexKey
)->peek( evalState
, loc
);
1472 Kernel::Environment::tackOn( const LexicalKey
& lexKey
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
, const Ast::SourceLocation
& callLoc
)
1474 getStateHandle( lexKey
)->tackOn( evalState
, piece
, callLoc
);
1478 Kernel::Environment::getStateHandle( const LexicalKey
& lexKey
)
1480 Environment
* env
= this;
1481 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1483 env
= env
->getParent( );
1486 return env
->getStateHandle( lexKey
.pos_
);
1490 Kernel::Environment::getStateHandle( size_t pos
)
1492 Kernel::StateHandle res
= (*states_
)[ pos
];
1493 if( res
== NullPtr
< Kernel::State
>( ) )
1495 throw Exceptions::UninitializedAccess( );
1503 Ast::AnalysisEnvironment::findLocalDynamicPosition( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
) const
1505 if( dynamicKeyBindings_
== NULL
)
1507 throw Exceptions::InternalError( "Environment::findLocalDynamicPosition called with dynamicKeyBindings_ == NULL." );
1509 size_t pos
= dynamicKeyBindings_
->lookup( id
);
1510 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1512 throw Exceptions::InternalError( loc
, "Environment::findLocalDynamicPosition failed" );
1518 Kernel::Environment::defineDynamic( const Ast::PlacedIdentifier
* debugId
, size_t pos
, const RefCountPtr
< const Lang::Function
> & filter
, const Kernel::VariableHandle
& defaultVal
)
1520 if( dynamicKeyValues_
== NULL
)
1522 throw Exceptions::InternalError( "Environment::defineDynamic called with dynamicKeyValues_ == NULL." );
1524 if( pos
> dynamicKeyValues_
->size( ) )
1526 throw Exceptions::InternalError( "Environment::defineDynamic called with pos out of range." );
1528 if( (*dynamicKeyValues_
)[ pos
] != NULL
)
1530 throw Exceptions::RedefiningDynamic( dynamicKeyBindings_
->reverseMap( pos
) );
1533 (*dynamicKeyValues_
)[ pos
] = new Kernel::UserDynamicVariableProperties( debugId
,
1534 Kernel::DynamicEnvironment::getFreshKey( ),
1539 Kernel::Environment::LexicalKey
1540 Ast::AnalysisEnvironment::findLexicalDynamicKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1542 if( dynamicKeyBindings_
== NULL
)
1544 if( isBaseEnvironment( ) )
1548 return parent_
->findLexicalDynamicKey( loc
, id
).oneAbove( );
1551 size_t pos
= dynamicKeyBindings_
->lookup( id
);
1552 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1554 if( isBaseEnvironment( ) )
1558 return parent_
->findLexicalDynamicKey( loc
, id
).oneAbove( );
1561 return LexicalKey( 0, pos
);
1565 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::DYNAMIC_VARIABLE
) );
1566 return Kernel::Environment::theMissingKey
;
1569 const Kernel::DynamicVariableProperties
&
1570 Kernel::Environment::lookupDynamicVariable( const LexicalKey
& lexKey
) const
1572 const Environment
* env
= this;
1573 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1575 env
= env
->getParent( );
1578 return env
->lookupDynamicVariable( lexKey
.pos_
);
1581 const Kernel::DynamicVariableProperties
&
1582 Kernel::Environment::lookupDynamicVariable( size_t pos
) const
1584 const DynamicVariableProperties
* res
= (*dynamicKeyValues_
)[ pos
];
1587 throw Exceptions::UninitializedAccess( );
1593 Ast::AnalysisEnvironment::findLocalDynamicStatePosition( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
) const
1595 if( dynamicStateKeyBindings_
== NULL
)
1597 throw Exceptions::InternalError( "Environment::findLocalDynamicStatePosition called with dynamicStateKeyBindings_ == NULL." );
1599 size_t pos
= dynamicStateKeyBindings_
->lookup( id
);
1600 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1602 throw Exceptions::InternalError( loc
, "Environment::findLocalDynamicStatePosition failed" );
1608 Kernel::Environment::defineDynamicState( const Ast::PlacedIdentifier
* debugId
, size_t pos
, Kernel::PassedEnv env
, Kernel::PassedDyn dyn
, Ast::StateReference
* defaultState
)
1610 if( dynamicStateKeyValues_
== NULL
)
1612 throw Exceptions::InternalError( "Environment::defineDynamicState called with dynamicStateKeyValues_ == NULL." );
1614 if( pos
> dynamicStateKeyValues_
->size( ) )
1616 throw Exceptions::InternalError( "Environment::defineDynamicState called with pos out of range." );
1618 if( (*dynamicStateKeyValues_
)[ pos
] != NULL
)
1620 throw Exceptions::RedefiningDynamic( dynamicStateKeyBindings_
->reverseMap( pos
) );
1623 (*dynamicStateKeyValues_
)[ pos
] = new Kernel::UserDynamicStateProperties( debugId
, env
, dyn
, defaultState
);
1627 Kernel::Environment::LexicalKey
1628 Ast::AnalysisEnvironment::findLexicalDynamicStateKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1630 if( dynamicStateKeyBindings_
== NULL
)
1632 return parent_
->findLexicalDynamicStateKey( loc
, id
).oneAbove( );
1635 size_t pos
= dynamicStateKeyBindings_
->lookup( id
);
1636 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1638 if( isBaseEnvironment( ) )
1640 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::DYNAMIC_STATE
) );
1641 return Kernel::Environment::theMissingKey
;
1643 return parent_
->findLexicalDynamicStateKey( loc
, id
).oneAbove( );
1646 return LexicalKey( 0, pos
);
1649 const Kernel::DynamicStateProperties
&
1650 Kernel::Environment::lookupDynamicState( const LexicalKey
& lexKey
) const
1652 const Environment
* env
= this;
1653 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1655 env
= env
->getParent( );
1658 return env
->lookupDynamicState( lexKey
.pos_
);
1661 const Kernel::DynamicStateProperties
&
1662 Kernel::Environment::lookupDynamicState( size_t pos
) const
1664 const DynamicStateProperties
* res
= (*dynamicStateKeyValues_
)[ pos
];
1667 throw Exceptions::UninitializedAccess( );
1674 Kernel::Environment::size( ) const
1676 return bindings_
->size( );
1681 Kernel::Environment::print( std::ostream
& os
) const
1683 std::set
< Ast::PlacedIdentifier
> shadowed
;
1684 std::set
< Ast::PlacedIdentifier
> shadowedStates
;
1685 recursivePrint( os
, & shadowed
, & shadowedStates
);
1689 Kernel::Environment::recursivePrint( std::ostream
& os
, std::set
< Ast::PlacedIdentifier
> * shadowed
, std::set
< Ast::PlacedIdentifier
> * shadowedStates
) const
1691 typedef std::map
< Ast::PlacedIdentifier
, size_t > IdMap
;
1693 std::set
< Ast::PlacedIdentifier
> shadowedBefore( *shadowed
);
1694 std::set
< Ast::PlacedIdentifier
> shadowedStatesBefore( *shadowedStates
);
1697 if( ! isBaseEnvironment( ) )
1701 bindings_
->dumpMap( & tmp
);
1702 for( IdMap::const_iterator i
= tmp
.begin( ); i
!= tmp
.end( ); ++i
){
1703 shadowed
->insert( shadowed
->begin( ), i
->first
);
1708 stateBindings_
->dumpMap( & tmp
);
1709 for( IdMap::const_iterator i
= tmp
.begin( ); i
!= tmp
.end( ); ++i
){
1710 shadowedStates
->insert( shadowedStates
->begin( ), i
->first
);
1713 depth
= parent_
->recursivePrint( os
, shadowed
, shadowedStates
) + 1;
1716 std::string indentation
= std::string( depth
, ' ' );
1719 for( size_t tmp
= bindings_
->size( ); tmp
>= 10; tmp
/= 10, ++width
)
1723 size_t tmp
= ( 29 - 4 ) - strlen( debugName_
);
1724 if( tmp
< 2 || tmp
> 29 ) /* the latter case corresponds to an underflow in the subtraction */
1728 os
<< indentation
<< std::string( tmp
/ 2, '-' ) << "( " << debugName_
<< " )" << std::string( tmp
- tmp
/ 2, '-' ) << std::endl
;
1730 if( ! isBaseEnvironment( ) )
1734 bindings_
->dumpMap( & tmp
);
1735 for( IdMap::const_iterator i
= tmp
.begin( ); i
!= tmp
.end( ); ++i
){
1736 os
<< indentation
<< std::setw(width
) << i
->second
;
1737 if( shadowedBefore
.find( i
->first
) != shadowedBefore
.end( ) )
1746 i
->first
.show( os
, Ast::Identifier::VARIABLE
);
1748 if( (*values_
)[ i
->second
] == NullPtr
< Kernel::Variable
>( ) )
1750 os
<< "< Uninitialized >" ;
1752 else if( (*values_
)[ i
->second
]->isThunk( ) )
1756 else if( dynamic_cast< const Lang::Instance
* >( (*values_
)[ i
->second
]->getUntyped( ).getPtr( ) ) == NULL
)
1758 (*values_
)[ i
->second
]->getUntyped( )->show( os
);
1769 stateBindings_
->dumpMap( & tmp
);
1770 for( IdMap::const_iterator i
= tmp
.begin( ); i
!= tmp
.end( ); ++i
){
1771 os
<< indentation
<< std::setw(width
) << i
->second
;
1772 if( shadowedStatesBefore
.find( i
->first
) != shadowedStatesBefore
.end( ) )
1781 i
->first
.show( os
, Ast::Identifier::STATE
);
1783 if( (*states_
)[ i
->second
] == NullPtr
< Kernel::State
>( ) )
1785 os
<< "< Uninitialized >" ;
1789 os
<< (*states_
)[ i
->second
]->getTypeName( ) ;
1797 os
<< indentation
<< "<< global env >>" << std::endl
;
1800 os
<< indentation
<< "-- -- -- -- -- -- -- -- -- --" << std::endl
;