1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008, 2014 Henrik Tidefelt
19 #include "Shapes_Helpers_decls.h"
22 #include "shapesexceptions.h"
23 #include "shapescore.h"
26 #include "continuations.h"
28 #include "astvalues.h"
29 #include "texlabelmanager.h"
33 using namespace Shapes
;
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
> ),
43 stateIdentifiers_( new Ast::IdentifierTree( NULL
, false ) ),
44 stateOrder_( new std::map
< const char *, size_t, charPtrLess
> )
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
> ),
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_
;
76 Kernel::Formals::setLoc( const Ast::SourceLocation
& loc
)
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. */
87 argumentOrder_
->insert( std::pair
< const char *, size_t >( id
.simpleId( ), pos
) );
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. */
97 stateOrder_
->insert( std::pair
< const char *, size_t >( id
.simpleId( ), pos
) );
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
)
109 args
->orderedExprs_
->push_back( *i
);
114 Kernel::EvaluatedFormals
*
115 Kernel::Formals::newEvaluatedFormals( Kernel::Arguments
& args
) const
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
)
135 res
->defaults_
.push_back( args
.getHandle( *pos
) );
136 res
->locations_
.push_back( args
.getNode( *pos
) );
141 res
->defaults_
.push_back( Kernel::THE_SLOT_VARIABLE
);
142 res
->locations_
.push_back( 0 ); // I really hope this is never dereferenced!
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
;
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
] ] );
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( );
201 while( curryPos
< curryArgs
.size( ) &&
202 ! curryArgs
.isSlot( curryPos
) )
207 for( size_t arg
= argList
->orderedExprs_
->size( ) - 1; ; --arg
)
209 (*res
)[ arg
] = *src
;
216 while( curryPos
< curryArgs
.size( ) &&
217 ! curryArgs
.isSlot( 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
] ] );
237 const Ast::SourceLocation
&
238 Kernel::Formals::loc( ) const
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
> )
259 // throw Exceptions::InternalError( strrefdup( "Ast::ArgListExprs( bool _exprOwner ) can only be called with false." ) );
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( )
272 typedef list
< Ast::Expression
* >::iterator I
;
273 for( I i
= orderedExprs_
->begin( ); i
!= orderedExprs_
->end( ); ++i
)
278 delete orderedExprs_
;
284 typedef std::map
< const char *, Ast::Expression
*, charPtrLess
>::const_iterator I
;
285 for( I i
= namedExprs_
->begin( ); i
!= namedExprs_
->end( ); ++i
)
297 typedef std::list
< Ast::StateReference
* >::iterator I
;
298 for( I i
= orderedStates_
->begin( ); i
!= orderedStates_
->end( ); ++i
)
303 delete orderedStates_
;
309 typedef std::map
< const char *, Ast::StateReference
*, charPtrLess
>::const_iterator I
;
310 for( I i
= namedStates_
->begin( ); i
!= namedStates_
->end( ); ++i
)
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
);
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
);
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_
;
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( ),
359 Ast::ArgListExprs::ConstIterator( next
, pos
.i2_
, pos
.index_
+ 1 ),
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_
;
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_
) ) ),
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. */
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_
;
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( ),
391 Ast::ArgListExprs::ConstIterator( pos
.i1_
, next
, pos
.index_
+ 1 ),
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_
;
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
) ) ),
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. */
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
);
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
);
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 )
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.
529 RefCountPtr
< ConsType
> lst
= vals
.down_cast
< ConsType
>( );
530 if( lst
== NullPtr
< ConsType
>( ) )
542 throw Exceptions::NonExistentPosition( pos
, i
- 1 );
546 Ast::ArgListExprs::analyze( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
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
) );
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
);
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
);
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( )
648 Ast::FunctionFunction::push_exprs( Ast::ArgListExprs
* args
) const
650 formals_
->push_exprs( args
);
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
);
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_
) ),
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( )
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_
);
698 evalState
->cont_
= cont_
;
699 cont_
->takeValue( Kernel::ValueRef( new Lang::CuteFunction( fun_
, args
) ), evalState
);
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_
);
711 Kernel::CallCont_last::up( ) const
716 RefCountPtr
< const char >
717 Kernel::CallCont_last::description( ) const
719 return strrefdup( "function call's application" );
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( )
747 Kernel::CallContInfo::force( const size_t & pos
) const
751 return (*forcePos_
)[ pos
];
757 Kernel::CallContInfo::isSelective( ) const
759 return forcePos_
!= 0;
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( )
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
);
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_
,
799 RefCountPtr
< const Lang::SingleListPair
>( new Lang::SingleListPair( val
, vals_
) ),
804 Kernel::CallCont_n::up( ) const
809 RefCountPtr
< const char >
810 Kernel::CallCont_n::description( ) const
812 return strrefdup( "function call's argument" );
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( )
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
,
848 typedef const Lang::Transform2D ArgType
;
849 ArgType
* transformVal
= dynamic_cast< ArgType
* >( funUntyped
.getPtr( ) );
850 if( transformVal
!= 0 )
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_
) );
872 typedef const Lang::Transform3D ArgType
;
873 ArgType
* transformVal
= dynamic_cast< ArgType
* >( funUntyped
.getPtr( ) );
874 if( transformVal
!= 0 )
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_
) );
897 typedef const Lang::ElementaryPath2D ArgType
;
898 RefCountPtr
< ArgType
> path
= NullPtr
< ArgType
>( );
901 path
= Helpers::elementaryPathCast2D( funUntyped
, this );
903 catch( const Exceptions::ContinuationTypeMismatch
& ball
)
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
,
932 typedef const Lang::ElementaryPath3D ArgType
;
933 RefCountPtr
< ArgType
> path
= NullPtr
< ArgType
>( );
936 path
= Helpers::elementaryPathCast3D( funUntyped
, this );
938 catch( const Exceptions::ContinuationTypeMismatch
& ball
)
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
,
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( ) ) );
976 Kernel::CallCont_1::up( ) const
981 RefCountPtr
< const char >
982 Kernel::CallCont_1::description( ) const
984 return strrefdup( "function call's function" );
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( )
1010 if( mutatorSelf_
!= 0 )
1012 delete mutatorSelf_
;
1018 Ast::CallExpr::setMutatorSelf( Ast::StateReference
* mutatorSelf
)
1020 mutatorSelf_
= mutatorSelf
;
1024 Ast::CallExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1026 if( mutatorSelf_
!= 0 )
1028 mutatorSelf_
->analyze( this, env
, freeStatesDst
);
1032 funExpr_
->analyze( this, env
, freeStatesDst
);
1036 const_cast< Lang::Function
* >( constFun_
.getPtr( ) )->analyze( this, env
);
1038 argList_
->analyze( this, env
, freeStatesDst
);
1042 Ast::LexiographicVariable
* var
= dynamic_cast< Ast::LexiographicVariable
* >( funExpr_
);
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( ) );
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. */
1074 Ast::CallExpr::eval( Kernel::EvalState
* evalState
) const
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_
) );
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
,
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( )
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
) ),
1109 Kernel::UnionCont_last::up( ) const
1114 RefCountPtr
< const char >
1115 Kernel::UnionCont_last::description( ) const
1117 return strrefdup( "union" );
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( )
1138 Ast::UnionExpr::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1140 argList_
->analyze( this, env
, freeStatesDst
);
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
,
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( )
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_
;
1174 Kernel::SplitCont_1::up( ) const
1179 RefCountPtr
< const char >
1180 Kernel::SplitCont_1::description() const
1182 return strrefdup( "split call's function" );
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( )
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_
);
1211 evalState
->cont_
= cont_
;
1212 cont_
->takeValue( Kernel::ValueRef( new Lang::CuteFunction( fun_
, args
) ),
1217 evalState
->dyn_
= dyn_
;
1218 evalState
->cont_
= cont_
;
1219 fun_
->call( evalState
, args
, traceLoc_
);
1224 Kernel::SplitCont_2::up( ) const
1229 RefCountPtr
< const char >
1230 Kernel::SplitCont_2::description( ) const
1232 return strrefdup( "Split/splice" );
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( )
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
);
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( )
1280 Ast::DummyExpression::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1282 /* Nothing to do! */
1286 Ast::DummyExpression::eval( Kernel::EvalState
* evalState
) const
1288 throw Exceptions::InternalError( strrefdup( "A DummyExpression must never be evaluated." ) );