Namespace documentation: Private namespaces and detailed look-up rules
[shapes.git] / source / functiontypes.cc
blob3602b888210c1559019e311bd35d32ce3559c23d
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 typedef typeof locations_ MyLocationsType;
1095 for( MyListType::iterator dst = variables_->begin( ); dst != variables_->end( ); ++dst, ++src, ++srcLoc, ++pos )
1097 if( *dst == Kernel::THE_SLOT_VARIABLE )
1099 /* Handle error situation.
1101 if( *src == Kernel::THE_SLOT_VARIABLE )
1103 if( missingArgs == 0 )
1105 missingArgs = new typeof *missingArgs;
1107 typedef typeof *(formals_->formals_->argumentOrder_) FormalsMapType;
1108 FormalsMapType & formalsMap = *(formals_->formals_->argumentOrder_);
1109 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
1111 if( i->second == pos )
1113 missingArgs->insert( missingArgs->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1114 break;
1116 ++i;
1117 if( i == formalsMap.end( ) )
1119 throw Exceptions::InternalError( "Failed to find position of missing argument." );
1124 /* Normal case.
1126 *dst = *src;
1127 locations_[ pos ] = *srcLoc;
1131 if( missingArgs != 0 || missingStates != 0 )
1133 throw Exceptions::MissingArguments( formals_->formals_->loc( ), missingArgs, missingStates );
1136 if( hasSink_ )
1138 variables_->push_back
1139 ( Helpers::newValHandle
1140 ( new Lang::Structure( sinkArgList_,
1141 sinkValues_,
1142 true ) ) ); // true means that the sinkArgList_ gets owned by the Structure.
1143 sinkArgList_ = 0;
1148 Kernel::VariableHandle &
1149 Kernel::Arguments::getHandle( size_t i )
1151 return (*variables_)[ i ];
1154 RefCountPtr< const Lang::Value > &
1155 Kernel::Arguments::getValue( size_t i )
1157 return (*variables_)[ i ]->getUntyped( );
1160 const Ast::SourceLocation &
1161 Kernel::Arguments::getLoc( size_t i ) const
1163 return locations_[ i ]->loc( );
1166 const Ast::Node *
1167 Kernel::Arguments::getNode( size_t i ) const
1169 return locations_[ i ];
1172 Kernel::Thunk *
1173 Kernel::Arguments::getThunk( size_t i )
1175 return (*variables_)[ i ]->copyThunk( );
1178 bool
1179 Kernel::Arguments::isSlot( size_t i ) const
1181 return (*variables_)[ i ] == Kernel::THE_SLOT_VARIABLE;
1184 Kernel::StateHandle
1185 Kernel::Arguments::getState( size_t i )
1187 return (*states_)[ i ];
1190 const Ast::SourceLocation &
1191 Kernel::Arguments::getStateLoc( size_t i ) const
1193 return stateLocations_[ i ]->loc( );
1196 size_t
1197 Kernel::Arguments::size( ) const
1199 return variables_->size( );
1202 bool
1203 Kernel::Arguments::empty( ) const
1205 return variables_->empty( );
1208 void
1209 Kernel::Arguments::setMutatorSelf( Kernel::StateHandle mutatorSelf )
1211 mutatorSelf_ = mutatorSelf;
1214 Kernel::StateHandle
1215 Kernel::Arguments::getMutatorSelf( )
1217 if( mutatorSelf_ == 0 )
1219 throw Exceptions::InternalError( "Kernel::Arguments::getMutatorSelf: self is null." );
1221 return mutatorSelf_;
1224 void
1225 Kernel::Arguments::gcMark( Kernel::GCMarkedSet & marked )
1228 typedef typeof *variables_ ListType;
1229 for( ListType::const_iterator i = variables_->begin( ); i != variables_->end( ); ++i )
1231 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1236 Kernel::Environment::ValueVector
1237 Kernel::Arguments::getVariables( )
1239 return variables_;
1242 Kernel::Environment::StateVector
1243 Kernel::Arguments::getStates( )
1245 return states_;
1249 namespace Shapes
1251 namespace Kernel
1254 class FunctionOneHandleCont : public Kernel::Continuation
1256 RefCountPtr< const Lang::Function > fun_;
1257 Kernel::PassedDyn dyn_;
1258 Kernel::ContRef cont_;
1259 public:
1260 FunctionOneHandleCont( const RefCountPtr< const Lang::Function > & fun, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1261 : Kernel::Continuation( traceLoc ), fun_( fun ), dyn_( dyn ), cont_( cont )
1263 virtual ~FunctionOneHandleCont( ) { }
1264 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
1266 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1267 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1270 if( val->isThunk( ) )
1272 val->force( val, evalState );
1273 return;
1276 Kernel::Arguments args = fun_->newCurriedArguments( );
1277 args.addOrderedArgument( val, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1279 evalState->dyn_ = dyn_;
1280 evalState->cont_ = cont_;
1281 fun_->call( evalState, args, traceLoc_ );
1283 virtual Kernel::ContRef up( ) const
1285 return cont_;
1287 virtual RefCountPtr< const char > description( ) const
1289 return strrefdup( "internal function call with one handle" );
1291 virtual void gcMark( Kernel::GCMarkedSet & marked )
1293 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1294 dyn_->gcMark( marked );
1295 cont_->gcMark( marked );
1299 class FunctionTwoHandlesCont_2 : public Kernel::Continuation
1301 RefCountPtr< const Lang::Function > fun_;
1302 Kernel::VariableHandle arg1_;
1303 Kernel::PassedDyn dyn_;
1304 Kernel::ContRef cont_;
1305 public:
1306 FunctionTwoHandlesCont_2( const RefCountPtr< const Lang::Function > & fun, const Kernel::VariableHandle & arg1, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1307 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), dyn_( dyn ), cont_( cont )
1309 virtual ~FunctionTwoHandlesCont_2( ) { }
1310 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1312 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1313 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1316 if( arg2->isThunk( ) )
1318 arg2->force( arg2, evalState );
1319 return;
1322 Kernel::Arguments args = fun_->newCurriedArguments( );
1323 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1324 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1325 evalState->dyn_ = dyn_;
1326 evalState->cont_ = cont_;
1327 fun_->call( evalState, args, traceLoc_ );
1329 virtual Kernel::ContRef up( ) const
1331 return cont_;
1333 virtual RefCountPtr< const char > description( ) const
1335 return strrefdup( "internal function call with two handles, second" );
1337 virtual void gcMark( Kernel::GCMarkedSet & marked )
1339 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1340 dyn_->gcMark( marked );
1341 cont_->gcMark( marked );
1345 class FunctionTwoHandlesCont_1 : public Kernel::Continuation
1347 RefCountPtr< const Lang::Function > fun_;
1348 Kernel::VariableHandle arg2_;
1349 bool forceArg2_;
1350 Kernel::PassedDyn dyn_;
1351 Kernel::ContRef cont_;
1352 public:
1353 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 )
1354 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), dyn_( dyn ), cont_( cont )
1356 virtual ~FunctionTwoHandlesCont_1( ) { }
1357 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1359 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1360 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1363 if( arg1->isThunk( ) )
1365 arg1->force( arg1, evalState );
1366 return;
1369 if( forceArg2_ )
1371 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( fun_, arg1, dyn_, cont_, traceLoc_ ) );
1372 evalState->cont_ = newCont;
1373 newCont->takeHandle( arg2_, evalState );
1374 return;
1377 /* The second handle need not be forced
1379 Kernel::Arguments args = fun_->newCurriedArguments( );
1380 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1381 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1382 evalState->dyn_ = dyn_;
1383 evalState->cont_ = cont_;
1384 fun_->call( evalState, args, traceLoc_ );
1386 virtual Kernel::ContRef up( ) const
1388 return cont_;
1390 virtual RefCountPtr< const char > description( ) const
1392 return strrefdup( "internal function call with two handles, first" );
1394 virtual void gcMark( Kernel::GCMarkedSet & marked )
1396 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1397 dyn_->gcMark( marked );
1398 cont_->gcMark( marked );
1402 class FunctionTwoHandlesOneStateCont_2 : public Kernel::Continuation
1404 RefCountPtr< const Lang::Function > fun_;
1405 Kernel::VariableHandle arg1_;
1406 Kernel::StateHandle state_;
1407 Kernel::PassedDyn dyn_;
1408 Kernel::ContRef cont_;
1409 public:
1410 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 )
1411 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), state_( state ), dyn_( dyn ), cont_( cont )
1413 virtual ~FunctionTwoHandlesOneStateCont_2( ) { }
1414 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1416 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1417 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1420 if( arg2->isThunk( ) )
1422 arg2->force( arg2, evalState );
1423 return;
1426 Kernel::Arguments args = fun_->newCurriedArguments( );
1427 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1428 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1429 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1430 evalState->dyn_ = dyn_;
1431 evalState->cont_ = cont_;
1432 fun_->call( evalState, args, traceLoc_ );
1434 virtual Kernel::ContRef up( ) const
1436 return cont_;
1438 virtual RefCountPtr< const char > description( ) const
1440 return strrefdup( "internal function call with two handles and one state, second" );
1442 virtual void gcMark( Kernel::GCMarkedSet & marked )
1444 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1445 state_->gcMark( marked );
1446 dyn_->gcMark( marked );
1447 cont_->gcMark( marked );
1451 class FunctionTwoHandlesOneStateCont_1 : public Kernel::Continuation
1453 RefCountPtr< const Lang::Function > fun_;
1454 Kernel::VariableHandle arg2_;
1455 bool forceArg2_;
1456 Kernel::StateHandle state_;
1457 Kernel::PassedDyn dyn_;
1458 Kernel::ContRef cont_;
1459 public:
1460 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 )
1461 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), state_( state ), dyn_( dyn ), cont_( cont )
1463 virtual ~FunctionTwoHandlesOneStateCont_1( ) { }
1464 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1466 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1467 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1470 if( arg1->isThunk( ) )
1472 arg1->force( arg1, evalState );
1473 return;
1476 if( forceArg2_ )
1478 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( fun_, arg1, state_, dyn_, cont_, traceLoc_ ) );
1479 evalState->cont_ = newCont;
1480 newCont->takeHandle( arg2_, evalState );
1481 return;
1484 /* The second handle need not be forced
1486 Kernel::Arguments args = fun_->newCurriedArguments( );
1487 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1488 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1489 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1490 evalState->dyn_ = dyn_;
1491 evalState->cont_ = cont_;
1492 fun_->call( evalState, args, traceLoc_ );
1494 virtual Kernel::ContRef up( ) const
1496 return cont_;
1498 virtual RefCountPtr< const char > description( ) const
1500 return strrefdup( "internal function call with two handles and one state, first" );
1502 virtual void gcMark( Kernel::GCMarkedSet & marked )
1504 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1505 dyn_->gcMark( marked );
1506 cont_->gcMark( marked );
1507 state_->gcMark( marked );
1515 Lang::Function::Function( Kernel::EvaluatedFormals * formals )
1516 : formals_( formals )
1519 DISPATCHIMPL( Function );
1521 Lang::Function::~Function( )
1523 if( formals_ != 0 )
1525 delete formals_->formals_;
1526 delete formals_;
1530 Kernel::ValueRef
1531 Lang::Function::transformed( const Lang::Transform2D & tf, Kernel::ValueRef self ) const
1533 return Kernel::ValueRef( new Lang::TransformedFunction2D( tf, self.down_cast< const Lang::Function >( ) ) );
1536 void
1537 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Ast::SourceLocation & callLoc ) const
1539 Kernel::Arguments args = this->newCurriedArguments( );
1541 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1543 this->call( evalState, args, callLoc );
1546 void
1547 Lang::Function::analyze( Ast::Node * parent, Ast::AnalysisEnvironment * env )
1549 Ast::StateIDSet * freeStates = new Ast::StateIDSet;
1550 this->analyze_impl( parent, env, freeStates );
1551 if( ! freeStates->empty( ) )
1553 Ast::theAnalysisErrorsList.push_back( new Exceptions::IllegalFreeStates( parent->loc( ), freeStates, "this is a function" ) );
1555 else
1557 delete freeStates;
1561 void
1562 Lang::Function::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1564 throw Exceptions::InternalError( "A syntax function is not overriding the analyze method." );
1567 void
1568 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Kernel::ValueRef & arg2, const Ast::SourceLocation & callLoc ) const
1570 Kernel::Arguments args = this->newCurriedArguments( );
1572 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1573 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg2 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1575 this->call( evalState, args, callLoc );
1578 Ast::ArgListExprs * Lang::Function::oneExprArgList = new Ast::ArgListExprs( static_cast< size_t >( 1 ) );
1579 Ast::ArgListExprs * Lang::Function::twoExprsArgList = new Ast::ArgListExprs( static_cast< size_t >( 2 ) );
1581 void
1582 Lang::Function::call( const RefCountPtr< const Lang::Function > & selfRef, Kernel::EvalState * evalState, const Kernel::VariableHandle & arg1, const Ast::SourceLocation & callLoc ) const
1584 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::oneExprArgList, *evalState );
1586 if( info->force( 0 ) )
1588 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionOneHandleCont( selfRef, evalState->dyn_, evalState->cont_, callLoc ) );
1589 evalState->cont_ = cont;
1590 cont->takeHandle( arg1, evalState );
1591 return;
1594 /* The handle need not be forced
1596 Kernel::Arguments args = this->newCurriedArguments( );
1597 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1598 this->call( evalState, args, callLoc );
1601 void
1602 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
1604 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1606 /* Remember that arguments are ordered backwards!
1609 if( info->force( 1 ) )
1611 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_1( selfRef, arg2, info->force( 0 ), evalState->dyn_, evalState->cont_, callLoc ) );
1612 evalState->cont_ = cont;
1613 cont->takeHandle( arg1, evalState );
1614 return;
1617 if( info->force( 0 ) )
1619 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( selfRef, arg1, evalState->dyn_, evalState->cont_, callLoc ) );
1620 evalState->cont_ = cont;
1621 cont->takeHandle( arg2, evalState );
1622 return;
1625 /* None of the handles need to be forced
1627 Kernel::Arguments args = this->newCurriedArguments( );
1628 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1629 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1630 this->call( evalState, args, callLoc );
1633 void
1634 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
1636 /* I'm not quite sure if we should also put a dummy state argument in info...
1638 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1640 /* Remember that arguments are ordered backwards!
1643 if( info->force( 1 ) )
1645 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_1( selfRef, arg2, info->force( 0 ), state, evalState->dyn_, evalState->cont_, callLoc ) );
1646 evalState->cont_ = cont;
1647 cont->takeHandle( arg1, evalState );
1648 return;
1651 if( info->force( 0 ) )
1653 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( selfRef, arg1, state, evalState->dyn_, evalState->cont_, callLoc ) );
1654 evalState->cont_ = cont;
1655 cont->takeHandle( arg2, evalState );
1656 return;
1659 /* None of the handles need to be forced
1661 Kernel::Arguments args = this->newCurriedArguments( );
1662 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1663 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1664 args.addOrderedState( state, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1665 this->call( evalState, args, callLoc );
1669 RefCountPtr< Kernel::CallContInfo >
1670 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1672 return formals_->newCallContInfo( argList, evalState );
1675 RefCountPtr< Kernel::CallContInfo >
1676 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1678 return formals_->newCallContInfo( argList, evalState, curryArgs );
1681 Kernel::Arguments
1682 Lang::Function::newCurriedArguments( ) const
1684 return Kernel::Arguments( formals_ );
1688 RefCountPtr< const Lang::Class > Lang::Function::TypeID( new Lang::SystemFinalClass( strrefdup( "Function" ) ) );
1689 TYPEINFOIMPL( Function );
1691 Kernel::EvaluatedFormals::EvaluatedFormals( Kernel::Formals * formals )
1692 : selectiveForcing_( false ), forceAll_( false ), formals_( formals ), isSink_( true )
1695 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID * locationFileID )
1696 : selectiveForcing_( true ), formals_( 0 ), isSink_( true )
1698 Kernel::Formals * formals( new Kernel::Formals( ) );
1699 formals->setLoc( Ast::SourceLocation( locationFileID ) );
1700 formals_ = formals;
1703 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID * locationFileID, bool forceAll)
1704 : selectiveForcing_( false ), forceAll_( forceAll ), formals_( 0 ), isSink_( true )
1706 Kernel::Formals * formals( new Kernel::Formals( ) );
1707 formals->setLoc( Ast::SourceLocation( locationFileID ) );
1708 formals_ = formals;
1711 Kernel::EvaluatedFormals::~EvaluatedFormals( )
1713 /* Don't delete the orderedFormals, since we don't own it. A case for reference counting? */
1716 RefCountPtr< Kernel::CallContInfo >
1717 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1719 if( selectiveForcing_ )
1721 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList ) ) );
1723 else
1725 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1729 RefCountPtr< Kernel::CallContInfo >
1730 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1732 if( selectiveForcing_ )
1734 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList, curryArgs ) ) );
1736 else
1738 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1742 void
1743 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc, bool force )
1745 if( ! selectiveForcing_ )
1747 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function does not have selective forcing." );
1749 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1750 formals_->forcePos_.push_back( force );
1751 defaults_.push_back( defaultVal );
1752 locations_.push_back( loc );
1755 void
1756 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc )
1758 if( selectiveForcing_ )
1760 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function requires individual forcing specification." );
1762 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1763 formals_->forcePos_.push_back( forceAll_ );
1764 defaults_.push_back( defaultVal );
1765 locations_.push_back( loc );
1768 void
1769 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal, bool force )
1771 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION, force );
1774 void
1775 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal )
1777 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION );
1780 void
1781 Kernel::EvaluatedFormals::appendCoreStateFormal( const char * id )
1783 (*(formals_->stateOrder_))[ id ] = formals_->stateOrder_->size( );
1786 void
1787 Kernel::EvaluatedFormals::gcMark( Kernel::GCMarkedSet & marked )
1789 typedef typeof defaults_ ListType;
1790 for( ListType::const_iterator i = defaults_.begin( ); i != defaults_.end( ); ++i )
1792 if( *i != NullPtr< Kernel::Variable >( ) )
1794 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1800 Lang::CuteFunction::CuteFunction( RefCountPtr< const Lang::Function > callee, const Kernel::Arguments & someArgs )
1801 : Lang::Function( 0 ), callee_( callee), someArgs_( someArgs.clone( ) )
1804 Lang::CuteFunction::~CuteFunction( )
1807 RefCountPtr< Kernel::CallContInfo >
1808 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1810 return callee_->newCallContInfo( argList, evalState, someArgs_ );
1813 RefCountPtr< Kernel::CallContInfo >
1814 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1816 /* when we are the callee of a CuteFunction, our someArgs are part of that CuteFunction's someArgs, and hence curryArgs
1817 * contains everything that is to be passed to our callee.
1819 return callee_->newCallContInfo( argList, evalState, curryArgs );
1822 Kernel::Arguments
1823 Lang::CuteFunction::newCurriedArguments( ) const
1825 return someArgs_.clone( );
1828 void
1829 Lang::CuteFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1831 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1832 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.
1834 callee_->call( evalState, args, callLoc );
1837 bool
1838 Lang::CuteFunction::isTransforming( ) const
1840 return callee_->isTransforming( );
1843 void
1844 Lang::CuteFunction::gcMark( Kernel::GCMarkedSet & marked )
1846 const_cast< Lang::Function * >( callee_.getPtr( ) )->gcMark( marked );
1847 someArgs_.gcMark( marked );
1850 void
1851 Lang::CuteFunction::show( std::ostream & os ) const
1853 os << "< evaluated cut of: " ;
1854 callee_->show( os );
1855 os << " >" ;
1859 Lang::ComposedFunction::ComposedFunction( const RefCountPtr< const Lang::Function > & second, const RefCountPtr< const Lang::Function > & first )
1860 : Lang::Function( 0 ), second_( second ), first_( first )
1863 Lang::ComposedFunction::~ComposedFunction( )
1866 void
1867 Lang::ComposedFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1869 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1870 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.
1872 evalState->cont_ = Kernel::ContRef( new Kernel::ComposedFunctionCall_cont( second_, evalState->dyn_, evalState->cont_, callLoc ) );
1873 first_->call( evalState, args, callLoc );
1876 RefCountPtr< Kernel::CallContInfo >
1877 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1879 return first_->newCallContInfo( argList, evalState );
1882 RefCountPtr< Kernel::CallContInfo >
1883 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1885 return first_->newCallContInfo( argList, evalState, curryArgs );
1888 Kernel::Arguments
1889 Lang::ComposedFunction::newCurriedArguments( ) const
1891 return first_->newCurriedArguments( );
1894 bool
1895 Lang::ComposedFunction::isTransforming( ) const
1897 return second_->isTransforming( );
1900 void
1901 Lang::ComposedFunction::gcMark( Kernel::GCMarkedSet & marked )
1903 const_cast< Lang::Function * >( second_.getPtr( ) )->gcMark( marked );
1904 const_cast< Lang::Function * >( first_.getPtr( ) )->gcMark( marked );
1907 void
1908 Lang::ComposedFunction::show( std::ostream & os ) const
1910 os << "< composition: " ;
1911 second_->show( os );
1912 os << " () " ;
1913 first_->show( os );
1914 os << " >" ;
1918 namespace Shapes
1920 namespace Kernel
1922 class SpanThunks
1924 std::vector< Kernel::VariableHandle > thunks_;
1925 public:
1926 SpanThunks( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count )
1928 thunks_.reserve( 4 );
1929 thunks_.push_back( count );
1930 thunks_.push_back( step );
1931 thunks_.push_back( end );
1932 thunks_.push_back( begin );
1934 const Kernel::VariableHandle & operator [] ( size_t i ) const
1936 return thunks_[ i ];
1938 ~SpanThunks( )
1940 void gcMark( Kernel::GCMarkedSet & marked )
1942 typedef typeof thunks_ VecType;
1943 for( VecType::iterator i = thunks_.begin( ); i != thunks_.end( ); ++i )
1945 (*i)->gcMark( marked );
1950 class SpanForcingContinuation : public Continuation
1952 RefCountPtr< const Kernel::SpanThunks > thunks_;
1953 size_t i_;
1954 RefCountPtr< const Lang::SingleList > values_;
1955 RefCountPtr< const Lang::Value > last_;
1956 Kernel::ContRef cont_;
1957 public:
1958 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 )
1959 : Kernel::Continuation( traceLoc ), thunks_( thunks ), i_( i ), values_( values ), last_( last ), cont_( cont )
1961 ~SpanForcingContinuation( )
1963 static void finish( RefCountPtr< const Lang::SingleList > values, RefCountPtr< const Lang::Value > last, Kernel::EvalState * evalState, const Ast::SourceLocation & traceLoc )
1965 Kernel::Arguments args = Lang::THE_FUNCTION_RANGE->newCurriedArguments( );
1966 RefCountPtr< const Lang::SingleListPair > src = values.down_cast< const Lang::SingleListPair >( );
1967 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1968 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1969 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1970 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1971 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1972 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1973 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1974 Lang::Core_range::makeRange( "<span>", evalState, args, traceLoc, true, last );
1976 virtual void takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
1978 RefCountPtr< const Lang::SingleList > values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( val ) ), values_ ) );
1980 for( size_t i = i_ + 1; i < 4; ++i )
1982 const Kernel::VariableHandle & var = (*thunks_)[ i ];
1983 if( var->isThunk( ) )
1985 evalState->cont_ = Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_, i, values, last_, cont_, traceLoc_ ) );
1986 var->force( var, evalState );
1987 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, last_ ) );
1988 return;
1990 values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( var, values ) );
1992 evalState->cont_ = cont_;
1993 finish( values, last_, evalState, traceLoc_ );
1995 virtual Kernel::ContRef up( ) const
1997 return cont_;
1999 virtual RefCountPtr< const char > description( ) const
2001 std::ostringstream msg;
2002 msg << "force span parameter number " << i_ ;
2003 return strrefdup( msg );
2005 virtual void gcMark( Kernel::GCMarkedSet & marked )
2007 const_cast< Kernel::SpanThunks * >( thunks_.getPtr( ) )->gcMark( marked );
2008 const_cast< Lang::SingleList * >( values_.getPtr( ) )->gcMark( marked );
2009 const_cast< Lang::Value * >( last_.getPtr( ) )->gcMark( marked );
2010 cont_->gcMark( marked );
2016 RefCountPtr< const Lang::Class > Lang::Span::TypeID( new Lang::SystemFinalClass( strrefdup( "Span" ) ) );
2017 TYPEINFOIMPL( Span );
2019 Lang::Span::Span( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count )
2020 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<span>" ), true ) ),
2021 thunks_( new Kernel::SpanThunks( begin, end, step, count ) )
2023 formals_->appendEvaluatedCoreFormal( "last", Kernel::THE_SLOT_VARIABLE );
2026 Lang::Span::~Span( )
2029 void
2030 Lang::Span::gcMark( Kernel::GCMarkedSet & marked )
2032 const_cast< Kernel::SpanThunks * >( thunks_.getPtr( ) )->gcMark( marked );
2035 void
2036 Lang::Span::show( std::ostream & os ) const
2038 os << "<span>" ;
2041 void
2042 Lang::Span::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2044 args.applyDefaults( );
2046 RefCountPtr< const Lang::SingleList > values = Lang::THE_CONS_NULL;
2047 for( size_t i = 0; i < 4; ++i )
2049 const Kernel::VariableHandle & var = (*thunks_)[ i ];
2050 if( var->isThunk( ) )
2052 evalState->cont_ = Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_, i, values, args.getValue( 0 ), evalState->cont_, callLoc ) );
2053 var->force( var, evalState );
2054 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, args.getValue( 0 ) ) );
2055 return;
2057 values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( var, values ) );
2060 /* We only reach this point if there were no thunks at all to be forced. */
2061 Kernel::SpanForcingContinuation::finish( values, args.getValue( 0 ), evalState, callLoc );
2064 bool
2065 Lang::Span::isTransforming( ) const
2067 return false;
2071 Lang::UserFunction::UserFunction( Kernel::EvaluatedFormals * formals, Ast::Expression * body, Kernel::PassedEnv env, const Ast::FunctionMode & functionMode )
2072 : Lang::Function( formals ), body_( body ), env_( env ), functionMode_( functionMode )
2075 // DISPATCHIMPL( UserFunction );
2077 Lang::UserFunction::~UserFunction( )
2079 // Note that we don't delete the things that we most likely share with other objects
2080 // Reference counting could be used here, but there will never be more such things than there are function expressions in the source
2082 // This prevents formals->formals from being deleted by Lang::Function::~Function
2083 delete formals_;
2084 formals_ = 0;
2087 void
2088 Lang::UserFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2090 args.applyDefaults( );
2091 evalState->env_ = new Kernel::Environment( Kernel::theEnvironmentList, env_, formals_->formals_->argumentIdentifiers_, args.getVariables( ), formals_->formals_->stateIdentifiers_, args.getStates( ), "Closure" );
2092 evalState->expr_ = body_;
2095 bool
2096 Lang::UserFunction::isTransforming( ) const
2098 return ( functionMode_ & Ast::FUNCTION_TRANSFORMING ) != 0;
2101 void
2102 Lang::UserFunction::gcMark( Kernel::GCMarkedSet & marked )
2104 env_->gcMark( marked );
2107 Ast::Expression *
2108 Lang::UserFunction::body( )
2110 return body_;
2113 void
2114 Lang::UserFunction::show( std::ostream & os ) const
2116 os << "< user function with body at " << body_->loc( ) << " >" ;
2120 Lang::TransformedFunction2D::TransformedFunction2D( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Function > & fun )
2121 : Lang::Function( 0 ), tf_( tf ), fun_( fun )
2124 Lang::TransformedFunction2D::~TransformedFunction2D( )
2127 void
2128 Lang::TransformedFunction2D::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2130 evalState->cont_ = Kernel::ContRef( new Kernel::Transform2DCont( tf_, evalState->cont_, 0 ) );
2131 fun_->call( evalState, args, callLoc );
2134 bool
2135 Lang::TransformedFunction2D::isTransforming( ) const
2137 return fun_->isTransforming( );
2140 void
2141 Lang::TransformedFunction2D::gcMark( Kernel::GCMarkedSet & marked )
2143 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
2146 void
2147 Lang::TransformedFunction2D::show( std::ostream & os ) const
2149 os << "< transformed function >" ;
2154 Lang::VectorFunction::VectorFunction( const std::vector< Kernel::ValueRef > * mem )
2155 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<vector>" ), true ) ), mem_( mem ),
2156 memNumeric_( NullPtr< const std::vector< double > >( ) ),
2157 list_( NullPtr< Kernel::Variable >( ) )
2159 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
2162 // DISPATCHIMPL( VectorFunction );
2164 Lang::VectorFunction::~VectorFunction( )
2167 RefCountPtr< const Lang::Class > Lang::VectorFunction::TypeID( new Lang::SystemFinalClass( strrefdup( "VectorFunction" ), Kernel::VectorFunction_register_methods ) );
2168 TYPEINFOIMPL( VectorFunction );
2170 Kernel::VariableHandle
2171 Lang::VectorFunction::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
2173 if( strcmp( fieldID, "size" ) == 0 )
2175 return Helpers::newValHandle( new Lang::Integer( mem_->size( ) ) );
2177 if( strcmp( fieldID, "range" ) == 0 )
2179 return Helpers::newValHandle( new Lang::SingleListRange< Lang::Integer >( 0, 1, mem_->size( ) ) );
2181 if( strcmp( fieldID, "reverse_range" ) == 0 )
2183 return Helpers::newValHandle( new Lang::SingleListRange< Lang::Integer >( mem_->size( ) - 1, -1, mem_->size( ) ) );
2185 if( strcmp( fieldID, "list" ) == 0 )
2187 compute_list( );
2188 return list_;
2191 return TypeID->getMethod( selfRef, fieldID ); /* This will throw if there is no such method. */
2194 const char * Lang::VectorFunction::title_ = "<vector>";
2196 void
2197 Lang::VectorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2199 const size_t ARITY = 1;
2200 if( args.size( ) != ARITY )
2202 throw Exceptions::CoreArityMismatch( title_, ARITY, args.size( ) );
2205 typedef const Lang::Integer ArgType;
2206 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
2208 if( arg->val_ < 0 )
2210 throw Exceptions::CoreOutOfRange( title_, args, 0, "Index is negative." );
2213 if( arg->val_ >= static_cast< int >( mem_->size( ) ) )
2215 throw Exceptions::CoreOutOfRange( title_, args, 0, "Index exceeds vector size." );
2218 Kernel::ContRef cont = evalState->cont_;
2219 cont->takeValue( (*mem_)[ arg->val_ ],
2220 evalState );
2223 bool
2224 Lang::VectorFunction::isTransforming( ) const
2226 return false;
2229 void
2230 Lang::VectorFunction::gcMark( Kernel::GCMarkedSet & marked )
2232 gcMark( mem_, marked );
2235 void
2236 Lang::VectorFunction::gcMark( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, Kernel::GCMarkedSet & marked )
2238 for( std::vector< Kernel::ValueRef >::const_iterator i = mem->begin( ); i != mem->end( ); ++i )
2240 const_cast< Lang::Value * >( i->getPtr( ) )->gcMark( marked );
2244 void
2245 Lang::VectorFunction::show( std::ostream & os ) const
2247 os << "< vector function >" ;
2250 RefCountPtr< const std::vector< double > >
2251 Lang::VectorFunction::getNumeric( const Ast::SourceLocation & callLoc ) const
2253 if( memNumeric_ == NullPtr< const std::vector< double > >( ) )
2255 RefCountPtr< std::vector< double > > res( new std::vector< double > ); // Note that this is not const, so far...
2256 res->reserve( mem_->size( ) );
2257 typedef typeof *mem_ SrcType;
2258 for( SrcType::const_iterator src = mem_->begin( ); src != mem_->end( ); ++src )
2260 res->push_back( Helpers::down_cast< const Lang::Float >( *src, callLoc )->val_ );
2263 memNumeric_ = res;
2265 return memNumeric_;
2268 void
2269 Lang::VectorFunction::compute_list( ) const
2271 if( list_ != NullPtr< Kernel::Variable >( ) )
2273 return;
2275 RefCountPtr< const Lang::SingleList > newList = Lang::THE_CONS_NULL;
2276 typedef typeof *mem_ ListType;
2277 for( ListType::const_reverse_iterator src = mem_->rbegin( ); src != mem_->rend( ); ++src )
2279 newList = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( *src ) ), newList ) );
2281 list_ = Kernel::VariableHandle( new Kernel::Variable( newList ) );
2284 namespace Shapes
2286 namespace Kernel
2289 class VectorFunctionFoldLCont : public Kernel::Continuation
2291 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2292 RefCountPtr< const Lang::Function > op_;
2293 Shapes::Lang::VectorFunction::vector_type::const_iterator i_;
2294 Kernel::PassedDyn dyn_;
2295 Kernel::ContRef cont_;
2296 public:
2297 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 )
2298 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), dyn_( dyn ), cont_( cont )
2300 virtual ~VectorFunctionFoldLCont( ) { }
2301 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2303 evalState->dyn_ = dyn_;
2304 evalState->cont_ = cont_;
2305 Lang::VectorFunction::foldl( mem_, evalState, op_, val, i_, traceLoc_ );
2307 virtual Kernel::ContRef up( ) const
2309 return cont_;
2311 virtual RefCountPtr< const char > description( ) const
2313 return strrefdup( "VectorFunction's foldl" );
2315 virtual void gcMark( Kernel::GCMarkedSet & marked )
2317 Lang::VectorFunction::gcMark( mem_, marked );
2318 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2319 dyn_->gcMark( marked );
2320 cont_->gcMark( marked );
2324 class VectorFunctionFoldRCont : public Kernel::Continuation
2326 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2327 RefCountPtr< const Lang::Function > op_;
2328 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_;
2329 Kernel::PassedDyn dyn_;
2330 Kernel::ContRef cont_;
2331 public:
2332 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 )
2333 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), dyn_( dyn ), cont_( cont )
2335 virtual ~VectorFunctionFoldRCont( ) { }
2336 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2338 evalState->dyn_ = dyn_;
2339 evalState->cont_ = cont_;
2340 Lang::VectorFunction::foldr( mem_, evalState, op_, val, i_, traceLoc_ );
2342 virtual Kernel::ContRef up( ) const
2344 return cont_;
2346 virtual RefCountPtr< const char > description( ) const
2348 return strrefdup( "VectorFunction's foldr" );
2350 virtual void gcMark( Kernel::GCMarkedSet & marked )
2352 Lang::VectorFunction::gcMark( mem_, marked );
2353 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2354 dyn_->gcMark( marked );
2355 cont_->gcMark( marked );
2359 class VectorFunctionFoldSLCont : public Kernel::Continuation
2361 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2362 RefCountPtr< const Lang::Function > op_;
2363 Shapes::Lang::VectorFunction::vector_type::const_iterator i_;
2364 Kernel::StateHandle state_;
2365 Kernel::PassedDyn dyn_;
2366 Kernel::ContRef cont_;
2367 public:
2368 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 )
2369 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), state_( state ), dyn_( dyn ), cont_( cont )
2371 virtual ~VectorFunctionFoldSLCont( ) { }
2372 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2374 evalState->dyn_ = dyn_;
2375 evalState->cont_ = cont_;
2376 Lang::VectorFunction::foldsl( mem_, evalState, op_, val, state_, i_, traceLoc_ );
2378 virtual Kernel::ContRef up( ) const
2380 return cont_;
2382 virtual RefCountPtr< const char > description( ) const
2384 return strrefdup( "VectorFunction's foldsl" );
2386 virtual void gcMark( Kernel::GCMarkedSet & marked )
2388 Lang::VectorFunction::gcMark( mem_, marked );
2389 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2390 state_->gcMark( marked );
2391 dyn_->gcMark( marked );
2392 cont_->gcMark( marked );
2396 class VectorFunctionFoldSRCont : public Kernel::Continuation
2398 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2399 RefCountPtr< const Lang::Function > op_;
2400 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_;
2401 Kernel::StateHandle state_;
2402 Kernel::PassedDyn dyn_;
2403 Kernel::ContRef cont_;
2404 public:
2405 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 )
2406 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), state_( state ), dyn_( dyn ), cont_( cont )
2408 virtual ~VectorFunctionFoldSRCont( ) { }
2409 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2411 evalState->dyn_ = dyn_;
2412 evalState->cont_ = cont_;
2413 Lang::VectorFunction::foldsr( mem_, evalState, op_, val, state_, i_, traceLoc_ );
2415 virtual Kernel::ContRef up( ) const
2417 return cont_;
2419 virtual RefCountPtr< const char > description( ) const
2421 return strrefdup( "VectorFunction's foldsr" );
2423 virtual void gcMark( Kernel::GCMarkedSet & marked )
2425 Lang::VectorFunction::gcMark( mem_, marked );
2426 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2427 state_->gcMark( marked );
2428 dyn_->gcMark( marked );
2429 cont_->gcMark( marked );
2436 void
2437 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 )
2439 if( i == mem->end( ) )
2441 Kernel::ContRef cont = evalState->cont_;
2442 cont->takeHandle( nullResult,
2443 evalState );
2444 return;
2447 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2448 ++i;
2449 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldLCont( mem, op, i, evalState->dyn_, evalState->cont_, callLoc ) );
2451 op->call( op, evalState, nullResult, elem, callLoc );
2454 void
2455 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 )
2457 if( i == mem->rend( ) )
2459 Kernel::ContRef cont = evalState->cont_;
2460 cont->takeHandle( nullResult,
2461 evalState );
2462 return;
2465 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2466 ++i;
2467 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldRCont( mem, op, i, evalState->dyn_, evalState->cont_, callLoc ) );
2469 op->call( op, evalState, nullResult, elem, callLoc );
2472 void
2473 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 )
2475 if( i == mem->end( ) )
2477 Kernel::ContRef cont = evalState->cont_;
2478 cont->takeHandle( nullResult,
2479 evalState );
2480 return;
2483 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2484 ++i;
2485 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldSLCont( mem, op, i, state, evalState->dyn_, evalState->cont_, callLoc ) );
2487 op->call( op, evalState, nullResult, elem, state, callLoc );
2490 void
2491 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 )
2493 if( i == mem->rend( ) )
2495 Kernel::ContRef cont = evalState->cont_;
2496 cont->takeHandle( nullResult,
2497 evalState );
2498 return;
2501 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2502 ++i;
2503 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldSRCont( mem, op, i, state, evalState->dyn_, evalState->cont_, callLoc ) );
2505 op->call( op, evalState, nullResult, elem, state, callLoc );
2509 const char * Lang::ColorInterpolator::title_ = "<color-interpolator>";
2511 Lang::ColorInterpolator::ColorInterpolator( const RefCountPtr< KeyContainer > & key,
2512 const RefCountPtr< RGBContainer > & RGBcolor,
2513 const RefCountPtr< GrayContainer > & graycolor,
2514 const RefCountPtr< CMYKContainer > & CMYKcolor,
2515 ColorType colorType)
2516 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( Lang::ColorInterpolator::title_ ), true ) ),
2517 key_( key ), RGBcolor_ ( RGBcolor ), graycolor_ ( graycolor ), CMYKcolor_ ( CMYKcolor ), colorType_(colorType)
2519 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
2522 Lang::ColorInterpolator::~ColorInterpolator( )
2525 Kernel::VariableHandle
2526 Lang::ColorInterpolator::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
2528 if( strcmp( fieldID, "low" ) == 0 )
2530 return Helpers::newValHandle( new Lang::Float( key_->front( ) ) );
2532 if( strcmp( fieldID, "high" ) == 0 )
2534 return Helpers::newValHandle( new Lang::Float( key_->back( ) ) );
2536 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
2540 template <class COLOR_TYPE, class COLOR_CONTAINER>
2541 void
2542 Lang::ColorInterpolator::callHelper( Kernel::EvalState * evalState,
2543 const RefCountPtr< COLOR_CONTAINER > & colorContainer,
2544 double key, KeyContainer::const_iterator keyHi ) const
2546 if( keyHi == key_->end( ) )
2548 Kernel::ContRef cont = evalState->cont_;
2549 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->back( ) ) ),
2550 evalState );
2551 return;
2554 if( keyHi == key_->begin( ) )
2556 Kernel::ContRef cont = evalState->cont_;
2557 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->front( ) ) ),
2558 evalState );
2559 return;
2562 KeyContainer::const_iterator keyLo = keyHi - 1;
2563 double rem = ( key - *keyLo ) / ( *keyHi - *keyLo );
2565 Kernel::ContRef cont = evalState->cont_;
2567 typename COLOR_CONTAINER::const_iterator colorHi = colorContainer->begin( ) + ( keyHi - key_->begin( ) );
2568 typename COLOR_CONTAINER::const_iterator colorLo = colorHi - 1;
2570 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorLo->mulNoCheck( 1 - rem ).addNoCheck( colorHi->mulNoCheck( rem ) ) ) ),
2571 evalState );
2575 void
2576 Lang::ColorInterpolator::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2578 const size_t ARITY = 1;
2579 if( args.size( ) != ARITY )
2581 throw Exceptions::CoreArityMismatch( title_, ARITY, args.size( ) );
2584 typedef const Lang::Float ArgType;
2585 double key = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc )->val_;
2587 KeyContainer::const_iterator keyHi = lower_bound( key_->begin( ), key_->end( ), key );
2588 switch( colorType_ )
2590 case RGB:
2591 callHelper< Lang::RGB >( evalState, RGBcolor_, key, keyHi );
2592 break;
2593 case GRAY:
2594 callHelper< Lang::Gray >( evalState, graycolor_, key, keyHi );
2595 break;
2596 case CMYK:
2597 callHelper< Lang::CMYK >( evalState, CMYKcolor_, key, keyHi );
2598 break;
2599 case UNDEFINED:
2600 throw Exceptions::InternalError( "ColorInterpolator::call: Did not expect UNDEFINED in ennum switch." );
2604 bool
2605 Lang::ColorInterpolator::isTransforming( ) const
2607 return false;
2610 void
2611 Lang::ColorInterpolator::gcMark( Kernel::GCMarkedSet & marked )
2614 void
2615 Lang::ColorInterpolator::show( std::ostream & os ) const
2617 os << "< color interpolator in " ;
2618 switch( colorType_ )
2620 case RGB:
2621 os << "RGB" ;
2622 break;
2623 case GRAY:
2624 os << "Gray" ;
2625 break;
2626 case CMYK:
2627 os << "CMYK" ;
2628 break;
2629 case UNDEFINED:
2630 throw Exceptions::InternalError( "ColorInterpolator::show: Did not expect UNDEFINED in ennum switch." );
2632 os << " mode >" ;
2635 Lang::BinaryOperatorFunction::BinaryOperatorFunction( Ast::BinaryInfixExpr * opExpr, const char * title )
2636 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) ), opExpr_( opExpr ), title_( title )
2638 formals_->appendEvaluatedCoreFormal( "first", Kernel::THE_SLOT_VARIABLE );
2639 formals_->appendEvaluatedCoreFormal( "second", Kernel::THE_SLOT_VARIABLE );
2642 Lang::BinaryOperatorFunction::~BinaryOperatorFunction( )
2644 delete opExpr_;
2647 void
2648 Lang::BinaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2650 const size_t ARITY = 2;
2651 CHECK_ARITY( args, ARITY, title_ );
2652 RefCountPtr< const Lang::Value > arg1 = args.getValue( 0 );
2653 RefCountPtr< const Lang::Value > arg2 = args.getValue( 1 );
2657 Kernel::ContRef cont = evalState->cont_;
2658 cont->takeValue( arg1->binaryDispatch1( arg1, arg2, evalState->dyn_, opExpr_ ),
2659 evalState );
2661 catch( Exceptions::BinaryInfixNotApplicable & ball )
2663 ball.setOperatorSymbol( title_ );
2664 throw;
2668 bool
2669 Lang::BinaryOperatorFunction::isTransforming( ) const
2671 return false;
2674 void
2675 Lang::BinaryOperatorFunction::show( std::ostream & os ) const
2677 os << "< binary operator function for " << title_ << " >" ;
2681 Lang::UnaryOperatorFunction::UnaryOperatorFunction( Ast::UnaryExpr * opExpr, const char * title )
2682 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title ), true ) ), opExpr_( opExpr ), title_( title )
2684 formals_->appendEvaluatedCoreFormal( "only", Kernel::THE_SLOT_VARIABLE );
2687 Lang::UnaryOperatorFunction::~UnaryOperatorFunction( )
2689 delete opExpr_;
2692 void
2693 Lang::UnaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2695 const size_t ARITY = 1;
2696 CHECK_ARITY( args, ARITY, title_ );
2698 RefCountPtr< const Lang::Value > arg = args.getValue( 0 );
2702 Kernel::ContRef cont = evalState->cont_;
2703 cont->takeValue( arg->unaryDispatch( arg, evalState->dyn_, opExpr_ ),
2704 evalState );
2706 catch( Exceptions::UnaryPrefixNotApplicable & ball )
2708 ball.setOperatorSymbol( title_ );
2709 throw;
2711 catch( Exceptions::UnaryPostfixNotApplicable & ball )
2713 ball.setOperatorSymbol( title_ );
2714 throw;
2718 bool
2719 Lang::UnaryOperatorFunction::isTransforming( ) const
2721 return false;
2724 void
2725 Lang::UnaryOperatorFunction::show( std::ostream & os ) const
2727 os << "< unary operator function for " << title_ << " >" ;
2731 Lang::Transform2DMethod_chop::Transform2DMethod_chop( RefCountPtr< const Lang::Transform2D > self, const Ast::FileID * fullMethodID )
2732 : Lang::MethodBase< class_type >( self, fullMethodID, false, true )
2734 formals_->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE );
2735 formals_->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE );
2738 Lang::Transform2DMethod_chop::~Transform2DMethod_chop( )
2741 void
2742 Lang::Transform2DMethod_chop::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2744 args.applyDefaults( );
2746 size_t argsi = 0;
2747 double Ltol = Helpers::down_cast_CoreArgument< const Lang::Float >( title_, args, argsi, callLoc )->val_;
2748 if( Ltol < 0 )
2750 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2753 ++argsi;
2754 Concrete::Length ptol = Helpers::down_cast_CoreArgument< const Lang::Length >( title_, args, argsi, callLoc )->get( );
2755 if( ptol < Concrete::ZERO_LENGTH )
2757 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2760 Lang::Transform2D * res = self_->clone( );
2762 CHOP_Ltol( res->xx_ );
2763 CHOP_Ltol( res->yx_ );
2765 CHOP_Ltol( res->xy_ );
2766 CHOP_Ltol( res->yy_ );
2768 CHOP_ptol( res->xt_ );
2769 CHOP_ptol( res->yt_ );
2771 Kernel::ContRef cont = evalState->cont_;
2772 cont->takeValue( RefCountPtr< const Lang::Value >( res ),
2773 evalState );
2777 Lang::Transform3DMethod_chop::Transform3DMethod_chop( RefCountPtr< const Lang::Transform3D > self, const Ast::FileID * fullMethodID )
2778 : Lang::MethodBase< class_type >( self, fullMethodID, false, true )
2780 formals_->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE );
2781 formals_->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE );
2784 Lang::Transform3DMethod_chop::~Transform3DMethod_chop( )
2787 void
2788 Lang::Transform3DMethod_chop::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2790 args.applyDefaults( );
2792 size_t argsi = 0;
2793 double Ltol = Helpers::down_cast_CoreArgument< const Lang::Float >( title_, args, argsi, callLoc )->val_;
2794 if( Ltol < 0 )
2796 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2799 ++argsi;
2800 Concrete::Length ptol = Helpers::down_cast_CoreArgument< const Lang::Length >( title_, args, argsi, callLoc )->get( );
2801 if( ptol < Concrete::ZERO_LENGTH )
2803 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Tolerances must not be negative." );
2806 Lang::Transform3D * res = self_->clone( );
2808 CHOP_Ltol( res->xx_ );
2809 CHOP_Ltol( res->yx_ );
2810 CHOP_Ltol( res->zx_ );
2812 CHOP_Ltol( res->xy_ );
2813 CHOP_Ltol( res->yy_ );
2814 CHOP_Ltol( res->zy_ );
2816 CHOP_Ltol( res->xz_ );
2817 CHOP_Ltol( res->yz_ );
2818 CHOP_Ltol( res->zz_ );
2820 CHOP_ptol( res->xt_ );
2821 CHOP_ptol( res->yt_ );
2822 CHOP_ptol( res->zt_ );
2824 Kernel::ContRef cont = evalState->cont_;
2825 cont->takeValue( RefCountPtr< const Lang::Value >( res ),
2826 evalState );