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 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( Kernel::VariableHandle
& selfRef
, Kernel::EvalState
* evalState
) const
207 if( state_
== Kernel::Variable::THUNK
)
209 state_
= Kernel::Variable::FORCING
;
210 evalState
->cont_
= Kernel::ContRef( new Kernel::StoreVariableContinuation( selfRef
, evalState
->cont_
, thunk_
->getExpr( )->loc( ) ) );
211 thunk_
->force( evalState
);
216 if( val_
== NullPtr
< const Lang::Value
>( ) )
218 if( state_
== Kernel::Variable::FORCING
)
220 throw Exceptions::MiscellaneousRequirement( "Cyclic forcing." );
222 throw Exceptions::InternalError( "Force failed. No value, not forcing." );
224 Kernel::ContRef cont
= evalState
->cont_
;
225 cont
->takeHandle( selfRef
, evalState
);
228 RefCountPtr
< const Lang::Value
> &
229 Kernel::Variable::getUntyped( ) const
231 if( val_
== NullPtr
< const Lang::Value
>( ) )
233 throw Exceptions::InternalError( "The value is not ready to be get without continuation." );
240 Kernel::Variable::isThunk( ) const
242 return ( state_
& Kernel::Variable::FORCING
) != 0;
246 Kernel::Variable::copyThunk( ) const
250 throw Exceptions::InternalError( "Variable::copyThunk: There was no thunk to copy." );
252 return thunk_
->deepCopy( );
256 Kernel::Variable::gcMark( Kernel::GCMarkedSet
& marked
)
260 thunk_
->gcMark( marked
);
263 if( val_
!= NullPtr
< const Lang::Value
>( ) )
265 const_cast< Lang::Value
* >( val_
.getPtr( ) )->gcMark( marked
);
270 Kernel::Variable::setValue( const RefCountPtr
< const Lang::Value
> & val
) const
273 state_
= Kernel::Variable::COLD
;
277 Kernel::DynamicVariableProperties::~DynamicVariableProperties( )
280 Kernel::DynamicStateProperties::~DynamicStateProperties( )
285 Kernel::Environment::initDefineCoreFunction( Lang::CoreFunction
* fun
)
287 initDefineHandle( fun
->getTitle( ), Kernel::VariableHandle( new Kernel::Variable( RefCountPtr
< const Lang::Value
>( fun
) ) ) );
291 Kernel::Environment::initDefineCoreFunction( RefCountPtr
< const Lang::CoreFunction
> fun
)
293 initDefineHandle( fun
->getTitle( ), Kernel::VariableHandle( new Kernel::Variable( fun
) ) );
297 Kernel::Environment::initDefineHandle( const char * id
, const Kernel::VariableHandle
& val
)
299 if( Interaction::logGlobals
)
301 Kernel::theDebugLog
.os( ) << "--log-globals> variable: " << id
<< std::endl
;
303 if( bindings_
->find( id
) != bindings_
->end( ) )
305 throw Exceptions::IntroducingExisting( Ast::SourceLocation( Ast::FileID::build_internal( "< Initialization >" ) ), id
);
308 (*bindings_
)[ id
] = values_
->size( );
310 values_
->push_back( val
);
314 Kernel::Environment::initDefine( const char * id
, const RefCountPtr
< const Lang::Value
> & val
)
316 initDefineHandle( id
, Kernel::VariableHandle( new Kernel::Variable( val
) ) );
320 Kernel::Environment::initDefine( const char * id
, Kernel::StateHandle state
)
322 if( Interaction::logGlobals
)
324 Kernel::theDebugLog
.os( ) << "--log-globals> state: " << id
<< std::endl
;
326 if( stateBindings_
->find( id
) != stateBindings_
->end( ) )
328 throw Exceptions::IntroducingExisting( Ast::SourceLocation( Ast::FileID::build_internal( "< Initialization >" ) ), id
);
331 (*stateBindings_
)[ id
] = states_
->size( );
333 states_
->push_back( state
);
337 Kernel::Environment::initDefineClass( const RefCountPtr
< const Lang::Class
> & cls
)
339 RefCountPtr
< const char > idRef
= cls
->getPrettyName( );
340 const char * id
= strdup( idRef
.getPtr( ) );
341 charPtrDeletionList_
.push_back( id
);
342 initDefineHandle( id
, Kernel::VariableHandle( new Kernel::Variable( cls
) ) );
346 Kernel::Environment::initDefineDynamic( DynamicVariableProperties
* dynProps
)
348 if( Interaction::logGlobals
)
350 Kernel::theDebugLog
.os( ) << "--log-globals> dynamic: " << dynProps
->getName( ) << std::endl
;
352 if( dynamicKeyBindings_
->find( dynProps
->getName( ) ) != dynamicKeyBindings_
->end( ) )
354 throw Exceptions::IntroducingExisting( Ast::SourceLocation( Ast::FileID::build_internal( "< System dynamic variable initialization >" ) ), dynProps
->getName( ) );
357 (*dynamicKeyBindings_
)[ dynProps
->getName( ) ] = dynamicKeyValues_
->size( );
359 dynamicKeyValues_
->push_back( dynProps
);
363 Kernel::Environment::initDefineDynamic( const char * id
, const RefCountPtr
< const Lang::Function
> & filter
, const Kernel::VariableHandle
& defaultVal
)
365 if( dynamicKeyBindings_
->find( id
) != dynamicKeyBindings_
->end( ) )
367 throw Exceptions::IntroducingExisting( Ast::SourceLocation( Ast::FileID::build_internal( "< System dynamic variable initialization >" ) ), id
);
370 Kernel::DynamicEnvironmentKeyType key
= dynamicKeyValues_
->size( );
371 (*dynamicKeyBindings_
)[ id
] = key
;
373 dynamicKeyValues_
->push_back( new Kernel::UserDynamicVariableProperties( id
, key
, filter
, defaultVal
) );
377 Kernel::Environment::initDefineDynamicHandler( const char * id
, const char * msg
)
379 initDefineDynamic( id
,
381 Helpers::newValHandle( new Lang::ExceptionWrapper
< Exceptions::HandlerError
>( id
, msg
) ) );
384 Kernel::Environment::Environment( std::list
< Kernel::Environment
* > & garbageArea
, const char * debugName
)
386 bindings_( new Kernel::Environment::MapType
),
387 values_( new std::vector
< Kernel::VariableHandle
>( ) ),
388 dynamicKeyBindings_( new Kernel::Environment::MapType
),
389 dynamicKeyValues_( new std::vector
< DynamicVariableProperties
* > ),
390 stateBindings_( new Kernel::Environment::MapType
),
391 states_( new std::vector
< Kernel::StateHandle
>( ) ),
392 dynamicStateKeyBindings_( new Kernel::Environment::MapType
),
393 dynamicStateKeyValues_( new std::vector
< DynamicStateProperties
* > ),
394 functionBoundary_( false ),
395 debugName_( debugName
)
397 garbageArea
.push_back( this );
402 Kernel::Environment::Environment( std::list
< Kernel::Environment
* > & garbageArea
, Environment
* parent
, MapType
* bindings
, const RefCountPtr
< std::vector
< VariableHandle
> > & values
, MapType
* stateBindings
, const RefCountPtr
< std::vector
< StateHandle
> > & states
, const char * debugName
)
404 bindings_( bindings
), values_( values
), dynamicKeyBindings_( 0 ),
405 stateBindings_( stateBindings
), states_( states
), dynamicStateKeyBindings_( 0 ),
406 functionBoundary_( false ),
407 debugName_( debugName
)
408 //, unitMap_( NullPtr< Kernel::Environment::UnitMapType >( ) )
410 garbageArea
.push_back( this );
411 // if( parent_ != 0 )
413 // unitMap_ = parent->unitMap_;
419 Kernel::Environment::~Environment( )
422 if( dynamicKeyBindings_
!= 0 )
426 /* The condition means that this is the global evironment, which created its own map.
428 delete dynamicKeyBindings_
;
430 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
432 for( std::vector
< DynamicVariableProperties
* >::iterator i
= dynamicKeyValues_
->begin( ); i
!= dynamicKeyValues_
->end( ); ++i
)
439 delete dynamicKeyValues_
;
441 if( stateBindings_
!= 0 )
445 /* The condition means that this is the global evironment, which created its own map.
447 delete stateBindings_
;
449 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
451 for( std::vector
< StateHandle
>::iterator i
= states_
->begin( ); i
!= states_
->end( ); ++i
)
459 if( dynamicStateKeyBindings_
!= 0 )
463 /* The condition means that this is the global evironment, which created its own map.
465 delete dynamicStateKeyBindings_
;
467 /* However, the values will always be owned by the environment itself, and be defined whenever dynamicKeyBindings != 0
469 for( std::vector
< DynamicStateProperties
* >::iterator i
= dynamicStateKeyValues_
->begin( ); i
!= dynamicStateKeyValues_
->end( ); ++i
)
476 delete dynamicStateKeyValues_
;
482 Kernel::Environment::setParent( Kernel::Environment
* parent
)
485 // unitMap_ = parent.unitMap_;
488 Kernel::Environment
*
489 Kernel::Environment::getParent( )
491 if( isBaseEnvironment( ) )
493 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level environment." );
498 const Kernel::Environment
*
499 Kernel::Environment::getParent( ) const
501 if( isBaseEnvironment( ) )
503 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level environment." );
509 Kernel::Environment::setupDynamicKeyVariables( MapType
* dynamicKeyBindings
)
511 if( dynamicKeyBindings_
== 0 )
513 dynamicKeyBindings_
= dynamicKeyBindings
;
514 dynamicKeyValues_
= new std::vector
< DynamicVariableProperties
* >;
519 if( dynamicKeyBindings_
!= dynamicKeyBindings
)
521 throw Exceptions::InternalError( "Kernel::Environment::setupDynamicKeyVariables: dynamicKeyBindings_ != dynamicKeyBindings" );
525 size_t theSize
= dynamicKeyBindings_
->size( );
526 dynamicKeyValues_
->reserve( theSize
);
527 while( dynamicKeyValues_
->size( ) < theSize
)
529 dynamicKeyValues_
->push_back( 0 );
534 Kernel::Environment::setupDynamicStateKeyVariables( MapType
* dynamicStateKeyBindings
)
536 if( dynamicStateKeyBindings_
== 0 )
538 dynamicStateKeyBindings_
= dynamicStateKeyBindings
;
539 dynamicStateKeyValues_
= new std::vector
< DynamicStateProperties
* >;
544 if( dynamicStateKeyBindings_
!= dynamicStateKeyBindings
)
546 throw Exceptions::InternalError( "Kernel::Environment::setupDynamicStateKeyVariables: dynamicStateKeyBindings_ != dynamicStateKeyBindings" );
550 size_t theSize
= dynamicStateKeyBindings_
->size( );
551 dynamicStateKeyValues_
->reserve( theSize
);
552 while( dynamicStateKeyValues_
->size( ) < theSize
)
554 dynamicStateKeyValues_
->push_back( 0 );
559 Kernel::Environment::extendVectors( )
561 values_
->reserve( bindings_
->size( ) );
562 while( values_
->size( ) < bindings_
->size( ) )
564 values_
->push_back( NullPtr
< Kernel::Variable
>( ) );
567 states_
->reserve( stateBindings_
->size( ) );
568 while( states_
->size( ) < stateBindings_
->size( ) )
570 states_
->push_back( NullPtr
< Kernel::State
>( ) );
576 Kernel::Environment::activateFunctionBoundary( )
578 functionBoundary_
= true;
582 Kernel::Environment::clear( )
584 /* Strange that this is empty...
585 * The idea, though, is that the reference counting of this->values shall take care of deletion.
589 Ast::AnalysisEnvironment
*
590 Kernel::Environment::newAnalysisEnvironment( Ast::AnalysisEnvironment
* parent
) const
592 Ast::AnalysisEnvironment
* res
= new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList
, parent
, bindings_
, stateBindings_
);
593 if( dynamicKeyBindings_
!= 0 )
595 res
->setupDynamicKeyVariables( dynamicKeyBindings_
);
597 if( dynamicStateKeyBindings_
!= 0 )
599 res
->setupDynamicStateKeyVariables( dynamicStateKeyBindings_
);
606 Kernel::Environment::gcMark( Kernel::GCMarkedSet
& marked
)
613 marked
.insert( marked
.begin( ), this );
619 Kernel::Environment::collect( std::list
< Kernel::Environment
* > & garbageArea
)
621 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); ++i
)
623 (*i
)->clear_gcMarked( );
626 Kernel::GCMarkedSet marked
;
627 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); ++i
)
629 (*i
)->gcMark( marked
);
632 for( std::list
< Kernel::Environment
* >::iterator i
= garbageArea
.begin( ); i
!= garbageArea
.end( ); )
634 if( (*i
)->gcMarked( ) )
639 std::list
< Kernel::Environment
* >::iterator tmp
= i
;
642 garbageArea
.erase( tmp
);
647 Ast::StateID
Ast::AnalysisEnvironment::nextStateID
= 1;
649 Ast::AnalysisEnvironment::AnalysisEnvironment( PtrOwner_back_Access
< std::list
< Ast::AnalysisEnvironment
* > > & deleter
, Ast::AnalysisEnvironment
* parent
, const MapType
* bindings
, const MapType
* stateBindings
)
651 bindings_( bindings
), dynamicKeyBindings_( 0 ),
652 stateBindings_( stateBindings
), dynamicStateKeyBindings_( 0 ),
653 functionBoundary_( false )
655 deleter
.push_back( this );
659 Ast::AnalysisEnvironment::~AnalysisEnvironment( )
663 Ast::AnalysisEnvironment::updateBindings( )
665 states_
.reserve( stateBindings_
->size( ) );
666 while( states_
.size( ) < stateBindings_
->size( ) )
668 states_
.push_back( nextStateID
);
673 Ast::AnalysisEnvironment
*
674 Ast::AnalysisEnvironment::getParent( ) const
676 if( isBaseEnvironment( ) )
678 throw Exceptions::MiscellaneousRequirement( "Trying to find the parent of the top level analysis environment." );
684 Ast::AnalysisEnvironment::activateFunctionBoundary( )
686 functionBoundary_
= true;
690 Ast::AnalysisEnvironment::setupDynamicKeyVariables( const MapType
* dynamicKeyBindings
)
692 dynamicKeyBindings_
= dynamicKeyBindings
;
696 Ast::AnalysisEnvironment::setupDynamicStateKeyVariables( const MapType
* dynamicStateKeyBindings
)
698 dynamicStateKeyBindings_
= dynamicStateKeyBindings
;
702 Ast::AnalysisEnvironment::findLocalVariablePosition( const Ast::SourceLocation
& loc
, const char * id
) const
704 MapType::const_iterator i
= bindings_
->find( id
);
705 if( i
== bindings_
->end( ) )
707 throw Exceptions::InternalError( loc
, "Environment::findLocalPosition failed" );
713 Kernel::Environment::define( size_t pos
, const Kernel::VariableHandle
& val
)
715 if( (*values_
)[ pos
] != NullPtr
< Kernel::Variable
>( ) )
717 throw Exceptions::RedefiningLexical( reverseMapVariable( pos
) );
720 (*values_
)[ pos
] = val
;
723 Kernel::Environment::LexicalKey
724 Ast::AnalysisEnvironment::findLexicalVariableKey( const Ast::SourceLocation
& loc
, const char * id
) const
726 MapType::const_iterator i
= bindings_
->find( id
);
727 if( i
== bindings_
->end( ) )
729 if( isBaseEnvironment( ) )
731 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, strrefdup( id
), Exceptions::LookupUnknown::VARIABLE
) );
732 return Kernel::Environment::theMissingKey
;
734 return parent_
->findLexicalVariableKey( loc
, id
).oneAbove( );
737 return LexicalKey( 0, i
->second
);
741 Kernel::Environment::lookup( const Kernel::Environment::LexicalKey
& lexKey
, Kernel::EvalState
* evalState
) const
743 const Environment
* env
= this;
744 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
746 env
= env
->getParent( );
749 env
->lookup( lexKey
.pos_
, evalState
);
753 Kernel::Environment::lookup( size_t pos
, Kernel::EvalState
* evalState
) const
755 Kernel::VariableHandle res
= (*values_
)[ pos
];
756 if( res
== NullPtr
< Kernel::Variable
>( ) )
758 throw Exceptions::UninitializedAccess( );
761 Kernel::ContRef cont
= evalState
->cont_
;
762 cont
->takeHandle( res
, evalState
);
765 Kernel::VariableHandle
766 Kernel::Environment::getVarHandle( const Kernel::Environment::LexicalKey
& lexKey
)
768 Environment
* env
= this;
769 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
771 env
= env
->getParent( );
774 return env
->getVarHandle( lexKey
.pos_
);
777 Kernel::VariableHandle
778 Kernel::Environment::getVarHandle( size_t pos
)
780 return (*values_
)[ pos
];
783 Kernel::Environment::LexicalKey
784 Ast::AnalysisEnvironment::findLexicalTypeKey( const Ast::SourceLocation
& loc
, const char * id
) const
786 MapType::const_iterator i
= bindings_
->find( id
);
787 if( i
== bindings_
->end( ) )
789 if( isBaseEnvironment( ) )
791 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, strrefdup( id
), Exceptions::LookupUnknown::TYPE
) );
792 return Kernel::Environment::theMissingKey
;
794 return parent_
->findLexicalTypeKey( loc
, id
).oneAbove( );
797 return LexicalKey( 0, i
->second
);
802 Ast::AnalysisEnvironment::findLocalStatePosition( const Ast::SourceLocation
& loc
, const char * id
) const
804 MapType::const_iterator i
= stateBindings_
->find( id
);
805 if( i
== stateBindings_
->end( ) )
807 throw Exceptions::InternalError( loc
, "Environment::findLocalStatePosition failed" );
812 Kernel::Environment::LexicalKey
813 Ast::AnalysisEnvironment::findLexicalStateKey( const Ast::SourceLocation
& loc
, const char * id
) const
815 MapType::const_iterator i
= stateBindings_
->find( id
);
816 if( i
== stateBindings_
->end( ) )
818 if( isBaseEnvironment( ) )
820 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, strrefdup( id
), Exceptions::LookupUnknown::STATE
) );
821 return Kernel::Environment::theMissingKey
;
823 if( functionBoundary_
)
825 // If the state is not found at all, this will throw an error.
826 parent_
->findLexicalStateKey( loc
, id
).oneAbove( ); // Ignore the result!
827 // If no error is thrown, we inform the user that the state is outside a function boundary.
828 Ast::theAnalysisErrorsList
.push_back( new Exceptions::StateBeyondFunctionBoundary( loc
, strrefdup( id
) ) );
829 return Kernel::Environment::theMissingKey
;
831 return parent_
->findLexicalStateKey( loc
, id
).oneAbove( );
834 return LexicalKey( 0, i
->second
);
838 Ast::AnalysisEnvironment::getStateID( const LexicalKey
& lexKey
) const
840 const Ast::AnalysisEnvironment
* env
= this;
841 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
843 env
= env
->getParent( );
846 return env
->getStateID( lexKey
.pos_
);
850 Ast::AnalysisEnvironment::getStateID( size_t pos
) const
852 return states_
[ pos
];
856 Ast::AnalysisEnvironment::getTheAnyStateID( )
862 Kernel::Environment::introduceState( size_t pos
, Kernel::State
* state
)
864 if( (*states_
)[ pos
] != NullPtr
< Kernel::State
>( ) )
866 throw Exceptions::InternalError( "Better error message needed when a state is introduced more than once." );
867 // throw Exceptions::RedefiningLexical( reverseMap( pos ) );
870 (*states_
)[ pos
] = state
;
874 Kernel::Environment::freeze( size_t pos
, Kernel::EvalState
* evalState
, const Ast::SourceLocation
& loc
)
876 if( (*states_
)[ pos
] == NullPtr
< Kernel::State
>( ) )
878 // This is a static inconsistency, so it should be detected before we reach here...
879 throw Exceptions::FreezingUndefined( loc
, reverseMapState( pos
) );
882 Kernel::StateHandle
& state
= (*states_
)[ pos
];
884 state
->freeze( evalState
, loc
);
888 Kernel::Environment::peek( const LexicalKey
& lexKey
, Kernel::EvalState
* evalState
, const Ast::SourceLocation
& loc
)
890 getStateHandle( lexKey
)->peek( evalState
, loc
);
894 Kernel::Environment::tackOn( const LexicalKey
& lexKey
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
, const Ast::SourceLocation
& callLoc
)
896 getStateHandle( lexKey
)->tackOn( evalState
, piece
, callLoc
);
900 Kernel::Environment::getStateHandle( const LexicalKey
& lexKey
)
902 Environment
* env
= this;
903 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
905 env
= env
->getParent( );
908 return env
->getStateHandle( lexKey
.pos_
);
912 Kernel::Environment::getStateHandle( size_t pos
)
914 Kernel::StateHandle res
= (*states_
)[ pos
];
915 if( res
== NullPtr
< Kernel::State
>( ) )
917 throw Exceptions::UninitializedAccess( );
925 Ast::AnalysisEnvironment::findLocalDynamicPosition( const Ast::SourceLocation
& loc
, const char * id
) const
927 if( dynamicKeyBindings_
== 0 )
929 throw Exceptions::InternalError( "Environment::findLocalDynamicPosition called with dynamicKeyBindings_ == 0." );
931 MapType::const_iterator i
= dynamicKeyBindings_
->find( id
);
932 if( i
== dynamicKeyBindings_
->end( ) )
934 throw Exceptions::InternalError( loc
, "Environment::findLocalDynamicPosition failed" );
940 Kernel::Environment::defineDynamic( const char * debugName
, size_t pos
, const RefCountPtr
< const Lang::Function
> & filter
, const Kernel::VariableHandle
& defaultVal
)
942 if( dynamicKeyValues_
== 0 )
944 throw Exceptions::InternalError( "Environment::defineDynamic called with dynamicKeyValues_ == 0." );
946 if( pos
> dynamicKeyValues_
->size( ) )
948 throw Exceptions::InternalError( "Environment::defineDynamic called with pos out of range." );
950 if( (*dynamicKeyValues_
)[ pos
] != 0 )
952 throw Exceptions::RedefiningDynamic( reverseMapDynamic( pos
) );
955 (*dynamicKeyValues_
)[ pos
] = new Kernel::UserDynamicVariableProperties( debugName
,
956 Kernel::DynamicEnvironment::getFreshKey( ),
961 Kernel::Environment::LexicalKey
962 Ast::AnalysisEnvironment::findLexicalDynamicKey( const Ast::SourceLocation
& loc
, const char * id
) const
964 if( dynamicKeyBindings_
== 0 )
966 if( isBaseEnvironment( ) )
970 return parent_
->findLexicalDynamicKey( loc
, id
).oneAbove( );
973 MapType::const_iterator i
= dynamicKeyBindings_
->find( id
);
974 if( i
== dynamicKeyBindings_
->end( ) )
976 if( isBaseEnvironment( ) )
980 return parent_
->findLexicalDynamicKey( loc
, id
).oneAbove( );
983 return LexicalKey( 0, i
->second
);
987 char * msg
= new char[ strlen( id
) + 2 ];
989 strcpy( msg
+ 1, id
);
990 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, RefCountPtr
< const char >( msg
), Exceptions::LookupUnknown::DYNAMIC_VARIABLE
) );
991 return Kernel::Environment::theMissingKey
;
995 const Kernel::DynamicVariableProperties
&
996 Kernel::Environment::lookupDynamicVariable( const LexicalKey
& lexKey
) const
998 const Environment
* env
= this;
999 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1001 env
= env
->getParent( );
1004 return env
->lookupDynamicVariable( lexKey
.pos_
);
1007 const Kernel::DynamicVariableProperties
&
1008 Kernel::Environment::lookupDynamicVariable( size_t pos
) const
1010 const DynamicVariableProperties
* res
= (*dynamicKeyValues_
)[ pos
];
1013 throw Exceptions::UninitializedAccess( );
1019 Ast::AnalysisEnvironment::findLocalDynamicStatePosition( const Ast::SourceLocation
& loc
, const char * id
) const
1021 if( dynamicStateKeyBindings_
== 0 )
1023 throw Exceptions::InternalError( "Environment::findLocalDynamicStatePosition called with dynamicStateKeyBindings_ == 0." );
1025 MapType::const_iterator i
= dynamicStateKeyBindings_
->find( id
);
1026 if( i
== dynamicStateKeyBindings_
->end( ) )
1028 throw Exceptions::InternalError( loc
, "Environment::findLocalDynamicStatePosition failed" );
1034 Kernel::Environment::defineDynamicState( const char * debugName
, size_t pos
, Kernel::EvalState
* evalState
, Ast::StateReference
* defaultState
)
1036 if( dynamicStateKeyValues_
== 0 )
1038 throw Exceptions::InternalError( "Environment::defineDynamicState called with dynamicStateKeyValues_ == 0." );
1040 if( pos
> dynamicStateKeyValues_
->size( ) )
1042 throw Exceptions::InternalError( "Environment::defineDynamicState called with pos out of range." );
1044 if( (*dynamicStateKeyValues_
)[ pos
] != 0 )
1046 throw Exceptions::RedefiningDynamic( reverseMapDynamicState( pos
) );
1049 (*dynamicStateKeyValues_
)[ pos
] = new Kernel::UserDynamicStateProperties( debugName
,
1050 Kernel::DynamicEnvironment::getFreshKey( ),
1057 Kernel::Environment::LexicalKey
1058 Ast::AnalysisEnvironment::findLexicalDynamicStateKey( const Ast::SourceLocation
& loc
, const char * id
) const
1060 if( dynamicStateKeyBindings_
== 0 )
1062 return parent_
->findLexicalDynamicStateKey( loc
, id
).oneAbove( );
1065 MapType::const_iterator i
= dynamicStateKeyBindings_
->find( id
);
1066 if( i
== dynamicStateKeyBindings_
->end( ) )
1068 if( isBaseEnvironment( ) )
1070 char * msg
= new char[ strlen( id
) + 2 ];
1071 strcpy( msg
, "@#" );
1072 strcpy( msg
+ 1, id
);
1073 Ast::theAnalysisErrorsList
.push_back( new Exceptions::LookupUnknown( loc
, RefCountPtr
< const char >( msg
), Exceptions::LookupUnknown::DYNAMIC_STATE
) );
1074 return Kernel::Environment::theMissingKey
;
1076 return parent_
->findLexicalDynamicStateKey( loc
, id
).oneAbove( );
1079 return LexicalKey( 0, i
->second
);
1082 const Kernel::DynamicStateProperties
&
1083 Kernel::Environment::lookupDynamicState( const LexicalKey
& lexKey
) const
1085 const Environment
* env
= this;
1086 for( size_t i
= lexKey
.up_
; i
> 0; --i
)
1088 env
= env
->getParent( );
1091 return env
->lookupDynamicState( lexKey
.pos_
);
1094 const Kernel::DynamicStateProperties
&
1095 Kernel::Environment::lookupDynamicState( size_t pos
) const
1097 const DynamicStateProperties
* res
= (*dynamicStateKeyValues_
)[ pos
];
1100 throw Exceptions::UninitializedAccess( );
1106 Kernel::Environment::reverseMapVariable( size_t pos
) const
1108 for( MapType::const_iterator i
= bindings_
->begin( ); i
!= bindings_
->end( ); ++i
)
1110 if( i
->second
== pos
)
1115 throw Exceptions::InternalError( "Environment::reverseMapVariable failure." );
1119 Kernel::Environment::reverseMapDynamic( size_t pos
) const
1121 for( MapType::const_iterator i
= dynamicKeyBindings_
->begin( ); i
!= dynamicKeyBindings_
->end( ); ++i
)
1123 if( i
->second
== pos
)
1128 throw Exceptions::InternalError( "Environment::reverseMapDynamic failure." );
1132 Kernel::Environment::reverseMapState( size_t pos
) const
1134 for( MapType::const_iterator i
= stateBindings_
->begin( ); i
!= stateBindings_
->end( ); ++i
)
1136 if( i
->second
== pos
)
1141 throw Exceptions::InternalError( "Environment::reverseMapState failure." );
1145 Kernel::Environment::reverseMapDynamicState( size_t pos
) const
1147 for( MapType::const_iterator i
= dynamicStateKeyBindings_
->begin( ); i
!= dynamicStateKeyBindings_
->end( ); ++i
)
1149 if( i
->second
== pos
)
1154 throw Exceptions::InternalError( "Environment::reverseMapDynamicState failure." );
1159 Kernel::Environment::size( ) const
1161 return bindings_
->size( );
1166 Kernel::Environment::print( std::ostream
& os
) const
1168 std::set
< MapType::key_type
> shadowed
;
1169 std::set
< MapType::key_type
> shadowedStates
;
1170 recursivePrint( os
, & shadowed
, & shadowedStates
);
1174 Kernel::Environment::recursivePrint( std::ostream
& os
, std::set
< MapType::key_type
> * shadowed
, std::set
< MapType::key_type
> * shadowedStates
) const
1176 std::set
< MapType::key_type
> shadowedBefore( *shadowed
);
1177 std::set
< MapType::key_type
> shadowedStatesBefore( *shadowedStates
);
1180 if( ! isBaseEnvironment( ) )
1182 for( MapType::const_iterator i
= bindings_
->begin( ); i
!= bindings_
->end( ); ++i
)
1184 shadowed
->insert( shadowed
->begin( ), i
->first
);
1186 for( MapType::const_iterator i
= stateBindings_
->begin( ); i
!= stateBindings_
->end( ); ++i
)
1188 shadowedStates
->insert( shadowedStates
->begin( ), i
->first
);
1190 depth
= parent_
->recursivePrint( os
, shadowed
, shadowedStates
) + 1;
1193 std::string indentation
= std::string( depth
, ' ' );
1196 for( size_t tmp
= bindings_
->size( ); tmp
>= 10; tmp
/= 10, ++width
)
1200 size_t tmp
= ( 29 - 4 ) - strlen( debugName_
);
1201 if( tmp
< 2 || tmp
> 29 ) /* the latter case corresponds to an underflow in the subtraction */
1205 os
<< indentation
<< std::string( tmp
/ 2, '-' ) << "( " << debugName_
<< " )" << std::string( tmp
- tmp
/ 2, '-' ) << std::endl
;
1207 if( ! isBaseEnvironment( ) )
1209 for( MapType::const_iterator i
= bindings_
->begin( ); i
!= bindings_
->end( ); ++i
)
1211 os
<< indentation
<< std::setw(width
) << i
->second
;
1212 if( shadowedBefore
.find( i
->first
) != shadowedBefore
.end( ) )
1220 os
<< " " << i
->first
<< " : " ;
1221 if( (*values_
)[ i
->second
] == NullPtr
< Kernel::Variable
>( ) )
1223 os
<< "< Uninitialized >" ;
1225 else if( (*values_
)[ i
->second
]->isThunk( ) )
1229 else if( dynamic_cast< const Lang::Instance
* >( (*values_
)[ i
->second
]->getUntyped( ).getPtr( ) ) == 0 )
1231 (*values_
)[ i
->second
]->getUntyped( )->show( os
);
1239 for( MapType::const_iterator i
= stateBindings_
->begin( ); i
!= stateBindings_
->end( ); ++i
)
1241 os
<< indentation
<< std::setw(width
) << i
->second
;
1242 if( shadowedStatesBefore
.find( i
->first
) != shadowedStatesBefore
.end( ) )
1250 os
<< " " << Interaction::STATE_PREFIX
<< i
->first
<< " :: " ;
1251 if( (*states_
)[ i
->second
] == NullPtr
< Kernel::State
>( ) )
1253 os
<< "< Uninitialized >" ;
1257 os
<< (*states_
)[ i
->second
]->getTypeName( ) ;
1264 os
<< indentation
<< "<< global env >>" << std::endl
;
1267 os
<< indentation
<< "-- -- -- -- -- -- -- -- -- --" << std::endl
;