Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / environment.cc
blob6a8dd0991d53e8c5aabddbcab296fa1f7626cb93
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include <cmath>
20 #include <iomanip>
22 #include "environment.h"
23 #include "shapesexceptions.h"
24 #include "shapescore.h"
25 #include "consts.h"
26 #include "globals.h"
27 #include "shapesvalue.h"
28 #include "classtypes.h"
29 #include "hottypes.h"
30 #include "continuations.h"
31 #include "statetypes.h"
32 #include "multipage.h"
33 #include "errorhandlers.h"
34 #include "debuglog.h"
35 #include "check.h"
37 using namespace Shapes;
40 size_t Kernel::Environment::createdCount = 0;
41 size_t Kernel::Environment::liveCount = 0;
42 Kernel::Environment::LexicalKey Kernel::Environment::theMissingKey( 0, std::numeric_limits< size_t >::max( ) );
44 template< class T >
45 class Binary
47 public:
48 T val;
49 Binary( const T & _val ) : val( _val ) { }
52 template< class T >
53 std::ostream &
54 operator << ( std::ostream & os, const Binary< T > & self )
56 for( int i = 8*sizeof( T ) - 1; i >= 0; --i )
58 if( (( self.val & (T(1)<<i) )) != 0 )
60 os << 1 ;
62 else
64 os << '_' ;
67 return os;
72 Kernel::Thunk::Thunk( Kernel::PassedEnv env, Kernel::PassedDyn dyn, Ast::Expression * expr )
73 : env_( env ), dyn_( dyn ), expr_( expr ), forced_( false )
74 { }
76 void
77 Kernel::Thunk::force( Kernel::EvalState * evalState, bool onlyOnce ) const
79 if( onlyOnce )
81 if( forced_ )
83 throw Exceptions::InternalError( "It's unwise to force a thunk twice! It should be deleted right after the first force." );
85 forced_ = true;
88 evalState->expr_ = expr_;
89 evalState->env_ = env_;
90 evalState->dyn_ = dyn_;
92 /* The continuation is not se by the thunk! */
95 Kernel::Thunk *
96 Kernel::Thunk::deepCopy( )
98 return new Thunk( env_, dyn_, expr_ );
102 void
103 Kernel::Thunk::gcMark( Kernel::GCMarkedSet & marked )
105 if( ! forced_ )
107 env_->gcMark( marked );
108 dyn_->gcMark( marked );
112 Ast::Expression *
113 Kernel::Thunk::getExpr( )
115 return expr_;
118 void
119 Kernel::Thunk::printEnv( std::ostream & os ) const
121 env_->print( os );
125 Kernel::Variable::Variable( const RefCountPtr< const Lang::Value > & val )
126 : thunk_( 0 ), val_( val ), state_( Kernel::Variable::COLD )
129 Kernel::Variable::Variable( Kernel::Thunk * thunk )
130 : thunk_( thunk ), val_( NullPtr< const Lang::Value >( ) ), state_( Kernel::Variable::THUNK )
133 Kernel::Variable::~Variable( )
135 if( thunk_ != 0 )
137 delete thunk_;
141 Kernel::State::State( )
142 : alive_( true )
145 Kernel::State::~State( )
148 void
149 Kernel::State::tackOn( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
151 if( ! alive_ )
153 throw Exceptions::DeadStateAccess( );
155 this->tackOnImpl( evalState, piece, callLoc );
158 void
159 Kernel::State::peek( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
161 if( ! alive_ )
163 throw Exceptions::DeadStateAccess( );
165 this->peekImpl( evalState, callLoc );
168 void
169 Kernel::State::freeze( Kernel::EvalState * evalState, const Ast::SourceLocation & callLoc )
171 if( ! alive_ )
173 throw Exceptions::DeadStateAccess( );
175 /* It would make sense to have an intermediate state here.
177 alive_ = false;
179 // Perhaps, it would be smart to use a continuation to erase the implementation once it is used...
180 // evalState->cont_ = Kernel::ContRef( new Kernel::StmtStoreVariableContinuation( selfRef, evalState->cont_, callLoc ) );
182 this->freezeImpl( evalState, callLoc );
185 RefCountPtr< const Lang::Function >
186 Kernel::State::getMutator( const char * mutatorID )
188 return getClass( )->getMutator( mutatorID );
191 RefCountPtr< const char >
192 Kernel::State::getTypeName( ) const
194 return this->getClass( )->getPrettyName( );
197 bool
198 Kernel::State::isAlive( ) const
200 return alive_;
204 void
205 Kernel::Variable::force( 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 );
212 delete thunk_;
213 thunk_ = 0;
214 return;
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." );
235 return val_;
239 bool
240 Kernel::Variable::isThunk( ) const
242 return ( state_ & Kernel::Variable::FORCING ) != 0;
245 Kernel::Thunk *
246 Kernel::Variable::copyThunk( ) const
248 if( thunk_ == 0 )
250 throw Exceptions::InternalError( "Variable::copyThunk: There was no thunk to copy." );
252 return thunk_->deepCopy( );
255 void
256 Kernel::Variable::gcMark( Kernel::GCMarkedSet & marked )
258 if( thunk_ != 0 )
260 thunk_->gcMark( marked );
261 return;
263 if( val_ != NullPtr< const Lang::Value >( ) )
265 const_cast< Lang::Value * >( val_.getPtr( ) )->gcMark( marked );
269 void
270 Kernel::Variable::setValue( const RefCountPtr< const Lang::Value > & val ) const
272 val_ = val;
273 state_ = Kernel::Variable::COLD;
277 Kernel::DynamicVariableProperties::~DynamicVariableProperties( )
280 Kernel::DynamicStateProperties::~DynamicStateProperties( )
284 void
285 Kernel::Environment::initDefineCoreFunction( Lang::CoreFunction * fun )
287 initDefineHandle( fun->getTitle( ), Kernel::VariableHandle( new Kernel::Variable( RefCountPtr< const Lang::Value >( fun ) ) ) );
290 void
291 Kernel::Environment::initDefineCoreFunction( RefCountPtr< const Lang::CoreFunction > fun )
293 initDefineHandle( fun->getTitle( ), Kernel::VariableHandle( new Kernel::Variable( fun ) ) );
296 void
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 );
313 void
314 Kernel::Environment::initDefine( const char * id, const RefCountPtr< const Lang::Value > & val )
316 initDefineHandle( id, Kernel::VariableHandle( new Kernel::Variable( val ) ) );
319 void
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 );
336 void
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 ) ) );
345 void
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 );
362 void
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 ) );
376 void
377 Kernel::Environment::initDefineDynamicHandler( const char * id, const char * msg )
379 initDefineDynamic( id,
380 Lang::THE_IDENTITY,
381 Helpers::newValHandle( new Lang::ExceptionWrapper< Exceptions::HandlerError >( id, msg ) ) );
384 Kernel::Environment::Environment( std::list< Kernel::Environment * > & garbageArea, const char * debugName )
385 : parent_( 0 ),
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 );
398 ++createdCount;
399 ++liveCount;
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 )
403 : parent_( parent ),
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 )
412 // {
413 // unitMap_ = parent->unitMap_;
414 // }
415 ++createdCount;
416 ++liveCount;
419 Kernel::Environment::~Environment( )
421 clear( );
422 if( dynamicKeyBindings_ != 0 )
424 if( parent_ == 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 )
434 if( *i != 0 )
436 delete *i;
439 delete dynamicKeyValues_;
441 if( stateBindings_ != 0 )
443 if( parent_ == 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 )
453 if( *i != 0 )
455 delete *i;
459 if( dynamicStateKeyBindings_ != 0 )
461 if( parent_ == 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 )
471 if( *i != 0 )
473 delete *i;
476 delete dynamicStateKeyValues_;
478 --liveCount;
481 void
482 Kernel::Environment::setParent( Kernel::Environment * parent )
484 parent_ = 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." );
495 return parent_;
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." );
505 return parent_;
508 void
509 Kernel::Environment::setupDynamicKeyVariables( MapType * dynamicKeyBindings )
511 if( dynamicKeyBindings_ == 0 )
513 dynamicKeyBindings_ = dynamicKeyBindings;
514 dynamicKeyValues_ = new std::vector< DynamicVariableProperties * >;
516 CHECK(
517 else
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 );
533 void
534 Kernel::Environment::setupDynamicStateKeyVariables( MapType * dynamicStateKeyBindings )
536 if( dynamicStateKeyBindings_ == 0 )
538 dynamicStateKeyBindings_ = dynamicStateKeyBindings;
539 dynamicStateKeyValues_ = new std::vector< DynamicStateProperties * >;
541 CHECK(
542 else
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 );
558 void
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 >( ) );
575 void
576 Kernel::Environment::activateFunctionBoundary( )
578 functionBoundary_ = true;
581 void
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_ );
602 return res;
605 void
606 Kernel::Environment::gcMark( Kernel::GCMarkedSet & marked )
608 if( gcMarked_ )
610 return;
612 gcMarked_ = true;
613 marked.insert( marked.begin( ), this );
615 values_->clear( );
618 void
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( ) )
636 ++i;
637 continue;
639 std::list< Kernel::Environment * >::iterator tmp = i;
640 ++i;
641 delete *tmp;
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 )
650 : parent_( parent ),
651 bindings_( bindings ), dynamicKeyBindings_( 0 ),
652 stateBindings_( stateBindings ), dynamicStateKeyBindings_( 0 ),
653 functionBoundary_( false )
655 deleter.push_back( this );
656 updateBindings( );
659 Ast::AnalysisEnvironment::~AnalysisEnvironment( )
662 void
663 Ast::AnalysisEnvironment::updateBindings( )
665 states_.reserve( stateBindings_->size( ) );
666 while( states_.size( ) < stateBindings_->size( ) )
668 states_.push_back( nextStateID );
669 ++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." );
680 return parent_;
683 void
684 Ast::AnalysisEnvironment::activateFunctionBoundary( )
686 functionBoundary_ = true;
689 void
690 Ast::AnalysisEnvironment::setupDynamicKeyVariables( const MapType * dynamicKeyBindings )
692 dynamicKeyBindings_ = dynamicKeyBindings;
695 void
696 Ast::AnalysisEnvironment::setupDynamicStateKeyVariables( const MapType * dynamicStateKeyBindings )
698 dynamicStateKeyBindings_ = dynamicStateKeyBindings;
701 size_t
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" );
709 return i->second;
712 void
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 );
740 void
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 );
752 void
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 );
801 size_t
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" );
809 return i->second;
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 );
837 Ast::StateID
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_ );
849 Ast::StateID
850 Ast::AnalysisEnvironment::getStateID( size_t pos ) const
852 return states_[ pos ];
855 Ast::StateID
856 Ast::AnalysisEnvironment::getTheAnyStateID( )
858 return -1;
861 void
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;
873 void
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 );
887 void
888 Kernel::Environment::peek( const LexicalKey & lexKey, Kernel::EvalState * evalState, const Ast::SourceLocation & loc )
890 getStateHandle( lexKey )->peek( evalState, loc );
893 void
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 );
899 Kernel::StateHandle
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_ );
911 Kernel::StateHandle
912 Kernel::Environment::getStateHandle( size_t pos )
914 Kernel::StateHandle res = (*states_)[ pos ];
915 if( res == NullPtr< Kernel::State >( ) )
917 throw Exceptions::UninitializedAccess( );
919 return res;
924 size_t
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" );
936 return i->second;
939 void
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( ),
957 filter,
958 defaultVal );
961 Kernel::Environment::LexicalKey
962 Ast::AnalysisEnvironment::findLexicalDynamicKey( const Ast::SourceLocation & loc, const char * id ) const
964 if( dynamicKeyBindings_ == 0 )
966 if( isBaseEnvironment( ) )
968 goto error;
970 return parent_->findLexicalDynamicKey( loc, id ).oneAbove( );
973 MapType::const_iterator i = dynamicKeyBindings_->find( id );
974 if( i == dynamicKeyBindings_->end( ) )
976 if( isBaseEnvironment( ) )
978 goto error;
980 return parent_->findLexicalDynamicKey( loc, id ).oneAbove( );
983 return LexicalKey( 0, i->second );
986 error:
987 char * msg = new char[ strlen( id ) + 2 ];
988 strcpy( msg, "@" );
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 ];
1011 if( res == 0 )
1013 throw Exceptions::UninitializedAccess( );
1015 return *res;
1018 size_t
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" );
1030 return i->second;
1033 void
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( ),
1051 evalState->env_,
1052 evalState->dyn_,
1053 defaultState );
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 ];
1098 if( res == 0 )
1100 throw Exceptions::UninitializedAccess( );
1102 return *res;
1105 const char *
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 )
1112 return i->first;
1115 throw Exceptions::InternalError( "Environment::reverseMapVariable failure." );
1118 const char *
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 )
1125 return i->first;
1128 throw Exceptions::InternalError( "Environment::reverseMapDynamic failure." );
1131 const char *
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 )
1138 return i->first;
1141 throw Exceptions::InternalError( "Environment::reverseMapState failure." );
1144 const char *
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 )
1151 return i->first;
1154 throw Exceptions::InternalError( "Environment::reverseMapDynamicState failure." );
1158 size_t
1159 Kernel::Environment::size( ) const
1161 return bindings_->size( );
1165 void
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 );
1173 size_t
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 );
1179 size_t depth = 0;
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, ' ' );
1195 size_t width = 1;
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 */
1203 tmp = 2;
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( ) )
1214 os << "^" ;
1216 else
1218 os << " " ;
1220 os << " " << i->first << " : " ;
1221 if( (*values_)[ i->second ] == NullPtr< Kernel::Variable >( ) )
1223 os << "< Uninitialized >" ;
1225 else if( (*values_)[ i->second ]->isThunk( ) )
1227 os << "< thunk >" ;
1229 else if( dynamic_cast< const Lang::Instance * >( (*values_)[ i->second ]->getUntyped( ).getPtr( ) ) == 0 )
1231 (*values_)[ i->second ]->getUntyped( )->show( os );
1233 else
1235 os << "..." ;
1237 os << std::endl ;
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( ) )
1244 os << "^" ;
1246 else
1248 os << " " ;
1250 os << " " << Interaction::STATE_PREFIX << i->first << " :: " ;
1251 if( (*states_)[ i->second ] == NullPtr< Kernel::State >( ) )
1253 os << "< Uninitialized >" ;
1255 else
1257 os << (*states_)[ i->second ]->getTypeName( ) ;
1259 os << std::endl ;
1262 else
1264 os << indentation << "<< global env >>" << std::endl ;
1267 os << indentation << "-- -- -- -- -- -- -- -- -- --" << std::endl ;
1269 return depth;