Remove old documentation chapter on core bindings
[shapes.git] / source / astfun.cc
blob64ef19b87339d9f2a822f5bce1c310c25bb4dc10
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, 2014 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"
28 #include "astvalues.h"
29 #include "texlabelmanager.h"
31 #include <sstream>
33 using namespace Shapes;
34 using namespace std;
37 Kernel::Formals::Formals( )
38 : loc_( Ast::THE_UNKNOWN_LOCATION ),
39 seenDefault_( false ),
40 argumentIdentifiers_( new Ast::IdentifierTree( NULL, false ) ),
41 argumentOrder_( new std::map< const char *, size_t, charPtrLess > ),
42 sink_( NULL ),
43 stateIdentifiers_( new Ast::IdentifierTree( NULL, false ) ),
44 stateOrder_( new std::map< const char *, size_t, charPtrLess > )
45 { }
47 Kernel::Formals::Formals( size_t numberOfDummyDefaultExprs )
48 : loc_( Ast::THE_UNKNOWN_LOCATION ),
49 seenDefault_( false ),
50 argumentIdentifiers_( new Ast::IdentifierTree( NULL, false ) ),
51 argumentOrder_( new std::map< const char *, size_t, charPtrLess > ),
52 sink_( NULL ),
53 stateIdentifiers_( new Ast::IdentifierTree( NULL, false ) ),
54 stateOrder_( new std::map< const char *, size_t, charPtrLess > )
56 // Pushing null expressions is just a way of specifying how many non-sink arguments there are.
57 for( size_t i = 0; i < numberOfDummyDefaultExprs; ++i )
59 defaultExprs_.push_back( NULL );
63 Kernel::Formals::~Formals( )
65 delete argumentIdentifiers_;
66 delete argumentOrder_;
67 delete stateIdentifiers_;
68 delete stateOrder_;
69 if( sink_ != NULL )
71 delete sink_;
75 void
76 Kernel::Formals::setLoc( const Ast::SourceLocation & loc )
78 loc_ = loc;
81 bool
82 Kernel::Formals::appendArgumentFormal( const Ast::PlacedIdentifier & id )
84 size_t pos = argumentIdentifiers_->size( );
85 if( ! argumentIdentifiers_->insert( id, loc_ ) ) /* The source location given here is more or less a dummy, it should never be needed. */
86 return false;
87 argumentOrder_->insert( std::pair< const char *, size_t >( id.simpleId( ), pos ) );
88 return true;
91 bool
92 Kernel::Formals::appendStateFormal( const Ast::PlacedIdentifier & id )
94 size_t pos = stateIdentifiers_->size( );
95 if( ! stateIdentifiers_->insert( id, loc_ ) ) /* The source location given here is more or less a dummy, it should never be needed. */
96 return false;
97 stateOrder_->insert( std::pair< const char *, size_t >( id.simpleId( ), pos ) );
98 return true;
101 void
102 Kernel::Formals::push_exprs( Ast::ArgListExprs * args ) const
104 typedef typeof defaultExprs_ ListType;
105 for( ListType::const_iterator i = defaultExprs_.begin( ); i != defaultExprs_.end( ); ++i )
107 if( *i != 0 )
109 args->orderedExprs_->push_back( *i );
114 Kernel::EvaluatedFormals *
115 Kernel::Formals::newEvaluatedFormals( Kernel::Arguments & args ) const
117 size_t pos = 0;
118 return newEvaluatedFormals( args, & pos );
121 Kernel::EvaluatedFormals *
122 Kernel::Formals::newEvaluatedFormals( Kernel::Arguments & args, size_t * pos ) const
124 Kernel::EvaluatedFormals * res = new Kernel::EvaluatedFormals( const_cast< Kernel::Formals * >( this ) );
125 res->isSink_ = false; // The formals created here belong to user functions, which are exactly those which are not sinks.
127 res->defaults_.reserve( defaultExprs_.size( ) );
128 res->locations_.reserve( defaultExprs_.size( ) );
130 typedef typeof defaultExprs_ ListType;
131 for( ListType::const_iterator i = defaultExprs_.begin( ); i != defaultExprs_.end( ); ++i )
133 if( *i != 0 )
135 res->defaults_.push_back( args.getHandle( *pos ) );
136 res->locations_.push_back( args.getNode( *pos ) );
137 ++(*pos);
139 else
141 res->defaults_.push_back( Kernel::THE_SLOT_VARIABLE );
142 res->locations_.push_back( 0 ); // I really hope this is never dereferenced!
146 return res;
149 std::vector< bool > *
150 Kernel::Formals::newArgListForcePos( const Ast::ArgListExprs * argList ) const
152 /* Here, we use the knowledge that ordered arguments are evaluated backwards, and named arguments
153 * in the natural order (the lexiographic order of std::map).
156 std::vector< bool > * res = new std::vector< bool >;
157 res->resize( argList->orderedExprs_->size( ) );
158 res->reserve( argList->orderedExprs_->size( ) + argList->namedExprs_->size( ) );
160 if( ! argList->orderedExprs_->empty( ) )
162 typedef typeof forcePos_ SrcType;
163 SrcType::const_iterator src = forcePos_.begin( );
164 for( size_t arg = argList->orderedExprs_->size( ) - 1; ; --arg, ++src )
166 (*res)[ arg ] = *src;
167 if( arg == 0 )
169 break;
175 typedef typeof *argList->namedExprs_ MapType;
176 MapType::const_iterator end = argList->namedExprs_->end( );
177 for( MapType::const_iterator arg = argList->namedExprs_->begin( ); arg != end; ++arg )
179 res->push_back( forcePos_[ (*argumentOrder_)[ arg->first ] ] );
183 return res;
186 std::vector< bool > *
187 Kernel::Formals::newArgListForcePos( const Ast::ArgListExprs * argList, const Kernel::Arguments & curryArgs ) const
189 /* Compare with the non-curry version!
192 std::vector< bool > * res = new std::vector< bool >;
193 res->resize( argList->orderedExprs_->size( ) );
194 res->reserve( argList->orderedExprs_->size( ) + argList->namedExprs_->size( ) );
196 if( ! argList->orderedExprs_->empty( ) )
198 typedef typeof forcePos_ SrcType;
199 SrcType::const_iterator src = forcePos_.begin( );
200 size_t curryPos = 0;
201 while( curryPos < curryArgs.size( ) &&
202 ! curryArgs.isSlot( curryPos ) )
204 ++src;
205 ++curryPos;
207 for( size_t arg = argList->orderedExprs_->size( ) - 1; ; --arg )
209 (*res)[ arg ] = *src;
210 if( arg == 0 )
212 break;
214 ++src;
215 ++curryPos;
216 while( curryPos < curryArgs.size( ) &&
217 ! curryArgs.isSlot( curryPos ) )
219 ++src;
220 ++curryPos;
226 typedef typeof *argList->namedExprs_ MapType;
227 MapType::const_iterator end = argList->namedExprs_->end( );
228 for( MapType::const_iterator arg = argList->namedExprs_->begin( ); arg != end; ++arg )
230 res->push_back( forcePos_[ (*argumentOrder_)[ arg->first ] ] );
234 return res;
237 const Ast::SourceLocation &
238 Kernel::Formals::loc( ) const
240 return loc_;
245 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 )
246 : i1_( i1 ), i2_( i2 ), index_( index )
249 Ast::ArgListExprs::ConstIterator::ConstIterator( const Ast::ArgListExprs::ConstIterator & orig )
250 : i1_( orig.i1_ ), i2_( orig.i2_ ), index_( orig.index_ )
253 Ast::ArgListExprs::ArgListExprs( bool exprOwner )
254 : exprOwner_( exprOwner ), orderedExprs_( new std::list< Ast::Expression * > ), namedExprs_( new std::map< const char *, Ast::Expression *, charPtrLess > ),
255 orderedStates_( new std::list< Ast::StateReference * > ), namedStates_( new std::map< const char *, Ast::StateReference *, charPtrLess > )
257 // if( exprOwner_ )
258 // {
259 // throw Exceptions::InternalError( strrefdup( "Ast::ArgListExprs( bool _exprOwner ) can only be called with false." ) );
260 // }
263 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 )
264 : exprOwner_( true ), orderedExprs_( orderedExprs ), namedExprs_( namedExprs ), orderedStates_( orderedStates ), namedStates_( namedStates )
267 Ast::ArgListExprs::~ArgListExprs( )
270 if( exprOwner_ )
272 typedef list< Ast::Expression * >::iterator I;
273 for( I i = orderedExprs_->begin( ); i != orderedExprs_->end( ); ++i )
275 delete *i;
278 delete orderedExprs_;
282 if( exprOwner_ )
284 typedef std::map< const char *, Ast::Expression *, charPtrLess >::const_iterator I;
285 for( I i = namedExprs_->begin( ); i != namedExprs_->end( ); ++i )
287 delete i->first;
288 delete i->second;
291 delete namedExprs_;
295 if( exprOwner_ )
297 typedef std::list< Ast::StateReference * >::iterator I;
298 for( I i = orderedStates_->begin( ); i != orderedStates_->end( ); ++i )
300 delete *i;
303 delete orderedStates_;
307 if( exprOwner_ )
309 typedef std::map< const char *, Ast::StateReference *, charPtrLess >::const_iterator I;
310 for( I i = namedStates_->begin( ); i != namedStates_->end( ); ++i )
312 delete i->first;
313 delete i->second;
316 delete namedStates_;
320 Ast::ArgListExprs::ArgListExprs( size_t numberOfOrderedDummyExprs )
321 : 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_ )
323 for( size_t i = 0; i < numberOfOrderedDummyExprs; ++i )
325 orderedExprs_->push_back( new Ast::DummyExpression );
330 void
331 Ast::ArgListExprs::evaluate( const RefCountPtr< const Kernel::CallContInfo > & info, const Ast::ArgListExprs::ConstIterator & pos, const RefCountPtr< const Lang::SingleList > & vals, Kernel::EvalState * evalState ) const
333 std::list< Ast::Expression * >::const_reverse_iterator i1end = orderedExprs_->rend( );
335 if( pos.i1_ == i1end &&
336 pos.i2_ == namedExprs_->end( ) )
338 evalState->cont_ = info->cont_;
339 info->cont_->takeValue( vals, evalState );
340 return;
343 if( pos.i1_ != i1end )
345 /* Note that it is necessary that the evaluation of expressions with free states is not delayed.
346 * If it would, it would be very strange for the calling function if a passed state would change
347 * value in response to the accessing of a formal parameter.
349 if( info->force( pos.index_ ) || (*(pos.i1_))->immediate_ )
351 typedef typeof const_cast< Ast::ArgListExprs::ConstIterator & >( pos ).i1_ Iterator;
352 Iterator next = pos.i1_;
353 ++next;
354 evalState->expr_ = *(pos.i1_);
355 evalState->env_ = info->env_;
356 evalState->dyn_ = info->dyn_;
357 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_n( evalState->expr_->loc( ),
358 info,
359 Ast::ArgListExprs::ConstIterator( next, pos.i2_, pos.index_ + 1 ),
360 vals ) );
361 return;
363 else
365 /* Delay evaluation of this argument by just putting a thunk in the list.
367 typedef typeof const_cast< Ast::ArgListExprs::ConstIterator & >( pos ).i1_ Iterator;
368 Iterator next = pos.i1_;
369 ++next;
370 evaluate( info,
371 Ast::ArgListExprs::ConstIterator( next, pos.i2_, pos.index_ + 1 ),
372 RefCountPtr< const Lang::SingleListPair >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( info->env_, info->dyn_, *pos.i1_ ) ) ),
373 vals ) ),
374 evalState );
375 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
376 * will always completes without evaluation of expressions. */
379 else
381 if( info->force( pos.index_ ) || pos.i2_->second->immediate_ )
383 typedef typeof const_cast< Ast::ArgListExprs::ConstIterator & >( pos ).i2_ Iterator;
384 Iterator next = pos.i2_;
385 ++next;
386 evalState->expr_ = pos.i2_->second;
387 evalState->env_ = info->env_;
388 evalState->dyn_ = info->dyn_;
389 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_n( evalState->expr_->loc( ),
390 info,
391 Ast::ArgListExprs::ConstIterator( pos.i1_, next, pos.index_ + 1 ),
392 vals ) );
393 return;
395 else
397 /* Delay evaluation of this argument by just putting a thunk in the list.
399 typedef typeof const_cast< Ast::ArgListExprs::ConstIterator & >( pos ).i2_ Iterator;
400 Iterator next = pos.i2_;
401 ++next;
402 evaluate( info,
403 Ast::ArgListExprs::ConstIterator( pos.i1_, next, pos.index_ + 1 ),
404 RefCountPtr< const Lang::SingleListPair >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( new Kernel::Thunk( info->env_, info->dyn_, pos.i2_->second ) ) ),
405 vals ) ),
406 evalState );
407 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
408 * will always complete without evaluation of expressions. */
413 void
414 Ast::ArgListExprs::bind( Kernel::Arguments * dst, RefCountPtr< const Lang::SingleList > vals, Kernel::PassedEnv env, Kernel::PassedDyn dyn ) const
416 typedef const Lang::SingleListPair ConsType;
418 /* Note that the arguments are bound in backwards-order, since that is how the values are accessed.
422 typedef std::map< const char *, Ast::Expression *, charPtrLess >::const_reverse_iterator I;
423 I i = namedExprs_->rbegin( );
424 I end = namedExprs_->rend( );
425 for( ; i != end; ++i )
427 RefCountPtr< ConsType > lst = vals.down_cast< ConsType >( );
428 if( lst == NullPtr< ConsType >( ) )
430 throw Exceptions::InternalError( strrefdup( "Out of argument values when binding application." ) );
432 dst->addNamedArgument( i->first, lst->car_, i->second );
433 vals = lst->cdr_;
438 typedef list< Ast::Expression * >::const_iterator I;
439 I i = orderedExprs_->begin( );
440 I end = orderedExprs_->end( );
441 for( ; i != end; ++i )
443 RefCountPtr< ConsType > lst = vals.down_cast< ConsType >( );
444 if( lst == NullPtr< ConsType >( ) )
446 throw Exceptions::InternalError( strrefdup( "Out of argument values when binding application." ) );
448 dst->addOrderedArgument( lst->car_, *i );
449 vals = lst->cdr_;
453 /* Here, it could/should be verified that vals is null. However, it only isn't in case of an internal error...
456 /* Next, we turn to the states. The states need no evaluation, as they are always passed by reference.
460 typedef std::map< const char *, Ast::StateReference *, charPtrLess >::const_iterator I;
461 I i = namedStates_->begin( );
462 I end = namedStates_->end( );
463 for( ; i != end; ++i )
465 dst->addNamedState( i->first, i->second->getHandle( env, dyn ) , i->second );
470 typedef list< Ast::StateReference * >::const_iterator I;
471 I i = orderedStates_->begin( );
472 I end = orderedStates_->end( );
473 for( ; i != end; ++i )
475 dst->addOrderedState( (*i)->getHandle( env, dyn ), *i );
482 Kernel::VariableHandle
483 Ast::ArgListExprs::findNamed( RefCountPtr< const Lang::SingleList > vals, const char * name ) const
485 /* This function is called when a Lang::Structure is asked for a field by name.
486 * This is reflected in the generated error in case the name is not found.
489 typedef const Lang::SingleListPair ConsType;
491 /* Note that the arguments are bound in backwards-order, since that is how the values are accessed.
494 typedef std::map< const char *, Ast::Expression *, charPtrLess >::const_reverse_iterator I;
495 I i = namedExprs_->rbegin( );
496 I end = namedExprs_->rend( );
497 for( ; i != end; ++i )
499 RefCountPtr< ConsType > lst = vals.down_cast< ConsType >( );
500 if( lst == NullPtr< ConsType >( ) )
502 throw Exceptions::InternalError( strrefdup( "Out of argument values when searching fields." ) );
504 if( strcmp( i->first, name ) == 0 )
506 return lst->car_;
508 vals = lst->cdr_;
511 throw Exceptions::NonExistentMember( strrefdup( "< user union >" ), name );
514 Kernel::VariableHandle
515 Ast::ArgListExprs::getOrdered( RefCountPtr< const Lang::SingleList > vals, size_t pos ) const
517 /* This function is called when a Lang::Structure is asked for a field by position.
518 * This is reflected in the generated error in case the position is not found.
521 typedef const Lang::SingleListPair ConsType;
523 /* Note that the arguments are bound in backwards-order, since that is how the values are accessed.
526 size_t i = 0;
527 while( true )
529 RefCountPtr< ConsType > lst = vals.down_cast< ConsType >( );
530 if( lst == NullPtr< ConsType >( ) )
532 break;
534 if( i == pos )
536 return lst->car_;
538 vals = lst->cdr_;
539 ++i;
542 throw Exceptions::NonExistentPosition( pos, i - 1 );
545 void
546 Ast::ArgListExprs::analyze( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
548 parent_ = parent;
550 RefCountPtr< Ast::StateIDSet > passedStates( new Ast::StateIDSet );
552 /* First traverse state arguments, so that we know which states that must not appear in the value arguments.
555 typedef typeof *orderedStates_ ListType;
556 for( ListType::iterator i = orderedStates_->begin( ); i != orderedStates_->end( ); ++i )
558 (*i)->analyze( parent_, env, passedStates.getPtr( ) );
562 typedef typeof *namedStates_ ListType;
563 for( ListType::iterator i = namedStates_->begin( ); i != namedStates_->end( ); ++i )
565 i->second->analyze( parent_, env, passedStates.getPtr( ) );
568 if( passedStates->size( ) < orderedStates_->size( ) + namedStates_->size( ) )
570 Ast::theAnalysisErrorsList.push_back( new Exceptions::RepeatedStateArgument( parent_->loc( ), passedStates ) );
573 /* Traverse children
576 typedef typeof *orderedExprs_ ListType;
577 for( ListType::iterator i = orderedExprs_->begin( ); i != orderedExprs_->end( ); ++i )
579 if( (*i)->immediate_ )
581 (*i)->analyze( parent_, env, freeStatesDst );
583 else
585 Ast::StateIDSet freeStates;
586 (*i)->analyze( parent_, env, & freeStates );
587 for( Ast::StateIDSet::const_iterator j = freeStates.begin( ); j != freeStates.end( ); ++j )
589 if( passedStates->find( *j ) != passedStates->end( ) )
591 Ast::theAnalysisErrorsList.push_back( new Exceptions::FreeStateIsAlsoPassed( (*i)->loc( ), *j ) );
593 freeStatesDst->insert( *j );
599 typedef typeof *namedExprs_ ListType;
600 for( ListType::iterator i = namedExprs_->begin( ); i != namedExprs_->end( ); ++i )
602 if( i->second->immediate_ )
604 i->second->analyze( parent_, env, freeStatesDst );
606 else
608 Ast::StateIDSet freeStates;
609 i->second->analyze( parent_, env, & freeStates );
610 for( Ast::StateIDSet::const_iterator j = freeStates.begin( ); j != freeStates.end( ); ++j )
612 if( passedStates->find( *j ) != passedStates->end( ) )
614 Ast::theAnalysisErrorsList.push_back( new Exceptions::FreeStateIsAlsoPassed( i->second->loc( ), *j ) );
616 freeStatesDst->insert( *j );
623 for( Ast::StateIDSet::const_iterator i = passedStates->begin( ); i != passedStates->end( ); ++i )
625 freeStatesDst->insert( *i );
630 Ast::ArgListExprs::ConstIterator
631 Ast::ArgListExprs::begin( ) const
633 return Ast::ArgListExprs::ConstIterator( orderedExprs_->rbegin( ), namedExprs_->begin( ), 0 );
637 Ast::FunctionFunction::FunctionFunction( const Ast::SourceLocation & loc, const Kernel::Formals * formals, Ast::Expression * body, const Ast::FunctionMode & functionMode )
638 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< function construction >" ), false ) ), loc_( loc ), formals_( formals ), body_( body ), functionMode_( functionMode )
641 Ast::FunctionFunction::~FunctionFunction( )
643 delete formals_;
644 delete body_;
647 void
648 Ast::FunctionFunction::push_exprs( Ast::ArgListExprs * args ) const
650 formals_->push_exprs( args );
653 void
654 Ast::FunctionFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * parentEnv, Ast::StateIDSet * freeStatesDst )
656 Ast::AnalysisEnvironment * env( new Ast::AnalysisEnvironment( Ast::theAnalysisEnvironmentList, parentEnv, formals_->argumentIdentifiers_, formals_->stateIdentifiers_ ) );
657 env->activateFunctionBoundary( );
659 /* We know that the body does not access states outside the function's scope, so we can simply
660 * leave freeStatesDst without change.
662 Ast::StateIDSet freeStates;
663 body_->analyze( parent, env, & freeStates );
666 void
667 Ast::FunctionFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
669 Kernel::ContRef cont = evalState->cont_;
670 cont->takeValue( Kernel::ValueRef( new Lang::UserFunction( formals_->newEvaluatedFormals( args ),
671 body_, evalState->env_, functionMode_ ) ),
672 evalState );
676 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 )
677 : Kernel::Continuation( callLoc ), fun_( fun ), argList_( argList ), curry_( curry ), mutatorSelf_( mutatorSelf ), env_( env ), dyn_( dyn ), cont_( cont )
680 Kernel::CallCont_last::~CallCont_last( )
683 void
684 Kernel::CallCont_last::takeValue( const RefCountPtr< const Lang::Value > & valsUntyped, Kernel::EvalState * evalState, bool dummy ) const
686 typedef const Lang::SingleList ArgType;
687 RefCountPtr< ArgType > vals = Helpers::down_cast< ArgType >( valsUntyped, "< Internal error situation in CallCont_last >" );
689 Kernel::Arguments args = fun_->newCurriedArguments( );
690 argList_->bind( & args, vals, env_, dyn_ );
691 if( mutatorSelf_ != 0 )
693 args.setMutatorSelf( mutatorSelf_ );
696 if( curry_ )
698 evalState->cont_ = cont_;
699 cont_->takeValue( Kernel::ValueRef( new Lang::CuteFunction( fun_, args ) ), evalState );
701 else
703 evalState->env_ = env_; /* This matters only when the function being called is FunctionFunction! */
704 evalState->dyn_ = dyn_;
705 evalState->cont_ = cont_;
706 fun_->call( evalState, args, traceLoc_ );
710 Kernel::ContRef
711 Kernel::CallCont_last::up( ) const
713 return cont_;
716 RefCountPtr< const char >
717 Kernel::CallCont_last::description( ) const
719 return strrefdup( "function call's application" );
722 void
723 Kernel::CallCont_last::gcMark( Kernel::GCMarkedSet & marked )
725 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
726 dyn_->gcMark( marked );
727 cont_->gcMark( marked );
730 Kernel::CallContInfo::CallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, std::vector< bool > * forcePos )
731 : forcePos_( forcePos ), forceAll_( false ), argList_( argList ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
734 Kernel::CallContInfo::CallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, bool forceAll )
735 : forcePos_( 0 ), forceAll_( forceAll ), argList_( argList ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ )
738 Kernel::CallContInfo::~CallContInfo( )
740 if( forcePos_ != 0 )
742 delete forcePos_;
746 bool
747 Kernel::CallContInfo::force( const size_t & pos ) const
749 if( forcePos_ != 0 )
751 return (*forcePos_)[ pos ];
753 return forceAll_;
756 bool
757 Kernel::CallContInfo::isSelective( ) const
759 return forcePos_ != 0;
762 void
763 Kernel::CallContInfo::gcMark( Kernel::GCMarkedSet & marked )
765 env_->gcMark( marked );
766 dyn_->gcMark( marked );
767 cont_->gcMark( marked );
770 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 )
771 : Kernel::Continuation( traceLoc ), info_( info ), pos_( pos ), vals_( vals )
774 Kernel::CallCont_n::~CallCont_n( )
777 void
778 Kernel::CallCont_n::takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
780 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
781 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
784 if( val->isThunk( ) )
786 val->force( val, evalState );
787 return;
789 if( val == Kernel::THE_SLOT_VARIABLE )
791 /* If we don't detect this, the error messages that will be printed later would be very confusing,
792 * saying that the argument is missing, when the problem is likely to be that some internal
793 * computation should result in THE_VOID_VARIABLE rather than THE_SLOT_VARIABLE.
795 throw Exceptions::InternalError( "An argument expression evaluated to THE_SLOT_VARIABLE." );
797 info_->argList_->evaluate( info_,
798 pos_,
799 RefCountPtr< const Lang::SingleListPair >( new Lang::SingleListPair( val, vals_ ) ),
800 evalState );
803 Kernel::ContRef
804 Kernel::CallCont_n::up( ) const
806 return info_->cont_;
809 RefCountPtr< const char >
810 Kernel::CallCont_n::description( ) const
812 return strrefdup( "function call's argument" );
815 void
816 Kernel::CallCont_n::gcMark( Kernel::GCMarkedSet & marked )
818 const_cast< Kernel::CallContInfo * >( info_.getPtr( ) )->gcMark( marked );
819 const_cast< Lang::SingleList * >( vals_.getPtr( ) )->gcMark( marked );
823 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 )
824 : Kernel::Continuation( traceLoc ), argList_( argList ), curry_( curry ), mutatorSelf_( mutatorSelf ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ ), callLoc_( callLoc )
827 Kernel::CallCont_1::~CallCont_1( )
830 void
831 Kernel::CallCont_1::takeValue( const RefCountPtr< const Lang::Value > & funUntyped, Kernel::EvalState * evalState, bool dummy ) const
834 typedef const Lang::Function ArgType;
835 RefCountPtr< ArgType > fun = funUntyped.down_cast< const Lang::Function >( );
836 if( fun != NullPtr< ArgType >( ) )
838 evalState->env_ = env_;
839 evalState->dyn_ = dyn_;
840 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_last( fun, argList_, curry_, mutatorSelf_, env_, dyn_, cont_, callLoc_ ) );
841 argList_->evaluate( fun->newCallContInfo( argList_, *evalState ),
842 argList_->begin( ), Lang::THE_CONS_NULL,
843 evalState );
844 return;
848 typedef const Lang::Transform2D ArgType;
849 ArgType * transformVal = dynamic_cast< ArgType * >( funUntyped.getPtr( ) );
850 if( transformVal != 0 )
852 if( curry_ )
854 throw Exceptions::MiscellaneousRequirement( strrefdup( "Don't Curry transform applications. It's useless anyway!" ) );
856 if( argList_->orderedExprs_->size( ) != 1 )
858 throw Exceptions::CoreArityMismatch( "<transform application>", 1, argList_->orderedExprs_->size( ) );
860 if( ! argList_->namedExprs_->empty( ) )
862 throw Exceptions::CoreNoNamedFormals( "<transform application>" );
864 evalState->expr_ = argList_->orderedExprs_->front( );
865 evalState->env_ = env_;
866 evalState->dyn_ = dyn_;
867 evalState->cont_ = Kernel::ContRef( new Kernel::Transform2DCont( *transformVal, cont_, callLoc_ ) );
868 return;
872 typedef const Lang::Transform3D ArgType;
873 ArgType * transformVal = dynamic_cast< ArgType * >( funUntyped.getPtr( ) );
874 if( transformVal != 0 )
876 if( curry_ )
878 throw Exceptions::MiscellaneousRequirement( strrefdup( "Don't Curry transform applications. It's useless anyway!" ) );
880 if( argList_->orderedExprs_->size( ) != 1 )
882 throw Exceptions::CoreArityMismatch( "<transform application>", 1, argList_->orderedExprs_->size( ) );
884 if( ! argList_->namedExprs_->empty( ) )
886 throw Exceptions::CoreNoNamedFormals( "<transform application>" );
888 evalState->expr_ = argList_->orderedExprs_->front( );
889 evalState->env_ = env_;
890 evalState->dyn_ = dyn_;
891 evalState->cont_ = Kernel::ContRef( new Kernel::Transform3DCont( *transformVal, cont_, callLoc_ ) );
892 return;
897 typedef const Lang::ElementaryPath2D ArgType;
898 RefCountPtr< ArgType > path = NullPtr< ArgType >( );
901 path = Helpers::elementaryPathCast2D( funUntyped, this );
903 catch( const Exceptions::ContinuationTypeMismatch & ball )
905 goto nextType1;
908 if( curry_ )
910 throw Exceptions::MiscellaneousRequirement( strrefdup( "Don't Curry path point selection. It's useless anyway!" ) );
912 if( argList_->orderedExprs_->size( ) != 1 )
914 throw Exceptions::CoreArityMismatch( "<path point selection>", 1, argList_->orderedExprs_->size( ) );
916 if( ! argList_->namedExprs_->empty( ) )
918 throw Exceptions::CoreNoNamedFormals( "<path point selection>" );
921 evalState->expr_ = argList_->orderedExprs_->front( );
922 evalState->env_ = env_;
923 evalState->dyn_ = dyn_;
924 evalState->cont_ = Kernel::ContRef( new Kernel::PathApplication2DCont( path,
925 cont_,
926 callLoc_ ) );
927 return;
929 nextType1:
932 typedef const Lang::ElementaryPath3D ArgType;
933 RefCountPtr< ArgType > path = NullPtr< ArgType >( );
936 path = Helpers::elementaryPathCast3D( funUntyped, this );
938 catch( const Exceptions::ContinuationTypeMismatch & ball )
940 goto nextType2;
943 if( curry_ )
945 throw Exceptions::MiscellaneousRequirement( strrefdup( "Don't Curry path point selection. It's useless anyway!" ) );
947 if( argList_->orderedExprs_->size( ) != 1 )
949 throw Exceptions::CoreArityMismatch( "<path point selection>", 1, argList_->orderedExprs_->size( ) );
951 if( ! argList_->namedExprs_->empty( ) )
953 throw Exceptions::CoreNoNamedFormals( "<path point selection>" );
956 evalState->expr_ = argList_->orderedExprs_->front( );
957 evalState->env_ = env_;
958 evalState->dyn_ = dyn_;
959 evalState->cont_ = Kernel::ContRef( new Kernel::PathApplication3DCont( path,
960 cont_,
961 callLoc_ ) );
962 return;
964 nextType2:
966 throw Exceptions::TypeMismatch( traceLoc_,
967 funUntyped->getTypeName( ),
968 Helpers::typeSetString( Lang::Function::staticTypeName( ),
969 Lang::Transform2D::staticTypeName( ),
970 Lang::Transform3D::staticTypeName( ),
971 Lang::ElementaryPath2D::staticTypeName( ),
972 Lang::ElementaryPath3D::staticTypeName( ) ) );
975 Kernel::ContRef
976 Kernel::CallCont_1::up( ) const
978 return cont_;
981 RefCountPtr< const char >
982 Kernel::CallCont_1::description( ) const
984 return strrefdup( "function call's function" );
987 void
988 Kernel::CallCont_1::gcMark( Kernel::GCMarkedSet & marked )
990 dyn_->gcMark( marked );
991 cont_->gcMark( marked );
996 Ast::CallExpr::CallExpr( const Ast::SourceLocation & loc, Ast::Expression * funExpr, Ast::ArgListExprs * argList, bool curry )
997 : Ast::Expression( loc ), curry_( curry ), constFun_( Kernel::THE_NO_FUNCTION ), mutatorSelf_( 0 ), funExpr_( funExpr ), argList_( argList )
1000 Ast::CallExpr::CallExpr( const Ast::SourceLocation & loc, const RefCountPtr< const Lang::Function > & constFun, Ast::ArgListExprs * argList, bool curry )
1001 : Ast::Expression( loc ), curry_( curry ), constFun_( constFun ), mutatorSelf_( 0 ), funExpr_( 0 ), argList_( argList )
1004 Ast::CallExpr::~CallExpr( )
1006 if( funExpr_ != 0 )
1008 delete funExpr_;
1010 if( mutatorSelf_ != 0 )
1012 delete mutatorSelf_;
1014 delete argList_;
1017 void
1018 Ast::CallExpr::setMutatorSelf( Ast::StateReference * mutatorSelf )
1020 mutatorSelf_ = mutatorSelf;
1023 void
1024 Ast::CallExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1026 if( mutatorSelf_ != 0 )
1028 mutatorSelf_->analyze( this, env, freeStatesDst );
1030 if( funExpr_ != 0 )
1032 funExpr_->analyze( this, env, freeStatesDst );
1034 else
1036 const_cast< Lang::Function * >( constFun_.getPtr( ) )->analyze( this, env );
1038 argList_->analyze( this, env, freeStatesDst );
1040 if( funExpr_ != 0 )
1042 Ast::LexiographicVariable * var = dynamic_cast< Ast::LexiographicVariable * >( funExpr_ );
1043 if( var != 0 &&
1044 var->scope_level( ) == 0 )
1046 /* The callee is bound in the base environment. */
1047 if( strcmp( var->id( )->simpleId( ), Lang::TEX_SYNTAX_ID ) == 0 ) /* Assume there is only one namespace with a matching identifier to simplify the comparison. */
1049 /* Someone is calling TeX. If the argument is a string literal, it should be announced. */
1050 if( argList_->orderedExprs_ != 0 && ! argList_->orderedExprs_->empty( ) )
1052 /* If there are named arguments or more than one ordered argument, they are ignored; only the first ordered argument is checked. */
1053 Ast::Constant * carg = dynamic_cast< Ast::Constant * >( argList_->orderedExprs_->front( ) );
1054 if( carg != 0 )
1058 typedef const Lang::String ArgType;
1059 RefCountPtr< ArgType > strArg = carg->val( )->tryVal< ArgType >( );
1060 Kernel::theTeXLabelManager.announce( std::string( strArg->val_.getPtr( ) ), carg->loc( ) );
1062 catch( const NonLocalExit::NotThisType & ball )
1064 /* This is probably a type mismatch error, but we let the callee make the decision. */
1073 void
1074 Ast::CallExpr::eval( Kernel::EvalState * evalState ) const
1076 if( funExpr_ != 0 )
1078 evalState->expr_ = funExpr_;
1079 evalState->cont_ = Kernel::ContRef( new Kernel::CallCont_1( evalState->expr_->loc( ), argList_, curry_, mutatorSelf_ ? (mutatorSelf_->getHandle( evalState->env_, evalState->dyn_ )) : 0, *evalState, loc_ ) );
1081 else
1083 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_ ) );
1084 argList_->evaluate( constFun_->newCallContInfo( argList_, *evalState ),
1085 argList_->begin( ), Lang::THE_CONS_NULL,
1086 evalState );
1090 Kernel::UnionCont_last::UnionCont_last( const Ast::ArgListExprs * argList, const Kernel::ContRef & cont, const Ast::SourceLocation & callLoc )
1091 : Kernel::Continuation( callLoc ), argList_( argList ), cont_( cont )
1094 Kernel::UnionCont_last::~UnionCont_last( )
1097 void
1098 Kernel::UnionCont_last::takeValue( const RefCountPtr< const Lang::Value > & valsUntyped, Kernel::EvalState * evalState, bool dummy ) const
1100 typedef const Lang::SingleList ArgType;
1101 RefCountPtr< ArgType > vals = Helpers::down_cast< ArgType >( valsUntyped, "< Internal error situation in UnionCont_last >" );
1103 evalState->cont_ = cont_;
1104 cont_->takeValue( Kernel::ValueRef( new Lang::Structure( argList_, vals ) ),
1105 evalState );
1108 Kernel::ContRef
1109 Kernel::UnionCont_last::up( ) const
1111 return cont_;
1114 RefCountPtr< const char >
1115 Kernel::UnionCont_last::description( ) const
1117 return strrefdup( "union" );
1120 void
1121 Kernel::UnionCont_last::gcMark( Kernel::GCMarkedSet & marked )
1123 cont_->gcMark( marked );
1127 Ast::UnionExpr::UnionExpr( const Ast::SourceLocation & loc, Ast::ArgListExprs * argList )
1128 : Ast::Expression( loc ), argList_( argList )
1131 Ast::UnionExpr::~UnionExpr( )
1133 delete argList_;
1137 void
1138 Ast::UnionExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1140 argList_->analyze( this, env, freeStatesDst );
1143 void
1144 Ast::UnionExpr::eval( Kernel::EvalState * evalState ) const
1146 evalState->cont_ = Kernel::ContRef( new Kernel::UnionCont_last( argList_, evalState->cont_, loc_ ) );
1148 argList_->evaluate( RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList_, *evalState, false ) ),
1149 argList_->begin( ), Lang::THE_CONS_NULL,
1150 evalState );
1154 Kernel::SplitCont_1::SplitCont_1( const Ast::SourceLocation & traceLoc, Ast::Expression * argList, bool curry, const Kernel::EvalState & evalState, const Ast::SourceLocation & callLoc )
1155 : Kernel::Continuation( traceLoc ), argList_( argList ), curry_( curry ), env_( evalState.env_ ), dyn_( evalState.dyn_ ), cont_( evalState.cont_ ), callLoc_( callLoc )
1158 Kernel::SplitCont_1::~SplitCont_1( )
1161 void
1162 Kernel::SplitCont_1::takeValue( const RefCountPtr< const Lang::Value > & funUntyped, Kernel::EvalState * evalState, bool dummy ) const
1164 typedef const Lang::Function ArgType;
1165 RefCountPtr< ArgType > fun = Helpers::down_cast< ArgType >( funUntyped, "Split's function" );
1167 evalState->env_ = env_;
1168 evalState->dyn_ = dyn_;
1169 evalState->cont_ = Kernel::ContRef( new Kernel::SplitCont_2( fun, curry_, env_, dyn_, cont_, callLoc_ ) );
1170 evalState->expr_ = argList_;
1173 Kernel::ContRef
1174 Kernel::SplitCont_1::up( ) const
1176 return cont_;
1179 RefCountPtr< const char >
1180 Kernel::SplitCont_1::description() const
1182 return strrefdup( "split call's function" );
1185 void
1186 Kernel::SplitCont_1::gcMark( Kernel::GCMarkedSet & marked )
1188 dyn_->gcMark( marked );
1189 cont_->gcMark( marked );
1193 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 )
1194 : Kernel::Continuation( callLoc ), fun_( fun ), curry_( curry ), env_( env ), dyn_( dyn ), cont_( cont )
1197 Kernel::SplitCont_2::~SplitCont_2( )
1200 void
1201 Kernel::SplitCont_2::takeValue( const RefCountPtr< const Lang::Value > & valsUntyped, Kernel::EvalState * evalState, bool dummy ) const
1203 typedef const Lang::Structure ArgType;
1204 RefCountPtr< ArgType > structure = Helpers::down_cast< ArgType >( valsUntyped, "Split" );
1206 Kernel::Arguments args = fun_->newCurriedArguments( );
1207 structure->argList_->bind( & args, structure->values_, env_, dyn_ );
1209 if( curry_ )
1211 evalState->cont_ = cont_;
1212 cont_->takeValue( Kernel::ValueRef( new Lang::CuteFunction( fun_, args ) ),
1213 evalState );
1215 else
1217 evalState->dyn_ = dyn_;
1218 evalState->cont_ = cont_;
1219 fun_->call( evalState, args, traceLoc_ );
1223 Kernel::ContRef
1224 Kernel::SplitCont_2::up( ) const
1226 return cont_;
1229 RefCountPtr< const char >
1230 Kernel::SplitCont_2::description( ) const
1232 return strrefdup( "Split/splice" );
1235 void
1236 Kernel::SplitCont_2::gcMark( Kernel::GCMarkedSet & marked )
1238 cont_->gcMark( marked );
1242 Ast::CallSplitExpr::CallSplitExpr( const Ast::SourceLocation & loc, Ast::Expression * funExpr, Ast::Expression * argList, bool curry )
1243 : Ast::Expression( loc ), curry_( curry ), funExpr_( funExpr ), argList_( argList )
1246 Ast::CallSplitExpr::~CallSplitExpr( )
1248 delete funExpr_;
1249 delete argList_;
1253 void
1254 Ast::CallSplitExpr::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1256 funExpr_->analyze( this, env, freeStatesDst );
1257 argList_->analyze( this, env, freeStatesDst );
1260 void
1261 Ast::CallSplitExpr::eval( Kernel::EvalState * evalState ) const
1263 evalState->expr_ = funExpr_;
1264 evalState->cont_ = Kernel::ContRef( new Kernel::SplitCont_1( evalState->expr_->loc( ), argList_, curry_, *evalState, loc_ ) );
1268 Ast::DummyExpression::DummyExpression( )
1269 : Ast::Expression( Ast::THE_UNKNOWN_LOCATION )
1272 Ast::DummyExpression::DummyExpression( const Ast::SourceLocation & loc )
1273 : Ast::Expression( loc )
1276 Ast::DummyExpression::~DummyExpression( )
1279 void
1280 Ast::DummyExpression::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1282 /* Nothing to do! */
1285 void
1286 Ast::DummyExpression::eval( Kernel::EvalState * evalState ) const
1288 throw Exceptions::InternalError( strrefdup( "A DummyExpression must never be evaluated." ) );