Introducing mutators.
[shapes.git] / source / functiontypes.cc
blob8a243a575c30abde6661e75df42f80d724246a02
1 #include <cmath>
3 #include "shapestypes.h"
4 #include "shapesexceptions.h"
5 #include "astexpr.h"
6 #include "consts.h"
7 #include "angleselect.h"
8 #include "astvar.h"
9 #include "astclass.h"
10 #include "globals.h"
11 #include "continuations.h"
12 #include "check.h"
14 //#include "clapack.h"
15 //#include "cblas.h"
16 #include <gsl/gsl_matrix.h>
17 #include <gsl/gsl_linalg.h>
18 #include <gsl/gsl_blas.h>
19 #include <ctype.h>
20 #include <stack>
22 using namespace Shapes;
23 using namespace std;
25 void displayArray( std::ostream & os, const double * pr, size_t m, size_t n )
27 size_t r;
28 size_t c;
29 char buf[20];
30 for( r = 0; r < m; ++r )
32 for( c = 0; c < n; ++c )
34 sprintf( buf, "%14.5e", *( pr + ( r + c * m ) ) );
35 os << buf ;
37 os << std::endl ;
41 void displayArray( std::ostream & os, const gsl_matrix * m )
43 char buf[20];
44 for( size_t r = 0; r < m->size1; ++r )
46 for( size_t c = 0; c < m->size2; ++c )
48 sprintf( buf, "%14.5e", gsl_matrix_get( m, r, c ) );
49 os << buf ;
51 os << std::endl ;
56 Lang::Transform2D::Transform2D( double xx, double yx, double xy, double yy, Concrete::Length xt, Concrete::Length yt )
57 : xx_( xx ), yx_( yx ), xy_( xy ), yy_( yy ), xt_( xt ), yt_( yt )
58 { }
60 Lang::Transform2D::Transform2D( const Lang::Transform2D & tf2, const Lang::Transform2D & tf1 )
61 : xx_( tf2.xx_ * tf1.xx_ + tf2.xy_ * tf1.yx_ ),
62 yx_( tf2.yx_ * tf1.xx_ + tf2.yy_ * tf1.yx_ ),
63 xy_( tf2.xx_ * tf1.xy_ + tf2.xy_ * tf1.yy_ ),
64 yy_( tf2.yx_ * tf1.xy_ + tf2.yy_ * tf1.yy_ ),
65 xt_( tf2.xx_ * tf1.xt_ + tf2.xy_ * tf1.yt_ + tf2.xt_ ),
66 yt_( tf2.yx_ * tf1.xt_ + tf2.yy_ * tf1.yt_ + tf2.yt_ )
67 { }
69 DISPATCHIMPL( Transform2D );
71 bool
72 Lang::Transform2D::isIdentity( ) const
74 return
75 xt_ == Concrete::ZERO_LENGTH && yt_ == Concrete::ZERO_LENGTH &&
76 xx_ == 1 && yy_ == 1 &&
77 xy_ == 0 && yx_ == 0;
80 bool
81 Lang::Transform2D::isTranslation( ) const
83 return
84 xx_ == 1 && yy_ == 1 &&
85 xy_ == 0 && yx_ == 0;
88 void
89 Lang::Transform2D::shipout( std::ostream & os ) const
91 os << xx_ << " " << yx_ << " " << xy_ << " " << yy_ << " "
92 << Concrete::Length::offtype( xt_ ) << " " << Concrete::Length::offtype( yt_ ) ;
95 // to be used by text moveto commands
96 void
97 Lang::Transform2D::replaceBy( const Lang::Transform2D & newtf )
99 xx_ = newtf.xx_;
100 yx_ = newtf.yx_;
101 xy_ = newtf.xy_;
102 yy_ = newtf.yy_;
103 xt_ = newtf.xt_;
104 yt_ = newtf.yt_;
107 // to be used by text newline commands
108 void
109 Lang::Transform2D::prependShift( const Concrete::Coords2D & d )
111 // Think of d as tf1 when composing transforms.
113 xt_ += xx_ * d.x_ + xy_ * d.y_;
114 yt_ += yx_ * d.x_ + yy_ * d.y_;
117 // to be used by text painting commands
118 void
119 Lang::Transform2D::prependXShift( const Concrete::Length & dx )
121 // Think of d as tf1 when composing transforms.
123 xt_ += xx_ * dx;
124 yt_ += yx_ * dx;
127 RefCountPtr< const Lang::Class > Lang::Transform2D::TypeID( new Lang::SystemFinalClass( strrefdup( "Transform2D" ) ) );
128 TYPEINFOIMPL( Transform2D );
130 void
131 Lang::Transform2D::show( std::ostream & os ) const
133 os << "[ ("
134 << xx_ << ", " << yx_ << ") ("
135 << xy_ << ", " << yy_ << ") ("
136 << Lang::Length( xt_ ) << ", " << Lang::Length( yt_ ) << ") ]" ;
140 Lang::Transform3D::Transform3D( double xx, double yx, double zx, double xy, double yy, double zy, double xz, double yz, double zz, Concrete::Length xt, Concrete::Length yt, Concrete::Length zt )
141 : planeNormalTransformData_( 0 ),
142 xx_( xx ), yx_( yx ), zx_( zx ), xy_( xy ), yy_( yy ), zy_( zy ), xz_( xz ), yz_( yz ), zz_( zz ), xt_( xt ), yt_( yt ), zt_( zt )
145 Lang::Transform3D::Transform3D( const Lang::Transform3D & tf2, const Lang::Transform3D & tf1 )
146 : planeNormalTransformData_( 0 ),
147 xx_( tf2.xx_ * tf1.xx_ + tf2.xy_ * tf1.yx_ + tf2.xz_ * tf1.zx_ ),
148 yx_( tf2.yx_ * tf1.xx_ + tf2.yy_ * tf1.yx_ + tf2.yz_ * tf1.zx_ ),
149 zx_( tf2.zx_ * tf1.xx_ + tf2.zy_ * tf1.yx_ + tf2.zz_ * tf1.zx_ ),
150 xy_( tf2.xx_ * tf1.xy_ + tf2.xy_ * tf1.yy_ + tf2.xz_ * tf1.zy_ ),
151 yy_( tf2.yx_ * tf1.xy_ + tf2.yy_ * tf1.yy_ + tf2.yz_ * tf1.zy_ ),
152 zy_( tf2.zx_ * tf1.xy_ + tf2.zy_ * tf1.yy_ + tf2.zz_ * tf1.zy_ ),
153 xz_( tf2.xx_ * tf1.xz_ + tf2.xy_ * tf1.yz_ + tf2.xz_ * tf1.zz_ ),
154 yz_( tf2.yx_ * tf1.xz_ + tf2.yy_ * tf1.yz_ + tf2.yz_ * tf1.zz_ ),
155 zz_( tf2.zx_ * tf1.xz_ + tf2.zy_ * tf1.yz_ + tf2.zz_ * tf1.zz_ ),
156 xt_( tf2.xx_ * tf1.xt_ + tf2.xy_ * tf1.yt_ + tf2.xz_ * tf1.zt_ + tf2.xt_ ),
157 yt_( tf2.yx_ * tf1.xt_ + tf2.yy_ * tf1.yt_ + tf2.yz_ * tf1.zt_ + tf2.yt_ ),
158 zt_( tf2.zx_ * tf1.xt_ + tf2.zy_ * tf1.yt_ + tf2.zz_ * tf1.zt_ + tf2.zt_ )
161 DISPATCHIMPL( Transform3D );
163 Lang::Transform3D::~Transform3D( )
165 if( planeNormalTransformData_ != 0 )
167 gsl_matrix_free( planeNormalTransformData_ );
168 // delete planeNormalTransformData_;
172 bool
173 Lang::Transform3D::isIdentity( ) const
175 return
176 xt_ == Concrete::ZERO_LENGTH && yt_ == Concrete::ZERO_LENGTH && zt_ == Concrete::ZERO_LENGTH &&
177 xx_ == 1 && yy_ == 1 && zz_ == 1 &&
178 xy_ == 0 && xz_ == 0 && yx_ == 0 && yz_ == 0 && zx_ == 0 && zy_ == 0;
181 Concrete::UnitFloatTriple
182 Lang::Transform3D::transformPlaneUnitNormal( const Concrete::UnitFloatTriple & n ) const
184 const int N = 3;
185 // These statically allocated matrices will leak memory. They could be removed by using a static automaitc
186 // deallocator object. However, since they shall not be deleted by delete (but by gsl_matrix_free), we cannot
187 // us RefCountPtr< gsl_matrix >.
188 static gsl_matrix * a = gsl_matrix_alloc( N, N );
189 static gsl_matrix * v = gsl_matrix_alloc( N, N );
190 static gsl_vector * s = gsl_vector_alloc( N );
191 static gsl_vector * work = gsl_vector_alloc( N );
194 // static __CLPK_integer mn = N;
195 // static char jobuvt = 'A';
197 // static double a[ N * N ];
198 // static double u[ N * N ];
199 // static double vt[ N * N ];
200 // __CLPK_integer ldauvt = N;
201 // static double s[ N ];
202 // __CLPK_integer lwork;
203 // __CLPK_integer info;
205 // static __CLPK_doublereal * work = 0;
206 // static RefCountPtr< __CLPK_doublereal > workCleaner;
208 // if( work == 0 )
209 // {
210 // // Then we ask LAPACK how much workspace it wants, and then we assume that this number will not change
211 // // as we call DGESVD with other arguments.
213 // double tmpwork;
214 // lwork = -1;
215 // dgesvd_( & jobuvt, & jobuvt,
216 // & mn, & mn,
217 // reinterpret_cast< __CLPK_doublereal * >( & a ), & ldauvt,
218 // reinterpret_cast< __CLPK_doublereal * >( & s ),
219 // reinterpret_cast< __CLPK_doublereal * >( & u ), & ldauvt,
220 // reinterpret_cast< __CLPK_doublereal * >( & vt ), & ldauvt,
221 // reinterpret_cast< __CLPK_doublereal * >( & tmpwork ), & lwork,
222 // & info );
223 // lwork = static_cast< __CLPK_integer >( tmpwork );
224 // work = new __CLPK_doublereal[ lwork ];
225 // workCleaner = RefCountPtr< __CLPK_doublereal >( work );
226 // }
229 if( planeNormalTransformData_ == 0 )
231 // This is the first time this transform is used to transform a unit plane normal.
232 // The linear part of this transform must then be computed, and we use the singular
233 // value decomposition for this.
235 planeNormalTransformData_ = gsl_matrix_alloc( N, N );
237 gsl_matrix_set( a, 0, 0, xx_ );
238 gsl_matrix_set( a, 1, 0, yx_ );
239 gsl_matrix_set( a, 2, 0, zx_ );
240 gsl_matrix_set( a, 0, 1, xy_ );
241 gsl_matrix_set( a, 1, 1, yy_ );
242 gsl_matrix_set( a, 2, 1, zy_ );
243 gsl_matrix_set( a, 0, 2, xz_ );
244 gsl_matrix_set( a, 1, 2, yz_ );
245 gsl_matrix_set( a, 2, 2, zz_ );
247 // std::cerr << "Here's a:" << std::endl ;
248 // displayArray( std::cerr, a );
251 int status = gsl_linalg_SV_decomp( a, v, s, work );
252 if( status != 0 )
254 throw Exceptions::ExternalError( "Gnu Scientific Library SVD routine failed." );
258 // a[ 0 ] = xx_;
259 // a[ 1 ] = yx_;
260 // a[ 2 ] = zx_;
261 // a[ 3 ] = xy_;
262 // a[ 4 ] = yy_;
263 // a[ 5 ] = zy_;
264 // a[ 6 ] = xz_;
265 // a[ 7 ] = yz_;
266 // a[ 8 ] = zz_;
268 // dgesvd_( & jobuvt, & jobuvt,
269 // & mn, & mn,
270 // reinterpret_cast< __CLPK_doublereal * >( & a ), & ldauvt,
271 // reinterpret_cast< __CLPK_doublereal * >( & s ),
272 // reinterpret_cast< __CLPK_doublereal * >( & u ), & ldauvt,
273 // reinterpret_cast< __CLPK_doublereal * >( & vt ), & ldauvt,
274 // reinterpret_cast< __CLPK_doublereal * >( work ), & lwork,
275 // & info );
277 // if( info != 0 )
278 // {
279 // throw Exceptions::ExternalError( "LAPACK routine DGESVD failed." );
280 // }
282 if( gsl_vector_get( s, 1 ) < 1e-5 )
284 throw Exceptions::AffineTransformKillsPlane( gsl_vector_get( s, 1 ) );
287 // std::cerr << "Here's s:" << std::endl ;
288 // gsl_vector_fprintf( stderr, s, "%f" );
290 gsl_vector_set( s, 0, gsl_vector_get( s, 2 ) / gsl_vector_get( s, 0 ) );
291 gsl_vector_set( s, 1, gsl_vector_get( s, 2 ) / gsl_vector_get( s, 1 ) );
292 // s[ 2 ] = 1;
294 // std::cerr << "Here's the modified s:" << std::endl ;
295 // gsl_vector_fprintf( stderr, s, "%f" );
298 // if( s[ 1 ] < 1e-5 )
299 // {
300 // throw Exceptions::AffineTransformKillsPlane( s[ 1 ] );
301 // }
303 // s[ 0 ] = s[ 2 ] / s[ 0 ];
304 // s[ 1 ] = s[ 2 ] / s[ 1 ];
305 // // s[ 2 ] = 1;
307 // We will now compute " u * diag( s ) * vt ".
309 // Note that "u" is stored in a when gsl_linalg_SV_decomp is used.
311 // std::cerr << "Here's u:" << std::endl ;
312 // displayArray( std::cerr, a );
314 gsl_matrix_set( a, 0, 0, gsl_matrix_get( a, 0, 0 ) * gsl_vector_get( s, 0 ) );
315 gsl_matrix_set( a, 1, 0, gsl_matrix_get( a, 1, 0 ) * gsl_vector_get( s, 0 ) );
316 gsl_matrix_set( a, 2, 0, gsl_matrix_get( a, 2, 0 ) * gsl_vector_get( s, 0 ) );
317 gsl_matrix_set( a, 0, 1, gsl_matrix_get( a, 0, 1 ) * gsl_vector_get( s, 1 ) );
318 gsl_matrix_set( a, 1, 1, gsl_matrix_get( a, 1, 1 ) * gsl_vector_get( s, 1 ) );
319 gsl_matrix_set( a, 2, 1, gsl_matrix_get( a, 2, 1 ) * gsl_vector_get( s, 1 ) );
320 // Note that s[ 2 ] == 1
322 // u[ 0 ] *= s[ 0 ];
323 // u[ 1 ] *= s[ 0 ];
324 // u[ 2 ] *= s[ 0 ];
325 // u[ 3 ] *= s[ 1 ];
326 // u[ 4 ] *= s[ 1 ];
327 // u[ 5 ] *= s[ 1 ];
328 // // Note that s[ 2 ] == 1
330 // std::cerr << "Here's the modified a:" << std::endl ;
331 // displayArray( std::cerr, a );
333 // std::cerr << "Here's v:" << std::endl ;
334 // displayArray( std::cerr, v );
336 gsl_blas_dgemm( CblasNoTrans,
337 CblasTrans,
342 planeNormalTransformData_ );
344 // std::cerr << "Here's the matrix:" << std::endl ;
345 // displayArray( std::cerr, planeNormalTransformData_ );
347 // cblas_dgemm( CblasColMajor, CblasNoTrans, CblasNoTrans,
348 // N, N, N,
349 // 1.,
350 // u, N,
351 // vt, N,
352 // 0., planeNormalTransformData_, N );
355 // Now that the linear, not too singular, transform has been computed, we just apply it and normalize the result.
356 // The normalization is made by the UnitFloatTriple constructor.
358 static gsl_vector * _n = gsl_vector_alloc( N );
359 static gsl_vector * res = gsl_vector_alloc( N );
361 // static double _n[ N ];
362 // static double res[ N ];
364 gsl_vector_set( _n, 0, n.x_ );
365 gsl_vector_set( _n, 1, n.y_ );
366 gsl_vector_set( _n, 2, n.z_ );
368 // _n[ 0 ] = n.x_;
369 // _n[ 1 ] = n.y_;
370 // _n[ 2 ] = n.z_;
372 // std::cerr << "Input vector: " << std::endl ;
373 // gsl_vector_fprintf( stderr, _n, "%f" );
374 // std::cerr << std::endl ;
376 gsl_blas_dgemv( CblasNoTrans,
378 planeNormalTransformData_,
381 res );
383 // std::cerr << "Result: " << std::endl ;
384 // gsl_vector_fprintf( stderr, res, "%f" );
385 // std::cerr << std::endl ;
387 // cblas_dgemv( CblasColMajor, CblasNoTrans,
388 // N, N,
389 // 1.,
390 // planeNormalTransformData_, N,
391 // reinterpret_cast< double * >( & _n ), 1,
392 // 0., reinterpret_cast< double * >( & res ), 1 );
394 return Concrete::UnitFloatTriple( gsl_vector_get( res, 0 ),
395 gsl_vector_get( res, 1 ),
396 gsl_vector_get( res, 2 ) );
397 // return Concrete::UnitFloatTriple( res[0], res[1], res[2] );
401 // First we compute a unit vector in the plane
402 static const Concrete::UnitFloatTriple xHat( 1, 0, 0 );
403 static const Concrete::UnitFloatTriple yHat( 0, 1, 0 );
404 Concrete::UnitFloatTriple r1 = Shapes::cross( unitNormal_, xHat );
405 Concrete::UnitFloatTriple r2 = Shapes::cross( unitNormal_, yHat );
406 Concrete::UnitFloatTriple r( 0, 0, 0 );
407 if( r1.norm( ) > r2.norm( ) )
409 r = r1.normalized( );
411 else
413 r = r2.normalized( );
416 // Then we find one point that is in the plane
417 double ax = fabs( unitNormal_.x_ );
418 double ay = fabs( unitNormal_.y_ );
419 double az = fabs( unitNormal_.z_ );
421 Concrete::Coords3D x0( 0, 0, 0 );
422 if( ax >= ay && ax >= az )
424 x0 = Concrete::Coords3D( m_ / unitNormal_.x_, 0, 0 );
426 else if( ay >= az )
428 x0 = Concrete::Coords3D( 0, m_ / unitNormal_.y_, 0 );
430 else
432 x0 = Concrete::Coords3D( 0, 0, m_ / unitNormal_.z_ );
435 // Now it is easy to find two more points that span the plane together with x0
436 Concrete::Coords3D x1 = x0 + r;
437 Concrete::Coords3D x2 = x0 + Shapes::cross( unitNormal_, r );
439 // Now we see where these points go...
440 Concrete::Coords3D Tx0 = x0.transformed( tf );
441 Concrete::Coords3D Tx1 = x1.transformed( tf );
442 Concrete::Coords3D Tx2 = x2.transformed( tf );
444 // ... from which the new equation may be computed.
445 Concrete::UnitFloatTriple Tnormal = Shapes::cross( Tx1 - Tx0, Tx2 - Tx0 );
446 double TnormalNorm = Tnormal.norm( );
447 if( TnormalNorm == 0 )
449 // A polygon of lower dimension is invisible, so we may just return without pushing any triangles.
450 return;
452 Concrete::UnitFloatTriple TunitNormal = Tnormal * ( 1 / TnormalNorm );
456 RefCountPtr< const Lang::Class > Lang::Transform3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Transform3D" ) ) );
457 TYPEINFOIMPL( Transform3D );
459 void
460 Lang::Transform3D::show( std::ostream & os ) const
462 os << "[ ("
463 << xx_ << ", " << yx_ << ", " << zx_ << ") ("
464 << xy_ << ", " << yy_ << ", " << zy_ << ") ("
465 << xz_ << ", " << yz_ << ", " << zz_ << ") ("
466 << Lang::Length( xt_ ) << ", " << Lang::Length( yt_ ) << ", " << Lang::Length( zt_ ) << ") ]" ;
470 Kernel::Arguments::Arguments( const Kernel::EvaluatedFormals * formals )
471 : formals_( formals ), variables_( new Environment::ValueVector::ValueType ), dst_( 0 ),
472 hasSink_( formals_->formals_->hasSink( ) ),
473 dstEnd_( formals_->formals_->defaultExprs_.size( ) ),
474 isSink_( formals_->isSink_ ),
475 sinkArgList_( 0 ), sinkValues_( NullPtr< const Lang::SingleList >( ) ),
476 states_( new Environment::StateVector::ValueType ), stateDst_( 0 ),
477 mutatorSelf_( 0 )
479 if( hasSink_ )
481 sinkArgList_ = new Ast::ArgListExprs( false ); // This is not an expression-owner.
482 sinkValues_ = RefCountPtr< const Lang::SingleList >( new Lang::SingleListNull( ) );
483 if( formals_->formals_->argumentOrder_->empty( ) )
485 // All arguments go in the sink.
486 dst_ = INT_MAX;
489 // Thinking of all the evaluated cuts, it actually makes some sense not to reserve memory here.
490 // variables_.reserve( formals_->argumentOrder_->size( ) );
491 // states_.reserve( formals_->stateOrder_->size( ) );
494 Kernel::Arguments::~Arguments( )
497 Kernel::Arguments
498 Kernel::Arguments::clone( ) const
500 CHECK(
501 if( ! states_->empty( ) )
503 throw Exceptions::InternalError( "Arguments with states may not be cloned." );
507 Kernel::Arguments res( formals_ );
509 res.variables_->reserve( variables_->size( ) );
511 typedef typeof *variables_ ListType;
512 for( ListType::const_iterator i = variables_->begin( ); i != variables_->end( ); ++i )
514 res.variables_->push_back( *i );
517 res.locations_ = locations_;
518 res.dst_ = dst_;
519 if( sinkArgList_ != 0 )
521 throw Exceptions::NotImplemented( "Cloning of arguments with sink." );
522 //res.sinkArgList_ = sinkArgList_->clone( );
523 res.sinkValues_ = sinkValues_;
526 return res;
530 void
531 Kernel::Arguments::addOrderedArgument( const Kernel::VariableHandle & arg, Ast::Expression * loc )
533 /* Recall that if there's a sink, this will be the last argument.
535 if( ! isSink_ &&
536 dst_ >= dstEnd_ )
538 /* If there is a sink, put it there. Otherwise, we have detected an arity mismatch, but to generate a good
539 * error message we don't throw the message from here, but rest assured that an error will be delivered in
540 * due time when applyDefaults is invoked.
542 if( hasSink_ )
544 sinkArgList_->orderedExprs_->push_back( loc );
545 sinkValues_ = RefCountPtr< Lang::SingleList >( new Lang::SingleListPair( arg, sinkValues_ ) );
547 else
549 variables_->push_back( arg );
550 locations_.push_back( loc );
551 ++dst_; // I'm not sure this is meaningful here...
554 else if( dst_ == variables_->size( ) )
556 variables_->push_back( arg );
557 locations_.push_back( loc );
558 ++dst_;
560 else
562 (*variables_)[ dst_ ] = arg;
563 locations_[ dst_ ] = loc;
564 while( dst_ < variables_->size( ) &&
565 (*variables_)[ dst_ ] != Kernel::THE_SLOT_VARIABLE )
567 ++dst_;
572 void
573 Kernel::Arguments::addNamedArgument( const char * id, const Kernel::VariableHandle & arg, Ast::Expression * loc )
575 if( formals_ == 0 )
577 throw Exceptions::CoreNoNamedFormals( "???" );
580 typedef typeof *(formals_->formals_->argumentOrder_) FormalsMapType;
581 FormalsMapType & formalsMap = *(formals_->formals_->argumentOrder_);
583 /* Note that the name of the sink is invisible, so referring to it is just another arguments which is
584 * put in the sink. This variable happens to have the same name as the sink.
586 FormalsMapType::const_iterator j = formalsMap.find( id );
587 if( j == formalsMap.end( ) ||
588 ( hasSink_ &&
589 j->second == dstEnd_ ) )
591 if( hasSink_ )
593 if( sinkArgList_->namedExprs_->find( id ) != sinkArgList_->namedExprs_->end( ) )
595 throw Exceptions::InternalError( "It is a surprise that the sink got a repeated formal." );
597 sinkArgList_->namedExprs_->insert( std::pair< const char *, Ast::Expression * >( id, loc ) );
598 sinkValues_ = RefCountPtr< Lang::SingleList >( new Lang::SingleListPair( arg, sinkValues_ ) );
599 return;
601 throw Exceptions::NamedFormalMismatch( formals_->formals_->loc( ), strrefdup( id ), Exceptions::NamedFormalMismatch::VARIABLE );
603 size_t pos = j->second;
605 if( pos < dst_ )
607 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::VARIABLE );
610 if( pos >= variables_->size( ) )
612 while( variables_->size( ) < pos )
614 variables_->push_back( Kernel::THE_SLOT_VARIABLE );
615 locations_.push_back( 0 );
617 variables_->push_back( arg );
618 locations_.push_back( loc );
620 else
622 if( (*variables_)[ pos ] != Kernel::THE_SLOT_VARIABLE )
624 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::VARIABLE );
626 (*variables_)[ pos ] = arg;
627 locations_[ pos ] = loc;
629 if( pos == dst_ )
631 while( dst_ < variables_->size( ) &&
632 (*variables_)[ dst_ ] != Kernel::THE_SLOT_VARIABLE )
634 ++dst_;
639 void
640 Kernel::Arguments::addOrderedState( const Kernel::StateHandle & state, Ast::Node * loc )
642 if( stateDst_ == states_->size( ) )
644 states_->push_back( state );
645 stateLocations_.push_back( loc );
646 ++stateDst_;
648 else
650 (*states_)[ stateDst_ ] = state;
651 stateLocations_[ stateDst_ ] = loc;
652 while( stateDst_ < states_->size( ) &&
653 (*states_)[ stateDst_ ] != Kernel::THE_SLOT_STATE )
655 ++stateDst_;
660 void
661 Kernel::Arguments::addNamedState( const char * id, const Kernel::StateHandle & state, Ast::Node * loc )
663 if( formals_ == 0 )
665 throw Exceptions::CoreNoNamedFormals( "???" );
668 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
669 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
671 FormalsMapType::const_iterator j = formalsMap.find( id );
672 if( j == formalsMap.end( ) )
674 throw Exceptions::NamedFormalMismatch( formals_->formals_->loc( ), strrefdup( id ), Exceptions::NamedFormalMismatch::STATE );
676 size_t pos = j->second;
678 if( pos < stateDst_ )
680 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::STATE );
683 if( pos >= states_->size( ) )
685 while( states_->size( ) < pos )
687 states_->push_back( Kernel::THE_SLOT_STATE );
688 stateLocations_.push_back( 0 );
690 states_->push_back( state );
691 stateLocations_.push_back( loc );
693 else
695 if( (*states_)[ pos ] != Kernel::THE_SLOT_STATE )
697 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::STATE );
699 (*states_)[ pos ] = state;
700 stateLocations_[ pos ] = loc;
702 if( pos == stateDst_ )
704 while( stateDst_ < states_->size( ) &&
705 (*states_)[ stateDst_ ] != Kernel::THE_SLOT_STATE )
707 ++stateDst_;
712 void
713 Kernel::Arguments::applyDefaults( )
715 if( formals_ == 0 )
717 return;
720 size_t numberOfArguments = variables_->size( );
721 size_t formalsSize = formals_->defaults_.size( );
723 if( numberOfArguments > formalsSize &&
724 ! hasSink_ )
726 /* The location of the ball must be set by the caller. */
727 throw Exceptions::UserArityMismatch( formals_->formals_->loc( ), formalsSize, numberOfArguments, Exceptions::UserArityMismatch::VARIABLE );
730 size_t numberOfStates = states_->size( );
731 size_t formalsStateSize = formals_->formals_->stateOrder_->size( );
732 if( numberOfStates > formalsStateSize )
734 /* The location of the ball must be set by the caller. */
735 throw Exceptions::UserArityMismatch( formals_->formals_->loc( ), formalsStateSize, numberOfStates, Exceptions::UserArityMismatch::STATE );
738 /* First the easy part: All states must be specified.
740 std::map< size_t, RefCountPtr< const char > > * missingStates = 0;
742 size_t pos = 0;
743 typedef typeof *states_ ListType;
744 for( ListType::const_iterator i = states_->begin( ); i != states_->end( ); ++i, ++pos )
746 if( *i == Kernel::THE_SLOT_STATE )
748 if( missingStates == 0 )
750 missingStates = new typeof *missingStates;
752 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
753 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
754 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
756 if( i->second == pos )
758 missingStates->insert( missingStates->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
759 break;
761 ++i;
762 if( i == formalsMap.end( ) )
764 throw Exceptions::InternalError( "Failed to find position of missing state." );
771 if( numberOfStates < formalsStateSize )
773 if( missingStates == 0 )
775 missingStates = new typeof *missingStates;
777 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
778 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
779 FormalsMapType::const_iterator i = formalsMap.begin( );
780 for( size_t j = 0; j < numberOfStates; ++j )
782 ++i;
785 for( ; i != formalsMap.end( ); ++i, ++pos)
787 missingStates->insert( missingStates->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
793 /* Allocate positions in the vector for all arguments.
795 variables_->reserve( hasSink_ ? formalsSize + 1 : formalsSize );
796 while( variables_->size( ) < formalsSize )
798 variables_->push_back( Kernel::THE_SLOT_VARIABLE );
800 locations_.resize( formalsSize );
802 typedef typeof *variables_ MyListType;
803 typedef typeof formals_->defaults_ DefaultListType;
804 typedef typeof formals_->locations_ LocationListType;
805 DefaultListType::const_iterator src = formals_->defaults_.begin( );
806 LocationListType::const_iterator srcLoc = formals_->locations_.begin( );
807 std::map< size_t, RefCountPtr< const char > > * missingArgs = 0;
808 size_t pos = 0;
809 typedef typeof locations_ MyLocationsType;
810 for( MyListType::iterator dst = variables_->begin( ); dst != variables_->end( ); ++dst, ++src, ++srcLoc, ++pos )
812 if( *dst == Kernel::THE_SLOT_VARIABLE )
814 /* Handle error situation.
816 if( *src == Kernel::THE_SLOT_VARIABLE )
818 if( missingArgs == 0 )
820 missingArgs = new typeof *missingArgs;
822 typedef typeof *(formals_->formals_->argumentOrder_) FormalsMapType;
823 FormalsMapType & formalsMap = *(formals_->formals_->argumentOrder_);
824 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
826 if( i->second == pos )
828 missingArgs->insert( missingArgs->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
829 break;
831 ++i;
832 if( i == formalsMap.end( ) )
834 throw Exceptions::InternalError( "Failed to find position of missing argument." );
839 /* Normal case.
841 *dst = *src;
842 locations_[ pos ] = *srcLoc;
846 if( missingArgs != 0 || missingStates != 0 )
848 throw Exceptions::MissingArguments( formals_->formals_->loc( ), missingArgs, missingStates );
851 if( hasSink_ )
853 variables_->push_back
854 ( Helpers::newValHandle
855 ( new Lang::Structure( sinkArgList_,
856 sinkValues_,
857 true ) ) ); // true means that the sinkArgList_ gets owned by the Structure.
858 sinkArgList_ = 0;
863 Kernel::VariableHandle &
864 Kernel::Arguments::getHandle( size_t i )
866 return (*variables_)[ i ];
869 RefCountPtr< const Lang::Value > &
870 Kernel::Arguments::getValue( size_t i )
872 return (*variables_)[ i ]->getUntyped( );
875 const Ast::SourceLocation &
876 Kernel::Arguments::getLoc( size_t i ) const
878 return locations_[ i ]->loc( );
881 const Ast::Node *
882 Kernel::Arguments::getNode( size_t i ) const
884 return locations_[ i ];
887 Kernel::Thunk *
888 Kernel::Arguments::getThunk( size_t i )
890 return (*variables_)[ i ]->copyThunk( );
893 bool
894 Kernel::Arguments::isSlot( size_t i ) const
896 return (*variables_)[ i ] == Kernel::THE_SLOT_VARIABLE;
899 Kernel::StateHandle
900 Kernel::Arguments::getState( size_t i )
902 return (*states_)[ i ];
905 const Ast::SourceLocation &
906 Kernel::Arguments::getStateLoc( size_t i ) const
908 return stateLocations_[ i ]->loc( );
911 size_t
912 Kernel::Arguments::size( ) const
914 return variables_->size( );
917 bool
918 Kernel::Arguments::empty( ) const
920 return variables_->empty( );
923 void
924 Kernel::Arguments::setMutatorSelf( Kernel::StateHandle mutatorSelf )
926 mutatorSelf_ = mutatorSelf;
929 Kernel::StateHandle
930 Kernel::Arguments::getMutatorSelf( )
932 if( mutatorSelf_ == 0 )
934 throw Exceptions::InternalError( "Kernel::Arguments::getMutatorSelf: self is null." );
936 return mutatorSelf_;
939 void
940 Kernel::Arguments::gcMark( Kernel::GCMarkedSet & marked )
943 typedef typeof *variables_ ListType;
944 for( ListType::const_iterator i = variables_->begin( ); i != variables_->end( ); ++i )
946 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
951 Kernel::Environment::ValueVector
952 Kernel::Arguments::getVariables( )
954 return variables_;
957 Kernel::Environment::StateVector
958 Kernel::Arguments::getStates( )
960 return states_;
964 namespace Shapes
966 namespace Kernel
969 class FunctionOneHandleCont : public Kernel::Continuation
971 RefCountPtr< const Lang::Function > fun_;
972 Kernel::PassedDyn dyn_;
973 Kernel::ContRef cont_;
974 public:
975 FunctionOneHandleCont( const RefCountPtr< const Lang::Function > & fun, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
976 : Kernel::Continuation( traceLoc ), fun_( fun ), dyn_( dyn ), cont_( cont )
978 virtual ~FunctionOneHandleCont( ) { }
979 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
981 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
982 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
985 if( val->isThunk( ) )
987 val->force( val, evalState );
988 return;
991 Kernel::Arguments args = fun_->newCurriedArguments( );
992 args.addOrderedArgument( val, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
994 evalState->dyn_ = dyn_;
995 evalState->cont_ = cont_;
996 fun_->call( evalState, args, traceLoc_ );
998 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1000 trace->push_front( Kernel::Continuation::BackTraceElem( this, "internal function call with one handle" ) );
1001 cont_->backTrace( trace );
1003 virtual void gcMark( Kernel::GCMarkedSet & marked )
1005 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1006 dyn_->gcMark( marked );
1007 cont_->gcMark( marked );
1011 class FunctionTwoHandlesCont_2 : public Kernel::Continuation
1013 RefCountPtr< const Lang::Function > fun_;
1014 Kernel::VariableHandle arg1_;
1015 Kernel::PassedDyn dyn_;
1016 Kernel::ContRef cont_;
1017 public:
1018 FunctionTwoHandlesCont_2( const RefCountPtr< const Lang::Function > & fun, const Kernel::VariableHandle & arg1, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1019 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), dyn_( dyn ), cont_( cont )
1021 virtual ~FunctionTwoHandlesCont_2( ) { }
1022 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1024 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1025 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1028 if( arg2->isThunk( ) )
1030 arg2->force( arg2, evalState );
1031 return;
1034 Kernel::Arguments args = fun_->newCurriedArguments( );
1035 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1036 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1037 evalState->dyn_ = dyn_;
1038 evalState->cont_ = cont_;
1039 fun_->call( evalState, args, traceLoc_ );
1041 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1043 trace->push_front( Kernel::Continuation::BackTraceElem( this, "internal function call with two handles, second" ) );
1044 cont_->backTrace( trace );
1046 virtual void gcMark( Kernel::GCMarkedSet & marked )
1048 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1049 dyn_->gcMark( marked );
1050 cont_->gcMark( marked );
1054 class FunctionTwoHandlesCont_1 : public Kernel::Continuation
1056 RefCountPtr< const Lang::Function > fun_;
1057 Kernel::VariableHandle arg2_;
1058 bool forceArg2_;
1059 Kernel::PassedDyn dyn_;
1060 Kernel::ContRef cont_;
1061 public:
1062 FunctionTwoHandlesCont_1( const RefCountPtr< const Lang::Function > & fun, const Kernel::VariableHandle & arg2, bool forceArg2, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1063 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), dyn_( dyn ), cont_( cont )
1065 virtual ~FunctionTwoHandlesCont_1( ) { }
1066 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1068 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1069 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1072 if( arg1->isThunk( ) )
1074 arg1->force( arg1, evalState );
1075 return;
1078 if( forceArg2_ )
1080 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( fun_, arg1, dyn_, cont_, traceLoc_ ) );
1081 evalState->cont_ = newCont;
1082 newCont->takeHandle( arg2_, evalState );
1083 return;
1086 /* The second handle need not be forced
1088 Kernel::Arguments args = fun_->newCurriedArguments( );
1089 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1090 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1091 evalState->dyn_ = dyn_;
1092 evalState->cont_ = cont_;
1093 fun_->call( evalState, args, traceLoc_ );
1095 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1097 trace->push_front( Kernel::Continuation::BackTraceElem( this, "internal function call with two handles, first" ) );
1098 cont_->backTrace( trace );
1100 virtual void gcMark( Kernel::GCMarkedSet & marked )
1102 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1103 dyn_->gcMark( marked );
1104 cont_->gcMark( marked );
1108 class FunctionTwoHandlesOneStateCont_2 : public Kernel::Continuation
1110 RefCountPtr< const Lang::Function > fun_;
1111 Kernel::VariableHandle arg1_;
1112 Kernel::StateHandle state_;
1113 Kernel::PassedDyn dyn_;
1114 Kernel::ContRef cont_;
1115 public:
1116 FunctionTwoHandlesOneStateCont_2( const RefCountPtr< const Lang::Function > & fun, const Kernel::VariableHandle & arg1, Kernel::StateHandle state, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1117 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), state_( state ), dyn_( dyn ), cont_( cont )
1119 virtual ~FunctionTwoHandlesOneStateCont_2( ) { }
1120 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1122 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1123 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1126 if( arg2->isThunk( ) )
1128 arg2->force( arg2, evalState );
1129 return;
1132 Kernel::Arguments args = fun_->newCurriedArguments( );
1133 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1134 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1135 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1136 evalState->dyn_ = dyn_;
1137 evalState->cont_ = cont_;
1138 fun_->call( evalState, args, traceLoc_ );
1140 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1142 trace->push_front( Kernel::Continuation::BackTraceElem( this, "internal function call with two handles and one state, second" ) );
1143 cont_->backTrace( trace );
1145 virtual void gcMark( Kernel::GCMarkedSet & marked )
1147 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1148 state_->gcMark( marked );
1149 dyn_->gcMark( marked );
1150 cont_->gcMark( marked );
1154 class FunctionTwoHandlesOneStateCont_1 : public Kernel::Continuation
1156 RefCountPtr< const Lang::Function > fun_;
1157 Kernel::VariableHandle arg2_;
1158 bool forceArg2_;
1159 Kernel::StateHandle state_;
1160 Kernel::PassedDyn dyn_;
1161 Kernel::ContRef cont_;
1162 public:
1163 FunctionTwoHandlesOneStateCont_1( const RefCountPtr< const Lang::Function > & fun, const Kernel::VariableHandle & arg2, bool forceArg2, Kernel::StateHandle state, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1164 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), state_( state ), dyn_( dyn ), cont_( cont )
1166 virtual ~FunctionTwoHandlesOneStateCont_1( ) { }
1167 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1169 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1170 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1173 if( arg1->isThunk( ) )
1175 arg1->force( arg1, evalState );
1176 return;
1179 if( forceArg2_ )
1181 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( fun_, arg1, state_, dyn_, cont_, traceLoc_ ) );
1182 evalState->cont_ = newCont;
1183 newCont->takeHandle( arg2_, evalState );
1184 return;
1187 /* The second handle need not be forced
1189 Kernel::Arguments args = fun_->newCurriedArguments( );
1190 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1191 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1192 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1193 evalState->dyn_ = dyn_;
1194 evalState->cont_ = cont_;
1195 fun_->call( evalState, args, traceLoc_ );
1197 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
1199 trace->push_front( Kernel::Continuation::BackTraceElem( this, "internal function call with two handles and one state, first" ) );
1200 cont_->backTrace( trace );
1202 virtual void gcMark( Kernel::GCMarkedSet & marked )
1204 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1205 dyn_->gcMark( marked );
1206 cont_->gcMark( marked );
1207 state_->gcMark( marked );
1215 Lang::Function::Function( Kernel::EvaluatedFormals * formals )
1216 : formals_( formals )
1219 DISPATCHIMPL( Function );
1221 Lang::Function::~Function( )
1223 if( formals_ != 0 )
1225 delete formals_->formals_;
1226 delete formals_;
1230 Kernel::ValueRef
1231 Lang::Function::transformed( const Lang::Transform2D & tf, Kernel::ValueRef self ) const
1233 return Kernel::ValueRef( new Lang::TransformedFunction2D( tf, self.down_cast< const Lang::Function >( ) ) );
1236 bool
1237 Lang::Function::isProcedural( ) const
1239 return false;
1242 bool
1243 Lang::Function::inScope( Kernel::PassedEnv env ) const
1245 return true;
1248 void
1249 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Ast::SourceLocation & callLoc ) const
1251 Kernel::Arguments args = this->newCurriedArguments( );
1253 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1255 this->call( evalState, args, callLoc );
1258 void
1259 Lang::Function::analyze( Ast::Node * parent, const Ast::AnalysisEnvironment * env )
1261 throw Exceptions::InternalError( "A syntax function is not overriding the analyze method." );
1264 void
1265 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Kernel::ValueRef & arg2, const Ast::SourceLocation & callLoc ) const
1267 Kernel::Arguments args = this->newCurriedArguments( );
1269 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1270 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg2 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1272 this->call( evalState, args, callLoc );
1275 Ast::ArgListExprs * Lang::Function::oneExprArgList = new Ast::ArgListExprs( static_cast< size_t >( 1 ) );
1276 Ast::ArgListExprs * Lang::Function::twoExprsArgList = new Ast::ArgListExprs( static_cast< size_t >( 2 ) );
1278 void
1279 Lang::Function::call( const RefCountPtr< const Lang::Function > & selfRef, Kernel::EvalState * evalState, const Kernel::VariableHandle & arg1, const Ast::SourceLocation & callLoc ) const
1281 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::oneExprArgList, *evalState );
1283 if( info->force( 0 ) )
1285 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionOneHandleCont( selfRef, evalState->dyn_, evalState->cont_, callLoc ) );
1286 evalState->cont_ = cont;
1287 cont->takeHandle( arg1, evalState );
1288 return;
1291 /* The handle need not be forced
1293 Kernel::Arguments args = this->newCurriedArguments( );
1294 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1295 this->call( evalState, args, callLoc );
1298 void
1299 Lang::Function::call( const RefCountPtr< const Lang::Function > & selfRef, Kernel::EvalState * evalState, const Kernel::VariableHandle & arg1, const Kernel::VariableHandle & arg2, const Ast::SourceLocation & callLoc ) const
1301 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1303 /* Remember that arguments are ordered backwards!
1306 if( info->force( 1 ) )
1308 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_1( selfRef, arg2, info->force( 0 ), evalState->dyn_, evalState->cont_, callLoc ) );
1309 evalState->cont_ = cont;
1310 cont->takeHandle( arg1, evalState );
1311 return;
1314 if( info->force( 0 ) )
1316 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( selfRef, arg1, evalState->dyn_, evalState->cont_, callLoc ) );
1317 evalState->cont_ = cont;
1318 cont->takeHandle( arg2, evalState );
1319 return;
1322 /* None of the handles need to be forced
1324 Kernel::Arguments args = this->newCurriedArguments( );
1325 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1326 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1327 this->call( evalState, args, callLoc );
1330 void
1331 Lang::Function::call( const RefCountPtr< const Lang::Function > & selfRef, Kernel::EvalState * evalState, const Kernel::VariableHandle & arg1, const Kernel::VariableHandle & arg2, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const
1333 /* I'm not quite sure if we should also put a dummy state argument in info...
1335 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1337 /* Remember that arguments are ordered backwards!
1340 if( info->force( 1 ) )
1342 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_1( selfRef, arg2, info->force( 0 ), state, evalState->dyn_, evalState->cont_, callLoc ) );
1343 evalState->cont_ = cont;
1344 cont->takeHandle( arg1, evalState );
1345 return;
1348 if( info->force( 0 ) )
1350 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( selfRef, arg1, state, evalState->dyn_, evalState->cont_, callLoc ) );
1351 evalState->cont_ = cont;
1352 cont->takeHandle( arg2, evalState );
1353 return;
1356 /* None of the handles need to be forced
1358 Kernel::Arguments args = this->newCurriedArguments( );
1359 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1360 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1361 args.addOrderedState( state, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1362 this->call( evalState, args, callLoc );
1366 RefCountPtr< Kernel::CallContInfo >
1367 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1369 return formals_->newCallContInfo( argList, evalState );
1372 RefCountPtr< Kernel::CallContInfo >
1373 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1375 return formals_->newCallContInfo( argList, evalState, curryArgs );
1378 Kernel::Arguments
1379 Lang::Function::newCurriedArguments( ) const
1381 return Kernel::Arguments( formals_ );
1385 RefCountPtr< const Lang::Class > Lang::Function::TypeID( new Lang::SystemFinalClass( strrefdup( "Function" ) ) );
1386 TYPEINFOIMPL( Function );
1388 Kernel::EvaluatedFormals::EvaluatedFormals( Kernel::Formals * formals )
1389 : selectiveForcing_( false ), forceAll_( false ), formals_( formals ), isSink_( true )
1392 Kernel::EvaluatedFormals::EvaluatedFormals( const char * locationString )
1393 : selectiveForcing_( true ), formals_( 0 ), isSink_( true )
1395 Kernel::Formals * formals( new Kernel::Formals( ) );
1396 formals->setLoc( Ast::SourceLocation( locationString ) );
1397 formals_ = formals;
1400 Kernel::EvaluatedFormals::EvaluatedFormals( const char * locationString, bool forceAll)
1401 : selectiveForcing_( false ), forceAll_( forceAll ), formals_( 0 ), isSink_( true )
1403 Kernel::Formals * formals( new Kernel::Formals( ) );
1404 formals->setLoc( Ast::SourceLocation( locationString ) );
1405 formals_ = formals;
1408 Kernel::EvaluatedFormals::~EvaluatedFormals( )
1410 /* Don't delete the orderedFormals, since we don't own it. A case for reference counting? */
1413 RefCountPtr< Kernel::CallContInfo >
1414 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1416 if( selectiveForcing_ )
1418 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList ) ) );
1420 else
1422 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1426 RefCountPtr< Kernel::CallContInfo >
1427 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1429 if( selectiveForcing_ )
1431 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList, curryArgs ) ) );
1433 else
1435 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1439 void
1440 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc, bool force )
1442 if( ! selectiveForcing_ )
1444 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function does not have selective forcing." );
1446 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1447 formals_->forcePos_.push_back( force );
1448 defaults_.push_back( defaultVal );
1449 locations_.push_back( loc );
1452 void
1453 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc )
1455 if( selectiveForcing_ )
1457 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function requires individual forcing specification." );
1459 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1460 formals_->forcePos_.push_back( forceAll_ );
1461 defaults_.push_back( defaultVal );
1462 locations_.push_back( loc );
1465 void
1466 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal, bool force )
1468 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION, force );
1471 void
1472 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal )
1474 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION );
1477 void
1478 Kernel::EvaluatedFormals::appendCoreStateFormal( const char * id )
1480 (*(formals_->stateOrder_))[ id ] = formals_->stateOrder_->size( );
1483 void
1484 Kernel::EvaluatedFormals::gcMark( Kernel::GCMarkedSet & marked )
1486 typedef typeof defaults_ ListType;
1487 for( ListType::const_iterator i = defaults_.begin( ); i != defaults_.end( ); ++i )
1489 if( *i != NullPtr< Kernel::Variable >( ) )
1491 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1497 Lang::CuteFunction::CuteFunction( RefCountPtr< const Lang::Function > callee, const Kernel::Arguments & someArgs )
1498 : Lang::Function( 0 ), callee_( callee), someArgs_( someArgs.clone( ) )
1501 Lang::CuteFunction::~CuteFunction( )
1504 RefCountPtr< Kernel::CallContInfo >
1505 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1507 return callee_->newCallContInfo( argList, evalState, someArgs_ );
1510 RefCountPtr< Kernel::CallContInfo >
1511 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1513 /* when we are the callee of a CuteFunction, our someArgs are part of that CuteFunction's someArgs, and hence curryArgs
1514 contains everything that is to be passed to our callee.
1516 return callee_->newCallContInfo( argList, evalState, curryArgs );
1519 Kernel::Arguments
1520 Lang::CuteFunction::newCurriedArguments( ) const
1522 return someArgs_.clone( );
1525 void
1526 Lang::CuteFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1528 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1529 Also note that the total set of arguments being passed to the original function is no more than someArgs and what was passed in the last call.
1531 callee_->call( evalState, args, callLoc );
1534 bool
1535 Lang::CuteFunction::isTransforming( ) const
1537 return callee_->isTransforming( );
1540 void
1541 Lang::CuteFunction::gcMark( Kernel::GCMarkedSet & marked )
1543 const_cast< Lang::Function * >( callee_.getPtr( ) )->gcMark( marked );
1544 someArgs_.gcMark( marked );
1548 Lang::ComposedFunction::ComposedFunction( const RefCountPtr< const Lang::Function > & second, const RefCountPtr< const Lang::Function > & first )
1549 : Lang::Function( 0 ), second_( second ), first_( first )
1552 Lang::ComposedFunction::~ComposedFunction( )
1555 void
1556 Lang::ComposedFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1558 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1559 Also note that the total set of arguments being passed to the original function is no more than someArgs and what was passed in the last call.
1561 evalState->cont_ = Kernel::ContRef( new Kernel::ComposedFunctionCall_cont( second_, evalState->dyn_, evalState->cont_, callLoc ) );
1562 first_->call( evalState, args, callLoc );
1565 RefCountPtr< Kernel::CallContInfo >
1566 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1568 return first_->newCallContInfo( argList, evalState );
1571 RefCountPtr< Kernel::CallContInfo >
1572 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1574 return first_->newCallContInfo( argList, evalState, curryArgs );
1577 Kernel::Arguments
1578 Lang::ComposedFunction::newCurriedArguments( ) const
1580 return first_->newCurriedArguments( );
1583 bool
1584 Lang::ComposedFunction::isTransforming( ) const
1586 return second_->isTransforming( );
1589 void
1590 Lang::ComposedFunction::gcMark( Kernel::GCMarkedSet & marked )
1592 const_cast< Lang::Function * >( second_.getPtr( ) )->gcMark( marked );
1593 const_cast< Lang::Function * >( first_.getPtr( ) )->gcMark( marked );
1597 Lang::UserFunction::UserFunction( Kernel::EvaluatedFormals * formals, Ast::Expression * body, Kernel::PassedEnv env, const Ast::FunctionMode & functionMode )
1598 : Lang::Function( formals ), body_( body ), env_( env ), functionMode_( functionMode )
1601 // DISPATCHIMPL( UserFunction );
1603 Lang::UserFunction::~UserFunction( )
1605 // Note that we don't delete the things that we most likely share with other objects
1606 // Reference counting could be used here, but there will never be more such things than there are function expressions in the source
1608 // This prevents formals->formals from being deleted by Lang::Function::~Function
1609 delete formals_;
1610 formals_ = 0;
1613 void
1614 Lang::UserFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1616 args.applyDefaults( );
1617 evalState->env_ = new Kernel::Environment( Kernel::theEnvironmentList, env_, formals_->formals_->argumentOrder_, args.getVariables( ), formals_->formals_->stateOrder_, args.getStates( ) );
1619 if( ! this->isProcedural( ) )
1621 evalState->env_->activateFunctionBoundary( );
1624 body_->eval( evalState );
1627 bool
1628 Lang::UserFunction::isTransforming( ) const
1630 return ( functionMode_ & Ast::FUNCTION_TRANSFORMING ) != 0;
1633 bool
1634 Lang::UserFunction::isProcedural( ) const
1636 return ( functionMode_ & Ast::FUNCTION_PROCEDURAL ) != 0;
1639 bool
1640 Lang::UserFunction::inScope( Kernel::PassedEnv env ) const
1642 return ! isProcedural( )
1643 || env_->isProceduralParentOf( env );
1646 void
1647 Lang::UserFunction::gcMark( Kernel::GCMarkedSet & marked )
1649 env_->gcMark( marked );
1653 Lang::TransformedFunction2D::TransformedFunction2D( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Function > & fun )
1654 : Lang::Function( 0 ), tf_( tf ), fun_( fun )
1657 Lang::TransformedFunction2D::~TransformedFunction2D( )
1660 void
1661 Lang::TransformedFunction2D::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1663 evalState->cont_ = Kernel::ContRef( new Kernel::Transform2DCont( tf_, evalState->cont_, 0 ) );
1664 fun_->call( evalState, args, callLoc );
1667 bool
1668 Lang::TransformedFunction2D::isTransforming( ) const
1670 return fun_->isTransforming( );
1673 void
1674 Lang::TransformedFunction2D::gcMark( Kernel::GCMarkedSet & marked )
1676 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1680 Lang::VectorFunction::VectorFunction( const std::vector< Kernel::ValueRef > * mem )
1681 : Lang::Function( new Kernel::EvaluatedFormals( "<vector>", true ) ), mem_( mem ),
1682 memNumeric_( NullPtr< const std::vector< double > >( ) )
1684 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
1687 // DISPATCHIMPL( VectorFunction );
1689 Lang::VectorFunction::~VectorFunction( )
1692 Kernel::VariableHandle
1693 Lang::VectorFunction::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
1695 if( strcmp( fieldID, "size" ) == 0 )
1697 return Helpers::newValHandle( new Lang::Integer( mem_->size( ) ) );
1699 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
1702 const char * Lang::VectorFunction::title_ = "<vector>";
1704 void
1705 Lang::VectorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1707 const size_t ARITY = 1;
1708 if( args.size( ) != ARITY )
1710 throw Exceptions::CoreArityMismatch( title_, ARITY, args.size( ) );
1713 typedef const Lang::Integer ArgType;
1714 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
1716 if( arg->val_ < 0 )
1718 throw Exceptions::CoreOutOfRange( title_, args, 0, "Index is negative." );
1721 if( arg->val_ >= static_cast< int >( mem_->size( ) ) )
1723 throw Exceptions::CoreOutOfRange( title_, args, 0, "Index exceeds vector size." );
1726 Kernel::ContRef cont = evalState->cont_;
1727 cont->takeValue( (*mem_)[ arg->val_ ],
1728 evalState );
1731 bool
1732 Lang::VectorFunction::isTransforming( ) const
1734 return false;
1737 void
1738 Lang::VectorFunction::gcMark( Kernel::GCMarkedSet & marked )
1740 for( std::vector< Kernel::ValueRef >::const_iterator i = mem_->begin( ); i != mem_->end( ); ++i )
1742 const_cast< Lang::Value * >( i->getPtr( ) )->gcMark( marked );
1746 RefCountPtr< const std::vector< double > >
1747 Lang::VectorFunction::getNumeric( const Ast::SourceLocation & callLoc ) const
1749 if( memNumeric_ == NullPtr< const std::vector< double > >( ) )
1751 RefCountPtr< std::vector< double > > res( new std::vector< double > ); // Note that this is not const, so far...
1752 res->reserve( mem_->size( ) );
1753 typedef typeof *mem_ SrcType;
1754 for( SrcType::const_iterator src = mem_->begin( ); src != mem_->end( ); ++src )
1756 res->push_back( Helpers::down_cast< const Lang::Float >( *src, callLoc )->val_ );
1759 memNumeric_ = res;
1761 return memNumeric_;
1765 const char * Lang::ColorInterpolator::title_ = "<color-interpolator>";
1767 Lang::ColorInterpolator::ColorInterpolator( const RefCountPtr< KeyContainer > & key,
1768 const RefCountPtr< RGBContainer > & RGBcolor,
1769 const RefCountPtr< GrayContainer > & graycolor,
1770 const RefCountPtr< CMYKContainer > & CMYKcolor,
1771 ColorType colorType)
1772 : Lang::Function( new Kernel::EvaluatedFormals( Lang::ColorInterpolator::title_, true ) ),
1773 key_( key ), RGBcolor_ ( RGBcolor ), graycolor_ ( graycolor ), CMYKcolor_ ( CMYKcolor ), colorType_(colorType)
1775 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
1778 Lang::ColorInterpolator::~ColorInterpolator( )
1781 Kernel::VariableHandle
1782 Lang::ColorInterpolator::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
1784 if( strcmp( fieldID, "low" ) == 0 )
1786 return Helpers::newValHandle( new Lang::Float( key_->front( ) ) );
1788 if( strcmp( fieldID, "high" ) == 0 )
1790 return Helpers::newValHandle( new Lang::Float( key_->back( ) ) );
1792 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
1796 template <class COLOR_TYPE, class COLOR_CONTAINER>
1797 void
1798 Lang::ColorInterpolator::callHelper( Kernel::EvalState * evalState,
1799 const RefCountPtr< COLOR_CONTAINER > & colorContainer,
1800 double key, KeyContainer::const_iterator keyHi ) const
1802 if( keyHi == key_->end( ) )
1804 Kernel::ContRef cont = evalState->cont_;
1805 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->back( ) ) ),
1806 evalState );
1807 return;
1810 if( keyHi == key_->begin( ) )
1812 Kernel::ContRef cont = evalState->cont_;
1813 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->front( ) ) ),
1814 evalState );
1815 return;
1818 KeyContainer::const_iterator keyLo = keyHi - 1;
1819 double rem = ( key - *keyLo ) / ( *keyHi - *keyLo );
1821 Kernel::ContRef cont = evalState->cont_;
1823 typename COLOR_CONTAINER::const_iterator colorHi = colorContainer->begin( ) + ( keyHi - key_->begin( ) );
1824 typename COLOR_CONTAINER::const_iterator colorLo = colorHi - 1;
1826 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorLo->mulNoCheck( 1 - rem ).addNoCheck( colorHi->mulNoCheck( rem ) ) ) ),
1827 evalState );
1831 void
1832 Lang::ColorInterpolator::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1834 const size_t ARITY = 1;
1835 if( args.size( ) != ARITY )
1837 throw Exceptions::CoreArityMismatch( title_, ARITY, args.size( ) );
1840 typedef const Lang::Float ArgType;
1841 double key = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc )->val_;
1843 KeyContainer::const_iterator keyHi = lower_bound( key_->begin( ), key_->end( ), key );
1844 switch( colorType_ )
1846 case RGB:
1847 callHelper< Lang::RGB >( evalState, RGBcolor_, key, keyHi );
1848 break;
1849 case GRAY:
1850 callHelper< Lang::Gray >( evalState, graycolor_, key, keyHi );
1851 break;
1852 case CMYK:
1853 callHelper< Lang::CMYK >( evalState, CMYKcolor_, key, keyHi );
1854 break;
1855 case UNDEFINED:
1856 throw Exceptions::InternalError( "ColorInterpolator::call: Did not expect UNDEFINED in ennum switch." );
1860 bool
1861 Lang::ColorInterpolator::isTransforming( ) const
1863 return false;
1866 void
1867 Lang::ColorInterpolator::gcMark( Kernel::GCMarkedSet & marked )
1871 Lang::BinaryOperatorFunction::BinaryOperatorFunction( Ast::BinaryInfixExpr * opExpr, const char * title )
1872 : Lang::Function( new Kernel::EvaluatedFormals( title, true ) ), opExpr_( opExpr ), title_( title )
1874 formals_->appendEvaluatedCoreFormal( "first", Kernel::THE_SLOT_VARIABLE );
1875 formals_->appendEvaluatedCoreFormal( "second", Kernel::THE_SLOT_VARIABLE );
1878 Lang::BinaryOperatorFunction::~BinaryOperatorFunction( )
1880 delete opExpr_;
1883 void
1884 Lang::BinaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1886 const size_t ARITY = 2;
1887 CHECK_ARITY( args, ARITY, title_ );
1888 RefCountPtr< const Lang::Value > arg1 = args.getValue( 0 );
1889 RefCountPtr< const Lang::Value > arg2 = args.getValue( 1 );
1893 Kernel::ContRef cont = evalState->cont_;
1894 cont->takeValue( arg1->binaryDispatch1( arg1, arg2, evalState->dyn_, opExpr_ ),
1895 evalState );
1897 catch( Exceptions::BinaryInfixNotApplicable & ball )
1899 ball.setOperatorSymbol( title_ );
1900 throw;
1904 bool
1905 Lang::BinaryOperatorFunction::isTransforming( ) const
1907 return false;
1911 Lang::UnaryOperatorFunction::UnaryOperatorFunction( Ast::UnaryExpr * opExpr, const char * title )
1912 : Lang::Function( new Kernel::EvaluatedFormals( title, true ) ), opExpr_( opExpr ), title_( title )
1914 formals_->appendEvaluatedCoreFormal( "only", Kernel::THE_SLOT_VARIABLE );
1917 Lang::UnaryOperatorFunction::~UnaryOperatorFunction( )
1919 delete opExpr_;
1922 void
1923 Lang::UnaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1925 const size_t ARITY = 1;
1926 CHECK_ARITY( args, ARITY, title_ );
1928 RefCountPtr< const Lang::Value > arg = args.getValue( 0 );
1932 Kernel::ContRef cont = evalState->cont_;
1933 cont->takeValue( arg->unaryDispatch( arg, evalState->dyn_, opExpr_ ),
1934 evalState );
1936 catch( Exceptions::UnaryPrefixNotApplicable & ball )
1938 ball.setOperatorSymbol( title_ );
1939 throw;
1941 catch( Exceptions::UnaryPostfixNotApplicable & ball )
1943 ball.setOperatorSymbol( title_ );
1944 throw;
1948 bool
1949 Lang::UnaryOperatorFunction::isTransforming( ) const
1951 return false;