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