1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include "Shapes_Helpers_decls.h"
22 #include "shapesexceptions.h"
23 #include "shapescore.h"
26 #include "continuations.h"
31 using namespace Shapes
;
35 Kernel::Formals::Formals( )
36 : loc_( Ast::THE_UNKNOWN_LOCATION
),
37 seenDefault_( false ), argumentOrder_( new std::map
< const char *, size_t, charPtrLess
> ),
39 stateOrder_( new std::map
< const char *, size_t, charPtrLess
> )
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
> ),
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_
;
66 Kernel::Formals::setLoc( Ast::SourceLocation loc
)
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
)
80 args
->orderedExprs_
->push_back( *i
);
85 Kernel::EvaluatedFormals
*
86 Kernel::Formals::newEvaluatedFormals( Kernel::Arguments
& args
) const
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
)
106 res
->defaults_
.push_back( args
.getHandle( *pos
) );
107 res
->locations_
.push_back( args
.getNode( *pos
) );
112 res
->defaults_
.push_back( Kernel::THE_SLOT_VARIABLE
);
113 res
->locations_
.push_back( 0 ); // I really hope this is never dereferenced!
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
;
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
] ] );
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( );
172 while( curryPos
< curryArgs
.size( ) &&
173 ! curryArgs
.isSlot( curryPos
) )
178 for( size_t arg
= argList
->orderedExprs_
->size( ) - 1; ; --arg
)
180 (*res
)[ arg
] = *src
;
187 while( curryPos
< curryArgs
.size( ) &&
188 ! curryArgs
.isSlot( 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
] ] );
208 const Ast::SourceLocation
&
209 Kernel::Formals::loc( ) const
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
> )
230 // throw Exceptions::InternalError( strrefdup( "Ast::ArgListExprs( bool _exprOwner ) can only be called with false." ) );
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( )
243 typedef list
< Ast::Expression
* >::iterator I
;
244 for( I i
= orderedExprs_
->begin( ); i
!= orderedExprs_
->end( ); ++i
)
249 delete orderedExprs_
;
255 typedef std::map
< const char *, Ast::Expression
*, charPtrLess
>::const_iterator I
;
256 for( I i
= namedExprs_
->begin( ); i
!= namedExprs_
->end( ); ++i
)
268 typedef std::list
< Ast::StateReference
* >::iterator I
;
269 for( I i
= orderedStates_
->begin( ); i
!= orderedStates_
->end( ); ++i
)
274 delete orderedStates_
;
280 typedef std::map
< const char *, Ast::StateReference
*, charPtrLess
>::const_iterator I
;
281 for( I i
= namedStates_
->begin( ); i
!= namedStates_
->end( ); ++i
)
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
);
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
);
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_
;
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( ),
330 Ast::ArgListExprs::ConstIterator( next
, pos
.i2_
, pos
.index_
+ 1 ),
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_
;
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_
) ) ),
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. */
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_
;
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( ),
362 Ast::ArgListExprs::ConstIterator( pos
.i1_
, next
, pos
.index_
+ 1 ),
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_
;
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
) ) ),
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. */
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
);
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
);
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 )
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.
499 typedef list
< Ast::Expression
* >::const_iterator I
;
502 RefCountPtr
< ConsType
> lst
= vals
.down_cast
< ConsType
>( );
503 if( lst
== NullPtr
< ConsType
>( ) )
516 throw Exceptions::NonExistentPosition( pos
, i
- 1 );
520 Ast::ArgListExprs::analyze( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
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
) );
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
);
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
);
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( )
622 Ast::FunctionFunction::push_exprs( Ast::ArgListExprs
* args
) const
624 formals_
->push_exprs( args
);
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
);
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_
) ),
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( )
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_
);
672 evalState
->cont_
= cont_
;
673 cont_
->takeValue( Kernel::ValueRef( new Lang::CuteFunction( fun_
, args
) ), evalState
);
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_
);
685 Kernel::CallCont_last::up( ) const
690 RefCountPtr
< const char >
691 Kernel::CallCont_last::description( ) const
693 return strrefdup( "function call's application" );
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( )
721 Kernel::CallContInfo::force( const size_t & pos
) const
725 return (*forcePos_
)[ pos
];
731 Kernel::CallContInfo::isSelective( ) const
733 return forcePos_
!= 0;
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( )
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
);
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_
,
773 RefCountPtr
< const Lang::SingleListPair
>( new Lang::SingleListPair( val
, vals_
) ),
778 Kernel::CallCont_n::up( ) const
783 RefCountPtr
< const char >
784 Kernel::CallCont_n::description( ) const
786 return strrefdup( "function call's argument" );
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( )
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
,
822 typedef const Lang::Transform2D ArgType
;
823 ArgType
* transformVal
= dynamic_cast< ArgType
* >( funUntyped
.getPtr( ) );
824 if( transformVal
!= 0 )
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_
) );
846 typedef const Lang::Transform3D ArgType
;
847 ArgType
* transformVal
= dynamic_cast< ArgType
* >( funUntyped
.getPtr( ) );
848 if( transformVal
!= 0 )
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_
) );
871 typedef const Lang::ElementaryPath2D ArgType
;
872 RefCountPtr
< ArgType
> path
= NullPtr
< ArgType
>( );
875 path
= Helpers::elementaryPathCast2D( funUntyped
, this );
877 catch( const Exceptions::ContinuationTypeMismatch
& ball
)
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
,
906 typedef const Lang::ElementaryPath3D ArgType
;
907 RefCountPtr
< ArgType
> path
= NullPtr
< ArgType
>( );
910 path
= Helpers::elementaryPathCast3D( funUntyped
, this );
912 catch( const Exceptions::ContinuationTypeMismatch
& ball
)
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
,
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( ) ) );
950 Kernel::CallCont_1::up( ) const
955 RefCountPtr
< const char >
956 Kernel::CallCont_1::description( ) const
958 return strrefdup( "function call's function" );
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( )
984 if( mutatorSelf_
!= 0 )
992 Ast::CallExpr::setMutatorSelf( Ast::StateReference
* mutatorSelf
)
994 mutatorSelf_
= mutatorSelf
;
998 Ast::CallExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1000 if( mutatorSelf_
!= 0 )
1002 mutatorSelf_
->analyze( this, env
, freeStatesDst
);
1006 funExpr_
->analyze( this, env
, freeStatesDst
);
1010 const_cast< Lang::Function
* >( constFun_
.getPtr( ) )->analyze( this, env
);
1012 argList_
->analyze( this, env
, freeStatesDst
);
1016 Ast::CallExpr::eval( Kernel::EvalState
* evalState
) const
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_
) );
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
,
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( )
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
) ),
1051 Kernel::UnionCont_last::up( ) const
1056 RefCountPtr
< const char >
1057 Kernel::UnionCont_last::description( ) const
1059 return strrefdup( "union" );
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( )
1080 Ast::UnionExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1082 argList_
->analyze( this, env
, freeStatesDst
);
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
,
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( )
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_
;
1116 Kernel::SplitCont_1::up( ) const
1121 RefCountPtr
< const char >
1122 Kernel::SplitCont_1::description() const
1124 return strrefdup( "split call's function" );
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( )
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_
);
1153 evalState
->cont_
= cont_
;
1154 cont_
->takeValue( Kernel::ValueRef( new Lang::CuteFunction( fun_
, args
) ),
1159 evalState
->dyn_
= dyn_
;
1160 evalState
->cont_
= cont_
;
1161 fun_
->call( evalState
, args
, traceLoc_
);
1166 Kernel::SplitCont_2::up( ) const
1171 RefCountPtr
< const char >
1172 Kernel::SplitCont_2::description( ) const
1174 return strrefdup( "Split/splice" );
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( )
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
);
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( )
1222 Ast::DummyExpression::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1224 /* Nothing to do! */
1228 Ast::DummyExpression::eval( Kernel::EvalState
* evalState
) const
1230 throw Exceptions::InternalError( strrefdup( "A DummyExpression must never be evaluated." ) );