Example: Changed glyph-outline.shape for use with FontConfig.
[shapes.git] / source / functiontypes.cc
blob169c8855fe1a0fe1868ecf1abe25aae1c19b1d5f
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 void
301 Lang::Transform2D::show( std::ostream & os ) const
303 os << "[ ("
304 << xx_ << ", " << yx_ << ") ("
305 << xy_ << ", " << yy_ << ") ("
306 << Lang::Length( xt_ ) << ", " << Lang::Length( yt_ ) << ") ]" ;
310 void
311 Transform3D_register_methods( Lang::SystemFinalClass * dstClass )
313 dstClass->registerMethod( new Kernel::MethodFactory< Lang::Transform3D, Lang::Transform3DMethod_chop >( ) );
316 RefCountPtr< const Lang::Class > Lang::Transform3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Transform3D" ), Transform3D_register_methods ) );
317 TYPEINFOIMPL( Transform3D );
319 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 )
320 : planeNormalTransformData_( 0 ),
321 xx_( xx ), yx_( yx ), zx_( zx ), xy_( xy ), yy_( yy ), zy_( zy ), xz_( xz ), yz_( yz ), zz_( zz ), xt_( xt ), yt_( yt ), zt_( zt )
324 Lang::Transform3D::Transform3D( const gsl_matrix * matrix_3_3, const gsl_vector * vec_3 )
325 : planeNormalTransformData_( 0 ),
326 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 ) ),
327 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 ) ),
328 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 ) ),
329 xt_( gsl_vector_get( vec_3, 0 ) ), yt_( gsl_vector_get( vec_3, 1 ) ), zt_( gsl_vector_get( vec_3, 2 ) )
334 Lang::Transform3D::Transform3D( const Lang::Transform3D & tf2, const Lang::Transform3D & tf1 )
335 : planeNormalTransformData_( 0 ),
336 xx_( tf2.xx_ * tf1.xx_ + tf2.xy_ * tf1.yx_ + tf2.xz_ * tf1.zx_ ),
337 yx_( tf2.yx_ * tf1.xx_ + tf2.yy_ * tf1.yx_ + tf2.yz_ * tf1.zx_ ),
338 zx_( tf2.zx_ * tf1.xx_ + tf2.zy_ * tf1.yx_ + tf2.zz_ * tf1.zx_ ),
339 xy_( tf2.xx_ * tf1.xy_ + tf2.xy_ * tf1.yy_ + tf2.xz_ * tf1.zy_ ),
340 yy_( tf2.yx_ * tf1.xy_ + tf2.yy_ * tf1.yy_ + tf2.yz_ * tf1.zy_ ),
341 zy_( tf2.zx_ * tf1.xy_ + tf2.zy_ * tf1.yy_ + tf2.zz_ * tf1.zy_ ),
342 xz_( tf2.xx_ * tf1.xz_ + tf2.xy_ * tf1.yz_ + tf2.xz_ * tf1.zz_ ),
343 yz_( tf2.yx_ * tf1.xz_ + tf2.yy_ * tf1.yz_ + tf2.yz_ * tf1.zz_ ),
344 zz_( tf2.zx_ * tf1.xz_ + tf2.zy_ * tf1.yz_ + tf2.zz_ * tf1.zz_ ),
345 xt_( tf2.xx_ * tf1.xt_ + tf2.xy_ * tf1.yt_ + tf2.xz_ * tf1.zt_ + tf2.xt_ ),
346 yt_( tf2.yx_ * tf1.xt_ + tf2.yy_ * tf1.yt_ + tf2.yz_ * tf1.zt_ + tf2.yt_ ),
347 zt_( tf2.zx_ * tf1.xt_ + tf2.zy_ * tf1.yt_ + tf2.zz_ * tf1.zt_ + tf2.zt_ )
350 DISPATCHIMPL( Transform3D );
352 Lang::Transform3D::~Transform3D( )
354 if( planeNormalTransformData_ != 0 )
356 gsl_matrix_free( planeNormalTransformData_ );
357 // delete planeNormalTransformData_;
361 Kernel::VariableHandle
362 Lang::Transform3D::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
364 const size_t N = 3;
365 if( strcmp( fieldID, "p" ) == 0 )
367 return Helpers::newValHandle( new Lang::Coords3D( xt_, yt_, zt_ ) );
369 if( strcmp( fieldID, "L" ) == 0 )
371 return Helpers::newValHandle( new Lang::Transform3D( xx_, yx_, zx_, xy_, yy_, zy_, xz_, yz_, zz_, 0, 0, 0 ) );
373 if( strcmp( fieldID, "Lx" ) == 0 )
375 return Helpers::newValHandle( new Lang::FloatTriple( xx_, yx_, zx_ ) );
377 if( strcmp( fieldID, "Ly" ) == 0 )
379 return Helpers::newValHandle( new Lang::FloatTriple( xy_, yy_, zy_ ) );
381 if( strcmp( fieldID, "Lz" ) == 0 )
383 return Helpers::newValHandle( new Lang::FloatTriple( xz_, yz_, zz_ ) );
385 if( strcmp( fieldID, "xL" ) == 0 )
387 return Helpers::newValHandle( new Lang::FloatTriple( xx_, xy_, xz_ ) );
389 if( strcmp( fieldID, "yL" ) == 0 )
391 return Helpers::newValHandle( new Lang::FloatTriple( yx_, yy_, yz_ ) );
393 if( strcmp( fieldID, "zL" ) == 0 )
395 return Helpers::newValHandle( new Lang::FloatTriple( zx_, zy_, zz_ ) );
397 if( strcmp( fieldID, "linear?" ) == 0 )
399 return ( xt_ == 0 && yt_ == 0 && zt_ == 0 ) ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
401 if( strcmp( fieldID, "translation?" ) == 0 )
403 return isTranslation( ) ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
405 if( strcmp( fieldID, "special?" ) == 0 )
407 gsl_matrix * A = gsl_matrix_alloc( N, N );
408 gsl_permutation * perm = gsl_permutation_alloc( N );
409 int signum;
410 write_gsl_matrix( A );
411 gsl_linalg_LU_decomp( A, perm, & signum );
412 bool res = gsl_linalg_LU_det( A, signum ) > 0;
413 gsl_matrix_free( A );
414 gsl_permutation_free( perm );
415 return res ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
417 if( strcmp( fieldID, "Euclidean?" ) == 0 )
419 gsl_matrix * A = gsl_matrix_alloc( N, N );
420 gsl_vector * SVD_work = gsl_vector_alloc( N );
421 gsl_vector * sigma = gsl_vector_alloc( N );
422 gsl_matrix * V = gsl_matrix_alloc( N, N );
423 write_gsl_matrix( A );
424 gsl_linalg_SV_decomp( A, V, sigma, SVD_work );
425 const double tol = 1e-4;
426 bool res = 1 - tol < gsl_vector_get( sigma, N - 1 ) && gsl_vector_get( sigma, 0 ) < 1 + tol;
427 gsl_matrix_free( V );
428 gsl_vector_free( sigma );
429 gsl_vector_free( SVD_work );
430 gsl_matrix_free( A );
431 return res ? Kernel::THE_TRUE_VARIABLE : Kernel::THE_FALSE_VARIABLE;
434 return TypeID->getMethod( selfRef, fieldID ); /* This will throw if there is no such method. */
437 Lang::Transform3D *
438 Lang::Transform3D::clone( ) const
440 return new Transform3D( xx_, yx_, zx_,
441 xy_, yy_, zy_,
442 xz_, yz_, zz_,
443 xt_, yt_, zt_ );
446 bool
447 Lang::Transform3D::isIdentity( ) const
449 return
450 xt_ == Concrete::ZERO_LENGTH && yt_ == Concrete::ZERO_LENGTH && zt_ == Concrete::ZERO_LENGTH &&
451 xx_ == 1 && yy_ == 1 && zz_ == 1 &&
452 xy_ == 0 && xz_ == 0 && yx_ == 0 && yz_ == 0 && zx_ == 0 && zy_ == 0;
455 bool
456 Lang::Transform3D::isTranslation( ) const
458 return
459 xx_ == 1 && yy_ == 1 && zz_ == 1 &&
460 xy_ == 0 && xz_ == 0 &&
461 yx_ == 0 && yz_ == 0 &&
462 zx_ == 0 && zy_ == 0;
465 void
466 Lang::Transform3D::write_gsl_matrix( gsl_matrix * matrix_3_3 ) const
468 gsl_matrix_set( matrix_3_3, 0, 0, xx_ );
469 gsl_matrix_set( matrix_3_3, 1, 0, yx_ );
470 gsl_matrix_set( matrix_3_3, 2, 0, zx_ );
471 gsl_matrix_set( matrix_3_3, 0, 1, xy_ );
472 gsl_matrix_set( matrix_3_3, 1, 1, yy_ );
473 gsl_matrix_set( matrix_3_3, 2, 1, zy_ );
474 gsl_matrix_set( matrix_3_3, 0, 2, xz_ );
475 gsl_matrix_set( matrix_3_3, 1, 2, yz_ );
476 gsl_matrix_set( matrix_3_3, 2, 2, zz_ );
479 void
480 Lang::Transform3D::write_gsl_vector( gsl_vector * vec_3 ) const
482 gsl_vector_set( vec_3, 0, Concrete::Length::offtype( xt_ ) );
483 gsl_vector_set( vec_3, 1, Concrete::Length::offtype( yt_ ) );
484 gsl_vector_set( vec_3, 2, Concrete::Length::offtype( zt_ ) );
487 Concrete::UnitFloatTriple
488 Lang::Transform3D::transformPlaneUnitNormal( const Concrete::UnitFloatTriple & n ) const
490 const int N = 3;
491 // These statically allocated matrices will leak memory. They could be removed by using a static automaitc
492 // deallocator object. However, since they shall not be deleted by delete (but by gsl_matrix_free), we cannot
493 // us RefCountPtr< gsl_matrix >.
494 static gsl_matrix * a = gsl_matrix_alloc( N, N );
495 static gsl_matrix * v = gsl_matrix_alloc( N, N );
496 static gsl_vector * s = gsl_vector_alloc( N );
497 static gsl_vector * work = gsl_vector_alloc( N );
500 // static __CLPK_integer mn = N;
501 // static char jobuvt = 'A';
503 // static double a[ N * N ];
504 // static double u[ N * N ];
505 // static double vt[ N * N ];
506 // __CLPK_integer ldauvt = N;
507 // static double s[ N ];
508 // __CLPK_integer lwork;
509 // __CLPK_integer info;
511 // static __CLPK_doublereal * work = 0;
512 // static RefCountPtr< __CLPK_doublereal > workCleaner;
514 // if( work == 0 )
515 // {
516 // // Then we ask LAPACK how much workspace it wants, and then we assume that this number will not change
517 // // as we call DGESVD with other arguments.
519 // double tmpwork;
520 // lwork = -1;
521 // dgesvd_( & jobuvt, & jobuvt,
522 // & mn, & mn,
523 // reinterpret_cast< __CLPK_doublereal * >( & a ), & ldauvt,
524 // reinterpret_cast< __CLPK_doublereal * >( & s ),
525 // reinterpret_cast< __CLPK_doublereal * >( & u ), & ldauvt,
526 // reinterpret_cast< __CLPK_doublereal * >( & vt ), & ldauvt,
527 // reinterpret_cast< __CLPK_doublereal * >( & tmpwork ), & lwork,
528 // & info );
529 // lwork = static_cast< __CLPK_integer >( tmpwork );
530 // work = new __CLPK_doublereal[ lwork ];
531 // workCleaner = RefCountPtr< __CLPK_doublereal >( work );
532 // }
535 if( planeNormalTransformData_ == 0 )
537 // This is the first time this transform is used to transform a unit plane normal.
538 // The linear part of this transform must then be computed, and we use the singular
539 // value decomposition for this.
541 planeNormalTransformData_ = gsl_matrix_alloc( N, N );
543 write_gsl_matrix( a );
545 // std::cerr << "Here's a:" << std::endl ;
546 // displayArray( std::cerr, a );
549 int status = gsl_linalg_SV_decomp( a, v, s, work );
550 if( status != 0 )
552 throw Exceptions::ExternalError( "Gnu Scientific Library SVD routine failed." );
556 // a[ 0 ] = xx_;
557 // a[ 1 ] = yx_;
558 // a[ 2 ] = zx_;
559 // a[ 3 ] = xy_;
560 // a[ 4 ] = yy_;
561 // a[ 5 ] = zy_;
562 // a[ 6 ] = xz_;
563 // a[ 7 ] = yz_;
564 // a[ 8 ] = zz_;
566 // dgesvd_( & jobuvt, & jobuvt,
567 // & mn, & mn,
568 // reinterpret_cast< __CLPK_doublereal * >( & a ), & ldauvt,
569 // reinterpret_cast< __CLPK_doublereal * >( & s ),
570 // reinterpret_cast< __CLPK_doublereal * >( & u ), & ldauvt,
571 // reinterpret_cast< __CLPK_doublereal * >( & vt ), & ldauvt,
572 // reinterpret_cast< __CLPK_doublereal * >( work ), & lwork,
573 // & info );
575 // if( info != 0 )
576 // {
577 // throw Exceptions::ExternalError( "LAPACK routine DGESVD failed." );
578 // }
580 if( gsl_vector_get( s, 1 ) < 1e-5 )
582 throw Exceptions::AffineTransformKillsPlane( gsl_vector_get( s, 1 ) );
585 // std::cerr << "Here's s:" << std::endl ;
586 // gsl_vector_fprintf( stderr, s, "%f" );
588 gsl_vector_set( s, 0, gsl_vector_get( s, 2 ) / gsl_vector_get( s, 0 ) );
589 gsl_vector_set( s, 1, gsl_vector_get( s, 2 ) / gsl_vector_get( s, 1 ) );
590 // s[ 2 ] = 1;
592 // std::cerr << "Here's the modified s:" << std::endl ;
593 // gsl_vector_fprintf( stderr, s, "%f" );
596 // if( s[ 1 ] < 1e-5 )
597 // {
598 // throw Exceptions::AffineTransformKillsPlane( s[ 1 ] );
599 // }
601 // s[ 0 ] = s[ 2 ] / s[ 0 ];
602 // s[ 1 ] = s[ 2 ] / s[ 1 ];
603 // // s[ 2 ] = 1;
605 // We will now compute " u * diag( s ) * vt ".
607 // Note that "u" is stored in a when gsl_linalg_SV_decomp is used.
609 // std::cerr << "Here's u:" << std::endl ;
610 // displayArray( std::cerr, a );
612 gsl_matrix_set( a, 0, 0, gsl_matrix_get( a, 0, 0 ) * gsl_vector_get( s, 0 ) );
613 gsl_matrix_set( a, 1, 0, gsl_matrix_get( a, 1, 0 ) * gsl_vector_get( s, 0 ) );
614 gsl_matrix_set( a, 2, 0, gsl_matrix_get( a, 2, 0 ) * gsl_vector_get( s, 0 ) );
615 gsl_matrix_set( a, 0, 1, gsl_matrix_get( a, 0, 1 ) * gsl_vector_get( s, 1 ) );
616 gsl_matrix_set( a, 1, 1, gsl_matrix_get( a, 1, 1 ) * gsl_vector_get( s, 1 ) );
617 gsl_matrix_set( a, 2, 1, gsl_matrix_get( a, 2, 1 ) * gsl_vector_get( s, 1 ) );
618 // Note that s[ 2 ] == 1
620 // u[ 0 ] *= s[ 0 ];
621 // u[ 1 ] *= s[ 0 ];
622 // u[ 2 ] *= s[ 0 ];
623 // u[ 3 ] *= s[ 1 ];
624 // u[ 4 ] *= s[ 1 ];
625 // u[ 5 ] *= s[ 1 ];
626 // // Note that s[ 2 ] == 1
628 // std::cerr << "Here's the modified a:" << std::endl ;
629 // displayArray( std::cerr, a );
631 // std::cerr << "Here's v:" << std::endl ;
632 // displayArray( std::cerr, v );
634 gsl_blas_dgemm( CblasNoTrans,
635 CblasTrans,
640 planeNormalTransformData_ );
642 // std::cerr << "Here's the matrix:" << std::endl ;
643 // displayArray( std::cerr, planeNormalTransformData_ );
645 // cblas_dgemm( CblasColMajor, CblasNoTrans, CblasNoTrans,
646 // N, N, N,
647 // 1.,
648 // u, N,
649 // vt, N,
650 // 0., planeNormalTransformData_, N );
653 // Now that the linear, not too singular, transform has been computed, we just apply it and normalize the result.
654 // The normalization is made by the UnitFloatTriple constructor.
656 static gsl_vector * _n = gsl_vector_alloc( N );
657 static gsl_vector * res = gsl_vector_alloc( N );
659 // static double _n[ N ];
660 // static double res[ N ];
662 gsl_vector_set( _n, 0, n.x_ );
663 gsl_vector_set( _n, 1, n.y_ );
664 gsl_vector_set( _n, 2, n.z_ );
666 // _n[ 0 ] = n.x_;
667 // _n[ 1 ] = n.y_;
668 // _n[ 2 ] = n.z_;
670 // std::cerr << "Input vector: " << std::endl ;
671 // gsl_vector_fprintf( stderr, _n, "%f" );
672 // std::cerr << std::endl ;
674 gsl_blas_dgemv( CblasNoTrans,
676 planeNormalTransformData_,
679 res );
681 // std::cerr << "Result: " << std::endl ;
682 // gsl_vector_fprintf( stderr, res, "%f" );
683 // std::cerr << std::endl ;
685 // cblas_dgemv( CblasColMajor, CblasNoTrans,
686 // N, N,
687 // 1.,
688 // planeNormalTransformData_, N,
689 // reinterpret_cast< double * >( & _n ), 1,
690 // 0., reinterpret_cast< double * >( & res ), 1 );
692 return Concrete::UnitFloatTriple( gsl_vector_get( res, 0 ),
693 gsl_vector_get( res, 1 ),
694 gsl_vector_get( res, 2 ) );
695 // return Concrete::UnitFloatTriple( res[0], res[1], res[2] );
699 // First we compute a unit vector in the plane
700 static const Concrete::UnitFloatTriple xHat( 1, 0, 0 );
701 static const Concrete::UnitFloatTriple yHat( 0, 1, 0 );
702 Concrete::UnitFloatTriple r1 = Shapes::cross( unitNormal_, xHat );
703 Concrete::UnitFloatTriple r2 = Shapes::cross( unitNormal_, yHat );
704 Concrete::UnitFloatTriple r( 0, 0, 0 );
705 if( r1.norm( ) > r2.norm( ) )
707 r = r1.normalized( );
709 else
711 r = r2.normalized( );
714 // Then we find one point that is in the plane
715 double ax = fabs( unitNormal_.x_ );
716 double ay = fabs( unitNormal_.y_ );
717 double az = fabs( unitNormal_.z_ );
719 Concrete::Coords3D x0( 0, 0, 0 );
720 if( ax >= ay && ax >= az )
722 x0 = Concrete::Coords3D( m_ / unitNormal_.x_, 0, 0 );
724 else if( ay >= az )
726 x0 = Concrete::Coords3D( 0, m_ / unitNormal_.y_, 0 );
728 else
730 x0 = Concrete::Coords3D( 0, 0, m_ / unitNormal_.z_ );
733 // Now it is easy to find two more points that span the plane together with x0
734 Concrete::Coords3D x1 = x0 + r;
735 Concrete::Coords3D x2 = x0 + Shapes::cross( unitNormal_, r );
737 // Now we see where these points go...
738 Concrete::Coords3D Tx0 = x0.transformed( tf );
739 Concrete::Coords3D Tx1 = x1.transformed( tf );
740 Concrete::Coords3D Tx2 = x2.transformed( tf );
742 // ... from which the new equation may be computed.
743 Concrete::UnitFloatTriple Tnormal = Shapes::cross( Tx1 - Tx0, Tx2 - Tx0 );
744 double TnormalNorm = Tnormal.norm( );
745 if( TnormalNorm == 0 )
747 // A polygon of lower dimension is invisible, so we may just return without pushing any triangles.
748 return;
750 Concrete::UnitFloatTriple TunitNormal = Tnormal * ( 1 / TnormalNorm );
754 void
755 Lang::Transform3D::show( std::ostream & os ) const
757 os << "[ ("
758 << xx_ << ", " << yx_ << ", " << zx_ << ") ("
759 << xy_ << ", " << yy_ << ", " << zy_ << ") ("
760 << xz_ << ", " << yz_ << ", " << zz_ << ") ("
761 << Lang::Length( xt_ ) << ", " << Lang::Length( yt_ ) << ", " << Lang::Length( zt_ ) << ") ]" ;
765 Kernel::Arguments::Arguments( const Kernel::EvaluatedFormals * formals )
766 : formals_( formals ), variables_( new Environment::ValueVector::ValueType ), dst_( 0 ),
767 hasSink_( formals_->formals_->hasSink( ) ),
768 dstEnd_( formals_->formals_->defaultExprs_.size( ) ),
769 isSink_( formals_->isSink_ ),
770 sinkArgList_( 0 ), sinkValues_( NullPtr< const Lang::SingleList >( ) ),
771 states_( new Environment::StateVector::ValueType ), stateDst_( 0 ),
772 mutatorSelf_( 0 )
774 if( hasSink_ )
776 sinkArgList_ = new Ast::ArgListExprs( false ); // This is not an expression-owner.
777 sinkValues_ = Lang::THE_CONS_NULL;
778 if( formals_->formals_->argumentOrder_->empty( ) )
780 // All arguments go in the sink.
781 dst_ = INT_MAX;
784 // Thinking of all the evaluated cuts, it actually makes some sense not to reserve memory here.
785 // variables_.reserve( formals_->argumentOrder_->size( ) );
786 // states_.reserve( formals_->stateOrder_->size( ) );
789 Kernel::Arguments::~Arguments( )
792 Kernel::Arguments
793 Kernel::Arguments::clone( ) const
795 CHECK(
796 if( ! states_->empty( ) )
798 throw Exceptions::InternalError( "Arguments with states may not be cloned." );
802 Kernel::Arguments res( formals_ );
804 res.variables_->reserve( variables_->size( ) );
806 typedef typeof *variables_ ListType;
807 for( ListType::const_iterator i = variables_->begin( ); i != variables_->end( ); ++i )
809 res.variables_->push_back( *i );
812 res.locations_ = locations_;
813 res.dst_ = dst_;
814 if( sinkArgList_ != 0 )
816 throw Exceptions::NotImplemented( "Cloning of arguments with sink." );
817 //res.sinkArgList_ = sinkArgList_->clone( );
818 res.sinkValues_ = sinkValues_;
821 return res;
825 void
826 Kernel::Arguments::addOrderedArgument( const Kernel::VariableHandle & arg, Ast::Expression * loc )
828 /* Recall that if there's a sink, this will be the last argument.
830 if( ! isSink_ &&
831 dst_ >= dstEnd_ )
833 /* If there is a sink, put it there. Otherwise, we have detected an arity mismatch, but to generate a good
834 * error message we don't throw the message from here, but rest assured that an error will be delivered in
835 * due time when applyDefaults is invoked.
837 if( hasSink_ )
839 sinkArgList_->orderedExprs_->push_back( loc );
840 sinkValues_ = RefCountPtr< Lang::SingleList >( new Lang::SingleListPair( arg, sinkValues_ ) );
842 else
844 variables_->push_back( arg );
845 locations_.push_back( loc );
846 ++dst_; // I'm not sure this is meaningful here...
849 else if( dst_ == variables_->size( ) )
851 variables_->push_back( arg );
852 locations_.push_back( loc );
853 ++dst_;
855 else
857 (*variables_)[ dst_ ] = arg;
858 locations_[ dst_ ] = loc;
859 while( dst_ < variables_->size( ) &&
860 (*variables_)[ dst_ ] != Kernel::THE_SLOT_VARIABLE )
862 ++dst_;
867 void
868 Kernel::Arguments::addNamedArgument( const char * id, const Kernel::VariableHandle & arg, Ast::Expression * loc )
870 if( formals_ == 0 )
872 throw Exceptions::CoreNoNamedFormals( "???" );
875 typedef typeof *(formals_->formals_->argumentOrder_) FormalsMapType;
876 FormalsMapType & formalsMap = *(formals_->formals_->argumentOrder_);
878 /* Note that the name of the sink is invisible, so referring to it is just another arguments which is
879 * put in the sink. This variable happens to have the same name as the sink.
881 FormalsMapType::const_iterator j = formalsMap.find( id );
882 if( j == formalsMap.end( ) ||
883 ( hasSink_ &&
884 j->second == dstEnd_ ) )
886 if( hasSink_ )
888 if( sinkArgList_->namedExprs_->find( id ) != sinkArgList_->namedExprs_->end( ) )
890 throw Exceptions::InternalError( "It is a surprise that the sink got a repeated formal." );
892 sinkArgList_->namedExprs_->insert( std::pair< const char *, Ast::Expression * >( id, loc ) );
893 sinkValues_ = RefCountPtr< Lang::SingleList >( new Lang::SingleListPair( arg, sinkValues_ ) );
894 return;
896 throw Exceptions::NamedFormalMismatch( formals_->formals_->loc( ), strrefdup( id ), Exceptions::NamedFormalMismatch::VARIABLE );
898 size_t pos = j->second;
900 if( pos < dst_ )
902 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::VARIABLE );
905 if( pos >= variables_->size( ) )
907 while( variables_->size( ) < pos )
909 variables_->push_back( Kernel::THE_SLOT_VARIABLE );
910 locations_.push_back( 0 );
912 variables_->push_back( arg );
913 locations_.push_back( loc );
915 else
917 if( (*variables_)[ pos ] != Kernel::THE_SLOT_VARIABLE )
919 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::VARIABLE );
921 (*variables_)[ pos ] = arg;
922 locations_[ pos ] = loc;
924 if( pos == dst_ )
926 while( dst_ < variables_->size( ) &&
927 (*variables_)[ dst_ ] != Kernel::THE_SLOT_VARIABLE )
929 ++dst_;
934 void
935 Kernel::Arguments::addOrderedState( const Kernel::StateHandle & state, Ast::Node * loc )
937 if( stateDst_ == states_->size( ) )
939 states_->push_back( state );
940 stateLocations_.push_back( loc );
941 ++stateDst_;
943 else
945 (*states_)[ stateDst_ ] = state;
946 stateLocations_[ stateDst_ ] = loc;
947 while( stateDst_ < states_->size( ) &&
948 (*states_)[ stateDst_ ] != Kernel::THE_SLOT_STATE )
950 ++stateDst_;
955 void
956 Kernel::Arguments::addNamedState( const char * id, const Kernel::StateHandle & state, Ast::Node * loc )
958 if( formals_ == 0 )
960 throw Exceptions::CoreNoNamedFormals( "???" );
963 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
964 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
966 FormalsMapType::const_iterator j = formalsMap.find( id );
967 if( j == formalsMap.end( ) )
969 throw Exceptions::NamedFormalMismatch( formals_->formals_->loc( ), strrefdup( id ), Exceptions::NamedFormalMismatch::STATE );
971 size_t pos = j->second;
973 if( pos < stateDst_ )
975 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::STATE );
978 if( pos >= states_->size( ) )
980 while( states_->size( ) < pos )
982 states_->push_back( Kernel::THE_SLOT_STATE );
983 stateLocations_.push_back( 0 );
985 states_->push_back( state );
986 stateLocations_.push_back( loc );
988 else
990 if( (*states_)[ pos ] != Kernel::THE_SLOT_STATE )
992 throw Exceptions::NamedFormalAlreadySpecified( formals_->formals_->loc( ), strrefdup( id ), pos, Exceptions::NamedFormalAlreadySpecified::STATE );
994 (*states_)[ pos ] = state;
995 stateLocations_[ pos ] = loc;
997 if( pos == stateDst_ )
999 while( stateDst_ < states_->size( ) &&
1000 (*states_)[ stateDst_ ] != Kernel::THE_SLOT_STATE )
1002 ++stateDst_;
1007 void
1008 Kernel::Arguments::applyDefaults( )
1010 if( formals_ == 0 )
1012 return;
1015 size_t numberOfArguments = variables_->size( );
1016 size_t formalsSize = formals_->defaults_.size( );
1018 if( numberOfArguments > formalsSize &&
1019 ! hasSink_ )
1021 /* The location of the ball must be set by the caller. */
1022 throw Exceptions::UserArityMismatch( formals_->formals_->loc( ), formalsSize, numberOfArguments, Exceptions::UserArityMismatch::VARIABLE );
1025 size_t numberOfStates = states_->size( );
1026 size_t formalsStateSize = formals_->formals_->stateOrder_->size( );
1027 if( numberOfStates > formalsStateSize )
1029 /* The location of the ball must be set by the caller. */
1030 throw Exceptions::UserArityMismatch( formals_->formals_->loc( ), formalsStateSize, numberOfStates, Exceptions::UserArityMismatch::STATE );
1033 /* First the easy part: All states must be specified.
1035 std::map< size_t, RefCountPtr< const char > > * missingStates = 0;
1037 size_t pos = 0;
1038 typedef typeof *states_ ListType;
1039 for( ListType::const_iterator i = states_->begin( ); i != states_->end( ); ++i, ++pos )
1041 if( *i == Kernel::THE_SLOT_STATE )
1043 if( missingStates == 0 )
1045 missingStates = new typeof *missingStates;
1047 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
1048 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
1049 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
1051 if( i->second == pos )
1053 missingStates->insert( missingStates->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1054 break;
1056 ++i;
1057 if( i == formalsMap.end( ) )
1059 throw Exceptions::InternalError( "Failed to find position of missing state." );
1066 if( numberOfStates < formalsStateSize )
1068 if( missingStates == 0 )
1070 missingStates = new typeof *missingStates;
1072 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
1073 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
1074 FormalsMapType::const_iterator i = formalsMap.begin( );
1075 for( size_t j = 0; j < numberOfStates; ++j )
1077 ++i;
1080 for( ; i != formalsMap.end( ); ++i, ++pos)
1082 missingStates->insert( missingStates->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1088 /* Allocate positions in the vector for all arguments.
1090 variables_->reserve( hasSink_ ? formalsSize + 1 : formalsSize );
1091 while( variables_->size( ) < formalsSize )
1093 variables_->push_back( Kernel::THE_SLOT_VARIABLE );
1095 locations_.resize( formalsSize );
1097 typedef typeof *variables_ MyListType;
1098 typedef typeof formals_->defaults_ DefaultListType;
1099 typedef typeof formals_->locations_ LocationListType;
1100 DefaultListType::const_iterator src = formals_->defaults_.begin( );
1101 LocationListType::const_iterator srcLoc = formals_->locations_.begin( );
1102 std::map< size_t, RefCountPtr< const char > > * missingArgs = 0;
1103 size_t pos = 0;
1104 typedef typeof locations_ MyLocationsType;
1105 for( MyListType::iterator dst = variables_->begin( ); dst != variables_->end( ); ++dst, ++src, ++srcLoc, ++pos )
1107 if( *dst == Kernel::THE_SLOT_VARIABLE )
1109 /* Handle error situation.
1111 if( *src == Kernel::THE_SLOT_VARIABLE )
1113 if( missingArgs == 0 )
1115 missingArgs = new typeof *missingArgs;
1117 typedef typeof *(formals_->formals_->argumentOrder_) FormalsMapType;
1118 FormalsMapType & formalsMap = *(formals_->formals_->argumentOrder_);
1119 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
1121 if( i->second == pos )
1123 missingArgs->insert( missingArgs->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1124 break;
1126 ++i;
1127 if( i == formalsMap.end( ) )
1129 throw Exceptions::InternalError( "Failed to find position of missing argument." );
1134 /* Normal case.
1136 *dst = *src;
1137 locations_[ pos ] = *srcLoc;
1141 if( missingArgs != 0 || missingStates != 0 )
1143 throw Exceptions::MissingArguments( formals_->formals_->loc( ), missingArgs, missingStates );
1146 if( hasSink_ )
1148 variables_->push_back
1149 ( Helpers::newValHandle
1150 ( new Lang::Structure( sinkArgList_,
1151 sinkValues_,
1152 true ) ) ); // true means that the sinkArgList_ gets owned by the Structure.
1153 sinkArgList_ = 0;
1158 Kernel::VariableHandle &
1159 Kernel::Arguments::getHandle( size_t i )
1161 return (*variables_)[ i ];
1164 RefCountPtr< const Lang::Value > &
1165 Kernel::Arguments::getValue( size_t i )
1167 return (*variables_)[ i ]->getUntyped( );
1170 const Ast::SourceLocation &
1171 Kernel::Arguments::getLoc( size_t i ) const
1173 return locations_[ i ]->loc( );
1176 const Ast::Node *
1177 Kernel::Arguments::getNode( size_t i ) const
1179 return locations_[ i ];
1182 Kernel::Thunk *
1183 Kernel::Arguments::getThunk( size_t i )
1185 return (*variables_)[ i ]->copyThunk( );
1188 bool
1189 Kernel::Arguments::isSlot( size_t i ) const
1191 return (*variables_)[ i ] == Kernel::THE_SLOT_VARIABLE;
1194 Kernel::StateHandle
1195 Kernel::Arguments::getState( size_t i )
1197 return (*states_)[ i ];
1200 const Ast::SourceLocation &
1201 Kernel::Arguments::getStateLoc( size_t i ) const
1203 return stateLocations_[ i ]->loc( );
1206 size_t
1207 Kernel::Arguments::size( ) const
1209 return variables_->size( );
1212 bool
1213 Kernel::Arguments::empty( ) const
1215 return variables_->empty( );
1218 void
1219 Kernel::Arguments::setMutatorSelf( Kernel::StateHandle mutatorSelf )
1221 mutatorSelf_ = mutatorSelf;
1224 Kernel::StateHandle
1225 Kernel::Arguments::getMutatorSelf( )
1227 if( mutatorSelf_ == 0 )
1229 throw Exceptions::InternalError( "Kernel::Arguments::getMutatorSelf: self is null." );
1231 return mutatorSelf_;
1234 void
1235 Kernel::Arguments::gcMark( Kernel::GCMarkedSet & marked )
1238 typedef typeof *variables_ ListType;
1239 for( ListType::const_iterator i = variables_->begin( ); i != variables_->end( ); ++i )
1241 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1246 Kernel::Environment::ValueVector
1247 Kernel::Arguments::getVariables( )
1249 return variables_;
1252 Kernel::Environment::StateVector
1253 Kernel::Arguments::getStates( )
1255 return states_;
1259 namespace Shapes
1261 namespace Kernel
1264 class FunctionOneHandleCont : public Kernel::Continuation
1266 RefCountPtr< const Lang::Function > fun_;
1267 Kernel::PassedDyn dyn_;
1268 Kernel::ContRef cont_;
1269 public:
1270 FunctionOneHandleCont( const RefCountPtr< const Lang::Function > & fun, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1271 : Kernel::Continuation( traceLoc ), fun_( fun ), dyn_( dyn ), cont_( cont )
1273 virtual ~FunctionOneHandleCont( ) { }
1274 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
1276 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1277 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1280 if( val->isThunk( ) )
1282 val->force( val, evalState );
1283 return;
1286 Kernel::Arguments args = fun_->newCurriedArguments( );
1287 args.addOrderedArgument( val, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1289 evalState->dyn_ = dyn_;
1290 evalState->cont_ = cont_;
1291 fun_->call( evalState, args, traceLoc_ );
1293 virtual Kernel::ContRef up( ) const
1295 return cont_;
1297 virtual RefCountPtr< const char > description( ) const
1299 return strrefdup( "internal function call with one handle" );
1301 virtual void gcMark( Kernel::GCMarkedSet & marked )
1303 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1304 dyn_->gcMark( marked );
1305 cont_->gcMark( marked );
1309 class FunctionTwoHandlesCont_2 : public Kernel::Continuation
1311 RefCountPtr< const Lang::Function > fun_;
1312 Kernel::VariableHandle arg1_;
1313 Kernel::PassedDyn dyn_;
1314 Kernel::ContRef cont_;
1315 public:
1316 FunctionTwoHandlesCont_2( const RefCountPtr< const Lang::Function > & fun, const Kernel::VariableHandle & arg1, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1317 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), dyn_( dyn ), cont_( cont )
1319 virtual ~FunctionTwoHandlesCont_2( ) { }
1320 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1322 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1323 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1326 if( arg2->isThunk( ) )
1328 arg2->force( arg2, evalState );
1329 return;
1332 Kernel::Arguments args = fun_->newCurriedArguments( );
1333 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1334 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1335 evalState->dyn_ = dyn_;
1336 evalState->cont_ = cont_;
1337 fun_->call( evalState, args, traceLoc_ );
1339 virtual Kernel::ContRef up( ) const
1341 return cont_;
1343 virtual RefCountPtr< const char > description( ) const
1345 return strrefdup( "internal function call with two handles, second" );
1347 virtual void gcMark( Kernel::GCMarkedSet & marked )
1349 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1350 dyn_->gcMark( marked );
1351 cont_->gcMark( marked );
1355 class FunctionTwoHandlesCont_1 : public Kernel::Continuation
1357 RefCountPtr< const Lang::Function > fun_;
1358 Kernel::VariableHandle arg2_;
1359 bool forceArg2_;
1360 Kernel::PassedDyn dyn_;
1361 Kernel::ContRef cont_;
1362 public:
1363 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 )
1364 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), dyn_( dyn ), cont_( cont )
1366 virtual ~FunctionTwoHandlesCont_1( ) { }
1367 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1369 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1370 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1373 if( arg1->isThunk( ) )
1375 arg1->force( arg1, evalState );
1376 return;
1379 if( forceArg2_ )
1381 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( fun_, arg1, dyn_, cont_, traceLoc_ ) );
1382 evalState->cont_ = newCont;
1383 newCont->takeHandle( arg2_, evalState );
1384 return;
1387 /* The second handle need not be forced
1389 Kernel::Arguments args = fun_->newCurriedArguments( );
1390 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1391 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1392 evalState->dyn_ = dyn_;
1393 evalState->cont_ = cont_;
1394 fun_->call( evalState, args, traceLoc_ );
1396 virtual Kernel::ContRef up( ) const
1398 return cont_;
1400 virtual RefCountPtr< const char > description( ) const
1402 return strrefdup( "internal function call with two handles, first" );
1404 virtual void gcMark( Kernel::GCMarkedSet & marked )
1406 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1407 dyn_->gcMark( marked );
1408 cont_->gcMark( marked );
1412 class FunctionTwoHandlesOneStateCont_2 : public Kernel::Continuation
1414 RefCountPtr< const Lang::Function > fun_;
1415 Kernel::VariableHandle arg1_;
1416 Kernel::StateHandle state_;
1417 Kernel::PassedDyn dyn_;
1418 Kernel::ContRef cont_;
1419 public:
1420 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 )
1421 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), state_( state ), dyn_( dyn ), cont_( cont )
1423 virtual ~FunctionTwoHandlesOneStateCont_2( ) { }
1424 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1426 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1427 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1430 if( arg2->isThunk( ) )
1432 arg2->force( arg2, evalState );
1433 return;
1436 Kernel::Arguments args = fun_->newCurriedArguments( );
1437 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1438 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1439 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1440 evalState->dyn_ = dyn_;
1441 evalState->cont_ = cont_;
1442 fun_->call( evalState, args, traceLoc_ );
1444 virtual Kernel::ContRef up( ) const
1446 return cont_;
1448 virtual RefCountPtr< const char > description( ) const
1450 return strrefdup( "internal function call with two handles and one state, second" );
1452 virtual void gcMark( Kernel::GCMarkedSet & marked )
1454 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1455 state_->gcMark( marked );
1456 dyn_->gcMark( marked );
1457 cont_->gcMark( marked );
1461 class FunctionTwoHandlesOneStateCont_1 : public Kernel::Continuation
1463 RefCountPtr< const Lang::Function > fun_;
1464 Kernel::VariableHandle arg2_;
1465 bool forceArg2_;
1466 Kernel::StateHandle state_;
1467 Kernel::PassedDyn dyn_;
1468 Kernel::ContRef cont_;
1469 public:
1470 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 )
1471 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), state_( state ), dyn_( dyn ), cont_( cont )
1473 virtual ~FunctionTwoHandlesOneStateCont_1( ) { }
1474 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1476 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1477 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1480 if( arg1->isThunk( ) )
1482 arg1->force( arg1, evalState );
1483 return;
1486 if( forceArg2_ )
1488 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( fun_, arg1, state_, dyn_, cont_, traceLoc_ ) );
1489 evalState->cont_ = newCont;
1490 newCont->takeHandle( arg2_, evalState );
1491 return;
1494 /* The second handle need not be forced
1496 Kernel::Arguments args = fun_->newCurriedArguments( );
1497 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1498 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1499 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1500 evalState->dyn_ = dyn_;
1501 evalState->cont_ = cont_;
1502 fun_->call( evalState, args, traceLoc_ );
1504 virtual Kernel::ContRef up( ) const
1506 return cont_;
1508 virtual RefCountPtr< const char > description( ) const
1510 return strrefdup( "internal function call with two handles and one state, first" );
1512 virtual void gcMark( Kernel::GCMarkedSet & marked )
1514 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1515 dyn_->gcMark( marked );
1516 cont_->gcMark( marked );
1517 state_->gcMark( marked );
1525 Lang::Function::Function( Kernel::EvaluatedFormals * formals )
1526 : formals_( formals )
1529 DISPATCHIMPL( Function );
1531 Lang::Function::~Function( )
1533 if( formals_ != 0 )
1535 delete formals_->formals_;
1536 delete formals_;
1540 Kernel::ValueRef
1541 Lang::Function::transformed( const Lang::Transform2D & tf, Kernel::ValueRef self ) const
1543 return Kernel::ValueRef( new Lang::TransformedFunction2D( tf, self.down_cast< const Lang::Function >( ) ) );
1546 void
1547 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Ast::SourceLocation & callLoc ) const
1549 Kernel::Arguments args = this->newCurriedArguments( );
1551 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1553 this->call( evalState, args, callLoc );
1556 void
1557 Lang::Function::analyze( Ast::Node * parent, Ast::AnalysisEnvironment * env )
1559 Ast::StateIDSet * freeStates = new Ast::StateIDSet;
1560 this->analyze_impl( parent, env, freeStates );
1561 if( ! freeStates->empty( ) )
1563 Ast::theAnalysisErrorsList.push_back( new Exceptions::IllegalFreeStates( parent->loc( ), freeStates, "this is a function" ) );
1565 else
1567 delete freeStates;
1571 void
1572 Lang::Function::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1574 throw Exceptions::InternalError( "A syntax function is not overriding the analyze method." );
1577 void
1578 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Kernel::ValueRef & arg2, const Ast::SourceLocation & callLoc ) const
1580 Kernel::Arguments args = this->newCurriedArguments( );
1582 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1583 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg2 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1585 this->call( evalState, args, callLoc );
1588 Ast::ArgListExprs * Lang::Function::oneExprArgList = new Ast::ArgListExprs( static_cast< size_t >( 1 ) );
1589 Ast::ArgListExprs * Lang::Function::twoExprsArgList = new Ast::ArgListExprs( static_cast< size_t >( 2 ) );
1591 void
1592 Lang::Function::call( const RefCountPtr< const Lang::Function > & selfRef, Kernel::EvalState * evalState, const Kernel::VariableHandle & arg1, const Ast::SourceLocation & callLoc ) const
1594 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::oneExprArgList, *evalState );
1596 if( info->force( 0 ) )
1598 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionOneHandleCont( selfRef, evalState->dyn_, evalState->cont_, callLoc ) );
1599 evalState->cont_ = cont;
1600 cont->takeHandle( arg1, evalState );
1601 return;
1604 /* The handle need not be forced
1606 Kernel::Arguments args = this->newCurriedArguments( );
1607 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1608 this->call( evalState, args, callLoc );
1611 void
1612 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
1614 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1616 /* Remember that arguments are ordered backwards!
1619 if( info->force( 1 ) )
1621 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_1( selfRef, arg2, info->force( 0 ), evalState->dyn_, evalState->cont_, callLoc ) );
1622 evalState->cont_ = cont;
1623 cont->takeHandle( arg1, evalState );
1624 return;
1627 if( info->force( 0 ) )
1629 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( selfRef, arg1, evalState->dyn_, evalState->cont_, callLoc ) );
1630 evalState->cont_ = cont;
1631 cont->takeHandle( arg2, evalState );
1632 return;
1635 /* None of the handles need to be forced
1637 Kernel::Arguments args = this->newCurriedArguments( );
1638 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1639 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1640 this->call( evalState, args, callLoc );
1643 void
1644 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
1646 /* I'm not quite sure if we should also put a dummy state argument in info...
1648 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1650 /* Remember that arguments are ordered backwards!
1653 if( info->force( 1 ) )
1655 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_1( selfRef, arg2, info->force( 0 ), state, evalState->dyn_, evalState->cont_, callLoc ) );
1656 evalState->cont_ = cont;
1657 cont->takeHandle( arg1, evalState );
1658 return;
1661 if( info->force( 0 ) )
1663 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( selfRef, arg1, state, evalState->dyn_, evalState->cont_, callLoc ) );
1664 evalState->cont_ = cont;
1665 cont->takeHandle( arg2, evalState );
1666 return;
1669 /* None of the handles need to be forced
1671 Kernel::Arguments args = this->newCurriedArguments( );
1672 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1673 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1674 args.addOrderedState( state, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1675 this->call( evalState, args, callLoc );
1679 RefCountPtr< Kernel::CallContInfo >
1680 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1682 return formals_->newCallContInfo( argList, evalState );
1685 RefCountPtr< Kernel::CallContInfo >
1686 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1688 return formals_->newCallContInfo( argList, evalState, curryArgs );
1691 Kernel::Arguments
1692 Lang::Function::newCurriedArguments( ) const
1694 return Kernel::Arguments( formals_ );
1698 RefCountPtr< const Lang::Class > Lang::Function::TypeID( new Lang::SystemFinalClass( strrefdup( "Function" ) ) );
1699 TYPEINFOIMPL( Function );
1701 Kernel::EvaluatedFormals::EvaluatedFormals( Kernel::Formals * formals )
1702 : selectiveForcing_( false ), forceAll_( false ), formals_( formals ), isSink_( true )
1705 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID * locationFileID )
1706 : selectiveForcing_( true ), formals_( 0 ), isSink_( true )
1708 Kernel::Formals * formals( new Kernel::Formals( ) );
1709 formals->setLoc( Ast::SourceLocation( locationFileID ) );
1710 formals_ = formals;
1713 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID * locationFileID, bool forceAll)
1714 : selectiveForcing_( false ), forceAll_( forceAll ), formals_( 0 ), isSink_( true )
1716 Kernel::Formals * formals( new Kernel::Formals( ) );
1717 formals->setLoc( Ast::SourceLocation( locationFileID ) );
1718 formals_ = formals;
1721 Kernel::EvaluatedFormals::~EvaluatedFormals( )
1723 /* Don't delete the orderedFormals, since we don't own it. A case for reference counting? */
1726 RefCountPtr< Kernel::CallContInfo >
1727 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1729 if( selectiveForcing_ )
1731 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList ) ) );
1733 else
1735 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1739 RefCountPtr< Kernel::CallContInfo >
1740 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1742 if( selectiveForcing_ )
1744 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList, curryArgs ) ) );
1746 else
1748 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1752 void
1753 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc, bool force )
1755 if( ! selectiveForcing_ )
1757 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function does not have selective forcing." );
1759 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1760 formals_->forcePos_.push_back( force );
1761 defaults_.push_back( defaultVal );
1762 locations_.push_back( loc );
1765 void
1766 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc )
1768 if( selectiveForcing_ )
1770 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function requires individual forcing specification." );
1772 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1773 formals_->forcePos_.push_back( forceAll_ );
1774 defaults_.push_back( defaultVal );
1775 locations_.push_back( loc );
1778 void
1779 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal, bool force )
1781 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION, force );
1784 void
1785 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal )
1787 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION );
1790 void
1791 Kernel::EvaluatedFormals::appendCoreStateFormal( const char * id )
1793 (*(formals_->stateOrder_))[ id ] = formals_->stateOrder_->size( );
1796 void
1797 Kernel::EvaluatedFormals::gcMark( Kernel::GCMarkedSet & marked )
1799 typedef typeof defaults_ ListType;
1800 for( ListType::const_iterator i = defaults_.begin( ); i != defaults_.end( ); ++i )
1802 if( *i != NullPtr< Kernel::Variable >( ) )
1804 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1810 Lang::CuteFunction::CuteFunction( RefCountPtr< const Lang::Function > callee, const Kernel::Arguments & someArgs )
1811 : Lang::Function( 0 ), callee_( callee), someArgs_( someArgs.clone( ) )
1814 Lang::CuteFunction::~CuteFunction( )
1817 RefCountPtr< Kernel::CallContInfo >
1818 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1820 return callee_->newCallContInfo( argList, evalState, someArgs_ );
1823 RefCountPtr< Kernel::CallContInfo >
1824 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1826 /* when we are the callee of a CuteFunction, our someArgs are part of that CuteFunction's someArgs, and hence curryArgs
1827 * contains everything that is to be passed to our callee.
1829 return callee_->newCallContInfo( argList, evalState, curryArgs );
1832 Kernel::Arguments
1833 Lang::CuteFunction::newCurriedArguments( ) const
1835 return someArgs_.clone( );
1838 void
1839 Lang::CuteFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1841 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1842 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.
1844 callee_->call( evalState, args, callLoc );
1847 bool
1848 Lang::CuteFunction::isTransforming( ) const
1850 return callee_->isTransforming( );
1853 void
1854 Lang::CuteFunction::gcMark( Kernel::GCMarkedSet & marked )
1856 const_cast< Lang::Function * >( callee_.getPtr( ) )->gcMark( marked );
1857 someArgs_.gcMark( marked );
1860 void
1861 Lang::CuteFunction::show( std::ostream & os ) const
1863 os << "< evaluated cut of: " ;
1864 callee_->show( os );
1865 os << " >" ;
1869 Lang::ComposedFunction::ComposedFunction( const RefCountPtr< const Lang::Function > & second, const RefCountPtr< const Lang::Function > & first )
1870 : Lang::Function( 0 ), second_( second ), first_( first )
1873 Lang::ComposedFunction::~ComposedFunction( )
1876 void
1877 Lang::ComposedFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1879 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1880 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.
1882 evalState->cont_ = Kernel::ContRef( new Kernel::ComposedFunctionCall_cont( second_, evalState->dyn_, evalState->cont_, callLoc ) );
1883 first_->call( evalState, args, callLoc );
1886 RefCountPtr< Kernel::CallContInfo >
1887 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1889 return first_->newCallContInfo( argList, evalState );
1892 RefCountPtr< Kernel::CallContInfo >
1893 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1895 return first_->newCallContInfo( argList, evalState, curryArgs );
1898 Kernel::Arguments
1899 Lang::ComposedFunction::newCurriedArguments( ) const
1901 return first_->newCurriedArguments( );
1904 bool
1905 Lang::ComposedFunction::isTransforming( ) const
1907 return second_->isTransforming( );
1910 void
1911 Lang::ComposedFunction::gcMark( Kernel::GCMarkedSet & marked )
1913 const_cast< Lang::Function * >( second_.getPtr( ) )->gcMark( marked );
1914 const_cast< Lang::Function * >( first_.getPtr( ) )->gcMark( marked );
1917 void
1918 Lang::ComposedFunction::show( std::ostream & os ) const
1920 os << "< composition: " ;
1921 second_->show( os );
1922 os << " () " ;
1923 first_->show( os );
1924 os << " >" ;
1928 namespace Shapes
1930 namespace Kernel
1932 class SpanThunks
1934 std::vector< Kernel::VariableHandle > thunks_;
1935 public:
1936 SpanThunks( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count )
1938 thunks_.reserve( 4 );
1939 thunks_.push_back( count );
1940 thunks_.push_back( step );
1941 thunks_.push_back( end );
1942 thunks_.push_back( begin );
1944 const Kernel::VariableHandle & operator [] ( size_t i ) const
1946 return thunks_[ i ];
1948 ~SpanThunks( )
1950 void gcMark( Kernel::GCMarkedSet & marked )
1952 typedef typeof thunks_ VecType;
1953 for( VecType::iterator i = thunks_.begin( ); i != thunks_.end( ); ++i )
1955 (*i)->gcMark( marked );
1960 class SpanForcingContinuation : public Continuation
1962 RefCountPtr< const Kernel::SpanThunks > thunks_;
1963 size_t i_;
1964 RefCountPtr< const Lang::SingleList > values_;
1965 RefCountPtr< const Lang::Value > last_;
1966 Kernel::ContRef cont_;
1967 public:
1968 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 )
1969 : Kernel::Continuation( traceLoc ), thunks_( thunks ), i_( i ), values_( values ), last_( last ), cont_( cont )
1971 ~SpanForcingContinuation( )
1973 static void finish( RefCountPtr< const Lang::SingleList > values, RefCountPtr< const Lang::Value > last, Kernel::EvalState * evalState, const Ast::SourceLocation & traceLoc )
1975 Kernel::Arguments args = Lang::THE_FUNCTION_RANGE->newCurriedArguments( );
1976 RefCountPtr< const Lang::SingleListPair > src = values.down_cast< const Lang::SingleListPair >( );
1977 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1978 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1979 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1980 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1981 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1982 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1983 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1984 Lang::Core_range::makeRange( "<span>", evalState, args, traceLoc, true, last );
1986 virtual void takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
1988 RefCountPtr< const Lang::SingleList > values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( val ) ), values_ ) );
1990 for( size_t i = i_ + 1; i < 4; ++i )
1992 const Kernel::VariableHandle & var = (*thunks_)[ i ];
1993 if( var->isThunk( ) )
1995 evalState->cont_ = Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_, i, values, last_, cont_, traceLoc_ ) );
1996 var->force( var, evalState );
1997 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, last_ ) );
1998 return;
2000 values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( var, values ) );
2002 evalState->cont_ = cont_;
2003 finish( values, last_, evalState, traceLoc_ );
2005 virtual Kernel::ContRef up( ) const
2007 return cont_;
2009 virtual RefCountPtr< const char > description( ) const
2011 std::ostringstream msg;
2012 msg << "force span parameter number " << i_ ;
2013 return strrefdup( msg );
2015 virtual void gcMark( Kernel::GCMarkedSet & marked )
2017 const_cast< Kernel::SpanThunks * >( thunks_.getPtr( ) )->gcMark( marked );
2018 const_cast< Lang::SingleList * >( values_.getPtr( ) )->gcMark( marked );
2019 const_cast< Lang::Value * >( last_.getPtr( ) )->gcMark( marked );
2020 cont_->gcMark( marked );
2026 RefCountPtr< const Lang::Class > Lang::Span::TypeID( new Lang::SystemFinalClass( strrefdup( "Span" ) ) );
2027 TYPEINFOIMPL( Span );
2029 Lang::Span::Span( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count )
2030 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<span>" ), true ) ),
2031 thunks_( new Kernel::SpanThunks( begin, end, step, count ) )
2033 formals_->appendEvaluatedCoreFormal( "last", Kernel::THE_SLOT_VARIABLE );
2036 Lang::Span::~Span( )
2039 void
2040 Lang::Span::gcMark( Kernel::GCMarkedSet & marked )
2042 const_cast< Kernel::SpanThunks * >( thunks_.getPtr( ) )->gcMark( marked );
2045 void
2046 Lang::Span::show( std::ostream & os ) const
2048 os << "<span>" ;
2051 void
2052 Lang::Span::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2054 args.applyDefaults( );
2056 RefCountPtr< const Lang::SingleList > values = Lang::THE_CONS_NULL;
2057 for( size_t i = 0; i < 4; ++i )
2059 const Kernel::VariableHandle & var = (*thunks_)[ i ];
2060 if( var->isThunk( ) )
2062 evalState->cont_ = Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_, i, values, args.getValue( 0 ), evalState->cont_, callLoc ) );
2063 var->force( var, evalState );
2064 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, args.getValue( 0 ) ) );
2065 return;
2067 values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( var, values ) );
2070 /* We only reach this point if there were no thunks at all to be forced. */
2071 Kernel::SpanForcingContinuation::finish( values, args.getValue( 0 ), evalState, callLoc );
2074 bool
2075 Lang::Span::isTransforming( ) const
2077 return false;
2081 Lang::UserFunction::UserFunction( Kernel::EvaluatedFormals * formals, Ast::Expression * body, Kernel::PassedEnv env, const Ast::FunctionMode & functionMode )
2082 : Lang::Function( formals ), body_( body ), env_( env ), functionMode_( functionMode )
2085 // DISPATCHIMPL( UserFunction );
2087 Lang::UserFunction::~UserFunction( )
2089 // Note that we don't delete the things that we most likely share with other objects
2090 // Reference counting could be used here, but there will never be more such things than there are function expressions in the source
2092 // This prevents formals->formals from being deleted by Lang::Function::~Function
2093 delete formals_;
2094 formals_ = 0;
2097 void
2098 Lang::UserFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2100 args.applyDefaults( );
2101 evalState->env_ = new Kernel::Environment( Kernel::theEnvironmentList, env_, formals_->formals_->argumentOrder_, args.getVariables( ), formals_->formals_->stateOrder_, args.getStates( ), "Closure" );
2102 evalState->env_->activateFunctionBoundary( );
2103 evalState->expr_ = body_;
2106 bool
2107 Lang::UserFunction::isTransforming( ) const
2109 return ( functionMode_ & Ast::FUNCTION_TRANSFORMING ) != 0;
2112 void
2113 Lang::UserFunction::gcMark( Kernel::GCMarkedSet & marked )
2115 env_->gcMark( marked );
2118 Ast::Expression *
2119 Lang::UserFunction::body( )
2121 return body_;
2124 void
2125 Lang::UserFunction::show( std::ostream & os ) const
2127 os << "< user function with body at " << body_->loc( ) << " >" ;
2131 Lang::TransformedFunction2D::TransformedFunction2D( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Function > & fun )
2132 : Lang::Function( 0 ), tf_( tf ), fun_( fun )
2135 Lang::TransformedFunction2D::~TransformedFunction2D( )
2138 void
2139 Lang::TransformedFunction2D::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2141 evalState->cont_ = Kernel::ContRef( new Kernel::Transform2DCont( tf_, evalState->cont_, 0 ) );
2142 fun_->call( evalState, args, callLoc );
2145 bool
2146 Lang::TransformedFunction2D::isTransforming( ) const
2148 return fun_->isTransforming( );
2151 void
2152 Lang::TransformedFunction2D::gcMark( Kernel::GCMarkedSet & marked )
2154 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
2157 void
2158 Lang::TransformedFunction2D::show( std::ostream & os ) const
2160 os << "< transformed function >" ;
2165 Lang::VectorFunction::VectorFunction( const std::vector< Kernel::ValueRef > * mem )
2166 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<vector>" ), true ) ), mem_( mem ),
2167 memNumeric_( NullPtr< const std::vector< double > >( ) ),
2168 list_( NullPtr< Kernel::Variable >( ) )
2170 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
2173 // DISPATCHIMPL( VectorFunction );
2175 Lang::VectorFunction::~VectorFunction( )
2178 RefCountPtr< const Lang::Class > Lang::VectorFunction::TypeID( new Lang::SystemFinalClass( strrefdup( "VectorFunction" ), Kernel::VectorFunction_register_methods ) );
2179 TYPEINFOIMPL( VectorFunction );
2181 Kernel::VariableHandle
2182 Lang::VectorFunction::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
2184 if( strcmp( fieldID, "size" ) == 0 )
2186 return Helpers::newValHandle( new Lang::Integer( mem_->size( ) ) );
2188 if( strcmp( fieldID, "range" ) == 0 )
2190 return Helpers::newValHandle( new Lang::SingleListRange< Lang::Integer >( 0, 1, mem_->size( ) ) );
2192 if( strcmp( fieldID, "reverse_range" ) == 0 )
2194 return Helpers::newValHandle( new Lang::SingleListRange< Lang::Integer >( mem_->size( ) - 1, -1, mem_->size( ) ) );
2196 if( strcmp( fieldID, "list" ) == 0 )
2198 compute_list( );
2199 return list_;
2202 return TypeID->getMethod( selfRef, fieldID ); /* This will throw if there is no such method. */
2205 const char * Lang::VectorFunction::title_ = "<vector>";
2207 void
2208 Lang::VectorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2210 const size_t ARITY = 1;
2211 if( args.size( ) != ARITY )
2213 throw Exceptions::CoreArityMismatch( title_, ARITY, args.size( ) );
2216 typedef const Lang::Integer ArgType;
2217 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
2219 if( arg->val_ < 0 )
2221 throw Exceptions::CoreOutOfRange( title_, args, 0, "Index is negative." );
2224 if( arg->val_ >= static_cast< int >( mem_->size( ) ) )
2226 throw Exceptions::CoreOutOfRange( title_, args, 0, "Index exceeds vector size." );
2229 Kernel::ContRef cont = evalState->cont_;
2230 cont->takeValue( (*mem_)[ arg->val_ ],
2231 evalState );
2234 bool
2235 Lang::VectorFunction::isTransforming( ) const
2237 return false;
2240 void
2241 Lang::VectorFunction::gcMark( Kernel::GCMarkedSet & marked )
2243 gcMark( mem_, marked );
2246 void
2247 Lang::VectorFunction::gcMark( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, Kernel::GCMarkedSet & marked )
2249 for( std::vector< Kernel::ValueRef >::const_iterator i = mem->begin( ); i != mem->end( ); ++i )
2251 const_cast< Lang::Value * >( i->getPtr( ) )->gcMark( marked );
2255 void
2256 Lang::VectorFunction::show( std::ostream & os ) const
2258 os << "< vector function >" ;
2261 RefCountPtr< const std::vector< double > >
2262 Lang::VectorFunction::getNumeric( const Ast::SourceLocation & callLoc ) const
2264 if( memNumeric_ == NullPtr< const std::vector< double > >( ) )
2266 RefCountPtr< std::vector< double > > res( new std::vector< double > ); // Note that this is not const, so far...
2267 res->reserve( mem_->size( ) );
2268 typedef typeof *mem_ SrcType;
2269 for( SrcType::const_iterator src = mem_->begin( ); src != mem_->end( ); ++src )
2271 res->push_back( Helpers::down_cast< const Lang::Float >( *src, callLoc )->val_ );
2274 memNumeric_ = res;
2276 return memNumeric_;
2279 void
2280 Lang::VectorFunction::compute_list( ) const
2282 if( list_ != NullPtr< Kernel::Variable >( ) )
2284 return;
2286 RefCountPtr< const Lang::SingleList > newList = Lang::THE_CONS_NULL;
2287 typedef typeof *mem_ ListType;
2288 for( ListType::const_reverse_iterator src = mem_->rbegin( ); src != mem_->rend( ); ++src )
2290 newList = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( *src ) ), newList ) );
2292 list_ = Kernel::VariableHandle( new Kernel::Variable( newList ) );
2295 namespace Shapes
2297 namespace Kernel
2300 class VectorFunctionFoldLCont : public Kernel::Continuation
2302 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2303 RefCountPtr< const Lang::Function > op_;
2304 Shapes::Lang::VectorFunction::vector_type::const_iterator i_;
2305 Kernel::PassedDyn dyn_;
2306 Kernel::ContRef cont_;
2307 public:
2308 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 )
2309 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), dyn_( dyn ), cont_( cont )
2311 virtual ~VectorFunctionFoldLCont( ) { }
2312 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2314 evalState->dyn_ = dyn_;
2315 evalState->cont_ = cont_;
2316 Lang::VectorFunction::foldl( mem_, evalState, op_, val, i_, traceLoc_ );
2318 virtual Kernel::ContRef up( ) const
2320 return cont_;
2322 virtual RefCountPtr< const char > description( ) const
2324 return strrefdup( "VectorFunction's foldl" );
2326 virtual void gcMark( Kernel::GCMarkedSet & marked )
2328 Lang::VectorFunction::gcMark( mem_, marked );
2329 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2330 dyn_->gcMark( marked );
2331 cont_->gcMark( marked );
2335 class VectorFunctionFoldRCont : public Kernel::Continuation
2337 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2338 RefCountPtr< const Lang::Function > op_;
2339 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_;
2340 Kernel::PassedDyn dyn_;
2341 Kernel::ContRef cont_;
2342 public:
2343 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 )
2344 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), dyn_( dyn ), cont_( cont )
2346 virtual ~VectorFunctionFoldRCont( ) { }
2347 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2349 evalState->dyn_ = dyn_;
2350 evalState->cont_ = cont_;
2351 Lang::VectorFunction::foldr( mem_, evalState, op_, val, i_, traceLoc_ );
2353 virtual Kernel::ContRef up( ) const
2355 return cont_;
2357 virtual RefCountPtr< const char > description( ) const
2359 return strrefdup( "VectorFunction's foldr" );
2361 virtual void gcMark( Kernel::GCMarkedSet & marked )
2363 Lang::VectorFunction::gcMark( mem_, marked );
2364 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2365 dyn_->gcMark( marked );
2366 cont_->gcMark( marked );
2370 class VectorFunctionFoldSLCont : public Kernel::Continuation
2372 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2373 RefCountPtr< const Lang::Function > op_;
2374 Shapes::Lang::VectorFunction::vector_type::const_iterator i_;
2375 Kernel::StateHandle state_;
2376 Kernel::PassedDyn dyn_;
2377 Kernel::ContRef cont_;
2378 public:
2379 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 )
2380 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), state_( state ), dyn_( dyn ), cont_( cont )
2382 virtual ~VectorFunctionFoldSLCont( ) { }
2383 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2385 evalState->dyn_ = dyn_;
2386 evalState->cont_ = cont_;
2387 Lang::VectorFunction::foldsl( mem_, evalState, op_, val, state_, i_, traceLoc_ );
2389 virtual Kernel::ContRef up( ) const
2391 return cont_;
2393 virtual RefCountPtr< const char > description( ) const
2395 return strrefdup( "VectorFunction's foldsl" );
2397 virtual void gcMark( Kernel::GCMarkedSet & marked )
2399 Lang::VectorFunction::gcMark( mem_, marked );
2400 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2401 state_->gcMark( marked );
2402 dyn_->gcMark( marked );
2403 cont_->gcMark( marked );
2407 class VectorFunctionFoldSRCont : public Kernel::Continuation
2409 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2410 RefCountPtr< const Lang::Function > op_;
2411 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_;
2412 Kernel::StateHandle state_;
2413 Kernel::PassedDyn dyn_;
2414 Kernel::ContRef cont_;
2415 public:
2416 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 )
2417 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), state_( state ), dyn_( dyn ), cont_( cont )
2419 virtual ~VectorFunctionFoldSRCont( ) { }
2420 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2422 evalState->dyn_ = dyn_;
2423 evalState->cont_ = cont_;
2424 Lang::VectorFunction::foldsr( mem_, evalState, op_, val, state_, i_, traceLoc_ );
2426 virtual Kernel::ContRef up( ) const
2428 return cont_;
2430 virtual RefCountPtr< const char > description( ) const
2432 return strrefdup( "VectorFunction's foldsr" );
2434 virtual void gcMark( Kernel::GCMarkedSet & marked )
2436 Lang::VectorFunction::gcMark( mem_, marked );
2437 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2438 state_->gcMark( marked );
2439 dyn_->gcMark( marked );
2440 cont_->gcMark( marked );
2447 void
2448 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 )
2450 if( i == mem->end( ) )
2452 Kernel::ContRef cont = evalState->cont_;
2453 cont->takeHandle( nullResult,
2454 evalState );
2455 return;
2458 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2459 ++i;
2460 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldLCont( mem, op, i, evalState->dyn_, evalState->cont_, callLoc ) );
2462 op->call( op, evalState, nullResult, elem, callLoc );
2465 void
2466 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 )
2468 if( i == mem->rend( ) )
2470 Kernel::ContRef cont = evalState->cont_;
2471 cont->takeHandle( nullResult,
2472 evalState );
2473 return;
2476 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2477 ++i;
2478 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldRCont( mem, op, i, evalState->dyn_, evalState->cont_, callLoc ) );
2480 op->call( op, evalState, nullResult, elem, callLoc );
2483 void
2484 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 )
2486 if( i == mem->end( ) )
2488 Kernel::ContRef cont = evalState->cont_;
2489 cont->takeHandle( nullResult,
2490 evalState );
2491 return;
2494 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2495 ++i;
2496 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldSLCont( mem, op, i, state, evalState->dyn_, evalState->cont_, callLoc ) );
2498 op->call( op, evalState, nullResult, elem, state, callLoc );
2501 void
2502 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 )
2504 if( i == mem->rend( ) )
2506 Kernel::ContRef cont = evalState->cont_;
2507 cont->takeHandle( nullResult,
2508 evalState );
2509 return;
2512 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2513 ++i;
2514 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldSRCont( mem, op, i, state, evalState->dyn_, evalState->cont_, callLoc ) );
2516 op->call( op, evalState, nullResult, elem, state, callLoc );
2520 const char * Lang::ColorInterpolator::title_ = "<color-interpolator>";
2522 Lang::ColorInterpolator::ColorInterpolator( const RefCountPtr< KeyContainer > & key,
2523 const RefCountPtr< RGBContainer > & RGBcolor,
2524 const RefCountPtr< GrayContainer > & graycolor,
2525 const RefCountPtr< CMYKContainer > & CMYKcolor,
2526 ColorType colorType)
2527 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( Lang::ColorInterpolator::title_ ), true ) ),
2528 key_( key ), RGBcolor_ ( RGBcolor ), graycolor_ ( graycolor ), CMYKcolor_ ( CMYKcolor ), colorType_(colorType)
2530 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
2533 Lang::ColorInterpolator::~ColorInterpolator( )
2536 Kernel::VariableHandle
2537 Lang::ColorInterpolator::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
2539 if( strcmp( fieldID, "low" ) == 0 )
2541 return Helpers::newValHandle( new Lang::Float( key_->front( ) ) );
2543 if( strcmp( fieldID, "high" ) == 0 )
2545 return Helpers::newValHandle( new Lang::Float( key_->back( ) ) );
2547 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
2551 template <class COLOR_TYPE, class COLOR_CONTAINER>
2552 void
2553 Lang::ColorInterpolator::callHelper( Kernel::EvalState * evalState,
2554 const RefCountPtr< COLOR_CONTAINER > & colorContainer,
2555 double key, KeyContainer::const_iterator keyHi ) const
2557 if( keyHi == key_->end( ) )
2559 Kernel::ContRef cont = evalState->cont_;
2560 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->back( ) ) ),
2561 evalState );
2562 return;
2565 if( keyHi == key_->begin( ) )
2567 Kernel::ContRef cont = evalState->cont_;
2568 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->front( ) ) ),
2569 evalState );
2570 return;
2573 KeyContainer::const_iterator keyLo = keyHi - 1;
2574 double rem = ( key - *keyLo ) / ( *keyHi - *keyLo );
2576 Kernel::ContRef cont = evalState->cont_;
2578 typename COLOR_CONTAINER::const_iterator colorHi = colorContainer->begin( ) + ( keyHi - key_->begin( ) );
2579 typename COLOR_CONTAINER::const_iterator colorLo = colorHi - 1;
2581 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorLo->mulNoCheck( 1 - rem ).addNoCheck( colorHi->mulNoCheck( rem ) ) ) ),
2582 evalState );
2586 void
2587 Lang::ColorInterpolator::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2589 const size_t ARITY = 1;
2590 if( args.size( ) != ARITY )
2592 throw Exceptions::CoreArityMismatch( title_, ARITY, args.size( ) );
2595 typedef const Lang::Float ArgType;
2596 double key = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc )->val_;
2598 KeyContainer::const_iterator keyHi = lower_bound( key_->begin( ), key_->end( ), key );
2599 switch( colorType_ )
2601 case RGB:
2602 callHelper< Lang::RGB >( evalState, RGBcolor_, key, keyHi );
2603 break;
2604 case GRAY:
2605 callHelper< Lang::Gray >( evalState, graycolor_, key, keyHi );
2606 break;
2607 case CMYK:
2608 callHelper< Lang::CMYK >( evalState, CMYKcolor_, key, keyHi );
2609 break;
2610 case UNDEFINED:
2611 throw Exceptions::InternalError( "ColorInterpolator::call: Did not expect UNDEFINED in ennum switch." );
2615 bool
2616 Lang::ColorInterpolator::isTransforming( ) const
2618 return false;
2621 void
2622 Lang::ColorInterpolator::gcMark( Kernel::GCMarkedSet & marked )
2625 void
2626 Lang::ColorInterpolator::show( std::ostream & os ) const
2628 os << "< color interpolator in " ;
2629 switch( colorType_ )
2631 case RGB:
2632 os << "RGB" ;
2633 break;
2634 case GRAY:
2635 os << "Gray" ;
2636 break;
2637 case CMYK:
2638 os << "CMYK" ;
2639 break;
2640 case UNDEFINED:
2641 throw Exceptions::InternalError( "ColorInterpolator::show: Did not expect UNDEFINED in ennum switch." );
2643 os << " mode >" ;
2646 Lang::BinaryOperatorFunction::BinaryOperatorFunction( Ast::BinaryInfixExpr * opExpr, const char * title )
2647 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) ), opExpr_( opExpr ), title_( title )
2649 formals_->appendEvaluatedCoreFormal( "first", Kernel::THE_SLOT_VARIABLE );
2650 formals_->appendEvaluatedCoreFormal( "second", Kernel::THE_SLOT_VARIABLE );
2653 Lang::BinaryOperatorFunction::~BinaryOperatorFunction( )
2655 delete opExpr_;
2658 void
2659 Lang::BinaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2661 const size_t ARITY = 2;
2662 CHECK_ARITY( args, ARITY, title_ );
2663 RefCountPtr< const Lang::Value > arg1 = args.getValue( 0 );
2664 RefCountPtr< const Lang::Value > arg2 = args.getValue( 1 );
2668 Kernel::ContRef cont = evalState->cont_;
2669 cont->takeValue( arg1->binaryDispatch1( arg1, arg2, evalState->dyn_, opExpr_ ),
2670 evalState );
2672 catch( Exceptions::BinaryInfixNotApplicable & ball )
2674 ball.setOperatorSymbol( title_ );
2675 throw;
2679 bool
2680 Lang::BinaryOperatorFunction::isTransforming( ) const
2682 return false;
2685 void
2686 Lang::BinaryOperatorFunction::show( std::ostream & os ) const
2688 os << "< binary operator function for " << title_ << " >" ;
2692 Lang::UnaryOperatorFunction::UnaryOperatorFunction( Ast::UnaryExpr * opExpr, const char * title )
2693 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) ), opExpr_( opExpr ), title_( title )
2695 formals_->appendEvaluatedCoreFormal( "only", Kernel::THE_SLOT_VARIABLE );
2698 Lang::UnaryOperatorFunction::~UnaryOperatorFunction( )
2700 delete opExpr_;
2703 void
2704 Lang::UnaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2706 const size_t ARITY = 1;
2707 CHECK_ARITY( args, ARITY, title_ );
2709 RefCountPtr< const Lang::Value > arg = args.getValue( 0 );
2713 Kernel::ContRef cont = evalState->cont_;
2714 cont->takeValue( arg->unaryDispatch( arg, evalState->dyn_, opExpr_ ),
2715 evalState );
2717 catch( Exceptions::UnaryPrefixNotApplicable & ball )
2719 ball.setOperatorSymbol( title_ );
2720 throw;
2722 catch( Exceptions::UnaryPostfixNotApplicable & ball )
2724 ball.setOperatorSymbol( title_ );
2725 throw;
2729 bool
2730 Lang::UnaryOperatorFunction::isTransforming( ) const
2732 return false;
2735 void
2736 Lang::UnaryOperatorFunction::show( std::ostream & os ) const
2738 os << "< unary operator function for " << title_ << " >" ;
2742 Lang::Transform2DMethod_chop::Transform2DMethod_chop( RefCountPtr< const Lang::Transform2D > self, const Ast::FileID * fullMethodID )
2743 : Lang::MethodBase< class_type >( self, fullMethodID, false, true )
2745 formals_->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE );
2746 formals_->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE );
2749 Lang::Transform2DMethod_chop::~Transform2DMethod_chop( )
2752 void
2753 Lang::Transform2DMethod_chop::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2755 args.applyDefaults( );
2757 size_t argsi = 0;
2758 double Ltol = Helpers::down_cast_CoreArgument< const Lang::Float >( title_, args, argsi, callLoc )->val_;
2759 if( Ltol < 0 )
2761 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2764 ++argsi;
2765 Concrete::Length ptol = Helpers::down_cast_CoreArgument< const Lang::Length >( title_, args, argsi, callLoc )->get( );
2766 if( ptol < Concrete::ZERO_LENGTH )
2768 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2771 Lang::Transform2D * res = self_->clone( );
2773 CHOP_Ltol( res->xx_ );
2774 CHOP_Ltol( res->yx_ );
2776 CHOP_Ltol( res->xy_ );
2777 CHOP_Ltol( res->yy_ );
2779 CHOP_ptol( res->xt_ );
2780 CHOP_ptol( res->yt_ );
2782 Kernel::ContRef cont = evalState->cont_;
2783 cont->takeValue( RefCountPtr< const Lang::Value >( res ),
2784 evalState );
2788 Lang::Transform3DMethod_chop::Transform3DMethod_chop( RefCountPtr< const Lang::Transform3D > self, const Ast::FileID * fullMethodID )
2789 : Lang::MethodBase< class_type >( self, fullMethodID, false, true )
2791 formals_->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE );
2792 formals_->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE );
2795 Lang::Transform3DMethod_chop::~Transform3DMethod_chop( )
2798 void
2799 Lang::Transform3DMethod_chop::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2801 args.applyDefaults( );
2803 size_t argsi = 0;
2804 double Ltol = Helpers::down_cast_CoreArgument< const Lang::Float >( title_, args, argsi, callLoc )->val_;
2805 if( Ltol < 0 )
2807 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2810 ++argsi;
2811 Concrete::Length ptol = Helpers::down_cast_CoreArgument< const Lang::Length >( title_, args, argsi, callLoc )->get( );
2812 if( ptol < Concrete::ZERO_LENGTH )
2814 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2817 Lang::Transform3D * res = self_->clone( );
2819 CHOP_Ltol( res->xx_ );
2820 CHOP_Ltol( res->yx_ );
2821 CHOP_Ltol( res->zx_ );
2823 CHOP_Ltol( res->xy_ );
2824 CHOP_Ltol( res->yy_ );
2825 CHOP_Ltol( res->zy_ );
2827 CHOP_Ltol( res->xz_ );
2828 CHOP_Ltol( res->yz_ );
2829 CHOP_Ltol( res->zz_ );
2831 CHOP_ptol( res->xt_ );
2832 CHOP_ptol( res->yt_ );
2833 CHOP_ptol( res->zt_ );
2835 Kernel::ContRef cont = evalState->cont_;
2836 cont->takeValue( RefCountPtr< const Lang::Value >( res ),
2837 evalState );