Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / astvar.cc
blobff6d81dec630dee3abafd315c474d41e9121052a
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 "astvar.h"
20 #include "shapesexceptions.h"
21 #include "globals.h"
22 #include "autoonoff.h"
23 #include "specialunits.h"
24 #include "astfun.h"
25 #include "continuations.h"
26 #include "containertypes.h"
27 #include "check.h"
29 #include <algorithm>
31 using namespace Shapes;
32 using namespace std;
35 Ast::SourceLocationMark::SourceLocationMark( const Ast::SourceLocation & loc )
36 : Ast::Node( loc )
37 { }
39 Ast::SourceLocationMark::~SourceLocationMark( )
40 { }
42 void
43 Ast::SourceLocationMark::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
44 { }
46 namespace Shapes
48 namespace Helpers
50 class IsSourceLocationMark
52 public:
53 bool operator () ( const Ast::Node * n ) const
55 return dynamic_cast< const Ast::SourceLocationMark * >( n ) != 0;
62 Ast::CodeBracket::CodeBracket( const Ast::SourceLocation & loc, std::list< Ast::Node * > * nodes, Ast::CodeBracket * extends )
63 : Ast::Expression( loc ), nodes_( nodes ), extends_( extends ),
64 argumentOrder_( ( extends == 0 ) ? ( new typeof *argumentOrder_ ) : ( extends->argumentOrder_ ) ),
65 dynamicMap_( ( extends == 0 ) ? ( 0 ) : ( extends->dynamicMap_ ) ),
66 stateOrder_( ( extends == 0 ) ? ( new typeof *stateOrder_ ) : ( extends->stateOrder_ ) )
68 /* First, we remove any source location marks -- we don't need them anymore. */
69 nodes_->remove_if( Helpers::IsSourceLocationMark( ) );
71 for( std::list< Ast::Node * >::const_iterator i = nodes_->begin( );
72 i != nodes_->end( );
73 ++i )
75 typedef const Ast::BindNode T;
76 T * tmp = dynamic_cast< T * >( *i );
77 if( tmp != 0 )
79 const char * name = tmp->id( );
81 typedef const Ast::DefineVariable T;
82 T * decl = dynamic_cast< T * >( tmp );
83 if( decl != 0 )
85 if( argumentOrder_->find( name ) != argumentOrder_->end( ) )
87 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExisting( tmp->idLoc( ), name ) );
88 continue;
90 argumentOrder_->insert( std::pair< const char *, size_t >( name, argumentOrder_->size( ) ) );
91 continue;
95 typedef const Ast::IntroduceState T;
96 T * decl = dynamic_cast< T * >( tmp );
97 if( decl != 0 )
99 if( stateOrder_->find( name ) != stateOrder_->end( ) )
101 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExisting( tmp->idLoc( ), name ) );
102 continue;
104 stateOrder_->insert( std::pair< const char *, size_t >( name, stateOrder_->size( ) ) );
105 continue;
109 typedef const Ast::DynamicVariableDecl T;
110 T * dynDecl = dynamic_cast< T * >( tmp );
111 if( dynDecl != 0 )
113 if( dynamicMap_ == 0 )
115 setDynamicMap( new std::map< const char *, size_t, charPtrLess > ); /* Sending the new map to extends_ recursively is important for memory management. */
117 if( dynamicMap_->find( name ) != dynamicMap_->end( ) )
119 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExisting( tmp->idLoc( ), name ) );
120 continue;
122 dynamicMap_->insert( std::pair< const char *, size_t >( name, dynamicMap_->size( ) ) );
123 continue;
130 void
131 Ast::CodeBracket::setDynamicMap( MapType * dynamicMap )
133 dynamicMap_ = dynamicMap;
134 if( extends_ != 0 )
136 extends_->setDynamicMap( dynamicMap );
140 Ast::CodeBracket::~CodeBracket( )
142 typedef list< Ast::Node * >::iterator I;
143 for( I i = nodes_->begin( ); i != nodes_->end( ); ++i )
145 delete *i;
147 delete nodes_;
149 if( extends_ == 0 )
151 /* If extends_ != 0, this object does not own the maps. */
152 delete argumentOrder_;
153 if( dynamicMap_ != 0 )
155 delete dynamicMap_;
157 delete stateOrder_;
161 void
162 Ast::CodeBracket::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * parentEnv, Ast::StateIDSet * freeStatesDst )
164 if( extends_ == 0 )
166 analysisEnv_ = new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList, parentEnv, argumentOrder_, stateOrder_ );
168 else
170 analysisEnv_ = extends_->analysisEnv_;
171 analysisEnv_->updateBindings( );
174 if( dynamicMap_ != 0 )
176 analysisEnv_->setupDynamicKeyVariables( dynamicMap_ );
180 Ast::StateIDSet allFreeStates;
181 Ast::StateIDSet introducedStates;
184 Ast::StateIDSet freeStates;
185 typedef list< Ast::Node * >::iterator I;
186 for( I i = nodes_->begin( ); i != nodes_->end( ); ++i )
188 freeStates.clear( );
189 (*i)->analyze( this, analysisEnv_, & freeStates );
190 if( ! freeStates.empty( ) )
192 typedef typeof freeStates SetType;
193 for( SetType::const_iterator j = freeStates.begin( ); j != freeStates.end( ); ++j )
195 allFreeStates.insert( *j );
198 else
200 Ast::Expression * expr = dynamic_cast< Ast::Expression * >( *i );
201 if( expr != 0 && ! expr->immediate_ )
203 I tmp = i;
204 ++tmp;
205 if( tmp != nodes_->end( ) )
207 Ast::theAnalysisErrorsList.push_back( new Exceptions::ExpectedImmediate( (*i)->loc( ) ) );
211 Ast::IntroduceState * introduceStateExpr = dynamic_cast< Ast::IntroduceState * >( *i );
212 if( introduceStateExpr != 0 )
214 introducedStates.insert( introduceStateExpr->getStateID( ) );
219 if( ! introducedStates.empty( ) )
221 Ast::StateIDSet diff;
222 std::set_difference( allFreeStates.begin( ), allFreeStates.end( ),
223 introducedStates.begin( ), introducedStates.end( ),
224 std::inserter( diff, diff.begin( ) ) );
225 allFreeStates.swap( diff );
227 if( ! allFreeStates.empty( ) )
229 typedef typeof allFreeStates SetType;
230 for( SetType::const_iterator j = allFreeStates.begin( ); j != allFreeStates.end( ); ++j )
232 freeStatesDst->insert( *j );
237 void
238 Ast::CodeBracket::eval( Kernel::EvalState * evalState ) const
240 if( nodes_->begin( ) == nodes_->end( ) )
242 Kernel::ContRef cont = evalState->cont_;
243 cont->takeValue( Lang::THE_VOID,
244 evalState );
245 return;
248 evalState->env_ = newEnvironment( evalState->env_ );
250 if( dynamicMap_ != 0 )
252 evalState->env_->setupDynamicKeyVariables( dynamicMap_ );
255 RefCountPtr< const Kernel::CodeBracketContInfo > info( new Kernel::CodeBracketContInfo( this, *evalState ) );
257 evalAt( info, nodes_->begin( ), evalState );
260 Kernel::Environment *
261 Ast::CodeBracket::newEnvironment( Kernel::Environment * parent, const char * debugName ) const
263 CHECK(
264 if( extends_ != 0 )
266 throw Exceptions::InternalError( "Ast::CodeBracket::newEnvironment( ): extends_ != 0" );
269 std::vector< Kernel::VariableHandle > * envValues = new std::vector< Kernel::VariableHandle >;
270 envValues->reserve( argumentOrder_->size( ) );
271 while( envValues->size( ) < argumentOrder_->size( ) )
273 envValues->push_back( NullPtr< Kernel::Variable >( ) );
276 std::vector< Kernel::StateHandle > * envStates = new std::vector< Kernel::StateHandle >;
277 envStates->reserve( stateOrder_->size( ) );
278 while( envStates->size( ) < stateOrder_->size( ) )
280 envStates->push_back( NullPtr< Kernel::State >( ) );
283 return new Kernel::Environment( Kernel::theEnvironmentList, parent, argumentOrder_, RefCountPtr< std::vector< Kernel::VariableHandle > >( envValues ), stateOrder_, RefCountPtr< std::vector< Kernel::StateHandle > >( envStates ), debugName );
286 void
287 Ast::CodeBracket::eval( Kernel::EvalState * evalState, Kernel::Environment * extendsEnv ) const
289 if( nodes_->begin( ) == nodes_->end( ) )
291 Kernel::ContRef cont = evalState->cont_;
292 cont->takeValue( Lang::THE_VOID,
293 evalState );
294 return;
297 evalState->env_ = extendsEnv;
298 if( dynamicMap_ != 0 )
300 evalState->env_->setupDynamicKeyVariables( dynamicMap_ );
302 evalState->env_->extendVectors( );
304 RefCountPtr< const Kernel::CodeBracketContInfo > info( new Kernel::CodeBracketContInfo( this, *evalState ) );
306 evalAt( info, nodes_->begin( ), evalState );
309 void
310 Ast::CodeBracket::evalAt( const RefCountPtr< const Kernel::CodeBracketContInfo > & info, const std::list< Ast::Node * >::const_iterator & pos, Kernel::EvalState * evalState ) const
312 Ast::Expression * e = dynamic_cast< Ast::Expression * >( *pos );
314 std::list< Ast::Node * >::const_iterator next = pos;
315 ++next;
316 if( next == nodes_->end( ) )
318 if( e != 0 &&
319 e->immediate_ )
321 evalState->cont_ = Kernel::ContRef( new Kernel::ForcingContinuation( info->cont_, (*pos)->loc( ) ) );
323 else
325 evalState->cont_ = info->cont_;
328 else
330 evalState->cont_ = Kernel::ContRef( new Kernel::CodeBracketContinuation( (*pos)->loc( ), info, next ) );
333 evalState->env_ = info->env_;
334 evalState->dyn_ = info->dyn_;
335 if( e != 0 )
337 evalState->expr_ = e;
338 return;
340 const Ast::BindNode * bn = dynamic_cast< const Ast::BindNode * >( *pos );
341 if( bn != 0 )
343 bn->evalHelper( evalState );
344 return;
346 throw Exceptions::InternalError( (*pos)->loc( ), "CodeBracket::evalAt: Node was neither Expression or BindNode." );
350 Kernel::CodeBracketContInfo::CodeBracketContInfo( const Ast::CodeBracket * bracketExpr, const Kernel::EvalState & evalState )
351 : bracketExpr_( bracketExpr ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
354 Kernel::CodeBracketContInfo::~CodeBracketContInfo( )
357 void
358 Kernel::CodeBracketContInfo::gcMark( Kernel::GCMarkedSet & marked )
360 env_->gcMark( marked );
361 dyn_->gcMark( marked );
362 cont_->gcMark( marked );
365 Kernel::CodeBracketContinuation::CodeBracketContinuation( const Ast::SourceLocation & traceLoc, const RefCountPtr< const Kernel::CodeBracketContInfo > & info, const std::list< Ast::Node * >::const_iterator & pos )
366 : Kernel::Continuation( traceLoc ), info_( info ), pos_( pos )
369 Kernel::CodeBracketContinuation::~CodeBracketContinuation( )
372 void
373 Kernel::CodeBracketContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
375 if( val.down_cast< const Lang::Void >( ) == NullPtr< const Lang::Void >( ) )
377 throw Exceptions::NonVoidStatement( traceLoc_, val );
379 info_->bracketExpr_->evalAt( info_,
380 pos_,
381 evalState );
384 Kernel::ContRef
385 Kernel::CodeBracketContinuation::up( ) const
387 return info_->cont_;
390 RefCountPtr< const char >
391 Kernel::CodeBracketContinuation::description( ) const
393 return strrefdup( "code bracket" );
396 void
397 Kernel::CodeBracketContinuation::gcMark( Kernel::GCMarkedSet & marked )
399 const_cast< Kernel::CodeBracketContInfo * >( info_.getPtr( ) )->gcMark( marked );
403 Ast::LexiographicVariable::LexiographicVariable( const Ast::SourceLocation & loc, const char * id, Kernel::Environment::LexicalKey ** idKey )
404 : Ast::Expression( loc ), id_( id ), idKey_( idKey )
406 immediate_ = true;
409 Ast::LexiographicVariable::~LexiographicVariable( )
411 delete id_;
412 if( *idKey_ != 0 )
414 delete *idKey_;
416 delete idKey_; // This can be done only as long as this is not shared!
419 void
420 Ast::LexiographicVariable::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
422 if( *idKey_ == 0 )
424 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalVariableKey( loc_, id_ ) );
428 void
429 Ast::LexiographicVariable::eval( Kernel::EvalState * evalState ) const
431 evalState->env_->lookup( **idKey_, evalState );
435 Ast::EvalOutsideExpr::EvalOutsideExpr( const Ast::SourceLocation & loc, Ast::Expression * expr )
436 : Ast::Expression( loc ), expr_( expr )
438 immediate_ = true;
441 Ast::EvalOutsideExpr::~EvalOutsideExpr( )
443 delete expr_;
446 void
447 Ast::EvalOutsideExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
449 expr_->analyze( this, env->getParent( ), freeStatesDst );
452 void
453 Ast::EvalOutsideExpr::eval( Kernel::EvalState * evalState ) const
455 evalState->expr_ = expr_;
456 evalState->env_ = evalState->env_->getParent( );
460 Ast::MemberReferenceFunction::MemberReferenceFunction( const Ast::SourceLocation & loc, Ast::Expression * variable, const char * fieldID )
461 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<>.<>" ), true ) ), loc_( loc ), variable_( variable ), fieldID_( fieldID )
464 Ast::MemberReferenceFunction::~MemberReferenceFunction( )
466 delete variable_;
467 delete fieldID_;
470 void
471 Ast::MemberReferenceFunction::push_exprs( Ast::ArgListExprs * args ) const
473 args->orderedExprs_->push_back( variable_ );
476 void
477 Ast::MemberReferenceFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
479 /* The variable is analyzed as part of the arguments passed to this function, so nothing needs to be done here...
480 * unless we would be able to figure out the type of the argument, and then check if the field reference is valid.
484 void
485 Ast::MemberReferenceFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
487 Kernel::ContRef cont = evalState->cont_;
488 RefCountPtr< const Lang::Value > arg = args.getValue( 0 );
489 cont->takeHandle( arg->getField( fieldID_, arg ),
490 evalState );
495 Ast::MutatorReference::MutatorReference( const Ast::SourceLocation & mutatorLoc, Ast::StateReference * state, const char * mutatorID )
496 : Ast::Expression( mutatorLoc ), mutatorLoc_( mutatorLoc ), state_( state ), mutatorID_( mutatorID )
499 Ast::MutatorReference::~MutatorReference( )
501 /* At the time of implementing this bug-fix, state_ will allways be owned by the Ast::CallExpr that is also the owner of us.
502 * Hence, we do not consider ourselves owners. Perhaps one should have a flag indicating whether ownership is transferred
503 * when calling the constructor, but at the moment this seems like a waste of resources.
505 // delete state_;
506 delete mutatorID_;
509 void
510 Ast::MutatorReference::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
512 state_->analyze( this, env, freeStatesDst );
513 /* If the type of the state was known here, we should verify that there is a mutator corresponding to the message <mutatorID>.
517 void
518 Ast::MutatorReference::eval( Kernel::EvalState * evalState ) const
520 Kernel::ContRef cont = evalState->cont_;
521 cont->takeValue( state_->getHandle( evalState->env_, evalState->dyn_ )->getMutator( mutatorID_ ),
522 evalState );
527 Ast::SpecialLength::SpecialLength( const Ast::SourceLocation & loc, double val, int sort )
528 : Ast::Expression( loc ), val_( val ), sort_( sort )
531 Ast::SpecialLength::~SpecialLength( )
534 void
535 Ast::SpecialLength::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
537 /* Nothing to do! */
540 void
541 Ast::SpecialLength::eval( Kernel::EvalState * evalState ) const
543 Concrete::Length d;
544 double a0;
545 double a1;
547 evalState->dyn_->specialUnitService( & d, & a0, & a1 );
549 if( sort_ == Computation::SPECIALU_NOINFLEX )
551 Kernel::ContRef cont = evalState->cont_;
552 cont->takeValue( Kernel::ValueRef( new Lang::Length( val_ * d * Computation::specialUnitNoInflexion( a0, a1 ) ) ),
553 evalState );
554 return;
556 if( ! sort_ & Computation::SPECIALU_DIST )
558 throw Exceptions::InternalError( strrefdup( "The special unit is neither based on inflexion or distance" ) );
561 double res = 1;
563 if( sort_ & Computation::SPECIALU_CIRC )
565 res *= Computation::specialUnitCircleHandle( a0 );
568 if( sort_ & Computation::SPECIALU_CORR )
570 res *= Computation::specialUnitCorrection( a0, a1 );
573 if( sort_ & Computation::SPECIALU_NOINFLEX )
575 res = min( res, Computation::specialUnitNoInflexion( a0, a1 ) );
577 Kernel::ContRef cont = evalState->cont_;
578 cont->takeValue( Kernel::ValueRef( new Lang::Length( val_ * d * res ) ),
579 evalState );
583 Ast::DynamicVariable::DynamicVariable( const Ast::SourceLocation & loc, const char * id )
584 : Ast::Expression( loc ), id_( id ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
586 immediate_ = true;
589 Ast::DynamicVariable::~DynamicVariable( )
591 delete id_;
592 if( *idKey_ != 0 )
594 delete *idKey_;
596 delete idKey_; // This can be done only as long as this is not shared!
599 void
600 Ast::DynamicVariable::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
602 if( *idKey_ == 0 )
604 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalDynamicKey( loc_, id_ ) );
608 void
609 Ast::DynamicVariable::eval( Kernel::EvalState * evalState ) const
611 const Kernel::DynamicVariableProperties & dynProps = evalState->env_->lookupDynamicVariable( **idKey_ );
613 Kernel::VariableHandle res = dynProps.fetch( evalState->dyn_ );
615 /* Now, we know that if the value was bound to a dynamic expression, a value was bound, and that value has
616 * a certain type.
618 if( ! res->isThunk( ) )
622 typedef const Lang::DynamicExpression DynType;
623 RefCountPtr< DynType > dynVal = res->tryVal< DynType >( );
624 dynVal->evalHelper( evalState );
625 return;
627 catch( const NonLocalExit::NotThisType & ball )
629 // Never mind.
633 Kernel::ContRef cont = evalState->cont_;
634 cont->takeHandle( res,
635 evalState );
639 Kernel::DynamicBindingContinuation::DynamicBindingContinuation( const Ast::SourceLocation & traceLoc, const Kernel::PassedEnv & env, const Kernel::Environment::LexicalKey & key, const Ast::DynamicBindingExpression * bindingExpr, const Kernel::ContRef & cont )
640 : Kernel::Continuation( traceLoc ), env_( env ), key_( key ), bindingExpr_( bindingExpr ), cont_( cont )
643 Kernel::DynamicBindingContinuation::~DynamicBindingContinuation( )
646 void
647 Kernel::DynamicBindingContinuation::takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
649 if( val->isThunk( ) )
651 val->force( val, evalState );
652 return;
654 evalState->cont_ = cont_;
655 env_->lookupDynamicVariable( key_ ).makeBinding( val, bindingExpr_, evalState );
658 Kernel::ContRef
659 Kernel::DynamicBindingContinuation::up( ) const
661 return cont_;
664 RefCountPtr< const char >
665 Kernel::DynamicBindingContinuation::description( ) const
667 return strrefdup( "dynamic binding" );
670 void
671 Kernel::DynamicBindingContinuation::gcMark( Kernel::GCMarkedSet & marked )
673 env_->gcMark( marked );
674 cont_->gcMark( marked );
677 Ast::DynamicBindingExpression::DynamicBindingExpression( const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * expr, Kernel::Environment::LexicalKey ** idKey )
678 : Ast::Expression( Ast::SourceLocation( idLoc, expr->loc( ) ) ), idLoc_( idLoc ), id_( id ), expr_( expr ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
681 Ast::DynamicBindingExpression::~DynamicBindingExpression( )
683 delete id_;
684 delete expr_;
685 if( *idKey_ != 0 )
687 delete *idKey_;
688 *idKey_ = 0;
690 // Don't delete idKey as it's shared!
693 void
694 Ast::DynamicBindingExpression::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
696 expr_->analyze( this, env, freeStatesDst );
697 if( *idKey_ == 0 )
699 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalDynamicKey( idLoc_, id_ ) );
703 void
704 Ast::DynamicBindingExpression::eval( Kernel::EvalState * evalState ) const
706 const Kernel::DynamicVariableProperties & dynProps = evalState->env_->lookupDynamicVariable( **idKey_ );
708 if( dynProps.forceValue( ) || expr_->immediate_ )
710 evalState->expr_ = expr_;
711 evalState->cont_ = Kernel::ContRef( new Kernel::DynamicBindingContinuation( expr_->loc( ), evalState->env_, **idKey_, this, evalState->cont_ ) );
713 else
715 dynProps.makeBinding( Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( evalState->env_, evalState->dyn_, expr_ ) ) ),
716 this,
717 evalState );
722 Ast::DynamicStateBindingExpression::DynamicStateBindingExpression( const Ast::SourceLocation & loc, const Ast::SourceLocation & dstLoc, const char * dstId, Ast::StateReference * src )
723 : Ast::Expression( loc ), dstLoc_( dstLoc ), dstId_( dstId ), dstIdKey_( new Kernel::Environment::LexicalKey * ( 0 ) ), src_( src )
726 Ast::DynamicStateBindingExpression::~DynamicStateBindingExpression( )
728 delete src_;
729 if( *dstIdKey_ != 0 )
731 delete *dstIdKey_;
733 delete dstIdKey_; // This can be done only as long as this is not shared!
736 void
737 Ast::DynamicStateBindingExpression::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
739 if( *dstIdKey_ == 0 )
741 *dstIdKey_ = new Kernel::Environment::LexicalKey( env->findLexicalDynamicKey( dstLoc_, dstId_ ) );
745 void
746 Ast::DynamicStateBindingExpression::eval( Kernel::EvalState * evalState ) const
748 const Kernel::DynamicStateProperties & dstDynProps = evalState->env_->lookupDynamicState( **dstIdKey_ );
750 dstDynProps.makeBinding( src_->getHandle( evalState->env_, evalState->dyn_ ), this, evalState );
754 Kernel::WithDynamicContinuation::WithDynamicContinuation( const Ast::SourceLocation & traceLoc, Ast::Expression * expr, const Kernel::EvalState & evalState )
755 : Kernel::Continuation( traceLoc ), expr_( expr ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
758 Kernel::WithDynamicContinuation::~WithDynamicContinuation( )
761 void
762 Kernel::WithDynamicContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
764 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( dyn_, *Helpers::down_cast< const Lang::DynamicBindings >( val, traceLoc_ ) ) );
765 evalState->env_ = env_;
766 evalState->expr_ = expr_;
767 evalState->cont_ = cont_;
770 Kernel::ContRef
771 Kernel::WithDynamicContinuation::up( ) const
773 return cont_;
776 RefCountPtr< const char >
777 Kernel::WithDynamicContinuation::description( ) const
779 return strrefdup("with dynamic bindings" );
782 void
783 Kernel::WithDynamicContinuation::gcMark( Kernel::GCMarkedSet & marked )
785 env_->gcMark( marked );
786 dyn_->gcMark( marked );
787 cont_->gcMark( marked );
791 Ast::WithDynamicExpr::WithDynamicExpr( const Ast::SourceLocation & loc, Ast::Expression * bindings, Ast::Expression * expr )
792 : Ast::Expression( loc ), bindings_( bindings ), expr_( expr )
795 Ast::WithDynamicExpr::~WithDynamicExpr( )
798 void
799 Ast::WithDynamicExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
801 bindings_->analyze( this, env, freeStatesDst );
802 expr_->analyze( this, env, freeStatesDst );
805 void
806 Ast::WithDynamicExpr::eval( Kernel::EvalState * evalState ) const
808 evalState->expr_ = bindings_;
809 evalState->cont_ = Kernel::ContRef( new Kernel::WithDynamicContinuation( bindings_->loc( ), expr_, *evalState ) );
813 Ast::DynamicVariableDecl::DynamicVariableDecl( const Ast::SourceLocation & loc, const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * filterExpr, Ast::Expression * defaultExpr )
814 : Ast::BindNode( loc, idLoc, id ), idPos_( new size_t * ( 0 ) )
816 /* This type of expression is an Ast::BindNode so that it is easy to recognize and extract the identifier for static analysis
817 * and similar tasks.
819 * The expression is implemented as a function call, since there are two subexpressions that may need evaluation.
822 Ast::ArgListExprs * args = new Ast::ArgListExprs( false );
823 Ast::DynamicVariableDeclFunction * res = new Ast::DynamicVariableDeclFunction( id, filterExpr, defaultExpr, idPos_ );
824 res->push_exprs( args );
825 impl_ = new Ast::CallExpr( loc,
826 RefCountPtr< const Lang::Function >( res ),
827 args );
830 Ast::DynamicVariableDecl::~DynamicVariableDecl( )
833 void
834 Ast::DynamicVariableDecl::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
836 impl_->analyze( this, env, freeStatesDst );
837 if( *idPos_ == 0 )
839 *idPos_ = new size_t( env->findLocalDynamicPosition( idLoc_, id_ ) );
843 void
844 Ast::DynamicVariableDecl::evalHelper( Kernel::EvalState * evalState ) const
846 evalState->expr_ = impl_;
850 Ast::DynamicVariableDeclFunction::DynamicVariableDeclFunction( const char * id, Ast::Expression * filterExpr, Ast::Expression * defaultExpr, size_t ** idPos )
851 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< dynamic variable declaration >" ) ) ), id_( id ), filterExpr_( filterExpr ), defaultExpr_( defaultExpr ), idPos_( idPos )
853 formals_->appendEvaluatedCoreFormal( "filter", Kernel::THE_SLOT_VARIABLE, true );
854 formals_->appendEvaluatedCoreFormal( "default", Kernel::THE_SLOT_VARIABLE, false );
857 Ast::DynamicVariableDeclFunction::~DynamicVariableDeclFunction( )
859 delete filterExpr_;
860 delete defaultExpr_;
863 void
864 Ast::DynamicVariableDeclFunction::push_exprs( Ast::ArgListExprs * args ) const
866 args->orderedExprs_->push_back( filterExpr_ );
867 args->orderedExprs_->push_back( defaultExpr_ );
870 void
871 Ast::DynamicVariableDeclFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
873 /* The analysis is carried out by the DynamicVariableDecl expression.
877 void
878 Ast::DynamicVariableDeclFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
880 static const char * title = "< dynamic variable declaration >";
881 typedef const Lang::Function FilterType;
882 evalState->env_->defineDynamic( id_,
883 **idPos_,
884 Helpers::down_cast_CoreArgument< FilterType >( title, args, 0, callLoc ),
885 args.getHandle( 1 ) );
887 Kernel::ContRef cont = evalState->cont_;
888 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
889 evalState );
892 Kernel::DynamicVariableDeclContinuation::DynamicVariableDeclContinuation( const Ast::SourceLocation & traceLoc, const Ast::DynamicVariableDecl * declExpr, Kernel::EvalState & evalState )
893 : Kernel::Continuation( traceLoc ), declExpr_( declExpr ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
896 Kernel::DynamicVariableDeclContinuation::~DynamicVariableDeclContinuation( )
899 void
900 Kernel::DynamicVariableDeclContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
902 evalState->env_ = env_;
903 evalState->dyn_ = dyn_;
904 evalState->cont_ = cont_;
905 throw Exceptions::NotImplemented( "Deprecated: DynamicVariableDeclContinuation" );
906 // declExpr_->callBack( Helpers::down_cast< const Lang::Function >( val, traceLoc_ ),
907 // evalState );
910 Kernel::ContRef
911 Kernel::DynamicVariableDeclContinuation::up( ) const
913 return cont_;
916 RefCountPtr< const char >
917 Kernel::DynamicVariableDeclContinuation::description( ) const
919 return strrefdup( "dynamic variable declaration" );
922 void
923 Kernel::DynamicVariableDeclContinuation::gcMark( Kernel::GCMarkedSet & marked )
925 env_->gcMark( marked );
926 dyn_->gcMark( marked );
927 cont_->gcMark( marked );
931 Ast::DynamicStateDecl::DynamicStateDecl( const Ast::SourceLocation & loc, const Ast::SourceLocation & idLoc, const char * id, Ast::StateReference * defaultState, size_t ** idPos )
932 : Ast::BindNode( loc, idLoc, id ), idPos_( idPos ), defaultState_( defaultState )
935 Ast::DynamicStateDecl::~DynamicStateDecl( )
939 void
940 Ast::DynamicStateDecl::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
942 if( *idPos_ == 0 )
944 *idPos_ = new size_t( env->findLocalDynamicStatePosition( idLoc_, id_ ) );
948 void
949 Ast::DynamicStateDecl::evalHelper( Kernel::EvalState * evalState ) const
951 evalState->env_->defineDynamicState( id_,
952 **idPos_,
953 evalState,
954 defaultState_ );
956 Kernel::ContRef cont = evalState->cont_;
957 cont->takeHandle( Kernel::THE_VOID_VARIABLE,
958 evalState );
962 Ast::EvalSymbolFunction::EvalSymbolFunction( const Ast::SourceLocation & loc, Ast::Expression * expr )
963 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< symbol evaluation >" ), true ) ), loc_( loc ), expr_( expr )
966 Ast::EvalSymbolFunction::~EvalSymbolFunction( )
968 delete expr_;
971 void
972 Ast::EvalSymbolFunction::push_exprs( Ast::ArgListExprs * args ) const
974 args->orderedExprs_->push_back( expr_ );
977 void
978 Ast::EvalSymbolFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
980 analysisEnv_ = env;
982 /* expr_ shall be analyzed from the calling expression.
983 * Here, it is only used to locate errors.
987 void
988 Ast::EvalSymbolFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
990 RefCountPtr< const Lang::Value > untypedVal = args.getValue( 0 );
991 typedef const Lang::Symbol ArgType;
992 ArgType * val = dynamic_cast< ArgType * >( untypedVal.getPtr( ) );
993 if( val == 0 )
995 throw Exceptions::TypeMismatch( expr_->loc( ), untypedVal->getTypeName( ), ArgType::staticTypeName( ) );
997 if( val->isUnique( ) )
999 throw Exceptions::OutOfRange( expr_->loc( ), strrefdup( "Unique symbols can't denote variables." ) );
1003 Kernel::Environment::LexicalKey key = analysisEnv_->findLexicalVariableKey( loc_, val->name( ).getPtr( ) );
1005 Kernel::PassedEnv env = evalState->env_;
1006 env->lookup( key, evalState );
1010 Ast::DefineVariable::DefineVariable( const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * expr, size_t ** idPos )
1011 : Ast::BindNode( Ast::SourceLocation( idLoc, expr->loc( ) ), idLoc, id ), expr_( expr ), idPos_( idPos )
1014 Ast::DefineVariable::~DefineVariable( )
1016 delete expr_;
1018 /* idPos_ is shared and will be a memory leak which must not be deleted.
1019 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1023 void
1024 Ast::DefineVariable::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1026 Ast::StateIDSet freeStates;
1027 expr_->analyze( this, env, & freeStates );
1028 if( ! freeStates.empty( ) )
1030 expr_->immediate_ = true;
1031 for( Ast::StateIDSet::const_iterator i = freeStates.begin( ); i != freeStates.end( ); ++i )
1033 freeStatesDst->insert( *i );
1036 if( *idPos_ == 0 )
1038 *idPos_ = new size_t( env->findLocalVariablePosition( idLoc_, id_ ) );
1042 void
1043 Ast::DefineVariable::evalHelper( Kernel::EvalState * evalState ) const
1045 if( expr_->immediate_ )
1047 evalState->cont_ = Kernel::ContRef( new Kernel::DefineVariableContinuation( evalState->env_,
1048 *idPos_,
1049 evalState->cont_,
1050 expr_->loc( ) ) );
1051 evalState->expr_ = expr_;
1053 else
1055 evalState->env_->define( **idPos_,
1056 Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( evalState->env_,
1057 evalState->dyn_,
1058 expr_ ) ) ) );
1059 Kernel::ContRef cont = evalState->cont_;
1060 cont->takeHandle( Kernel::THE_VOID_VARIABLE, evalState );
1064 Ast::LexicalVariableLocationExpr::LexicalVariableLocationExpr( const Ast::SourceLocation & idLoc, const char * id, Kind kind )
1065 : Ast::Expression( idLoc ), id_( id ), kind_( kind ), value_( NullPtr< const Lang::Value >( ) )
1067 immediate_ = true;
1070 Ast::LexicalVariableLocationExpr::~LexicalVariableLocationExpr( )
1073 void
1074 Ast::LexicalVariableLocationExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1076 Kernel::Environment::LexicalKey key = Kernel::Environment::LexicalKey( env->findLexicalVariableKey( loc_, id_ ) );
1077 switch( kind_ )
1079 case INDEX:
1080 value_ = Kernel::ValueRef( new Lang::Integer( key.pos_ ) );
1081 break;
1082 case DEPTH:
1083 value_ = Kernel::ValueRef( new Lang::Integer( key.up_ ) );
1084 break;
1088 void
1089 Ast::LexicalVariableLocationExpr::eval( Kernel::EvalState * evalState ) const
1091 Kernel::ContRef cont = evalState->cont_;
1092 cont->takeValue( value_, evalState );
1096 Ast::LexicalVariableNameExpr::LexicalVariableNameExpr( const Ast::SourceLocation & loc )
1097 : Ast::Expression( loc ), value_( NullPtr< const Lang::Value >( ) )
1099 immediate_ = true;
1102 Ast::LexicalVariableNameExpr::~LexicalVariableNameExpr( )
1105 void
1106 Ast::LexicalVariableNameExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1108 Ast::Node * n = parent->parent( );
1109 while( n != 0 )
1111 Ast::BindNode * bn = dynamic_cast< Ast::DefineVariable * >( n );
1112 if( bn != 0 )
1114 value_ = Kernel::ValueRef( new Lang::String( bn->id( ), true ) );
1115 return;
1117 n = n->parent( );
1119 Ast::theAnalysisErrorsList.push_back( new Exceptions::MiscellaneousStaticInconsistency( loc( ), strrefdup( "Cannot retrieve variable name, since the location is not inside a binding's right hand side." ) ) );
1122 void
1123 Ast::LexicalVariableNameExpr::eval( Kernel::EvalState * evalState ) const
1125 Kernel::ContRef cont = evalState->cont_;
1126 cont->takeValue( value_, evalState );
1130 Kernel::AssertStructureContinuation::AssertStructureContinuation( const Kernel::ContRef & cont, const Ast::SourceLocation & traceLoc )
1131 : Kernel::Continuation( traceLoc ), cont_( cont )
1134 Kernel::AssertStructureContinuation::~AssertStructureContinuation( )
1137 void
1138 Kernel::AssertStructureContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
1140 evalState->cont_ = cont_;
1141 cont_->takeValue( Helpers::down_cast_ContinuationArgument< const Lang::Structure >( val, this ), evalState );
1144 Kernel::ContRef
1145 Kernel::AssertStructureContinuation::up( ) const
1147 return cont_;
1150 RefCountPtr< const char >
1151 Kernel::AssertStructureContinuation::description( ) const
1153 return strrefdup( "Assert type is struct" );
1156 void
1157 Kernel::AssertStructureContinuation::gcMark( Kernel::GCMarkedSet & marked )
1159 cont_->gcMark( marked );
1163 Ast::StructSplitReference::StructSplitReference( Ast::SourceLocation fieldLoc, const char * fieldId, Ast::Expression * defaultExpr )
1164 : Ast::Expression( fieldLoc ),
1165 structLoc_( Ast::THE_UNKNOWN_LOCATION ), // This is a dummy value! The correct value is set later.
1166 fieldId_( fieldId ),
1167 defaultExpr_( defaultExpr )
1170 Ast::StructSplitReference::StructSplitReference( Ast::SourceLocation fieldLoc, size_t fieldPos, Ast::Expression * defaultExpr )
1171 : Ast::Expression( fieldLoc ),
1172 structLoc_( Ast::THE_UNKNOWN_LOCATION ), // This is a dummy value! The correct value is set later.
1173 fieldId_( 0 ), fieldPos_( fieldPos ),
1174 defaultExpr_( defaultExpr )
1177 Ast::StructSplitReference::~StructSplitReference( )
1179 if( fieldId_ != 0 )
1181 delete fieldId_;
1183 if( defaultExpr_ != 0 )
1185 delete defaultExpr_;
1189 void
1190 Ast::StructSplitReference::setStruct( Ast::SourceLocation structLoc, size_t ** structPos )
1192 structLoc_ = structLoc;
1193 structPos_ = structPos;
1196 void
1197 Ast::StructSplitReference::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1199 if( defaultExpr_ != 0 )
1201 defaultExpr_->analyze( this, env, freeStatesDst );
1205 void
1206 Ast::StructSplitReference::eval( Kernel::EvalState * evalState ) const
1208 Kernel::VariableHandle structHandle = evalState->env_->getVarHandle( **structPos_ );
1209 typedef const Lang::Structure StructType;
1210 RefCountPtr< StructType > structVal = structHandle->getVal< StructType >( "Type-checked value in StructSplitReference::eval." );
1212 Kernel::ContRef cont = evalState->cont_;
1213 if( fieldId_ != 0 )
1217 cont->takeHandle( structVal->getField( fieldId_, structVal ),
1218 evalState );
1219 return;
1221 catch( const Exceptions::NonExistentMember & ball )
1223 if( defaultExpr_ == 0 )
1225 throw;
1227 // Never mind, we use the default instead. See below.
1230 else
1234 cont->takeHandle( structVal->getPosition( fieldPos_, structVal ),
1235 evalState );
1236 return;
1238 catch( const Exceptions::NonExistentPosition & ball )
1240 if( defaultExpr_ == 0 )
1242 throw;
1244 // Never mind, we use the default instead. See below.
1248 if( defaultExpr_ == 0 )
1250 throw Exceptions::InternalError( "Just about to use null pointer defaultExpr_ in StructSplitReference::eval." );
1252 evalState->expr_ = defaultExpr_;
1255 Ast::StructSplitSink::StructSplitSink( )
1256 : Ast::Expression( Ast::THE_UNKNOWN_LOCATION ), structLoc_( Ast::THE_UNKNOWN_LOCATION )
1259 Ast::StructSplitSink::~StructSplitSink( )
1262 void
1263 Ast::StructSplitSink::setStruct( Ast::SourceLocation structLoc, size_t ** structPos, size_t consumedArguments )
1265 structLoc_ = structLoc;
1266 structPos_ = structPos;
1267 consumedArguments_ = consumedArguments;
1270 void
1271 Ast::StructSplitSink::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1273 /* Nothing to do! */
1276 void
1277 Ast::StructSplitSink::eval( Kernel::EvalState * evalState ) const
1279 Kernel::VariableHandle structHandle = evalState->env_->getVarHandle( **structPos_ );
1280 typedef const Lang::Structure StructType;
1281 RefCountPtr< StructType > structVal = structHandle->getVal< StructType >( "Type-checked value in StructSplitReference::eval." );
1283 Kernel::ContRef cont = evalState->cont_;
1284 cont->takeValue( structVal->getSink( consumedArguments_ ),
1285 evalState );
1289 Ast::AssertNoSinkNeeded::AssertNoSinkNeeded( const Ast::SourceLocation & loc, size_t orderedCount, Ast::SourceLocation structLoc, size_t ** structPos )
1290 : Ast::Assertion( loc ), orderedCount_( orderedCount ), structLoc_( structLoc ), structPos_( structPos )
1293 Ast::AssertNoSinkNeeded::~AssertNoSinkNeeded( )
1296 void
1297 Ast::AssertNoSinkNeeded::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1299 /* immediate_ is already true by the inheritage from Ast::Assertion. */
1302 void
1303 Ast::AssertNoSinkNeeded::eval( Kernel::EvalState * evalState ) const
1305 Kernel::VariableHandle structHandle = evalState->env_->getVarHandle( **structPos_ );
1306 typedef const Lang::Structure StructType;
1307 RefCountPtr< StructType > structVal = structHandle->getVal< StructType >( "Type-checked value in StructSplitReference::eval." );
1309 if( structVal->argList_->orderedExprs_->size( ) > orderedCount_ )
1311 throw Exceptions::SinkRequired( loc_, orderedCount_, structVal->argList_->orderedExprs_->size( ) );
1314 Kernel::ContRef cont = evalState->cont_;
1315 cont->takeHandle( Kernel::THE_VOID_VARIABLE, evalState );
1318 size_t Ast::SplitDefineVariables::splitVarCount = 0;
1319 PtrOwner_back_Access< std::list< const char * > > Ast::SplitDefineVariables::mem;
1321 Ast::SplitDefineVariables::SplitDefineVariables( )
1322 : sinkDefine_( 0 ), sinkExpr_( 0 ), seenNamed_( false ), seenDefault_( false )
1324 std::ostringstream oss;
1325 oss << Kernel::SPLIT_VAR_PREFIX << splitVarCount ;
1326 splitVarId_ = strdup( oss.str( ).c_str( ) );
1327 mem.push_back( splitVarId_ );
1328 ++splitVarCount;
1331 const char *
1332 Ast::SplitDefineVariables::newSplitVarId( ) const
1334 return strdup( splitVarId_ );
1338 Ast::StateReference::StateReference( const Ast::SourceLocation & loc )
1339 : Ast::Node( loc )
1342 Ast::StateReference::~StateReference( )
1346 Ast::LexiographicState::LexiographicState( const Ast::SourceLocation & loc, const char * id, Kernel::Environment::LexicalKey ** idKey )
1347 : Ast::StateReference( loc ), id_( id ), idKey_( idKey )
1350 Ast::LexiographicState::~LexiographicState( )
1352 delete id_;
1353 if( *idKey_ != 0 )
1355 delete *idKey_;
1357 delete idKey_; // This can be done only as long as this is not shared!
1360 void
1361 Ast::LexiographicState::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1363 /* The following lines is the ugly solution to the problem that the inherited parent_ and analysisEnv_
1364 * are not well defined for reused nodes. And nodes of this type are typically reused.
1365 * For this type of node, one _could_ refer to someParent_ and someAnalysisEnv_ instead, but probably,
1366 * it is a mistake to even try.
1368 someParent_ = parent_;
1369 parent_ = 0;
1370 someAnalysisEnv_ = analysisEnv_;
1371 analysisEnv_ = 0;
1373 if( *idKey_ == 0 )
1375 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalStateKey( loc_, id_ ) );
1377 if( ! (*idKey_)->isMissing( ) )
1379 freeStatesDst->insert( env->getStateID( **idKey_ ) );
1383 Kernel::StateHandle
1384 Ast::LexiographicState::getHandle( Kernel::PassedEnv env, Kernel::PassedDyn dyn ) const
1386 return env->getStateHandle( **idKey_ );
1390 Ast::DynamicState::DynamicState( const Ast::SourceLocation & loc, const char * id )
1391 : Ast::StateReference( loc ), id_( id ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
1394 Ast::DynamicState::~DynamicState( )
1396 delete id_;
1397 if( *idKey_ != 0 )
1399 delete *idKey_;
1401 delete idKey_; // This can be done only as long as this is not shared!
1404 void
1405 Ast::DynamicState::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1407 /* See comment in LexicalState::analyze_impl.
1409 someParent_ = parent_;
1410 parent_ = 0;
1411 someAnalysisEnv_ = analysisEnv_;
1412 analysisEnv_ = 0;
1414 /* It would make sense to check the reference and...
1415 * This might be overly conservative... but we really shouldn't support dynamic states anyway.
1417 freeStatesDst->insert( Ast::AnalysisEnvironment::getTheAnyStateID( ) );
1420 Kernel::StateHandle
1421 Ast::DynamicState::getHandle( Kernel::PassedEnv env, Kernel::PassedDyn dyn ) const
1423 throw Exceptions::NotImplemented( "Referencing dynamic states" );
1427 Ast::IntroduceState::IntroduceState( const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * expr, size_t ** idPos )
1428 : Ast::BindNode( Ast::SourceLocation( idLoc, expr->loc( ) ), idLoc, id ), expr_( expr ), idPos_( idPos )
1431 Ast::IntroduceState::~IntroduceState( )
1433 delete expr_;
1435 /* idPos_ shared and will be a memory leak which must not be deleted.
1436 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1441 void
1442 Ast::IntroduceState::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1444 expr_->analyze( this, env, freeStatesDst );
1446 if( *idPos_ == 0 )
1448 *idPos_ = new size_t( env->findLocalStatePosition( idLoc_, id_ ) );
1451 stateID_ = env->getStateID( **idPos_ );
1452 freeStatesDst->insert( stateID_ );
1455 void
1456 Ast::IntroduceState::evalHelper( Kernel::EvalState * evalState ) const
1458 evalState->cont_ = Kernel::ContRef( new Kernel::IntroduceStateContinuation( evalState->env_,
1459 *idPos_,
1460 evalState->cont_,
1461 expr_->loc( ) ) );
1462 evalState->expr_ = expr_;
1466 Ast::Insertion::Insertion( Ast::StateReference * stateRef, Ast::Expression * expr )
1467 : Ast::Expression( Ast::SourceLocation( stateRef->loc( ), expr->loc( ) ) ), stateRef_( stateRef ), expr_( expr )
1470 Ast::Insertion::~Insertion( )
1473 void
1474 Ast::Insertion::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1476 stateRef_->analyze( this, env, freeStatesDst ); /* This will always add something to the set of free states. */
1477 expr_->analyze( this, env, freeStatesDst );
1480 void
1481 Ast::Insertion::eval( Kernel::EvalState * evalState ) const
1483 evalState->cont_ = Kernel::ContRef( new Kernel::InsertionContinuation( stateRef_->getHandle( evalState->env_, evalState->dyn_ ),
1484 evalState->cont_,
1485 evalState->dyn_,
1486 expr_->loc( ) ) );
1487 evalState->expr_ = expr_;
1490 Ast::Freeze::Freeze( const Ast::SourceLocation & idLoc, const char * id, size_t ** idPos )
1491 : Ast::Expression( idLoc ), id_( id ), idPos_( idPos )
1493 immediate_ = true;
1496 Ast::Freeze::~Freeze( )
1498 /* idPos shared and will be a memory leak which must not be deleted.
1499 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1503 void
1504 Ast::Freeze::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1506 if( *idPos_ == 0 )
1508 *idPos_ = new size_t( env->findLocalStatePosition( loc( ), id_ ) );
1511 freeStatesDst->insert( env->getStateID( **idPos_ ) );
1514 void
1515 Ast::Freeze::eval( Kernel::EvalState * evalState ) const
1517 evalState->env_->freeze( **idPos_, evalState, loc( ) );
1521 Ast::Peek::Peek( const Ast::SourceLocation & idLoc, Ast::StateReference * stateRef )
1522 : Ast::Expression( idLoc ), stateRef_( stateRef )
1524 immediate_ = true;
1527 Ast::Peek::~Peek( )
1529 /* idPos shared and will be a memory leak which must not be deleted.
1530 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1534 void
1535 Ast::Peek::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1537 stateRef_->analyze( this, env, freeStatesDst ); /* This will always add something to the set of free states. */
1540 void
1541 Ast::Peek::eval( Kernel::EvalState * evalState ) const
1543 stateRef_->getHandle( evalState->env_, evalState->dyn_ )->peek( evalState, loc( ) );
1547 Ast::DynamicExpression::DynamicExpression( const Ast::SourceLocation & loc, Ast::Expression * expr )
1548 : Ast::Expression( loc ), expr_( expr )
1550 immediate_ = true;
1553 Ast::DynamicExpression::~DynamicExpression( )
1556 void
1557 Ast::DynamicExpression::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1559 Ast::StateIDSet * freeStates = new Ast::StateIDSet;
1560 expr_->analyze( this, env, freeStates );
1562 if( ! freeStates->empty( ) )
1564 Ast::theAnalysisErrorsList.push_back( new Exceptions::IllegalFreeStates( expr_->loc( ), freeStates, "dynamic expressions must be pure" ) );
1566 else
1568 delete freeStates;
1572 void
1573 Ast::DynamicExpression::eval( Kernel::EvalState * evalState ) const
1575 Kernel::ContRef cont = evalState->cont_;
1576 cont->takeValue( Kernel::ValueRef( new Lang::DynamicExpression( evalState->env_, expr_ ) ),
1577 evalState );
1581 Ast::LexiographicType::LexiographicType( const Ast::SourceLocation & loc, const char * id, Kernel::Environment::LexicalKey ** idKey )
1582 : Ast::Expression( loc ), id_( id ), idKey_( idKey )
1584 immediate_ = true;
1587 Ast::LexiographicType::~LexiographicType( )
1589 delete id_;
1590 if( *idKey_ != 0 )
1592 delete *idKey_;
1594 delete idKey_; // This can be done only as long as this is not shared!
1597 void
1598 Ast::LexiographicType::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1600 if( *idKey_ == 0 )
1602 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalTypeKey( loc_, id_ ) );
1606 void
1607 Ast::LexiographicType::eval( Kernel::EvalState * evalState ) const
1609 evalState->env_->lookup( **idKey_, evalState );