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 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( ) );
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::copyThunk( ) const
252 throw Exceptions::InternalError( "Variable::copyThunk: There was no thunk to copy." );
254 return thunk_
->deepCopy( );
258 Kernel::Variable::gcMark( Kernel::GCMarkedSet
& marked
)
262 thunk_
->gcMark( marked
);
265 if( val_
!= NullPtr
< const Lang::Value
>( ) )
267 const_cast< Lang::Value
* >( val_
.getPtr( ) )->gcMark( marked
);
272 Kernel::Variable::setValue( const RefCountPtr
< const Lang::Value
> & val
) const
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_.
293 Kernel::Environment::initDefineCoreFunction( Lang::CoreFunction
* fun
)
295 initDefineHandle( fun
->getTitle( ), Kernel::VariableHandle( new Kernel::Variable( RefCountPtr
< const Lang::Value
>( fun
) ) ) );
299 Kernel::Environment::initDefineCoreFunction( RefCountPtr
< const Lang::CoreFunction
> fun
)
301 initDefineHandle( fun
->getTitle( ), Kernel::VariableHandle( new Kernel::Variable( fun
) ) );
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
) )
316 throw Exceptions::IntroducingExisting( Ast::SourceLocation( Ast::FileID::build_internal( "< Initialization >" ) ), id
);
318 values_
->push_back( val
);
320 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
321 if( values_
->size( ) != bindings_
->size( ) ){
322 throw Exceptions::InternalError( "Kernel::Environment::initDefineHandle: Inconsistent number of values." );
327 Kernel::Environment::initDefine( const char * simpleId
, const RefCountPtr
< const Lang::Value
> & val
)
329 initDefineHandle( simpleId
, Kernel::VariableHandle( new Kernel::Variable( val
) ) );
333 Kernel::Environment::initDefine( const char * simpleId
, Kernel::StateHandle state
)
335 initDefine( Ast::PlacedIdentifier( Lang::THE_CORE_NAMESPACE_PATH
, simpleId
), state
);
339 Kernel::Environment::initDefine( const Ast::PlacedIdentifier
& id
, Kernel::StateHandle state
)
341 if( Interaction::logGlobals
)
343 std::ostream
& os
= Kernel::theDebugLog
.os( );
344 os
<< "--log-globals> state: " ;
345 id
.show( os
, Ast::Identifier::STATE
);
349 if( ! stateBindings_
->insert( id
) )
351 throw Exceptions::IntroducingExisting( Ast::SourceLocation( Ast::FileID::build_internal( "< Initialization >" ) ), id
);
353 states_
->push_back( state
);
355 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
356 if( states_
->size( ) != stateBindings_
->size( ) ){
357 throw Exceptions::InternalError( "Kernel::Environment::initDefine: Inconsistent number of states." );
362 Kernel::Environment::initDefineClass( const RefCountPtr
< const Lang::Class
> & cls
)
364 RefCountPtr
< const char > idRef
= cls
->getPrettyName( );
365 const char * simpleId
= strdup( idRef
.getPtr( ) );
366 charPtrDeletionList_
.push_back( simpleId
);
367 initDefineHandle( simpleId
, Kernel::VariableHandle( new Kernel::Variable( cls
) ) );
371 Kernel::Environment::initDefineDynamic( DynamicVariableProperties
* dynProps
)
373 const Ast::PlacedIdentifier
& id( dynProps
->id( ) );
375 if( Interaction::logGlobals
)
377 Kernel::theDebugLog
.os( ) << "--log-globals> dynamic: " ;
378 id
.show( Kernel::theDebugLog
.os( ), Ast::Identifier::DYNAMIC_VARIABLE
);
379 Kernel::theDebugLog
.os( ) << std::endl
;
382 if( ! dynamicKeyBindings_
->insert( id
) )
384 throw Exceptions::IntroducingExisting( Ast::SourceLocation( Ast::FileID::build_internal( "< System dynamic variable initialization >" ) ), id
);
386 dynamicKeyValues_
->push_back( dynProps
);
388 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
389 if( dynamicKeyValues_
->size( ) != dynamicKeyBindings_
->size( ) ){
390 throw Exceptions::InternalError( "Kernel::Environment::initDefineDynamic: Inconsistent number of dynamic keys (1 argument)." );
395 Kernel::Environment::initDefineDynamic( const char * simpleId
, const RefCountPtr
< const Lang::Function
> & filter
, const Kernel::VariableHandle
& defaultVal
)
397 initDefineDynamic( newPlacedIdentifier( Lang::THE_CORE_NAMESPACE_PATH
, simpleId
), filter
, defaultVal
);
401 Kernel::Environment::initDefineDynamic( const Ast::PlacedIdentifier
* id
, const RefCountPtr
< const Lang::Function
> & filter
, const Kernel::VariableHandle
& defaultVal
)
403 if( ! dynamicKeyBindings_
->insert( *id
) )
405 throw Exceptions::IntroducingExisting( Ast::SourceLocation( Ast::FileID::build_internal( "< System dynamic variable initialization >" ) ), *id
);
407 Kernel::DynamicEnvironmentKeyType key
= dynamicKeyValues_
->size( );
408 dynamicKeyValues_
->push_back( new Kernel::UserDynamicVariableProperties( id
, key
, filter
, defaultVal
) );
410 CHECK( /* Assume that matching element counts insure that the identifier is mapped to the correct position. */
411 if( dynamicKeyValues_
->size( ) != dynamicKeyBindings_
->size( ) ){
412 throw Exceptions::InternalError( "Kernel::Environment::initDefineDynamic: Inconsistent number of dynamic keys (3 arguments)." );
417 Kernel::Environment::initDefineDynamicHandler( const Ast::PlacedIdentifier
& id
, const char * msg
)
419 initDefineDynamic( id
.clone( ),
421 Helpers::newValHandle( new Lang::ExceptionWrapper
< Exceptions::HandlerError
>( id
, msg
) ) );
424 PtrOwner_back_Access
< std::list
< const Ast::PlacedIdentifier
* > > Kernel::Environment::coreIdentifiers
;
426 const Ast::PlacedIdentifier
*
427 Kernel::Environment::newPlacedIdentifier( const RefCountPtr
< const Ast::NamespacePath
> & path
, const char * simpleId
)
429 const Ast::PlacedIdentifier
* id
= new Ast::PlacedIdentifier( path
, simpleId
);
430 coreIdentifiers
.push_back( id
);
434 Kernel::Environment::Environment( std::list
< Kernel::Environment
* > & garbageArea
, const char * debugName
)
436 bindings_( new Ast::IdentifierTree
),
437 values_( new std::vector
< Kernel::VariableHandle
>( ) ),
438 dynamicKeyBindings_( new Ast::IdentifierTree
),
439 dynamicKeyValues_( new std::vector
< DynamicVariableProperties
* > ),
440 stateBindings_( new Ast::IdentifierTree
),
441 states_( new std::vector
< Kernel::StateHandle
>( ) ),
442 dynamicStateKeyBindings_( new Ast::IdentifierTree
),
443 dynamicStateKeyValues_( new std::vector
< DynamicStateProperties
* > ),
444 debugName_( debugName
)
446 garbageArea
.push_back( this );
451 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
)
453 bindings_( bindings
), values_( values
), dynamicKeyBindings_( 0 ),
454 stateBindings_( stateBindings
), states_( states
), dynamicStateKeyBindings_( 0 ),
455 debugName_( debugName
)
456 //, unitMap_( NullPtr< Kernel::Environment::UnitMapType >( ) )
458 garbageArea
.push_back( this );
459 // if( parent_ != 0 )
461 // unitMap_ = parent->unitMap_;
467 Kernel::Environment::~Environment( )
470 if( dynamicKeyBindings_
!= 0 )
474 /* The condition means that this is the global evironment, which created its own map.
476 delete dynamicKeyBindings_
;
478 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
480 for( std::vector
< DynamicVariableProperties
* >::iterator i
= dynamicKeyValues_
->begin( ); i
!= dynamicKeyValues_
->end( ); ++i
)
487 delete dynamicKeyValues_
;
489 if( stateBindings_
!= 0 )
493 /* The condition means that this is the global evironment, which created its own map.
495 delete stateBindings_
;
497 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
499 for( std::vector
< StateHandle
>::iterator i
= states_
->begin( ); i
!= states_
->end( ); ++i
)
507 if( dynamicStateKeyBindings_
!= 0 )
511 /* The condition means that this is the global evironment, which created its own map.
513 delete dynamicStateKeyBindings_
;
515 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
517 for( std::vector
< DynamicStateProperties
* >::iterator i
= dynamicStateKeyValues_
->begin( ); i
!= dynamicStateKeyValues_
->end( ); ++i
)
524 delete dynamicStateKeyValues_
;
530 Kernel::Environment::setParent( Kernel::Environment
* parent
)
533 // unitMap_ = parent.unitMap_;
536 Kernel::Environment
*
537 Kernel::Environment::getParent( )
539 if( isBaseEnvironment( ) )
541 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level environment." );
546 const Kernel::Environment
*
547 Kernel::Environment::getParent( ) const
549 if( isBaseEnvironment( ) )
551 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level environment." );
557 Kernel::Environment::setupDynamicKeyVariables( Ast::IdentifierTree
* dynamicKeyBindings
)
559 if( dynamicKeyBindings_
== 0 )
561 dynamicKeyBindings_
= dynamicKeyBindings
;
562 dynamicKeyValues_
= new std::vector
< DynamicVariableProperties
* >;
567 if( dynamicKeyBindings_
!= dynamicKeyBindings
)
569 throw Exceptions::InternalError( "Kernel::Environment::setupDynamicKeyVariables: dynamicKeyBindings_ != dynamicKeyBindings" );
573 size_t theSize
= dynamicKeyBindings_
->size( );
574 dynamicKeyValues_
->reserve( theSize
);
575 while( dynamicKeyValues_
->size( ) < theSize
)
577 dynamicKeyValues_
->push_back( 0 );
582 Kernel::Environment::setupDynamicStateKeyVariables( Ast::IdentifierTree
* dynamicStateKeyBindings
)
584 if( dynamicStateKeyBindings_
== 0 )
586 dynamicStateKeyBindings_
= dynamicStateKeyBindings
;
587 dynamicStateKeyValues_
= new std::vector
< DynamicStateProperties
* >;
592 if( dynamicStateKeyBindings_
!= dynamicStateKeyBindings
)
594 throw Exceptions::InternalError( "Kernel::Environment::setupDynamicStateKeyVariables: dynamicStateKeyBindings_ != dynamicStateKeyBindings" );
598 size_t theSize
= dynamicStateKeyBindings_
->size( );
599 dynamicStateKeyValues_
->reserve( theSize
);
600 while( dynamicStateKeyValues_
->size( ) < theSize
)
602 dynamicStateKeyValues_
->push_back( 0 );
607 Kernel::Environment::extendVectors( )
609 values_
->reserve( bindings_
->size( ) );
610 while( values_
->size( ) < bindings_
->size( ) )
612 values_
->push_back( NullPtr
< Kernel::Variable
>( ) );
615 states_
->reserve( stateBindings_
->size( ) );
616 while( states_
->size( ) < stateBindings_
->size( ) )
618 states_
->push_back( NullPtr
< Kernel::State
>( ) );
624 Kernel::Environment::clear( )
626 /* Strange that this is empty...
627 * The idea, though, is that the reference counting of this->values shall take care of deletion.
631 Ast::AnalysisEnvironment
*
632 Kernel::Environment::newAnalysisEnvironment( Ast::AnalysisEnvironment
* parent
) const
634 Ast::AnalysisEnvironment
* res
= new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList
, parent
, bindings_
, stateBindings_
);
635 if( dynamicKeyBindings_
!= 0 )
637 res
->setupDynamicKeyVariables( dynamicKeyBindings_
);
639 if( dynamicStateKeyBindings_
!= 0 )
641 res
->setupDynamicStateKeyVariables( dynamicStateKeyBindings_
);
648 Kernel::Environment::gcMark( Kernel::GCMarkedSet
& marked
)
655 marked
.insert( marked
.begin( ), this );
661 Kernel::Environment::collect( std::list
< Kernel::Environment
* > & garbageArea
)
663 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); ++i
)
665 (*i
)->clear_gcMarked( );
668 Kernel::GCMarkedSet marked
;
669 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); ++i
)
671 (*i
)->gcMark( marked
);
674 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); )
676 if( (*i
)->gcMarked( ) )
681 std::list
< Kernel::Environment
* >::iterator tmp
= i
;
684 garbageArea
.erase( tmp
);
689 const size_t Ast::IdentifierTree::NOT_FOUND
= std::numeric_limits
< size_t >::max( );
691 Ast::IdentifierTree::IdentifierTree( )
695 Ast::IdentifierTree::~IdentifierTree( )
697 typedef typeof namespaces_ MapType
;
698 for( MapType::iterator i
= namespaces_
.begin( ); i
!= namespaces_
.end( ); ++i
)
705 Ast::IdentifierTree::insert( const Ast::PlacedIdentifier
& id
)
707 return insert( id
.absolutePath( ).begin( ), id
.absolutePath( ).end( ), id
.simpleId( ), size_
);
711 Ast::IdentifierTree::insert( Ast::NamespacePath::const_iterator begin
, const Ast::NamespacePath::const_iterator
& end
, const char * simpleId
, size_t pos
)
715 typedef typeof simpleIdentifiers_ MapType
;
716 if( simpleIdentifiers_
.find( simpleId
) != simpleIdentifiers_
.end( ) )
718 simpleIdentifiers_
.insert( MapType::value_type( simpleId
, pos
) );
724 typedef typeof namespaces_ MapType
;
725 MapType::iterator j
= namespaces_
.find( *begin
);
726 if( j
!= namespaces_
.end( ) ){
728 bool success
= j
->second
->insert( ++begin
, end
, simpleId
, pos
);
735 IdentifierTree
* tree
= new IdentifierTree
;
736 namespaces_
.insert( MapType::value_type( *begin
, tree
) );
737 bool success
= tree
->insert( ++begin
, end
, simpleId
, pos
);
740 throw Exceptions::InternalError( "Ast::IdentifierTree::insert: Could not insert into new namespace." );
752 Ast::IdentifierTree::lookup( const Ast::Identifier
& id
) const
754 if( id
.absolute( ) ){
756 if( ! id
.path( ).empty( ) ){
758 const Ast::SearchContext
& context
= id
.searchContext( );
759 Ast::NamespacePath::const_iterator begin
= id
.path( ).begin( );
760 const char * pathFront
= *begin
;
763 for( RefCountPtr
< const Ast::NamespaceAliasStack
> i( context
.aliasStack( ) ); i
!= NullPtr
< const Ast::NamespaceAliasStack
>( ); i
= i
->cdr( ) ){
764 if( strcmp( pathFront
, i
->carAlias( ) ) != 0 )
767 if( i
->carAbsolute( ) ){
769 return lookupSuffix( i
->carOriginal( ).begin( ), i
->carOriginal( ).end( ), id
);
773 return lookupPrefix( context
.lexicalPath( )->begin( ), context
.lexicalPath( )->end( ), i
->carOriginal( ), id
);
779 return lookupSuffix( id
.path( ).begin( ), id
.path( ).end( ), id
.simpleId( ) );
783 const Ast::SearchContext
& context
= id
.searchContext( );
786 size_t pos
= lookupPrefix( context
.lexicalPath( )->begin( ), context
.lexicalPath( )->end( ), id
.path( ), id
.simpleId( ) );
787 if( pos
!= NOT_FOUND
)
791 for( RefCountPtr
< const Ast::LookinPathStack
> i( context
.lookinStack( ) ); i
!= NullPtr
< const Ast::LookinPathStack
>( ); i
= i
->cdr( ) ){
792 size_t pos
= lookupSuffix( i
->car( )->begin( ), i
->car( )->end( ), id
.simpleId( ) );
793 if( pos
!= NOT_FOUND
)
803 Ast::IdentifierTree::lookup( const Ast::PlacedIdentifier
& id
) const
805 return lookupSuffix( id
.absolutePath( ).begin( ), id
.absolutePath( ).end( ), id
.simpleId( ) );
809 Ast::IdentifierTree::lookupPrefix( Ast::NamespacePath::const_iterator begin
, const Ast::NamespacePath::const_iterator
& end
, const Ast::NamespacePath
& relativePath
, const char * simpleId
) const
812 typedef typeof namespaces_ MapType
;
813 MapType::const_iterator j
= namespaces_
.find( *begin
);
814 if( j
!= namespaces_
.end( ) ){
816 size_t pos
= j
->second
->lookupPrefix( ++begin
, end
, relativePath
, simpleId
);
817 if( pos
!= NOT_FOUND
)
823 return lookupSuffix( relativePath
.begin( ), relativePath
.end( ), simpleId
);
827 Ast::IdentifierTree::lookupSuffix( Ast::NamespacePath::const_iterator begin
, const Ast::NamespacePath::const_iterator
& end
, const char * simpleId
) const
831 typedef typeof simpleIdentifiers_ MapType
;
832 MapType::const_iterator i
= simpleIdentifiers_
.find( simpleId
);
833 if( i
== simpleIdentifiers_
.end( ) )
840 typedef typeof namespaces_ MapType
;
841 MapType::const_iterator j
= namespaces_
.find( *begin
);
842 if( j
== namespaces_
.end( ) )
845 return j
->second
->lookupSuffix( ++begin
, end
, simpleId
);
851 Ast::IdentifierTree::lookupPrefix( Ast::NamespacePath::const_iterator begin
, const Ast::NamespacePath::const_iterator
& end
, const Ast::NamespacePath
& aliasPath
, const Ast::Identifier
& id
) const
853 /* Note that this function is only used for relative namespace aliases. This means that id will have the form of an absolute identifier,
854 * ::Alias::A::B::...::x
855 * where ::Alias is being expanded to a relative namespace path, and the par beginning wth A:: is what gets appended to the expanded alias.
859 typedef typeof namespaces_ MapType
;
860 MapType::const_iterator j
= namespaces_
.find( *begin
);
861 if( j
!= namespaces_
.end( ) ){
863 size_t pos
= j
->second
->lookupPrefix( ++begin
, end
, aliasPath
, id
);
864 if( pos
!= NOT_FOUND
)
870 return lookupSuffix( aliasPath
.begin( ), aliasPath
.end( ), id
);
874 Ast::IdentifierTree::lookupSuffix( Ast::NamespacePath::const_iterator begin
, const Ast::NamespacePath::const_iterator
& end
, const Ast::Identifier
& id
) const
876 /* Note that this function is only used for absolute namespace aliases. This means that id will have the form of an absolute identifier,
877 * ::Alias::A::B::...::x
878 * where ::Alias is being expanded to an absolute namespace path, and the par beginning wth A:: is what gets appended to the expanded alias.
883 Ast::NamespacePath::const_iterator idBegin
= id
.path( ).begin( );
886 return lookupSuffix( idBegin
, id
.path( ).end( ), id
.simpleId( ) );
890 typedef typeof namespaces_ MapType
;
891 MapType::const_iterator j
= namespaces_
.find( *begin
);
892 if( j
== namespaces_
.end( ) )
895 return j
->second
->lookupSuffix( ++begin
, end
, id
);
901 Ast::PlacedIdentifier
902 Ast::IdentifierTree::reverseMap( size_t pos
) const
904 const char * simpleId
;
905 std::list
< const char * > * absolutePath
= reverseMapHelper( pos
, & simpleId
);
906 if( absolutePath
== NULL
)
907 throw Exceptions::InternalError( "Ast::IdentifierTree::reverseMap failure." );
908 return Ast::PlacedIdentifier( absolutePath
, simpleId
);
911 std::list
< const char * > *
912 Ast::IdentifierTree::reverseMapHelper( size_t pos
, const char ** simpleIdDst
) const
915 typedef typeof simpleIdentifiers_ MapType
;
916 for( MapType::const_iterator i
= simpleIdentifiers_
.begin( ); i
!= simpleIdentifiers_
.end( ); ++i
){
917 if( i
->second
== pos
)
919 std::list
< const char * > * result( new std::list
< const char * > );
920 *simpleIdDst
= i
->first
;
927 typedef typeof namespaces_ MapType
;
928 for( MapType::const_iterator i
= namespaces_
.begin( ); i
!= namespaces_
.end( ); ++i
){
929 std::list
< const char * > * path
= i
->second
->reverseMapHelper( pos
, simpleIdDst
);
932 path
->push_front( i
->first
);
941 Ast::IdentifierTree::dumpMap( std::map
< Ast::PlacedIdentifier
, size_t > * dst
) const
943 Ast::NamespacePath path
;
944 dumpMap( dst
, & path
);
948 Ast::IdentifierTree::dumpMap( std::map
< Ast::PlacedIdentifier
, size_t > * dst
, Ast::NamespacePath
* path
) const
951 typedef typeof simpleIdentifiers_ MapType
;
952 typedef typeof *dst DstType
;
953 for( MapType::const_iterator i
= simpleIdentifiers_
.begin( ); i
!= simpleIdentifiers_
.end( ); ++i
){
954 dst
->insert( DstType::value_type( Ast::PlacedIdentifier( *path
, i
->first
), i
->second
) );
959 typedef typeof namespaces_ MapType
;
960 for( MapType::const_iterator i
= namespaces_
.begin( ); i
!= namespaces_
.end( ); ++i
){
961 path
->push_back( i
->first
);
962 i
->second
->dumpMap( dst
, path
);
969 Ast::StateID
Ast::AnalysisEnvironment::nextStateID
= 1;
971 Ast::AnalysisEnvironment::AnalysisEnvironment( PtrOwner_back_Access
< std::list
< Ast::AnalysisEnvironment
* > > & deleter
, Ast::AnalysisEnvironment
* parent
, const Ast::IdentifierTree
* bindings
, const Ast::IdentifierTree
* stateBindings
)
973 level_( ( parent_
== 0 ) ? 0 : ( parent_
->level_
+ 1 ) ),
974 bindings_( bindings
), dynamicKeyBindings_( 0 ),
975 stateBindings_( stateBindings
), dynamicStateKeyBindings_( 0 ),
976 functionBoundary_( false )
978 deleter
.push_back( this );
982 Ast::AnalysisEnvironment::~AnalysisEnvironment( )
986 Ast::AnalysisEnvironment::updateBindings( )
988 states_
.reserve( stateBindings_
->size( ) );
989 while( states_
.size( ) < stateBindings_
->size( ) )
991 states_
.push_back( nextStateID
);
996 Ast::AnalysisEnvironment
*
997 Ast::AnalysisEnvironment::getParent( ) const
999 if( isBaseEnvironment( ) )
1001 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level analysis environment." );
1007 Ast::AnalysisEnvironment::activateFunctionBoundary( )
1009 functionBoundary_
= true;
1013 Ast::AnalysisEnvironment::setupDynamicKeyVariables( const Ast::IdentifierTree
* dynamicKeyBindings
)
1015 dynamicKeyBindings_
= dynamicKeyBindings
;
1019 Ast::AnalysisEnvironment::setupDynamicStateKeyVariables( const Ast::IdentifierTree
* dynamicStateKeyBindings
)
1021 dynamicStateKeyBindings_
= dynamicStateKeyBindings
;
1025 Ast::AnalysisEnvironment::findLocalVariablePosition( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
) const
1027 size_t pos
= bindings_
->lookup( id
);
1028 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1030 throw Exceptions::InternalError( loc
, "Environment::findLocalPosition failed" );
1036 Kernel::Environment::define( size_t pos
, const Kernel::VariableHandle
& val
)
1038 if( (*values_
)[ pos
] != NullPtr
< Kernel::Variable
>( ) )
1040 throw Exceptions::RedefiningLexical( bindings_
->reverseMap( pos
) );
1043 (*values_
)[ pos
] = val
;
1046 Kernel::Environment::LexicalKey
1047 Ast::AnalysisEnvironment::findLexicalVariableKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1049 size_t pos
= bindings_
->lookup( id
);
1050 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1052 if( isBaseEnvironment( ) )
1054 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::VARIABLE
) );
1055 return Kernel::Environment::theMissingKey
;
1057 return parent_
->findLexicalVariableKey( loc
, id
).oneAbove( );
1060 return LexicalKey( 0, pos
);
1063 Ast::PlacedIdentifier
1064 Ast::AnalysisEnvironment::reverseMapLexicalVariable( const LexicalKey
& lexKey
) const
1066 const AnalysisEnvironment
* env
= this;
1067 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1069 env
= env
->getParent( );
1072 return env
->bindings_
->reverseMap( lexKey
.pos_
);
1076 Kernel::Environment::lookup( const Kernel::Environment::LexicalKey
& lexKey
, Kernel::EvalState
* evalState
) const
1078 const Environment
* env
= this;
1079 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1081 env
= env
->getParent( );
1084 env
->lookup( lexKey
.pos_
, evalState
);
1088 Kernel::Environment::lookup( size_t pos
, Kernel::EvalState
* evalState
) const
1090 Kernel::VariableHandle res
= (*values_
)[ pos
];
1091 if( res
== NullPtr
< Kernel::Variable
>( ) )
1093 throw Exceptions::UninitializedAccess( );
1096 Kernel::ContRef cont
= evalState
->cont_
;
1097 cont
->takeHandle( res
, evalState
);
1100 Kernel::VariableHandle
1101 Kernel::Environment::getVarHandle( const Kernel::Environment::LexicalKey
& lexKey
)
1103 Environment
* env
= this;
1104 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1106 env
= env
->getParent( );
1109 return env
->getVarHandle( lexKey
.pos_
);
1112 Kernel::VariableHandle
1113 Kernel::Environment::getVarHandle( size_t pos
)
1115 return (*values_
)[ pos
];
1118 Kernel::Environment::LexicalKey
1119 Ast::AnalysisEnvironment::findLexicalTypeKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1121 size_t pos
= bindings_
->lookup( id
);
1122 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1124 if( isBaseEnvironment( ) )
1126 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::TYPE
) );
1127 return Kernel::Environment::theMissingKey
;
1129 return parent_
->findLexicalTypeKey( loc
, id
).oneAbove( );
1132 return LexicalKey( 0, pos
);
1137 Ast::AnalysisEnvironment::findLocalStatePosition( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
) const
1139 size_t pos
= stateBindings_
->lookup( id
);
1140 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1142 throw Exceptions::InternalError( loc
, "Environment::findLocalStatePosition failed" );
1147 Kernel::Environment::LexicalKey
1148 Ast::AnalysisEnvironment::findLexicalStateKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1150 size_t pos
= stateBindings_
->lookup( id
);
1151 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1153 if( isBaseEnvironment( ) )
1155 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::STATE
) );
1156 return Kernel::Environment::theMissingKey
;
1158 if( functionBoundary_
)
1160 // If the state is not found at all, this will throw an error.
1161 parent_
->findLexicalStateKey( loc
, id
).oneAbove( ); // Ignore the result!
1162 // If no error is thrown, we inform the user that the state is outside a function boundary.
1163 Ast::theAnalysisErrorsList
.push_back( new Exceptions::StateBeyondFunctionBoundary( loc
, id
) );
1164 return Kernel::Environment::theMissingKey
;
1166 return parent_
->findLexicalStateKey( loc
, id
).oneAbove( );
1169 return LexicalKey( 0, pos
);
1173 Ast::AnalysisEnvironment::getStateID( const LexicalKey
& lexKey
) const
1175 const Ast::AnalysisEnvironment
* env
= this;
1176 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1178 env
= env
->getParent( );
1181 return env
->getStateID( lexKey
.pos_
);
1185 Ast::AnalysisEnvironment::getStateID( size_t pos
) const
1187 return states_
[ pos
];
1191 Ast::AnalysisEnvironment::getTheAnyStateID( )
1197 Kernel::Environment::introduceState( size_t pos
, Kernel::State
* state
)
1199 if( (*states_
)[ pos
] != NullPtr
< Kernel::State
>( ) )
1201 throw Exceptions::InternalError( "Better error message needed when a state is introduced more than once." );
1202 // throw Exceptions::RedefiningLexical( reverseMap( pos ) );
1205 (*states_
)[ pos
] = state
;
1209 Kernel::Environment::freeze( size_t pos
, Kernel::EvalState
* evalState
, const Ast::SourceLocation
& loc
)
1211 if( (*states_
)[ pos
] == NullPtr
< Kernel::State
>( ) )
1213 // This is a static inconsistency, so it should be detected before we reach here...
1214 throw Exceptions::FreezingUndefined( loc
, stateBindings_
->reverseMap( pos
) );
1217 Kernel::StateHandle
& state
= (*states_
)[ pos
];
1219 state
->freeze( evalState
, loc
);
1223 Kernel::Environment::peek( const LexicalKey
& lexKey
, Kernel::EvalState
* evalState
, const Ast::SourceLocation
& loc
)
1225 getStateHandle( lexKey
)->peek( evalState
, loc
);
1229 Kernel::Environment::tackOn( const LexicalKey
& lexKey
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
, const Ast::SourceLocation
& callLoc
)
1231 getStateHandle( lexKey
)->tackOn( evalState
, piece
, callLoc
);
1235 Kernel::Environment::getStateHandle( const LexicalKey
& lexKey
)
1237 Environment
* env
= this;
1238 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1240 env
= env
->getParent( );
1243 return env
->getStateHandle( lexKey
.pos_
);
1247 Kernel::Environment::getStateHandle( size_t pos
)
1249 Kernel::StateHandle res
= (*states_
)[ pos
];
1250 if( res
== NullPtr
< Kernel::State
>( ) )
1252 throw Exceptions::UninitializedAccess( );
1260 Ast::AnalysisEnvironment::findLocalDynamicPosition( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
) const
1262 if( dynamicKeyBindings_
== 0 )
1264 throw Exceptions::InternalError( "Environment::findLocalDynamicPosition called with dynamicKeyBindings_ == 0." );
1266 size_t pos
= dynamicKeyBindings_
->lookup( id
);
1267 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1269 throw Exceptions::InternalError( loc
, "Environment::findLocalDynamicPosition failed" );
1275 Kernel::Environment::defineDynamic( const Ast::PlacedIdentifier
* debugId
, size_t pos
, const RefCountPtr
< const Lang::Function
> & filter
, const Kernel::VariableHandle
& defaultVal
)
1277 if( dynamicKeyValues_
== 0 )
1279 throw Exceptions::InternalError( "Environment::defineDynamic called with dynamicKeyValues_ == 0." );
1281 if( pos
> dynamicKeyValues_
->size( ) )
1283 throw Exceptions::InternalError( "Environment::defineDynamic called with pos out of range." );
1285 if( (*dynamicKeyValues_
)[ pos
] != 0 )
1287 throw Exceptions::RedefiningDynamic( dynamicKeyBindings_
->reverseMap( pos
) );
1290 (*dynamicKeyValues_
)[ pos
] = new Kernel::UserDynamicVariableProperties( debugId
,
1291 Kernel::DynamicEnvironment::getFreshKey( ),
1296 Kernel::Environment::LexicalKey
1297 Ast::AnalysisEnvironment::findLexicalDynamicKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1299 if( dynamicKeyBindings_
== 0 )
1301 if( isBaseEnvironment( ) )
1305 return parent_
->findLexicalDynamicKey( loc
, id
).oneAbove( );
1308 size_t pos
= dynamicKeyBindings_
->lookup( id
);
1309 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1311 if( isBaseEnvironment( ) )
1315 return parent_
->findLexicalDynamicKey( loc
, id
).oneAbove( );
1318 return LexicalKey( 0, pos
);
1322 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::DYNAMIC_VARIABLE
) );
1323 return Kernel::Environment::theMissingKey
;
1327 const Kernel::DynamicVariableProperties
&
1328 Kernel::Environment::lookupDynamicVariable( const LexicalKey
& lexKey
) const
1330 const Environment
* env
= this;
1331 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1333 env
= env
->getParent( );
1336 return env
->lookupDynamicVariable( lexKey
.pos_
);
1339 const Kernel::DynamicVariableProperties
&
1340 Kernel::Environment::lookupDynamicVariable( size_t pos
) const
1342 const DynamicVariableProperties
* res
= (*dynamicKeyValues_
)[ pos
];
1345 throw Exceptions::UninitializedAccess( );
1351 Ast::AnalysisEnvironment::findLocalDynamicStatePosition( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
) const
1353 if( dynamicStateKeyBindings_
== 0 )
1355 throw Exceptions::InternalError( "Environment::findLocalDynamicStatePosition called with dynamicStateKeyBindings_ == 0." );
1357 size_t pos
= dynamicStateKeyBindings_
->lookup( id
);
1358 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1360 throw Exceptions::InternalError( loc
, "Environment::findLocalDynamicStatePosition failed" );
1366 Kernel::Environment::defineDynamicState( const Ast::PlacedIdentifier
* debugId
, size_t pos
, Kernel::EvalState
* evalState
, Ast::StateReference
* defaultState
)
1368 if( dynamicStateKeyValues_
== 0 )
1370 throw Exceptions::InternalError( "Environment::defineDynamicState called with dynamicStateKeyValues_ == 0." );
1372 if( pos
> dynamicStateKeyValues_
->size( ) )
1374 throw Exceptions::InternalError( "Environment::defineDynamicState called with pos out of range." );
1376 if( (*dynamicStateKeyValues_
)[ pos
] != 0 )
1378 throw Exceptions::RedefiningDynamic( dynamicStateKeyBindings_
->reverseMap( pos
) );
1381 (*dynamicStateKeyValues_
)[ pos
] = new Kernel::UserDynamicStateProperties( debugId
,
1382 // Kernel::DynamicEnvironment::getFreshKey( ),
1389 Kernel::Environment::LexicalKey
1390 Ast::AnalysisEnvironment::findLexicalDynamicStateKey( const Ast::SourceLocation
& loc
, const Ast::Identifier
& id
) const
1392 if( dynamicStateKeyBindings_
== 0 )
1394 return parent_
->findLexicalDynamicStateKey( loc
, id
).oneAbove( );
1397 size_t pos
= dynamicStateKeyBindings_
->lookup( id
);
1398 if( pos
== Ast::IdentifierTree::NOT_FOUND
)
1400 if( isBaseEnvironment( ) )
1402 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, id
, Ast::Identifier::DYNAMIC_STATE
) );
1403 return Kernel::Environment::theMissingKey
;
1405 return parent_
->findLexicalDynamicStateKey( loc
, id
).oneAbove( );
1408 return LexicalKey( 0, pos
);
1411 const Kernel::DynamicStateProperties
&
1412 Kernel::Environment::lookupDynamicState( const LexicalKey
& lexKey
) const
1414 const Environment
* env
= this;
1415 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1417 env
= env
->getParent( );
1420 return env
->lookupDynamicState( lexKey
.pos_
);
1423 const Kernel::DynamicStateProperties
&
1424 Kernel::Environment::lookupDynamicState( size_t pos
) const
1426 const DynamicStateProperties
* res
= (*dynamicStateKeyValues_
)[ pos
];
1429 throw Exceptions::UninitializedAccess( );
1436 Kernel::Environment::size( ) const
1438 return bindings_
->size( );
1443 Kernel::Environment::print( std::ostream
& os
) const
1445 std::set
< Ast::PlacedIdentifier
> shadowed
;
1446 std::set
< Ast::PlacedIdentifier
> shadowedStates
;
1447 recursivePrint( os
, & shadowed
, & shadowedStates
);
1451 Kernel::Environment::recursivePrint( std::ostream
& os
, std::set
< Ast::PlacedIdentifier
> * shadowed
, std::set
< Ast::PlacedIdentifier
> * shadowedStates
) const
1453 typedef std::map
< Ast::PlacedIdentifier
, size_t > IdMap
;
1455 std::set
< Ast::PlacedIdentifier
> shadowedBefore( *shadowed
);
1456 std::set
< Ast::PlacedIdentifier
> shadowedStatesBefore( *shadowedStates
);
1459 if( ! isBaseEnvironment( ) )
1463 bindings_
->dumpMap( & tmp
);
1464 for( IdMap::const_iterator i
= tmp
.begin( ); i
!= tmp
.end( ); ++i
){
1465 shadowed
->insert( shadowed
->begin( ), i
->first
);
1470 stateBindings_
->dumpMap( & tmp
);
1471 for( IdMap::const_iterator i
= tmp
.begin( ); i
!= tmp
.end( ); ++i
){
1472 shadowedStates
->insert( shadowedStates
->begin( ), i
->first
);
1475 depth
= parent_
->recursivePrint( os
, shadowed
, shadowedStates
) + 1;
1478 std::string indentation
= std::string( depth
, ' ' );
1481 for( size_t tmp
= bindings_
->size( ); tmp
>= 10; tmp
/= 10, ++width
)
1485 size_t tmp
= ( 29 - 4 ) - strlen( debugName_
);
1486 if( tmp
< 2 || tmp
> 29 ) /* the latter case corresponds to an underflow in the subtraction */
1490 os
<< indentation
<< std::string( tmp
/ 2, '-' ) << "( " << debugName_
<< " )" << std::string( tmp
- tmp
/ 2, '-' ) << std::endl
;
1492 if( ! isBaseEnvironment( ) )
1496 bindings_
->dumpMap( & tmp
);
1497 for( IdMap::const_iterator i
= tmp
.begin( ); i
!= tmp
.end( ); ++i
){
1498 os
<< indentation
<< std::setw(width
) << i
->second
;
1499 if( shadowedBefore
.find( i
->first
) != shadowedBefore
.end( ) )
1508 i
->first
.show( os
, Ast::Identifier::VARIABLE
);
1510 if( (*values_
)[ i
->second
] == NullPtr
< Kernel::Variable
>( ) )
1512 os
<< "< Uninitialized >" ;
1514 else if( (*values_
)[ i
->second
]->isThunk( ) )
1518 else if( dynamic_cast< const Lang::Instance
* >( (*values_
)[ i
->second
]->getUntyped( ).getPtr( ) ) == 0 )
1520 (*values_
)[ i
->second
]->getUntyped( )->show( os
);
1531 stateBindings_
->dumpMap( & tmp
);
1532 for( IdMap::const_iterator i
= tmp
.begin( ); i
!= tmp
.end( ); ++i
){
1533 os
<< indentation
<< std::setw(width
) << i
->second
;
1534 if( shadowedStatesBefore
.find( i
->first
) != shadowedStatesBefore
.end( ) )
1543 i
->first
.show( os
, Ast::Identifier::STATE
);
1545 if( (*states_
)[ i
->second
] == NullPtr
< Kernel::State
>( ) )
1547 os
<< "< Uninitialized >" ;
1551 os
<< (*states_
)[ i
->second
]->getTypeName( ) ;
1559 os
<< indentation
<< "<< global env >>" << std::endl
;
1562 os
<< indentation
<< "-- -- -- -- -- -- -- -- -- --" << std::endl
;