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, 2014, 2015 Henrik Tidefelt
20 #include "shapesexceptions.h"
22 #include "autoonoff.h"
23 #include "specialunits.h"
25 #include "continuations.h"
26 #include "containertypes.h"
31 using namespace Shapes
;
35 Ast::SourceLocationMark::SourceLocationMark( const Ast::SourceLocation
& loc
)
39 Ast::SourceLocationMark::~SourceLocationMark( )
43 Ast::SourceLocationMark::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
50 class IsSourceLocationMark
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 Ast::IdentifierTree( NULL
, false ) ) : ( extends
->argumentOrder_
) ),
65 dynamicMap_( ( extends
== 0 ) ? ( 0 ) : ( extends
->dynamicMap_
) ),
66 stateOrder_( ( extends
== 0 ) ? ( new Ast::IdentifierTree( NULL
, false ) ) : ( extends
->stateOrder_
) )
68 /* First, we remove any source location marks -- we don't need them anymore. */
69 nodes_
->remove_if( Helpers::IsSourceLocationMark( ) );
71 /* Alias definitions will be extracted and applied in this function. */
72 PtrOwner_back_Access
< std::list
< const Ast::DefineAlias
* > > aliasNodes
;
74 for( std::list
< Ast::Node
* >::const_iterator i
= nodes_
->begin( );
78 typedef Ast::BindNode T
;
79 if( T
* tmp
= dynamic_cast< T
* >( *i
) )
81 bindNodes_
.push_back( tmp
);
83 const Ast::PlacedIdentifier
* id
= tmp
->id( );
84 if( dynamic_cast< const Ast::DefineVariable
* >( tmp
) != NULL
)
86 if( ! argumentOrder_
->insert( *id
, tmp
->idLoc( ) ) ){
87 Ast::theAnalysisErrorsList
.push_back( new Exceptions::IntroducingExisting( tmp
->idLoc( ), *id
) );
92 if( dynamic_cast< const Ast::IntroduceState
* >( tmp
) != NULL
)
94 if( ! stateOrder_
->insert( *id
, tmp
->idLoc( ) ) ){
95 Ast::theAnalysisErrorsList
.push_back( new Exceptions::IntroducingExisting( tmp
->idLoc( ), *id
) );
100 if( dynamic_cast< const Ast::DynamicVariableDecl
* >( tmp
) != NULL
)
102 if( dynamicMap_
== 0 )
104 setDynamicMap( new Ast::IdentifierTree( NULL
, false ) ); /* Sending the new map to extends_ recursively is important for memory management. */
106 if( ! dynamicMap_
->insert( *id
, tmp
->idLoc( ) ) ){
107 Ast::theAnalysisErrorsList
.push_back( new Exceptions::IntroducingExisting( tmp
->idLoc( ), *id
) );
113 if( const Ast::DefineAlias
* defineAliasNode
= dynamic_cast< const Ast::DefineAlias
* >( *i
) )
115 aliasNodes
.push_back( defineAliasNode
);
116 std::list
< Ast::Node
* >::const_iterator j
= i
;
124 for( std::list
< const Ast::DefineAlias
* >::const_iterator i
= aliasNodes
.begin( );
125 i
!= aliasNodes
.end( );
128 bool resolved
= false;
129 resolved
= resolved
|| argumentOrder_
->insertAlias( *((*i
)->id( )), (*i
)->expansion( ), (*i
)->idLoc( ) );
130 resolved
= resolved
|| stateOrder_
->insertAlias( *((*i
)->id( )), (*i
)->expansion( ), (*i
)->idLoc( ) );
131 if( dynamicMap_
!= NULL
){
132 resolved
= resolved
|| dynamicMap_
->insertAlias( *((*i
)->id( )), (*i
)->expansion( ), (*i
)->idLoc( ) );
135 Interaction::warn_or_push( new Exceptions::UndefinedNamespace( (*i
)->expansionLoc( ), (*i
)->expansion( ) ), & Ast::theAnalysisErrorsList
);
141 Ast::CodeBracket::setDynamicMap( Ast::IdentifierTree
* dynamicMap
)
143 dynamicMap_
= dynamicMap
;
146 extends_
->setDynamicMap( dynamicMap
);
150 Ast::CodeBracket::~CodeBracket( )
152 typedef list
< Ast::Node
* >::iterator I
;
153 for( I i
= nodes_
->begin( ); i
!= nodes_
->end( ); ++i
)
161 /* If extends_ != 0, this object does not own the maps. */
162 delete argumentOrder_
;
163 if( dynamicMap_
!= 0 )
172 Ast::CodeBracket::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* parentEnv
, Ast::StateIDSet
* freeStatesDst
)
176 analysisEnv_
= new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList
, parentEnv
, argumentOrder_
, stateOrder_
);
180 analysisEnv_
= extends_
->analysisEnv_
;
181 analysisEnv_
->updateBindings( );
184 if( dynamicMap_
!= 0 )
186 analysisEnv_
->setupDynamicKeyVariables( dynamicMap_
);
190 Ast::StateIDSet allFreeStates
;
191 Ast::StateIDSet introducedStates
;
194 Ast::StateIDSet freeStates
;
195 typedef list
< Ast::Node
* >::iterator I
;
196 for( I i
= nodes_
->begin( ); i
!= nodes_
->end( ); ++i
)
199 (*i
)->analyze( this, analysisEnv_
, & freeStates
);
200 if( ! freeStates
.empty( ) )
202 typedef typeof freeStates SetType
;
203 for( SetType::const_iterator j
= freeStates
.begin( ); j
!= freeStates
.end( ); ++j
)
205 allFreeStates
.insert( *j
);
210 Ast::Expression
* expr
= dynamic_cast< Ast::Expression
* >( *i
);
211 if( expr
!= 0 && ! expr
->immediate_
)
215 if( tmp
!= nodes_
->end( ) )
217 Ast::theAnalysisErrorsList
.push_back( new Exceptions::ExpectedImmediate( (*i
)->loc( ) ) );
221 Ast::IntroduceState
* introduceStateExpr
= dynamic_cast< Ast::IntroduceState
* >( *i
);
222 if( introduceStateExpr
!= 0 )
224 introducedStates
.insert( introduceStateExpr
->getStateID( ) );
229 if( ! introducedStates
.empty( ) )
231 Ast::StateIDSet diff
;
232 std::set_difference( allFreeStates
.begin( ), allFreeStates
.end( ),
233 introducedStates
.begin( ), introducedStates
.end( ),
234 std::inserter( diff
, diff
.begin( ) ) );
235 allFreeStates
.swap( diff
);
237 if( ! allFreeStates
.empty( ) )
239 typedef typeof allFreeStates SetType
;
240 for( SetType::const_iterator j
= allFreeStates
.begin( ); j
!= allFreeStates
.end( ); ++j
)
242 freeStatesDst
->insert( *j
);
248 Ast::CodeBracket::eval( Kernel::EvalState
* evalState
) const
250 if( nodes_
->begin( ) == nodes_
->end( ) )
252 Kernel::ContRef cont
= evalState
->cont_
;
253 cont
->takeValue( Lang::THE_VOID
,
258 evalState
->env_
= newEnvironment( evalState
->env_
);
260 if( dynamicMap_
!= 0 )
262 evalState
->env_
->setupDynamicKeyVariables( dynamicMap_
);
265 typedef typeof bindNodes_ ListType
;
266 for( ListType::const_iterator i
= bindNodes_
.begin( ); i
!= bindNodes_
.end( ); ++i
){
267 (*i
)->initializeEnvironment( evalState
->env_
, evalState
->dyn_
);
270 RefCountPtr
< const Kernel::CodeBracketContInfo
> info( new Kernel::CodeBracketContInfo( this, *evalState
) );
272 evalAt( info
, nodes_
->begin( ), evalState
);
275 Kernel::Environment
*
276 Ast::CodeBracket::newEnvironment( Kernel::Environment
* parent
, const char * debugName
) const
281 throw Exceptions::InternalError( "Ast::CodeBracket::newEnvironment( ): extends_ != 0" );
284 std::vector
< Kernel::VariableHandle
> * envValues
= new std::vector
< Kernel::VariableHandle
>;
285 envValues
->reserve( argumentOrder_
->size( ) );
286 while( envValues
->size( ) < argumentOrder_
->size( ) )
288 envValues
->push_back( NullPtr
< Kernel::Variable
>( ) );
291 std::vector
< Kernel::StateHandle
> * envStates
= new std::vector
< Kernel::StateHandle
>;
292 envStates
->reserve( stateOrder_
->size( ) );
293 while( envStates
->size( ) < stateOrder_
->size( ) )
295 envStates
->push_back( NullPtr
< Kernel::State
>( ) );
298 return new Kernel::Environment( Kernel::theEnvironmentList
, parent
, argumentOrder_
, RefCountPtr
< std::vector
< Kernel::VariableHandle
> >( envValues
), stateOrder_
, RefCountPtr
< std::vector
< Kernel::StateHandle
> >( envStates
), debugName
);
302 Ast::CodeBracket::eval( Kernel::EvalState
* evalState
, Kernel::Environment
* extendsEnv
) const
304 if( nodes_
->begin( ) == nodes_
->end( ) )
306 Kernel::ContRef cont
= evalState
->cont_
;
307 cont
->takeValue( Lang::THE_VOID
,
312 evalState
->env_
= extendsEnv
;
313 if( dynamicMap_
!= 0 )
315 evalState
->env_
->setupDynamicKeyVariables( dynamicMap_
);
317 evalState
->env_
->extendVectors( );
319 RefCountPtr
< const Kernel::CodeBracketContInfo
> info( new Kernel::CodeBracketContInfo( this, *evalState
) );
321 evalAt( info
, nodes_
->begin( ), evalState
);
325 Ast::CodeBracket::evalAt( const RefCountPtr
< const Kernel::CodeBracketContInfo
> & info
, const std::list
< Ast::Node
* >::const_iterator
& pos
, Kernel::EvalState
* evalState
) const
328 std::list
< Ast::Node
* >::const_iterator next
= pos
;
330 if( next
== nodes_
->end( ) ){
331 evalState
->cont_
= info
->cont_
;
333 evalState
->cont_
= Kernel::ContRef( new Kernel::CodeBracketContinuation( (*pos
)->loc( ), info
, next
) );
336 evalState
->env_
= info
->env_
;
337 evalState
->dyn_
= info
->dyn_
;
338 if( Ast::Expression
* e
= dynamic_cast< Ast::Expression
* >( *pos
) ){
339 evalState
->expr_
= e
;
342 if( const Ast::BindNode
* bn
= dynamic_cast< const Ast::BindNode
* >( *pos
) ){
343 bn
->evalHelper( evalState
);
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( )
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( )
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_
,
385 Kernel::CodeBracketContinuation::up( ) const
390 RefCountPtr
< const char >
391 Kernel::CodeBracketContinuation::description( ) const
393 return strrefdup( "code bracket" );
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 Ast::Identifier
* id
, Kernel::Environment::LexicalKey
** idKey
)
404 : Ast::Expression( loc
), id_( id
), idKey_( idKey
)
409 Ast::LexiographicVariable::~LexiographicVariable( )
416 delete idKey_
; /* This can be done only as long as this is not shared! */
420 Ast::LexiographicVariable::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
424 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalVariableKey( loc_
, *id_
) );
426 scope_level_
= env
->level( ) - (*idKey_
)->up_
;
430 Ast::LexiographicVariable::eval( Kernel::EvalState
* evalState
) const
432 evalState
->env_
->lookup( **idKey_
, evalState
);
436 Ast::PrivateAliasVariable::PrivateAliasVariable( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
, const RefCountPtr
< const char > & privateName
)
437 : Ast::Expression( loc
), id_( id
), privateName_( privateName
), aliasKey_( NULL
)
442 Ast::PrivateAliasVariable::~PrivateAliasVariable( )
444 /* Don't delete id_ -- it will be shared with the id_ of a DefineVariable. */
445 if( aliasKey_
!= NULL
){
451 Ast::PrivateAliasVariable::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
453 aliasKey_
= new Kernel::Environment::LexicalKey( env
->findPrivateAliasVariableKey( loc_
, id_
, privateName_
.getPtr( ) ) );
457 Ast::PrivateAliasVariable::eval( Kernel::EvalState
* evalState
) const
459 evalState
->env_
->lookup( *aliasKey_
, evalState
);
463 Ast::Force::Force( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
464 : Ast::Expression( loc
), expr_( expr
)
469 Ast::Force::~Force( )
475 Ast::Force::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
477 expr_
->analyze( this, env
, freeStatesDst
);
481 Ast::Force::eval( Kernel::EvalState
* evalState
) const
483 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingContinuation( evalState
->cont_
, loc_
) );
484 evalState
->expr_
= expr_
;
488 Ast::EvalOutsideExpr::EvalOutsideExpr( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
489 : Ast::Expression( loc
), expr_( expr
)
494 Ast::EvalOutsideExpr::~EvalOutsideExpr( )
500 Ast::EvalOutsideExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
502 expr_
->analyze( this, env
->getParent( ), freeStatesDst
);
506 Ast::EvalOutsideExpr::eval( Kernel::EvalState
* evalState
) const
508 evalState
->expr_
= expr_
;
509 evalState
->env_
= evalState
->env_
->getParent( );
513 Ast::MemberReferenceFunction::MemberReferenceFunction( const Ast::SourceLocation
& loc
, Ast::Expression
* variable
, const char * fieldID
)
514 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<>.<>" ), true ) ), loc_( loc
), variable_( variable
), fieldID_( fieldID
)
517 Ast::MemberReferenceFunction::~MemberReferenceFunction( )
524 Ast::MemberReferenceFunction::push_exprs( Ast::ArgListExprs
* args
) const
526 args
->orderedExprs_
->push_back( variable_
);
530 Ast::MemberReferenceFunction::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
532 /* The variable is analyzed as part of the arguments passed to this function, so nothing needs to be done here...
533 * unless we would be able to figure out the type of the argument, and then check if the field reference is valid.
538 Ast::MemberReferenceFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
540 Kernel::ContRef cont
= evalState
->cont_
;
541 RefCountPtr
< const Lang::Value
> arg
= args
.getValue( 0 );
542 cont
->takeHandle( arg
->getField( fieldID_
, arg
),
548 Ast::MutatorReference::MutatorReference( const Ast::SourceLocation
& mutatorLoc
, Ast::StateReference
* state
, const char * mutatorID
)
549 : Ast::Expression( mutatorLoc
), mutatorLoc_( mutatorLoc
), state_( state
), mutatorID_( mutatorID
)
552 Ast::MutatorReference::~MutatorReference( )
554 /* At the time of implementing this bug-fix, state_ will allways be owned by the Ast::CallExpr that is also the owner of us.
555 * Hence, we do not consider ourselves owners. Perhaps one should have a flag indicating whether ownership is transferred
556 * when calling the constructor, but at the moment this seems like a waste of resources.
563 Ast::MutatorReference::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
565 state_
->analyze( this, env
, freeStatesDst
);
566 /* If the type of the state was known here, we should verify that there is a mutator corresponding to the message <mutatorID>.
571 Ast::MutatorReference::eval( Kernel::EvalState
* evalState
) const
573 Kernel::ContRef cont
= evalState
->cont_
;
574 cont
->takeValue( state_
->getHandle( evalState
->env_
, evalState
->dyn_
)->getMutator( mutatorID_
),
580 Ast::SpecialLength::SpecialLength( const Ast::SourceLocation
& loc
, double val
, int sort
)
581 : Ast::Expression( loc
), val_( val
), sort_( sort
)
584 Ast::SpecialLength::~SpecialLength( )
588 Ast::SpecialLength::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
594 Ast::SpecialLength::eval( Kernel::EvalState
* evalState
) const
600 evalState
->dyn_
->specialUnitService( & d
, & a0
, & a1
);
602 if( sort_
== Computation::SPECIALU_NOINFLEX
)
604 Kernel::ContRef cont
= evalState
->cont_
;
605 cont
->takeValue( Kernel::ValueRef( new Lang::Length( val_
* d
* Computation::specialUnitNoInflexion( a0
, a1
) ) ),
609 if( ! sort_
& Computation::SPECIALU_DIST
)
611 throw Exceptions::InternalError( strrefdup( "The special unit is neither based on inflexion or distance" ) );
616 if( sort_
& Computation::SPECIALU_CIRC
)
618 res
*= Computation::specialUnitCircleHandle( a0
);
621 if( sort_
& Computation::SPECIALU_CORR
)
623 res
*= Computation::specialUnitCorrection( a0
, a1
);
626 if( sort_
& Computation::SPECIALU_NOINFLEX
)
628 res
= min( res
, Computation::specialUnitNoInflexion( a0
, a1
) );
630 Kernel::ContRef cont
= evalState
->cont_
;
631 cont
->takeValue( Kernel::ValueRef( new Lang::Length( val_
* d
* res
) ),
636 Ast::DynamicVariable::DynamicVariable( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
)
637 : Ast::Expression( loc
), id_( id
), idKey_( new Kernel::Environment::LexicalKey
* ( 0 ) )
642 Ast::DynamicVariable::~DynamicVariable( )
649 delete idKey_
; // This can be done only as long as this is not shared!
653 Ast::DynamicVariable::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
657 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalDynamicKey( loc_
, *id_
) );
662 Ast::DynamicVariable::eval( Kernel::EvalState
* evalState
) const
664 const Kernel::DynamicVariableProperties
& dynProps
= evalState
->env_
->lookupDynamicVariable( **idKey_
);
666 Kernel::VariableHandle res
= dynProps
.fetch( evalState
->dyn_
);
668 /* Now, we know that if the value was bound to a dynamic expression, a value was bound, and that value has
671 if( ! res
->isThunk( ) )
675 typedef const Lang::DynamicExpression DynType
;
676 RefCountPtr
< DynType
> dynVal
= res
->tryVal
< DynType
>( );
677 dynVal
->evalHelper( evalState
);
680 catch( const NonLocalExit::NotThisType
& ball
)
686 Kernel::ContRef cont
= evalState
->cont_
;
687 cont
->takeHandle( res
,
692 Kernel::DynamicBindingContinuation::DynamicBindingContinuation( const Ast::SourceLocation
& traceLoc
, const Kernel::PassedEnv
& env
, const Kernel::Environment::LexicalKey
& key
, const Ast::DynamicBindingExpression
* bindingExpr
, const Kernel::ContRef
& cont
)
693 : Kernel::Continuation( traceLoc
), env_( env
), key_( key
), bindingExpr_( bindingExpr
), cont_( cont
)
696 Kernel::DynamicBindingContinuation::~DynamicBindingContinuation( )
700 Kernel::DynamicBindingContinuation::takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
702 if( val
->isThunk( ) )
704 val
->force( val
, evalState
);
707 evalState
->cont_
= cont_
;
708 env_
->lookupDynamicVariable( key_
).makeBinding( val
, bindingExpr_
, evalState
);
712 Kernel::DynamicBindingContinuation::up( ) const
717 RefCountPtr
< const char >
718 Kernel::DynamicBindingContinuation::description( ) const
720 return strrefdup( "dynamic binding" );
724 Kernel::DynamicBindingContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
726 env_
->gcMark( marked
);
727 cont_
->gcMark( marked
);
730 Ast::DynamicBindingExpression::DynamicBindingExpression( const Ast::SourceLocation
& idLoc
, const Ast::Identifier
* id
, Ast::Expression
* expr
, Kernel::Environment::LexicalKey
** idKey
)
731 : Ast::Expression( Ast::SourceLocation( idLoc
, expr
->loc( ) ) ), idLoc_( idLoc
), id_( id
), expr_( expr
), idKey_( new Kernel::Environment::LexicalKey
* ( 0 ) )
734 Ast::DynamicBindingExpression::~DynamicBindingExpression( )
743 // Don't delete idKey as it's shared!
747 Ast::DynamicBindingExpression::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
749 expr_
->analyze( this, env
, freeStatesDst
);
752 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalDynamicKey( idLoc_
, *id_
) );
757 Ast::DynamicBindingExpression::eval( Kernel::EvalState
* evalState
) const
759 const Kernel::DynamicVariableProperties
& dynProps
= evalState
->env_
->lookupDynamicVariable( **idKey_
);
761 if( dynProps
.forceValue( ) || expr_
->immediate_
)
763 evalState
->expr_
= expr_
;
764 evalState
->cont_
= Kernel::ContRef( new Kernel::DynamicBindingContinuation( expr_
->loc( ), evalState
->env_
, **idKey_
, this, evalState
->cont_
) );
768 dynProps
.makeBinding( Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( evalState
->env_
, evalState
->dyn_
, expr_
) ) ),
775 Ast::DynamicStateBindingExpression::DynamicStateBindingExpression( const Ast::SourceLocation
& loc
, const Ast::SourceLocation
& dstLoc
, const Ast::Identifier
* dstId
, Ast::StateReference
* src
)
776 : Ast::Expression( loc
), dstLoc_( dstLoc
), dstId_( dstId
), dstIdKey_( new Kernel::Environment::LexicalKey
* ( 0 ) ), src_( src
)
779 Ast::DynamicStateBindingExpression::~DynamicStateBindingExpression( )
782 if( *dstIdKey_
!= 0 )
786 delete dstIdKey_
; // This can be done only as long as this is not shared!
790 Ast::DynamicStateBindingExpression::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
792 if( *dstIdKey_
== 0 )
794 *dstIdKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalDynamicKey( dstLoc_
, *dstId_
) );
799 Ast::DynamicStateBindingExpression::eval( Kernel::EvalState
* evalState
) const
801 const Kernel::DynamicStateProperties
& dstDynProps
= evalState
->env_
->lookupDynamicState( **dstIdKey_
);
803 dstDynProps
.makeBinding( src_
->getHandle( evalState
->env_
, evalState
->dyn_
), this, evalState
);
807 Kernel::WithDynamicContinuation::WithDynamicContinuation( const Ast::SourceLocation
& traceLoc
, Ast::Expression
* expr
, const Kernel::EvalState
& evalState
)
808 : Kernel::Continuation( traceLoc
), expr_( expr
), env_( evalState
.env_
), dyn_( evalState
.dyn_
), cont_( evalState
.cont_
)
811 Kernel::WithDynamicContinuation::~WithDynamicContinuation( )
815 Kernel::WithDynamicContinuation::takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
817 evalState
->dyn_
= Kernel::PassedDyn( new Kernel::DynamicEnvironment( dyn_
, *Helpers::down_cast
< const Lang::DynamicBindings
>( val
, traceLoc_
) ) );
818 evalState
->env_
= env_
;
819 evalState
->expr_
= expr_
;
820 evalState
->cont_
= cont_
;
824 Kernel::WithDynamicContinuation::up( ) const
829 RefCountPtr
< const char >
830 Kernel::WithDynamicContinuation::description( ) const
832 return strrefdup("with dynamic bindings" );
836 Kernel::WithDynamicContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
838 env_
->gcMark( marked
);
839 dyn_
->gcMark( marked
);
840 cont_
->gcMark( marked
);
844 Ast::WithDynamicExpr::WithDynamicExpr( const Ast::SourceLocation
& loc
, Ast::Expression
* bindings
, Ast::Expression
* expr
)
845 : Ast::Expression( loc
), bindings_( bindings
), expr_( expr
)
848 Ast::WithDynamicExpr::~WithDynamicExpr( )
852 Ast::WithDynamicExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
854 bindings_
->analyze( this, env
, freeStatesDst
);
855 expr_
->analyze( this, env
, freeStatesDst
);
859 Ast::WithDynamicExpr::eval( Kernel::EvalState
* evalState
) const
861 evalState
->expr_
= bindings_
;
862 evalState
->cont_
= Kernel::ContRef( new Kernel::WithDynamicContinuation( bindings_
->loc( ), expr_
, *evalState
) );
866 Ast::DynamicVariableDecl::DynamicVariableDecl( const Ast::SourceLocation
& loc
, const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, Ast::Expression
* filterExpr
, Ast::Expression
* defaultExpr
)
867 : Ast::BindNode( loc
, idLoc
, id
), idPos_( new size_t * ( 0 ) )
869 /* This type of expression is an Ast::BindNode so that it is easy to recognize and extract the identifier for static analysis
872 * The expression is implemented as a function call, since there are two subexpressions that may need evaluation.
875 Ast::ArgListExprs
* args
= new Ast::ArgListExprs( false );
876 Ast::DynamicVariableDeclFunction
* res
= new Ast::DynamicVariableDeclFunction( id
, filterExpr
, defaultExpr
, idPos_
);
877 res
->push_exprs( args
);
878 Ast::CallExpr
* callExpr
=
879 new Ast::CallExpr( loc
,
880 RefCountPtr
< const Lang::Function
>( res
),
882 /* Wrap the call in Ast::Force as a poor substitute for doing the right thing, see comment in initializeEnvironment. */
883 impl_
= new Ast::Force( loc
, callExpr
);
886 Ast::DynamicVariableDecl::~DynamicVariableDecl( )
890 Ast::DynamicVariableDecl::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
892 impl_
->analyze( this, env
, freeStatesDst
);
894 *idPos_
= new size_t( env
->findLocalDynamicPosition( idLoc_
, *id_
) );
899 Ast::DynamicVariableDecl::initializeEnvironment( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
901 /* Here, the right thing to do is probably to put the impl_ call in a DynamicVariableProperties thunk, but
902 * that type of thunk is not invented yet.
904 * As a poor substitute for the right thing, the impl_ call is wrapped in Ast::Force, see contructor.
909 Ast::DynamicVariableDecl::evalHelper( Kernel::EvalState
* evalState
) const
911 evalState
->expr_
= impl_
;
915 Ast::DynamicVariableDeclFunction::DynamicVariableDeclFunction( const Ast::PlacedIdentifier
* id
, Ast::Expression
* filterExpr
, Ast::Expression
* defaultExpr
, size_t ** idPos
)
916 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< dynamic variable declaration >" ) ) ), id_( id
), filterExpr_( filterExpr
), defaultExpr_( defaultExpr
), idPos_( idPos
)
918 formals_
->appendEvaluatedCoreFormal( "filter", Kernel::THE_SLOT_VARIABLE
, true );
919 formals_
->appendEvaluatedCoreFormal( "default", Kernel::THE_SLOT_VARIABLE
, false );
922 Ast::DynamicVariableDeclFunction::~DynamicVariableDeclFunction( )
929 Ast::DynamicVariableDeclFunction::push_exprs( Ast::ArgListExprs
* args
) const
931 args
->orderedExprs_
->push_back( filterExpr_
);
932 args
->orderedExprs_
->push_back( defaultExpr_
);
936 Ast::DynamicVariableDeclFunction::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
938 /* The analysis is carried out by the DynamicVariableDecl expression.
943 Ast::DynamicVariableDeclFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
945 static const char * title
= "< dynamic variable declaration >";
946 typedef const Lang::Function FilterType
;
947 evalState
->env_
->defineDynamic( id_
,
949 Helpers::down_cast_SyntaxArgument
< FilterType
>( title
, args
, 0, callLoc
),
950 args
.getHandle( 1 ) );
952 Kernel::ContRef cont
= evalState
->cont_
;
953 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
957 Kernel::DynamicVariableDeclContinuation::DynamicVariableDeclContinuation( const Ast::SourceLocation
& traceLoc
, const Ast::DynamicVariableDecl
*, Kernel::EvalState
& evalState
)
958 : Kernel::Continuation( traceLoc
), env_( evalState
.env_
), dyn_( evalState
.dyn_
), cont_( evalState
.cont_
)
961 Kernel::DynamicVariableDeclContinuation::~DynamicVariableDeclContinuation( )
965 Kernel::DynamicVariableDeclContinuation::takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
967 evalState
->env_
= env_
;
968 evalState
->dyn_
= dyn_
;
969 evalState
->cont_
= cont_
;
970 throw Exceptions::NotImplemented( "Deprecated: DynamicVariableDeclContinuation" );
971 // declExpr_->callBack( Helpers::down_cast< const Lang::Function >( val, traceLoc_ ),
976 Kernel::DynamicVariableDeclContinuation::up( ) const
981 RefCountPtr
< const char >
982 Kernel::DynamicVariableDeclContinuation::description( ) const
984 return strrefdup( "dynamic variable declaration" );
988 Kernel::DynamicVariableDeclContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
990 env_
->gcMark( marked
);
991 dyn_
->gcMark( marked
);
992 cont_
->gcMark( marked
);
996 Ast::DynamicStateDecl::DynamicStateDecl( const Ast::SourceLocation
& loc
, const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, Ast::StateReference
* defaultState
, size_t ** idPos
)
997 : Ast::BindNode( loc
, idLoc
, id
), idPos_( idPos
), defaultState_( defaultState
)
1000 Ast::DynamicStateDecl::~DynamicStateDecl( )
1005 Ast::DynamicStateDecl::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1009 *idPos_
= new size_t( env
->findLocalDynamicStatePosition( idLoc_
, *id_
) );
1014 Ast::DynamicStateDecl::initializeEnvironment( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1016 env
->defineDynamicState( id_
, **idPos_
, env
, dyn
, defaultState_
);
1020 Ast::DynamicStateDecl::evalHelper( Kernel::EvalState
* evalState
) const
1022 Kernel::ContRef cont
= evalState
->cont_
;
1023 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
1028 Ast::EvalSymbolFunction::EvalSymbolFunction( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
, const RefCountPtr
< const Ast::NamespacePath
> & lexicalPath
)
1029 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< symbol evaluation >" ), true ) ), loc_( loc
), expr_( expr
), lexicalPath_( lexicalPath
)
1032 Ast::EvalSymbolFunction::~EvalSymbolFunction( )
1038 Ast::EvalSymbolFunction::push_exprs( Ast::ArgListExprs
* args
) const
1040 args
->orderedExprs_
->push_back( expr_
);
1044 Ast::EvalSymbolFunction::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1048 /* expr_ shall be analyzed from the calling expression.
1049 * Here, it is only used to locate errors.
1054 Ast::EvalSymbolFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1056 static const RefCountPtr
< const Ast::NamespacePath
> EMPTY_RELATIVE_PATH( new Ast::NamespacePath( ) );
1058 RefCountPtr
< const Lang::Value
> untypedVal
= args
.getValue( 0 );
1059 typedef const Lang::Symbol ArgType
;
1060 ArgType
* val
= dynamic_cast< ArgType
* >( untypedVal
.getPtr( ) );
1063 throw Exceptions::TypeMismatch( expr_
->loc( ), untypedVal
->getTypeName( ), ArgType::staticTypeName( ) );
1065 if( val
->isUnique( ) )
1067 throw Exceptions::OutOfRange( expr_
->loc( ), strrefdup( "Unique symbols can't denote variables." ) );
1070 RefCountPtr
< const Ast::SearchContext
> searchContext( new Ast::SearchContext( lexicalPath_
, RefCountPtr
< const char >( NullPtr
< const char >( ) ) ) );
1071 Kernel::Environment::LexicalKey key
= analysisEnv_
->findLexicalVariableKey( loc_
, Ast::Identifier( searchContext
, Ast::NamespaceReference::RELATIVE
, EMPTY_RELATIVE_PATH
, val
->name( ).getPtr( ) ) );
1073 Kernel::PassedEnv env
= evalState
->env_
;
1074 env
->lookup( key
, evalState
);
1078 Ast::DefineVariable::DefineVariable( const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, Ast::Expression
* expr
, size_t ** idPos
)
1079 : Ast::BindNode( Ast::SourceLocation( idLoc
, expr
->loc( ) ), idLoc
, id
), expr_( expr
), idPos_( idPos
)
1082 Ast::DefineVariable::~DefineVariable( )
1086 /* idPos_ is shared and will be a memory leak which must not be deleted.
1087 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1092 Ast::DefineVariable::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1094 Ast::StateIDSet freeStates
;
1095 expr_
->analyze( this, env
, & freeStates
);
1096 if( ! freeStates
.empty( ) )
1098 Ast::Force
* forcedExpr( new Ast::Force( loc_
, expr_
) );
1099 /* The forcedExpr should not be analyzed since the contained expr_ is already
1100 * analyzed, and analyzing forcedExpr would just cause expr_ to be analyzed again.
1101 * Instead, we just need to update parent/child links.
1103 expr_
->changeParent( forcedExpr
);
1104 forcedExpr
->setParent( this, env
);
1106 for( Ast::StateIDSet::const_iterator i
= freeStates
.begin( ); i
!= freeStates
.end( ); ++i
)
1108 freeStatesDst
->insert( *i
);
1113 *idPos_
= new size_t( env
->findLocalVariablePosition( idLoc_
, *id_
) );
1118 Ast::DefineVariable::initializeEnvironment( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1120 env
->define( **idPos_
,
1121 Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( env
, dyn
, expr_
) ) ) );
1125 Ast::DefineVariable::evalHelper( Kernel::EvalState
* evalState
) const
1127 if( expr_
->immediate_
){
1128 Kernel::VariableHandle var
= evalState
->env_
->getVarHandle( **idPos_
);
1129 /* Using sufficient but not necessary condition for recognizing that the thunk
1130 * set up in initializeEnvironment is still not forced. The worst thing that
1131 * can happen is that another thunk for this expression, but in another environment
1132 * or another dynamic environment, is forced. If that happens, note that
1133 * expr_->immediate_ also applies to the other thunk, so it should be forced sooner or
1136 if( var
->isThunk( expr_
) ){
1137 evalState
->cont_
= Kernel::ContRef( new Kernel::IgnoreContinuation( evalState
->cont_
, expr_
->loc( ) ) );
1138 var
->force( var
, evalState
);
1143 Kernel::ContRef cont
= evalState
->cont_
;
1144 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
, evalState
);
1148 Ast::DefineAlias::DefineAlias( const Ast::SourceLocation
& idLoc
, const Ast::SourceLocation
& expansionLoc
, const Ast::PlacedIdentifier
* id
, const Ast::NamespaceReference
& expansion
)
1149 : Ast::Node( idLoc
), idLoc_( idLoc
), id_( id
), expansion_( expansion
), expansionLoc_( expansionLoc
)
1152 Ast::DefineAlias::~DefineAlias( )
1158 Ast::DefineAlias::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1160 throw Exceptions::InternalError( "Ast::DefineAlias::analyze_impl: Alias definitions should not be present at program analysis." );
1163 Ast::LexicalVariableLocationExpr::LexicalVariableLocationExpr( const Ast::SourceLocation
& idLoc
, const Ast::Identifier
* id
, Kind kind
)
1164 : Ast::Expression( idLoc
), id_( id
), kind_( kind
), value_( NullPtr
< const Lang::Value
>( ) )
1169 Ast::LexicalVariableLocationExpr::~LexicalVariableLocationExpr( )
1173 Ast::LexicalVariableLocationExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1175 Kernel::Environment::LexicalKey key
= Kernel::Environment::LexicalKey( env
->findLexicalVariableKey( loc_
, *id_
) );
1176 if( key
.isMissing( ) ){
1177 /* If the variable wasn't found, compilation will be terminated after the analysis sweep, and there's
1178 * no point in trying to assign something meaningless to value_.
1186 value_
= Kernel::ValueRef( new Lang::Integer( key
.pos_
) );
1189 value_
= Kernel::ValueRef( new Lang::Integer( key
.up_
) );
1193 Ast::PlacedIdentifier
idPlaced( env
->reverseMapLexicalVariable( key
) );
1194 std::ostringstream oss
;
1195 oss
<< Interaction::NAMESPACE_SEPARATOR
;
1196 idPlaced
.show( oss
, Ast::Identifier::VARIABLE
);
1197 value_
= Kernel::ValueRef( new Lang::String( strrefdup( oss
) ) );
1204 Ast::LexicalVariableLocationExpr::eval( Kernel::EvalState
* evalState
) const
1206 Kernel::ContRef cont
= evalState
->cont_
;
1207 cont
->takeValue( value_
, evalState
);
1211 Ast::LexicalVariableNameExpr::LexicalVariableNameExpr( const Ast::SourceLocation
& loc
)
1212 : Ast::Expression( loc
), value_( NullPtr
< const Lang::Value
>( ) )
1217 Ast::LexicalVariableNameExpr::~LexicalVariableNameExpr( )
1221 Ast::LexicalVariableNameExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1223 Ast::Node
* n
= parent
->parent( );
1226 Ast::BindNode
* bn
= dynamic_cast< Ast::DefineVariable
* >( n
);
1229 std::ostringstream os
;
1230 bn
->id( )->show( os
, Ast::Identifier::VARIABLE
);
1231 value_
= Kernel::ValueRef( new Lang::String( strrefdup( os
) ) );
1236 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." ) ) );
1240 Ast::LexicalVariableNameExpr::eval( Kernel::EvalState
* evalState
) const
1242 Kernel::ContRef cont
= evalState
->cont_
;
1243 cont
->takeValue( value_
, evalState
);
1247 Kernel::AssertStructureContinuation::AssertStructureContinuation( const Kernel::ContRef
& cont
, const Ast::SourceLocation
& traceLoc
)
1248 : Kernel::Continuation( traceLoc
), cont_( cont
)
1251 Kernel::AssertStructureContinuation::~AssertStructureContinuation( )
1255 Kernel::AssertStructureContinuation::takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
1257 evalState
->cont_
= cont_
;
1258 cont_
->takeValue( Helpers::down_cast_ContinuationArgument
< const Lang::Structure
>( val
, this ), evalState
);
1262 Kernel::AssertStructureContinuation::up( ) const
1267 RefCountPtr
< const char >
1268 Kernel::AssertStructureContinuation::description( ) const
1270 return strrefdup( "Assert type is struct" );
1274 Kernel::AssertStructureContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
1276 cont_
->gcMark( marked
);
1280 Ast::StructSplitReference::StructSplitReference( Ast::SourceLocation fieldLoc
, const char * fieldId
, Ast::Expression
* defaultExpr
)
1281 : Ast::Expression( fieldLoc
),
1282 structLoc_( Ast::THE_UNKNOWN_LOCATION
), // This is a dummy value! The correct value is set later.
1283 fieldId_( fieldId
),
1284 defaultExpr_( defaultExpr
)
1287 Ast::StructSplitReference::StructSplitReference( Ast::SourceLocation fieldLoc
, size_t fieldPos
, Ast::Expression
* defaultExpr
)
1288 : Ast::Expression( fieldLoc
),
1289 structLoc_( Ast::THE_UNKNOWN_LOCATION
), // This is a dummy value! The correct value is set later.
1290 fieldId_( 0 ), fieldPos_( fieldPos
),
1291 defaultExpr_( defaultExpr
)
1294 Ast::StructSplitReference::~StructSplitReference( )
1300 if( defaultExpr_
!= 0 )
1302 delete defaultExpr_
;
1307 Ast::StructSplitReference::setStruct( Ast::SourceLocation structLoc
, size_t ** structPos
)
1309 structLoc_
= structLoc
;
1310 structPos_
= structPos
;
1314 Ast::StructSplitReference::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1316 if( defaultExpr_
!= 0 )
1318 defaultExpr_
->analyze( this, env
, freeStatesDst
);
1323 Ast::StructSplitReference::eval( Kernel::EvalState
* evalState
) const
1325 Kernel::VariableHandle structHandle
= evalState
->env_
->getVarHandle( **structPos_
);
1326 typedef const Lang::Structure StructType
;
1327 RefCountPtr
< StructType
> structVal
= structHandle
->getVal
< StructType
>( "Type-checked value in StructSplitReference::eval." );
1329 Kernel::ContRef cont
= evalState
->cont_
;
1334 cont
->takeHandle( structVal
->getField( fieldId_
, structVal
),
1338 catch( const Exceptions::NonExistentMember
& ball
)
1340 if( defaultExpr_
== 0 )
1344 // Never mind, we use the default instead. See below.
1351 cont
->takeHandle( structVal
->getPosition( fieldPos_
, structVal
),
1355 catch( const Exceptions::NonExistentPosition
& ball
)
1357 if( defaultExpr_
== 0 )
1361 // Never mind, we use the default instead. See below.
1365 if( defaultExpr_
== 0 )
1367 throw Exceptions::InternalError( "Just about to use null pointer defaultExpr_ in StructSplitReference::eval." );
1369 evalState
->expr_
= defaultExpr_
;
1372 Ast::StructSplitSink::StructSplitSink( )
1373 : Ast::Expression( Ast::THE_UNKNOWN_LOCATION
), structLoc_( Ast::THE_UNKNOWN_LOCATION
)
1376 Ast::StructSplitSink::~StructSplitSink( )
1380 Ast::StructSplitSink::setStruct( Ast::SourceLocation structLoc
, size_t ** structPos
, size_t consumedArguments
)
1382 structLoc_
= structLoc
;
1383 structPos_
= structPos
;
1384 consumedArguments_
= consumedArguments
;
1388 Ast::StructSplitSink::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1390 /* Nothing to do! */
1394 Ast::StructSplitSink::eval( Kernel::EvalState
* evalState
) const
1396 Kernel::VariableHandle structHandle
= evalState
->env_
->getVarHandle( **structPos_
);
1397 typedef const Lang::Structure StructType
;
1398 RefCountPtr
< StructType
> structVal
= structHandle
->getVal
< StructType
>( "Type-checked value in StructSplitReference::eval." );
1400 Kernel::ContRef cont
= evalState
->cont_
;
1401 cont
->takeValue( structVal
->getSink( consumedArguments_
),
1406 Ast::AssertNoSinkNeeded::AssertNoSinkNeeded( const Ast::SourceLocation
& loc
, size_t orderedCount
, Ast::SourceLocation structLoc
, size_t ** structPos
)
1407 : Ast::Assertion( loc
), orderedCount_( orderedCount
), structLoc_( structLoc
), structPos_( structPos
)
1410 Ast::AssertNoSinkNeeded::~AssertNoSinkNeeded( )
1414 Ast::AssertNoSinkNeeded::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1416 /* immediate_ is already true by the inheritage from Ast::Assertion. */
1420 Ast::AssertNoSinkNeeded::eval( Kernel::EvalState
* evalState
) const
1422 Kernel::VariableHandle structHandle
= evalState
->env_
->getVarHandle( **structPos_
);
1423 typedef const Lang::Structure StructType
;
1424 RefCountPtr
< StructType
> structVal
= structHandle
->getVal
< StructType
>( "Type-checked value in StructSplitReference::eval." );
1426 if( structVal
->argList_
->orderedExprs_
->size( ) > orderedCount_
)
1428 throw Exceptions::SinkRequired( loc_
, orderedCount_
, structVal
->argList_
->orderedExprs_
->size( ) );
1431 Kernel::ContRef cont
= evalState
->cont_
;
1432 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
, evalState
);
1435 size_t Ast::SplitDefineVariables::splitVarCount
= 0;
1436 PtrOwner_back_Access
< std::list
< const Ast::PlacedIdentifier
* > > Ast::SplitDefineVariables::mem
;
1438 Ast::SplitDefineVariables::SplitDefineVariables( )
1439 : sinkDefine_( 0 ), sinkExpr_( 0 ), seenNamed_( false ), seenDefault_( false )
1441 std::ostringstream oss
;
1442 oss
<< Kernel::SPLIT_VAR_PREFIX
<< splitVarCount
;
1443 splitVarId_
= new Ast::PlacedIdentifier( Lang::THE_NAMESPACE_Shapes
, strdup( oss
.str( ).c_str( ) ) );
1444 mem
.push_back( splitVarId_
);
1448 Ast::PlacedIdentifier
*
1449 Ast::SplitDefineVariables::newSplitVarId( ) const
1451 return splitVarId_
->clone( );
1455 Ast::StateReference::StateReference( const Ast::SourceLocation
& loc
)
1459 Ast::StateReference::~StateReference( )
1463 Ast::LexiographicState::LexiographicState( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
, Kernel::Environment::LexicalKey
** idKey
)
1464 : Ast::StateReference( loc
), id_( id
), idKey_( idKey
)
1467 Ast::LexiographicState::~LexiographicState( )
1474 delete idKey_
; // This can be done only as long as this is not shared!
1478 Ast::LexiographicState::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1480 /* The following lines is the ugly solution to the problem that the inherited parent_ and analysisEnv_
1481 * are not well defined for reused nodes. And nodes of this type are typically reused.
1482 * For this type of node, one _could_ refer to someParent_ and someAnalysisEnv_ instead, but probably,
1483 * it is a mistake to even try.
1485 someParent_
= parent_
;
1487 someAnalysisEnv_
= analysisEnv_
;
1492 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalStateKey( loc_
, *id_
, this ) );
1494 if( ! (*idKey_
)->isMissing( ) )
1496 freeStatesDst
->insert( env
->getStateID( **idKey_
) );
1501 Ast::LexiographicState::getHandle( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1503 return env
->getStateHandle( **idKey_
);
1507 Ast::DynamicState::DynamicState( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
)
1508 : Ast::StateReference( loc
), id_( id
), idKey_( new Kernel::Environment::LexicalKey
* ( 0 ) )
1511 Ast::DynamicState::~DynamicState( )
1518 delete idKey_
; // This can be done only as long as this is not shared!
1522 Ast::DynamicState::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1524 /* See comment in LexicalState::analyze_impl.
1526 someParent_
= parent_
;
1528 someAnalysisEnv_
= analysisEnv_
;
1531 /* It would make sense to check the reference and...
1532 * This might be overly conservative... but we really shouldn't support dynamic states anyway.
1534 freeStatesDst
->insert( Ast::AnalysisEnvironment::getTheAnyStateID( ) );
1538 Ast::DynamicState::getHandle( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1540 throw Exceptions::NotImplemented( "Referencing dynamic states" );
1544 Ast::IntroduceState::IntroduceState( const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, Ast::Expression
* expr
, size_t ** idPos
)
1545 : Ast::BindNode( Ast::SourceLocation( idLoc
, expr
->loc( ) ), idLoc
, id
), expr_( expr
), idPos_( idPos
)
1548 Ast::IntroduceState::~IntroduceState( )
1552 /* idPos_ shared and will be a memory leak which must not be deleted.
1553 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1559 Ast::IntroduceState::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1561 expr_
->analyze( this, env
, freeStatesDst
);
1564 *idPos_
= new size_t( env
->findLocalStatePosition( idLoc_
, *id_
) );
1567 const Ast::Node
* firstUse
= env
->getStateFirstUse( **idPos_
);
1568 if( firstUse
!= NULL
){
1569 Ast::theAnalysisErrorsList
.push_back( new Exceptions::StateUninitializedUse( firstUse
->loc( ), id_
, this ) );
1572 stateID_
= env
->getStateID( **idPos_
);
1573 freeStatesDst
->insert( stateID_
);
1577 Ast::IntroduceState::initializeEnvironment( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1579 /* Although it would be possible to insert some kind of thunk in the environment here,
1580 * it is not obvious that such a feature would be desirable. With such a feature, one
1581 * would be able to use a state before the place in the code where it is introduced:
1588 * This just seems awkward; this is a stateful program, and order generally matters -- this is
1589 * why use before declaration is considered illegal and treated as error already during
1595 Ast::IntroduceState::evalHelper( Kernel::EvalState
* evalState
) const
1597 evalState
->cont_
= Kernel::ContRef( new Kernel::IntroduceStateContinuation( evalState
->env_
,
1601 evalState
->expr_
= expr_
;
1605 Ast::Insertion::Insertion( Ast::StateReference
* stateRef
, Ast::Expression
* expr
)
1606 : Ast::Expression( Ast::SourceLocation( stateRef
->loc( ), expr
->loc( ) ) ), stateRef_( stateRef
), expr_( expr
)
1609 Ast::Insertion::~Insertion( )
1613 Ast::Insertion::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1615 stateRef_
->analyze( this, env
, freeStatesDst
); /* This will always add something to the set of free states. */
1616 expr_
->analyze( this, env
, freeStatesDst
);
1620 Ast::Insertion::eval( Kernel::EvalState
* evalState
) const
1622 evalState
->cont_
= Kernel::ContRef( new Kernel::InsertionContinuation( stateRef_
->getHandle( evalState
->env_
, evalState
->dyn_
),
1626 evalState
->expr_
= expr_
;
1629 Ast::InsertionMutatorCall::InsertionMutatorCall( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
1630 : Ast::Expression( loc
), expr_( expr
)
1633 Ast::InsertionMutatorCall::~InsertionMutatorCall( )
1637 Ast::InsertionMutatorCall::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1639 throw Exceptions::InternalError( loc_
, "An InsertionMutatorCall was analyzed (the contained expression should have been extracted and replaced this object)." );
1643 Ast::InsertionMutatorCall::eval( Kernel::EvalState
* evalState
) const
1645 throw Exceptions::InternalError( loc_
, "An InsertionMutatorCall was evaluated (the contained expression should have been extracted and replaced this object)." );
1649 Ast::Freeze::Freeze( const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, size_t ** idPos
)
1650 : Ast::Expression( idLoc
), id_( id
), idPos_( idPos
)
1655 Ast::Freeze::~Freeze( )
1657 /* idPos shared and will be a memory leak which must not be deleted.
1658 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1663 Ast::Freeze::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1667 *idPos_
= new size_t( env
->findLocalStatePosition( loc( ), *id_
) );
1670 freeStatesDst
->insert( env
->getStateID( **idPos_
) );
1674 Ast::Freeze::eval( Kernel::EvalState
* evalState
) const
1676 evalState
->env_
->freeze( **idPos_
, evalState
, loc( ) );
1680 Ast::Peek::Peek( const Ast::SourceLocation
& idLoc
, Ast::StateReference
* stateRef
)
1681 : Ast::Expression( idLoc
), stateRef_( stateRef
)
1688 /* idPos shared and will be a memory leak which must not be deleted.
1689 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1694 Ast::Peek::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1696 stateRef_
->analyze( this, env
, freeStatesDst
); /* This will always add something to the set of free states. */
1700 Ast::Peek::eval( Kernel::EvalState
* evalState
) const
1702 stateRef_
->getHandle( evalState
->env_
, evalState
->dyn_
)->peek( evalState
, loc( ) );
1706 Ast::DynamicExpression::DynamicExpression( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
1707 : Ast::Expression( loc
), expr_( expr
)
1712 Ast::DynamicExpression::~DynamicExpression( )
1716 Ast::DynamicExpression::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1718 Ast::StateIDSet
* freeStates
= new Ast::StateIDSet
;
1719 expr_
->analyze( this, env
, freeStates
);
1721 if( ! freeStates
->empty( ) )
1723 Ast::theAnalysisErrorsList
.push_back( new Exceptions::IllegalFreeStates( expr_
->loc( ), freeStates
, "dynamic expressions must be pure" ) );
1732 Ast::DynamicExpression::eval( Kernel::EvalState
* evalState
) const
1734 Kernel::ContRef cont
= evalState
->cont_
;
1735 cont
->takeValue( Kernel::ValueRef( new Lang::DynamicExpression( evalState
->env_
, expr_
) ),
1740 Ast::LexiographicType::LexiographicType( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
, Kernel::Environment::LexicalKey
** idKey
)
1741 : Ast::Expression( loc
), id_( id
), idKey_( idKey
)
1746 Ast::LexiographicType::~LexiographicType( )
1753 delete idKey_
; /* This can be done only as long as this is not shared! */
1757 Ast::LexiographicType::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1761 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalTypeKey( loc_
, *id_
) );
1766 Ast::LexiographicType::eval( Kernel::EvalState
* evalState
) const
1768 evalState
->env_
->lookup( **idKey_
, evalState
);