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.
300 // to be used for text rise
302 Lang::Transform2D::prependYShift( const Concrete::Length
& dy
)
304 // Implementation is symmetric to prependXShift.
310 // to be used for text horizontal scaling
312 Lang::Transform2D::prependXScale( double a
)
314 // Think of a as tf1.xx_ when composing transforms.
321 Lang::Transform2D::show( std::ostream
& os
) const
324 << xx_
<< ", " << yx_
<< ") ("
325 << xy_
<< ", " << yy_
<< ") ("
326 << Lang::Length( xt_
) << ", " << Lang::Length( yt_
) << ") ]" ;
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
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
);
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. */
458 Lang::Transform3D::clone( ) const
460 return new Transform3D( xx_
, yx_
, zx_
,
467 Lang::Transform3D::isIdentity( ) const
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;
476 Lang::Transform3D::isTranslation( ) const
479 xx_
== 1 && yy_
== 1 && zz_
== 1 &&
480 xy_
== 0 && xz_
== 0 &&
481 yx_
== 0 && yz_
== 0 &&
482 zx_
== 0 && zy_
== 0;
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_
);
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
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;
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.
541 // dgesvd_( & jobuvt, & jobuvt,
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,
549 // lwork = static_cast< __CLPK_integer >( tmpwork );
550 // work = new __CLPK_doublereal[ lwork ];
551 // workCleaner = RefCountPtr< __CLPK_doublereal >( work );
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
);
569 throw Exceptions::ExternalError( "Gnu Scientific Library SVD routine failed." );
583 // dgesvd_( & jobuvt, & jobuvt,
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,
594 // throw Exceptions::ExternalError( "LAPACK routine DGESVD failed." );
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 ) );
606 // if( s[ 1 ] < 1e-5 )
608 // throw Exceptions::AffineTransformKillsPlane( s[ 1 ] );
611 // s[ 0 ] = s[ 2 ] / s[ 0 ];
612 // s[ 1 ] = s[ 2 ] / s[ 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
633 // // Note that s[ 2 ] == 1
635 gsl_blas_dgemm( CblasNoTrans
,
641 planeNormalTransformData_
);
643 // cblas_dgemm( CblasColMajor, CblasNoTrans, CblasNoTrans,
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_
);
668 gsl_blas_dgemv( CblasNoTrans
,
670 planeNormalTransformData_
,
675 // cblas_dgemv( CblasColMajor, CblasNoTrans,
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( );
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 );
716 x0 = Concrete::Coords3D( 0, m_ / unitNormal_.y_, 0 );
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.
740 Concrete::UnitFloatTriple TunitNormal = Tnormal * ( 1 / TnormalNorm );
745 Lang::Transform3D::show( std::ostream
& os
) const
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 ),
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.
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( )
783 Kernel::Arguments::clone( ) const
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_
;
804 if( sinkArgList_
!= 0 )
806 throw Exceptions::NotImplemented( "Cloning of arguments with sink." );
807 //res.sinkArgList_ = sinkArgList_->clone( );
808 res
.sinkValues_
= sinkValues_
;
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.
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.
829 sinkArgList_
->orderedExprs_
->push_back( loc
);
830 sinkValues_
= RefCountPtr
< Lang::SingleList
>( new Lang::SingleListPair( arg
, sinkValues_
) );
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
);
847 (*variables_
)[ dst_
] = arg
;
848 locations_
[ dst_
] = loc
;
849 while( dst_
< variables_
->size( ) &&
850 (*variables_
)[ dst_
] != Kernel::THE_SLOT_VARIABLE
)
858 Kernel::Arguments::addNamedArgument( const char * id
, const Kernel::VariableHandle
& arg
, Ast::Expression
* loc
)
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( ) ||
874 j
->second
== dstEnd_
) )
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_
) );
886 throw Exceptions::NamedFormalMismatch( formals_
->formals_
->loc( ), strrefdup( id
), Exceptions::NamedFormalMismatch::VARIABLE
);
888 size_t pos
= j
->second
;
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
);
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
;
916 while( dst_
< variables_
->size( ) &&
917 (*variables_
)[ dst_
] != Kernel::THE_SLOT_VARIABLE
)
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
);
935 (*states_
)[ stateDst_
] = state
;
936 stateLocations_
[ stateDst_
] = loc
;
937 while( stateDst_
< states_
->size( ) &&
938 (*states_
)[ stateDst_
] != Kernel::THE_SLOT_STATE
)
946 Kernel::Arguments::addNamedState( const char * id
, const Kernel::StateHandle
& state
, Ast::Node
* loc
)
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
);
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
)
998 Kernel::Arguments::applyDefaults( )
1005 size_t numberOfArguments
= variables_
->size( );
1006 size_t formalsSize
= formals_
->defaults_
.size( );
1008 if( numberOfArguments
> formalsSize
&&
1011 /* The location of the ball must be set by the caller. */
1012 throw Exceptions::UserArityMismatch( formals_
->formals_
->loc( ), formalsSize
, numberOfArguments
, Exceptions::UserArityMismatch::VARIABLE
);
1015 size_t numberOfStates
= states_
->size( );
1016 size_t formalsStateSize
= formals_
->formals_
->stateOrder_
->size( );
1017 if( numberOfStates
> formalsStateSize
)
1019 /* The location of the ball must be set by the caller. */
1020 throw Exceptions::UserArityMismatch( formals_
->formals_
->loc( ), formalsStateSize
, numberOfStates
, Exceptions::UserArityMismatch::STATE
);
1023 /* First the easy part: All states must be specified.
1025 std::map
< size_t, RefCountPtr
< const char > > * missingStates
= 0;
1028 typedef typeof *states_ ListType
;
1029 for( ListType::const_iterator i
= states_
->begin( ); i
!= states_
->end( ); ++i
, ++pos
)
1031 if( *i
== Kernel::THE_SLOT_STATE
)
1033 if( missingStates
== 0 )
1035 missingStates
= new typeof *missingStates
;
1037 typedef typeof *(formals_
->formals_
->stateOrder_
) FormalsMapType
;
1038 FormalsMapType
& formalsMap
= *(formals_
->formals_
->stateOrder_
);
1039 for( FormalsMapType::const_iterator i
= formalsMap
.begin( ); ; )
1041 if( i
->second
== pos
)
1043 missingStates
->insert( missingStates
->begin( ), std::pair
< size_t, RefCountPtr
< const char > >( pos
, strrefdup( i
->first
) ) );
1047 if( i
== formalsMap
.end( ) )
1049 throw Exceptions::InternalError( "Failed to find position of missing state." );
1056 if( numberOfStates
< formalsStateSize
)
1058 if( missingStates
== 0 )
1060 missingStates
= new typeof *missingStates
;
1062 typedef typeof *(formals_
->formals_
->stateOrder_
) FormalsMapType
;
1063 FormalsMapType
& formalsMap
= *(formals_
->formals_
->stateOrder_
);
1064 FormalsMapType::const_iterator i
= formalsMap
.begin( );
1065 for( size_t j
= 0; j
< numberOfStates
; ++j
)
1070 for( ; i
!= formalsMap
.end( ); ++i
, ++pos
)
1072 missingStates
->insert( missingStates
->begin( ), std::pair
< size_t, RefCountPtr
< const char > >( pos
, strrefdup( i
->first
) ) );
1078 /* Allocate positions in the vector for all arguments.
1080 variables_
->reserve( hasSink_
? formalsSize
+ 1 : formalsSize
);
1081 while( variables_
->size( ) < formalsSize
)
1083 variables_
->push_back( Kernel::THE_SLOT_VARIABLE
);
1085 locations_
.resize( formalsSize
);
1087 typedef typeof *variables_ MyListType
;
1088 typedef typeof formals_
->defaults_ DefaultListType
;
1089 typedef typeof formals_
->locations_ LocationListType
;
1090 DefaultListType::const_iterator src
= formals_
->defaults_
.begin( );
1091 LocationListType::const_iterator srcLoc
= formals_
->locations_
.begin( );
1092 std::map
< size_t, RefCountPtr
< const char > > * missingArgs
= 0;
1094 typedef typeof locations_ MyLocationsType
;
1095 for( MyListType::iterator dst
= variables_
->begin( ); dst
!= variables_
->end( ); ++dst
, ++src
, ++srcLoc
, ++pos
)
1097 if( *dst
== Kernel::THE_SLOT_VARIABLE
)
1099 /* Handle error situation.
1101 if( *src
== Kernel::THE_SLOT_VARIABLE
)
1103 if( missingArgs
== 0 )
1105 missingArgs
= new typeof *missingArgs
;
1107 typedef typeof *(formals_
->formals_
->argumentOrder_
) FormalsMapType
;
1108 FormalsMapType
& formalsMap
= *(formals_
->formals_
->argumentOrder_
);
1109 for( FormalsMapType::const_iterator i
= formalsMap
.begin( ); ; )
1111 if( i
->second
== pos
)
1113 missingArgs
->insert( missingArgs
->begin( ), std::pair
< size_t, RefCountPtr
< const char > >( pos
, strrefdup( i
->first
) ) );
1117 if( i
== formalsMap
.end( ) )
1119 throw Exceptions::InternalError( "Failed to find position of missing argument." );
1127 locations_
[ pos
] = *srcLoc
;
1131 if( missingArgs
!= 0 || missingStates
!= 0 )
1133 throw Exceptions::MissingArguments( formals_
->formals_
->loc( ), missingArgs
, missingStates
);
1138 variables_
->push_back
1139 ( Helpers::newValHandle
1140 ( new Lang::Structure( sinkArgList_
,
1142 true ) ) ); // true means that the sinkArgList_ gets owned by the Structure.
1148 Kernel::VariableHandle
&
1149 Kernel::Arguments::getHandle( size_t i
)
1151 return (*variables_
)[ i
];
1154 RefCountPtr
< const Lang::Value
> &
1155 Kernel::Arguments::getValue( size_t i
)
1157 return (*variables_
)[ i
]->getUntyped( );
1160 const Ast::SourceLocation
&
1161 Kernel::Arguments::getLoc( size_t i
) const
1163 return locations_
[ i
]->loc( );
1167 Kernel::Arguments::getNode( size_t i
) const
1169 return locations_
[ i
];
1173 Kernel::Arguments::getThunk( size_t i
)
1175 return (*variables_
)[ i
]->copyThunk( );
1179 Kernel::Arguments::isSlot( size_t i
) const
1181 return (*variables_
)[ i
] == Kernel::THE_SLOT_VARIABLE
;
1185 Kernel::Arguments::getState( size_t i
)
1187 return (*states_
)[ i
];
1190 const Ast::SourceLocation
&
1191 Kernel::Arguments::getStateLoc( size_t i
) const
1193 return stateLocations_
[ i
]->loc( );
1197 Kernel::Arguments::size( ) const
1199 return variables_
->size( );
1203 Kernel::Arguments::empty( ) const
1205 return variables_
->empty( );
1209 Kernel::Arguments::setMutatorSelf( Kernel::StateHandle mutatorSelf
)
1211 mutatorSelf_
= mutatorSelf
;
1215 Kernel::Arguments::getMutatorSelf( )
1217 if( mutatorSelf_
== 0 )
1219 throw Exceptions::InternalError( "Kernel::Arguments::getMutatorSelf: self is null." );
1221 return mutatorSelf_
;
1225 Kernel::Arguments::gcMark( Kernel::GCMarkedSet
& marked
)
1228 typedef typeof *variables_ ListType
;
1229 for( ListType::const_iterator i
= variables_
->begin( ); i
!= variables_
->end( ); ++i
)
1231 const_cast< Kernel::Variable
* >( i
->getPtr( ) )->gcMark( marked
);
1236 Kernel::Environment::ValueVector
1237 Kernel::Arguments::getVariables( )
1242 Kernel::Environment::StateVector
1243 Kernel::Arguments::getStates( )
1254 class FunctionOneHandleCont
: public Kernel::Continuation
1256 RefCountPtr
< const Lang::Function
> fun_
;
1257 Kernel::PassedDyn dyn_
;
1258 Kernel::ContRef cont_
;
1260 FunctionOneHandleCont( const RefCountPtr
< const Lang::Function
> & fun
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1261 : Kernel::Continuation( traceLoc
), fun_( fun
), dyn_( dyn
), cont_( cont
)
1263 virtual ~FunctionOneHandleCont( ) { }
1264 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
1266 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1267 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1270 if( val
->isThunk( ) )
1272 val
->force( val
, evalState
);
1276 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1277 args
.addOrderedArgument( val
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1279 evalState
->dyn_
= dyn_
;
1280 evalState
->cont_
= cont_
;
1281 fun_
->call( evalState
, args
, traceLoc_
);
1283 virtual Kernel::ContRef
up( ) const
1287 virtual RefCountPtr
< const char > description( ) const
1289 return strrefdup( "internal function call with one handle" );
1291 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1293 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1294 dyn_
->gcMark( marked
);
1295 cont_
->gcMark( marked
);
1299 class FunctionTwoHandlesCont_2
: public Kernel::Continuation
1301 RefCountPtr
< const Lang::Function
> fun_
;
1302 Kernel::VariableHandle arg1_
;
1303 Kernel::PassedDyn dyn_
;
1304 Kernel::ContRef cont_
;
1306 FunctionTwoHandlesCont_2( const RefCountPtr
< const Lang::Function
> & fun
, const Kernel::VariableHandle
& arg1
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1307 : Kernel::Continuation( traceLoc
), fun_( fun
), arg1_( arg1
), dyn_( dyn
), cont_( cont
)
1309 virtual ~FunctionTwoHandlesCont_2( ) { }
1310 virtual void takeHandle( Kernel::VariableHandle arg2
, Kernel::EvalState
* evalState
, bool dummy
) const
1312 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1313 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1316 if( arg2
->isThunk( ) )
1318 arg2
->force( arg2
, evalState
);
1322 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1323 args
.addOrderedArgument( arg1_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1324 args
.addOrderedArgument( arg2
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1325 evalState
->dyn_
= dyn_
;
1326 evalState
->cont_
= cont_
;
1327 fun_
->call( evalState
, args
, traceLoc_
);
1329 virtual Kernel::ContRef
up( ) const
1333 virtual RefCountPtr
< const char > description( ) const
1335 return strrefdup( "internal function call with two handles, second" );
1337 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1339 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1340 dyn_
->gcMark( marked
);
1341 cont_
->gcMark( marked
);
1345 class FunctionTwoHandlesCont_1
: public Kernel::Continuation
1347 RefCountPtr
< const Lang::Function
> fun_
;
1348 Kernel::VariableHandle arg2_
;
1350 Kernel::PassedDyn dyn_
;
1351 Kernel::ContRef cont_
;
1353 FunctionTwoHandlesCont_1( const RefCountPtr
< const Lang::Function
> & fun
, const Kernel::VariableHandle
& arg2
, bool forceArg2
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1354 : Kernel::Continuation( traceLoc
), fun_( fun
), arg2_( arg2
), forceArg2_( forceArg2
), dyn_( dyn
), cont_( cont
)
1356 virtual ~FunctionTwoHandlesCont_1( ) { }
1357 virtual void takeHandle( Kernel::VariableHandle arg1
, Kernel::EvalState
* evalState
, bool dummy
) const
1359 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1360 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1363 if( arg1
->isThunk( ) )
1365 arg1
->force( arg1
, evalState
);
1371 Kernel::ContRef newCont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( fun_
, arg1
, dyn_
, cont_
, traceLoc_
) );
1372 evalState
->cont_
= newCont
;
1373 newCont
->takeHandle( arg2_
, evalState
);
1377 /* The second handle need not be forced
1379 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1380 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1381 args
.addOrderedArgument( arg2_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1382 evalState
->dyn_
= dyn_
;
1383 evalState
->cont_
= cont_
;
1384 fun_
->call( evalState
, args
, traceLoc_
);
1386 virtual Kernel::ContRef
up( ) const
1390 virtual RefCountPtr
< const char > description( ) const
1392 return strrefdup( "internal function call with two handles, first" );
1394 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1396 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1397 dyn_
->gcMark( marked
);
1398 cont_
->gcMark( marked
);
1402 class FunctionTwoHandlesOneStateCont_2
: public Kernel::Continuation
1404 RefCountPtr
< const Lang::Function
> fun_
;
1405 Kernel::VariableHandle arg1_
;
1406 Kernel::StateHandle state_
;
1407 Kernel::PassedDyn dyn_
;
1408 Kernel::ContRef cont_
;
1410 FunctionTwoHandlesOneStateCont_2( const RefCountPtr
< const Lang::Function
> & fun
, const Kernel::VariableHandle
& arg1
, Kernel::StateHandle state
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1411 : Kernel::Continuation( traceLoc
), fun_( fun
), arg1_( arg1
), state_( state
), dyn_( dyn
), cont_( cont
)
1413 virtual ~FunctionTwoHandlesOneStateCont_2( ) { }
1414 virtual void takeHandle( Kernel::VariableHandle arg2
, Kernel::EvalState
* evalState
, bool dummy
) const
1416 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1417 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1420 if( arg2
->isThunk( ) )
1422 arg2
->force( arg2
, evalState
);
1426 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1427 args
.addOrderedArgument( arg1_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1428 args
.addOrderedArgument( arg2
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1429 args
.addOrderedState( state_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1430 evalState
->dyn_
= dyn_
;
1431 evalState
->cont_
= cont_
;
1432 fun_
->call( evalState
, args
, traceLoc_
);
1434 virtual Kernel::ContRef
up( ) const
1438 virtual RefCountPtr
< const char > description( ) const
1440 return strrefdup( "internal function call with two handles and one state, second" );
1442 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1444 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1445 state_
->gcMark( marked
);
1446 dyn_
->gcMark( marked
);
1447 cont_
->gcMark( marked
);
1451 class FunctionTwoHandlesOneStateCont_1
: public Kernel::Continuation
1453 RefCountPtr
< const Lang::Function
> fun_
;
1454 Kernel::VariableHandle arg2_
;
1456 Kernel::StateHandle state_
;
1457 Kernel::PassedDyn dyn_
;
1458 Kernel::ContRef cont_
;
1460 FunctionTwoHandlesOneStateCont_1( const RefCountPtr
< const Lang::Function
> & fun
, const Kernel::VariableHandle
& arg2
, bool forceArg2
, Kernel::StateHandle state
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1461 : Kernel::Continuation( traceLoc
), fun_( fun
), arg2_( arg2
), forceArg2_( forceArg2
), state_( state
), dyn_( dyn
), cont_( cont
)
1463 virtual ~FunctionTwoHandlesOneStateCont_1( ) { }
1464 virtual void takeHandle( Kernel::VariableHandle arg1
, Kernel::EvalState
* evalState
, bool dummy
) const
1466 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1467 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1470 if( arg1
->isThunk( ) )
1472 arg1
->force( arg1
, evalState
);
1478 Kernel::ContRef newCont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( fun_
, arg1
, state_
, dyn_
, cont_
, traceLoc_
) );
1479 evalState
->cont_
= newCont
;
1480 newCont
->takeHandle( arg2_
, evalState
);
1484 /* The second handle need not be forced
1486 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1487 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1488 args
.addOrderedArgument( arg2_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1489 args
.addOrderedState( state_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1490 evalState
->dyn_
= dyn_
;
1491 evalState
->cont_
= cont_
;
1492 fun_
->call( evalState
, args
, traceLoc_
);
1494 virtual Kernel::ContRef
up( ) const
1498 virtual RefCountPtr
< const char > description( ) const
1500 return strrefdup( "internal function call with two handles and one state, first" );
1502 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1504 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1505 dyn_
->gcMark( marked
);
1506 cont_
->gcMark( marked
);
1507 state_
->gcMark( marked
);
1515 Lang::Function::Function( Kernel::EvaluatedFormals
* formals
)
1516 : formals_( formals
)
1519 DISPATCHIMPL( Function
);
1521 Lang::Function::~Function( )
1525 delete formals_
->formals_
;
1531 Lang::Function::transformed( const Lang::Transform2D
& tf
, Kernel::ValueRef self
) const
1533 return Kernel::ValueRef( new Lang::TransformedFunction2D( tf
, self
.down_cast
< const Lang::Function
>( ) ) );
1537 Lang::Function::call( Kernel::EvalState
* evalState
, const Kernel::ValueRef
& arg1
, const Ast::SourceLocation
& callLoc
) const
1539 Kernel::Arguments args
= this->newCurriedArguments( );
1541 args
.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1
) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1543 this->call( evalState
, args
, callLoc
);
1547 Lang::Function::analyze( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
)
1549 Ast::StateIDSet
* freeStates
= new Ast::StateIDSet
;
1550 this->analyze_impl( parent
, env
, freeStates
);
1551 if( ! freeStates
->empty( ) )
1553 Ast::theAnalysisErrorsList
.push_back( new Exceptions::IllegalFreeStates( parent
->loc( ), freeStates
, "this is a function" ) );
1562 Lang::Function::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1564 throw Exceptions::InternalError( "A syntax function is not overriding the analyze method." );
1568 Lang::Function::call( Kernel::EvalState
* evalState
, const Kernel::ValueRef
& arg1
, const Kernel::ValueRef
& arg2
, const Ast::SourceLocation
& callLoc
) const
1570 Kernel::Arguments args
= this->newCurriedArguments( );
1572 args
.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1
) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1573 args
.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg2
) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1575 this->call( evalState
, args
, callLoc
);
1578 Ast::ArgListExprs
* Lang::Function::oneExprArgList
= new Ast::ArgListExprs( static_cast< size_t >( 1 ) );
1579 Ast::ArgListExprs
* Lang::Function::twoExprsArgList
= new Ast::ArgListExprs( static_cast< size_t >( 2 ) );
1582 Lang::Function::call( const RefCountPtr
< const Lang::Function
> & selfRef
, Kernel::EvalState
* evalState
, const Kernel::VariableHandle
& arg1
, const Ast::SourceLocation
& callLoc
) const
1584 const RefCountPtr
< const Kernel::CallContInfo
> info
= this->newCallContInfo( Lang::Function::oneExprArgList
, *evalState
);
1586 if( info
->force( 0 ) )
1588 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionOneHandleCont( selfRef
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1589 evalState
->cont_
= cont
;
1590 cont
->takeHandle( arg1
, evalState
);
1594 /* The handle need not be forced
1596 Kernel::Arguments args
= this->newCurriedArguments( );
1597 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1598 this->call( evalState
, args
, callLoc
);
1602 Lang::Function::call( const RefCountPtr
< const Lang::Function
> & selfRef
, Kernel::EvalState
* evalState
, const Kernel::VariableHandle
& arg1
, const Kernel::VariableHandle
& arg2
, const Ast::SourceLocation
& callLoc
) const
1604 const RefCountPtr
< const Kernel::CallContInfo
> info
= this->newCallContInfo( Lang::Function::twoExprsArgList
, *evalState
);
1606 /* Remember that arguments are ordered backwards!
1609 if( info
->force( 1 ) )
1611 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_1( selfRef
, arg2
, info
->force( 0 ), evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1612 evalState
->cont_
= cont
;
1613 cont
->takeHandle( arg1
, evalState
);
1617 if( info
->force( 0 ) )
1619 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( selfRef
, arg1
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1620 evalState
->cont_
= cont
;
1621 cont
->takeHandle( arg2
, evalState
);
1625 /* None of the handles need to be forced
1627 Kernel::Arguments args
= this->newCurriedArguments( );
1628 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1629 args
.addOrderedArgument( arg2
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1630 this->call( evalState
, args
, callLoc
);
1634 Lang::Function::call( const RefCountPtr
< const Lang::Function
> & selfRef
, Kernel::EvalState
* evalState
, const Kernel::VariableHandle
& arg1
, const Kernel::VariableHandle
& arg2
, Kernel::StateHandle state
, const Ast::SourceLocation
& callLoc
) const
1636 /* I'm not quite sure if we should also put a dummy state argument in info...
1638 const RefCountPtr
< const Kernel::CallContInfo
> info
= this->newCallContInfo( Lang::Function::twoExprsArgList
, *evalState
);
1640 /* Remember that arguments are ordered backwards!
1643 if( info
->force( 1 ) )
1645 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_1( selfRef
, arg2
, info
->force( 0 ), state
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1646 evalState
->cont_
= cont
;
1647 cont
->takeHandle( arg1
, evalState
);
1651 if( info
->force( 0 ) )
1653 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( selfRef
, arg1
, state
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1654 evalState
->cont_
= cont
;
1655 cont
->takeHandle( arg2
, evalState
);
1659 /* None of the handles need to be forced
1661 Kernel::Arguments args
= this->newCurriedArguments( );
1662 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1663 args
.addOrderedArgument( arg2
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1664 args
.addOrderedState( state
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1665 this->call( evalState
, args
, callLoc
);
1669 RefCountPtr
< Kernel::CallContInfo
>
1670 Lang::Function::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const
1672 return formals_
->newCallContInfo( argList
, evalState
);
1675 RefCountPtr
< Kernel::CallContInfo
>
1676 Lang::Function::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const
1678 return formals_
->newCallContInfo( argList
, evalState
, curryArgs
);
1682 Lang::Function::newCurriedArguments( ) const
1684 return Kernel::Arguments( formals_
);
1688 RefCountPtr
< const Lang::Class
> Lang::Function::TypeID( new Lang::SystemFinalClass( strrefdup( "Function" ) ) );
1689 TYPEINFOIMPL( Function
);
1691 Kernel::EvaluatedFormals::EvaluatedFormals( Kernel::Formals
* formals
)
1692 : selectiveForcing_( false ), forceAll_( false ), formals_( formals
), isSink_( true )
1695 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID
* locationFileID
)
1696 : selectiveForcing_( true ), formals_( 0 ), isSink_( true )
1698 Kernel::Formals
* formals( new Kernel::Formals( ) );
1699 formals
->setLoc( Ast::SourceLocation( locationFileID
) );
1703 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID
* locationFileID
, bool forceAll
)
1704 : selectiveForcing_( false ), forceAll_( forceAll
), formals_( 0 ), isSink_( true )
1706 Kernel::Formals
* formals( new Kernel::Formals( ) );
1707 formals
->setLoc( Ast::SourceLocation( locationFileID
) );
1711 Kernel::EvaluatedFormals::~EvaluatedFormals( )
1713 /* Don't delete the orderedFormals, since we don't own it. A case for reference counting? */
1716 RefCountPtr
< Kernel::CallContInfo
>
1717 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const
1719 if( selectiveForcing_
)
1721 return RefCountPtr
< Kernel::CallContInfo
>( new Kernel::CallContInfo( argList
, evalState
, formals_
->newArgListForcePos( argList
) ) );
1725 return RefCountPtr
< Kernel::CallContInfo
>( new Kernel::CallContInfo( argList
, evalState
, forceAll_
) );
1729 RefCountPtr
< Kernel::CallContInfo
>
1730 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const
1732 if( selectiveForcing_
)
1734 return RefCountPtr
< Kernel::CallContInfo
>( new Kernel::CallContInfo( argList
, evalState
, formals_
->newArgListForcePos( argList
, curryArgs
) ) );
1738 return RefCountPtr
< Kernel::CallContInfo
>( new Kernel::CallContInfo( argList
, evalState
, forceAll_
) );
1743 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, const Ast::Node
* loc
, bool force
)
1745 if( ! selectiveForcing_
)
1747 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function does not have selective forcing." );
1749 (*(formals_
->argumentOrder_
))[ id
] = defaults_
.size( );
1750 formals_
->forcePos_
.push_back( force
);
1751 defaults_
.push_back( defaultVal
);
1752 locations_
.push_back( loc
);
1756 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, const Ast::Node
* loc
)
1758 if( selectiveForcing_
)
1760 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function requires individual forcing specification." );
1762 (*(formals_
->argumentOrder_
))[ id
] = defaults_
.size( );
1763 formals_
->forcePos_
.push_back( forceAll_
);
1764 defaults_
.push_back( defaultVal
);
1765 locations_
.push_back( loc
);
1769 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, bool force
)
1771 appendEvaluatedFormal( id
, defaultVal
, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION
, force
);
1775 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
)
1777 appendEvaluatedFormal( id
, defaultVal
, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION
);
1781 Kernel::EvaluatedFormals::appendCoreStateFormal( const char * id
)
1783 (*(formals_
->stateOrder_
))[ id
] = formals_
->stateOrder_
->size( );
1787 Kernel::EvaluatedFormals::gcMark( Kernel::GCMarkedSet
& marked
)
1789 typedef typeof defaults_ ListType
;
1790 for( ListType::const_iterator i
= defaults_
.begin( ); i
!= defaults_
.end( ); ++i
)
1792 if( *i
!= NullPtr
< Kernel::Variable
>( ) )
1794 const_cast< Kernel::Variable
* >( i
->getPtr( ) )->gcMark( marked
);
1800 Lang::CuteFunction::CuteFunction( RefCountPtr
< const Lang::Function
> callee
, const Kernel::Arguments
& someArgs
)
1801 : Lang::Function( 0 ), callee_( callee
), someArgs_( someArgs
.clone( ) )
1804 Lang::CuteFunction::~CuteFunction( )
1807 RefCountPtr
< Kernel::CallContInfo
>
1808 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const
1810 return callee_
->newCallContInfo( argList
, evalState
, someArgs_
);
1813 RefCountPtr
< Kernel::CallContInfo
>
1814 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const
1816 /* when we are the callee of a CuteFunction, our someArgs are part of that CuteFunction's someArgs, and hence curryArgs
1817 * contains everything that is to be passed to our callee.
1819 return callee_
->newCallContInfo( argList
, evalState
, curryArgs
);
1823 Lang::CuteFunction::newCurriedArguments( ) const
1825 return someArgs_
.clone( );
1829 Lang::CuteFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1831 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1832 Also note that the total set of arguments being passed to the original function is no more than someArgs and what was passed in the last call.
1834 callee_
->call( evalState
, args
, callLoc
);
1838 Lang::CuteFunction::isTransforming( ) const
1840 return callee_
->isTransforming( );
1844 Lang::CuteFunction::gcMark( Kernel::GCMarkedSet
& marked
)
1846 const_cast< Lang::Function
* >( callee_
.getPtr( ) )->gcMark( marked
);
1847 someArgs_
.gcMark( marked
);
1851 Lang::CuteFunction::show( std::ostream
& os
) const
1853 os
<< "< evaluated cut of: " ;
1854 callee_
->show( os
);
1859 Lang::ComposedFunction::ComposedFunction( const RefCountPtr
< const Lang::Function
> & second
, const RefCountPtr
< const Lang::Function
> & first
)
1860 : Lang::Function( 0 ), second_( second
), first_( first
)
1863 Lang::ComposedFunction::~ComposedFunction( )
1867 Lang::ComposedFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1869 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1870 Also note that the total set of arguments being passed to the original function is no more than someArgs and what was passed in the last call.
1872 evalState
->cont_
= Kernel::ContRef( new Kernel::ComposedFunctionCall_cont( second_
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1873 first_
->call( evalState
, args
, callLoc
);
1876 RefCountPtr
< Kernel::CallContInfo
>
1877 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const
1879 return first_
->newCallContInfo( argList
, evalState
);
1882 RefCountPtr
< Kernel::CallContInfo
>
1883 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const
1885 return first_
->newCallContInfo( argList
, evalState
, curryArgs
);
1889 Lang::ComposedFunction::newCurriedArguments( ) const
1891 return first_
->newCurriedArguments( );
1895 Lang::ComposedFunction::isTransforming( ) const
1897 return second_
->isTransforming( );
1901 Lang::ComposedFunction::gcMark( Kernel::GCMarkedSet
& marked
)
1903 const_cast< Lang::Function
* >( second_
.getPtr( ) )->gcMark( marked
);
1904 const_cast< Lang::Function
* >( first_
.getPtr( ) )->gcMark( marked
);
1908 Lang::ComposedFunction::show( std::ostream
& os
) const
1910 os
<< "< composition: " ;
1911 second_
->show( os
);
1924 std::vector
< Kernel::VariableHandle
> thunks_
;
1926 SpanThunks( const Kernel::VariableHandle
& begin
, const Kernel::VariableHandle
& end
, const Kernel::VariableHandle
& step
, const Kernel::VariableHandle
& count
)
1928 thunks_
.reserve( 4 );
1929 thunks_
.push_back( count
);
1930 thunks_
.push_back( step
);
1931 thunks_
.push_back( end
);
1932 thunks_
.push_back( begin
);
1934 const Kernel::VariableHandle
& operator [] ( size_t i
) const
1936 return thunks_
[ i
];
1940 void gcMark( Kernel::GCMarkedSet
& marked
)
1942 typedef typeof thunks_ VecType
;
1943 for( VecType::iterator i
= thunks_
.begin( ); i
!= thunks_
.end( ); ++i
)
1945 (*i
)->gcMark( marked
);
1950 class SpanForcingContinuation
: public Continuation
1952 RefCountPtr
< const Kernel::SpanThunks
> thunks_
;
1954 RefCountPtr
< const Lang::SingleList
> values_
;
1955 RefCountPtr
< const Lang::Value
> last_
;
1956 Kernel::ContRef cont_
;
1958 SpanForcingContinuation( const RefCountPtr
< const Kernel::SpanThunks
> & thunks
, size_t i
, const RefCountPtr
< const Lang::SingleList
> & values
, const RefCountPtr
< const Lang::Value
> & last
, const Kernel::ContRef
& cont
, const Ast::SourceLocation
& traceLoc
)
1959 : Kernel::Continuation( traceLoc
), thunks_( thunks
), i_( i
), values_( values
), last_( last
), cont_( cont
)
1961 ~SpanForcingContinuation( )
1963 static void finish( RefCountPtr
< const Lang::SingleList
> values
, RefCountPtr
< const Lang::Value
> last
, Kernel::EvalState
* evalState
, const Ast::SourceLocation
& traceLoc
)
1965 Kernel::Arguments args
= Lang::THE_FUNCTION_RANGE
->newCurriedArguments( );
1966 RefCountPtr
< const Lang::SingleListPair
> src
= values
.down_cast
< const Lang::SingleListPair
>( );
1967 args
.addOrderedArgument( src
->car_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1968 src
= src
->cdr_
.down_cast
< const Lang::SingleListPair
>( );
1969 args
.addOrderedArgument( src
->car_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1970 src
= src
->cdr_
.down_cast
< const Lang::SingleListPair
>( );
1971 args
.addOrderedArgument( src
->car_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1972 src
= src
->cdr_
.down_cast
< const Lang::SingleListPair
>( );
1973 args
.addOrderedArgument( src
->car_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1974 Lang::Core_range::makeRange( "<span>", evalState
, args
, traceLoc
, true, last
);
1976 virtual void takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
1978 RefCountPtr
< const Lang::SingleList
> values
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( val
) ), values_
) );
1980 for( size_t i
= i_
+ 1; i
< 4; ++i
)
1982 const Kernel::VariableHandle
& var
= (*thunks_
)[ i
];
1983 if( var
->isThunk( ) )
1985 evalState
->cont_
= Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_
, i
, values
, last_
, cont_
, traceLoc_
) );
1986 var
->force( var
, evalState
);
1987 evalState
->dyn_
= Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState
->dyn_
, last_
) );
1990 values
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( var
, values
) );
1992 evalState
->cont_
= cont_
;
1993 finish( values
, last_
, evalState
, traceLoc_
);
1995 virtual Kernel::ContRef
up( ) const
1999 virtual RefCountPtr
< const char > description( ) const
2001 std::ostringstream msg
;
2002 msg
<< "force span parameter number " << i_
;
2003 return strrefdup( msg
);
2005 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2007 const_cast< Kernel::SpanThunks
* >( thunks_
.getPtr( ) )->gcMark( marked
);
2008 const_cast< Lang::SingleList
* >( values_
.getPtr( ) )->gcMark( marked
);
2009 const_cast< Lang::Value
* >( last_
.getPtr( ) )->gcMark( marked
);
2010 cont_
->gcMark( marked
);
2016 RefCountPtr
< const Lang::Class
> Lang::Span::TypeID( new Lang::SystemFinalClass( strrefdup( "Span" ) ) );
2017 TYPEINFOIMPL( Span
);
2019 Lang::Span::Span( const Kernel::VariableHandle
& begin
, const Kernel::VariableHandle
& end
, const Kernel::VariableHandle
& step
, const Kernel::VariableHandle
& count
)
2020 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<span>" ), true ) ),
2021 thunks_( new Kernel::SpanThunks( begin
, end
, step
, count
) )
2023 formals_
->appendEvaluatedCoreFormal( "last", Kernel::THE_SLOT_VARIABLE
);
2026 Lang::Span::~Span( )
2030 Lang::Span::gcMark( Kernel::GCMarkedSet
& marked
)
2032 const_cast< Kernel::SpanThunks
* >( thunks_
.getPtr( ) )->gcMark( marked
);
2036 Lang::Span::show( std::ostream
& os
) const
2042 Lang::Span::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2044 args
.applyDefaults( );
2046 RefCountPtr
< const Lang::SingleList
> values
= Lang::THE_CONS_NULL
;
2047 for( size_t i
= 0; i
< 4; ++i
)
2049 const Kernel::VariableHandle
& var
= (*thunks_
)[ i
];
2050 if( var
->isThunk( ) )
2052 evalState
->cont_
= Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_
, i
, values
, args
.getValue( 0 ), evalState
->cont_
, callLoc
) );
2053 var
->force( var
, evalState
);
2054 evalState
->dyn_
= Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState
->dyn_
, args
.getValue( 0 ) ) );
2057 values
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( var
, values
) );
2060 /* We only reach this point if there were no thunks at all to be forced. */
2061 Kernel::SpanForcingContinuation::finish( values
, args
.getValue( 0 ), evalState
, callLoc
);
2065 Lang::Span::isTransforming( ) const
2071 Lang::UserFunction::UserFunction( Kernel::EvaluatedFormals
* formals
, Ast::Expression
* body
, Kernel::PassedEnv env
, const Ast::FunctionMode
& functionMode
)
2072 : Lang::Function( formals
), body_( body
), env_( env
), functionMode_( functionMode
)
2075 // DISPATCHIMPL( UserFunction );
2077 Lang::UserFunction::~UserFunction( )
2079 // Note that we don't delete the things that we most likely share with other objects
2080 // Reference counting could be used here, but there will never be more such things than there are function expressions in the source
2082 // This prevents formals->formals from being deleted by Lang::Function::~Function
2088 Lang::UserFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2090 args
.applyDefaults( );
2091 evalState
->env_
= new Kernel::Environment( Kernel::theEnvironmentList
, env_
, formals_
->formals_
->argumentIdentifiers_
, args
.getVariables( ), formals_
->formals_
->stateIdentifiers_
, args
.getStates( ), "Closure" );
2092 evalState
->expr_
= body_
;
2096 Lang::UserFunction::isTransforming( ) const
2098 return ( functionMode_
& Ast::FUNCTION_TRANSFORMING
) != 0;
2102 Lang::UserFunction::gcMark( Kernel::GCMarkedSet
& marked
)
2104 env_
->gcMark( marked
);
2108 Lang::UserFunction::body( )
2114 Lang::UserFunction::show( std::ostream
& os
) const
2116 os
<< "< user function with body at " << body_
->loc( ) << " >" ;
2120 Lang::TransformedFunction2D::TransformedFunction2D( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Function
> & fun
)
2121 : Lang::Function( 0 ), tf_( tf
), fun_( fun
)
2124 Lang::TransformedFunction2D::~TransformedFunction2D( )
2128 Lang::TransformedFunction2D::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2130 evalState
->cont_
= Kernel::ContRef( new Kernel::Transform2DCont( tf_
, evalState
->cont_
, 0 ) );
2131 fun_
->call( evalState
, args
, callLoc
);
2135 Lang::TransformedFunction2D::isTransforming( ) const
2137 return fun_
->isTransforming( );
2141 Lang::TransformedFunction2D::gcMark( Kernel::GCMarkedSet
& marked
)
2143 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
2147 Lang::TransformedFunction2D::show( std::ostream
& os
) const
2149 os
<< "< transformed function >" ;
2154 Lang::VectorFunction::VectorFunction( const std::vector
< Kernel::ValueRef
> * mem
)
2155 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<vector>" ), true ) ), mem_( mem
),
2156 memNumeric_( NullPtr
< const std::vector
< double > >( ) ),
2157 list_( NullPtr
< Kernel::Variable
>( ) )
2159 formals_
->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE
);
2162 // DISPATCHIMPL( VectorFunction );
2164 Lang::VectorFunction::~VectorFunction( )
2167 RefCountPtr
< const Lang::Class
> Lang::VectorFunction::TypeID( new Lang::SystemFinalClass( strrefdup( "VectorFunction" ), Kernel::VectorFunction_register_methods
) );
2168 TYPEINFOIMPL( VectorFunction
);
2170 Kernel::VariableHandle
2171 Lang::VectorFunction::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
2173 if( strcmp( fieldID
, "size" ) == 0 )
2175 return Helpers::newValHandle( new Lang::Integer( mem_
->size( ) ) );
2177 if( strcmp( fieldID
, "range" ) == 0 )
2179 return Helpers::newValHandle( new Lang::SingleListRange
< Lang::Integer
>( 0, 1, mem_
->size( ) ) );
2181 if( strcmp( fieldID
, "reverse_range" ) == 0 )
2183 return Helpers::newValHandle( new Lang::SingleListRange
< Lang::Integer
>( mem_
->size( ) - 1, -1, mem_
->size( ) ) );
2185 if( strcmp( fieldID
, "list" ) == 0 )
2191 return TypeID
->getMethod( selfRef
, fieldID
); /* This will throw if there is no such method. */
2194 const char * Lang::VectorFunction::title_
= "<vector>";
2197 Lang::VectorFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2199 const size_t ARITY
= 1;
2200 if( args
.size( ) != ARITY
)
2202 throw Exceptions::CoreArityMismatch( title_
, ARITY
, args
.size( ) );
2205 typedef const Lang::Integer ArgType
;
2206 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
);
2210 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "Index is negative." );
2213 if( arg
->val_
>= static_cast< int >( mem_
->size( ) ) )
2215 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "Index exceeds vector size." );
2218 Kernel::ContRef cont
= evalState
->cont_
;
2219 cont
->takeValue( (*mem_
)[ arg
->val_
],
2224 Lang::VectorFunction::isTransforming( ) const
2230 Lang::VectorFunction::gcMark( Kernel::GCMarkedSet
& marked
)
2232 gcMark( mem_
, marked
);
2236 Lang::VectorFunction::gcMark( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, Kernel::GCMarkedSet
& marked
)
2238 for( std::vector
< Kernel::ValueRef
>::const_iterator i
= mem
->begin( ); i
!= mem
->end( ); ++i
)
2240 const_cast< Lang::Value
* >( i
->getPtr( ) )->gcMark( marked
);
2245 Lang::VectorFunction::show( std::ostream
& os
) const
2247 os
<< "< vector function >" ;
2250 RefCountPtr
< const std::vector
< double > >
2251 Lang::VectorFunction::getNumeric( const Ast::SourceLocation
& callLoc
) const
2253 if( memNumeric_
== NullPtr
< const std::vector
< double > >( ) )
2255 RefCountPtr
< std::vector
< double > > res( new std::vector
< double > ); // Note that this is not const, so far...
2256 res
->reserve( mem_
->size( ) );
2257 typedef typeof *mem_ SrcType
;
2258 for( SrcType::const_iterator src
= mem_
->begin( ); src
!= mem_
->end( ); ++src
)
2260 res
->push_back( Helpers::down_cast
< const Lang::Float
>( *src
, callLoc
)->val_
);
2269 Lang::VectorFunction::compute_list( ) const
2271 if( list_
!= NullPtr
< Kernel::Variable
>( ) )
2275 RefCountPtr
< const Lang::SingleList
> newList
= Lang::THE_CONS_NULL
;
2276 typedef typeof *mem_ ListType
;
2277 for( ListType::const_reverse_iterator src
= mem_
->rbegin( ); src
!= mem_
->rend( ); ++src
)
2279 newList
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( *src
) ), newList
) );
2281 list_
= Kernel::VariableHandle( new Kernel::Variable( newList
) );
2289 class VectorFunctionFoldLCont
: public Kernel::Continuation
2291 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
2292 RefCountPtr
< const Lang::Function
> op_
;
2293 Shapes::Lang::VectorFunction::vector_type::const_iterator i_
;
2294 Kernel::PassedDyn dyn_
;
2295 Kernel::ContRef cont_
;
2297 VectorFunctionFoldLCont( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, const RefCountPtr
< const Lang::Function
> & op
, Shapes::Lang::VectorFunction::vector_type::const_iterator i
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
2298 : Kernel::Continuation( traceLoc
), mem_( mem
), op_( op
), i_( i
), dyn_( dyn
), cont_( cont
)
2300 virtual ~VectorFunctionFoldLCont( ) { }
2301 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
2303 evalState
->dyn_
= dyn_
;
2304 evalState
->cont_
= cont_
;
2305 Lang::VectorFunction::foldl( mem_
, evalState
, op_
, val
, i_
, traceLoc_
);
2307 virtual Kernel::ContRef
up( ) const
2311 virtual RefCountPtr
< const char > description( ) const
2313 return strrefdup( "VectorFunction's foldl" );
2315 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2317 Lang::VectorFunction::gcMark( mem_
, marked
);
2318 const_cast< Lang::Function
* >( op_
.getPtr( ) )->gcMark( marked
);
2319 dyn_
->gcMark( marked
);
2320 cont_
->gcMark( marked
);
2324 class VectorFunctionFoldRCont
: public Kernel::Continuation
2326 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
2327 RefCountPtr
< const Lang::Function
> op_
;
2328 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_
;
2329 Kernel::PassedDyn dyn_
;
2330 Kernel::ContRef cont_
;
2332 VectorFunctionFoldRCont( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, const RefCountPtr
< const Lang::Function
> & op
, Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
2333 : Kernel::Continuation( traceLoc
), mem_( mem
), op_( op
), i_( i
), dyn_( dyn
), cont_( cont
)
2335 virtual ~VectorFunctionFoldRCont( ) { }
2336 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
2338 evalState
->dyn_
= dyn_
;
2339 evalState
->cont_
= cont_
;
2340 Lang::VectorFunction::foldr( mem_
, evalState
, op_
, val
, i_
, traceLoc_
);
2342 virtual Kernel::ContRef
up( ) const
2346 virtual RefCountPtr
< const char > description( ) const
2348 return strrefdup( "VectorFunction's foldr" );
2350 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2352 Lang::VectorFunction::gcMark( mem_
, marked
);
2353 const_cast< Lang::Function
* >( op_
.getPtr( ) )->gcMark( marked
);
2354 dyn_
->gcMark( marked
);
2355 cont_
->gcMark( marked
);
2359 class VectorFunctionFoldSLCont
: public Kernel::Continuation
2361 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
2362 RefCountPtr
< const Lang::Function
> op_
;
2363 Shapes::Lang::VectorFunction::vector_type::const_iterator i_
;
2364 Kernel::StateHandle state_
;
2365 Kernel::PassedDyn dyn_
;
2366 Kernel::ContRef cont_
;
2368 VectorFunctionFoldSLCont( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, const RefCountPtr
< const Lang::Function
> & op
, Shapes::Lang::VectorFunction::vector_type::const_iterator i
, Kernel::StateHandle state
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
2369 : Kernel::Continuation( traceLoc
), mem_( mem
), op_( op
), i_( i
), state_( state
), dyn_( dyn
), cont_( cont
)
2371 virtual ~VectorFunctionFoldSLCont( ) { }
2372 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
2374 evalState
->dyn_
= dyn_
;
2375 evalState
->cont_
= cont_
;
2376 Lang::VectorFunction::foldsl( mem_
, evalState
, op_
, val
, state_
, i_
, traceLoc_
);
2378 virtual Kernel::ContRef
up( ) const
2382 virtual RefCountPtr
< const char > description( ) const
2384 return strrefdup( "VectorFunction's foldsl" );
2386 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2388 Lang::VectorFunction::gcMark( mem_
, marked
);
2389 const_cast< Lang::Function
* >( op_
.getPtr( ) )->gcMark( marked
);
2390 state_
->gcMark( marked
);
2391 dyn_
->gcMark( marked
);
2392 cont_
->gcMark( marked
);
2396 class VectorFunctionFoldSRCont
: public Kernel::Continuation
2398 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
2399 RefCountPtr
< const Lang::Function
> op_
;
2400 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_
;
2401 Kernel::StateHandle state_
;
2402 Kernel::PassedDyn dyn_
;
2403 Kernel::ContRef cont_
;
2405 VectorFunctionFoldSRCont( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, const RefCountPtr
< const Lang::Function
> & op
, Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i
, Kernel::StateHandle state
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
2406 : Kernel::Continuation( traceLoc
), mem_( mem
), op_( op
), i_( i
), state_( state
), dyn_( dyn
), cont_( cont
)
2408 virtual ~VectorFunctionFoldSRCont( ) { }
2409 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
2411 evalState
->dyn_
= dyn_
;
2412 evalState
->cont_
= cont_
;
2413 Lang::VectorFunction::foldsr( mem_
, evalState
, op_
, val
, state_
, i_
, traceLoc_
);
2415 virtual Kernel::ContRef
up( ) const
2419 virtual RefCountPtr
< const char > description( ) const
2421 return strrefdup( "VectorFunction's foldsr" );
2423 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2425 Lang::VectorFunction::gcMark( mem_
, marked
);
2426 const_cast< Lang::Function
* >( op_
.getPtr( ) )->gcMark( marked
);
2427 state_
->gcMark( marked
);
2428 dyn_
->gcMark( marked
);
2429 cont_
->gcMark( marked
);
2437 Lang::VectorFunction::foldl( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Function
> & op
, const Kernel::VariableHandle
& nullResult
, vector_type::const_iterator i
, const Ast::SourceLocation
& callLoc
)
2439 if( i
== mem
->end( ) )
2441 Kernel::ContRef cont
= evalState
->cont_
;
2442 cont
->takeHandle( nullResult
,
2447 Kernel::VariableHandle elem
= Kernel::VariableHandle( new Kernel::Variable( *i
) );
2449 evalState
->cont_
= Kernel::ContRef( new Kernel::VectorFunctionFoldLCont( mem
, op
, i
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
2451 op
->call( op
, evalState
, nullResult
, elem
, callLoc
);
2455 Lang::VectorFunction::foldr( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Function
> & op
, const Kernel::VariableHandle
& nullResult
, vector_type::const_reverse_iterator i
, const Ast::SourceLocation
& callLoc
)
2457 if( i
== mem
->rend( ) )
2459 Kernel::ContRef cont
= evalState
->cont_
;
2460 cont
->takeHandle( nullResult
,
2465 Kernel::VariableHandle elem
= Kernel::VariableHandle( new Kernel::Variable( *i
) );
2467 evalState
->cont_
= Kernel::ContRef( new Kernel::VectorFunctionFoldRCont( mem
, op
, i
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
2469 op
->call( op
, evalState
, nullResult
, elem
, callLoc
);
2473 Lang::VectorFunction::foldsl( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Function
> & op
, const Kernel::VariableHandle
& nullResult
, Kernel::StateHandle state
, vector_type::const_iterator i
, const Ast::SourceLocation
& callLoc
)
2475 if( i
== mem
->end( ) )
2477 Kernel::ContRef cont
= evalState
->cont_
;
2478 cont
->takeHandle( nullResult
,
2483 Kernel::VariableHandle elem
= Kernel::VariableHandle( new Kernel::Variable( *i
) );
2485 evalState
->cont_
= Kernel::ContRef( new Kernel::VectorFunctionFoldSLCont( mem
, op
, i
, state
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
2487 op
->call( op
, evalState
, nullResult
, elem
, state
, callLoc
);
2491 Lang::VectorFunction::foldsr( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Function
> & op
, const Kernel::VariableHandle
& nullResult
, Kernel::StateHandle state
, vector_type::const_reverse_iterator i
, const Ast::SourceLocation
& callLoc
)
2493 if( i
== mem
->rend( ) )
2495 Kernel::ContRef cont
= evalState
->cont_
;
2496 cont
->takeHandle( nullResult
,
2501 Kernel::VariableHandle elem
= Kernel::VariableHandle( new Kernel::Variable( *i
) );
2503 evalState
->cont_
= Kernel::ContRef( new Kernel::VectorFunctionFoldSRCont( mem
, op
, i
, state
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
2505 op
->call( op
, evalState
, nullResult
, elem
, state
, callLoc
);
2509 const char * Lang::ColorInterpolator::title_
= "<color-interpolator>";
2511 Lang::ColorInterpolator::ColorInterpolator( const RefCountPtr
< KeyContainer
> & key
,
2512 const RefCountPtr
< RGBContainer
> & RGBcolor
,
2513 const RefCountPtr
< GrayContainer
> & graycolor
,
2514 const RefCountPtr
< CMYKContainer
> & CMYKcolor
,
2515 ColorType colorType
)
2516 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( Lang::ColorInterpolator::title_
), true ) ),
2517 key_( key
), RGBcolor_ ( RGBcolor
), graycolor_ ( graycolor
), CMYKcolor_ ( CMYKcolor
), colorType_(colorType
)
2519 formals_
->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE
);
2522 Lang::ColorInterpolator::~ColorInterpolator( )
2525 Kernel::VariableHandle
2526 Lang::ColorInterpolator::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
2528 if( strcmp( fieldID
, "low" ) == 0 )
2530 return Helpers::newValHandle( new Lang::Float( key_
->front( ) ) );
2532 if( strcmp( fieldID
, "high" ) == 0 )
2534 return Helpers::newValHandle( new Lang::Float( key_
->back( ) ) );
2536 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
2540 template <class COLOR_TYPE
, class COLOR_CONTAINER
>
2542 Lang::ColorInterpolator::callHelper( Kernel::EvalState
* evalState
,
2543 const RefCountPtr
< COLOR_CONTAINER
> & colorContainer
,
2544 double key
, KeyContainer::const_iterator keyHi
) const
2546 if( keyHi
== key_
->end( ) )
2548 Kernel::ContRef cont
= evalState
->cont_
;
2549 cont
->takeValue( RefCountPtr
< const::Lang::Value
>( new COLOR_TYPE( colorContainer
->back( ) ) ),
2554 if( keyHi
== key_
->begin( ) )
2556 Kernel::ContRef cont
= evalState
->cont_
;
2557 cont
->takeValue( RefCountPtr
< const::Lang::Value
>( new COLOR_TYPE( colorContainer
->front( ) ) ),
2562 KeyContainer::const_iterator keyLo
= keyHi
- 1;
2563 double rem
= ( key
- *keyLo
) / ( *keyHi
- *keyLo
);
2565 Kernel::ContRef cont
= evalState
->cont_
;
2567 typename
COLOR_CONTAINER::const_iterator colorHi
= colorContainer
->begin( ) + ( keyHi
- key_
->begin( ) );
2568 typename
COLOR_CONTAINER::const_iterator colorLo
= colorHi
- 1;
2570 cont
->takeValue( RefCountPtr
< const::Lang::Value
>( new COLOR_TYPE( colorLo
->mulNoCheck( 1 - rem
).addNoCheck( colorHi
->mulNoCheck( rem
) ) ) ),
2576 Lang::ColorInterpolator::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2578 const size_t ARITY
= 1;
2579 if( args
.size( ) != ARITY
)
2581 throw Exceptions::CoreArityMismatch( title_
, ARITY
, args
.size( ) );
2584 typedef const Lang::Float ArgType
;
2585 double key
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
)->val_
;
2587 KeyContainer::const_iterator keyHi
= lower_bound( key_
->begin( ), key_
->end( ), key
);
2588 switch( colorType_
)
2591 callHelper
< Lang::RGB
>( evalState
, RGBcolor_
, key
, keyHi
);
2594 callHelper
< Lang::Gray
>( evalState
, graycolor_
, key
, keyHi
);
2597 callHelper
< Lang::CMYK
>( evalState
, CMYKcolor_
, key
, keyHi
);
2600 throw Exceptions::InternalError( "ColorInterpolator::call: Did not expect UNDEFINED in ennum switch." );
2605 Lang::ColorInterpolator::isTransforming( ) const
2611 Lang::ColorInterpolator::gcMark( Kernel::GCMarkedSet
& marked
)
2615 Lang::ColorInterpolator::show( std::ostream
& os
) const
2617 os
<< "< color interpolator in " ;
2618 switch( colorType_
)
2630 throw Exceptions::InternalError( "ColorInterpolator::show: Did not expect UNDEFINED in ennum switch." );
2635 Lang::BinaryOperatorFunction::BinaryOperatorFunction( Ast::BinaryInfixExpr
* opExpr
, const char * title
)
2636 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) ), opExpr_( opExpr
), title_( title
)
2638 formals_
->appendEvaluatedCoreFormal( "first", Kernel::THE_SLOT_VARIABLE
);
2639 formals_
->appendEvaluatedCoreFormal( "second", Kernel::THE_SLOT_VARIABLE
);
2642 Lang::BinaryOperatorFunction::~BinaryOperatorFunction( )
2648 Lang::BinaryOperatorFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2650 const size_t ARITY
= 2;
2651 CHECK_ARITY( args
, ARITY
, title_
);
2652 RefCountPtr
< const Lang::Value
> arg1
= args
.getValue( 0 );
2653 RefCountPtr
< const Lang::Value
> arg2
= args
.getValue( 1 );
2657 Kernel::ContRef cont
= evalState
->cont_
;
2658 cont
->takeValue( arg1
->binaryDispatch1( arg1
, arg2
, evalState
->dyn_
, opExpr_
),
2661 catch( Exceptions::BinaryInfixNotApplicable
& ball
)
2663 ball
.setOperatorSymbol( title_
);
2669 Lang::BinaryOperatorFunction::isTransforming( ) const
2675 Lang::BinaryOperatorFunction::show( std::ostream
& os
) const
2677 os
<< "< binary operator function for " << title_
<< " >" ;
2681 Lang::UnaryOperatorFunction::UnaryOperatorFunction( Ast::UnaryExpr
* opExpr
, const char * title
)
2682 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) ), opExpr_( opExpr
), title_( title
)
2684 formals_
->appendEvaluatedCoreFormal( "only", Kernel::THE_SLOT_VARIABLE
);
2687 Lang::UnaryOperatorFunction::~UnaryOperatorFunction( )
2693 Lang::UnaryOperatorFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2695 const size_t ARITY
= 1;
2696 CHECK_ARITY( args
, ARITY
, title_
);
2698 RefCountPtr
< const Lang::Value
> arg
= args
.getValue( 0 );
2702 Kernel::ContRef cont
= evalState
->cont_
;
2703 cont
->takeValue( arg
->unaryDispatch( arg
, evalState
->dyn_
, opExpr_
),
2706 catch( Exceptions::UnaryPrefixNotApplicable
& ball
)
2708 ball
.setOperatorSymbol( title_
);
2711 catch( Exceptions::UnaryPostfixNotApplicable
& ball
)
2713 ball
.setOperatorSymbol( title_
);
2719 Lang::UnaryOperatorFunction::isTransforming( ) const
2725 Lang::UnaryOperatorFunction::show( std::ostream
& os
) const
2727 os
<< "< unary operator function for " << title_
<< " >" ;
2731 Lang::Transform2DMethod_chop::Transform2DMethod_chop( RefCountPtr
< const Lang::Transform2D
> self
, const Ast::FileID
* fullMethodID
)
2732 : Lang::MethodBase
< class_type
>( self
, fullMethodID
, false, true )
2734 formals_
->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE
);
2735 formals_
->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE
);
2738 Lang::Transform2DMethod_chop::~Transform2DMethod_chop( )
2742 Lang::Transform2DMethod_chop::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2744 args
.applyDefaults( );
2747 double Ltol
= Helpers::down_cast_CoreArgument
< const Lang::Float
>( title_
, args
, argsi
, callLoc
)->val_
;
2750 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Tolerances must not be negative." );
2754 Concrete::Length ptol
= Helpers::down_cast_CoreArgument
< const Lang::Length
>( title_
, args
, argsi
, callLoc
)->get( );
2755 if( ptol
< Concrete::ZERO_LENGTH
)
2757 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Tolerances must not be negative." );
2760 Lang::Transform2D
* res
= self_
->clone( );
2762 CHOP_Ltol( res
->xx_
);
2763 CHOP_Ltol( res
->yx_
);
2765 CHOP_Ltol( res
->xy_
);
2766 CHOP_Ltol( res
->yy_
);
2768 CHOP_ptol( res
->xt_
);
2769 CHOP_ptol( res
->yt_
);
2771 Kernel::ContRef cont
= evalState
->cont_
;
2772 cont
->takeValue( RefCountPtr
< const Lang::Value
>( res
),
2777 Lang::Transform3DMethod_chop::Transform3DMethod_chop( RefCountPtr
< const Lang::Transform3D
> self
, const Ast::FileID
* fullMethodID
)
2778 : Lang::MethodBase
< class_type
>( self
, fullMethodID
, false, true )
2780 formals_
->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE
);
2781 formals_
->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE
);
2784 Lang::Transform3DMethod_chop::~Transform3DMethod_chop( )
2788 Lang::Transform3DMethod_chop::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2790 args
.applyDefaults( );
2793 double Ltol
= Helpers::down_cast_CoreArgument
< const Lang::Float
>( title_
, args
, argsi
, callLoc
)->val_
;
2796 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Tolerances must not be negative." );
2800 Concrete::Length ptol
= Helpers::down_cast_CoreArgument
< const Lang::Length
>( title_
, args
, argsi
, callLoc
)->get( );
2801 if( ptol
< Concrete::ZERO_LENGTH
)
2803 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Tolerances must not be negative." );
2806 Lang::Transform3D
* res
= self_
->clone( );
2808 CHOP_Ltol( res
->xx_
);
2809 CHOP_Ltol( res
->yx_
);
2810 CHOP_Ltol( res
->zx_
);
2812 CHOP_Ltol( res
->xy_
);
2813 CHOP_Ltol( res
->yy_
);
2814 CHOP_Ltol( res
->zy_
);
2816 CHOP_Ltol( res
->xz_
);
2817 CHOP_Ltol( res
->yz_
);
2818 CHOP_Ltol( res
->zz_
);
2820 CHOP_ptol( res
->xt_
);
2821 CHOP_ptol( res
->yt_
);
2822 CHOP_ptol( res
->zt_
);
2824 Kernel::ContRef cont
= evalState
->cont_
;
2825 cont
->takeValue( RefCountPtr
< const Lang::Value
>( res
),