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
327 Ast::Expression
* e
= dynamic_cast< Ast::Expression
* >( *pos
);
329 std::list
< Ast::Node
* >::const_iterator next
= pos
;
331 if( next
== nodes_
->end( ) )
336 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingContinuation( info
->cont_
, (*pos
)->loc( ) ) );
340 evalState
->cont_
= info
->cont_
;
345 evalState
->cont_
= Kernel::ContRef( new Kernel::CodeBracketContinuation( (*pos
)->loc( ), info
, next
) );
348 evalState
->env_
= info
->env_
;
349 evalState
->dyn_
= info
->dyn_
;
352 evalState
->expr_
= e
;
355 const Ast::BindNode
* bn
= dynamic_cast< const Ast::BindNode
* >( *pos
);
358 bn
->evalHelper( evalState
);
361 throw Exceptions::InternalError( (*pos
)->loc( ), "CodeBracket::evalAt: Node was neither Expression or BindNode." );
365 Kernel::CodeBracketContInfo::CodeBracketContInfo( const Ast::CodeBracket
* bracketExpr
, const Kernel::EvalState
& evalState
)
366 : bracketExpr_( bracketExpr
), env_( evalState
.env_
), dyn_( evalState
.dyn_
), cont_( evalState
.cont_
)
369 Kernel::CodeBracketContInfo::~CodeBracketContInfo( )
373 Kernel::CodeBracketContInfo::gcMark( Kernel::GCMarkedSet
& marked
)
375 env_
->gcMark( marked
);
376 dyn_
->gcMark( marked
);
377 cont_
->gcMark( marked
);
380 Kernel::CodeBracketContinuation::CodeBracketContinuation( const Ast::SourceLocation
& traceLoc
, const RefCountPtr
< const Kernel::CodeBracketContInfo
> & info
, const std::list
< Ast::Node
* >::const_iterator
& pos
)
381 : Kernel::Continuation( traceLoc
), info_( info
), pos_( pos
)
384 Kernel::CodeBracketContinuation::~CodeBracketContinuation( )
388 Kernel::CodeBracketContinuation::takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
390 if( val
.down_cast
< const Lang::Void
>( ) == NullPtr
< const Lang::Void
>( ) )
392 throw Exceptions::NonVoidStatement( traceLoc_
, val
);
394 info_
->bracketExpr_
->evalAt( info_
,
400 Kernel::CodeBracketContinuation::up( ) const
405 RefCountPtr
< const char >
406 Kernel::CodeBracketContinuation::description( ) const
408 return strrefdup( "code bracket" );
412 Kernel::CodeBracketContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
414 const_cast< Kernel::CodeBracketContInfo
* >( info_
.getPtr( ) )->gcMark( marked
);
418 Ast::LexiographicVariable::LexiographicVariable( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
, Kernel::Environment::LexicalKey
** idKey
)
419 : Ast::Expression( loc
), id_( id
), idKey_( idKey
)
424 Ast::LexiographicVariable::~LexiographicVariable( )
431 delete idKey_
; /* This can be done only as long as this is not shared! */
435 Ast::LexiographicVariable::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
439 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalVariableKey( loc_
, *id_
) );
441 scope_level_
= env
->level( ) - (*idKey_
)->up_
;
445 Ast::LexiographicVariable::eval( Kernel::EvalState
* evalState
) const
447 evalState
->env_
->lookup( **idKey_
, evalState
);
451 Ast::PrivateAliasVariable::PrivateAliasVariable( const Ast::SourceLocation
& loc
, const Ast::PlacedIdentifier
& id
, const RefCountPtr
< const char > & privateName
)
452 : Ast::Expression( loc
), id_( id
), privateName_( privateName
), aliasKey_( NULL
)
457 Ast::PrivateAliasVariable::~PrivateAliasVariable( )
459 /* Don't delete id_ -- it will be shared with the id_ of a DefineVariable. */
460 if( aliasKey_
!= NULL
){
466 Ast::PrivateAliasVariable::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
468 aliasKey_
= new Kernel::Environment::LexicalKey( env
->findPrivateAliasVariableKey( loc_
, id_
, privateName_
.getPtr( ) ) );
472 Ast::PrivateAliasVariable::eval( Kernel::EvalState
* evalState
) const
474 evalState
->env_
->lookup( *aliasKey_
, evalState
);
478 Ast::Force::Force( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
479 : Ast::Expression( loc
), expr_( expr
)
484 Ast::Force::~Force( )
490 Ast::Force::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
492 expr_
->analyze( this, env
, freeStatesDst
);
496 Ast::Force::eval( Kernel::EvalState
* evalState
) const
498 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingContinuation( evalState
->cont_
, loc_
) );
499 evalState
->expr_
= expr_
;
503 Ast::EvalOutsideExpr::EvalOutsideExpr( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
504 : Ast::Expression( loc
), expr_( expr
)
509 Ast::EvalOutsideExpr::~EvalOutsideExpr( )
515 Ast::EvalOutsideExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
517 expr_
->analyze( this, env
->getParent( ), freeStatesDst
);
521 Ast::EvalOutsideExpr::eval( Kernel::EvalState
* evalState
) const
523 evalState
->expr_
= expr_
;
524 evalState
->env_
= evalState
->env_
->getParent( );
528 Ast::MemberReferenceFunction::MemberReferenceFunction( const Ast::SourceLocation
& loc
, Ast::Expression
* variable
, const char * fieldID
)
529 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<>.<>" ), true ) ), loc_( loc
), variable_( variable
), fieldID_( fieldID
)
532 Ast::MemberReferenceFunction::~MemberReferenceFunction( )
539 Ast::MemberReferenceFunction::push_exprs( Ast::ArgListExprs
* args
) const
541 args
->orderedExprs_
->push_back( variable_
);
545 Ast::MemberReferenceFunction::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
547 /* The variable is analyzed as part of the arguments passed to this function, so nothing needs to be done here...
548 * unless we would be able to figure out the type of the argument, and then check if the field reference is valid.
553 Ast::MemberReferenceFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
555 Kernel::ContRef cont
= evalState
->cont_
;
556 RefCountPtr
< const Lang::Value
> arg
= args
.getValue( 0 );
557 cont
->takeHandle( arg
->getField( fieldID_
, arg
),
563 Ast::MutatorReference::MutatorReference( const Ast::SourceLocation
& mutatorLoc
, Ast::StateReference
* state
, const char * mutatorID
)
564 : Ast::Expression( mutatorLoc
), mutatorLoc_( mutatorLoc
), state_( state
), mutatorID_( mutatorID
)
567 Ast::MutatorReference::~MutatorReference( )
569 /* At the time of implementing this bug-fix, state_ will allways be owned by the Ast::CallExpr that is also the owner of us.
570 * Hence, we do not consider ourselves owners. Perhaps one should have a flag indicating whether ownership is transferred
571 * when calling the constructor, but at the moment this seems like a waste of resources.
578 Ast::MutatorReference::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
580 state_
->analyze( this, env
, freeStatesDst
);
581 /* If the type of the state was known here, we should verify that there is a mutator corresponding to the message <mutatorID>.
586 Ast::MutatorReference::eval( Kernel::EvalState
* evalState
) const
588 Kernel::ContRef cont
= evalState
->cont_
;
589 cont
->takeValue( state_
->getHandle( evalState
->env_
, evalState
->dyn_
)->getMutator( mutatorID_
),
595 Ast::SpecialLength::SpecialLength( const Ast::SourceLocation
& loc
, double val
, int sort
)
596 : Ast::Expression( loc
), val_( val
), sort_( sort
)
599 Ast::SpecialLength::~SpecialLength( )
603 Ast::SpecialLength::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
609 Ast::SpecialLength::eval( Kernel::EvalState
* evalState
) const
615 evalState
->dyn_
->specialUnitService( & d
, & a0
, & a1
);
617 if( sort_
== Computation::SPECIALU_NOINFLEX
)
619 Kernel::ContRef cont
= evalState
->cont_
;
620 cont
->takeValue( Kernel::ValueRef( new Lang::Length( val_
* d
* Computation::specialUnitNoInflexion( a0
, a1
) ) ),
624 if( ! sort_
& Computation::SPECIALU_DIST
)
626 throw Exceptions::InternalError( strrefdup( "The special unit is neither based on inflexion or distance" ) );
631 if( sort_
& Computation::SPECIALU_CIRC
)
633 res
*= Computation::specialUnitCircleHandle( a0
);
636 if( sort_
& Computation::SPECIALU_CORR
)
638 res
*= Computation::specialUnitCorrection( a0
, a1
);
641 if( sort_
& Computation::SPECIALU_NOINFLEX
)
643 res
= min( res
, Computation::specialUnitNoInflexion( a0
, a1
) );
645 Kernel::ContRef cont
= evalState
->cont_
;
646 cont
->takeValue( Kernel::ValueRef( new Lang::Length( val_
* d
* res
) ),
651 Ast::DynamicVariable::DynamicVariable( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
)
652 : Ast::Expression( loc
), id_( id
), idKey_( new Kernel::Environment::LexicalKey
* ( 0 ) )
657 Ast::DynamicVariable::~DynamicVariable( )
664 delete idKey_
; // This can be done only as long as this is not shared!
668 Ast::DynamicVariable::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
672 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalDynamicKey( loc_
, *id_
) );
677 Ast::DynamicVariable::eval( Kernel::EvalState
* evalState
) const
679 const Kernel::DynamicVariableProperties
& dynProps
= evalState
->env_
->lookupDynamicVariable( **idKey_
);
681 Kernel::VariableHandle res
= dynProps
.fetch( evalState
->dyn_
);
683 /* Now, we know that if the value was bound to a dynamic expression, a value was bound, and that value has
686 if( ! res
->isThunk( ) )
690 typedef const Lang::DynamicExpression DynType
;
691 RefCountPtr
< DynType
> dynVal
= res
->tryVal
< DynType
>( );
692 dynVal
->evalHelper( evalState
);
695 catch( const NonLocalExit::NotThisType
& ball
)
701 Kernel::ContRef cont
= evalState
->cont_
;
702 cont
->takeHandle( res
,
707 Kernel::DynamicBindingContinuation::DynamicBindingContinuation( const Ast::SourceLocation
& traceLoc
, const Kernel::PassedEnv
& env
, const Kernel::Environment::LexicalKey
& key
, const Ast::DynamicBindingExpression
* bindingExpr
, const Kernel::ContRef
& cont
)
708 : Kernel::Continuation( traceLoc
), env_( env
), key_( key
), bindingExpr_( bindingExpr
), cont_( cont
)
711 Kernel::DynamicBindingContinuation::~DynamicBindingContinuation( )
715 Kernel::DynamicBindingContinuation::takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
717 if( val
->isThunk( ) )
719 val
->force( val
, evalState
);
722 evalState
->cont_
= cont_
;
723 env_
->lookupDynamicVariable( key_
).makeBinding( val
, bindingExpr_
, evalState
);
727 Kernel::DynamicBindingContinuation::up( ) const
732 RefCountPtr
< const char >
733 Kernel::DynamicBindingContinuation::description( ) const
735 return strrefdup( "dynamic binding" );
739 Kernel::DynamicBindingContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
741 env_
->gcMark( marked
);
742 cont_
->gcMark( marked
);
745 Ast::DynamicBindingExpression::DynamicBindingExpression( const Ast::SourceLocation
& idLoc
, const Ast::Identifier
* id
, Ast::Expression
* expr
, Kernel::Environment::LexicalKey
** idKey
)
746 : Ast::Expression( Ast::SourceLocation( idLoc
, expr
->loc( ) ) ), idLoc_( idLoc
), id_( id
), expr_( expr
), idKey_( new Kernel::Environment::LexicalKey
* ( 0 ) )
749 Ast::DynamicBindingExpression::~DynamicBindingExpression( )
758 // Don't delete idKey as it's shared!
762 Ast::DynamicBindingExpression::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
764 expr_
->analyze( this, env
, freeStatesDst
);
767 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalDynamicKey( idLoc_
, *id_
) );
772 Ast::DynamicBindingExpression::eval( Kernel::EvalState
* evalState
) const
774 const Kernel::DynamicVariableProperties
& dynProps
= evalState
->env_
->lookupDynamicVariable( **idKey_
);
776 if( dynProps
.forceValue( ) || expr_
->immediate_
)
778 evalState
->expr_
= expr_
;
779 evalState
->cont_
= Kernel::ContRef( new Kernel::DynamicBindingContinuation( expr_
->loc( ), evalState
->env_
, **idKey_
, this, evalState
->cont_
) );
783 dynProps
.makeBinding( Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( evalState
->env_
, evalState
->dyn_
, expr_
) ) ),
790 Ast::DynamicStateBindingExpression::DynamicStateBindingExpression( const Ast::SourceLocation
& loc
, const Ast::SourceLocation
& dstLoc
, const Ast::Identifier
* dstId
, Ast::StateReference
* src
)
791 : Ast::Expression( loc
), dstLoc_( dstLoc
), dstId_( dstId
), dstIdKey_( new Kernel::Environment::LexicalKey
* ( 0 ) ), src_( src
)
794 Ast::DynamicStateBindingExpression::~DynamicStateBindingExpression( )
797 if( *dstIdKey_
!= 0 )
801 delete dstIdKey_
; // This can be done only as long as this is not shared!
805 Ast::DynamicStateBindingExpression::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
807 if( *dstIdKey_
== 0 )
809 *dstIdKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalDynamicKey( dstLoc_
, *dstId_
) );
814 Ast::DynamicStateBindingExpression::eval( Kernel::EvalState
* evalState
) const
816 const Kernel::DynamicStateProperties
& dstDynProps
= evalState
->env_
->lookupDynamicState( **dstIdKey_
);
818 dstDynProps
.makeBinding( src_
->getHandle( evalState
->env_
, evalState
->dyn_
), this, evalState
);
822 Kernel::WithDynamicContinuation::WithDynamicContinuation( const Ast::SourceLocation
& traceLoc
, Ast::Expression
* expr
, const Kernel::EvalState
& evalState
)
823 : Kernel::Continuation( traceLoc
), expr_( expr
), env_( evalState
.env_
), dyn_( evalState
.dyn_
), cont_( evalState
.cont_
)
826 Kernel::WithDynamicContinuation::~WithDynamicContinuation( )
830 Kernel::WithDynamicContinuation::takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
832 evalState
->dyn_
= Kernel::PassedDyn( new Kernel::DynamicEnvironment( dyn_
, *Helpers::down_cast
< const Lang::DynamicBindings
>( val
, traceLoc_
) ) );
833 evalState
->env_
= env_
;
834 evalState
->expr_
= expr_
;
835 evalState
->cont_
= cont_
;
839 Kernel::WithDynamicContinuation::up( ) const
844 RefCountPtr
< const char >
845 Kernel::WithDynamicContinuation::description( ) const
847 return strrefdup("with dynamic bindings" );
851 Kernel::WithDynamicContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
853 env_
->gcMark( marked
);
854 dyn_
->gcMark( marked
);
855 cont_
->gcMark( marked
);
859 Ast::WithDynamicExpr::WithDynamicExpr( const Ast::SourceLocation
& loc
, Ast::Expression
* bindings
, Ast::Expression
* expr
)
860 : Ast::Expression( loc
), bindings_( bindings
), expr_( expr
)
863 Ast::WithDynamicExpr::~WithDynamicExpr( )
867 Ast::WithDynamicExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
869 bindings_
->analyze( this, env
, freeStatesDst
);
870 expr_
->analyze( this, env
, freeStatesDst
);
874 Ast::WithDynamicExpr::eval( Kernel::EvalState
* evalState
) const
876 evalState
->expr_
= bindings_
;
877 evalState
->cont_
= Kernel::ContRef( new Kernel::WithDynamicContinuation( bindings_
->loc( ), expr_
, *evalState
) );
881 Ast::DynamicVariableDecl::DynamicVariableDecl( const Ast::SourceLocation
& loc
, const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, Ast::Expression
* filterExpr
, Ast::Expression
* defaultExpr
)
882 : Ast::BindNode( loc
, idLoc
, id
), idPos_( new size_t * ( 0 ) )
884 /* This type of expression is an Ast::BindNode so that it is easy to recognize and extract the identifier for static analysis
887 * The expression is implemented as a function call, since there are two subexpressions that may need evaluation.
890 Ast::ArgListExprs
* args
= new Ast::ArgListExprs( false );
891 Ast::DynamicVariableDeclFunction
* res
= new Ast::DynamicVariableDeclFunction( id
, filterExpr
, defaultExpr
, idPos_
);
892 res
->push_exprs( args
);
893 Ast::CallExpr
* callExpr
=
894 new Ast::CallExpr( loc
,
895 RefCountPtr
< const Lang::Function
>( res
),
897 /* Wrap the call in Ast::Force as a poor substitute for doing the right thing, see comment in initializeEnvironment. */
898 impl_
= new Ast::Force( loc
, callExpr
);
901 Ast::DynamicVariableDecl::~DynamicVariableDecl( )
905 Ast::DynamicVariableDecl::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
907 impl_
->analyze( this, env
, freeStatesDst
);
909 *idPos_
= new size_t( env
->findLocalDynamicPosition( idLoc_
, *id_
) );
914 Ast::DynamicVariableDecl::initializeEnvironment( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
916 /* Here, the right thing to do is probably to put the impl_ call in a DynamicVariableProperties thunk, but
917 * that type of thunk is not invented yet.
919 * As a poor substitute for the right thing, the impl_ call is wrapped in Ast::Force, see contructor.
924 Ast::DynamicVariableDecl::evalHelper( Kernel::EvalState
* evalState
) const
926 evalState
->expr_
= impl_
;
930 Ast::DynamicVariableDeclFunction::DynamicVariableDeclFunction( const Ast::PlacedIdentifier
* id
, Ast::Expression
* filterExpr
, Ast::Expression
* defaultExpr
, size_t ** idPos
)
931 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< dynamic variable declaration >" ) ) ), id_( id
), filterExpr_( filterExpr
), defaultExpr_( defaultExpr
), idPos_( idPos
)
933 formals_
->appendEvaluatedCoreFormal( "filter", Kernel::THE_SLOT_VARIABLE
, true );
934 formals_
->appendEvaluatedCoreFormal( "default", Kernel::THE_SLOT_VARIABLE
, false );
937 Ast::DynamicVariableDeclFunction::~DynamicVariableDeclFunction( )
944 Ast::DynamicVariableDeclFunction::push_exprs( Ast::ArgListExprs
* args
) const
946 args
->orderedExprs_
->push_back( filterExpr_
);
947 args
->orderedExprs_
->push_back( defaultExpr_
);
951 Ast::DynamicVariableDeclFunction::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
953 /* The analysis is carried out by the DynamicVariableDecl expression.
958 Ast::DynamicVariableDeclFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
960 static const char * title
= "< dynamic variable declaration >";
961 typedef const Lang::Function FilterType
;
962 evalState
->env_
->defineDynamic( id_
,
964 Helpers::down_cast_CoreArgument
< FilterType
>( title
, args
, 0, callLoc
),
965 args
.getHandle( 1 ) );
967 Kernel::ContRef cont
= evalState
->cont_
;
968 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
972 Kernel::DynamicVariableDeclContinuation::DynamicVariableDeclContinuation( const Ast::SourceLocation
& traceLoc
, const Ast::DynamicVariableDecl
*, Kernel::EvalState
& evalState
)
973 : Kernel::Continuation( traceLoc
), env_( evalState
.env_
), dyn_( evalState
.dyn_
), cont_( evalState
.cont_
)
976 Kernel::DynamicVariableDeclContinuation::~DynamicVariableDeclContinuation( )
980 Kernel::DynamicVariableDeclContinuation::takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
982 evalState
->env_
= env_
;
983 evalState
->dyn_
= dyn_
;
984 evalState
->cont_
= cont_
;
985 throw Exceptions::NotImplemented( "Deprecated: DynamicVariableDeclContinuation" );
986 // declExpr_->callBack( Helpers::down_cast< const Lang::Function >( val, traceLoc_ ),
991 Kernel::DynamicVariableDeclContinuation::up( ) const
996 RefCountPtr
< const char >
997 Kernel::DynamicVariableDeclContinuation::description( ) const
999 return strrefdup( "dynamic variable declaration" );
1003 Kernel::DynamicVariableDeclContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
1005 env_
->gcMark( marked
);
1006 dyn_
->gcMark( marked
);
1007 cont_
->gcMark( marked
);
1011 Ast::DynamicStateDecl::DynamicStateDecl( const Ast::SourceLocation
& loc
, const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, Ast::StateReference
* defaultState
, size_t ** idPos
)
1012 : Ast::BindNode( loc
, idLoc
, id
), idPos_( idPos
), defaultState_( defaultState
)
1015 Ast::DynamicStateDecl::~DynamicStateDecl( )
1020 Ast::DynamicStateDecl::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1024 *idPos_
= new size_t( env
->findLocalDynamicStatePosition( idLoc_
, *id_
) );
1029 Ast::DynamicStateDecl::initializeEnvironment( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1031 env
->defineDynamicState( id_
, **idPos_
, env
, dyn
, defaultState_
);
1035 Ast::DynamicStateDecl::evalHelper( Kernel::EvalState
* evalState
) const
1037 Kernel::ContRef cont
= evalState
->cont_
;
1038 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
1043 Ast::EvalSymbolFunction::EvalSymbolFunction( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
, const RefCountPtr
< const Ast::NamespacePath
> & lexicalPath
)
1044 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< symbol evaluation >" ), true ) ), loc_( loc
), expr_( expr
), lexicalPath_( lexicalPath
)
1047 Ast::EvalSymbolFunction::~EvalSymbolFunction( )
1053 Ast::EvalSymbolFunction::push_exprs( Ast::ArgListExprs
* args
) const
1055 args
->orderedExprs_
->push_back( expr_
);
1059 Ast::EvalSymbolFunction::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1063 /* expr_ shall be analyzed from the calling expression.
1064 * Here, it is only used to locate errors.
1069 Ast::EvalSymbolFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1071 static const RefCountPtr
< const Ast::NamespacePath
> EMPTY_RELATIVE_PATH( new Ast::NamespacePath( ) );
1073 RefCountPtr
< const Lang::Value
> untypedVal
= args
.getValue( 0 );
1074 typedef const Lang::Symbol ArgType
;
1075 ArgType
* val
= dynamic_cast< ArgType
* >( untypedVal
.getPtr( ) );
1078 throw Exceptions::TypeMismatch( expr_
->loc( ), untypedVal
->getTypeName( ), ArgType::staticTypeName( ) );
1080 if( val
->isUnique( ) )
1082 throw Exceptions::OutOfRange( expr_
->loc( ), strrefdup( "Unique symbols can't denote variables." ) );
1085 RefCountPtr
< const Ast::SearchContext
> searchContext( new Ast::SearchContext( lexicalPath_
, RefCountPtr
< const char >( NullPtr
< const char >( ) ) ) );
1086 Kernel::Environment::LexicalKey key
= analysisEnv_
->findLexicalVariableKey( loc_
, Ast::Identifier( searchContext
, Ast::NamespaceReference::RELATIVE
, EMPTY_RELATIVE_PATH
, val
->name( ).getPtr( ) ) );
1088 Kernel::PassedEnv env
= evalState
->env_
;
1089 env
->lookup( key
, evalState
);
1093 Ast::DefineVariable::DefineVariable( const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, Ast::Expression
* expr
, size_t ** idPos
)
1094 : Ast::BindNode( Ast::SourceLocation( idLoc
, expr
->loc( ) ), idLoc
, id
), expr_( expr
), idPos_( idPos
)
1097 Ast::DefineVariable::~DefineVariable( )
1101 /* idPos_ is shared and will be a memory leak which must not be deleted.
1102 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1107 Ast::DefineVariable::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1109 Ast::StateIDSet freeStates
;
1110 expr_
->analyze( this, env
, & freeStates
);
1111 if( ! freeStates
.empty( ) )
1113 Ast::Force
* forcedExpr( new Ast::Force( loc_
, expr_
) );
1114 /* The forcedExpr should not be analyzed since the contained expr_ is already
1115 * analyzed, and analyzing forcedExpr would just cause expr_ to be analyzed again.
1116 * Instead, we just need to update parent/child links.
1118 expr_
->changeParent( forcedExpr
);
1119 forcedExpr
->setParent( this, env
);
1121 for( Ast::StateIDSet::const_iterator i
= freeStates
.begin( ); i
!= freeStates
.end( ); ++i
)
1123 freeStatesDst
->insert( *i
);
1128 *idPos_
= new size_t( env
->findLocalVariablePosition( idLoc_
, *id_
) );
1133 Ast::DefineVariable::initializeEnvironment( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1135 env
->define( **idPos_
,
1136 Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( env
, dyn
, expr_
) ) ) );
1140 Ast::DefineVariable::evalHelper( Kernel::EvalState
* evalState
) const
1142 if( expr_
->immediate_
){
1143 Kernel::VariableHandle var
= evalState
->env_
->getVarHandle( **idPos_
);
1144 /* Using sufficient but not necessary condition for recognizing that the thunk
1145 * set up in initializeEnvironment is still not forced. The worst thing that
1146 * can happen is that another thunk for this expression, but in another environment
1147 * or another dynamic environment, is forced. If that happens, note that
1148 * expr_->immediate_ also applies to the other thunk, so it should be forced sooner or
1151 if( var
->isThunk( expr_
) ){
1152 evalState
->cont_
= Kernel::ContRef( new Kernel::IgnoreContinuation( evalState
->cont_
, expr_
->loc( ) ) );
1153 var
->force( var
, evalState
);
1158 Kernel::ContRef cont
= evalState
->cont_
;
1159 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
, evalState
);
1163 Ast::DefineAlias::DefineAlias( const Ast::SourceLocation
& idLoc
, const Ast::SourceLocation
& expansionLoc
, const Ast::PlacedIdentifier
* id
, const Ast::NamespaceReference
& expansion
)
1164 : Ast::Node( idLoc
), idLoc_( idLoc
), id_( id
), expansion_( expansion
), expansionLoc_( expansionLoc
)
1167 Ast::DefineAlias::~DefineAlias( )
1173 Ast::DefineAlias::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1175 throw Exceptions::InternalError( "Ast::DefineAlias::analyze_impl: Alias definitions should not be present at program analysis." );
1178 Ast::LexicalVariableLocationExpr::LexicalVariableLocationExpr( const Ast::SourceLocation
& idLoc
, const Ast::Identifier
* id
, Kind kind
)
1179 : Ast::Expression( idLoc
), id_( id
), kind_( kind
), value_( NullPtr
< const Lang::Value
>( ) )
1184 Ast::LexicalVariableLocationExpr::~LexicalVariableLocationExpr( )
1188 Ast::LexicalVariableLocationExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1190 Kernel::Environment::LexicalKey key
= Kernel::Environment::LexicalKey( env
->findLexicalVariableKey( loc_
, *id_
) );
1191 if( key
.isMissing( ) ){
1192 /* If the variable wasn't found, compilation will be terminated after the analysis sweep, and there's
1193 * no point in trying to assign something meaningless to value_.
1201 value_
= Kernel::ValueRef( new Lang::Integer( key
.pos_
) );
1204 value_
= Kernel::ValueRef( new Lang::Integer( key
.up_
) );
1208 Ast::PlacedIdentifier
idPlaced( env
->reverseMapLexicalVariable( key
) );
1209 std::ostringstream oss
;
1210 oss
<< Interaction::NAMESPACE_SEPARATOR
;
1211 idPlaced
.show( oss
, Ast::Identifier::VARIABLE
);
1212 value_
= Kernel::ValueRef( new Lang::String( strrefdup( oss
) ) );
1219 Ast::LexicalVariableLocationExpr::eval( Kernel::EvalState
* evalState
) const
1221 Kernel::ContRef cont
= evalState
->cont_
;
1222 cont
->takeValue( value_
, evalState
);
1226 Ast::LexicalVariableNameExpr::LexicalVariableNameExpr( const Ast::SourceLocation
& loc
)
1227 : Ast::Expression( loc
), value_( NullPtr
< const Lang::Value
>( ) )
1232 Ast::LexicalVariableNameExpr::~LexicalVariableNameExpr( )
1236 Ast::LexicalVariableNameExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1238 Ast::Node
* n
= parent
->parent( );
1241 Ast::BindNode
* bn
= dynamic_cast< Ast::DefineVariable
* >( n
);
1244 std::ostringstream os
;
1245 bn
->id( )->show( os
, Ast::Identifier::VARIABLE
);
1246 value_
= Kernel::ValueRef( new Lang::String( strrefdup( os
) ) );
1251 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." ) ) );
1255 Ast::LexicalVariableNameExpr::eval( Kernel::EvalState
* evalState
) const
1257 Kernel::ContRef cont
= evalState
->cont_
;
1258 cont
->takeValue( value_
, evalState
);
1262 Kernel::AssertStructureContinuation::AssertStructureContinuation( const Kernel::ContRef
& cont
, const Ast::SourceLocation
& traceLoc
)
1263 : Kernel::Continuation( traceLoc
), cont_( cont
)
1266 Kernel::AssertStructureContinuation::~AssertStructureContinuation( )
1270 Kernel::AssertStructureContinuation::takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
1272 evalState
->cont_
= cont_
;
1273 cont_
->takeValue( Helpers::down_cast_ContinuationArgument
< const Lang::Structure
>( val
, this ), evalState
);
1277 Kernel::AssertStructureContinuation::up( ) const
1282 RefCountPtr
< const char >
1283 Kernel::AssertStructureContinuation::description( ) const
1285 return strrefdup( "Assert type is struct" );
1289 Kernel::AssertStructureContinuation::gcMark( Kernel::GCMarkedSet
& marked
)
1291 cont_
->gcMark( marked
);
1295 Ast::StructSplitReference::StructSplitReference( Ast::SourceLocation fieldLoc
, const char * fieldId
, Ast::Expression
* defaultExpr
)
1296 : Ast::Expression( fieldLoc
),
1297 structLoc_( Ast::THE_UNKNOWN_LOCATION
), // This is a dummy value! The correct value is set later.
1298 fieldId_( fieldId
),
1299 defaultExpr_( defaultExpr
)
1302 Ast::StructSplitReference::StructSplitReference( Ast::SourceLocation fieldLoc
, size_t fieldPos
, Ast::Expression
* defaultExpr
)
1303 : Ast::Expression( fieldLoc
),
1304 structLoc_( Ast::THE_UNKNOWN_LOCATION
), // This is a dummy value! The correct value is set later.
1305 fieldId_( 0 ), fieldPos_( fieldPos
),
1306 defaultExpr_( defaultExpr
)
1309 Ast::StructSplitReference::~StructSplitReference( )
1315 if( defaultExpr_
!= 0 )
1317 delete defaultExpr_
;
1322 Ast::StructSplitReference::setStruct( Ast::SourceLocation structLoc
, size_t ** structPos
)
1324 structLoc_
= structLoc
;
1325 structPos_
= structPos
;
1329 Ast::StructSplitReference::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1331 if( defaultExpr_
!= 0 )
1333 defaultExpr_
->analyze( this, env
, freeStatesDst
);
1338 Ast::StructSplitReference::eval( Kernel::EvalState
* evalState
) const
1340 Kernel::VariableHandle structHandle
= evalState
->env_
->getVarHandle( **structPos_
);
1341 typedef const Lang::Structure StructType
;
1342 RefCountPtr
< StructType
> structVal
= structHandle
->getVal
< StructType
>( "Type-checked value in StructSplitReference::eval." );
1344 Kernel::ContRef cont
= evalState
->cont_
;
1349 cont
->takeHandle( structVal
->getField( fieldId_
, structVal
),
1353 catch( const Exceptions::NonExistentMember
& ball
)
1355 if( defaultExpr_
== 0 )
1359 // Never mind, we use the default instead. See below.
1366 cont
->takeHandle( structVal
->getPosition( fieldPos_
, structVal
),
1370 catch( const Exceptions::NonExistentPosition
& ball
)
1372 if( defaultExpr_
== 0 )
1376 // Never mind, we use the default instead. See below.
1380 if( defaultExpr_
== 0 )
1382 throw Exceptions::InternalError( "Just about to use null pointer defaultExpr_ in StructSplitReference::eval." );
1384 evalState
->expr_
= defaultExpr_
;
1387 Ast::StructSplitSink::StructSplitSink( )
1388 : Ast::Expression( Ast::THE_UNKNOWN_LOCATION
), structLoc_( Ast::THE_UNKNOWN_LOCATION
)
1391 Ast::StructSplitSink::~StructSplitSink( )
1395 Ast::StructSplitSink::setStruct( Ast::SourceLocation structLoc
, size_t ** structPos
, size_t consumedArguments
)
1397 structLoc_
= structLoc
;
1398 structPos_
= structPos
;
1399 consumedArguments_
= consumedArguments
;
1403 Ast::StructSplitSink::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1405 /* Nothing to do! */
1409 Ast::StructSplitSink::eval( Kernel::EvalState
* evalState
) const
1411 Kernel::VariableHandle structHandle
= evalState
->env_
->getVarHandle( **structPos_
);
1412 typedef const Lang::Structure StructType
;
1413 RefCountPtr
< StructType
> structVal
= structHandle
->getVal
< StructType
>( "Type-checked value in StructSplitReference::eval." );
1415 Kernel::ContRef cont
= evalState
->cont_
;
1416 cont
->takeValue( structVal
->getSink( consumedArguments_
),
1421 Ast::AssertNoSinkNeeded::AssertNoSinkNeeded( const Ast::SourceLocation
& loc
, size_t orderedCount
, Ast::SourceLocation structLoc
, size_t ** structPos
)
1422 : Ast::Assertion( loc
), orderedCount_( orderedCount
), structLoc_( structLoc
), structPos_( structPos
)
1425 Ast::AssertNoSinkNeeded::~AssertNoSinkNeeded( )
1429 Ast::AssertNoSinkNeeded::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1431 /* immediate_ is already true by the inheritage from Ast::Assertion. */
1435 Ast::AssertNoSinkNeeded::eval( Kernel::EvalState
* evalState
) const
1437 Kernel::VariableHandle structHandle
= evalState
->env_
->getVarHandle( **structPos_
);
1438 typedef const Lang::Structure StructType
;
1439 RefCountPtr
< StructType
> structVal
= structHandle
->getVal
< StructType
>( "Type-checked value in StructSplitReference::eval." );
1441 if( structVal
->argList_
->orderedExprs_
->size( ) > orderedCount_
)
1443 throw Exceptions::SinkRequired( loc_
, orderedCount_
, structVal
->argList_
->orderedExprs_
->size( ) );
1446 Kernel::ContRef cont
= evalState
->cont_
;
1447 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
, evalState
);
1450 size_t Ast::SplitDefineVariables::splitVarCount
= 0;
1451 PtrOwner_back_Access
< std::list
< const Ast::PlacedIdentifier
* > > Ast::SplitDefineVariables::mem
;
1453 Ast::SplitDefineVariables::SplitDefineVariables( )
1454 : sinkDefine_( 0 ), sinkExpr_( 0 ), seenNamed_( false ), seenDefault_( false )
1456 std::ostringstream oss
;
1457 oss
<< Kernel::SPLIT_VAR_PREFIX
<< splitVarCount
;
1458 splitVarId_
= new Ast::PlacedIdentifier( Lang::THE_CORE_NAMESPACE_PATH
, strdup( oss
.str( ).c_str( ) ) );
1459 mem
.push_back( splitVarId_
);
1463 Ast::PlacedIdentifier
*
1464 Ast::SplitDefineVariables::newSplitVarId( ) const
1466 return splitVarId_
->clone( );
1470 Ast::StateReference::StateReference( const Ast::SourceLocation
& loc
)
1474 Ast::StateReference::~StateReference( )
1478 Ast::LexiographicState::LexiographicState( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
, Kernel::Environment::LexicalKey
** idKey
)
1479 : Ast::StateReference( loc
), id_( id
), idKey_( idKey
)
1482 Ast::LexiographicState::~LexiographicState( )
1489 delete idKey_
; // This can be done only as long as this is not shared!
1493 Ast::LexiographicState::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1495 /* The following lines is the ugly solution to the problem that the inherited parent_ and analysisEnv_
1496 * are not well defined for reused nodes. And nodes of this type are typically reused.
1497 * For this type of node, one _could_ refer to someParent_ and someAnalysisEnv_ instead, but probably,
1498 * it is a mistake to even try.
1500 someParent_
= parent_
;
1502 someAnalysisEnv_
= analysisEnv_
;
1507 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalStateKey( loc_
, *id_
, this ) );
1509 if( ! (*idKey_
)->isMissing( ) )
1511 freeStatesDst
->insert( env
->getStateID( **idKey_
) );
1516 Ast::LexiographicState::getHandle( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1518 return env
->getStateHandle( **idKey_
);
1522 Ast::DynamicState::DynamicState( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
)
1523 : Ast::StateReference( loc
), id_( id
), idKey_( new Kernel::Environment::LexicalKey
* ( 0 ) )
1526 Ast::DynamicState::~DynamicState( )
1533 delete idKey_
; // This can be done only as long as this is not shared!
1537 Ast::DynamicState::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1539 /* See comment in LexicalState::analyze_impl.
1541 someParent_
= parent_
;
1543 someAnalysisEnv_
= analysisEnv_
;
1546 /* It would make sense to check the reference and...
1547 * This might be overly conservative... but we really shouldn't support dynamic states anyway.
1549 freeStatesDst
->insert( Ast::AnalysisEnvironment::getTheAnyStateID( ) );
1553 Ast::DynamicState::getHandle( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1555 throw Exceptions::NotImplemented( "Referencing dynamic states" );
1559 Ast::IntroduceState::IntroduceState( const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, Ast::Expression
* expr
, size_t ** idPos
)
1560 : Ast::BindNode( Ast::SourceLocation( idLoc
, expr
->loc( ) ), idLoc
, id
), expr_( expr
), idPos_( idPos
)
1563 Ast::IntroduceState::~IntroduceState( )
1567 /* idPos_ shared and will be a memory leak which must not be deleted.
1568 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1574 Ast::IntroduceState::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1576 expr_
->analyze( this, env
, freeStatesDst
);
1579 *idPos_
= new size_t( env
->findLocalStatePosition( idLoc_
, *id_
) );
1582 const Ast::Node
* firstUse
= env
->getStateFirstUse( **idPos_
);
1583 if( firstUse
!= NULL
){
1584 Ast::theAnalysisErrorsList
.push_back( new Exceptions::StateUninitializedUse( firstUse
->loc( ), id_
, this ) );
1587 stateID_
= env
->getStateID( **idPos_
);
1588 freeStatesDst
->insert( stateID_
);
1592 Ast::IntroduceState::initializeEnvironment( Kernel::PassedEnv env
, Kernel::PassedDyn dyn
) const
1594 /* Although it would be possible to insert some kind of thunk in the environment here,
1595 * it is not obvious that such a feature would be desirable. With such a feature, one
1596 * would be able to use a state before the place in the code where it is introduced:
1603 * This just seems awkward; this is a stateful program, and order generally matters -- this is
1604 * why use before declaration is considered illegal and treated as error already during
1610 Ast::IntroduceState::evalHelper( Kernel::EvalState
* evalState
) const
1612 evalState
->cont_
= Kernel::ContRef( new Kernel::IntroduceStateContinuation( evalState
->env_
,
1616 evalState
->expr_
= expr_
;
1620 Ast::Insertion::Insertion( Ast::StateReference
* stateRef
, Ast::Expression
* expr
)
1621 : Ast::Expression( Ast::SourceLocation( stateRef
->loc( ), expr
->loc( ) ) ), stateRef_( stateRef
), expr_( expr
)
1624 Ast::Insertion::~Insertion( )
1628 Ast::Insertion::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1630 stateRef_
->analyze( this, env
, freeStatesDst
); /* This will always add something to the set of free states. */
1631 expr_
->analyze( this, env
, freeStatesDst
);
1635 Ast::Insertion::eval( Kernel::EvalState
* evalState
) const
1637 evalState
->cont_
= Kernel::ContRef( new Kernel::InsertionContinuation( stateRef_
->getHandle( evalState
->env_
, evalState
->dyn_
),
1641 evalState
->expr_
= expr_
;
1644 Ast::InsertionMutatorCall::InsertionMutatorCall( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
1645 : Ast::Expression( loc
), expr_( expr
)
1648 Ast::InsertionMutatorCall::~InsertionMutatorCall( )
1652 Ast::InsertionMutatorCall::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1654 throw Exceptions::InternalError( loc_
, "An InsertionMutatorCall was analyzed (the contained expression should have been extracted and replaced this object)." );
1658 Ast::InsertionMutatorCall::eval( Kernel::EvalState
* evalState
) const
1660 throw Exceptions::InternalError( loc_
, "An InsertionMutatorCall was evaluated (the contained expression should have been extracted and replaced this object)." );
1664 Ast::Freeze::Freeze( const Ast::SourceLocation
& idLoc
, const Ast::PlacedIdentifier
* id
, size_t ** idPos
)
1665 : Ast::Expression( idLoc
), id_( id
), idPos_( idPos
)
1670 Ast::Freeze::~Freeze( )
1672 /* idPos shared and will be a memory leak which must not be deleted.
1673 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1678 Ast::Freeze::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1682 *idPos_
= new size_t( env
->findLocalStatePosition( loc( ), *id_
) );
1685 freeStatesDst
->insert( env
->getStateID( **idPos_
) );
1689 Ast::Freeze::eval( Kernel::EvalState
* evalState
) const
1691 evalState
->env_
->freeze( **idPos_
, evalState
, loc( ) );
1695 Ast::Peek::Peek( const Ast::SourceLocation
& idLoc
, Ast::StateReference
* stateRef
)
1696 : Ast::Expression( idLoc
), stateRef_( stateRef
)
1703 /* idPos shared and will be a memory leak which must not be deleted.
1704 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1709 Ast::Peek::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1711 stateRef_
->analyze( this, env
, freeStatesDst
); /* This will always add something to the set of free states. */
1715 Ast::Peek::eval( Kernel::EvalState
* evalState
) const
1717 stateRef_
->getHandle( evalState
->env_
, evalState
->dyn_
)->peek( evalState
, loc( ) );
1721 Ast::DynamicExpression::DynamicExpression( const Ast::SourceLocation
& loc
, Ast::Expression
* expr
)
1722 : Ast::Expression( loc
), expr_( expr
)
1727 Ast::DynamicExpression::~DynamicExpression( )
1731 Ast::DynamicExpression::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1733 Ast::StateIDSet
* freeStates
= new Ast::StateIDSet
;
1734 expr_
->analyze( this, env
, freeStates
);
1736 if( ! freeStates
->empty( ) )
1738 Ast::theAnalysisErrorsList
.push_back( new Exceptions::IllegalFreeStates( expr_
->loc( ), freeStates
, "dynamic expressions must be pure" ) );
1747 Ast::DynamicExpression::eval( Kernel::EvalState
* evalState
) const
1749 Kernel::ContRef cont
= evalState
->cont_
;
1750 cont
->takeValue( Kernel::ValueRef( new Lang::DynamicExpression( evalState
->env_
, expr_
) ),
1755 Ast::LexiographicType::LexiographicType( const Ast::SourceLocation
& loc
, const Ast::Identifier
* id
, Kernel::Environment::LexicalKey
** idKey
)
1756 : Ast::Expression( loc
), id_( id
), idKey_( idKey
)
1761 Ast::LexiographicType::~LexiographicType( )
1768 delete idKey_
; // This can be done only as long as this is not shared!
1772 Ast::LexiographicType::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1776 *idKey_
= new Kernel::Environment::LexicalKey( env
->findLexicalTypeKey( loc_
, *id_
) );
1781 Ast::LexiographicType::eval( Kernel::EvalState
* evalState
) const
1783 evalState
->env_
->lookup( **idKey_
, evalState
);