Introducing mutators.
[shapes.git] / source / astvar.cc
blob7f3e2a7799dcde9e9f7403aec832e9d753412d47
1 #include "astvar.h"
2 #include "shapesexceptions.h"
3 #include "globals.h"
4 #include "autoonoff.h"
5 #include "specialunits.h"
6 #include "astfun.h"
7 #include "continuations.h"
8 #include "containertypes.h"
10 using namespace Shapes;
11 using namespace std;
14 Ast::CodeBracket::CodeBracket( const Ast::SourceLocation & loc, std::list< Ast::Node * > * nodes )
15 : Ast::Expression( loc ), nodes_( nodes ), argumentOrder_( new typeof *argumentOrder_ ), dynamicMap_( 0 ), stateOrder_( new typeof *stateOrder_ )
17 for( std::list< Ast::Node * >::const_iterator i = nodes_->begin( );
18 i != nodes_->end( );
19 ++i )
21 typedef const Ast::BindNode T;
22 T * tmp = dynamic_cast< T * >( *i );
23 if( tmp != 0 )
25 const char * name = tmp->id( );
27 typedef const Ast::DefineVariable T;
28 T * decl = dynamic_cast< T * >( tmp );
29 if( decl != 0 )
31 if( argumentOrder_->find( name ) != argumentOrder_->end( ) )
33 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExisting( tmp->idLoc( ), name ) );
34 continue;
36 argumentOrder_->insert( std::pair< const char *, size_t >( name, argumentOrder_->size( ) ) );
37 continue;
41 typedef const Ast::IntroduceState T;
42 T * decl = dynamic_cast< T * >( tmp );
43 if( decl != 0 )
45 if( stateOrder_->find( name ) != stateOrder_->end( ) )
47 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExisting( tmp->idLoc( ), name ) );
48 continue;
50 stateOrder_->insert( std::pair< const char *, size_t >( name, stateOrder_->size( ) ) );
51 continue;
55 typedef const Ast::DynamicVariableDecl T;
56 T * dynDecl = dynamic_cast< T * >( tmp );
57 if( dynDecl != 0 )
59 if( dynamicMap_ == 0 )
61 dynamicMap_ = new std::map< const char *, size_t, charPtrLess >;
63 if( dynamicMap_->find( name ) != dynamicMap_->end( ) )
65 Ast::theAnalysisErrorsList.push_back( new Exceptions::IntroducingExisting( tmp->idLoc( ), name ) );
66 continue;
68 dynamicMap_->insert( std::pair< const char *, size_t >( name, dynamicMap_->size( ) ) );
69 continue;
76 Ast::CodeBracket::~CodeBracket( )
78 typedef list< Ast::Node * >::iterator I;
79 for( I i = nodes_->begin( ); i != nodes_->end( ); ++i )
81 delete *i;
83 delete nodes_;
84 delete argumentOrder_;
85 if( dynamicMap_ != 0 )
87 delete dynamicMap_;
89 delete stateOrder_;
93 void
94 Ast::CodeBracket::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * parentEnv )
96 parent_ = parent;
98 Ast::AnalysisEnvironment * env( new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList, parentEnv, argumentOrder_, stateOrder_ ) );
99 if( dynamicMap_ != 0 )
101 env->setupDynamicKeyVariables( dynamicMap_ );
106 typedef list< Ast::Node * >::iterator I;
107 for( I i = nodes_->begin( ); i != nodes_->end( ); ++i )
109 (*i)->analyze( this, env );
114 imperative_ = false;
116 typedef list< Ast::Node * >::const_iterator I;
117 for( I i = nodes_->begin( ); i != nodes_->end( ); ++i )
119 if( dynamic_cast< Ast::Expression * >( *i ) != 0 &&
120 ! (*i)->imperative_ )
122 I tmp = i;
123 ++tmp;
124 if( tmp != nodes_->end( ) )
126 Ast::theAnalysisErrorsList.push_back( new Exceptions::ExpectedImperative( (*i)->loc( ) ) );
129 imperative_ = imperative_ || (*i)->imperative_;
134 void
135 Ast::CodeBracket::eval( Kernel::EvalState * evalState ) const
137 if( nodes_->begin( ) == nodes_->end( ) )
139 Kernel::ContRef cont = evalState->cont_;
140 cont->takeValue( Lang::THE_VOID,
141 evalState );
142 return;
145 std::vector< Kernel::VariableHandle > * envValues = new std::vector< Kernel::VariableHandle >;
146 envValues->reserve( argumentOrder_->size( ) );
147 while( envValues->size( ) < argumentOrder_->size( ) )
149 envValues->push_back( NullPtr< Kernel::Variable >( ) );
152 std::vector< Kernel::StateHandle > * envStates = new std::vector< Kernel::StateHandle >;
153 envStates->reserve( stateOrder_->size( ) );
154 while( envStates->size( ) < stateOrder_->size( ) )
156 envStates->push_back( NullPtr< Kernel::State >( ) );
159 evalState->env_ = new Kernel::Environment( Kernel::theEnvironmentList, evalState->env_, argumentOrder_, RefCountPtr< std::vector< Kernel::VariableHandle > >( envValues ), stateOrder_, RefCountPtr< std::vector< Kernel::StateHandle > >( envStates ) );
161 if( dynamicMap_ != 0 )
163 evalState->env_->setupDynamicKeyVariables( dynamicMap_ );
166 RefCountPtr< const Kernel::CodeBracketContInfo > info( new Kernel::CodeBracketContInfo( this, *evalState ) );
168 evalAt( info, nodes_->begin( ), evalState );
171 void
172 Ast::CodeBracket::evalAt( const RefCountPtr< const Kernel::CodeBracketContInfo > & info, const std::list< Ast::Node * >::const_iterator & pos, Kernel::EvalState * evalState ) const
175 std::list< Ast::Node * >::const_iterator next = pos;
176 ++next;
177 if( next == nodes_->end( ) )
179 const Ast::Expression * e = dynamic_cast< const Ast::Expression * >( *pos );
180 if( e != 0 &&
181 e->immediate_ )
183 evalState->cont_ = Kernel::ContRef( new Kernel::ForcingContinuation( info->cont_, (*pos)->loc( ) ) );
185 else
187 evalState->cont_ = info->cont_;
190 else
192 evalState->cont_ = Kernel::ContRef( new Kernel::CodeBracketContinuation( (*pos)->loc( ), info, next ) );
195 evalState->env_ = info->env_;
196 evalState->dyn_ = info->dyn_;
197 (*pos)->eval( evalState );
201 Kernel::CodeBracketContInfo::CodeBracketContInfo( const Ast::CodeBracket * bracketExpr, const Kernel::EvalState & evalState )
202 : bracketExpr_( bracketExpr ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
205 Kernel::CodeBracketContInfo::~CodeBracketContInfo( )
208 void
209 Kernel::CodeBracketContInfo::gcMark( Kernel::GCMarkedSet & marked )
211 env_->gcMark( marked );
212 dyn_->gcMark( marked );
213 cont_->gcMark( marked );
216 Kernel::CodeBracketContinuation::CodeBracketContinuation( const Ast::SourceLocation & traceLoc, const RefCountPtr< const Kernel::CodeBracketContInfo > & info, const std::list< Ast::Node * >::const_iterator & pos )
217 : Kernel::Continuation( traceLoc ), info_( info ), pos_( pos )
220 Kernel::CodeBracketContinuation::~CodeBracketContinuation( )
223 void
224 Kernel::CodeBracketContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
226 if( val.down_cast< const Lang::Void >( ) == NullPtr< const Lang::Void >( ) )
228 throw Exceptions::NonVoidStatement( traceLoc_, val );
230 info_->bracketExpr_->evalAt( info_,
231 pos_,
232 evalState );
235 void
236 Kernel::CodeBracketContinuation::backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
238 trace->push_front( Kernel::Continuation::BackTraceElem( this, "code bracket" ) );
239 info_->cont_->backTrace( trace );
242 void
243 Kernel::CodeBracketContinuation::gcMark( Kernel::GCMarkedSet & marked )
245 const_cast< Kernel::CodeBracketContInfo * >( info_.getPtr( ) )->gcMark( marked );
249 Ast::LexiographicVariable::LexiographicVariable( const Ast::SourceLocation & loc, const char * id, Kernel::Environment::LexicalKey ** idKey )
250 : Ast::Expression( loc ), id_( id ), idKey_( idKey )
252 immediate_ = true;
255 Ast::LexiographicVariable::~LexiographicVariable( )
257 delete id_;
258 if( *idKey_ != 0 )
260 delete *idKey_;
262 delete idKey_; // This can be done only as long as this is not shared!
265 void
266 Ast::LexiographicVariable::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
268 parent_ = parent;
270 if( *idKey_ == 0 )
272 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalVariableKey( loc_, id_ ) );
275 imperative_ = false;
278 void
279 Ast::LexiographicVariable::eval( Kernel::EvalState * evalState ) const
281 evalState->env_->lookup( **idKey_, evalState );
285 Ast::EvalOutsideExpr::EvalOutsideExpr( const Ast::SourceLocation & loc, Ast::Expression * expr )
286 : Ast::Expression( loc ), expr_( expr )
288 immediate_ = true;
291 Ast::EvalOutsideExpr::~EvalOutsideExpr( )
293 delete expr_;
296 void
297 Ast::EvalOutsideExpr::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
299 parent_ = parent;
301 expr_->analyze( this, env->getParent( ) );
303 imperative_ = expr_->imperative_;
306 void
307 Ast::EvalOutsideExpr::eval( Kernel::EvalState * evalState ) const
309 evalState->expr_ = expr_;
310 evalState->env_ = evalState->env_->getParent( );
314 Ast::MemberReferenceFunction::MemberReferenceFunction( const Ast::SourceLocation & loc, Ast::Expression * variable, const char * fieldID )
315 : Lang::Function( new Kernel::EvaluatedFormals( "<>.<>", true ) ), loc_( loc ), variable_( variable ), fieldID_( fieldID )
318 Ast::MemberReferenceFunction::~MemberReferenceFunction( )
320 delete variable_;
321 delete fieldID_;
324 void
325 Ast::MemberReferenceFunction::push_exprs( Ast::ArgListExprs * args ) const
327 args->orderedExprs_->push_back( variable_ );
330 void
331 Ast::MemberReferenceFunction::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
333 /* The variable is analyzed as part of the arguments passed to this function, so nothing needs to be done here...
334 * unless we would be able to figure out the type of the argument, and then check if the field reference is valid.
338 void
339 Ast::MemberReferenceFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
341 Kernel::ContRef cont = evalState->cont_;
342 RefCountPtr< const Lang::Value > arg = args.getValue( 0 );
343 cont->takeHandle( arg->getField( fieldID_, arg ),
344 evalState );
349 Ast::MutatorReference::MutatorReference( const Ast::SourceLocation & mutatorLoc, Ast::StateReference * state, const char * mutatorID )
350 : Ast::Expression( mutatorLoc ), mutatorLoc_( mutatorLoc ), state_( state ), mutatorID_( mutatorID )
353 Ast::MutatorReference::~MutatorReference( )
355 /* At the time of implementing this bug-fix, state_ will allways be owned by the Ast::CallExpr that is also the owner of us.
356 * Hence, we do not consider ourselves owners. Perhaps one should have a flag indicating whether ownership is transferred
357 * when calling the constructor, but at the moment this seems like a waste of resources.
359 // delete state_;
360 delete mutatorID_;
363 void
364 Ast::MutatorReference::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
366 state_->analyze( this, env );
368 imperative_ = true;
370 /* If the type of the state was known here, we should verify that there is a mutator corresponding to the message <mutatorID>.
374 void
375 Ast::MutatorReference::eval( Kernel::EvalState * evalState ) const
377 Kernel::ContRef cont = evalState->cont_;
378 cont->takeValue( state_->getHandle( evalState->env_, evalState->dyn_ )->getMutator( mutatorID_ ),
379 evalState );
384 Ast::SpecialLength::SpecialLength( const Ast::SourceLocation & loc, double val, int sort )
385 : Ast::Expression( loc ), val_( val ), sort_( sort )
388 Ast::SpecialLength::~SpecialLength( )
391 void
392 Ast::SpecialLength::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
394 parent_ = parent;
396 imperative_ = false;
399 void
400 Ast::SpecialLength::eval( Kernel::EvalState * evalState ) const
402 Concrete::Length d;
403 double a0;
404 double a1;
406 evalState->dyn_->specialUnitService( & d, & a0, & a1 );
408 if( sort_ == Computation::SPECIALU_NOINFLEX )
410 Kernel::ContRef cont = evalState->cont_;
411 cont->takeValue( Kernel::ValueRef( new Lang::Length( val_ * d * Computation::specialUnitNoInflexion( a0, a1 ) ) ),
412 evalState );
413 return;
415 if( ! sort_ & Computation::SPECIALU_DIST )
417 throw Exceptions::InternalError( strrefdup( "The special unit is neither based on inflexion or distance" ) );
420 double res = 1;
422 if( sort_ & Computation::SPECIALU_CIRC )
424 res *= Computation::specialUnitCircleHandle( a0 );
427 if( sort_ & Computation::SPECIALU_CORR )
429 res *= Computation::specialUnitCorrection( a0, a1 );
432 if( sort_ & Computation::SPECIALU_NOINFLEX )
434 res = min( res, Computation::specialUnitNoInflexion( a0, a1 ) );
436 Kernel::ContRef cont = evalState->cont_;
437 cont->takeValue( Kernel::ValueRef( new Lang::Length( val_ * d * res ) ),
438 evalState );
442 Ast::DynamicVariable::DynamicVariable( const Ast::SourceLocation & loc, const char * id )
443 : Ast::Expression( loc ), id_( id ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
445 immediate_ = true;
448 Ast::DynamicVariable::~DynamicVariable( )
450 delete id_;
451 if( *idKey_ != 0 )
453 delete *idKey_;
455 delete idKey_; // This can be done only as long as this is not shared!
458 void
459 Ast::DynamicVariable::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
461 parent_ = parent;
463 if( *idKey_ == 0 )
465 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalDynamicKey( loc_, id_ ) );
468 imperative_ = false;
471 void
472 Ast::DynamicVariable::eval( Kernel::EvalState * evalState ) const
474 const Kernel::DynamicVariableProperties & dynProps = evalState->env_->lookupDynamicVariable( **idKey_ );
476 Kernel::VariableHandle res = dynProps.fetch( evalState->dyn_ );
478 /* Now, we know that if the value was bound to a dynamic expression, a value was bound, and that value has
479 * a certain type.
481 if( ! res->isThunk( ) )
485 typedef const Lang::DynamicExpression DynType;
486 RefCountPtr< DynType > dynVal = res->tryVal< DynType >( );
487 dynVal->eval( evalState );
488 return;
490 catch( const NonLocalExit::NotThisType & ball )
492 // Never mind.
496 Kernel::ContRef cont = evalState->cont_;
497 cont->takeHandle( res,
498 evalState );
502 Kernel::DynamicBindingContinuation::DynamicBindingContinuation( const Ast::SourceLocation & traceLoc, const Kernel::PassedEnv & env, const Kernel::Environment::LexicalKey & key, const Ast::SourceLocation & idLoc, const Kernel::ContRef & cont )
503 : Kernel::Continuation( traceLoc ), env_( env ), key_( key ), idLoc_( idLoc ), cont_( cont )
506 Kernel::DynamicBindingContinuation::~DynamicBindingContinuation( )
509 void
510 Kernel::DynamicBindingContinuation::takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
512 if( val->isThunk( ) )
514 val->force( val, evalState );
515 return;
517 evalState->cont_ = cont_;
518 env_->lookupDynamicVariable( key_ ).makeBinding( val, idLoc_, evalState );
521 void
522 Kernel::DynamicBindingContinuation::backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
524 trace->push_front( Kernel::Continuation::BackTraceElem( this, "dynamic binding" ) );
525 cont_->backTrace( trace );
528 void
529 Kernel::DynamicBindingContinuation::gcMark( Kernel::GCMarkedSet & marked )
531 env_->gcMark( marked );
532 cont_->gcMark( marked );
535 Ast::DynamicBindingExpression::DynamicBindingExpression( const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * expr, Kernel::Environment::LexicalKey ** idKey )
536 : Ast::Expression( Ast::SourceLocation( idLoc, expr->loc( ) ) ), idLoc_( idLoc ), id_( id ), expr_( expr ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
539 Ast::DynamicBindingExpression::~DynamicBindingExpression( )
541 delete id_;
542 delete expr_;
543 if( *idKey_ != 0 )
545 delete *idKey_;
546 *idKey_ = 0;
548 // Don't delete idKey as it's shared!
551 void
552 Ast::DynamicBindingExpression::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
554 parent_ = parent;
556 expr_->analyze( this, env );
557 if( *idKey_ == 0 )
559 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalDynamicKey( idLoc_, id_ ) );
562 imperative_ = expr_->imperative_;
565 void
566 Ast::DynamicBindingExpression::eval( Kernel::EvalState * evalState ) const
568 const Kernel::DynamicVariableProperties & dynProps = evalState->env_->lookupDynamicVariable( **idKey_ );
570 if( dynProps.forceValue( ) || expr_->immediate_ )
572 evalState->expr_ = expr_;
573 evalState->cont_ = Kernel::ContRef( new Kernel::DynamicBindingContinuation( expr_->loc( ), evalState->env_, **idKey_, idLoc_, evalState->cont_ ) );
575 else
577 dynProps.makeBinding( Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( evalState->env_, evalState->dyn_, expr_ ) ) ),
578 idLoc_,
579 evalState );
584 Ast::DynamicStateBindingExpression::DynamicStateBindingExpression( const Ast::SourceLocation & loc, const Ast::SourceLocation & dstLoc, const char * dstId, Ast::StateReference * src )
585 : Ast::Expression( loc ), dstLoc_( dstLoc ), dstId_( dstId ), dstIdKey_( new Kernel::Environment::LexicalKey * ( 0 ) ), src_( src )
588 Ast::DynamicStateBindingExpression::~DynamicStateBindingExpression( )
590 delete src_;
591 if( *dstIdKey_ != 0 )
593 delete *dstIdKey_;
595 delete dstIdKey_; // This can be done only as long as this is not shared!
598 void
599 Ast::DynamicStateBindingExpression::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
601 parent_ = parent;
603 if( *dstIdKey_ == 0 )
605 *dstIdKey_ = new Kernel::Environment::LexicalKey( env->findLexicalDynamicKey( dstLoc_, dstId_ ) );
608 imperative_ = false;
611 void
612 Ast::DynamicStateBindingExpression::eval( Kernel::EvalState * evalState ) const
614 const Kernel::DynamicStateProperties & dstDynProps = evalState->env_->lookupDynamicState( **dstIdKey_ );
616 dstDynProps.makeBinding( src_->getHandle( evalState->env_, evalState->dyn_ ), dstLoc_, evalState );
620 Kernel::WithDynamicContinuation::WithDynamicContinuation( const Ast::SourceLocation & traceLoc, Ast::Expression * expr, const Kernel::EvalState & evalState )
621 : Kernel::Continuation( traceLoc ), expr_( expr ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
624 Kernel::WithDynamicContinuation::~WithDynamicContinuation( )
627 void
628 Kernel::WithDynamicContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
630 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( dyn_, *Helpers::down_cast< const Lang::DynamicBindings >( val, traceLoc_ ) ) );
631 evalState->env_ = env_;
632 evalState->expr_ = expr_;
633 evalState->cont_ = cont_;
636 void
637 Kernel::WithDynamicContinuation::backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
639 trace->push_front( Kernel::Continuation::BackTraceElem( this, "with dynamic bindings" ) );
640 cont_->backTrace( trace );
643 void
644 Kernel::WithDynamicContinuation::gcMark( Kernel::GCMarkedSet & marked )
646 env_->gcMark( marked );
647 dyn_->gcMark( marked );
648 cont_->gcMark( marked );
652 Ast::WithDynamicExpr::WithDynamicExpr( const Ast::SourceLocation & loc, Ast::Expression * bindings, Ast::Expression * expr )
653 : Ast::Expression( loc ), bindings_( bindings ), expr_( expr )
656 Ast::WithDynamicExpr::~WithDynamicExpr( )
659 void
660 Ast::WithDynamicExpr::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
662 parent_ = parent;
664 bindings_->analyze( this, env );
665 expr_->analyze( this, env );
667 imperative_ = bindings_->imperative_ || expr_->imperative_;
670 void
671 Ast::WithDynamicExpr::eval( Kernel::EvalState * evalState ) const
673 evalState->expr_ = bindings_;
674 evalState->cont_ = Kernel::ContRef( new Kernel::WithDynamicContinuation( bindings_->loc( ), expr_, *evalState ) );
678 Ast::DynamicVariableDecl::DynamicVariableDecl( const Ast::SourceLocation & loc, const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * filterExpr, Ast::Expression * defaultExpr )
679 : Ast::BindNode( loc, idLoc, id ), idPos_( new size_t * ( 0 ) )
681 /* This type of expression is an Ast::BindNode so that it is easy to recognize and extract the identifier for static analysis
682 * and similar tasks.
684 * The expression is implemented as a function call, since there are two subexpressions that may need evaluation.
687 Ast::ArgListExprs * args = new Ast::ArgListExprs( false );
688 Ast::DynamicVariableDeclFunction * res = new Ast::DynamicVariableDeclFunction( id, filterExpr, defaultExpr, idPos_ );
689 res->push_exprs( args );
690 impl_ = new Ast::CallExpr( loc,
691 RefCountPtr< const Lang::Function >( res ),
692 args );
695 Ast::DynamicVariableDecl::~DynamicVariableDecl( )
698 void
699 Ast::DynamicVariableDecl::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
701 parent_ = parent;
703 impl_->analyze( this, env );
704 if( *idPos_ == 0 )
706 *idPos_ = new size_t( env->findLocalDynamicPosition( idLoc_, id_ ) );
709 imperative_ = impl_->imperative_;
712 void
713 Ast::DynamicVariableDecl::eval( Kernel::EvalState * evalState ) const
715 evalState->expr_ = impl_;
719 Ast::DynamicVariableDeclFunction::DynamicVariableDeclFunction( const char * id, Ast::Expression * filterExpr, Ast::Expression * defaultExpr, size_t ** idPos )
720 : Lang::Function( new Kernel::EvaluatedFormals( "< dynamic variable declaration >", false ) ), id_( id ), filterExpr_( filterExpr ), defaultExpr_( defaultExpr ), idPos_( idPos )
723 Ast::DynamicVariableDeclFunction::~DynamicVariableDeclFunction( )
725 delete filterExpr_;
726 delete defaultExpr_;
729 void
730 Ast::DynamicVariableDeclFunction::push_exprs( Ast::ArgListExprs * args ) const
732 args->orderedExprs_->push_back( filterExpr_ );
733 args->orderedExprs_->push_back( defaultExpr_ );
736 void
737 Ast::DynamicVariableDeclFunction::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
739 /* The analysis is carried out by the DynamicVariableDecl expression.
743 void
744 Ast::DynamicVariableDeclFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
746 static const char * title = "< dynamic variable declaration >";
747 typedef const Lang::Function FilterType;
748 evalState->env_->defineDynamic( id_,
749 **idPos_,
750 Helpers::down_cast_CoreArgument< FilterType >( title, args, 0, callLoc ),
751 args.getHandle( 1 ) );
753 Kernel::ContRef cont = evalState->cont_;
754 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
755 evalState );
758 Kernel::DynamicVariableDeclContinuation::DynamicVariableDeclContinuation( const Ast::SourceLocation & traceLoc, const Ast::DynamicVariableDecl * declExpr, Kernel::EvalState & evalState )
759 : Kernel::Continuation( traceLoc ), declExpr_( declExpr ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
762 Kernel::DynamicVariableDeclContinuation::~DynamicVariableDeclContinuation( )
765 void
766 Kernel::DynamicVariableDeclContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
768 evalState->env_ = env_;
769 evalState->dyn_ = dyn_;
770 evalState->cont_ = cont_;
771 throw Exceptions::NotImplemented( "Deprecated: DynamicVariableDeclContinuation" );
772 // declExpr_->callBack( Helpers::down_cast< const Lang::Function >( val, traceLoc_ ),
773 // evalState );
776 void
777 Kernel::DynamicVariableDeclContinuation::backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
779 trace->push_front( Kernel::Continuation::BackTraceElem( this, "dynamic variable declaration" ) );
780 cont_->backTrace( trace );
783 void
784 Kernel::DynamicVariableDeclContinuation::gcMark( Kernel::GCMarkedSet & marked )
786 env_->gcMark( marked );
787 dyn_->gcMark( marked );
788 cont_->gcMark( marked );
792 Ast::DynamicStateDecl::DynamicStateDecl( const Ast::SourceLocation & loc, const Ast::SourceLocation & idLoc, const char * id, Ast::StateReference * defaultState, size_t ** idPos )
793 : Ast::BindNode( loc, idLoc, id ), idPos_( idPos ), defaultState_( defaultState )
796 Ast::DynamicStateDecl::~DynamicStateDecl( )
800 void
801 Ast::DynamicStateDecl::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
803 parent_ = parent;
805 if( *idPos_ == 0 )
807 *idPos_ = new size_t( env->findLocalDynamicStatePosition( idLoc_, id_ ) );
810 imperative_ = false;
813 void
814 Ast::DynamicStateDecl::eval( Kernel::EvalState * evalState ) const
816 evalState->env_->defineDynamicState( id_,
817 **idPos_,
818 evalState,
819 defaultState_ );
821 Kernel::ContRef cont = evalState->cont_;
822 cont->takeHandle( Kernel::THE_SLOT_VARIABLE,
823 evalState );
827 Ast::EvalSymbolFunction::EvalSymbolFunction( const Ast::SourceLocation & loc, Ast::Expression * expr )
828 : Lang::Function( new Kernel::EvaluatedFormals( "< symbol evaluation >", true ) ), loc_( loc ), expr_( expr )
831 Ast::EvalSymbolFunction::~EvalSymbolFunction( )
833 delete expr_;
836 void
837 Ast::EvalSymbolFunction::push_exprs( Ast::ArgListExprs * args ) const
839 args->orderedExprs_->push_back( expr_ );
842 void
843 Ast::EvalSymbolFunction::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
845 analysisEnv_ = env;
847 /* expr_ shall be analyzed from the calling expression.
848 * Here, it is only used to locate errors.
852 void
853 Ast::EvalSymbolFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
855 RefCountPtr< const Lang::Value > untypedVal = args.getValue( 0 );
856 typedef const Lang::Symbol ArgType;
857 ArgType * val = dynamic_cast< ArgType * >( untypedVal.getPtr( ) );
858 if( val == 0 )
860 throw Exceptions::TypeMismatch( expr_->loc( ), untypedVal->getTypeName( ), ArgType::staticTypeName( ) );
862 if( val->isUnique( ) )
864 throw Exceptions::OutOfRange( expr_->loc( ), strrefdup( "Unique symbols can't denote variables." ) );
868 Kernel::Environment::LexicalKey key = analysisEnv_->findLexicalVariableKey( loc_, val->name( ).getPtr( ) );
870 Kernel::PassedEnv env = evalState->env_;
871 env->lookup( key, evalState );
875 Ast::DefineVariable::DefineVariable( const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * expr, size_t ** idPos )
876 : Ast::BindNode( Ast::SourceLocation( idLoc, expr->loc( ) ), idLoc, id ), expr_( expr ), idPos_( idPos )
879 Ast::DefineVariable::~DefineVariable( )
881 delete expr_;
883 /* idPos_ is shared and will be a memory leak which must not be deleted.
884 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
889 void
890 Ast::DefineVariable::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
892 parent_ = parent;
894 expr_->analyze( this, env );
895 if( *idPos_ == 0 )
897 *idPos_ = new size_t( env->findLocalVariablePosition( idLoc_, id_ ) );
900 imperative_ = expr_->imperative_;
903 void
904 Ast::DefineVariable::eval( Kernel::EvalState * evalState ) const
906 if( expr_->immediate_ || expr_->imperative_ )
908 evalState->cont_ = Kernel::ContRef( new Kernel::DefineVariableContinuation( evalState->env_,
909 *idPos_,
910 evalState->cont_,
911 expr_->loc( ) ) );
912 evalState->expr_ = expr_;
914 else
916 evalState->env_->define( **idPos_,
917 Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( evalState->env_,
918 evalState->dyn_,
919 expr_ ) ) ) );
920 Kernel::ContRef cont = evalState->cont_;
921 cont->takeHandle( Kernel::THE_SLOT_VARIABLE, evalState );
926 Kernel::AssertStructureContinuation::AssertStructureContinuation( const Kernel::ContRef & cont, const Ast::SourceLocation & traceLoc )
927 : Kernel::Continuation( traceLoc ), cont_( cont )
930 Kernel::AssertStructureContinuation::~AssertStructureContinuation( )
933 void
934 Kernel::AssertStructureContinuation::takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
936 evalState->cont_ = cont_;
937 cont_->takeValue( Helpers::down_cast_ContinuationArgument< const Lang::Structure >( val, this ), evalState );
940 void
941 Kernel::AssertStructureContinuation::backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
943 trace->push_front( Kernel::Continuation::BackTraceElem( this, "Assert type is struct" ) );
944 cont_->backTrace( trace );
947 void
948 Kernel::AssertStructureContinuation::gcMark( Kernel::GCMarkedSet & marked )
950 cont_->gcMark( marked );
954 Ast::StructSplitReference::StructSplitReference( Ast::SourceLocation fieldLoc, const char * fieldId, Ast::Expression * defaultExpr )
955 : Ast::Expression( fieldLoc ),
956 structLoc_( Ast::THE_UNKNOWN_LOCATION ), // This is a dummy value! The correct value is set later.
957 fieldId_( fieldId ),
958 defaultExpr_( defaultExpr )
961 Ast::StructSplitReference::StructSplitReference( Ast::SourceLocation fieldLoc, size_t fieldPos, Ast::Expression * defaultExpr )
962 : Ast::Expression( fieldLoc ),
963 structLoc_( Ast::THE_UNKNOWN_LOCATION ), // This is a dummy value! The correct value is set later.
964 fieldId_( 0 ), fieldPos_( fieldPos ),
965 defaultExpr_( defaultExpr )
968 Ast::StructSplitReference::~StructSplitReference( )
970 if( fieldId_ != 0 )
972 delete fieldId_;
974 if( defaultExpr_ != 0 )
976 delete defaultExpr_;
980 void
981 Ast::StructSplitReference::setStruct( Ast::SourceLocation structLoc, size_t ** structPos )
983 structLoc_ = structLoc;
984 structPos_ = structPos;
987 void
988 Ast::StructSplitReference::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
990 parent_ = parent;
992 if( defaultExpr_ != 0 )
994 defaultExpr_->analyze( this, env );
995 imperative_ = defaultExpr_->imperative_;
997 else
999 imperative_ = false;
1003 void
1004 Ast::StructSplitReference::eval( Kernel::EvalState * evalState ) const
1006 Kernel::VariableHandle structHandle = evalState->env_->getVarHandle( **structPos_ );
1007 typedef const Lang::Structure StructType;
1008 RefCountPtr< StructType > structVal = structHandle->getVal< StructType >( "Type-checked value in StructSplitReference::eval." );
1010 Kernel::ContRef cont = evalState->cont_;
1011 if( fieldId_ != 0 )
1015 cont->takeHandle( structVal->getField( fieldId_, structVal ),
1016 evalState );
1017 return;
1019 catch( const Exceptions::NonExistentMember & ball )
1021 if( defaultExpr_ == 0 )
1023 throw;
1025 // Never mind, we use the default instead. See below.
1028 else
1032 cont->takeHandle( structVal->getPosition( fieldPos_, structVal ),
1033 evalState );
1034 return;
1036 catch( const Exceptions::NonExistentPosition & ball )
1038 if( defaultExpr_ == 0 )
1040 throw;
1042 // Never mind, we use the default instead. See below.
1046 if( defaultExpr_ == 0 )
1048 throw Exceptions::InternalError( "Just about to use null pointer defaultExpr_ in StructSplitReference::eval." );
1050 evalState->expr_ = defaultExpr_;
1053 Ast::StructSplitSink::StructSplitSink( )
1054 : Ast::Expression( Ast::THE_UNKNOWN_LOCATION ), structLoc_( Ast::THE_UNKNOWN_LOCATION )
1057 Ast::StructSplitSink::~StructSplitSink( )
1060 void
1061 Ast::StructSplitSink::setStruct( Ast::SourceLocation structLoc, size_t ** structPos, size_t consumedArguments )
1063 structLoc_ = structLoc;
1064 structPos_ = structPos;
1065 consumedArguments_ = consumedArguments;
1068 void
1069 Ast::StructSplitSink::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1071 parent_ = parent;
1073 imperative_ = false;
1076 void
1077 Ast::StructSplitSink::eval( Kernel::EvalState * evalState ) const
1079 Kernel::VariableHandle structHandle = evalState->env_->getVarHandle( **structPos_ );
1080 typedef const Lang::Structure StructType;
1081 RefCountPtr< StructType > structVal = structHandle->getVal< StructType >( "Type-checked value in StructSplitReference::eval." );
1083 Kernel::ContRef cont = evalState->cont_;
1084 cont->takeValue( structVal->getSink( consumedArguments_ ),
1085 evalState );
1089 Ast::AssertNoSinkNeeded::AssertNoSinkNeeded( const Ast::SourceLocation & loc, size_t orderedCount, Ast::SourceLocation structLoc, size_t ** structPos )
1090 : Ast::Expression( loc ), orderedCount_( orderedCount ), structLoc_( structLoc ), structPos_( structPos )
1093 Ast::AssertNoSinkNeeded::~AssertNoSinkNeeded( )
1096 void
1097 Ast::AssertNoSinkNeeded::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1099 parent_ = parent;
1101 imperative_ = true;
1104 void
1105 Ast::AssertNoSinkNeeded::eval( Kernel::EvalState * evalState ) const
1107 Kernel::VariableHandle structHandle = evalState->env_->getVarHandle( **structPos_ );
1108 typedef const Lang::Structure StructType;
1109 RefCountPtr< StructType > structVal = structHandle->getVal< StructType >( "Type-checked value in StructSplitReference::eval." );
1111 if( structVal->argList_->orderedExprs_->size( ) > orderedCount_ )
1113 throw Exceptions::SinkRequired( loc_, orderedCount_, structVal->argList_->orderedExprs_->size( ) );
1116 Kernel::ContRef cont = evalState->cont_;
1117 cont->takeHandle( Kernel::THE_SLOT_VARIABLE, evalState );
1120 size_t Ast::SplitDefineVariables::splitVarCount = 0;
1121 PtrOwner_back_Access< std::list< const char * > > Ast::SplitDefineVariables::mem;
1123 Ast::SplitDefineVariables::SplitDefineVariables( )
1124 : sinkDefine_( 0 ), sinkExpr_( 0 ), seenNamed_( false ), seenDefault_( false )
1126 std::ostringstream oss;
1127 oss << Kernel::SPLIT_VAR_PREFIX << splitVarCount ;
1128 splitVarId_ = strdup( oss.str( ).c_str( ) );
1129 mem.push_back( splitVarId_ );
1130 ++splitVarCount;
1133 const char *
1134 Ast::SplitDefineVariables::newSplitVarId( ) const
1136 return strdup( splitVarId_ );
1140 Ast::StateReference::StateReference( const Ast::SourceLocation & loc )
1141 : Ast::Node( loc )
1144 Ast::StateReference::~StateReference( )
1147 void
1148 Ast::StateReference::eval( Kernel::EvalState * evalState ) const
1150 throw Exceptions::InternalError( "A state reference was evaluated." );
1154 Ast::LexiographicState::LexiographicState( const Ast::SourceLocation & loc, const char * id, Kernel::Environment::LexicalKey ** idKey )
1155 : Ast::StateReference( loc ), id_( id ), idKey_( idKey )
1158 Ast::LexiographicState::~LexiographicState( )
1160 delete id_;
1161 if( *idKey_ != 0 )
1163 delete *idKey_;
1165 delete idKey_; // This can be done only as long as this is not shared!
1168 void
1169 Ast::LexiographicState::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1171 parent_ = parent;
1173 if( *idKey_ == 0 )
1175 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalStateKey( loc_, id_ ) );
1178 imperative_ = true;
1181 Kernel::StateHandle
1182 Ast::LexiographicState::getHandle( Kernel::PassedEnv env, Kernel::PassedDyn dyn ) const
1184 return env->getStateHandle( **idKey_ );
1188 Ast::DynamicState::DynamicState( const Ast::SourceLocation & loc, const char * id )
1189 : Ast::StateReference( loc ), id_( id ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
1192 Ast::DynamicState::~DynamicState( )
1194 delete id_;
1195 if( *idKey_ != 0 )
1197 delete *idKey_;
1199 delete idKey_; // This can be done only as long as this is not shared!
1202 void
1203 Ast::DynamicState::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1205 parent_ = parent;
1207 /* It would make sense to check the reference and...
1209 imperative_ = true;
1212 Kernel::StateHandle
1213 Ast::DynamicState::getHandle( Kernel::PassedEnv env, Kernel::PassedDyn dyn ) const
1215 throw Exceptions::NotImplemented( "Referencing dynamic states" );
1219 Ast::IntroduceState::IntroduceState( const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * expr, size_t ** idPos )
1220 : Ast::BindNode( Ast::SourceLocation( idLoc, expr->loc( ) ), idLoc, id ), expr_( expr ), idPos_( idPos )
1223 Ast::IntroduceState::~IntroduceState( )
1225 delete expr_;
1227 /* idPos_ shared and will be a memory leak which must not be deleted.
1228 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1233 void
1234 Ast::IntroduceState::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1236 parent_ = parent;
1238 expr_->analyze( this, env );
1240 if( *idPos_ == 0 )
1242 *idPos_ = new size_t( env->findLocalStatePosition( idLoc_, id_ ) );
1245 imperative_ = expr_->imperative_;
1248 void
1249 Ast::IntroduceState::eval( Kernel::EvalState * evalState ) const
1251 evalState->cont_ = Kernel::ContRef( new Kernel::IntroduceStateContinuation( evalState->env_,
1252 *idPos_,
1253 evalState->cont_,
1254 expr_->loc( ) ) );
1255 evalState->expr_ = expr_;
1259 Ast::Insertion::Insertion( Ast::StateReference * stateRef, Ast::Expression * expr )
1260 : Ast::Node( Ast::SourceLocation( stateRef->loc( ), expr->loc( ) ) ), stateRef_( stateRef ), expr_( expr )
1263 Ast::Insertion::~Insertion( )
1266 void
1267 Ast::Insertion::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1269 parent_ = parent;
1271 stateRef_->analyze( this, env );
1272 expr_->analyze( this, env );
1274 imperative_ = true;
1277 void
1278 Ast::Insertion::eval( Kernel::EvalState * evalState ) const
1280 evalState->cont_ = Kernel::ContRef( new Kernel::InsertionContinuation( stateRef_->getHandle( evalState->env_, evalState->dyn_ ),
1281 evalState->cont_,
1282 evalState->dyn_,
1283 expr_->loc( ) ) );
1284 evalState->expr_ = expr_;
1287 Ast::Freeze::Freeze( const Ast::SourceLocation & idLoc, const char * id, size_t ** idPos )
1288 : Ast::Expression( idLoc ), id_( id ), idPos_( idPos )
1290 immediate_ = true;
1293 Ast::Freeze::~Freeze( )
1295 /* idPos shared and will be a memory leak which must not be deleted.
1296 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1300 void
1301 Ast::Freeze::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1303 parent_ = parent;
1305 if( *idPos_ == 0 )
1307 *idPos_ = new size_t( env->findLocalStatePosition( loc( ), id_ ) );
1310 imperative_ = true;
1313 void
1314 Ast::Freeze::eval( Kernel::EvalState * evalState ) const
1316 evalState->env_->freeze( **idPos_, evalState, loc( ) );
1320 Ast::Peek::Peek( const Ast::SourceLocation & idLoc, Ast::StateReference * stateRef )
1321 : Ast::Expression( idLoc ), stateRef_( stateRef )
1323 immediate_ = true;
1326 Ast::Peek::~Peek( )
1328 /* idPos shared and will be a memory leak which must not be deleted.
1329 * It would be easy to fix the leak using RefCountPtr< size_t >, but the leakage is constant space, so silly efficiency is prioritized.
1333 void
1334 Ast::Peek::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1336 parent_ = parent;
1338 stateRef_->analyze( this, env );
1340 imperative_ = true;
1343 void
1344 Ast::Peek::eval( Kernel::EvalState * evalState ) const
1346 stateRef_->getHandle( evalState->env_, evalState->dyn_ )->peek( evalState, loc( ) );
1350 Ast::DynamicExpression::DynamicExpression( const Ast::SourceLocation & loc, Ast::Expression * expr )
1351 : Ast::Expression( loc ), expr_( expr )
1353 immediate_ = true;
1356 Ast::DynamicExpression::~DynamicExpression( )
1359 void
1360 Ast::DynamicExpression::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1362 parent_ = parent;
1364 expr_->analyze( this, env );
1366 if( expr_->imperative_ )
1368 Ast::theAnalysisErrorsList.push_back( new Exceptions::IllegalImperative( expr_->loc( ) ) );
1370 imperative_ = false;
1373 void
1374 Ast::DynamicExpression::eval( Kernel::EvalState * evalState ) const
1376 Kernel::ContRef cont = evalState->cont_;
1377 cont->takeValue( Kernel::ValueRef( new Lang::DynamicExpression( evalState->env_, expr_ ) ),
1378 evalState );
1382 Ast::LexiographicType::LexiographicType( const Ast::SourceLocation & loc, const char * id, Kernel::Environment::LexicalKey ** idKey )
1383 : Ast::Expression( loc ), id_( id ), idKey_( idKey )
1385 immediate_ = true;
1388 Ast::LexiographicType::~LexiographicType( )
1390 delete id_;
1391 if( *idKey_ != 0 )
1393 delete *idKey_;
1395 delete idKey_; // This can be done only as long as this is not shared!
1398 void
1399 Ast::LexiographicType::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1401 parent_ = parent;
1403 if( *idKey_ == 0 )
1405 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalTypeKey( loc_, id_ ) );
1408 imperative_ = false;
1411 void
1412 Ast::LexiographicType::eval( Kernel::EvalState * evalState ) const
1414 evalState->env_->lookup( **idKey_, evalState );