Update procedures
[shapes.git] / source / functiontypes.cc
blobcd3f876b9253871065aa174f65f57625ea34bbf2
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, 2014 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( const Ast::SourceLocation & callLoc )
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 throw Exceptions::UserArityMismatch( callLoc, formals_->formals_->loc( ), formalsSize, numberOfArguments, Exceptions::UserArityMismatch::VARIABLE );
1014 size_t numberOfStates = states_->size( );
1015 size_t formalsStateSize = formals_->formals_->stateOrder_->size( );
1016 if( numberOfStates > formalsStateSize )
1018 throw Exceptions::UserArityMismatch( callLoc, formals_->formals_->loc( ), formalsStateSize, numberOfStates, Exceptions::UserArityMismatch::STATE );
1021 /* First the easy part: All states must be specified.
1023 std::map< size_t, RefCountPtr< const char > > * missingStates = 0;
1025 size_t pos = 0;
1026 typedef typeof *states_ ListType;
1027 for( ListType::const_iterator i = states_->begin( ); i != states_->end( ); ++i, ++pos )
1029 if( *i == Kernel::THE_SLOT_STATE )
1031 if( missingStates == 0 )
1033 missingStates = new typeof *missingStates;
1035 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
1036 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
1037 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
1039 if( i->second == pos )
1041 missingStates->insert( missingStates->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1042 break;
1044 ++i;
1045 if( i == formalsMap.end( ) )
1047 throw Exceptions::InternalError( "Failed to find position of missing state." );
1054 if( numberOfStates < formalsStateSize )
1056 if( missingStates == 0 )
1058 missingStates = new typeof *missingStates;
1060 typedef typeof *(formals_->formals_->stateOrder_) FormalsMapType;
1061 FormalsMapType & formalsMap = *(formals_->formals_->stateOrder_);
1062 FormalsMapType::const_iterator i = formalsMap.begin( );
1063 for( size_t j = 0; j < numberOfStates; ++j )
1065 ++i;
1068 for( ; i != formalsMap.end( ); ++i, ++pos)
1070 missingStates->insert( missingStates->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1076 /* Allocate positions in the vector for all arguments.
1078 variables_->reserve( hasSink_ ? formalsSize + 1 : formalsSize );
1079 while( variables_->size( ) < formalsSize )
1081 variables_->push_back( Kernel::THE_SLOT_VARIABLE );
1083 locations_.resize( formalsSize );
1085 typedef typeof *variables_ MyListType;
1086 typedef typeof formals_->defaults_ DefaultListType;
1087 typedef typeof formals_->locations_ LocationListType;
1088 DefaultListType::const_iterator src = formals_->defaults_.begin( );
1089 LocationListType::const_iterator srcLoc = formals_->locations_.begin( );
1090 std::map< size_t, RefCountPtr< const char > > * missingArgs = 0;
1091 size_t pos = 0;
1092 for( MyListType::iterator dst = variables_->begin( ); dst != variables_->end( ); ++dst, ++src, ++srcLoc, ++pos )
1094 if( *dst == Kernel::THE_SLOT_VARIABLE )
1096 /* Handle error situation.
1098 if( *src == Kernel::THE_SLOT_VARIABLE )
1100 if( missingArgs == 0 )
1102 missingArgs = new typeof *missingArgs;
1104 typedef typeof *(formals_->formals_->argumentOrder_) FormalsMapType;
1105 FormalsMapType & formalsMap = *(formals_->formals_->argumentOrder_);
1106 for( FormalsMapType::const_iterator i = formalsMap.begin( ); ; )
1108 if( i->second == pos )
1110 missingArgs->insert( missingArgs->begin( ), std::pair< size_t, RefCountPtr< const char > >( pos, strrefdup( i->first ) ) );
1111 break;
1113 ++i;
1114 if( i == formalsMap.end( ) )
1116 throw Exceptions::InternalError( "Failed to find position of missing argument." );
1121 /* Normal case.
1123 *dst = *src;
1124 locations_[ pos ] = *srcLoc;
1128 if( missingArgs != 0 || missingStates != 0 )
1130 throw Exceptions::MissingArguments( callLoc, formals_->formals_->loc( ), missingArgs, missingStates );
1133 if( hasSink_ )
1135 variables_->push_back
1136 ( Helpers::newValHandle
1137 ( new Lang::Structure( sinkArgList_,
1138 sinkValues_,
1139 true ) ) ); // true means that the sinkArgList_ gets owned by the Structure.
1140 sinkArgList_ = 0;
1145 Kernel::VariableHandle &
1146 Kernel::Arguments::getHandle( size_t i )
1148 return (*variables_)[ i ];
1151 RefCountPtr< const Lang::Value > &
1152 Kernel::Arguments::getValue( size_t i )
1154 return (*variables_)[ i ]->getUntyped( );
1157 const Ast::SourceLocation &
1158 Kernel::Arguments::getLoc( size_t i ) const
1160 return locations_[ i ]->loc( );
1163 const Ast::Node *
1164 Kernel::Arguments::getNode( size_t i ) const
1166 return locations_[ i ];
1169 Kernel::Thunk *
1170 Kernel::Arguments::getThunk( size_t i )
1172 return (*variables_)[ i ]->copyThunk( );
1175 bool
1176 Kernel::Arguments::isSlot( size_t i ) const
1178 return (*variables_)[ i ] == Kernel::THE_SLOT_VARIABLE;
1181 Kernel::StateHandle
1182 Kernel::Arguments::getState( size_t i )
1184 return (*states_)[ i ];
1187 const Ast::SourceLocation &
1188 Kernel::Arguments::getStateLoc( size_t i ) const
1190 return stateLocations_[ i ]->loc( );
1193 size_t
1194 Kernel::Arguments::size( ) const
1196 return variables_->size( );
1199 bool
1200 Kernel::Arguments::empty( ) const
1202 return variables_->empty( );
1205 void
1206 Kernel::Arguments::setMutatorSelf( Kernel::StateHandle mutatorSelf )
1208 mutatorSelf_ = mutatorSelf;
1211 Kernel::StateHandle
1212 Kernel::Arguments::getMutatorSelf( )
1214 if( mutatorSelf_ == 0 )
1216 throw Exceptions::InternalError( "Kernel::Arguments::getMutatorSelf: self is null." );
1218 return mutatorSelf_;
1221 void
1222 Kernel::Arguments::gcMark( Kernel::GCMarkedSet & marked )
1225 typedef typeof *variables_ ListType;
1226 for( ListType::const_iterator i = variables_->begin( ); i != variables_->end( ); ++i )
1228 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1233 Kernel::Environment::ValueVector
1234 Kernel::Arguments::getVariables( )
1236 return variables_;
1239 Kernel::Environment::StateVector
1240 Kernel::Arguments::getStates( )
1242 return states_;
1246 namespace Shapes
1248 namespace Kernel
1251 class FunctionOneHandleCont : public Kernel::Continuation
1253 RefCountPtr< const Lang::Function > fun_;
1254 Kernel::PassedDyn dyn_;
1255 Kernel::ContRef cont_;
1256 public:
1257 FunctionOneHandleCont( const RefCountPtr< const Lang::Function > & fun, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1258 : Kernel::Continuation( traceLoc ), fun_( fun ), dyn_( dyn ), cont_( cont )
1260 virtual ~FunctionOneHandleCont( ) { }
1261 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
1263 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1264 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1267 if( val->isThunk( ) )
1269 val->force( val, evalState );
1270 return;
1273 Kernel::Arguments args = fun_->newCurriedArguments( );
1274 args.addOrderedArgument( val, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1276 evalState->dyn_ = dyn_;
1277 evalState->cont_ = cont_;
1278 fun_->call( evalState, args, traceLoc_ );
1280 virtual Kernel::ContRef up( ) const
1282 return cont_;
1284 virtual RefCountPtr< const char > description( ) const
1286 return strrefdup( "internal function call with one handle" );
1288 virtual void gcMark( Kernel::GCMarkedSet & marked )
1290 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1291 dyn_->gcMark( marked );
1292 cont_->gcMark( marked );
1296 class FunctionTwoHandlesCont_2 : public Kernel::Continuation
1298 RefCountPtr< const Lang::Function > fun_;
1299 Kernel::VariableHandle arg1_;
1300 Kernel::PassedDyn dyn_;
1301 Kernel::ContRef cont_;
1302 public:
1303 FunctionTwoHandlesCont_2( const RefCountPtr< const Lang::Function > & fun, const Kernel::VariableHandle & arg1, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
1304 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), dyn_( dyn ), cont_( cont )
1306 virtual ~FunctionTwoHandlesCont_2( ) { }
1307 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1309 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1310 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1313 if( arg2->isThunk( ) )
1315 arg2->force( arg2, evalState );
1316 return;
1319 Kernel::Arguments args = fun_->newCurriedArguments( );
1320 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1321 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1322 evalState->dyn_ = dyn_;
1323 evalState->cont_ = cont_;
1324 fun_->call( evalState, args, traceLoc_ );
1326 virtual Kernel::ContRef up( ) const
1328 return cont_;
1330 virtual RefCountPtr< const char > description( ) const
1332 return strrefdup( "internal function call with two handles, second" );
1334 virtual void gcMark( Kernel::GCMarkedSet & marked )
1336 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1337 dyn_->gcMark( marked );
1338 cont_->gcMark( marked );
1342 class FunctionTwoHandlesCont_1 : public Kernel::Continuation
1344 RefCountPtr< const Lang::Function > fun_;
1345 Kernel::VariableHandle arg2_;
1346 bool forceArg2_;
1347 Kernel::PassedDyn dyn_;
1348 Kernel::ContRef cont_;
1349 public:
1350 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 )
1351 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), dyn_( dyn ), cont_( cont )
1353 virtual ~FunctionTwoHandlesCont_1( ) { }
1354 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1356 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1357 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1360 if( arg1->isThunk( ) )
1362 arg1->force( arg1, evalState );
1363 return;
1366 if( forceArg2_ )
1368 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( fun_, arg1, dyn_, cont_, traceLoc_ ) );
1369 evalState->cont_ = newCont;
1370 newCont->takeHandle( arg2_, evalState );
1371 return;
1374 /* The second handle need not be forced
1376 Kernel::Arguments args = fun_->newCurriedArguments( );
1377 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1378 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1379 evalState->dyn_ = dyn_;
1380 evalState->cont_ = cont_;
1381 fun_->call( evalState, args, traceLoc_ );
1383 virtual Kernel::ContRef up( ) const
1385 return cont_;
1387 virtual RefCountPtr< const char > description( ) const
1389 return strrefdup( "internal function call with two handles, first" );
1391 virtual void gcMark( Kernel::GCMarkedSet & marked )
1393 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1394 dyn_->gcMark( marked );
1395 cont_->gcMark( marked );
1399 class FunctionTwoHandlesOneStateCont_2 : public Kernel::Continuation
1401 RefCountPtr< const Lang::Function > fun_;
1402 Kernel::VariableHandle arg1_;
1403 Kernel::StateHandle state_;
1404 Kernel::PassedDyn dyn_;
1405 Kernel::ContRef cont_;
1406 public:
1407 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 )
1408 : Kernel::Continuation( traceLoc ), fun_( fun ), arg1_( arg1 ), state_( state ), dyn_( dyn ), cont_( cont )
1410 virtual ~FunctionTwoHandlesOneStateCont_2( ) { }
1411 virtual void takeHandle( Kernel::VariableHandle arg2, Kernel::EvalState * evalState, bool dummy ) const
1413 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1414 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1417 if( arg2->isThunk( ) )
1419 arg2->force( arg2, evalState );
1420 return;
1423 Kernel::Arguments args = fun_->newCurriedArguments( );
1424 args.addOrderedArgument( arg1_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1425 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1426 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1427 evalState->dyn_ = dyn_;
1428 evalState->cont_ = cont_;
1429 fun_->call( evalState, args, traceLoc_ );
1431 virtual Kernel::ContRef up( ) const
1433 return cont_;
1435 virtual RefCountPtr< const char > description( ) const
1437 return strrefdup( "internal function call with two handles and one state, second" );
1439 virtual void gcMark( Kernel::GCMarkedSet & marked )
1441 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1442 state_->gcMark( marked );
1443 dyn_->gcMark( marked );
1444 cont_->gcMark( marked );
1448 class FunctionTwoHandlesOneStateCont_1 : public Kernel::Continuation
1450 RefCountPtr< const Lang::Function > fun_;
1451 Kernel::VariableHandle arg2_;
1452 bool forceArg2_;
1453 Kernel::StateHandle state_;
1454 Kernel::PassedDyn dyn_;
1455 Kernel::ContRef cont_;
1456 public:
1457 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 )
1458 : Kernel::Continuation( traceLoc ), fun_( fun ), arg2_( arg2 ), forceArg2_( forceArg2 ), state_( state ), dyn_( dyn ), cont_( cont )
1460 virtual ~FunctionTwoHandlesOneStateCont_1( ) { }
1461 virtual void takeHandle( Kernel::VariableHandle arg1, Kernel::EvalState * evalState, bool dummy ) const
1463 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1464 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1467 if( arg1->isThunk( ) )
1469 arg1->force( arg1, evalState );
1470 return;
1473 if( forceArg2_ )
1475 Kernel::ContRef newCont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( fun_, arg1, state_, dyn_, cont_, traceLoc_ ) );
1476 evalState->cont_ = newCont;
1477 newCont->takeHandle( arg2_, evalState );
1478 return;
1481 /* The second handle need not be forced
1483 Kernel::Arguments args = fun_->newCurriedArguments( );
1484 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1485 args.addOrderedArgument( arg2_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1486 args.addOrderedState( state_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1487 evalState->dyn_ = dyn_;
1488 evalState->cont_ = cont_;
1489 fun_->call( evalState, args, traceLoc_ );
1491 virtual Kernel::ContRef up( ) const
1493 return cont_;
1495 virtual RefCountPtr< const char > description( ) const
1497 return strrefdup( "internal function call with two handles and one state, first" );
1499 virtual void gcMark( Kernel::GCMarkedSet & marked )
1501 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
1502 dyn_->gcMark( marked );
1503 cont_->gcMark( marked );
1504 state_->gcMark( marked );
1512 Lang::Function::Function( Kernel::EvaluatedFormals * formals )
1513 : formals_( formals )
1516 DISPATCHIMPL( Function );
1518 Lang::Function::~Function( )
1520 if( formals_ != 0 )
1522 delete formals_->formals_;
1523 delete formals_;
1527 Kernel::ValueRef
1528 Lang::Function::transformed( const Lang::Transform2D & tf, Kernel::ValueRef self ) const
1530 return Kernel::ValueRef( new Lang::TransformedFunction2D( tf, self.down_cast< const Lang::Function >( ) ) );
1533 void
1534 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Ast::SourceLocation & callLoc ) const
1536 Kernel::Arguments args = this->newCurriedArguments( );
1538 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1540 this->call( evalState, args, callLoc );
1543 void
1544 Lang::Function::analyze( Ast::Node * parent, Ast::AnalysisEnvironment * env )
1546 Ast::StateIDSet * freeStates = new Ast::StateIDSet;
1547 this->analyze_impl( parent, env, freeStates );
1548 if( ! freeStates->empty( ) )
1550 Ast::theAnalysisErrorsList.push_back( new Exceptions::IllegalFreeStates( parent->loc( ), freeStates, "this is a function" ) );
1552 else
1554 delete freeStates;
1558 void
1559 Lang::Function::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
1561 throw Exceptions::InternalError( "A syntax function is not overriding the analyze method." );
1564 void
1565 Lang::Function::call( Kernel::EvalState * evalState, const Kernel::ValueRef & arg1, const Kernel::ValueRef & arg2, const Ast::SourceLocation & callLoc ) const
1567 Kernel::Arguments args = this->newCurriedArguments( );
1569 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1570 args.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg2 ) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1572 this->call( evalState, args, callLoc );
1575 Ast::ArgListExprs * Lang::Function::oneExprArgList = new Ast::ArgListExprs( static_cast< size_t >( 1 ) );
1576 Ast::ArgListExprs * Lang::Function::twoExprsArgList = new Ast::ArgListExprs( static_cast< size_t >( 2 ) );
1578 void
1579 Lang::Function::call( const RefCountPtr< const Lang::Function > & selfRef, Kernel::EvalState * evalState, const Kernel::VariableHandle & arg1, const Ast::SourceLocation & callLoc ) const
1581 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::oneExprArgList, *evalState );
1583 if( info->force( 0 ) )
1585 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionOneHandleCont( selfRef, evalState->dyn_, evalState->cont_, callLoc ) );
1586 evalState->cont_ = cont;
1587 cont->takeHandle( arg1, evalState );
1588 return;
1591 /* The handle need not be forced
1593 Kernel::Arguments args = this->newCurriedArguments( );
1594 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1595 this->call( evalState, args, callLoc );
1598 void
1599 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
1601 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1603 /* Remember that arguments are ordered backwards!
1606 if( info->force( 1 ) )
1608 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_1( selfRef, arg2, info->force( 0 ), evalState->dyn_, evalState->cont_, callLoc ) );
1609 evalState->cont_ = cont;
1610 cont->takeHandle( arg1, evalState );
1611 return;
1614 if( info->force( 0 ) )
1616 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( selfRef, arg1, evalState->dyn_, evalState->cont_, callLoc ) );
1617 evalState->cont_ = cont;
1618 cont->takeHandle( arg2, evalState );
1619 return;
1622 /* None of the handles need to be forced
1624 Kernel::Arguments args = this->newCurriedArguments( );
1625 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1626 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1627 this->call( evalState, args, callLoc );
1630 void
1631 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
1633 /* I'm not quite sure if we should also put a dummy state argument in info...
1635 const RefCountPtr< const Kernel::CallContInfo > info = this->newCallContInfo( Lang::Function::twoExprsArgList, *evalState );
1637 /* Remember that arguments are ordered backwards!
1640 if( info->force( 1 ) )
1642 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_1( selfRef, arg2, info->force( 0 ), state, evalState->dyn_, evalState->cont_, callLoc ) );
1643 evalState->cont_ = cont;
1644 cont->takeHandle( arg1, evalState );
1645 return;
1648 if( info->force( 0 ) )
1650 Kernel::ContRef cont = Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( selfRef, arg1, state, evalState->dyn_, evalState->cont_, callLoc ) );
1651 evalState->cont_ = cont;
1652 cont->takeHandle( arg2, evalState );
1653 return;
1656 /* None of the handles need to be forced
1658 Kernel::Arguments args = this->newCurriedArguments( );
1659 args.addOrderedArgument( arg1, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1660 args.addOrderedArgument( arg2, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1661 args.addOrderedState( state, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1662 this->call( evalState, args, callLoc );
1666 RefCountPtr< Kernel::CallContInfo >
1667 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1669 return formals_->newCallContInfo( argList, evalState );
1672 RefCountPtr< Kernel::CallContInfo >
1673 Lang::Function::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1675 return formals_->newCallContInfo( argList, evalState, curryArgs );
1678 Kernel::Arguments
1679 Lang::Function::newCurriedArguments( ) const
1681 return Kernel::Arguments( formals_ );
1685 RefCountPtr< const Lang::Class > Lang::Function::TypeID( new Lang::SystemFinalClass( strrefdup( "Function" ) ) );
1686 TYPEINFOIMPL( Function );
1688 Kernel::EvaluatedFormals::EvaluatedFormals( Kernel::Formals * formals )
1689 : selectiveForcing_( false ), forceAll_( false ), formals_( formals ), isSink_( true )
1692 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID * locationFileID )
1693 : selectiveForcing_( true ), formals_( 0 ), isSink_( true )
1695 Kernel::Formals * formals( new Kernel::Formals( ) );
1696 formals->setLoc( Ast::theSourceLocationFactory.construct( locationFileID ) );
1697 formals_ = formals;
1700 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID * locationFileID, bool forceAll )
1701 : selectiveForcing_( false ), forceAll_( forceAll ), formals_( 0 ), isSink_( true )
1703 Kernel::Formals * formals( new Kernel::Formals( ) );
1704 formals->setLoc( Ast::theSourceLocationFactory.construct( locationFileID ) );
1705 formals_ = formals;
1708 Kernel::EvaluatedFormals::~EvaluatedFormals( )
1710 /* Don't delete the orderedFormals, since we don't own it. A case for reference counting? */
1713 RefCountPtr< Kernel::CallContInfo >
1714 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1716 if( selectiveForcing_ )
1718 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList ) ) );
1720 else
1722 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1726 RefCountPtr< Kernel::CallContInfo >
1727 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1729 if( selectiveForcing_ )
1731 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, formals_->newArgListForcePos( argList, curryArgs ) ) );
1733 else
1735 return RefCountPtr< Kernel::CallContInfo >( new Kernel::CallContInfo( argList, evalState, forceAll_ ) );
1739 void
1740 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc, bool force )
1742 if( ! selectiveForcing_ )
1744 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function does not have selective forcing." );
1746 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1747 formals_->forcePos_.push_back( force );
1748 defaults_.push_back( defaultVal );
1749 locations_.push_back( loc );
1752 void
1753 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id, const Kernel::VariableHandle & defaultVal, const Ast::Node * loc )
1755 if( selectiveForcing_ )
1757 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function requires individual forcing specification." );
1759 (*(formals_->argumentOrder_))[ id ] = defaults_.size( );
1760 formals_->forcePos_.push_back( forceAll_ );
1761 defaults_.push_back( defaultVal );
1762 locations_.push_back( loc );
1765 void
1766 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal, bool force )
1768 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION, force );
1771 void
1772 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id, const Kernel::VariableHandle & defaultVal )
1774 appendEvaluatedFormal( id, defaultVal, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION );
1777 void
1778 Kernel::EvaluatedFormals::appendCoreStateFormal( const char * id )
1780 (*(formals_->stateOrder_))[ id ] = formals_->stateOrder_->size( );
1783 void
1784 Kernel::EvaluatedFormals::gcMark( Kernel::GCMarkedSet & marked )
1786 typedef typeof defaults_ ListType;
1787 for( ListType::const_iterator i = defaults_.begin( ); i != defaults_.end( ); ++i )
1789 if( *i != NullPtr< Kernel::Variable >( ) )
1791 const_cast< Kernel::Variable * >( i->getPtr( ) )->gcMark( marked );
1797 Lang::CuteFunction::CuteFunction( RefCountPtr< const Lang::Function > callee, const Kernel::Arguments & someArgs )
1798 : Lang::Function( 0 ), callee_( callee), someArgs_( someArgs.clone( ) )
1801 Lang::CuteFunction::~CuteFunction( )
1804 RefCountPtr< Kernel::CallContInfo >
1805 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1807 return callee_->newCallContInfo( argList, evalState, someArgs_ );
1810 RefCountPtr< Kernel::CallContInfo >
1811 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1813 /* when we are the callee of a CuteFunction, our someArgs are part of that CuteFunction's someArgs, and hence curryArgs
1814 * contains everything that is to be passed to our callee.
1816 return callee_->newCallContInfo( argList, evalState, curryArgs );
1819 Kernel::Arguments
1820 Lang::CuteFunction::newCurriedArguments( ) const
1822 return someArgs_.clone( );
1825 void
1826 Lang::CuteFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1828 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1829 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.
1831 callee_->call( evalState, args, callLoc );
1834 bool
1835 Lang::CuteFunction::isTransforming( ) const
1837 return callee_->isTransforming( );
1840 void
1841 Lang::CuteFunction::gcMark( Kernel::GCMarkedSet & marked )
1843 const_cast< Lang::Function * >( callee_.getPtr( ) )->gcMark( marked );
1844 someArgs_.gcMark( marked );
1847 void
1848 Lang::CuteFunction::show( std::ostream & os ) const
1850 os << "< evaluated cut of: " ;
1851 callee_->show( os );
1852 os << " >" ;
1856 Lang::ComposedFunction::ComposedFunction( const RefCountPtr< const Lang::Function > & second, const RefCountPtr< const Lang::Function > & first )
1857 : Lang::Function( 0 ), second_( second ), first_( first )
1860 Lang::ComposedFunction::~ComposedFunction( )
1863 void
1864 Lang::ComposedFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1866 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1867 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.
1869 evalState->cont_ = Kernel::ContRef( new Kernel::ComposedFunctionCall_cont( second_, evalState->dyn_, evalState->cont_, callLoc ) );
1870 first_->call( evalState, args, callLoc );
1873 RefCountPtr< Kernel::CallContInfo >
1874 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState ) const
1876 return first_->newCallContInfo( argList, evalState );
1879 RefCountPtr< Kernel::CallContInfo >
1880 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs * argList, const Kernel::EvalState & evalState, const Kernel::Arguments & curryArgs ) const
1882 return first_->newCallContInfo( argList, evalState, curryArgs );
1885 Kernel::Arguments
1886 Lang::ComposedFunction::newCurriedArguments( ) const
1888 return first_->newCurriedArguments( );
1891 bool
1892 Lang::ComposedFunction::isTransforming( ) const
1894 return second_->isTransforming( );
1897 void
1898 Lang::ComposedFunction::gcMark( Kernel::GCMarkedSet & marked )
1900 const_cast< Lang::Function * >( second_.getPtr( ) )->gcMark( marked );
1901 const_cast< Lang::Function * >( first_.getPtr( ) )->gcMark( marked );
1904 void
1905 Lang::ComposedFunction::show( std::ostream & os ) const
1907 os << "< composition: " ;
1908 second_->show( os );
1909 os << " () " ;
1910 first_->show( os );
1911 os << " >" ;
1915 namespace Shapes
1917 namespace Kernel
1919 class SpanThunks
1921 std::vector< Kernel::VariableHandle > thunks_;
1922 public:
1923 SpanThunks( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count )
1925 thunks_.reserve( 4 );
1926 thunks_.push_back( count );
1927 thunks_.push_back( step );
1928 thunks_.push_back( end );
1929 thunks_.push_back( begin );
1931 const Kernel::VariableHandle & operator [] ( size_t i ) const
1933 return thunks_[ i ];
1935 ~SpanThunks( )
1937 void gcMark( Kernel::GCMarkedSet & marked )
1939 typedef typeof thunks_ VecType;
1940 for( VecType::iterator i = thunks_.begin( ); i != thunks_.end( ); ++i )
1942 (*i)->gcMark( marked );
1947 class SpanForcingContinuation : public Continuation
1949 RefCountPtr< const Kernel::SpanThunks > thunks_;
1950 size_t i_;
1951 RefCountPtr< const Lang::SingleList > values_;
1952 RefCountPtr< const Lang::Value > last_;
1953 Kernel::ContRef cont_;
1954 public:
1955 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 )
1956 : Kernel::Continuation( traceLoc ), thunks_( thunks ), i_( i ), values_( values ), last_( last ), cont_( cont )
1958 ~SpanForcingContinuation( )
1960 static void finish( RefCountPtr< const Lang::SingleList > values, RefCountPtr< const Lang::Value > last, Kernel::EvalState * evalState, const Ast::SourceLocation & traceLoc )
1962 Kernel::Arguments args = Lang::THE_FUNCTION_RANGE->newCurriedArguments( );
1963 RefCountPtr< const Lang::SingleListPair > src = values.down_cast< const Lang::SingleListPair >( );
1964 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1965 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1966 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1967 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1968 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1969 src = src->cdr_.down_cast< const Lang::SingleListPair >( );
1970 args.addOrderedArgument( src->car_, & Ast::THE_INTERNAL_VALUE_EXPRESSION );
1971 Lang::Core_range::makeRange( Lang::Span::coreLoc, evalState, args, traceLoc, true, last );
1973 virtual void takeValue( const RefCountPtr< const Lang::Value > & val, Kernel::EvalState * evalState, bool dummy ) const
1975 RefCountPtr< const Lang::SingleList > values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( val ) ), values_ ) );
1977 for( size_t i = i_ + 1; i < 4; ++i )
1979 const Kernel::VariableHandle & var = (*thunks_)[ i ];
1980 if( var->isThunk( ) )
1982 evalState->cont_ = Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_, i, values, last_, cont_, traceLoc_ ) );
1983 var->force( var, evalState );
1984 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, last_ ) );
1985 return;
1987 values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( var, values ) );
1989 evalState->cont_ = cont_;
1990 finish( values, last_, evalState, traceLoc_ );
1992 virtual Kernel::ContRef up( ) const
1994 return cont_;
1996 virtual RefCountPtr< const char > description( ) const
1998 std::ostringstream msg;
1999 msg << "force span parameter number " << i_ ;
2000 return strrefdup( msg );
2002 virtual void gcMark( Kernel::GCMarkedSet & marked )
2004 const_cast< Kernel::SpanThunks * >( thunks_.getPtr( ) )->gcMark( marked );
2005 const_cast< Lang::SingleList * >( values_.getPtr( ) )->gcMark( marked );
2006 const_cast< Lang::Value * >( last_.getPtr( ) )->gcMark( marked );
2007 cont_->gcMark( marked );
2013 RefCountPtr< const Lang::Class > Lang::Span::TypeID( new Lang::SystemFinalClass( strrefdup( "Span" ) ) );
2014 TYPEINFOIMPL( Span );
2016 Lang::Span::Span( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count )
2017 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<span>" ), true ) ),
2018 thunks_( new Kernel::SpanThunks( begin, end, step, count ) )
2020 formals_->appendEvaluatedCoreFormal( "last", Kernel::THE_SLOT_VARIABLE );
2023 const RefCountPtr< const Interaction::CoreLocation > Lang::Span::coreLoc( new Interaction::CharPtrLocation( "<span>" ) );
2025 Lang::Span::~Span( )
2028 void
2029 Lang::Span::gcMark( Kernel::GCMarkedSet & marked )
2031 const_cast< Kernel::SpanThunks * >( thunks_.getPtr( ) )->gcMark( marked );
2034 void
2035 Lang::Span::show( std::ostream & os ) const
2037 Lang::Span::coreLoc->show( os );
2040 void
2041 Lang::Span::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2043 args.applyDefaults( callLoc );
2045 RefCountPtr< const Lang::SingleList > values = Lang::THE_CONS_NULL;
2046 for( size_t i = 0; i < 4; ++i )
2048 const Kernel::VariableHandle & var = (*thunks_)[ i ];
2049 if( var->isThunk( ) )
2051 evalState->cont_ = Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_, i, values, args.getValue( 0 ), evalState->cont_, callLoc ) );
2052 var->force( var, evalState );
2053 evalState->dyn_ = Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState->dyn_, args.getValue( 0 ) ) );
2054 return;
2056 values = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( var, values ) );
2059 /* We only reach this point if there were no thunks at all to be forced. */
2060 Kernel::SpanForcingContinuation::finish( values, args.getValue( 0 ), evalState, callLoc );
2063 bool
2064 Lang::Span::isTransforming( ) const
2066 return false;
2070 Lang::UserFunction::UserFunction( Kernel::EvaluatedFormals * formals, Ast::Expression * body, Kernel::PassedEnv env, const Ast::FunctionMode & functionMode )
2071 : Lang::Function( formals ), body_( body ), env_( env ), functionMode_( functionMode )
2074 // DISPATCHIMPL( UserFunction );
2076 Lang::UserFunction::~UserFunction( )
2078 // Note that we don't delete the things that we most likely share with other objects
2079 // Reference counting could be used here, but there will never be more such things than there are function expressions in the source
2081 // This prevents formals->formals from being deleted by Lang::Function::~Function
2082 delete formals_;
2083 formals_ = 0;
2086 void
2087 Lang::UserFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2089 args.applyDefaults( callLoc );
2090 evalState->env_ = new Kernel::Environment( Kernel::theEnvironmentList, env_, formals_->formals_->argumentIdentifiers_, args.getVariables( ), formals_->formals_->stateIdentifiers_, args.getStates( ), "Closure" );
2091 evalState->expr_ = body_;
2094 bool
2095 Lang::UserFunction::isTransforming( ) const
2097 return ( functionMode_ & Ast::FUNCTION_TRANSFORMING ) != 0;
2100 void
2101 Lang::UserFunction::gcMark( Kernel::GCMarkedSet & marked )
2103 env_->gcMark( marked );
2106 Ast::Expression *
2107 Lang::UserFunction::body( )
2109 return body_;
2112 void
2113 Lang::UserFunction::show( std::ostream & os ) const
2115 os << "< user function with body at " << body_->loc( ) << " >" ;
2119 Lang::TransformedFunction2D::TransformedFunction2D( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Function > & fun )
2120 : Lang::Function( 0 ), tf_( tf ), fun_( fun )
2123 Lang::TransformedFunction2D::~TransformedFunction2D( )
2126 void
2127 Lang::TransformedFunction2D::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2129 evalState->cont_ = Kernel::ContRef( new Kernel::Transform2DCont( tf_, evalState->cont_, 0 ) );
2130 fun_->call( evalState, args, callLoc );
2133 bool
2134 Lang::TransformedFunction2D::isTransforming( ) const
2136 return fun_->isTransforming( );
2139 void
2140 Lang::TransformedFunction2D::gcMark( Kernel::GCMarkedSet & marked )
2142 const_cast< Lang::Function * >( fun_.getPtr( ) )->gcMark( marked );
2145 void
2146 Lang::TransformedFunction2D::show( std::ostream & os ) const
2148 os << "< transformed function >" ;
2153 Lang::VectorFunction::VectorFunction( const std::vector< Kernel::ValueRef > * mem )
2154 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<vector>" ), true ) ), mem_( mem ),
2155 memNumeric_( NullPtr< const std::vector< double > >( ) ),
2156 list_( NullPtr< Kernel::Variable >( ) )
2158 formals_->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE );
2161 // DISPATCHIMPL( VectorFunction );
2163 Lang::VectorFunction::~VectorFunction( )
2166 RefCountPtr< const Lang::Class > Lang::VectorFunction::TypeID( new Lang::SystemFinalClass( strrefdup( "VectorFunction" ), Kernel::VectorFunction_register_methods ) );
2167 TYPEINFOIMPL( VectorFunction );
2169 Kernel::VariableHandle
2170 Lang::VectorFunction::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
2172 if( strcmp( fieldID, "size" ) == 0 )
2174 return Helpers::newValHandle( new Lang::Integer( mem_->size( ) ) );
2176 if( strcmp( fieldID, "range" ) == 0 )
2178 if( mem_->size( ) == 0 )
2179 return Kernel::VariableHandle( new Kernel::Variable( Lang::THE_CONS_NULL ) );
2180 return Helpers::newValHandle( new Lang::SingleListRange< Lang::Integer >( 0, 1, mem_->size( ) ) );
2182 if( strcmp( fieldID, "reverse_range" ) == 0 )
2184 if( mem_->size( ) == 0 )
2185 return Kernel::VariableHandle( new Kernel::Variable( Lang::THE_CONS_NULL ) );
2186 return Helpers::newValHandle( new Lang::SingleListRange< Lang::Integer >( mem_->size( ) - 1, -1, mem_->size( ) ) );
2188 if( strcmp( fieldID, "list" ) == 0 )
2190 compute_list( );
2191 return list_;
2194 return TypeID->getMethod( selfRef, fieldID ); /* This will throw if there is no such method. */
2197 const RefCountPtr< const Interaction::CoreLocation > Lang::VectorFunction::coreLoc( new Interaction::CharPtrLocation( "<vector>" ) );
2199 void
2200 Lang::VectorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2202 const size_t ARITY = 1;
2203 if( args.size( ) != ARITY )
2205 throw Exceptions::CoreArityMismatch( coreLoc, ARITY, args.size( ) );
2208 typedef const Lang::Integer ArgType;
2209 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( coreLoc, args, 0, callLoc );
2211 if( arg->val_ < 0 )
2213 throw Exceptions::CoreOutOfRange( coreLoc, args, 0, "Index is negative." );
2216 if( arg->val_ >= static_cast< int >( mem_->size( ) ) )
2218 throw Exceptions::CoreOutOfRange( coreLoc, args, 0, "Index exceeds vector size." );
2221 Kernel::ContRef cont = evalState->cont_;
2222 cont->takeValue( (*mem_)[ arg->val_ ],
2223 evalState );
2226 bool
2227 Lang::VectorFunction::isTransforming( ) const
2229 return false;
2232 void
2233 Lang::VectorFunction::gcMark( Kernel::GCMarkedSet & marked )
2235 gcMark( mem_, marked );
2238 void
2239 Lang::VectorFunction::gcMark( const RefCountPtr< const std::vector< Kernel::ValueRef > > & mem, Kernel::GCMarkedSet & marked )
2241 for( std::vector< Kernel::ValueRef >::const_iterator i = mem->begin( ); i != mem->end( ); ++i )
2243 const_cast< Lang::Value * >( i->getPtr( ) )->gcMark( marked );
2247 void
2248 Lang::VectorFunction::show( std::ostream & os ) const
2250 os << "< vector function >" ;
2253 RefCountPtr< const std::vector< double > >
2254 Lang::VectorFunction::getNumeric( const Ast::SourceLocation & callLoc ) const
2256 if( memNumeric_ == NullPtr< const std::vector< double > >( ) )
2258 RefCountPtr< std::vector< double > > res( new std::vector< double > ); // Note that this is not const, so far...
2259 res->reserve( mem_->size( ) );
2260 typedef typeof *mem_ SrcType;
2261 for( SrcType::const_iterator src = mem_->begin( ); src != mem_->end( ); ++src )
2263 res->push_back( Helpers::down_cast< const Lang::Float >( *src, callLoc )->val_ );
2266 memNumeric_ = res;
2268 return memNumeric_;
2271 void
2272 Lang::VectorFunction::compute_list( ) const
2274 if( list_ != NullPtr< Kernel::Variable >( ) )
2276 return;
2278 RefCountPtr< const Lang::SingleList > newList = Lang::THE_CONS_NULL;
2279 typedef typeof *mem_ ListType;
2280 for( ListType::const_reverse_iterator src = mem_->rbegin( ); src != mem_->rend( ); ++src )
2282 newList = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( *src ) ), newList ) );
2284 list_ = Kernel::VariableHandle( new Kernel::Variable( newList ) );
2287 namespace Shapes
2289 namespace Kernel
2292 class VectorFunctionFoldLCont : public Kernel::Continuation
2294 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2295 RefCountPtr< const Lang::Function > op_;
2296 Shapes::Lang::VectorFunction::vector_type::const_iterator i_;
2297 Kernel::PassedDyn dyn_;
2298 Kernel::ContRef cont_;
2299 public:
2300 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 )
2301 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), dyn_( dyn ), cont_( cont )
2303 virtual ~VectorFunctionFoldLCont( ) { }
2304 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2306 evalState->dyn_ = dyn_;
2307 evalState->cont_ = cont_;
2308 Lang::VectorFunction::foldl( mem_, evalState, op_, val, i_, traceLoc_ );
2310 virtual Kernel::ContRef up( ) const
2312 return cont_;
2314 virtual RefCountPtr< const char > description( ) const
2316 return strrefdup( "VectorFunction's foldl" );
2318 virtual void gcMark( Kernel::GCMarkedSet & marked )
2320 Lang::VectorFunction::gcMark( mem_, marked );
2321 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2322 dyn_->gcMark( marked );
2323 cont_->gcMark( marked );
2327 class VectorFunctionFoldRCont : public Kernel::Continuation
2329 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2330 RefCountPtr< const Lang::Function > op_;
2331 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_;
2332 Kernel::PassedDyn dyn_;
2333 Kernel::ContRef cont_;
2334 public:
2335 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 )
2336 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), dyn_( dyn ), cont_( cont )
2338 virtual ~VectorFunctionFoldRCont( ) { }
2339 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2341 evalState->dyn_ = dyn_;
2342 evalState->cont_ = cont_;
2343 Lang::VectorFunction::foldr( mem_, evalState, op_, val, i_, traceLoc_ );
2345 virtual Kernel::ContRef up( ) const
2347 return cont_;
2349 virtual RefCountPtr< const char > description( ) const
2351 return strrefdup( "VectorFunction's foldr" );
2353 virtual void gcMark( Kernel::GCMarkedSet & marked )
2355 Lang::VectorFunction::gcMark( mem_, marked );
2356 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2357 dyn_->gcMark( marked );
2358 cont_->gcMark( marked );
2362 class VectorFunctionFoldSLCont : public Kernel::Continuation
2364 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2365 RefCountPtr< const Lang::Function > op_;
2366 Shapes::Lang::VectorFunction::vector_type::const_iterator i_;
2367 Kernel::StateHandle state_;
2368 Kernel::PassedDyn dyn_;
2369 Kernel::ContRef cont_;
2370 public:
2371 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 )
2372 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), state_( state ), dyn_( dyn ), cont_( cont )
2374 virtual ~VectorFunctionFoldSLCont( ) { }
2375 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2377 evalState->dyn_ = dyn_;
2378 evalState->cont_ = cont_;
2379 Lang::VectorFunction::foldsl( mem_, evalState, op_, val, state_, i_, traceLoc_ );
2381 virtual Kernel::ContRef up( ) const
2383 return cont_;
2385 virtual RefCountPtr< const char > description( ) const
2387 return strrefdup( "VectorFunction's foldsl" );
2389 virtual void gcMark( Kernel::GCMarkedSet & marked )
2391 Lang::VectorFunction::gcMark( mem_, marked );
2392 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2393 state_->gcMark( marked );
2394 dyn_->gcMark( marked );
2395 cont_->gcMark( marked );
2399 class VectorFunctionFoldSRCont : public Kernel::Continuation
2401 RefCountPtr< const std::vector< Kernel::ValueRef > > mem_;
2402 RefCountPtr< const Lang::Function > op_;
2403 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_;
2404 Kernel::StateHandle state_;
2405 Kernel::PassedDyn dyn_;
2406 Kernel::ContRef cont_;
2407 public:
2408 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 )
2409 : Kernel::Continuation( traceLoc ), mem_( mem ), op_( op ), i_( i ), state_( state ), dyn_( dyn ), cont_( cont )
2411 virtual ~VectorFunctionFoldSRCont( ) { }
2412 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
2414 evalState->dyn_ = dyn_;
2415 evalState->cont_ = cont_;
2416 Lang::VectorFunction::foldsr( mem_, evalState, op_, val, state_, i_, traceLoc_ );
2418 virtual Kernel::ContRef up( ) const
2420 return cont_;
2422 virtual RefCountPtr< const char > description( ) const
2424 return strrefdup( "VectorFunction's foldsr" );
2426 virtual void gcMark( Kernel::GCMarkedSet & marked )
2428 Lang::VectorFunction::gcMark( mem_, marked );
2429 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
2430 state_->gcMark( marked );
2431 dyn_->gcMark( marked );
2432 cont_->gcMark( marked );
2439 void
2440 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 )
2442 if( i == mem->end( ) )
2444 Kernel::ContRef cont = evalState->cont_;
2445 cont->takeHandle( nullResult,
2446 evalState );
2447 return;
2450 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2451 ++i;
2452 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldLCont( mem, op, i, evalState->dyn_, evalState->cont_, callLoc ) );
2454 op->call( op, evalState, nullResult, elem, callLoc );
2457 void
2458 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 )
2460 if( i == mem->rend( ) )
2462 Kernel::ContRef cont = evalState->cont_;
2463 cont->takeHandle( nullResult,
2464 evalState );
2465 return;
2468 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2469 ++i;
2470 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldRCont( mem, op, i, evalState->dyn_, evalState->cont_, callLoc ) );
2472 op->call( op, evalState, elem, nullResult, callLoc );
2475 void
2476 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 )
2478 if( i == mem->end( ) )
2480 Kernel::ContRef cont = evalState->cont_;
2481 cont->takeHandle( nullResult,
2482 evalState );
2483 return;
2486 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2487 ++i;
2488 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldSLCont( mem, op, i, state, evalState->dyn_, evalState->cont_, callLoc ) );
2490 op->call( op, evalState, nullResult, elem, state, callLoc );
2493 void
2494 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 )
2496 if( i == mem->rend( ) )
2498 Kernel::ContRef cont = evalState->cont_;
2499 cont->takeHandle( nullResult,
2500 evalState );
2501 return;
2504 Kernel::VariableHandle elem = Kernel::VariableHandle( new Kernel::Variable( *i ) );
2505 ++i;
2506 evalState->cont_ = Kernel::ContRef( new Kernel::VectorFunctionFoldSRCont( mem, op, i, state, evalState->dyn_, evalState->cont_, callLoc ) );
2508 op->call( op, evalState, elem, nullResult, state, callLoc );
2512 const char * Lang::ColorInterpolator::title( "<color-interpolator>" );
2513 const RefCountPtr< const Interaction::CoreLocation > Lang::ColorInterpolator::coreLoc( new Interaction::CharPtrLocation( Lang::ColorInterpolator::title ) );
2515 Lang::ColorInterpolator::ColorInterpolator( const RefCountPtr< KeyContainer > & key,
2516 const RefCountPtr< RGBContainer > & RGBcolor,
2517 const RefCountPtr< GrayContainer > & graycolor,
2518 const RefCountPtr< CMYKContainer > & CMYKcolor,
2519 ColorType colorType)
2520 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( Lang::ColorInterpolator::title ), true ) ),
2521 key_( key ), RGBcolor_ ( RGBcolor ), graycolor_ ( graycolor ), CMYKcolor_ ( CMYKcolor ), colorType_(colorType)
2523 formals_->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE );
2526 Lang::ColorInterpolator::~ColorInterpolator( )
2529 Kernel::VariableHandle
2530 Lang::ColorInterpolator::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
2532 if( strcmp( fieldID, "low" ) == 0 )
2534 return Helpers::newValHandle( new Lang::Float( key_->front( ) ) );
2536 if( strcmp( fieldID, "high" ) == 0 )
2538 return Helpers::newValHandle( new Lang::Float( key_->back( ) ) );
2540 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
2544 template< class COLOR_TYPE, class COLOR_CONTAINER >
2545 void
2546 Lang::ColorInterpolator::callHelper( Kernel::EvalState * evalState,
2547 const RefCountPtr< COLOR_CONTAINER > & colorContainer,
2548 double key, KeyContainer::const_iterator keyHi ) const
2550 if( keyHi == key_->end( ) )
2552 Kernel::ContRef cont = evalState->cont_;
2553 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->back( ) ) ),
2554 evalState );
2555 return;
2558 if( keyHi == key_->begin( ) )
2560 Kernel::ContRef cont = evalState->cont_;
2561 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorContainer->front( ) ) ),
2562 evalState );
2563 return;
2566 KeyContainer::const_iterator keyLo = keyHi - 1;
2567 double rem = ( key - *keyLo ) / ( *keyHi - *keyLo );
2569 Kernel::ContRef cont = evalState->cont_;
2571 typename COLOR_CONTAINER::const_iterator colorHi = colorContainer->begin( ) + ( keyHi - key_->begin( ) );
2572 typename COLOR_CONTAINER::const_iterator colorLo = colorHi - 1;
2574 cont->takeValue( RefCountPtr< const::Lang::Value >( new COLOR_TYPE( colorLo->mulNoCheck( 1 - rem ).addNoCheck( colorHi->mulNoCheck( rem ) ) ) ),
2575 evalState );
2579 void
2580 Lang::ColorInterpolator::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2582 const size_t ARITY = 1;
2583 if( args.size( ) != ARITY )
2585 throw Exceptions::CoreArityMismatch( coreLoc, ARITY, args.size( ) );
2588 typedef const Lang::Float ArgType;
2589 double key = Helpers::down_cast_CoreArgument< ArgType >( coreLoc, args, 0, callLoc )->val_;
2591 KeyContainer::const_iterator keyHi = lower_bound( key_->begin( ), key_->end( ), key );
2592 switch( colorType_ )
2594 case RGB:
2595 callHelper< Lang::RGB >( evalState, RGBcolor_, key, keyHi );
2596 break;
2597 case GRAY:
2598 callHelper< Lang::Gray >( evalState, graycolor_, key, keyHi );
2599 break;
2600 case CMYK:
2601 callHelper< Lang::CMYK >( evalState, CMYKcolor_, key, keyHi );
2602 break;
2603 case UNDEFINED:
2604 throw Exceptions::InternalError( "ColorInterpolator::call: Did not expect UNDEFINED in ennum switch." );
2608 bool
2609 Lang::ColorInterpolator::isTransforming( ) const
2611 return false;
2614 void
2615 Lang::ColorInterpolator::gcMark( Kernel::GCMarkedSet & marked )
2618 void
2619 Lang::ColorInterpolator::show( std::ostream & os ) const
2621 os << "< color interpolator in " ;
2622 switch( colorType_ )
2624 case RGB:
2625 os << "RGB" ;
2626 break;
2627 case GRAY:
2628 os << "Gray" ;
2629 break;
2630 case CMYK:
2631 os << "CMYK" ;
2632 break;
2633 case UNDEFINED:
2634 throw Exceptions::InternalError( "ColorInterpolator::show: Did not expect UNDEFINED in ennum switch." );
2636 os << " mode >" ;
2639 Lang::BinaryOperatorFunction::BinaryOperatorFunction( Ast::BinaryInfixExpr * opExpr, const char * coreSyntax )
2640 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( coreSyntax ), true ) ), opExpr_( opExpr ), coreLoc_( new Interaction::CharPtrLocation( coreSyntax ) )
2642 formals_->appendEvaluatedCoreFormal( "first", Kernel::THE_SLOT_VARIABLE );
2643 formals_->appendEvaluatedCoreFormal( "second", Kernel::THE_SLOT_VARIABLE );
2646 Lang::BinaryOperatorFunction::~BinaryOperatorFunction( )
2648 delete opExpr_;
2651 void
2652 Lang::BinaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2654 const size_t ARITY = 2;
2655 CHECK_ARITY( args, ARITY, coreLoc_ );
2656 RefCountPtr< const Lang::Value > arg1 = args.getValue( 0 );
2657 RefCountPtr< const Lang::Value > arg2 = args.getValue( 1 );
2661 Kernel::ContRef cont = evalState->cont_;
2662 cont->takeValue( arg1->binaryDispatch1( arg1, arg2, evalState->dyn_, opExpr_ ),
2663 evalState );
2665 catch( Exceptions::BinaryInfixNotApplicable & ball )
2667 ball.setCoreLocation( coreLoc_ );
2668 throw;
2672 bool
2673 Lang::BinaryOperatorFunction::isTransforming( ) const
2675 return false;
2678 void
2679 Lang::BinaryOperatorFunction::show( std::ostream & os ) const
2681 os << "< binary operator function for " << coreLoc_ << " >" ;
2685 Lang::UnaryOperatorFunction::UnaryOperatorFunction( Ast::UnaryExpr * opExpr, const char * coreSyntax )
2686 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( coreSyntax ), true ) ), opExpr_( opExpr ), coreLoc_( new Interaction::CharPtrLocation( coreSyntax ) )
2688 formals_->appendEvaluatedCoreFormal( "only", Kernel::THE_SLOT_VARIABLE );
2691 Lang::UnaryOperatorFunction::~UnaryOperatorFunction( )
2693 delete opExpr_;
2696 void
2697 Lang::UnaryOperatorFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2699 const size_t ARITY = 1;
2700 CHECK_ARITY( args, ARITY, coreLoc_ );
2702 RefCountPtr< const Lang::Value > arg = args.getValue( 0 );
2706 Kernel::ContRef cont = evalState->cont_;
2707 cont->takeValue( arg->unaryDispatch( arg, evalState->dyn_, opExpr_ ),
2708 evalState );
2710 catch( Exceptions::UnaryPrefixNotApplicable & ball )
2712 ball.setCoreLocation( coreLoc_ );
2713 throw;
2715 catch( Exceptions::UnaryPostfixNotApplicable & ball )
2717 ball.setCoreLocation( coreLoc_ );
2718 throw;
2722 bool
2723 Lang::UnaryOperatorFunction::isTransforming( ) const
2725 return false;
2728 void
2729 Lang::UnaryOperatorFunction::show( std::ostream & os ) const
2731 os << "< unary operator function for " << coreLoc_ << " >" ;
2735 Lang::Transform2DMethod_chop::Transform2DMethod_chop( RefCountPtr< const Lang::Transform2D > self, const Ast::FileID * fullMethodID )
2736 : Lang::MethodBase< class_type >( self, fullMethodID, false, true )
2738 formals_->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE );
2739 formals_->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE );
2742 Lang::Transform2DMethod_chop::~Transform2DMethod_chop( )
2745 void
2746 Lang::Transform2DMethod_chop::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2748 args.applyDefaults( callLoc );
2750 size_t argsi = 0;
2751 double Ltol = Helpers::down_cast_CoreArgument< const Lang::Float >( coreLoc_, args, argsi, callLoc )->val_;
2752 if( Ltol < 0 )
2754 throw Exceptions::CoreOutOfRange( coreLoc_, args, argsi, "Tolerances must not be negative." );
2757 ++argsi;
2758 Concrete::Length ptol = Helpers::down_cast_CoreArgument< const Lang::Length >( coreLoc_, args, argsi, callLoc )->get( );
2759 if( ptol < Concrete::ZERO_LENGTH )
2761 throw Exceptions::CoreOutOfRange( coreLoc_, args, argsi, "Tolerances must not be negative." );
2764 Lang::Transform2D * res = self_->clone( );
2766 CHOP_Ltol( res->xx_ );
2767 CHOP_Ltol( res->yx_ );
2769 CHOP_Ltol( res->xy_ );
2770 CHOP_Ltol( res->yy_ );
2772 CHOP_ptol( res->xt_ );
2773 CHOP_ptol( res->yt_ );
2775 Kernel::ContRef cont = evalState->cont_;
2776 cont->takeValue( RefCountPtr< const Lang::Value >( res ),
2777 evalState );
2781 Lang::Transform3DMethod_chop::Transform3DMethod_chop( RefCountPtr< const Lang::Transform3D > self, const Ast::FileID * fullMethodID )
2782 : Lang::MethodBase< class_type >( self, fullMethodID, false, true )
2784 formals_->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE );
2785 formals_->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE );
2788 Lang::Transform3DMethod_chop::~Transform3DMethod_chop( )
2791 void
2792 Lang::Transform3DMethod_chop::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
2794 args.applyDefaults( callLoc );
2796 size_t argsi = 0;
2797 double Ltol = Helpers::down_cast_CoreArgument< const Lang::Float >( coreLoc_, args, argsi, callLoc )->val_;
2798 if( Ltol < 0 )
2800 throw Exceptions::CoreOutOfRange( coreLoc_, args, argsi, "Tolerances must not be negative." );
2803 ++argsi;
2804 Concrete::Length ptol = Helpers::down_cast_CoreArgument< const Lang::Length >( coreLoc_, args, argsi, callLoc )->get( );
2805 if( ptol < Concrete::ZERO_LENGTH )
2807 throw Exceptions::CoreOutOfRange( coreLoc_, args, argsi, "Tolerances must not be negative." );
2810 Lang::Transform3D * res = self_->clone( );
2812 CHOP_Ltol( res->xx_ );
2813 CHOP_Ltol( res->yx_ );
2814 CHOP_Ltol( res->zx_ );
2816 CHOP_Ltol( res->xy_ );
2817 CHOP_Ltol( res->yy_ );
2818 CHOP_Ltol( res->zy_ );
2820 CHOP_Ltol( res->xz_ );
2821 CHOP_Ltol( res->yz_ );
2822 CHOP_Ltol( res->zz_ );
2824 CHOP_ptol( res->xt_ );
2825 CHOP_ptol( res->yt_ );
2826 CHOP_ptol( res->zt_ );
2828 Kernel::ContRef cont = evalState->cont_;
2829 cont->takeValue( RefCountPtr< const Lang::Value >( res ),
2830 evalState );