Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / astfun.cc
blob1f8320e32e756d67e9addb0a9a93d5237bc4417f
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include "Shapes_Helpers_decls.h"
21 #include "astfun.h"
22 #include "shapesexceptions.h"
23 #include "shapescore.h"
24 #include "consts.h"
25 #include "globals.h"
26 #include "continuations.h"
27 #include "astvar.h"
29 #include <sstream>
31 using namespace Shapes;
32 using namespace std;
35 Kernel::Formals::Formals( )
36 : loc_( Ast::THE_UNKNOWN_LOCATION ),
37 seenDefault_( false ), argumentOrder_( new std::map< const char *, size_t, charPtrLess > ),
38 sink_( 0 ),
39 stateOrder_( new std::map< const char *, size_t, charPtrLess > )
40 { }
42 Kernel::Formals::Formals( size_t numberOfDummyDefaultExprs )
43 : loc_( Ast::THE_UNKNOWN_LOCATION ),
44 seenDefault_( false ), argumentOrder_( new std::map< const char *, size_t, charPtrLess > ),
45 sink_( 0 ),
46 stateOrder_( new std::map< const char *, size_t, charPtrLess > )
48 // Pushing null expressions is just a way of specifying how many non-sink arguments there are.
49 for( size_t i = 0; i < numberOfDummyDefaultExprs; ++i )
51 defaultExprs_.push_back( 0 );
55 Kernel::Formals::~Formals( )
57 delete argumentOrder_;
58 delete stateOrder_;
59 if( sink_ != 0 )
61 delete sink_;
65 void
66 Kernel::Formals::setLoc( Ast::SourceLocation loc )
68 loc_ = loc;
72 void
73 Kernel::Formals::push_exprs( Ast::ArgListExprs * args ) const
75 typedef typeof defaultExprs_ ListType;
76 for( ListType::const_iterator i = defaultExprs_.begin( ); i != defaultExprs_.end( ); ++i )
78 if( *i != 0 )
80 args->orderedExprs_->push_back( *i );
85 Kernel::EvaluatedFormals *
86 Kernel::Formals::newEvaluatedFormals( Kernel::Arguments & args ) const
88 size_t pos = 0;
89 return newEvaluatedFormals( args, & pos );
92 Kernel::EvaluatedFormals *
93 Kernel::Formals::newEvaluatedFormals( Kernel::Arguments & args, size_t * pos ) const
95 Kernel::EvaluatedFormals * res = new Kernel::EvaluatedFormals( const_cast< Kernel::Formals * >( this ) );
96 res->isSink_ = false; // The formals created here belong to user functions, which are exactly those which are not sinks.
98 res->defaults_.reserve( defaultExprs_.size( ) );
99 res->locations_.reserve( defaultExprs_.size( ) );
101 typedef typeof defaultExprs_ ListType;
102 for( ListType::const_iterator i = defaultExprs_.begin( ); i != defaultExprs_.end( ); ++i )
104 if( *i != 0 )
106 res->defaults_.push_back( args.getHandle( *pos ) );
107 res->locations_.push_back( args.getNode( *pos ) );
108 ++(*pos);
110 else
112 res->defaults_.push_back( Kernel::THE_SLOT_VARIABLE );
113 res->locations_.push_back( 0 ); // I really hope this is never dereferenced!
117 return res;
120 std::vector< bool > *
121 Kernel::Formals::newArgListForcePos( const Ast::ArgListExprs * argList ) const
123 /* Here, we use the knowledge that ordered arguments are evaluated backwards, and named arguments
124 * in the natural order (the lexiographic order of std::map).
127 std::vector< bool > * res = new std::vector< bool >;
128 res->resize( argList->orderedExprs_->size( ) );
129 res->reserve( argList->orderedExprs_->size( ) + argList->namedExprs_->size( ) );
131 if( ! argList->orderedExprs_->empty( ) )
133 typedef typeof forcePos_ SrcType;
134 SrcType::const_iterator src = forcePos_.begin( );
135 for( size_t arg = argList->orderedExprs_->size( ) - 1; ; --arg, ++src )
137 (*res)[ arg ] = *src;
138 if( arg == 0 )
140 break;
146 typedef typeof *argList->namedExprs_ MapType;
147 MapType::const_iterator end = argList->namedExprs_->end( );
148 for( MapType::const_iterator arg = argList->namedExprs_->begin( ); arg != end; ++arg )
150 res->push_back( forcePos_[ (*argumentOrder_)[ arg->first ] ] );
154 return res;
157 std::vector< bool > *
158 Kernel::Formals::newArgListForcePos( const Ast::ArgListExprs * argList, const Kernel::Arguments & curryArgs ) const
160 /* Compare with the non-curry version!
163 std::vector< bool > * res = new std::vector< bool >;
164 res->resize( argList->orderedExprs_->size( ) );
165 res->reserve( argList->orderedExprs_->size( ) + argList->namedExprs_->size( ) );
167 if( ! argList->orderedExprs_->empty( ) )
169 typedef typeof forcePos_ SrcType;
170 SrcType::const_iterator src = forcePos_.begin( );
171 size_t curryPos = 0;
172 while( curryPos < curryArgs.size( ) &&
173 ! curryArgs.isSlot( curryPos ) )
175 ++src;
176 ++curryPos;
178 for( size_t arg = argList->orderedExprs_->size( ) - 1; ; --arg )
180 (*res)[ arg ] = *src;
181 if( arg == 0 )
183 break;
185 ++src;
186 ++curryPos;
187 while( curryPos < curryArgs.size( ) &&
188 ! curryArgs.isSlot( curryPos ) )
190 ++src;
191 ++curryPos;
197 typedef typeof *argList->namedExprs_ MapType;
198 MapType::const_iterator end = argList->namedExprs_->end( );
199 for( MapType::const_iterator arg = argList->namedExprs_->begin( ); arg != end; ++arg )
201 res->push_back( forcePos_[ (*argumentOrder_)[ arg->first ] ] );
205 return res;
208 const Ast::SourceLocation &
209 Kernel::Formals::loc( ) const
211 return loc_;
216 Ast::ArgListExprs::ConstIterator::ConstIterator( std::list< Ast::Expression * >::const_reverse_iterator i1, std::map< const char *, Ast::Expression *, charPtrLess >::const_iterator i2, const size_t & index )
217 : i1_( i1 ), i2_( i2 ), index_( index )
220 Ast::ArgListExprs::ConstIterator::ConstIterator( const Ast::ArgListExprs::ConstIterator & orig )
221 : i1_( orig.i1_ ), i2_( orig.i2_ ), index_( orig.index_ )
224 Ast::ArgListExprs::ArgListExprs( bool exprOwner )
225 : exprOwner_( exprOwner ), orderedExprs_( new std::list< Ast::Expression * > ), namedExprs_( new std::map< const char *, Ast::Expression *, charPtrLess > ),
226 orderedStates_( new std::list< Ast::StateReference * > ), namedStates_( new std::map< const char *, Ast::StateReference *, charPtrLess > )
228 // if( exprOwner_ )
229 // {
230 // throw Exceptions::InternalError( strrefdup( "Ast::ArgListExprs( bool _exprOwner ) can only be called with false." ) );
231 // }
234 Ast::ArgListExprs::ArgListExprs( std::list< Ast::Expression * > * orderedExprs, std::map< const char *, Ast::Expression *, charPtrLess > * namedExprs, std::list< Ast::StateReference * > * orderedStates, std::map< const char *, Ast::StateReference *, charPtrLess > * namedStates )
235 : exprOwner_( true ), orderedExprs_( orderedExprs ), namedExprs_( namedExprs ), orderedStates_( orderedStates ), namedStates_( namedStates )
238 Ast::ArgListExprs::~ArgListExprs( )
241 if( exprOwner_ )
243 typedef list< Ast::Expression * >::iterator I;
244 for( I i = orderedExprs_->begin( ); i != orderedExprs_->end( ); ++i )
246 delete *i;
249 delete orderedExprs_;
253 if( exprOwner_ )
255 typedef std::map< const char *, Ast::Expression *, charPtrLess >::const_iterator I;
256 for( I i = namedExprs_->begin( ); i != namedExprs_->end( ); ++i )
258 delete i->first;
259 delete i->second;
262 delete namedExprs_;
266 if( exprOwner_ )
268 typedef std::list< Ast::StateReference * >::iterator I;
269 for( I i = orderedStates_->begin( ); i != orderedStates_->end( ); ++i )
271 delete *i;
274 delete orderedStates_;
278 if( exprOwner_ )
280 typedef std::map< const char *, Ast::StateReference *, charPtrLess >::const_iterator I;
281 for( I i = namedStates_->begin( ); i != namedStates_->end( ); ++i )
283 delete i->first;
284 delete i->second;
287 delete namedStates_;
291 Ast::ArgListExprs::ArgListExprs( size_t numberOfOrderedDummyExprs )
292 : exprOwner_( true ), orderedExprs_( new std::list< Ast::Expression * > ), namedExprs_( new std::map< const char *, Ast::Expression *, charPtrLess > ), orderedStates_( new typeof *orderedStates_ ), namedStates_( new typeof *namedStates_ )
294 for( size_t i = 0; i < numberOfOrderedDummyExprs; ++i )
296 orderedExprs_->push_back( new Ast::DummyExpression );
301 void
302 Ast::ArgListExprs::evaluate( const RefCountPtr< const Kernel::CallContInfo > & info, const Ast::ArgListExprs::ConstIterator & pos, const RefCountPtr< const Lang::SingleList > & vals, Kernel::EvalState * evalState ) const
304 std::list< Ast::Expression * >::const_reverse_iterator i1end = orderedExprs_->rend( );
306 if( pos.i1_ == i1end &&
307 pos.i2_ == namedExprs_->end( ) )
309 evalState->cont_ = info->cont_;
310 info->cont_->takeValue( vals, evalState );
311 return;
314 if( pos.i1_ != i1end )
316 /* Note that it is necessary that the evaluation of expressions with free states is not delayed.
317 * If it would, it would be very strange for the calling function if a passed state would change
318 * value in response to the accessing of a formal parameter.
320 if( info->force( pos.index_ ) || (*(pos.i1_))->immediate_ )
322 typedef typeof const_cast< Ast::ArgListExprs::ConstIterator & >( pos ).i1_ Iterator;
323 Iterator next = pos.i1_;
324 ++next;
325 evalState->expr_ = *(pos.i1_);
326 evalState->env_ = info->env_;
327 evalState->dyn_ = info->dyn_;
328 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_n( evalState->expr_->loc( ),
329 info,
330 Ast::ArgListExprs::ConstIterator( next, pos.i2_, pos.index_ + 1 ),
331 vals ) );
332 return;
334 else
336 /* Delay evaluation of this argument by just putting a thunk in the list.
338 typedef typeof const_cast< Ast::ArgListExprs::ConstIterator & >( pos ).i1_ Iterator;
339 Iterator next = pos.i1_;
340 ++next;
341 evaluate( info,
342 Ast::ArgListExprs::ConstIterator( next, pos.i2_, pos.index_ + 1 ),
343 RefCountPtr< const Lang::SingleListPair >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( info->env_, info->dyn_, *pos.i1_ ) ) ),
344 vals ) ),
345 evalState );
346 return; /* It is not really important that the above compiles to a tail call. Hopefully, it does, but otherwise it is easy to see that the chain of recursive calls to this function
347 * will always completes without evaluation of expressions. */
350 else
352 if( info->force( pos.index_ ) || pos.i2_->second->immediate_ )
354 typedef typeof const_cast< Ast::ArgListExprs::ConstIterator & >( pos ).i2_ Iterator;
355 Iterator next = pos.i2_;
356 ++next;
357 evalState->expr_ = pos.i2_->second;
358 evalState->env_ = info->env_;
359 evalState->dyn_ = info->dyn_;
360 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_n( evalState->expr_->loc( ),
361 info,
362 Ast::ArgListExprs::ConstIterator( pos.i1_, next, pos.index_ + 1 ),
363 vals ) );
364 return;
366 else
368 /* Delay evaluation of this argument by just putting a thunk in the list.
370 typedef typeof const_cast< Ast::ArgListExprs::ConstIterator & >( pos ).i2_ Iterator;
371 Iterator next = pos.i2_;
372 ++next;
373 evaluate( info,
374 Ast::ArgListExprs::ConstIterator( pos.i1_, next, pos.index_ + 1 ),
375 RefCountPtr< const Lang::SingleListPair >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( info->env_, info->dyn_, pos.i2_->second ) ) ),
376 vals ) ),
377 evalState );
378 return; /* It is not really important that the above compiles to a tail call. Hopefully, it does, but otherwise it is easy to see that the chain of recursive calls to this function
379 * will always complete without evaluation of expressions. */
384 void
385 Ast::ArgListExprs::bind( Kernel::Arguments * dst, RefCountPtr< const Lang::SingleList > vals, Kernel::PassedEnv env, Kernel::PassedDyn dyn ) const
387 typedef const Lang::SingleListPair ConsType;
389 /* Note that the arguments are bound in backwards-order, since that is how the values are accessed.
393 typedef std::map< const char *, Ast::Expression *, charPtrLess >::const_reverse_iterator I;
394 I i = namedExprs_->rbegin( );
395 I end = namedExprs_->rend( );
396 for( ; i != end; ++i )
398 RefCountPtr< ConsType > lst = vals.down_cast< ConsType >( );
399 if( lst == NullPtr< ConsType >( ) )
401 throw Exceptions::InternalError( strrefdup( "Out of argument values when binding application." ) );
403 dst->addNamedArgument( i->first, lst->car_, i->second );
404 vals = lst->cdr_;
409 typedef list< Ast::Expression * >::const_iterator I;
410 I i = orderedExprs_->begin( );
411 I end = orderedExprs_->end( );
412 for( ; i != end; ++i )
414 RefCountPtr< ConsType > lst = vals.down_cast< ConsType >( );
415 if( lst == NullPtr< ConsType >( ) )
417 throw Exceptions::InternalError( strrefdup( "Out of argument values when binding application." ) );
419 dst->addOrderedArgument( lst->car_, *i );
420 vals = lst->cdr_;
424 /* Here, it could/should be verified that vals is null. However, it only isn't in case of an internal error...
427 /* Next, we turn to the states. The states need no evaluation, as they are always passed by reference.
431 typedef std::map< const char *, Ast::StateReference *, charPtrLess >::const_iterator I;
432 I i = namedStates_->begin( );
433 I end = namedStates_->end( );
434 for( ; i != end; ++i )
436 dst->addNamedState( i->first, i->second->getHandle( env, dyn ) , i->second );
441 typedef list< Ast::StateReference * >::const_iterator I;
442 I i = orderedStates_->begin( );
443 I end = orderedStates_->end( );
444 for( ; i != end; ++i )
446 dst->addOrderedState( (*i)->getHandle( env, dyn ), *i );
453 Kernel::VariableHandle
454 Ast::ArgListExprs::findNamed( RefCountPtr< const Lang::SingleList > vals, const char * name ) const
456 /* This function is called when a Lang::Structure is asked for a field by name.
457 * This is reflected in the generated error in case the name is not found.
460 typedef const Lang::SingleListPair ConsType;
462 /* Note that the arguments are bound in backwards-order, since that is how the values are accessed.
465 typedef std::map< const char *, Ast::Expression *, charPtrLess >::const_reverse_iterator I;
466 I i = namedExprs_->rbegin( );
467 I end = namedExprs_->rend( );
468 for( ; i != end; ++i )
470 RefCountPtr< ConsType > lst = vals.down_cast< ConsType >( );
471 if( lst == NullPtr< ConsType >( ) )
473 throw Exceptions::InternalError( strrefdup( "Out of argument values when searching fields." ) );
475 if( strcmp( i->first, name ) == 0 )
477 return lst->car_;
479 vals = lst->cdr_;
482 throw Exceptions::NonExistentMember( strrefdup( "< user union >" ), name );
485 Kernel::VariableHandle
486 Ast::ArgListExprs::getOrdered( RefCountPtr< const Lang::SingleList > vals, size_t pos ) const
488 /* This function is called when a Lang::Structure is asked for a field by position.
489 * This is reflected in the generated error in case the position is not found.
492 typedef const Lang::SingleListPair ConsType;
494 /* Note that the arguments are bound in backwards-order, since that is how the values are accessed.
497 size_t i = 0;
499 typedef list< Ast::Expression * >::const_iterator I;
500 while( true )
502 RefCountPtr< ConsType > lst = vals.down_cast< ConsType >( );
503 if( lst == NullPtr< ConsType >( ) )
505 break;
507 if( i == pos )
509 return lst->car_;
511 vals = lst->cdr_;
512 ++i;
516 throw Exceptions::NonExistentPosition( pos, i - 1 );
519 void
520 Ast::ArgListExprs::analyze( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
522 parent_ = parent;
524 RefCountPtr< Ast::StateIDSet > passedStates( new Ast::StateIDSet );
526 /* First traverse state arguments, so that we know which states that must not appear in the value arguments.
529 typedef typeof *orderedStates_ ListType;
530 for( ListType::iterator i = orderedStates_->begin( ); i != orderedStates_->end( ); ++i )
532 (*i)->analyze( parent_, env, passedStates.getPtr( ) );
536 typedef typeof *namedStates_ ListType;
537 for( ListType::iterator i = namedStates_->begin( ); i != namedStates_->end( ); ++i )
539 i->second->analyze( parent_, env, passedStates.getPtr( ) );
542 if( passedStates->size( ) < orderedStates_->size( ) + namedStates_->size( ) )
544 Ast::theAnalysisErrorsList.push_back( new Exceptions::RepeatedStateArgument( parent_->loc( ), passedStates ) );
547 /* Traverse children
550 typedef typeof *orderedExprs_ ListType;
551 for( ListType::iterator i = orderedExprs_->begin( ); i != orderedExprs_->end( ); ++i )
553 if( (*i)->immediate_ )
555 (*i)->analyze( parent_, env, freeStatesDst );
557 else
559 Ast::StateIDSet freeStates;
560 (*i)->analyze( parent_, env, & freeStates );
561 for( Ast::StateIDSet::const_iterator j = freeStates.begin( ); j != freeStates.end( ); ++j )
563 if( passedStates->find( *j ) != passedStates->end( ) )
565 Ast::theAnalysisErrorsList.push_back( new Exceptions::FreeStateIsAlsoPassed( (*i)->loc( ), *j ) );
567 freeStatesDst->insert( *j );
573 typedef typeof *namedExprs_ ListType;
574 for( ListType::iterator i = namedExprs_->begin( ); i != namedExprs_->end( ); ++i )
576 if( i->second->immediate_ )
578 i->second->analyze( parent_, env, freeStatesDst );
580 else
582 Ast::StateIDSet freeStates;
583 i->second->analyze( parent_, env, & freeStates );
584 for( Ast::StateIDSet::const_iterator j = freeStates.begin( ); j != freeStates.end( ); ++j )
586 if( passedStates->find( *j ) != passedStates->end( ) )
588 Ast::theAnalysisErrorsList.push_back( new Exceptions::FreeStateIsAlsoPassed( i->second->loc( ), *j ) );
590 freeStatesDst->insert( *j );
597 for( Ast::StateIDSet::const_iterator i = passedStates->begin( ); i != passedStates->end( ); ++i )
599 freeStatesDst->insert( *i );
604 Ast::ArgListExprs::ConstIterator
605 Ast::ArgListExprs::begin( ) const
607 return Ast::ArgListExprs::ConstIterator( orderedExprs_->rbegin( ), namedExprs_->begin( ), 0 );
611 Ast::FunctionFunction::FunctionFunction( const Ast::SourceLocation & loc, const Kernel::Formals * formals, Ast::Expression * body, const Ast::FunctionMode & functionMode )
612 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< function construction >" ), false ) ), loc_( loc ), formals_( formals ), body_( body ), functionMode_( functionMode )
615 Ast::FunctionFunction::~FunctionFunction( )
617 delete formals_;
618 delete body_;
621 void
622 Ast::FunctionFunction::push_exprs( Ast::ArgListExprs * args ) const
624 formals_->push_exprs( args );
627 void
628 Ast::FunctionFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * parentEnv, Ast::StateIDSet * freeStatesDst )
630 Ast::AnalysisEnvironment * env( new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList, parentEnv, formals_->argumentOrder_, formals_->stateOrder_ ) );
631 env->activateFunctionBoundary( );
633 /* We know that the body does not access states outside the function's scope, so we can simply
634 * leave freeStatesDst without change.
636 Ast::StateIDSet freeStates;
637 body_->analyze( parent, env, & freeStates );
640 void
641 Ast::FunctionFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
643 Kernel::ContRef cont = evalState->cont_;
644 cont->takeValue( Kernel::ValueRef( new Lang::UserFunction( formals_->newEvaluatedFormals( args ),
645 body_, evalState->env_, functionMode_ ) ),
646 evalState );
650 Kernel::CallCont_last::CallCont_last( const RefCountPtr< const Lang::Function > & fun, const Ast::ArgListExprs * argList, bool curry, Kernel::StateHandle mutatorSelf, const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, const Kernel::ContRef & cont, const Ast::SourceLocation & callLoc )
651 : Kernel::Continuation( callLoc ), fun_( fun ), argList_( argList ), curry_( curry ), mutatorSelf_( mutatorSelf ), env_( env ), dyn_( dyn ), cont_( cont )
654 Kernel::CallCont_last::~CallCont_last( )
657 void
658 Kernel::CallCont_last::takeValue( const RefCountPtr< const Lang::Value > & valsUntyped, Kernel::EvalState * evalState, bool dummy ) const
660 typedef const Lang::SingleList ArgType;
661 RefCountPtr< ArgType > vals = Helpers::down_cast< ArgType >( valsUntyped, "< Internal error situation in CallCont_last >" );
663 Kernel::Arguments args = fun_->newCurriedArguments( );
664 argList_->bind( & args, vals, env_, dyn_ );
665 if( mutatorSelf_ != 0 )
667 args.setMutatorSelf( mutatorSelf_ );
670 if( curry_ )
672 evalState->cont_ = cont_;
673 cont_->takeValue( Kernel::ValueRef( new Lang::CuteFunction( fun_, args ) ), evalState );
675 else
677 evalState->env_ = env_; /* This matters only when the function being called is FunctionFunction! */
678 evalState->dyn_ = dyn_;
679 evalState->cont_ = cont_;
680 fun_->call( evalState, args, traceLoc_ );
684 Kernel::ContRef
685 Kernel::CallCont_last::up( ) const
687 return cont_;
690 RefCountPtr< const char >
691 Kernel::CallCont_last::description( ) const
693 return strrefdup( "function call's application" );
696 void
697 Kernel::CallCont_last::gcMark( Kernel::GCMarkedSet & marked )
699 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
700 dyn_->gcMark( marked );
701 cont_->gcMark( marked );
704 Kernel::CallContInfo::CallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, std::vector< bool > * forcePos )
705 : forcePos_( forcePos ), forceAll_( false ), argList_( argList ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
708 Kernel::CallContInfo::CallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, bool forceAll )
709 : forcePos_( 0 ), forceAll_( forceAll ), argList_( argList ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
712 Kernel::CallContInfo::~CallContInfo( )
714 if( forcePos_ != 0 )
716 delete forcePos_;
720 bool
721 Kernel::CallContInfo::force( const size_t & pos ) const
723 if( forcePos_ != 0 )
725 return (*forcePos_)[ pos ];
727 return forceAll_;
730 bool
731 Kernel::CallContInfo::isSelective( ) const
733 return forcePos_ != 0;
736 void
737 Kernel::CallContInfo::gcMark( Kernel::GCMarkedSet & marked )
739 env_->gcMark( marked );
740 dyn_->gcMark( marked );
741 cont_->gcMark( marked );
744 Kernel::CallCont_n::CallCont_n( const Ast::SourceLocation & traceLoc, const RefCountPtr< const Kernel::CallContInfo > & info, const Ast::ArgListExprs::ConstIterator & pos, RefCountPtr< const Lang::SingleList > vals )
745 : Kernel::Continuation( traceLoc ), info_( info ), pos_( pos ), vals_( vals )
748 Kernel::CallCont_n::~CallCont_n( )
751 void
752 Kernel::CallCont_n::takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
754 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
755 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
758 if( val->isThunk( ) )
760 val->force( val, evalState );
761 return;
763 if( val == Kernel::THE_SLOT_VARIABLE )
765 /* If we don't detect this, the error messages that will be printed later would be very confusing,
766 * saying that the argument is missing, when the problem is likely to be that some internal
767 * computation should result in THE_VOID_VARIABLE rather than THE_SLOT_VARIABLE.
769 throw Exceptions::InternalError( "An argument expression evaluated to THE_SLOT_VARIABLE." );
771 info_->argList_->evaluate( info_,
772 pos_,
773 RefCountPtr< const Lang::SingleListPair >( new Lang::SingleListPair( val, vals_ ) ),
774 evalState );
777 Kernel::ContRef
778 Kernel::CallCont_n::up( ) const
780 return info_->cont_;
783 RefCountPtr< const char >
784 Kernel::CallCont_n::description( ) const
786 return strrefdup( "function call's argument" );
789 void
790 Kernel::CallCont_n::gcMark( Kernel::GCMarkedSet & marked )
792 const_cast< Kernel::CallContInfo * >( info_.getPtr( ) )->gcMark( marked );
793 const_cast< Lang::SingleList * >( vals_.getPtr( ) )->gcMark( marked );
797 Kernel::CallCont_1::CallCont_1( const Ast::SourceLocation & traceLoc, const Ast::ArgListExprs * argList, bool curry, Kernel::StateHandle mutatorSelf, const Kernel::EvalState & evalState, const Ast::SourceLocation & callLoc )
798 : Kernel::Continuation( traceLoc ), argList_( argList ), curry_( curry ), mutatorSelf_( mutatorSelf ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ ), callLoc_( callLoc )
801 Kernel::CallCont_1::~CallCont_1( )
804 void
805 Kernel::CallCont_1::takeValue( const RefCountPtr< const Lang::Value > & funUntyped, Kernel::EvalState * evalState, bool dummy ) const
808 typedef const Lang::Function ArgType;
809 RefCountPtr< ArgType > fun = funUntyped.down_cast< const Lang::Function >( );
810 if( fun != NullPtr< ArgType >( ) )
812 evalState->env_ = env_;
813 evalState->dyn_ = dyn_;
814 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_last( fun, argList_, curry_, mutatorSelf_, env_, dyn_, cont_, callLoc_ ) );
815 argList_->evaluate( fun->newCallContInfo( argList_, *evalState ),
816 argList_->begin( ), Lang::THE_CONS_NULL,
817 evalState );
818 return;
822 typedef const Lang::Transform2D ArgType;
823 ArgType * transformVal = dynamic_cast< ArgType * >( funUntyped.getPtr( ) );
824 if( transformVal != 0 )
826 if( curry_ )
828 throw Exceptions::MiscellaneousRequirement( strrefdup( "Don't Curry transform applications. It's useless anyway!" ) );
830 if( argList_->orderedExprs_->size( ) != 1 )
832 throw Exceptions::CoreArityMismatch( "<transform application>", 1, argList_->orderedExprs_->size( ) );
834 if( ! argList_->namedExprs_->empty( ) )
836 throw Exceptions::CoreNoNamedFormals( "<transform application>" );
838 evalState->expr_ = argList_->orderedExprs_->front( );
839 evalState->env_ = env_;
840 evalState->dyn_ = dyn_;
841 evalState->cont_ = Kernel::ContRef( new Kernel::Transform2DCont( *transformVal, cont_, callLoc_ ) );
842 return;
846 typedef const Lang::Transform3D ArgType;
847 ArgType * transformVal = dynamic_cast< ArgType * >( funUntyped.getPtr( ) );
848 if( transformVal != 0 )
850 if( curry_ )
852 throw Exceptions::MiscellaneousRequirement( strrefdup( "Don't Curry transform applications. It's useless anyway!" ) );
854 if( argList_->orderedExprs_->size( ) != 1 )
856 throw Exceptions::CoreArityMismatch( "<transform application>", 1, argList_->orderedExprs_->size( ) );
858 if( ! argList_->namedExprs_->empty( ) )
860 throw Exceptions::CoreNoNamedFormals( "<transform application>" );
862 evalState->expr_ = argList_->orderedExprs_->front( );
863 evalState->env_ = env_;
864 evalState->dyn_ = dyn_;
865 evalState->cont_ = Kernel::ContRef( new Kernel::Transform3DCont( *transformVal, cont_, callLoc_ ) );
866 return;
871 typedef const Lang::ElementaryPath2D ArgType;
872 RefCountPtr< ArgType > path = NullPtr< ArgType >( );
875 path = Helpers::elementaryPathCast2D( funUntyped, this );
877 catch( const Exceptions::ContinuationTypeMismatch & ball )
879 goto nextType1;
882 if( curry_ )
884 throw Exceptions::MiscellaneousRequirement( strrefdup( "Don't Curry path point selection. It's useless anyway!" ) );
886 if( argList_->orderedExprs_->size( ) != 1 )
888 throw Exceptions::CoreArityMismatch( "<path point selection>", 1, argList_->orderedExprs_->size( ) );
890 if( ! argList_->namedExprs_->empty( ) )
892 throw Exceptions::CoreNoNamedFormals( "<path point selection>" );
895 evalState->expr_ = argList_->orderedExprs_->front( );
896 evalState->env_ = env_;
897 evalState->dyn_ = dyn_;
898 evalState->cont_ = Kernel::ContRef( new Kernel::PathApplication2DCont( path,
899 cont_,
900 callLoc_ ) );
901 return;
903 nextType1:
906 typedef const Lang::ElementaryPath3D ArgType;
907 RefCountPtr< ArgType > path = NullPtr< ArgType >( );
910 path = Helpers::elementaryPathCast3D( funUntyped, this );
912 catch( const Exceptions::ContinuationTypeMismatch & ball )
914 goto nextType2;
917 if( curry_ )
919 throw Exceptions::MiscellaneousRequirement( strrefdup( "Don't Curry path point selection. It's useless anyway!" ) );
921 if( argList_->orderedExprs_->size( ) != 1 )
923 throw Exceptions::CoreArityMismatch( "<path point selection>", 1, argList_->orderedExprs_->size( ) );
925 if( ! argList_->namedExprs_->empty( ) )
927 throw Exceptions::CoreNoNamedFormals( "<path point selection>" );
930 evalState->expr_ = argList_->orderedExprs_->front( );
931 evalState->env_ = env_;
932 evalState->dyn_ = dyn_;
933 evalState->cont_ = Kernel::ContRef( new Kernel::PathApplication3DCont( path,
934 cont_,
935 callLoc_ ) );
936 return;
938 nextType2:
940 throw Exceptions::TypeMismatch( traceLoc_,
941 funUntyped->getTypeName( ),
942 Helpers::typeSetString( Lang::Function::staticTypeName( ),
943 Lang::Transform2D::staticTypeName( ),
944 Lang::Transform3D::staticTypeName( ),
945 Lang::ElementaryPath2D::staticTypeName( ),
946 Lang::ElementaryPath3D::staticTypeName( ) ) );
949 Kernel::ContRef
950 Kernel::CallCont_1::up( ) const
952 return cont_;
955 RefCountPtr< const char >
956 Kernel::CallCont_1::description( ) const
958 return strrefdup( "function call's function" );
961 void
962 Kernel::CallCont_1::gcMark( Kernel::GCMarkedSet & marked )
964 dyn_->gcMark( marked );
965 cont_->gcMark( marked );
970 Ast::CallExpr::CallExpr( const Ast::SourceLocation & loc, Ast::Expression * funExpr, Ast::ArgListExprs * argList, bool curry )
971 : Ast::Expression( loc ), curry_( curry ), constFun_( Kernel::THE_NO_FUNCTION ), mutatorSelf_( 0 ), funExpr_( funExpr ), argList_( argList )
974 Ast::CallExpr::CallExpr( const Ast::SourceLocation & loc, const RefCountPtr< const Lang::Function > & constFun, Ast::ArgListExprs * argList, bool curry )
975 : Ast::Expression( loc ), curry_( curry ), constFun_( constFun ), mutatorSelf_( 0 ), funExpr_( 0 ), argList_( argList )
978 Ast::CallExpr::~CallExpr( )
980 if( funExpr_ != 0 )
982 delete funExpr_;
984 if( mutatorSelf_ != 0 )
986 delete mutatorSelf_;
988 delete argList_;
991 void
992 Ast::CallExpr::setMutatorSelf( Ast::StateReference * mutatorSelf )
994 mutatorSelf_ = mutatorSelf;
997 void
998 Ast::CallExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1000 if( mutatorSelf_ != 0 )
1002 mutatorSelf_->analyze( this, env, freeStatesDst );
1004 if( funExpr_ != 0 )
1006 funExpr_->analyze( this, env, freeStatesDst );
1008 else
1010 const_cast< Lang::Function * >( constFun_.getPtr( ) )->analyze( this, env );
1012 argList_->analyze( this, env, freeStatesDst );
1015 void
1016 Ast::CallExpr::eval( Kernel::EvalState * evalState ) const
1018 if( funExpr_ != 0 )
1020 evalState->expr_ = funExpr_;
1021 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_1( evalState->expr_->loc( ), argList_, curry_, mutatorSelf_ ? (mutatorSelf_->getHandle( evalState->env_, evalState->dyn_ )) : 0, *evalState, loc_ ) );
1023 else
1025 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_last( constFun_, argList_, curry_, mutatorSelf_ ? (mutatorSelf_->getHandle( evalState->env_, evalState->dyn_ )) : 0, evalState->env_, evalState->dyn_, evalState->cont_, loc_ ) );
1026 argList_->evaluate( constFun_->newCallContInfo( argList_, *evalState ),
1027 argList_->begin( ), Lang::THE_CONS_NULL,
1028 evalState );
1032 Kernel::UnionCont_last::UnionCont_last( const Ast::ArgListExprs * argList, const Kernel::ContRef & cont, const Ast::SourceLocation & callLoc )
1033 : Kernel::Continuation( callLoc ), argList_( argList ), cont_( cont )
1036 Kernel::UnionCont_last::~UnionCont_last( )
1039 void
1040 Kernel::UnionCont_last::takeValue( const RefCountPtr< const Lang::Value > & valsUntyped, Kernel::EvalState * evalState, bool dummy ) const
1042 typedef const Lang::SingleList ArgType;
1043 RefCountPtr< ArgType > vals = Helpers::down_cast< ArgType >( valsUntyped, "< Internal error situation in UnionCont_last >" );
1045 evalState->cont_ = cont_;
1046 cont_->takeValue( Kernel::ValueRef( new Lang::Structure( argList_, vals ) ),
1047 evalState );
1050 Kernel::ContRef
1051 Kernel::UnionCont_last::up( ) const
1053 return cont_;
1056 RefCountPtr< const char >
1057 Kernel::UnionCont_last::description( ) const
1059 return strrefdup( "union" );
1062 void
1063 Kernel::UnionCont_last::gcMark( Kernel::GCMarkedSet & marked )
1065 cont_->gcMark( marked );
1069 Ast::UnionExpr::UnionExpr( const Ast::SourceLocation & loc, Ast::ArgListExprs * argList )
1070 : Ast::Expression( loc ), argList_( argList )
1073 Ast::UnionExpr::~UnionExpr( )
1075 delete argList_;
1079 void
1080 Ast::UnionExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1082 argList_->analyze( this, env, freeStatesDst );
1085 void
1086 Ast::UnionExpr::eval( Kernel::EvalState * evalState ) const
1088 evalState->cont_ = Kernel::ContRef( new Kernel::UnionCont_last( argList_, evalState->cont_, loc_ ) );
1090 argList_->evaluate( RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList_, *evalState, false ) ),
1091 argList_->begin( ), Lang::THE_CONS_NULL,
1092 evalState );
1096 Kernel::SplitCont_1::SplitCont_1( const Ast::SourceLocation & traceLoc, Ast::Expression * argList, bool curry, const Kernel::EvalState & evalState, const Ast::SourceLocation & callLoc )
1097 : Kernel::Continuation( traceLoc ), argList_( argList ), curry_( curry ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ ), callLoc_( callLoc )
1100 Kernel::SplitCont_1::~SplitCont_1( )
1103 void
1104 Kernel::SplitCont_1::takeValue( const RefCountPtr< const Lang::Value > & funUntyped, Kernel::EvalState * evalState, bool dummy ) const
1106 typedef const Lang::Function ArgType;
1107 RefCountPtr< ArgType > fun = Helpers::down_cast< ArgType >( funUntyped, "Split's function" );
1109 evalState->env_ = env_;
1110 evalState->dyn_ = dyn_;
1111 evalState->cont_ = Kernel::ContRef( new Kernel::SplitCont_2( fun, curry_, env_, dyn_, cont_, callLoc_ ) );
1112 evalState->expr_ = argList_;
1115 Kernel::ContRef
1116 Kernel::SplitCont_1::up( ) const
1118 return cont_;
1121 RefCountPtr< const char >
1122 Kernel::SplitCont_1::description() const
1124 return strrefdup( "split call's function" );
1127 void
1128 Kernel::SplitCont_1::gcMark( Kernel::GCMarkedSet & marked )
1130 dyn_->gcMark( marked );
1131 cont_->gcMark( marked );
1135 Kernel::SplitCont_2::SplitCont_2( const RefCountPtr< const Lang::Function > & fun, bool curry, const Kernel::PassedEnv & env, const Kernel::PassedDyn & dyn, const Kernel::ContRef & cont, const Ast::SourceLocation & callLoc )
1136 : Kernel::Continuation( callLoc ), fun_( fun ), curry_( curry ), env_( env ), dyn_( dyn ), cont_( cont )
1139 Kernel::SplitCont_2::~SplitCont_2( )
1142 void
1143 Kernel::SplitCont_2::takeValue( const RefCountPtr< const Lang::Value > & valsUntyped, Kernel::EvalState * evalState, bool dummy ) const
1145 typedef const Lang::Structure ArgType;
1146 RefCountPtr< ArgType > structure = Helpers::down_cast< ArgType >( valsUntyped, "Split" );
1148 Kernel::Arguments args = fun_->newCurriedArguments( );
1149 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1151 if( curry_ )
1153 evalState->cont_ = cont_;
1154 cont_->takeValue( Kernel::ValueRef( new Lang::CuteFunction( fun_, args ) ),
1155 evalState );
1157 else
1159 evalState->dyn_ = dyn_;
1160 evalState->cont_ = cont_;
1161 fun_->call( evalState, args, traceLoc_ );
1165 Kernel::ContRef
1166 Kernel::SplitCont_2::up( ) const
1168 return cont_;
1171 RefCountPtr< const char >
1172 Kernel::SplitCont_2::description( ) const
1174 return strrefdup( "Split/splice" );
1177 void
1178 Kernel::SplitCont_2::gcMark( Kernel::GCMarkedSet & marked )
1180 cont_->gcMark( marked );
1184 Ast::CallSplitExpr::CallSplitExpr( const Ast::SourceLocation & loc, Ast::Expression * funExpr, Ast::Expression * argList, bool curry )
1185 : Ast::Expression( loc ), curry_( curry ), funExpr_( funExpr ), argList_( argList )
1188 Ast::CallSplitExpr::~CallSplitExpr( )
1190 delete funExpr_;
1191 delete argList_;
1195 void
1196 Ast::CallSplitExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1198 funExpr_->analyze( this, env, freeStatesDst );
1199 argList_->analyze( this, env, freeStatesDst );
1202 void
1203 Ast::CallSplitExpr::eval( Kernel::EvalState * evalState ) const
1205 evalState->expr_ = funExpr_;
1206 evalState->cont_ = Kernel::ContRef( new Kernel::SplitCont_1( evalState->expr_->loc( ), argList_, curry_, *evalState, loc_ ) );
1210 Ast::DummyExpression::DummyExpression( )
1211 : Ast::Expression( Ast::THE_UNKNOWN_LOCATION )
1214 Ast::DummyExpression::DummyExpression( const Ast::SourceLocation & loc )
1215 : Ast::Expression( loc )
1218 Ast::DummyExpression::~DummyExpression( )
1221 void
1222 Ast::DummyExpression::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1224 /* Nothing to do! */
1227 void
1228 Ast::DummyExpression::eval( Kernel::EvalState * evalState ) const
1230 throw Exceptions::InternalError( strrefdup( "A DummyExpression must never be evaluated." ) );