Doc: Update namespace of extensions
[shapes.git] / source / functiontypes.cc
blob171478f7bc686be1d967f8cbd709f61897e50be0
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include <cmath>
21 #include "singlelistrange.h"
23 #include "shapestypes.h"
24 #include "shapesexceptions.h"
25 #include "astexpr.h"
26 #include "consts.h"
27 #include "angleselect.h"
28 #include "astvar.h"
29 #include "astclass.h"
30 #include "globals.h"
31 #include "continuations.h"
32 #include "methodbase.h"
33 #include "shapescore.h"
34 #include "check.h"
36 //#include "clapack.h"
37 //#include "cblas.h"
38 #include <gsl/gsl_matrix.h>
39 #include <gsl/gsl_linalg.h>
40 #include <gsl/gsl_blas.h>
41 #include <ctype.h>
42 #include <stack>
43 #include <algorithm>
45 #define CHOP_Ltol( x )\
46 if( fabs( x ) < Ltol )\
48 x = 0;\
50 else if( fabs( x - 1 ) < Ltol )\
52 x = 1;\
54 else if( fabs( x + 1 ) < Ltol )\
56 x = -1;\
59 #define CHOP_ptol( x )\
60 if( x.abs( ) < ptol )\
62 x = Concrete::ZERO_LENGTH;\
65 using namespace Shapes;
66 using namespace std;
68 void displayArray( std::ostream & os, const double * pr, size_t m, size_t n )
70 size_t r;
71 size_t c;
72 char buf[20];
73 for( r = 0; r < m; ++r )
75 for( c = 0; c < n; ++c )
77 sprintf( buf, "%14.5e", *( pr + ( r + c * m ) ) );
78 os << buf ;
80 os << std::endl ;
84 void displayArray( std::ostream & os, const gsl_matrix * m )
86 char buf[20];
87 for( size_t r = 0; r < m->size1; ++r )
89 for( size_t c = 0; c < m->size2; ++c )
91 sprintf( buf, "%14.5e", gsl_matrix_get( m, r, c ) );
92 os << buf ;
94 os << std::endl ;
98 namespace Shapes
101 namespace Lang
104 class Transform2DMethod_chop : public Lang::MethodBase< Lang::Transform2D >
106 public:
107 Transform2DMethod_chop( RefCountPtr< const Lang::Transform2D > _self, const Ast::FileID * fullMethodID );
108 virtual ~Transform2DMethod_chop( );
109 virtual void call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const;
110 static const char * staticFieldID( ) { return "chop"; }
113 class Transform3DMethod_chop : public Lang::MethodBase< Lang::Transform3D >
115 public:
116 Transform3DMethod_chop( RefCountPtr< const Lang::Transform3D > _self, const Ast::FileID * fullMethodID );
117 virtual ~Transform3DMethod_chop( );
118 virtual void call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const;
119 static const char * staticFieldID( ) { return "chop"; }
125 void
126 Transform2D_register_methods( Lang::SystemFinalClass * dstClass )
128 dstClass->registerMethod( new Kernel::MethodFactory< Lang::Transform2D, Lang::Transform2DMethod_chop >( ) );
131 RefCountPtr< const Lang::Class > Lang::Transform2D::TypeID( new Lang::SystemFinalClass( strrefdup( "Transform2D" ), Transform2D_register_methods ) );
132 TYPEINFOIMPL( Transform2D );
134 Lang::Transform2D::Transform2D( double xx, double yx, double xy, double yy, Concrete::Length xt, Concrete::Length yt )
135 : xx_( xx ), yx_( yx ), xy_( xy ), yy_( yy ), xt_( xt ), yt_( yt )
138 Lang::Transform2D::Transform2D( const Lang::Transform2D & tf2, const Lang::Transform2D & tf1 )
139 : xx_( tf2.xx_ * tf1.xx_ + tf2.xy_ * tf1.yx_ ),
140 yx_( tf2.yx_ * tf1.xx_ + tf2.yy_ * tf1.yx_ ),
141 xy_( tf2.xx_ * tf1.xy_ + tf2.xy_ * tf1.yy_ ),
142 yy_( tf2.yx_ * tf1.xy_ + tf2.yy_ * tf1.yy_ ),
143 xt_( tf2.xx_ * tf1.xt_ + tf2.xy_ * tf1.yt_ + tf2.xt_ ),
144 yt_( tf2.yx_ * tf1.xt_ + tf2.yy_ * tf1.yt_ + tf2.yt_ )
147 DISPATCHIMPL( Transform2D );
149 Lang::Transform2D::~Transform2D( )
152 Kernel::VariableHandle
153 Lang::Transform2D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
155 const size_t N = 2;
156 if( strcmp( fieldID, "p" ) == 0 )
158 return Helpers::newValHandle( new Lang::Coords2D( xt_, yt_ ) );
160 if( strcmp( fieldID, "L" ) == 0 )
162 return Helpers::newValHandle( new Lang::Transform2D( xx_, yx_, xy_, yy_, 0, 0 ) );
164 if( strcmp( fieldID, "Lx" ) == 0 )
166 return Helpers::newValHandle( new Lang::FloatPair( xx_, yx_ ) );
168 if( strcmp( fieldID, "Ly" ) == 0 )
170 return Helpers::newValHandle( new Lang::FloatPair( xy_, yy_ ) );
172 if( strcmp( fieldID, "xL" ) == 0 )
174 return Helpers::newValHandle( new Lang::FloatPair( xx_, xy_ ) );
176 if( strcmp( fieldID, "yL" ) == 0 )
178 return Helpers::newValHandle( new Lang::FloatPair( yx_, yy_ ) );
180 if( strcmp( fieldID, "linear?" ) == 0 )
182 return ( xt_ == 0 && yt_ == 0 ) ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
184 if( strcmp( fieldID, "translation?" ) == 0 )
186 return isTranslation( ) ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
188 if( strcmp( fieldID, "special?" ) == 0 )
190 gsl_matrix * A = gsl_matrix_alloc( N, N );
191 gsl_permutation * perm = gsl_permutation_alloc( N );
192 int signum;
193 write_gsl_matrix( A );
194 gsl_linalg_LU_decomp( A, perm, & signum );
195 bool res = gsl_linalg_LU_det( A, signum ) > 0;
196 gsl_matrix_free( A );
197 gsl_permutation_free( perm );
198 return res ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
200 if( strcmp( fieldID, "Euclidean?" ) == 0 )
202 gsl_matrix * A = gsl_matrix_alloc( N, N );
203 gsl_vector * SVD_work = gsl_vector_alloc( N );
204 gsl_vector * sigma = gsl_vector_alloc( N );
205 gsl_matrix * V = gsl_matrix_alloc( N, N );
206 write_gsl_matrix( A );
207 gsl_linalg_SV_decomp( A, V, sigma, SVD_work );
208 const double tol = 1e-4;
209 bool res = 1 - tol < gsl_vector_get( sigma, N - 1 ) && gsl_vector_get( sigma, 0 ) < 1 + tol;
210 gsl_matrix_free( V );
211 gsl_vector_free( sigma );
212 gsl_vector_free( SVD_work );
213 gsl_matrix_free( A );
214 return res ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
217 return TypeID->getMethod( selfRef, fieldID ); /* This will throw if there is no such method. */
220 Lang::Transform2D *
221 Lang::Transform2D::clone( ) const
223 return new Transform2D( xx_, yx_,
224 xy_, yy_,
225 xt_, yt_ );
228 bool
229 Lang::Transform2D::isIdentity( ) const
231 return
232 xt_ == Concrete::ZERO_LENGTH && yt_ == Concrete::ZERO_LENGTH &&
233 xx_ == 1 && yy_ == 1 &&
234 xy_ == 0 && yx_ == 0;
237 bool
238 Lang::Transform2D::isTranslation( ) const
240 return
241 xx_ == 1 && yy_ == 1 &&
242 xy_ == 0 && yx_ == 0;
245 void
246 Lang::Transform2D::write_gsl_matrix( gsl_matrix * matrix_2_2 ) const
248 gsl_matrix_set( matrix_2_2, 0, 0, xx_ );
249 gsl_matrix_set( matrix_2_2, 1, 0, yx_ );
250 gsl_matrix_set( matrix_2_2, 0, 1, xy_ );
251 gsl_matrix_set( matrix_2_2, 1, 1, yy_ );
254 void
255 Lang::Transform2D::write_gsl_vector( gsl_vector * vec_2 ) const
257 gsl_vector_set( vec_2, 0, Concrete::Length::offtype( xt_ ) );
258 gsl_vector_set( vec_2, 1, Concrete::Length::offtype( yt_ ) );
261 void
262 Lang::Transform2D::shipout( std::ostream & os ) const
264 os << xx_ << " " << yx_ << " " << xy_ << " " << yy_ << " "
265 << Concrete::Length::offtype( xt_ ) << " " << Concrete::Length::offtype( yt_ ) ;
268 // to be used by text moveto commands
269 void
270 Lang::Transform2D::replaceBy( const Lang::Transform2D & newtf )
272 xx_ = newtf.xx_;
273 yx_ = newtf.yx_;
274 xy_ = newtf.xy_;
275 yy_ = newtf.yy_;
276 xt_ = newtf.xt_;
277 yt_ = newtf.yt_;
280 // to be used by text newline commands
281 void
282 Lang::Transform2D::prependShift( const Concrete::Coords2D & d )
284 // Think of d as tf1 when composing transforms.
286 xt_ += xx_ * d.x_ + xy_ * d.y_;
287 yt_ += yx_ * d.x_ + yy_ * d.y_;
290 // to be used by text painting commands
291 void
292 Lang::Transform2D::prependXShift( const Concrete::Length & dx )
294 // Think of d as tf1 when composing transforms.
296 xt_ += xx_ * dx;
297 yt_ += yx_ * dx;
300 // to be used for text rise
301 void
302 Lang::Transform2D::prependYShift( const Concrete::Length & dy )
304 // Implementation is symmetric to prependXShift.
306 xt_ += xy_ * dy;
307 yt_ += yy_ * dy;
310 // to be used for text horizontal scaling
311 void
312 Lang::Transform2D::prependXScale( double a )
314 // Think of a as tf1.xx_ when composing transforms.
316 xx_ *= a;
317 yx_ *= a;
320 void
321 Lang::Transform2D::show( std::ostream & os ) const
323 os << "[ ("
324 << xx_ << ", " << yx_ << ") ("
325 << xy_ << ", " << yy_ << ") ("
326 << Lang::Length( xt_ ) << ", " << Lang::Length( yt_ ) << ") ]" ;
330 void
331 Transform3D_register_methods( Lang::SystemFinalClass * dstClass )
333 dstClass->registerMethod( new Kernel::MethodFactory< Lang::Transform3D, Lang::Transform3DMethod_chop >( ) );
336 RefCountPtr< const Lang::Class > Lang::Transform3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Transform3D" ), Transform3D_register_methods ) );
337 TYPEINFOIMPL( Transform3D );
339 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 )
340 : planeNormalTransformData_( 0 ),
341 xx_( xx ), yx_( yx ), zx_( zx ), xy_( xy ), yy_( yy ), zy_( zy ), xz_( xz ), yz_( yz ), zz_( zz ), xt_( xt ), yt_( yt ), zt_( zt )
344 Lang::Transform3D::Transform3D( const gsl_matrix * matrix_3_3, const gsl_vector * vec_3 )
345 : planeNormalTransformData_( 0 ),
346 xx_( gsl_matrix_get( matrix_3_3, 0, 0 ) ), yx_( gsl_matrix_get( matrix_3_3, 1, 0 ) ), zx_( gsl_matrix_get( matrix_3_3, 2, 0 ) ),
347 xy_( gsl_matrix_get( matrix_3_3, 0, 1 ) ), yy_( gsl_matrix_get( matrix_3_3, 1, 1 ) ), zy_( gsl_matrix_get( matrix_3_3, 2, 1 ) ),
348 xz_( gsl_matrix_get( matrix_3_3, 0, 2 ) ), yz_( gsl_matrix_get( matrix_3_3, 1, 2 ) ), zz_( gsl_matrix_get( matrix_3_3, 2, 2 ) ),
349 xt_( gsl_vector_get( vec_3, 0 ) ), yt_( gsl_vector_get( vec_3, 1 ) ), zt_( gsl_vector_get( vec_3, 2 ) )
354 Lang::Transform3D::Transform3D( const Lang::Transform3D & tf2, const Lang::Transform3D & tf1 )
355 : planeNormalTransformData_( 0 ),
356 xx_( tf2.xx_ * tf1.xx_ + tf2.xy_ * tf1.yx_ + tf2.xz_ * tf1.zx_ ),
357 yx_( tf2.yx_ * tf1.xx_ + tf2.yy_ * tf1.yx_ + tf2.yz_ * tf1.zx_ ),
358 zx_( tf2.zx_ * tf1.xx_ + tf2.zy_ * tf1.yx_ + tf2.zz_ * tf1.zx_ ),
359 xy_( tf2.xx_ * tf1.xy_ + tf2.xy_ * tf1.yy_ + tf2.xz_ * tf1.zy_ ),
360 yy_( tf2.yx_ * tf1.xy_ + tf2.yy_ * tf1.yy_ + tf2.yz_ * tf1.zy_ ),
361 zy_( tf2.zx_ * tf1.xy_ + tf2.zy_ * tf1.yy_ + tf2.zz_ * tf1.zy_ ),
362 xz_( tf2.xx_ * tf1.xz_ + tf2.xy_ * tf1.yz_ + tf2.xz_ * tf1.zz_ ),
363 yz_( tf2.yx_ * tf1.xz_ + tf2.yy_ * tf1.yz_ + tf2.yz_ * tf1.zz_ ),
364 zz_( tf2.zx_ * tf1.xz_ + tf2.zy_ * tf1.yz_ + tf2.zz_ * tf1.zz_ ),
365 xt_( tf2.xx_ * tf1.xt_ + tf2.xy_ * tf1.yt_ + tf2.xz_ * tf1.zt_ + tf2.xt_ ),
366 yt_( tf2.yx_ * tf1.xt_ + tf2.yy_ * tf1.yt_ + tf2.yz_ * tf1.zt_ + tf2.yt_ ),
367 zt_( tf2.zx_ * tf1.xt_ + tf2.zy_ * tf1.yt_ + tf2.zz_ * tf1.zt_ + tf2.zt_ )
370 DISPATCHIMPL( Transform3D );
372 Lang::Transform3D::~Transform3D( )
374 if( planeNormalTransformData_ != 0 )
376 gsl_matrix_free( planeNormalTransformData_ );
377 // delete planeNormalTransformData_;
381 Kernel::VariableHandle
382 Lang::Transform3D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
384 const size_t N = 3;
385 if( strcmp( fieldID, "p" ) == 0 )
387 return Helpers::newValHandle( new Lang::Coords3D( xt_, yt_, zt_ ) );
389 if( strcmp( fieldID, "L" ) == 0 )
391 return Helpers::newValHandle( new Lang::Transform3D( xx_, yx_, zx_, xy_, yy_, zy_, xz_, yz_, zz_, 0, 0, 0 ) );
393 if( strcmp( fieldID, "Lx" ) == 0 )
395 return Helpers::newValHandle( new Lang::FloatTriple( xx_, yx_, zx_ ) );
397 if( strcmp( fieldID, "Ly" ) == 0 )
399 return Helpers::newValHandle( new Lang::FloatTriple( xy_, yy_, zy_ ) );
401 if( strcmp( fieldID, "Lz" ) == 0 )
403 return Helpers::newValHandle( new Lang::FloatTriple( xz_, yz_, zz_ ) );
405 if( strcmp( fieldID, "xL" ) == 0 )
407 return Helpers::newValHandle( new Lang::FloatTriple( xx_, xy_, xz_ ) );
409 if( strcmp( fieldID, "yL" ) == 0 )
411 return Helpers::newValHandle( new Lang::FloatTriple( yx_, yy_, yz_ ) );
413 if( strcmp( fieldID, "zL" ) == 0 )
415 return Helpers::newValHandle( new Lang::FloatTriple( zx_, zy_, zz_ ) );
417 if( strcmp( fieldID, "linear?" ) == 0 )
419 return ( xt_ == 0 && yt_ == 0 && zt_ == 0 ) ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
421 if( strcmp( fieldID, "translation?" ) == 0 )
423 return isTranslation( ) ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
425 if( strcmp( fieldID, "special?" ) == 0 )
427 gsl_matrix * A = gsl_matrix_alloc( N, N );
428 gsl_permutation * perm = gsl_permutation_alloc( N );
429 int signum;
430 write_gsl_matrix( A );
431 gsl_linalg_LU_decomp( A, perm, & signum );
432 bool res = gsl_linalg_LU_det( A, signum ) > 0;
433 gsl_matrix_free( A );
434 gsl_permutation_free( perm );
435 return res ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
437 if( strcmp( fieldID, "Euclidean?" ) == 0 )
439 gsl_matrix * A = gsl_matrix_alloc( N, N );
440 gsl_vector * SVD_work = gsl_vector_alloc( N );
441 gsl_vector * sigma = gsl_vector_alloc( N );
442 gsl_matrix * V = gsl_matrix_alloc( N, N );
443 write_gsl_matrix( A );
444 gsl_linalg_SV_decomp( A, V, sigma, SVD_work );
445 const double tol = 1e-4;
446 bool res = 1 - tol < gsl_vector_get( sigma, N - 1 ) && gsl_vector_get( sigma, 0 ) < 1 + tol;
447 gsl_matrix_free( V );
448 gsl_vector_free( sigma );
449 gsl_vector_free( SVD_work );
450 gsl_matrix_free( A );
451 return res ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
454 return TypeID->getMethod( selfRef, fieldID ); /* This will throw if there is no such method. */
457 Lang::Transform3D *
458 Lang::Transform3D::clone( ) const
460 return new Transform3D( xx_, yx_, zx_,
461 xy_, yy_, zy_,
462 xz_, yz_, zz_,
463 xt_, yt_, zt_ );
466 bool
467 Lang::Transform3D::isIdentity( ) const
469 return
470 xt_ == Concrete::ZERO_LENGTH && yt_ == Concrete::ZERO_LENGTH && zt_ == Concrete::ZERO_LENGTH &&
471 xx_ == 1 && yy_ == 1 && zz_ == 1 &&
472 xy_ == 0 && xz_ == 0 && yx_ == 0 && yz_ == 0 && zx_ == 0 && zy_ == 0;
475 bool
476 Lang::Transform3D::isTranslation( ) const
478 return
479 xx_ == 1 && yy_ == 1 && zz_ == 1 &&
480 xy_ == 0 && xz_ == 0 &&
481 yx_ == 0 && yz_ == 0 &&
482 zx_ == 0 && zy_ == 0;
485 void
486 Lang::Transform3D::write_gsl_matrix( gsl_matrix * matrix_3_3 ) const
488 gsl_matrix_set( matrix_3_3, 0, 0, xx_ );
489 gsl_matrix_set( matrix_3_3, 1, 0, yx_ );
490 gsl_matrix_set( matrix_3_3, 2, 0, zx_ );
491 gsl_matrix_set( matrix_3_3, 0, 1, xy_ );
492 gsl_matrix_set( matrix_3_3, 1, 1, yy_ );
493 gsl_matrix_set( matrix_3_3, 2, 1, zy_ );
494 gsl_matrix_set( matrix_3_3, 0, 2, xz_ );
495 gsl_matrix_set( matrix_3_3, 1, 2, yz_ );
496 gsl_matrix_set( matrix_3_3, 2, 2, zz_ );
499 void
500 Lang::Transform3D::write_gsl_vector( gsl_vector * vec_3 ) const
502 gsl_vector_set( vec_3, 0, Concrete::Length::offtype( xt_ ) );
503 gsl_vector_set( vec_3, 1, Concrete::Length::offtype( yt_ ) );
504 gsl_vector_set( vec_3, 2, Concrete::Length::offtype( zt_ ) );
507 Concrete::UnitFloatTriple
508 Lang::Transform3D::transformPlaneUnitNormal( const Concrete::UnitFloatTriple & n ) const
510 const int N = 3;
511 // These statically allocated matrices will leak memory. They could be removed by using a static automaitc
512 // deallocator object. However, since they shall not be deleted by delete (but by gsl_matrix_free), we cannot
513 // us RefCountPtr< gsl_matrix >.
514 static gsl_matrix * a = gsl_matrix_alloc( N, N );
515 static gsl_matrix * v = gsl_matrix_alloc( N, N );
516 static gsl_vector * s = gsl_vector_alloc( N );
517 static gsl_vector * work = gsl_vector_alloc( N );
520 // static __CLPK_integer mn = N;
521 // static char jobuvt = 'A';
523 // static double a[ N * N ];
524 // static double u[ N * N ];
525 // static double vt[ N * N ];
526 // __CLPK_integer ldauvt = N;
527 // static double s[ N ];
528 // __CLPK_integer lwork;
529 // __CLPK_integer info;
531 // static __CLPK_doublereal * work = 0;
532 // static RefCountPtr< __CLPK_doublereal > workCleaner;
534 // if( work == 0 )
535 // {
536 // // Then we ask LAPACK how much workspace it wants, and then we assume that this number will not change
537 // // as we call DGESVD with other arguments.
539 // double tmpwork;
540 // lwork = -1;
541 // dgesvd_( & jobuvt, & jobuvt,
542 // & mn, & mn,
543 // reinterpret_cast< __CLPK_doublereal * >( & a ), & ldauvt,
544 // reinterpret_cast< __CLPK_doublereal * >( & s ),
545 // reinterpret_cast< __CLPK_doublereal * >( & u ), & ldauvt,
546 // reinterpret_cast< __CLPK_doublereal * >( & vt ), & ldauvt,
547 // reinterpret_cast< __CLPK_doublereal * >( & tmpwork ), & lwork,
548 // & info );
549 // lwork = static_cast< __CLPK_integer >( tmpwork );
550 // work = new __CLPK_doublereal[ lwork ];
551 // workCleaner = RefCountPtr< __CLPK_doublereal >( work );
552 // }
555 if( planeNormalTransformData_ == 0 )
557 // This is the first time this transform is used to transform a unit plane normal.
558 // The linear part of this transform must then be computed, and we use the singular
559 // value decomposition for this.
561 planeNormalTransformData_ = gsl_matrix_alloc( N, N );
563 write_gsl_matrix( a );
566 int status = gsl_linalg_SV_decomp( a, v, s, work );
567 if( status != 0 )
569 throw Exceptions::ExternalError( "Gnu Scientific Library SVD routine failed." );
573 // a[ 0 ] = xx_;
574 // a[ 1 ] = yx_;
575 // a[ 2 ] = zx_;
576 // a[ 3 ] = xy_;
577 // a[ 4 ] = yy_;
578 // a[ 5 ] = zy_;
579 // a[ 6 ] = xz_;
580 // a[ 7 ] = yz_;
581 // a[ 8 ] = zz_;
583 // dgesvd_( & jobuvt, & jobuvt,
584 // & mn, & mn,
585 // reinterpret_cast< __CLPK_doublereal * >( & a ), & ldauvt,
586 // reinterpret_cast< __CLPK_doublereal * >( & s ),
587 // reinterpret_cast< __CLPK_doublereal * >( & u ), & ldauvt,
588 // reinterpret_cast< __CLPK_doublereal * >( & vt ), & ldauvt,
589 // reinterpret_cast< __CLPK_doublereal * >( work ), & lwork,
590 // & info );
592 // if( info != 0 )
593 // {
594 // throw Exceptions::ExternalError( "LAPACK routine DGESVD failed." );
595 // }
597 if( gsl_vector_get( s, 1 ) < 1e-5 )
599 throw Exceptions::AffineTransformKillsPlane( gsl_vector_get( s, 1 ) );
602 gsl_vector_set( s, 0, gsl_vector_get( s, 2 ) / gsl_vector_get( s, 0 ) );
603 gsl_vector_set( s, 1, gsl_vector_get( s, 2 ) / gsl_vector_get( s, 1 ) );
604 // s[ 2 ] = 1;
606 // if( s[ 1 ] < 1e-5 )
607 // {
608 // throw Exceptions::AffineTransformKillsPlane( s[ 1 ] );
609 // }
611 // s[ 0 ] = s[ 2 ] / s[ 0 ];
612 // s[ 1 ] = s[ 2 ] / s[ 1 ];
613 // // s[ 2 ] = 1;
615 // We will now compute " u * diag( s ) * vt ".
617 // Note that "u" is stored in a when gsl_linalg_SV_decomp is used.
619 gsl_matrix_set( a, 0, 0, gsl_matrix_get( a, 0, 0 ) * gsl_vector_get( s, 0 ) );
620 gsl_matrix_set( a, 1, 0, gsl_matrix_get( a, 1, 0 ) * gsl_vector_get( s, 0 ) );
621 gsl_matrix_set( a, 2, 0, gsl_matrix_get( a, 2, 0 ) * gsl_vector_get( s, 0 ) );
622 gsl_matrix_set( a, 0, 1, gsl_matrix_get( a, 0, 1 ) * gsl_vector_get( s, 1 ) );
623 gsl_matrix_set( a, 1, 1, gsl_matrix_get( a, 1, 1 ) * gsl_vector_get( s, 1 ) );
624 gsl_matrix_set( a, 2, 1, gsl_matrix_get( a, 2, 1 ) * gsl_vector_get( s, 1 ) );
625 // Note that s[ 2 ] == 1
627 // u[ 0 ] *= s[ 0 ];
628 // u[ 1 ] *= s[ 0 ];
629 // u[ 2 ] *= s[ 0 ];
630 // u[ 3 ] *= s[ 1 ];
631 // u[ 4 ] *= s[ 1 ];
632 // u[ 5 ] *= s[ 1 ];
633 // // Note that s[ 2 ] == 1
635 gsl_blas_dgemm( CblasNoTrans,
636 CblasTrans,
641 planeNormalTransformData_ );
643 // cblas_dgemm( CblasColMajor, CblasNoTrans, CblasNoTrans,
644 // N, N, N,
645 // 1.,
646 // u, N,
647 // vt, N,
648 // 0., planeNormalTransformData_, N );
651 // Now that the linear, not too singular, transform has been computed, we just apply it and normalize the result.
652 // The normalization is made by the UnitFloatTriple constructor.
654 static gsl_vector * _n = gsl_vector_alloc( N );
655 static gsl_vector * res = gsl_vector_alloc( N );
657 // static double _n[ N ];
658 // static double res[ N ];
660 gsl_vector_set( _n, 0, n.x_ );
661 gsl_vector_set( _n, 1, n.y_ );
662 gsl_vector_set( _n, 2, n.z_ );
664 // _n[ 0 ] = n.x_;
665 // _n[ 1 ] = n.y_;
666 // _n[ 2 ] = n.z_;
668 gsl_blas_dgemv( CblasNoTrans,
670 planeNormalTransformData_,
673 res );
675 // cblas_dgemv( CblasColMajor, CblasNoTrans,
676 // N, N,
677 // 1.,
678 // planeNormalTransformData_, N,
679 // reinterpret_cast< double * >( & _n ), 1,
680 // 0., reinterpret_cast< double * >( & res ), 1 );
682 return Concrete::UnitFloatTriple( gsl_vector_get( res, 0 ),
683 gsl_vector_get( res, 1 ),
684 gsl_vector_get( res, 2 ) );
685 // return Concrete::UnitFloatTriple( res[0], res[1], res[2] );
689 // First we compute a unit vector in the plane
690 static const Concrete::UnitFloatTriple xHat( 1, 0, 0 );
691 static const Concrete::UnitFloatTriple yHat( 0, 1, 0 );
692 Concrete::UnitFloatTriple r1 = Shapes::cross( unitNormal_, xHat );
693 Concrete::UnitFloatTriple r2 = Shapes::cross( unitNormal_, yHat );
694 Concrete::UnitFloatTriple r( 0, 0, 0 );
695 if( r1.norm( ) > r2.norm( ) )
697 r = r1.normalized( );
699 else
701 r = r2.normalized( );
704 // Then we find one point that is in the plane
705 double ax = fabs( unitNormal_.x_ );
706 double ay = fabs( unitNormal_.y_ );
707 double az = fabs( unitNormal_.z_ );
709 Concrete::Coords3D x0( 0, 0, 0 );
710 if( ax >= ay && ax >= az )
712 x0 = Concrete::Coords3D( m_ / unitNormal_.x_, 0, 0 );
714 else if( ay >= az )
716 x0 = Concrete::Coords3D( 0, m_ / unitNormal_.y_, 0 );
718 else
720 x0 = Concrete::Coords3D( 0, 0, m_ / unitNormal_.z_ );
723 // Now it is easy to find two more points that span the plane together with x0
724 Concrete::Coords3D x1 = x0 + r;
725 Concrete::Coords3D x2 = x0 + Shapes::cross( unitNormal_, r );
727 // Now we see where these points go...
728 Concrete::Coords3D Tx0 = x0.transformed( tf );
729 Concrete::Coords3D Tx1 = x1.transformed( tf );
730 Concrete::Coords3D Tx2 = x2.transformed( tf );
732 // ... from which the new equation may be computed.
733 Concrete::UnitFloatTriple Tnormal = Shapes::cross( Tx1 - Tx0, Tx2 - Tx0 );
734 double TnormalNorm = Tnormal.norm( );
735 if( TnormalNorm == 0 )
737 // A polygon of lower dimension is invisible, so we may just return without pushing any triangles.
738 return;
740 Concrete::UnitFloatTriple TunitNormal = Tnormal * ( 1 / TnormalNorm );
744 void
745 Lang::Transform3D::show( std::ostream & os ) const
747 os << "[ ("
748 << xx_ << ", " << yx_ << ", " << zx_ << ") ("
749 << xy_ << ", " << yy_ << ", " << zy_ << ") ("
750 << xz_ << ", " << yz_ << ", " << zz_ << ") ("
751 << Lang::Length( xt_ ) << ", " << Lang::Length( yt_ ) << ", " << Lang::Length( zt_ ) << ") ]" ;
755 Kernel::Arguments::Arguments( const Kernel::EvaluatedFormals * formals )
756 : formals_( formals ), variables_( new Environment::ValueVector::ValueType ), dst_( 0 ),
757 hasSink_( formals_->formals_->hasSink( ) ),
758 dstEnd_( formals_->formals_->defaultExprs_.size( ) ),
759 isSink_( formals_->isSink_ ),
760 sinkArgList_( 0 ), sinkValues_( NullPtr< const Lang::SingleList >( ) ),
761 states_( new Environment::StateVector::ValueType ), stateDst_( 0 ),
762 mutatorSelf_( 0 )
764 if( hasSink_ )
766 sinkArgList_ = new Ast::ArgListExprs( false ); // This is not an expression-owner.
767 sinkValues_ = Lang::THE_CONS_NULL;
768 if( formals_->formals_->argumentOrder_->empty( ) )
770 // All arguments go in the sink.
771 dst_ = INT_MAX;
774 // Thinking of all the evaluated cuts, it actually makes some sense not to reserve memory here.
775 // variables_.reserve( formals_->argumentOrder_->size( ) );
776 // states_.reserve( formals_->stateOrder_->size( ) );
779 Kernel::Arguments::~Arguments( )
782 Kernel::Arguments
783 Kernel::Arguments::clone( ) const
785 CHECK(
786 if( ! states_->empty( ) )
788 throw Exceptions::InternalError( "Arguments with states may not be cloned." );
792 Kernel::Arguments res( formals_ );
794 res.variables_->reserve( variables_->size( ) );
796 typedef typeof *variables_ ListType;
797 for( ListType::const_iterator i = variables_->begin( ); i != variables_->end( ); ++i )
799 res.variables_->push_back( *i );
802 res.locations_ = locations_;
803 res.dst_ = dst_;
804 if( sinkArgList_ != 0 )
806 throw Exceptions::NotImplemented( "Cloning of arguments with sink." );
807 //res.sinkArgList_ = sinkArgList_->clone( );
808 res.sinkValues_ = sinkValues_;
811 return res;
815 void
816 Kernel::Arguments::addOrderedArgument( const Kernel::VariableHandle & arg, Ast::Expression * loc )
818 /* Recall that if there's a sink, this will be the last argument.
820 if( ! isSink_ &&
821 dst_ >= dstEnd_ )
823 /* If there is a sink, put it there. Otherwise, we have detected an arity mismatch, but to generate a good
824 * error message we don't throw the message from here, but rest assured that an error will be delivered in
825 * due time when applyDefaults is invoked.
827 if( hasSink_ )
829 sinkArgList_->orderedExprs_->push_back( loc );
830 sinkValues_ = RefCountPtr< Lang::SingleList >( new Lang::SingleListPair( arg, sinkValues_ ) );
832 else
834 variables_->push_back( arg );
835 locations_.push_back( loc );
836 ++dst_; // I'm not sure this is meaningful here...
839 else if( dst_ == variables_->size( ) )
841 variables_->push_back( arg );
842 locations_.push_back( loc );
843 ++dst_;
845 else
847 (*variables_)[ dst_ ] = arg;
848 locations_[ dst_ ] = loc;
849 while( dst_ < variables_->size( ) &&
850 (*variables_)[ dst_ ] != Kernel::THE_SLOT_VARIABLE )
852 ++dst_;
857 void
858 Kernel::Arguments::addNamedArgument( const char * id, const Kernel::VariableHandle & arg, Ast::Expression * loc )
860 if( formals_ == 0 )
862 throw Exceptions::CoreNoNamedFormals( "???" );
865 typedef typeof *(formals_->formals_->argumentOrder_) FormalsMapType;
866 FormalsMapType & formalsMap = *(formals_->formals_->argumentOrder_);
868 /* Note that the name of the sink is invisible, so referring to it is just another arguments which is
869 * put in the sink. This variable happens to have the same name as the sink.
871 FormalsMapType::const_iterator j = formalsMap.find( id );
872 if( j == formalsMap.end( ) ||
873 ( hasSink_ &&
874 j->second == dstEnd_ ) )
876 if( hasSink_ )
878 if( sinkArgList_->namedExprs_->find( id ) != sinkArgList_->namedExprs_->end( ) )
880 throw Exceptions::InternalError( "It is a surprise that the sink got a repeated formal." );
882 sinkArgList_->namedExprs_->insert( std::pair< const char *, Ast::Expression * >( id, loc ) );
883 sinkValues_ = RefCountPtr< Lang::SingleList >( new Lang::SingleListPair( arg, sinkValues_ ) );
884 return;
886 throw Exceptions::NamedFormalMismatch( formals_->formals_->loc( ), strrefdup( id ), Exceptions::NamedFormalMismatch::VARIABLE );
888 size_t pos = j->second;
890 if( pos < dst_ )
892 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::VARIABLE );
895 if( pos >= variables_->size( ) )
897 while( variables_->size( ) < pos )
899 variables_->push_back( Kernel::THE_SLOT_VARIABLE );
900 locations_.push_back( 0 );
902 variables_->push_back( arg );
903 locations_.push_back( loc );
905 else
907 if( (*variables_)[ pos ] != Kernel::THE_SLOT_VARIABLE )
909 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::VARIABLE );
911 (*variables_)[ pos ] = arg;
912 locations_[ pos ] = loc;
914 if( pos == dst_ )
916 while( dst_ < variables_->size( ) &&
917 (*variables_)[ dst_ ] != Kernel::THE_SLOT_VARIABLE )
919 ++dst_;
924 void
925 Kernel::Arguments::addOrderedState( const Kernel::StateHandle & state, Ast::Node * loc )
927 if( stateDst_ == states_->size( ) )
929 states_->push_back( state );
930 stateLocations_.push_back( loc );
931 ++stateDst_;
933 else
935 (*states_)[ stateDst_ ] = state;
936 stateLocations_[ stateDst_ ] = loc;
937 while( stateDst_ < states_->size( ) &&
938 (*states_)[ stateDst_ ] != Kernel::THE_SLOT_STATE )
940 ++stateDst_;
945 void
946 Kernel::Arguments::addNamedState( const char * id, const Kernel::StateHandle & state, Ast::Node * loc )
948 if( formals_ == 0 )
950 throw Exceptions::CoreNoNamedFormals( "???" );
953 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
954 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
956 FormalsMapType::const_iterator j = formalsMap.find( id );
957 if( j == formalsMap.end( ) )
959 throw Exceptions::NamedFormalMismatch( formals_->formals_->loc( ), strrefdup( id ), Exceptions::NamedFormalMismatch::STATE );
961 size_t pos = j->second;
963 if( pos < stateDst_ )
965 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::STATE );
968 if( pos >= states_->size( ) )
970 while( states_->size( ) < pos )
972 states_->push_back( Kernel::THE_SLOT_STATE );
973 stateLocations_.push_back( 0 );
975 states_->push_back( state );
976 stateLocations_.push_back( loc );
978 else
980 if( (*states_)[ pos ] != Kernel::THE_SLOT_STATE )
982 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::STATE );
984 (*states_)[ pos ] = state;
985 stateLocations_[ pos ] = loc;
987 if( pos == stateDst_ )
989 while( stateDst_ < states_->size( ) &&
990 (*states_)[ stateDst_ ] != Kernel::THE_SLOT_STATE )
992 ++stateDst_;
997 void
998 Kernel::Arguments::applyDefaults( )
1000 if( formals_ == 0 )
1002 return;
1005 size_t numberOfArguments = variables_->size( );
1006 size_t formalsSize = formals_->defaults_.size( );
1008 if( numberOfArguments > formalsSize &&
1009 ! hasSink_ )
1011 /* The location of the ball must be set by the caller. */
1012 throw Exceptions::UserArityMismatch( formals_->formals_->loc( ), formalsSize, numberOfArguments, Exceptions::UserArityMismatch::VARIABLE );
1015 size_t numberOfStates = states_->size( );
1016 size_t formalsStateSize = formals_->formals_->stateOrder_->size( );
1017 if( numberOfStates > formalsStateSize )
1019 /* The location of the ball must be set by the caller. */
1020 throw Exceptions::UserArityMismatch( formals_->formals_->loc( ), formalsStateSize, numberOfStates, Exceptions::UserArityMismatch::STATE );
1023 /* First the easy part: All states must be specified.
1025 std::map< size_t, RefCountPtr< const char > > * missingStates = 0;
1027 size_t pos = 0;
1028 typedef typeof *states_ ListType;
1029 for( ListType::const_iterator i = states_->begin( ); i != states_->end( ); ++i, ++pos )
1031 if( *i == Kernel::THE_SLOT_STATE )
1033 if( missingStates == 0 )
1035 missingStates = new typeof *missingStates;
1037 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
1038 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
1039 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
1041 if( i->second == pos )
1043 missingStates->insert( missingStates->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1044 break;
1046 ++i;
1047 if( i == formalsMap.end( ) )
1049 throw Exceptions::InternalError( "Failed to find position of missing state." );
1056 if( numberOfStates < formalsStateSize )
1058 if( missingStates == 0 )
1060 missingStates = new typeof *missingStates;
1062 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
1063 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
1064 FormalsMapType::const_iterator i = formalsMap.begin( );
1065 for( size_t j = 0; j < numberOfStates; ++j )
1067 ++i;
1070 for( ; i != formalsMap.end( ); ++i, ++pos)
1072 missingStates->insert( missingStates->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1078 /* Allocate positions in the vector for all arguments.
1080 variables_->reserve( hasSink_ ? formalsSize + 1 : formalsSize );
1081 while( variables_->size( ) < formalsSize )
1083 variables_->push_back( Kernel::THE_SLOT_VARIABLE );
1085 locations_.resize( formalsSize );
1087 typedef typeof *variables_ MyListType;
1088 typedef typeof formals_->defaults_ DefaultListType;
1089 typedef typeof formals_->locations_ LocationListType;
1090 DefaultListType::const_iterator src = formals_->defaults_.begin( );
1091 LocationListType::const_iterator srcLoc = formals_->locations_.begin( );
1092 std::map< size_t, RefCountPtr< const char > > * missingArgs = 0;
1093 size_t pos = 0;
1094 for( MyListType::iterator dst = variables_->begin( ); dst != variables_->end( ); ++dst, ++src, ++srcLoc, ++pos )
1096 if( *dst == Kernel::THE_SLOT_VARIABLE )
1098 /* Handle error situation.
1100 if( *src == Kernel::THE_SLOT_VARIABLE )
1102 if( missingArgs == 0 )
1104 missingArgs = new typeof *missingArgs;
1106 typedef typeof *(formals_->formals_->argumentOrder_) FormalsMapType;
1107 FormalsMapType & formalsMap = *(formals_->formals_->argumentOrder_);
1108 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
1110 if( i->second == pos )
1112 missingArgs->insert( missingArgs->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1113 break;
1115 ++i;
1116 if( i == formalsMap.end( ) )
1118 throw Exceptions::InternalError( "Failed to find position of missing argument." );
1123 /* Normal case.
1125 *dst = *src;
1126 locations_[ pos ] = *srcLoc;
1130 if( missingArgs != 0 || missingStates != 0 )
1132 throw Exceptions::MissingArguments( formals_->formals_->loc( ), missingArgs, missingStates );
1135 if( hasSink_ )
1137 variables_->push_back
1138 ( Helpers::newValHandle
1139 ( new Lang::Structure( sinkArgList_,
1140 sinkValues_,
1141 true ) ) ); // true means that the sinkArgList_ gets owned by the Structure.
1142 sinkArgList_ = 0;
1147 Kernel::VariableHandle &
1148 Kernel::Arguments::getHandle( size_t i )
1150 return (*variables_)[ i ];
1153 RefCountPtr< const Lang::Value > &
1154 Kernel::Arguments::getValue( size_t i )
1156 return (*variables_)[ i ]->getUntyped( );
1159 const Ast::SourceLocation &
1160 Kernel::Arguments::getLoc( size_t i ) const
1162 return locations_[ i ]->loc( );
1165 const Ast::Node *
1166 Kernel::Arguments::getNode( size_t i ) const
1168 return locations_[ i ];
1171 Kernel::Thunk *
1172 Kernel::Arguments::getThunk( size_t i )
1174 return (*variables_)[ i ]->copyThunk( );
1177 bool
1178 Kernel::Arguments::isSlot( size_t i ) const
1180 return (*variables_)[ i ] == Kernel::THE_SLOT_VARIABLE;
1183 Kernel::StateHandle
1184 Kernel::Arguments::getState( size_t i )
1186 return (*states_)[ i ];
1189 const Ast::SourceLocation &
1190 Kernel::Arguments::getStateLoc( size_t i ) const
1192 return stateLocations_[ i ]->loc( );
1195 size_t
1196 Kernel::Arguments::size( ) const
1198 return variables_->size( );
1201 bool
1202 Kernel::Arguments::empty( ) const
1204 return variables_->empty( );
1207 void
1208 Kernel::Arguments::setMutatorSelf( Kernel::StateHandle mutatorSelf )
1210 mutatorSelf_ = mutatorSelf;
1213 Kernel::StateHandle
1214 Kernel::Arguments::getMutatorSelf( )
1216 if( mutatorSelf_ == 0 )
1218 throw Exceptions::InternalError( "Kernel::Arguments::getMutatorSelf: self is null." );
1220 return mutatorSelf_;
1223 void
1224 Kernel::Arguments::gcMark( Kernel::GCMarkedSet & marked )
1227 typedef typeof *variables_ ListType;
1228 for( ListType::const_iterator i = variables_->begin( ); i != variables_->end( ); ++i )
1230 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1235 Kernel::Environment::ValueVector
1236 Kernel::Arguments::getVariables( )
1238 return variables_;
1241 Kernel::Environment::StateVector
1242 Kernel::Arguments::getStates( )
1244 return states_;
1248 namespace Shapes
1250 namespace Kernel
1253 class FunctionOneHandleCont : public Kernel::Continuation
1255 RefCountPtr< const Lang::Function > fun_;
1256 Kernel::PassedDyn dyn_;
1257 Kernel::ContRef cont_;
1258 public:
1259 FunctionOneHandleCont( const RefCountPtr< const Lang::Function > & fun, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1260 : Kernel::Continuation( traceLoc ), fun_( fun ), dyn_( dyn ), cont_( cont )
1262 virtual ~FunctionOneHandleCont( ) { }
1263 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
1265 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1266 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1269 if( val->isThunk( ) )
1271 val->force( val, evalState );
1272 return;
1275 Kernel::Arguments args = fun_->newCurriedArguments( );
1276 args.addOrderedArgument( val, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1278 evalState->dyn_ = dyn_;
1279 evalState->cont_ = cont_;
1280 fun_->call( evalState, args, traceLoc_ );
1282 virtual Kernel::ContRef up( ) const
1284 return cont_;
1286 virtual RefCountPtr< const char > description( ) const
1288 return strrefdup( "internal function call with one handle" );
1290 virtual void gcMark( Kernel::GCMarkedSet & marked )
1292 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1293 dyn_->gcMark( marked );
1294 cont_->gcMark( marked );
1298 class FunctionTwoHandlesCont_2 : public Kernel::Continuation
1300 RefCountPtr< const Lang::Function > fun_;
1301 Kernel::VariableHandle arg1_;
1302 Kernel::PassedDyn dyn_;
1303 Kernel::ContRef cont_;
1304 public:
1305 FunctionTwoHandlesCont_2( const RefCountPtr< const Lang::Function > & fun, const Kernel::VariableHandle & arg1, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1306 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), dyn_( dyn ), cont_( cont )
1308 virtual ~FunctionTwoHandlesCont_2( ) { }
1309 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1311 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1312 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1315 if( arg2->isThunk( ) )
1317 arg2->force( arg2, evalState );
1318 return;
1321 Kernel::Arguments args = fun_->newCurriedArguments( );
1322 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1323 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1324 evalState->dyn_ = dyn_;
1325 evalState->cont_ = cont_;
1326 fun_->call( evalState, args, traceLoc_ );
1328 virtual Kernel::ContRef up( ) const
1330 return cont_;
1332 virtual RefCountPtr< const char > description( ) const
1334 return strrefdup( "internal function call with two handles, second" );
1336 virtual void gcMark( Kernel::GCMarkedSet & marked )
1338 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1339 dyn_->gcMark( marked );
1340 cont_->gcMark( marked );
1344 class FunctionTwoHandlesCont_1 : public Kernel::Continuation
1346 RefCountPtr< const Lang::Function > fun_;
1347 Kernel::VariableHandle arg2_;
1348 bool forceArg2_;
1349 Kernel::PassedDyn dyn_;
1350 Kernel::ContRef cont_;
1351 public:
1352 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 )
1353 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), dyn_( dyn ), cont_( cont )
1355 virtual ~FunctionTwoHandlesCont_1( ) { }
1356 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1358 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1359 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1362 if( arg1->isThunk( ) )
1364 arg1->force( arg1, evalState );
1365 return;
1368 if( forceArg2_ )
1370 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( fun_, arg1, dyn_, cont_, traceLoc_ ) );
1371 evalState->cont_ = newCont;
1372 newCont->takeHandle( arg2_, evalState );
1373 return;
1376 /* The second handle need not be forced
1378 Kernel::Arguments args = fun_->newCurriedArguments( );
1379 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1380 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1381 evalState->dyn_ = dyn_;
1382 evalState->cont_ = cont_;
1383 fun_->call( evalState, args, traceLoc_ );
1385 virtual Kernel::ContRef up( ) const
1387 return cont_;
1389 virtual RefCountPtr< const char > description( ) const
1391 return strrefdup( "internal function call with two handles, first" );
1393 virtual void gcMark( Kernel::GCMarkedSet & marked )
1395 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1396 dyn_->gcMark( marked );
1397 cont_->gcMark( marked );
1401 class FunctionTwoHandlesOneStateCont_2 : public Kernel::Continuation
1403 RefCountPtr< const Lang::Function > fun_;
1404 Kernel::VariableHandle arg1_;
1405 Kernel::StateHandle state_;
1406 Kernel::PassedDyn dyn_;
1407 Kernel::ContRef cont_;
1408 public:
1409 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 )
1410 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), state_( state ), dyn_( dyn ), cont_( cont )
1412 virtual ~FunctionTwoHandlesOneStateCont_2( ) { }
1413 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1415 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1416 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1419 if( arg2->isThunk( ) )
1421 arg2->force( arg2, evalState );
1422 return;
1425 Kernel::Arguments args = fun_->newCurriedArguments( );
1426 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1427 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1428 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1429 evalState->dyn_ = dyn_;
1430 evalState->cont_ = cont_;
1431 fun_->call( evalState, args, traceLoc_ );
1433 virtual Kernel::ContRef up( ) const
1435 return cont_;
1437 virtual RefCountPtr< const char > description( ) const
1439 return strrefdup( "internal function call with two handles and one state, second" );
1441 virtual void gcMark( Kernel::GCMarkedSet & marked )
1443 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1444 state_->gcMark( marked );
1445 dyn_->gcMark( marked );
1446 cont_->gcMark( marked );
1450 class FunctionTwoHandlesOneStateCont_1 : public Kernel::Continuation
1452 RefCountPtr< const Lang::Function > fun_;
1453 Kernel::VariableHandle arg2_;
1454 bool forceArg2_;
1455 Kernel::StateHandle state_;
1456 Kernel::PassedDyn dyn_;
1457 Kernel::ContRef cont_;
1458 public:
1459 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 )
1460 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), state_( state ), dyn_( dyn ), cont_( cont )
1462 virtual ~FunctionTwoHandlesOneStateCont_1( ) { }
1463 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1465 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1466 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1469 if( arg1->isThunk( ) )
1471 arg1->force( arg1, evalState );
1472 return;
1475 if( forceArg2_ )
1477 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( fun_, arg1, state_, dyn_, cont_, traceLoc_ ) );
1478 evalState->cont_ = newCont;
1479 newCont->takeHandle( arg2_, evalState );
1480 return;
1483 /* The second handle need not be forced
1485 Kernel::Arguments args = fun_->newCurriedArguments( );
1486 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1487 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1488 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1489 evalState->dyn_ = dyn_;
1490 evalState->cont_ = cont_;
1491 fun_->call( evalState, args, traceLoc_ );
1493 virtual Kernel::ContRef up( ) const
1495 return cont_;
1497 virtual RefCountPtr< const char > description( ) const
1499 return strrefdup( "internal function call with two handles and one state, first" );
1501 virtual void gcMark( Kernel::GCMarkedSet & marked )
1503 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1504 dyn_->gcMark( marked );
1505 cont_->gcMark( marked );
1506 state_->gcMark( marked );
1514 Lang::Function::Function( Kernel::EvaluatedFormals * formals )
1515 : formals_( formals )
1518 DISPATCHIMPL( Function );
1520 Lang::Function::~Function( )
1522 if( formals_ != 0 )
1524 delete formals_->formals_;
1525 delete formals_;
1529 Kernel::ValueRef
1530 Lang::Function::transformed( const Lang::Transform2D & tf, Kernel::ValueRef self ) const
1532 return Kernel::ValueRef( new Lang::TransformedFunction2D( tf, self.down_cast< const Lang::Function >( ) ) );
1535 void
1536 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Ast::SourceLocation & callLoc ) const
1538 Kernel::Arguments args = this->newCurriedArguments( );
1540 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1542 this->call( evalState, args, callLoc );
1545 void
1546 Lang::Function::analyze( Ast::Node * parent, Ast::AnalysisEnvironment * env )
1548 Ast::StateIDSet * freeStates = new Ast::StateIDSet;
1549 this->analyze_impl( parent, env, freeStates );
1550 if( ! freeStates->empty( ) )
1552 Ast::theAnalysisErrorsList.push_back( new Exceptions::IllegalFreeStates( parent->loc( ), freeStates, "this is a function" ) );
1554 else
1556 delete freeStates;
1560 void
1561 Lang::Function::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1563 throw Exceptions::InternalError( "A syntax function is not overriding the analyze method." );
1566 void
1567 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Kernel::ValueRef & arg2, const Ast::SourceLocation & callLoc ) const
1569 Kernel::Arguments args = this->newCurriedArguments( );
1571 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1572 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg2 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1574 this->call( evalState, args, callLoc );
1577 Ast::ArgListExprs * Lang::Function::oneExprArgList = new Ast::ArgListExprs( static_cast< size_t >( 1 ) );
1578 Ast::ArgListExprs * Lang::Function::twoExprsArgList = new Ast::ArgListExprs( static_cast< size_t >( 2 ) );
1580 void
1581 Lang::Function::call( const RefCountPtr< const Lang::Function > & selfRef, Kernel::EvalState * evalState, const Kernel::VariableHandle & arg1, const Ast::SourceLocation & callLoc ) const
1583 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::oneExprArgList, *evalState );
1585 if( info->force( 0 ) )
1587 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionOneHandleCont( selfRef, evalState->dyn_, evalState->cont_, callLoc ) );
1588 evalState->cont_ = cont;
1589 cont->takeHandle( arg1, evalState );
1590 return;
1593 /* The handle need not be forced
1595 Kernel::Arguments args = this->newCurriedArguments( );
1596 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1597 this->call( evalState, args, callLoc );
1600 void
1601 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
1603 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1605 /* Remember that arguments are ordered backwards!
1608 if( info->force( 1 ) )
1610 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_1( selfRef, arg2, info->force( 0 ), evalState->dyn_, evalState->cont_, callLoc ) );
1611 evalState->cont_ = cont;
1612 cont->takeHandle( arg1, evalState );
1613 return;
1616 if( info->force( 0 ) )
1618 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( selfRef, arg1, evalState->dyn_, evalState->cont_, callLoc ) );
1619 evalState->cont_ = cont;
1620 cont->takeHandle( arg2, evalState );
1621 return;
1624 /* None of the handles need to be forced
1626 Kernel::Arguments args = this->newCurriedArguments( );
1627 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1628 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1629 this->call( evalState, args, callLoc );
1632 void
1633 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
1635 /* I'm not quite sure if we should also put a dummy state argument in info...
1637 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1639 /* Remember that arguments are ordered backwards!
1642 if( info->force( 1 ) )
1644 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_1( selfRef, arg2, info->force( 0 ), state, evalState->dyn_, evalState->cont_, callLoc ) );
1645 evalState->cont_ = cont;
1646 cont->takeHandle( arg1, evalState );
1647 return;
1650 if( info->force( 0 ) )
1652 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( selfRef, arg1, state, evalState->dyn_, evalState->cont_, callLoc ) );
1653 evalState->cont_ = cont;
1654 cont->takeHandle( arg2, evalState );
1655 return;
1658 /* None of the handles need to be forced
1660 Kernel::Arguments args = this->newCurriedArguments( );
1661 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1662 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1663 args.addOrderedState( state, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1664 this->call( evalState, args, callLoc );
1668 RefCountPtr< Kernel::CallContInfo >
1669 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1671 return formals_->newCallContInfo( argList, evalState );
1674 RefCountPtr< Kernel::CallContInfo >
1675 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1677 return formals_->newCallContInfo( argList, evalState, curryArgs );
1680 Kernel::Arguments
1681 Lang::Function::newCurriedArguments( ) const
1683 return Kernel::Arguments( formals_ );
1687 RefCountPtr< const Lang::Class > Lang::Function::TypeID( new Lang::SystemFinalClass( strrefdup( "Function" ) ) );
1688 TYPEINFOIMPL( Function );
1690 Kernel::EvaluatedFormals::EvaluatedFormals( Kernel::Formals * formals )
1691 : selectiveForcing_( false ), forceAll_( false ), formals_( formals ), isSink_( true )
1694 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID * locationFileID )
1695 : selectiveForcing_( true ), formals_( 0 ), isSink_( true )
1697 Kernel::Formals * formals( new Kernel::Formals( ) );
1698 formals->setLoc( Ast::SourceLocation( locationFileID ) );
1699 formals_ = formals;
1702 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID * locationFileID, bool forceAll)
1703 : selectiveForcing_( false ), forceAll_( forceAll ), formals_( 0 ), isSink_( true )
1705 Kernel::Formals * formals( new Kernel::Formals( ) );
1706 formals->setLoc( Ast::SourceLocation( locationFileID ) );
1707 formals_ = formals;
1710 Kernel::EvaluatedFormals::~EvaluatedFormals( )
1712 /* Don't delete the orderedFormals, since we don't own it. A case for reference counting? */
1715 RefCountPtr< Kernel::CallContInfo >
1716 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1718 if( selectiveForcing_ )
1720 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList ) ) );
1722 else
1724 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1728 RefCountPtr< Kernel::CallContInfo >
1729 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1731 if( selectiveForcing_ )
1733 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList, curryArgs ) ) );
1735 else
1737 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1741 void
1742 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc, bool force )
1744 if( ! selectiveForcing_ )
1746 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function does not have selective forcing." );
1748 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1749 formals_->forcePos_.push_back( force );
1750 defaults_.push_back( defaultVal );
1751 locations_.push_back( loc );
1754 void
1755 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc )
1757 if( selectiveForcing_ )
1759 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function requires individual forcing specification." );
1761 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1762 formals_->forcePos_.push_back( forceAll_ );
1763 defaults_.push_back( defaultVal );
1764 locations_.push_back( loc );
1767 void
1768 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal, bool force )
1770 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION, force );
1773 void
1774 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal )
1776 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION );
1779 void
1780 Kernel::EvaluatedFormals::appendCoreStateFormal( const char * id )
1782 (*(formals_->stateOrder_))[ id ] = formals_->stateOrder_->size( );
1785 void
1786 Kernel::EvaluatedFormals::gcMark( Kernel::GCMarkedSet & marked )
1788 typedef typeof defaults_ ListType;
1789 for( ListType::const_iterator i = defaults_.begin( ); i != defaults_.end( ); ++i )
1791 if( *i != NullPtr< Kernel::Variable >( ) )
1793 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1799 Lang::CuteFunction::CuteFunction( RefCountPtr< const Lang::Function > callee, const Kernel::Arguments & someArgs )
1800 : Lang::Function( 0 ), callee_( callee), someArgs_( someArgs.clone( ) )
1803 Lang::CuteFunction::~CuteFunction( )
1806 RefCountPtr< Kernel::CallContInfo >
1807 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1809 return callee_->newCallContInfo( argList, evalState, someArgs_ );
1812 RefCountPtr< Kernel::CallContInfo >
1813 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1815 /* when we are the callee of a CuteFunction, our someArgs are part of that CuteFunction's someArgs, and hence curryArgs
1816 * contains everything that is to be passed to our callee.
1818 return callee_->newCallContInfo( argList, evalState, curryArgs );
1821 Kernel::Arguments
1822 Lang::CuteFunction::newCurriedArguments( ) const
1824 return someArgs_.clone( );
1827 void
1828 Lang::CuteFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1830 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1831 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.
1833 callee_->call( evalState, args, callLoc );
1836 bool
1837 Lang::CuteFunction::isTransforming( ) const
1839 return callee_->isTransforming( );
1842 void
1843 Lang::CuteFunction::gcMark( Kernel::GCMarkedSet & marked )
1845 const_cast< Lang::Function * >( callee_.getPtr( ) )->gcMark( marked );
1846 someArgs_.gcMark( marked );
1849 void
1850 Lang::CuteFunction::show( std::ostream & os ) const
1852 os << "< evaluated cut of: " ;
1853 callee_->show( os );
1854 os << " >" ;
1858 Lang::ComposedFunction::ComposedFunction( const RefCountPtr< const Lang::Function > & second, const RefCountPtr< const Lang::Function > & first )
1859 : Lang::Function( 0 ), second_( second ), first_( first )
1862 Lang::ComposedFunction::~ComposedFunction( )
1865 void
1866 Lang::ComposedFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1868 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1869 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.
1871 evalState->cont_ = Kernel::ContRef( new Kernel::ComposedFunctionCall_cont( second_, evalState->dyn_, evalState->cont_, callLoc ) );
1872 first_->call( evalState, args, callLoc );
1875 RefCountPtr< Kernel::CallContInfo >
1876 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1878 return first_->newCallContInfo( argList, evalState );
1881 RefCountPtr< Kernel::CallContInfo >
1882 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1884 return first_->newCallContInfo( argList, evalState, curryArgs );
1887 Kernel::Arguments
1888 Lang::ComposedFunction::newCurriedArguments( ) const
1890 return first_->newCurriedArguments( );
1893 bool
1894 Lang::ComposedFunction::isTransforming( ) const
1896 return second_->isTransforming( );
1899 void
1900 Lang::ComposedFunction::gcMark( Kernel::GCMarkedSet & marked )
1902 const_cast< Lang::Function * >( second_.getPtr( ) )->gcMark( marked );
1903 const_cast< Lang::Function * >( first_.getPtr( ) )->gcMark( marked );
1906 void
1907 Lang::ComposedFunction::show( std::ostream & os ) const
1909 os << "< composition: " ;
1910 second_->show( os );
1911 os << " () " ;
1912 first_->show( os );
1913 os << " >" ;
1917 namespace Shapes
1919 namespace Kernel
1921 class SpanThunks
1923 std::vector< Kernel::VariableHandle > thunks_;
1924 public:
1925 SpanThunks( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count )
1927 thunks_.reserve( 4 );
1928 thunks_.push_back( count );
1929 thunks_.push_back( step );
1930 thunks_.push_back( end );
1931 thunks_.push_back( begin );
1933 const Kernel::VariableHandle & operator [] ( size_t i ) const
1935 return thunks_[ i ];
1937 ~SpanThunks( )
1939 void gcMark( Kernel::GCMarkedSet & marked )
1941 typedef typeof thunks_ VecType;
1942 for( VecType::iterator i = thunks_.begin( ); i != thunks_.end( ); ++i )
1944 (*i)->gcMark( marked );
1949 class SpanForcingContinuation : public Continuation
1951 RefCountPtr< const Kernel::SpanThunks > thunks_;
1952 size_t i_;
1953 RefCountPtr< const Lang::SingleList > values_;
1954 RefCountPtr< const Lang::Value > last_;
1955 Kernel::ContRef cont_;
1956 public:
1957 SpanForcingContinuation( const RefCountPtr< const Kernel::SpanThunks > & thunks, size_t i, const RefCountPtr< const Lang::SingleList > & values, const RefCountPtr< const Lang::Value > & last, const Kernel::ContRef & cont, const Ast::SourceLocation & traceLoc )
1958 : Kernel::Continuation( traceLoc ), thunks_( thunks ), i_( i ), values_( values ), last_( last ), cont_( cont )
1960 ~SpanForcingContinuation( )
1962 static void finish( RefCountPtr< const Lang::SingleList > values, RefCountPtr< const Lang::Value > last, Kernel::EvalState * evalState, const Ast::SourceLocation & traceLoc )
1964 Kernel::Arguments args = Lang::THE_FUNCTION_RANGE->newCurriedArguments( );
1965 RefCountPtr< const Lang::SingleListPair > src = values.down_cast< const Lang::SingleListPair >( );
1966 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1967 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1968 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1969 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1970 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1971 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1972 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1973 Lang::Core_range::makeRange( "<span>", evalState, args, traceLoc, true, last );
1975 virtual void takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
1977 RefCountPtr< const Lang::SingleList > values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( val ) ), values_ ) );
1979 for( size_t i = i_ + 1; i < 4; ++i )
1981 const Kernel::VariableHandle & var = (*thunks_)[ i ];
1982 if( var->isThunk( ) )
1984 evalState->cont_ = Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_, i, values, last_, cont_, traceLoc_ ) );
1985 var->force( var, evalState );
1986 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, last_ ) );
1987 return;
1989 values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( var, values ) );
1991 evalState->cont_ = cont_;
1992 finish( values, last_, evalState, traceLoc_ );
1994 virtual Kernel::ContRef up( ) const
1996 return cont_;
1998 virtual RefCountPtr< const char > description( ) const
2000 std::ostringstream msg;
2001 msg << "force span parameter number " << i_ ;
2002 return strrefdup( msg );
2004 virtual void gcMark( Kernel::GCMarkedSet & marked )
2006 const_cast< Kernel::SpanThunks * >( thunks_.getPtr( ) )->gcMark( marked );
2007 const_cast< Lang::SingleList * >( values_.getPtr( ) )->gcMark( marked );
2008 const_cast< Lang::Value * >( last_.getPtr( ) )->gcMark( marked );
2009 cont_->gcMark( marked );
2015 RefCountPtr< const Lang::Class > Lang::Span::TypeID( new Lang::SystemFinalClass( strrefdup( "Span" ) ) );
2016 TYPEINFOIMPL( Span );
2018 Lang::Span::Span( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count )
2019 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<span>" ), true ) ),
2020 thunks_( new Kernel::SpanThunks( begin, end, step, count ) )
2022 formals_->appendEvaluatedCoreFormal( "last", Kernel::THE_SLOT_VARIABLE );
2025 Lang::Span::~Span( )
2028 void
2029 Lang::Span::gcMark( Kernel::GCMarkedSet & marked )
2031 const_cast< Kernel::SpanThunks * >( thunks_.getPtr( ) )->gcMark( marked );
2034 void
2035 Lang::Span::show( std::ostream & os ) const
2037 os << "<span>" ;
2040 void
2041 Lang::Span::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2043 args.applyDefaults( );
2045 RefCountPtr< const Lang::SingleList > values = Lang::THE_CONS_NULL;
2046 for( size_t i = 0; i < 4; ++i )
2048 const Kernel::VariableHandle & var = (*thunks_)[ i ];
2049 if( var->isThunk( ) )
2051 evalState->cont_ = Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_, i, values, args.getValue( 0 ), evalState->cont_, callLoc ) );
2052 var->force( var, evalState );
2053 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, args.getValue( 0 ) ) );
2054 return;
2056 values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( var, values ) );
2059 /* We only reach this point if there were no thunks at all to be forced. */
2060 Kernel::SpanForcingContinuation::finish( values, args.getValue( 0 ), evalState, callLoc );
2063 bool
2064 Lang::Span::isTransforming( ) const
2066 return false;
2070 Lang::UserFunction::UserFunction( Kernel::EvaluatedFormals * formals, Ast::Expression * body, Kernel::PassedEnv env, const Ast::FunctionMode & functionMode )
2071 : Lang::Function( formals ), body_( body ), env_( env ), functionMode_( functionMode )
2074 // DISPATCHIMPL( UserFunction );
2076 Lang::UserFunction::~UserFunction( )
2078 // Note that we don't delete the things that we most likely share with other objects
2079 // Reference counting could be used here, but there will never be more such things than there are function expressions in the source
2081 // This prevents formals->formals from being deleted by Lang::Function::~Function
2082 delete formals_;
2083 formals_ = 0;
2086 void
2087 Lang::UserFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2089 args.applyDefaults( );
2090 evalState->env_ = new Kernel::Environment( Kernel::theEnvironmentList, env_, formals_->formals_->argumentIdentifiers_, args.getVariables( ), formals_->formals_->stateIdentifiers_, args.getStates( ), "Closure" );
2091 evalState->expr_ = body_;
2094 bool
2095 Lang::UserFunction::isTransforming( ) const
2097 return ( functionMode_ & Ast::FUNCTION_TRANSFORMING ) != 0;
2100 void
2101 Lang::UserFunction::gcMark( Kernel::GCMarkedSet & marked )
2103 env_->gcMark( marked );
2106 Ast::Expression *
2107 Lang::UserFunction::body( )
2109 return body_;
2112 void
2113 Lang::UserFunction::show( std::ostream & os ) const
2115 os << "< user function with body at " << body_->loc( ) << " >" ;
2119 Lang::TransformedFunction2D::TransformedFunction2D( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Function > & fun )
2120 : Lang::Function( 0 ), tf_( tf ), fun_( fun )
2123 Lang::TransformedFunction2D::~TransformedFunction2D( )
2126 void
2127 Lang::TransformedFunction2D::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2129 evalState->cont_ = Kernel::ContRef( new Kernel::Transform2DCont( tf_, evalState->cont_, 0 ) );
2130 fun_->call( evalState, args, callLoc );
2133 bool
2134 Lang::TransformedFunction2D::isTransforming( ) const
2136 return fun_->isTransforming( );
2139 void
2140 Lang::TransformedFunction2D::gcMark( Kernel::GCMarkedSet & marked )
2142 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
2145 void
2146 Lang::TransformedFunction2D::show( std::ostream & os ) const
2148 os << "< transformed function >" ;
2153 Lang::VectorFunction::VectorFunction( const std::vector< Kernel::ValueRef > * mem )
2154 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<vector>" ), true ) ), mem_( mem ),
2155 memNumeric_( NullPtr< const std::vector< double > >( ) ),
2156 list_( NullPtr< Kernel::Variable >( ) )
2158 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
2161 // DISPATCHIMPL( VectorFunction );
2163 Lang::VectorFunction::~VectorFunction( )
2166 RefCountPtr< const Lang::Class > Lang::VectorFunction::TypeID( new Lang::SystemFinalClass( strrefdup( "VectorFunction" ), Kernel::VectorFunction_register_methods ) );
2167 TYPEINFOIMPL( VectorFunction );
2169 Kernel::VariableHandle
2170 Lang::VectorFunction::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
2172 if( strcmp( fieldID, "size" ) == 0 )
2174 return Helpers::newValHandle( new Lang::Integer( mem_->size( ) ) );
2176 if( strcmp( fieldID, "range" ) == 0 )
2178 return Helpers::newValHandle( new Lang::SingleListRange< Lang::Integer >( 0, 1, mem_->size( ) ) );
2180 if( strcmp( fieldID, "reverse_range" ) == 0 )
2182 return Helpers::newValHandle( new Lang::SingleListRange< Lang::Integer >( mem_->size( ) - 1, -1, mem_->size( ) ) );
2184 if( strcmp( fieldID, "list" ) == 0 )
2186 compute_list( );
2187 return list_;
2190 return TypeID->getMethod( selfRef, fieldID ); /* This will throw if there is no such method. */
2193 const char * Lang::VectorFunction::title_ = "<vector>";
2195 void
2196 Lang::VectorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2198 const size_t ARITY = 1;
2199 if( args.size( ) != ARITY )
2201 throw Exceptions::CoreArityMismatch( title_, ARITY, args.size( ) );
2204 typedef const Lang::Integer ArgType;
2205 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
2207 if( arg->val_ < 0 )
2209 throw Exceptions::CoreOutOfRange( title_, args, 0, "Index is negative." );
2212 if( arg->val_ >= static_cast< int >( mem_->size( ) ) )
2214 throw Exceptions::CoreOutOfRange( title_, args, 0, "Index exceeds vector size." );
2217 Kernel::ContRef cont = evalState->cont_;
2218 cont->takeValue( (*mem_)[ arg->val_ ],
2219 evalState );
2222 bool
2223 Lang::VectorFunction::isTransforming( ) const
2225 return false;
2228 void
2229 Lang::VectorFunction::gcMark( Kernel::GCMarkedSet & marked )
2231 gcMark( mem_, marked );
2234 void
2235 Lang::VectorFunction::gcMark( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, Kernel::GCMarkedSet & marked )
2237 for( std::vector< Kernel::ValueRef >::const_iterator i = mem->begin( ); i != mem->end( ); ++i )
2239 const_cast< Lang::Value * >( i->getPtr( ) )->gcMark( marked );
2243 void
2244 Lang::VectorFunction::show( std::ostream & os ) const
2246 os << "< vector function >" ;
2249 RefCountPtr< const std::vector< double > >
2250 Lang::VectorFunction::getNumeric( const Ast::SourceLocation & callLoc ) const
2252 if( memNumeric_ == NullPtr< const std::vector< double > >( ) )
2254 RefCountPtr< std::vector< double > > res( new std::vector< double > ); // Note that this is not const, so far...
2255 res->reserve( mem_->size( ) );
2256 typedef typeof *mem_ SrcType;
2257 for( SrcType::const_iterator src = mem_->begin( ); src != mem_->end( ); ++src )
2259 res->push_back( Helpers::down_cast< const Lang::Float >( *src, callLoc )->val_ );
2262 memNumeric_ = res;
2264 return memNumeric_;
2267 void
2268 Lang::VectorFunction::compute_list( ) const
2270 if( list_ != NullPtr< Kernel::Variable >( ) )
2272 return;
2274 RefCountPtr< const Lang::SingleList > newList = Lang::THE_CONS_NULL;
2275 typedef typeof *mem_ ListType;
2276 for( ListType::const_reverse_iterator src = mem_->rbegin( ); src != mem_->rend( ); ++src )
2278 newList = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( *src ) ), newList ) );
2280 list_ = Kernel::VariableHandle( new Kernel::Variable( newList ) );
2283 namespace Shapes
2285 namespace Kernel
2288 class VectorFunctionFoldLCont : public Kernel::Continuation
2290 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2291 RefCountPtr< const Lang::Function > op_;
2292 Shapes::Lang::VectorFunction::vector_type::const_iterator i_;
2293 Kernel::PassedDyn dyn_;
2294 Kernel::ContRef cont_;
2295 public:
2296 VectorFunctionFoldLCont( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, const RefCountPtr< const Lang::Function > & op, Shapes::Lang::VectorFunction::vector_type::const_iterator i, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
2297 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), dyn_( dyn ), cont_( cont )
2299 virtual ~VectorFunctionFoldLCont( ) { }
2300 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2302 evalState->dyn_ = dyn_;
2303 evalState->cont_ = cont_;
2304 Lang::VectorFunction::foldl( mem_, evalState, op_, val, i_, traceLoc_ );
2306 virtual Kernel::ContRef up( ) const
2308 return cont_;
2310 virtual RefCountPtr< const char > description( ) const
2312 return strrefdup( "VectorFunction's foldl" );
2314 virtual void gcMark( Kernel::GCMarkedSet & marked )
2316 Lang::VectorFunction::gcMark( mem_, marked );
2317 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2318 dyn_->gcMark( marked );
2319 cont_->gcMark( marked );
2323 class VectorFunctionFoldRCont : public Kernel::Continuation
2325 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2326 RefCountPtr< const Lang::Function > op_;
2327 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_;
2328 Kernel::PassedDyn dyn_;
2329 Kernel::ContRef cont_;
2330 public:
2331 VectorFunctionFoldRCont( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, const RefCountPtr< const Lang::Function > & op, Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
2332 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), dyn_( dyn ), cont_( cont )
2334 virtual ~VectorFunctionFoldRCont( ) { }
2335 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2337 evalState->dyn_ = dyn_;
2338 evalState->cont_ = cont_;
2339 Lang::VectorFunction::foldr( mem_, evalState, op_, val, i_, traceLoc_ );
2341 virtual Kernel::ContRef up( ) const
2343 return cont_;
2345 virtual RefCountPtr< const char > description( ) const
2347 return strrefdup( "VectorFunction's foldr" );
2349 virtual void gcMark( Kernel::GCMarkedSet & marked )
2351 Lang::VectorFunction::gcMark( mem_, marked );
2352 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2353 dyn_->gcMark( marked );
2354 cont_->gcMark( marked );
2358 class VectorFunctionFoldSLCont : public Kernel::Continuation
2360 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2361 RefCountPtr< const Lang::Function > op_;
2362 Shapes::Lang::VectorFunction::vector_type::const_iterator i_;
2363 Kernel::StateHandle state_;
2364 Kernel::PassedDyn dyn_;
2365 Kernel::ContRef cont_;
2366 public:
2367 VectorFunctionFoldSLCont( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, const RefCountPtr< const Lang::Function > & op, Shapes::Lang::VectorFunction::vector_type::const_iterator i, Kernel::StateHandle state, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
2368 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), state_( state ), dyn_( dyn ), cont_( cont )
2370 virtual ~VectorFunctionFoldSLCont( ) { }
2371 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2373 evalState->dyn_ = dyn_;
2374 evalState->cont_ = cont_;
2375 Lang::VectorFunction::foldsl( mem_, evalState, op_, val, state_, i_, traceLoc_ );
2377 virtual Kernel::ContRef up( ) const
2379 return cont_;
2381 virtual RefCountPtr< const char > description( ) const
2383 return strrefdup( "VectorFunction's foldsl" );
2385 virtual void gcMark( Kernel::GCMarkedSet & marked )
2387 Lang::VectorFunction::gcMark( mem_, marked );
2388 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2389 state_->gcMark( marked );
2390 dyn_->gcMark( marked );
2391 cont_->gcMark( marked );
2395 class VectorFunctionFoldSRCont : public Kernel::Continuation
2397 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2398 RefCountPtr< const Lang::Function > op_;
2399 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_;
2400 Kernel::StateHandle state_;
2401 Kernel::PassedDyn dyn_;
2402 Kernel::ContRef cont_;
2403 public:
2404 VectorFunctionFoldSRCont( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, const RefCountPtr< const Lang::Function > & op, Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i, Kernel::StateHandle state, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
2405 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), state_( state ), dyn_( dyn ), cont_( cont )
2407 virtual ~VectorFunctionFoldSRCont( ) { }
2408 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2410 evalState->dyn_ = dyn_;
2411 evalState->cont_ = cont_;
2412 Lang::VectorFunction::foldsr( mem_, evalState, op_, val, state_, i_, traceLoc_ );
2414 virtual Kernel::ContRef up( ) const
2416 return cont_;
2418 virtual RefCountPtr< const char > description( ) const
2420 return strrefdup( "VectorFunction's foldsr" );
2422 virtual void gcMark( Kernel::GCMarkedSet & marked )
2424 Lang::VectorFunction::gcMark( mem_, marked );
2425 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2426 state_->gcMark( marked );
2427 dyn_->gcMark( marked );
2428 cont_->gcMark( marked );
2435 void
2436 Lang::VectorFunction::foldl( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, vector_type::const_iterator i, const Ast::SourceLocation & callLoc )
2438 if( i == mem->end( ) )
2440 Kernel::ContRef cont = evalState->cont_;
2441 cont->takeHandle( nullResult,
2442 evalState );
2443 return;
2446 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2447 ++i;
2448 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldLCont( mem, op, i, evalState->dyn_, evalState->cont_, callLoc ) );
2450 op->call( op, evalState, nullResult, elem, callLoc );
2453 void
2454 Lang::VectorFunction::foldr( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, vector_type::const_reverse_iterator i, const Ast::SourceLocation & callLoc )
2456 if( i == mem->rend( ) )
2458 Kernel::ContRef cont = evalState->cont_;
2459 cont->takeHandle( nullResult,
2460 evalState );
2461 return;
2464 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2465 ++i;
2466 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldRCont( mem, op, i, evalState->dyn_, evalState->cont_, callLoc ) );
2468 op->call( op, evalState, nullResult, elem, callLoc );
2471 void
2472 Lang::VectorFunction::foldsl( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, vector_type::const_iterator i, const Ast::SourceLocation & callLoc )
2474 if( i == mem->end( ) )
2476 Kernel::ContRef cont = evalState->cont_;
2477 cont->takeHandle( nullResult,
2478 evalState );
2479 return;
2482 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2483 ++i;
2484 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldSLCont( mem, op, i, state, evalState->dyn_, evalState->cont_, callLoc ) );
2486 op->call( op, evalState, nullResult, elem, state, callLoc );
2489 void
2490 Lang::VectorFunction::foldsr( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, vector_type::const_reverse_iterator i, const Ast::SourceLocation & callLoc )
2492 if( i == mem->rend( ) )
2494 Kernel::ContRef cont = evalState->cont_;
2495 cont->takeHandle( nullResult,
2496 evalState );
2497 return;
2500 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2501 ++i;
2502 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldSRCont( mem, op, i, state, evalState->dyn_, evalState->cont_, callLoc ) );
2504 op->call( op, evalState, nullResult, elem, state, callLoc );
2508 const char * Lang::ColorInterpolator::title_ = "<color-interpolator>";
2510 Lang::ColorInterpolator::ColorInterpolator( const RefCountPtr< KeyContainer > & key,
2511 const RefCountPtr< RGBContainer > & RGBcolor,
2512 const RefCountPtr< GrayContainer > & graycolor,
2513 const RefCountPtr< CMYKContainer > & CMYKcolor,
2514 ColorType colorType)
2515 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( Lang::ColorInterpolator::title_ ), true ) ),
2516 key_( key ), RGBcolor_ ( RGBcolor ), graycolor_ ( graycolor ), CMYKcolor_ ( CMYKcolor ), colorType_(colorType)
2518 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
2521 Lang::ColorInterpolator::~ColorInterpolator( )
2524 Kernel::VariableHandle
2525 Lang::ColorInterpolator::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
2527 if( strcmp( fieldID, "low" ) == 0 )
2529 return Helpers::newValHandle( new Lang::Float( key_->front( ) ) );
2531 if( strcmp( fieldID, "high" ) == 0 )
2533 return Helpers::newValHandle( new Lang::Float( key_->back( ) ) );
2535 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
2539 template <class COLOR_TYPE, class COLOR_CONTAINER>
2540 void
2541 Lang::ColorInterpolator::callHelper( Kernel::EvalState * evalState,
2542 const RefCountPtr< COLOR_CONTAINER > & colorContainer,
2543 double key, KeyContainer::const_iterator keyHi ) const
2545 if( keyHi == key_->end( ) )
2547 Kernel::ContRef cont = evalState->cont_;
2548 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->back( ) ) ),
2549 evalState );
2550 return;
2553 if( keyHi == key_->begin( ) )
2555 Kernel::ContRef cont = evalState->cont_;
2556 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->front( ) ) ),
2557 evalState );
2558 return;
2561 KeyContainer::const_iterator keyLo = keyHi - 1;
2562 double rem = ( key - *keyLo ) / ( *keyHi - *keyLo );
2564 Kernel::ContRef cont = evalState->cont_;
2566 typename COLOR_CONTAINER::const_iterator colorHi = colorContainer->begin( ) + ( keyHi - key_->begin( ) );
2567 typename COLOR_CONTAINER::const_iterator colorLo = colorHi - 1;
2569 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorLo->mulNoCheck( 1 - rem ).addNoCheck( colorHi->mulNoCheck( rem ) ) ) ),
2570 evalState );
2574 void
2575 Lang::ColorInterpolator::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2577 const size_t ARITY = 1;
2578 if( args.size( ) != ARITY )
2580 throw Exceptions::CoreArityMismatch( title_, ARITY, args.size( ) );
2583 typedef const Lang::Float ArgType;
2584 double key = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc )->val_;
2586 KeyContainer::const_iterator keyHi = lower_bound( key_->begin( ), key_->end( ), key );
2587 switch( colorType_ )
2589 case RGB:
2590 callHelper< Lang::RGB >( evalState, RGBcolor_, key, keyHi );
2591 break;
2592 case GRAY:
2593 callHelper< Lang::Gray >( evalState, graycolor_, key, keyHi );
2594 break;
2595 case CMYK:
2596 callHelper< Lang::CMYK >( evalState, CMYKcolor_, key, keyHi );
2597 break;
2598 case UNDEFINED:
2599 throw Exceptions::InternalError( "ColorInterpolator::call: Did not expect UNDEFINED in ennum switch." );
2603 bool
2604 Lang::ColorInterpolator::isTransforming( ) const
2606 return false;
2609 void
2610 Lang::ColorInterpolator::gcMark( Kernel::GCMarkedSet & marked )
2613 void
2614 Lang::ColorInterpolator::show( std::ostream & os ) const
2616 os << "< color interpolator in " ;
2617 switch( colorType_ )
2619 case RGB:
2620 os << "RGB" ;
2621 break;
2622 case GRAY:
2623 os << "Gray" ;
2624 break;
2625 case CMYK:
2626 os << "CMYK" ;
2627 break;
2628 case UNDEFINED:
2629 throw Exceptions::InternalError( "ColorInterpolator::show: Did not expect UNDEFINED in ennum switch." );
2631 os << " mode >" ;
2634 Lang::BinaryOperatorFunction::BinaryOperatorFunction( Ast::BinaryInfixExpr * opExpr, const char * title )
2635 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) ), opExpr_( opExpr ), title_( title )
2637 formals_->appendEvaluatedCoreFormal( "first", Kernel::THE_SLOT_VARIABLE );
2638 formals_->appendEvaluatedCoreFormal( "second", Kernel::THE_SLOT_VARIABLE );
2641 Lang::BinaryOperatorFunction::~BinaryOperatorFunction( )
2643 delete opExpr_;
2646 void
2647 Lang::BinaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2649 const size_t ARITY = 2;
2650 CHECK_ARITY( args, ARITY, title_ );
2651 RefCountPtr< const Lang::Value > arg1 = args.getValue( 0 );
2652 RefCountPtr< const Lang::Value > arg2 = args.getValue( 1 );
2656 Kernel::ContRef cont = evalState->cont_;
2657 cont->takeValue( arg1->binaryDispatch1( arg1, arg2, evalState->dyn_, opExpr_ ),
2658 evalState );
2660 catch( Exceptions::BinaryInfixNotApplicable & ball )
2662 ball.setOperatorSymbol( title_ );
2663 throw;
2667 bool
2668 Lang::BinaryOperatorFunction::isTransforming( ) const
2670 return false;
2673 void
2674 Lang::BinaryOperatorFunction::show( std::ostream & os ) const
2676 os << "< binary operator function for " << title_ << " >" ;
2680 Lang::UnaryOperatorFunction::UnaryOperatorFunction( Ast::UnaryExpr * opExpr, const char * title )
2681 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) ), opExpr_( opExpr ), title_( title )
2683 formals_->appendEvaluatedCoreFormal( "only", Kernel::THE_SLOT_VARIABLE );
2686 Lang::UnaryOperatorFunction::~UnaryOperatorFunction( )
2688 delete opExpr_;
2691 void
2692 Lang::UnaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2694 const size_t ARITY = 1;
2695 CHECK_ARITY( args, ARITY, title_ );
2697 RefCountPtr< const Lang::Value > arg = args.getValue( 0 );
2701 Kernel::ContRef cont = evalState->cont_;
2702 cont->takeValue( arg->unaryDispatch( arg, evalState->dyn_, opExpr_ ),
2703 evalState );
2705 catch( Exceptions::UnaryPrefixNotApplicable & ball )
2707 ball.setOperatorSymbol( title_ );
2708 throw;
2710 catch( Exceptions::UnaryPostfixNotApplicable & ball )
2712 ball.setOperatorSymbol( title_ );
2713 throw;
2717 bool
2718 Lang::UnaryOperatorFunction::isTransforming( ) const
2720 return false;
2723 void
2724 Lang::UnaryOperatorFunction::show( std::ostream & os ) const
2726 os << "< unary operator function for " << title_ << " >" ;
2730 Lang::Transform2DMethod_chop::Transform2DMethod_chop( RefCountPtr< const Lang::Transform2D > self, const Ast::FileID * fullMethodID )
2731 : Lang::MethodBase< class_type >( self, fullMethodID, false, true )
2733 formals_->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE );
2734 formals_->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE );
2737 Lang::Transform2DMethod_chop::~Transform2DMethod_chop( )
2740 void
2741 Lang::Transform2DMethod_chop::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2743 args.applyDefaults( );
2745 size_t argsi = 0;
2746 double Ltol = Helpers::down_cast_CoreArgument< const Lang::Float >( title_, args, argsi, callLoc )->val_;
2747 if( Ltol < 0 )
2749 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2752 ++argsi;
2753 Concrete::Length ptol = Helpers::down_cast_CoreArgument< const Lang::Length >( title_, args, argsi, callLoc )->get( );
2754 if( ptol < Concrete::ZERO_LENGTH )
2756 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2759 Lang::Transform2D * res = self_->clone( );
2761 CHOP_Ltol( res->xx_ );
2762 CHOP_Ltol( res->yx_ );
2764 CHOP_Ltol( res->xy_ );
2765 CHOP_Ltol( res->yy_ );
2767 CHOP_ptol( res->xt_ );
2768 CHOP_ptol( res->yt_ );
2770 Kernel::ContRef cont = evalState->cont_;
2771 cont->takeValue( RefCountPtr< const Lang::Value >( res ),
2772 evalState );
2776 Lang::Transform3DMethod_chop::Transform3DMethod_chop( RefCountPtr< const Lang::Transform3D > self, const Ast::FileID * fullMethodID )
2777 : Lang::MethodBase< class_type >( self, fullMethodID, false, true )
2779 formals_->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE );
2780 formals_->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE );
2783 Lang::Transform3DMethod_chop::~Transform3DMethod_chop( )
2786 void
2787 Lang::Transform3DMethod_chop::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2789 args.applyDefaults( );
2791 size_t argsi = 0;
2792 double Ltol = Helpers::down_cast_CoreArgument< const Lang::Float >( title_, args, argsi, callLoc )->val_;
2793 if( Ltol < 0 )
2795 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2798 ++argsi;
2799 Concrete::Length ptol = Helpers::down_cast_CoreArgument< const Lang::Length >( title_, args, argsi, callLoc )->get( );
2800 if( ptol < Concrete::ZERO_LENGTH )
2802 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2805 Lang::Transform3D * res = self_->clone( );
2807 CHOP_Ltol( res->xx_ );
2808 CHOP_Ltol( res->yx_ );
2809 CHOP_Ltol( res->zx_ );
2811 CHOP_Ltol( res->xy_ );
2812 CHOP_Ltol( res->yy_ );
2813 CHOP_Ltol( res->zy_ );
2815 CHOP_Ltol( res->xz_ );
2816 CHOP_Ltol( res->yz_ );
2817 CHOP_Ltol( res->zz_ );
2819 CHOP_ptol( res->xt_ );
2820 CHOP_ptol( res->yt_ );
2821 CHOP_ptol( res->zt_ );
2823 Kernel::ContRef cont = evalState->cont_;
2824 cont->takeValue( RefCountPtr< const Lang::Value >( res ),
2825 evalState );