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 for( MyListType::iterator dst
= variables_
->begin( ); dst
!= variables_
->end( ); ++dst
, ++src
, ++srcLoc
, ++pos
)
1096 if( *dst
== Kernel::THE_SLOT_VARIABLE
)
1098 /* Handle error situation.
1100 if( *src
== Kernel::THE_SLOT_VARIABLE
)
1102 if( missingArgs
== 0 )
1104 missingArgs
= new typeof *missingArgs
;
1106 typedef typeof *(formals_
->formals_
->argumentOrder_
) FormalsMapType
;
1107 FormalsMapType
& formalsMap
= *(formals_
->formals_
->argumentOrder_
);
1108 for( FormalsMapType::const_iterator i
= formalsMap
.begin( ); ; )
1110 if( i
->second
== pos
)
1112 missingArgs
->insert( missingArgs
->begin( ), std::pair
< size_t, RefCountPtr
< const char > >( pos
, strrefdup( i
->first
) ) );
1116 if( i
== formalsMap
.end( ) )
1118 throw Exceptions::InternalError( "Failed to find position of missing argument." );
1126 locations_
[ pos
] = *srcLoc
;
1130 if( missingArgs
!= 0 || missingStates
!= 0 )
1132 throw Exceptions::MissingArguments( formals_
->formals_
->loc( ), missingArgs
, missingStates
);
1137 variables_
->push_back
1138 ( Helpers::newValHandle
1139 ( new Lang::Structure( sinkArgList_
,
1141 true ) ) ); // true means that the sinkArgList_ gets owned by the Structure.
1147 Kernel::VariableHandle
&
1148 Kernel::Arguments::getHandle( size_t i
)
1150 return (*variables_
)[ i
];
1153 RefCountPtr
< const Lang::Value
> &
1154 Kernel::Arguments::getValue( size_t i
)
1156 return (*variables_
)[ i
]->getUntyped( );
1159 const Ast::SourceLocation
&
1160 Kernel::Arguments::getLoc( size_t i
) const
1162 return locations_
[ i
]->loc( );
1166 Kernel::Arguments::getNode( size_t i
) const
1168 return locations_
[ i
];
1172 Kernel::Arguments::getThunk( size_t i
)
1174 return (*variables_
)[ i
]->copyThunk( );
1178 Kernel::Arguments::isSlot( size_t i
) const
1180 return (*variables_
)[ i
] == Kernel::THE_SLOT_VARIABLE
;
1184 Kernel::Arguments::getState( size_t i
)
1186 return (*states_
)[ i
];
1189 const Ast::SourceLocation
&
1190 Kernel::Arguments::getStateLoc( size_t i
) const
1192 return stateLocations_
[ i
]->loc( );
1196 Kernel::Arguments::size( ) const
1198 return variables_
->size( );
1202 Kernel::Arguments::empty( ) const
1204 return variables_
->empty( );
1208 Kernel::Arguments::setMutatorSelf( Kernel::StateHandle mutatorSelf
)
1210 mutatorSelf_
= mutatorSelf
;
1214 Kernel::Arguments::getMutatorSelf( )
1216 if( mutatorSelf_
== 0 )
1218 throw Exceptions::InternalError( "Kernel::Arguments::getMutatorSelf: self is null." );
1220 return mutatorSelf_
;
1224 Kernel::Arguments::gcMark( Kernel::GCMarkedSet
& marked
)
1227 typedef typeof *variables_ ListType
;
1228 for( ListType::const_iterator i
= variables_
->begin( ); i
!= variables_
->end( ); ++i
)
1230 const_cast< Kernel::Variable
* >( i
->getPtr( ) )->gcMark( marked
);
1235 Kernel::Environment::ValueVector
1236 Kernel::Arguments::getVariables( )
1241 Kernel::Environment::StateVector
1242 Kernel::Arguments::getStates( )
1253 class FunctionOneHandleCont
: public Kernel::Continuation
1255 RefCountPtr
< const Lang::Function
> fun_
;
1256 Kernel::PassedDyn dyn_
;
1257 Kernel::ContRef cont_
;
1259 FunctionOneHandleCont( const RefCountPtr
< const Lang::Function
> & fun
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1260 : Kernel::Continuation( traceLoc
), fun_( fun
), dyn_( dyn
), cont_( cont
)
1262 virtual ~FunctionOneHandleCont( ) { }
1263 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
1265 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1266 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1269 if( val
->isThunk( ) )
1271 val
->force( val
, evalState
);
1275 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1276 args
.addOrderedArgument( val
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1278 evalState
->dyn_
= dyn_
;
1279 evalState
->cont_
= cont_
;
1280 fun_
->call( evalState
, args
, traceLoc_
);
1282 virtual Kernel::ContRef
up( ) const
1286 virtual RefCountPtr
< const char > description( ) const
1288 return strrefdup( "internal function call with one handle" );
1290 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1292 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1293 dyn_
->gcMark( marked
);
1294 cont_
->gcMark( marked
);
1298 class FunctionTwoHandlesCont_2
: public Kernel::Continuation
1300 RefCountPtr
< const Lang::Function
> fun_
;
1301 Kernel::VariableHandle arg1_
;
1302 Kernel::PassedDyn dyn_
;
1303 Kernel::ContRef cont_
;
1305 FunctionTwoHandlesCont_2( const RefCountPtr
< const Lang::Function
> & fun
, const Kernel::VariableHandle
& arg1
, const Kernel::PassedDyn
& dyn
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1306 : Kernel::Continuation( traceLoc
), fun_( fun
), arg1_( arg1
), dyn_( dyn
), cont_( cont
)
1308 virtual ~FunctionTwoHandlesCont_2( ) { }
1309 virtual void takeHandle( Kernel::VariableHandle arg2
, Kernel::EvalState
* evalState
, bool dummy
) const
1311 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1312 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1315 if( arg2
->isThunk( ) )
1317 arg2
->force( arg2
, evalState
);
1321 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1322 args
.addOrderedArgument( arg1_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1323 args
.addOrderedArgument( arg2
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1324 evalState
->dyn_
= dyn_
;
1325 evalState
->cont_
= cont_
;
1326 fun_
->call( evalState
, args
, traceLoc_
);
1328 virtual Kernel::ContRef
up( ) const
1332 virtual RefCountPtr
< const char > description( ) const
1334 return strrefdup( "internal function call with two handles, second" );
1336 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1338 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1339 dyn_
->gcMark( marked
);
1340 cont_
->gcMark( marked
);
1344 class FunctionTwoHandlesCont_1
: public Kernel::Continuation
1346 RefCountPtr
< const Lang::Function
> fun_
;
1347 Kernel::VariableHandle arg2_
;
1349 Kernel::PassedDyn dyn_
;
1350 Kernel::ContRef cont_
;
1352 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
)
1353 : Kernel::Continuation( traceLoc
), fun_( fun
), arg2_( arg2
), forceArg2_( forceArg2
), dyn_( dyn
), cont_( cont
)
1355 virtual ~FunctionTwoHandlesCont_1( ) { }
1356 virtual void takeHandle( Kernel::VariableHandle arg1
, Kernel::EvalState
* evalState
, bool dummy
) const
1358 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1359 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1362 if( arg1
->isThunk( ) )
1364 arg1
->force( arg1
, evalState
);
1370 Kernel::ContRef newCont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( fun_
, arg1
, dyn_
, cont_
, traceLoc_
) );
1371 evalState
->cont_
= newCont
;
1372 newCont
->takeHandle( arg2_
, evalState
);
1376 /* The second handle need not be forced
1378 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1379 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1380 args
.addOrderedArgument( arg2_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1381 evalState
->dyn_
= dyn_
;
1382 evalState
->cont_
= cont_
;
1383 fun_
->call( evalState
, args
, traceLoc_
);
1385 virtual Kernel::ContRef
up( ) const
1389 virtual RefCountPtr
< const char > description( ) const
1391 return strrefdup( "internal function call with two handles, first" );
1393 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1395 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1396 dyn_
->gcMark( marked
);
1397 cont_
->gcMark( marked
);
1401 class FunctionTwoHandlesOneStateCont_2
: public Kernel::Continuation
1403 RefCountPtr
< const Lang::Function
> fun_
;
1404 Kernel::VariableHandle arg1_
;
1405 Kernel::StateHandle state_
;
1406 Kernel::PassedDyn dyn_
;
1407 Kernel::ContRef cont_
;
1409 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
)
1410 : Kernel::Continuation( traceLoc
), fun_( fun
), arg1_( arg1
), state_( state
), dyn_( dyn
), cont_( cont
)
1412 virtual ~FunctionTwoHandlesOneStateCont_2( ) { }
1413 virtual void takeHandle( Kernel::VariableHandle arg2
, Kernel::EvalState
* evalState
, bool dummy
) const
1415 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1416 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1419 if( arg2
->isThunk( ) )
1421 arg2
->force( arg2
, evalState
);
1425 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1426 args
.addOrderedArgument( arg1_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1427 args
.addOrderedArgument( arg2
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1428 args
.addOrderedState( state_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1429 evalState
->dyn_
= dyn_
;
1430 evalState
->cont_
= cont_
;
1431 fun_
->call( evalState
, args
, traceLoc_
);
1433 virtual Kernel::ContRef
up( ) const
1437 virtual RefCountPtr
< const char > description( ) const
1439 return strrefdup( "internal function call with two handles and one state, second" );
1441 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1443 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1444 state_
->gcMark( marked
);
1445 dyn_
->gcMark( marked
);
1446 cont_
->gcMark( marked
);
1450 class FunctionTwoHandlesOneStateCont_1
: public Kernel::Continuation
1452 RefCountPtr
< const Lang::Function
> fun_
;
1453 Kernel::VariableHandle arg2_
;
1455 Kernel::StateHandle state_
;
1456 Kernel::PassedDyn dyn_
;
1457 Kernel::ContRef cont_
;
1459 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
)
1460 : Kernel::Continuation( traceLoc
), fun_( fun
), arg2_( arg2
), forceArg2_( forceArg2
), state_( state
), dyn_( dyn
), cont_( cont
)
1462 virtual ~FunctionTwoHandlesOneStateCont_1( ) { }
1463 virtual void takeHandle( Kernel::VariableHandle arg1
, Kernel::EvalState
* evalState
, bool dummy
) const
1465 /* This continuation really seeks forced arguments, for otherwise a thunk would have been generated directly.
1466 * However, this continuation takes handles anyway, since handles is what goes into the argument list.
1469 if( arg1
->isThunk( ) )
1471 arg1
->force( arg1
, evalState
);
1477 Kernel::ContRef newCont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( fun_
, arg1
, state_
, dyn_
, cont_
, traceLoc_
) );
1478 evalState
->cont_
= newCont
;
1479 newCont
->takeHandle( arg2_
, evalState
);
1483 /* The second handle need not be forced
1485 Kernel::Arguments args
= fun_
->newCurriedArguments( );
1486 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1487 args
.addOrderedArgument( arg2_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1488 args
.addOrderedState( state_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1489 evalState
->dyn_
= dyn_
;
1490 evalState
->cont_
= cont_
;
1491 fun_
->call( evalState
, args
, traceLoc_
);
1493 virtual Kernel::ContRef
up( ) const
1497 virtual RefCountPtr
< const char > description( ) const
1499 return strrefdup( "internal function call with two handles and one state, first" );
1501 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1503 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
1504 dyn_
->gcMark( marked
);
1505 cont_
->gcMark( marked
);
1506 state_
->gcMark( marked
);
1514 Lang::Function::Function( Kernel::EvaluatedFormals
* formals
)
1515 : formals_( formals
)
1518 DISPATCHIMPL( Function
);
1520 Lang::Function::~Function( )
1524 delete formals_
->formals_
;
1530 Lang::Function::transformed( const Lang::Transform2D
& tf
, Kernel::ValueRef self
) const
1532 return Kernel::ValueRef( new Lang::TransformedFunction2D( tf
, self
.down_cast
< const Lang::Function
>( ) ) );
1536 Lang::Function::call( Kernel::EvalState
* evalState
, const Kernel::ValueRef
& arg1
, const Ast::SourceLocation
& callLoc
) const
1538 Kernel::Arguments args
= this->newCurriedArguments( );
1540 args
.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1
) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1542 this->call( evalState
, args
, callLoc
);
1546 Lang::Function::analyze( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
)
1548 Ast::StateIDSet
* freeStates
= new Ast::StateIDSet
;
1549 this->analyze_impl( parent
, env
, freeStates
);
1550 if( ! freeStates
->empty( ) )
1552 Ast::theAnalysisErrorsList
.push_back( new Exceptions::IllegalFreeStates( parent
->loc( ), freeStates
, "this is a function" ) );
1561 Lang::Function::analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
)
1563 throw Exceptions::InternalError( "A syntax function is not overriding the analyze method." );
1567 Lang::Function::call( Kernel::EvalState
* evalState
, const Kernel::ValueRef
& arg1
, const Kernel::ValueRef
& arg2
, const Ast::SourceLocation
& callLoc
) const
1569 Kernel::Arguments args
= this->newCurriedArguments( );
1571 args
.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg1
) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1572 args
.addOrderedArgument( Kernel::VariableHandle( new Kernel::Variable( arg2
) ), & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1574 this->call( evalState
, args
, callLoc
);
1577 Ast::ArgListExprs
* Lang::Function::oneExprArgList
= new Ast::ArgListExprs( static_cast< size_t >( 1 ) );
1578 Ast::ArgListExprs
* Lang::Function::twoExprsArgList
= new Ast::ArgListExprs( static_cast< size_t >( 2 ) );
1581 Lang::Function::call( const RefCountPtr
< const Lang::Function
> & selfRef
, Kernel::EvalState
* evalState
, const Kernel::VariableHandle
& arg1
, const Ast::SourceLocation
& callLoc
) const
1583 const RefCountPtr
< const Kernel::CallContInfo
> info
= this->newCallContInfo( Lang::Function::oneExprArgList
, *evalState
);
1585 if( info
->force( 0 ) )
1587 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionOneHandleCont( selfRef
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1588 evalState
->cont_
= cont
;
1589 cont
->takeHandle( arg1
, evalState
);
1593 /* The handle need not be forced
1595 Kernel::Arguments args
= this->newCurriedArguments( );
1596 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1597 this->call( evalState
, args
, callLoc
);
1601 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
1603 const RefCountPtr
< const Kernel::CallContInfo
> info
= this->newCallContInfo( Lang::Function::twoExprsArgList
, *evalState
);
1605 /* Remember that arguments are ordered backwards!
1608 if( info
->force( 1 ) )
1610 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_1( selfRef
, arg2
, info
->force( 0 ), evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1611 evalState
->cont_
= cont
;
1612 cont
->takeHandle( arg1
, evalState
);
1616 if( info
->force( 0 ) )
1618 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesCont_2( selfRef
, arg1
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1619 evalState
->cont_
= cont
;
1620 cont
->takeHandle( arg2
, evalState
);
1624 /* None of the handles need to be forced
1626 Kernel::Arguments args
= this->newCurriedArguments( );
1627 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1628 args
.addOrderedArgument( arg2
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1629 this->call( evalState
, args
, callLoc
);
1633 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
1635 /* I'm not quite sure if we should also put a dummy state argument in info...
1637 const RefCountPtr
< const Kernel::CallContInfo
> info
= this->newCallContInfo( Lang::Function::twoExprsArgList
, *evalState
);
1639 /* Remember that arguments are ordered backwards!
1642 if( info
->force( 1 ) )
1644 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_1( selfRef
, arg2
, info
->force( 0 ), state
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1645 evalState
->cont_
= cont
;
1646 cont
->takeHandle( arg1
, evalState
);
1650 if( info
->force( 0 ) )
1652 Kernel::ContRef cont
= Kernel::ContRef( new Kernel::FunctionTwoHandlesOneStateCont_2( selfRef
, arg1
, state
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1653 evalState
->cont_
= cont
;
1654 cont
->takeHandle( arg2
, evalState
);
1658 /* None of the handles need to be forced
1660 Kernel::Arguments args
= this->newCurriedArguments( );
1661 args
.addOrderedArgument( arg1
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1662 args
.addOrderedArgument( arg2
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1663 args
.addOrderedState( state
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1664 this->call( evalState
, args
, callLoc
);
1668 RefCountPtr
< Kernel::CallContInfo
>
1669 Lang::Function::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const
1671 return formals_
->newCallContInfo( argList
, evalState
);
1674 RefCountPtr
< Kernel::CallContInfo
>
1675 Lang::Function::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const
1677 return formals_
->newCallContInfo( argList
, evalState
, curryArgs
);
1681 Lang::Function::newCurriedArguments( ) const
1683 return Kernel::Arguments( formals_
);
1687 RefCountPtr
< const Lang::Class
> Lang::Function::TypeID( new Lang::SystemFinalClass( strrefdup( "Function" ) ) );
1688 TYPEINFOIMPL( Function
);
1690 Kernel::EvaluatedFormals::EvaluatedFormals( Kernel::Formals
* formals
)
1691 : selectiveForcing_( false ), forceAll_( false ), formals_( formals
), isSink_( true )
1694 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID
* locationFileID
)
1695 : selectiveForcing_( true ), formals_( 0 ), isSink_( true )
1697 Kernel::Formals
* formals( new Kernel::Formals( ) );
1698 formals
->setLoc( Ast::SourceLocation( locationFileID
) );
1702 Kernel::EvaluatedFormals::EvaluatedFormals( const Ast::FileID
* locationFileID
, bool forceAll
)
1703 : selectiveForcing_( false ), forceAll_( forceAll
), formals_( 0 ), isSink_( true )
1705 Kernel::Formals
* formals( new Kernel::Formals( ) );
1706 formals
->setLoc( Ast::SourceLocation( locationFileID
) );
1710 Kernel::EvaluatedFormals::~EvaluatedFormals( )
1712 /* Don't delete the orderedFormals, since we don't own it. A case for reference counting? */
1715 RefCountPtr
< Kernel::CallContInfo
>
1716 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const
1718 if( selectiveForcing_
)
1720 return RefCountPtr
< Kernel::CallContInfo
>( new Kernel::CallContInfo( argList
, evalState
, formals_
->newArgListForcePos( argList
) ) );
1724 return RefCountPtr
< Kernel::CallContInfo
>( new Kernel::CallContInfo( argList
, evalState
, forceAll_
) );
1728 RefCountPtr
< Kernel::CallContInfo
>
1729 Kernel::EvaluatedFormals::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const
1731 if( selectiveForcing_
)
1733 return RefCountPtr
< Kernel::CallContInfo
>( new Kernel::CallContInfo( argList
, evalState
, formals_
->newArgListForcePos( argList
, curryArgs
) ) );
1737 return RefCountPtr
< Kernel::CallContInfo
>( new Kernel::CallContInfo( argList
, evalState
, forceAll_
) );
1742 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, const Ast::Node
* loc
, bool force
)
1744 if( ! selectiveForcing_
)
1746 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function does not have selective forcing." );
1748 (*(formals_
->argumentOrder_
))[ id
] = defaults_
.size( );
1749 formals_
->forcePos_
.push_back( force
);
1750 defaults_
.push_back( defaultVal
);
1751 locations_
.push_back( loc
);
1755 Kernel::EvaluatedFormals::appendEvaluatedFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, const Ast::Node
* loc
)
1757 if( selectiveForcing_
)
1759 throw Exceptions::InternalError( "EvaluatedFormals::appendEvaluatedFormal: Function requires individual forcing specification." );
1761 (*(formals_
->argumentOrder_
))[ id
] = defaults_
.size( );
1762 formals_
->forcePos_
.push_back( forceAll_
);
1763 defaults_
.push_back( defaultVal
);
1764 locations_
.push_back( loc
);
1768 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, bool force
)
1770 appendEvaluatedFormal( id
, defaultVal
, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION
, force
);
1774 Kernel::EvaluatedFormals::appendEvaluatedCoreFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
)
1776 appendEvaluatedFormal( id
, defaultVal
, & Ast::THE_CORE_DEFAULT_VALUE_EXPRESSION
);
1780 Kernel::EvaluatedFormals::appendCoreStateFormal( const char * id
)
1782 (*(formals_
->stateOrder_
))[ id
] = formals_
->stateOrder_
->size( );
1786 Kernel::EvaluatedFormals::gcMark( Kernel::GCMarkedSet
& marked
)
1788 typedef typeof defaults_ ListType
;
1789 for( ListType::const_iterator i
= defaults_
.begin( ); i
!= defaults_
.end( ); ++i
)
1791 if( *i
!= NullPtr
< Kernel::Variable
>( ) )
1793 const_cast< Kernel::Variable
* >( i
->getPtr( ) )->gcMark( marked
);
1799 Lang::CuteFunction::CuteFunction( RefCountPtr
< const Lang::Function
> callee
, const Kernel::Arguments
& someArgs
)
1800 : Lang::Function( 0 ), callee_( callee
), someArgs_( someArgs
.clone( ) )
1803 Lang::CuteFunction::~CuteFunction( )
1806 RefCountPtr
< Kernel::CallContInfo
>
1807 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const
1809 return callee_
->newCallContInfo( argList
, evalState
, someArgs_
);
1812 RefCountPtr
< Kernel::CallContInfo
>
1813 Lang::CuteFunction::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const
1815 /* when we are the callee of a CuteFunction, our someArgs are part of that CuteFunction's someArgs, and hence curryArgs
1816 * contains everything that is to be passed to our callee.
1818 return callee_
->newCallContInfo( argList
, evalState
, curryArgs
);
1822 Lang::CuteFunction::newCurriedArguments( ) const
1824 return someArgs_
.clone( );
1828 Lang::CuteFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1830 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1831 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.
1833 callee_
->call( evalState
, args
, callLoc
);
1837 Lang::CuteFunction::isTransforming( ) const
1839 return callee_
->isTransforming( );
1843 Lang::CuteFunction::gcMark( Kernel::GCMarkedSet
& marked
)
1845 const_cast< Lang::Function
* >( callee_
.getPtr( ) )->gcMark( marked
);
1846 someArgs_
.gcMark( marked
);
1850 Lang::CuteFunction::show( std::ostream
& os
) const
1852 os
<< "< evaluated cut of: " ;
1853 callee_
->show( os
);
1858 Lang::ComposedFunction::ComposedFunction( const RefCountPtr
< const Lang::Function
> & second
, const RefCountPtr
< const Lang::Function
> & first
)
1859 : Lang::Function( 0 ), second_( second
), first_( first
)
1862 Lang::ComposedFunction::~ComposedFunction( )
1866 Lang::ComposedFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1868 /* Note that curruying "takes place" in newCurriedArguments. Other than that, this is the same as the original function.
1869 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.
1871 evalState
->cont_
= Kernel::ContRef( new Kernel::ComposedFunctionCall_cont( second_
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
1872 first_
->call( evalState
, args
, callLoc
);
1875 RefCountPtr
< Kernel::CallContInfo
>
1876 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const
1878 return first_
->newCallContInfo( argList
, evalState
);
1881 RefCountPtr
< Kernel::CallContInfo
>
1882 Lang::ComposedFunction::newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const
1884 return first_
->newCallContInfo( argList
, evalState
, curryArgs
);
1888 Lang::ComposedFunction::newCurriedArguments( ) const
1890 return first_
->newCurriedArguments( );
1894 Lang::ComposedFunction::isTransforming( ) const
1896 return second_
->isTransforming( );
1900 Lang::ComposedFunction::gcMark( Kernel::GCMarkedSet
& marked
)
1902 const_cast< Lang::Function
* >( second_
.getPtr( ) )->gcMark( marked
);
1903 const_cast< Lang::Function
* >( first_
.getPtr( ) )->gcMark( marked
);
1907 Lang::ComposedFunction::show( std::ostream
& os
) const
1909 os
<< "< composition: " ;
1910 second_
->show( os
);
1923 std::vector
< Kernel::VariableHandle
> thunks_
;
1925 SpanThunks( const Kernel::VariableHandle
& begin
, const Kernel::VariableHandle
& end
, const Kernel::VariableHandle
& step
, const Kernel::VariableHandle
& count
)
1927 thunks_
.reserve( 4 );
1928 thunks_
.push_back( count
);
1929 thunks_
.push_back( step
);
1930 thunks_
.push_back( end
);
1931 thunks_
.push_back( begin
);
1933 const Kernel::VariableHandle
& operator [] ( size_t i
) const
1935 return thunks_
[ i
];
1939 void gcMark( Kernel::GCMarkedSet
& marked
)
1941 typedef typeof thunks_ VecType
;
1942 for( VecType::iterator i
= thunks_
.begin( ); i
!= thunks_
.end( ); ++i
)
1944 (*i
)->gcMark( marked
);
1949 class SpanForcingContinuation
: public Continuation
1951 RefCountPtr
< const Kernel::SpanThunks
> thunks_
;
1953 RefCountPtr
< const Lang::SingleList
> values_
;
1954 RefCountPtr
< const Lang::Value
> last_
;
1955 Kernel::ContRef cont_
;
1957 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
)
1958 : Kernel::Continuation( traceLoc
), thunks_( thunks
), i_( i
), values_( values
), last_( last
), cont_( cont
)
1960 ~SpanForcingContinuation( )
1962 static void finish( RefCountPtr
< const Lang::SingleList
> values
, RefCountPtr
< const Lang::Value
> last
, Kernel::EvalState
* evalState
, const Ast::SourceLocation
& traceLoc
)
1964 Kernel::Arguments args
= Lang::THE_FUNCTION_RANGE
->newCurriedArguments( );
1965 RefCountPtr
< const Lang::SingleListPair
> src
= values
.down_cast
< const Lang::SingleListPair
>( );
1966 args
.addOrderedArgument( src
->car_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1967 src
= src
->cdr_
.down_cast
< const Lang::SingleListPair
>( );
1968 args
.addOrderedArgument( src
->car_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1969 src
= src
->cdr_
.down_cast
< const Lang::SingleListPair
>( );
1970 args
.addOrderedArgument( src
->car_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1971 src
= src
->cdr_
.down_cast
< const Lang::SingleListPair
>( );
1972 args
.addOrderedArgument( src
->car_
, & Ast::THE_INTERNAL_VALUE_EXPRESSION
);
1973 Lang::Core_range::makeRange( "<span>", evalState
, args
, traceLoc
, true, last
);
1975 virtual void takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
1977 RefCountPtr
< const Lang::SingleList
> values
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( val
) ), values_
) );
1979 for( size_t i
= i_
+ 1; i
< 4; ++i
)
1981 const Kernel::VariableHandle
& var
= (*thunks_
)[ i
];
1982 if( var
->isThunk( ) )
1984 evalState
->cont_
= Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_
, i
, values
, last_
, cont_
, traceLoc_
) );
1985 var
->force( var
, evalState
);
1986 evalState
->dyn_
= Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState
->dyn_
, last_
) );
1989 values
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( var
, values
) );
1991 evalState
->cont_
= cont_
;
1992 finish( values
, last_
, evalState
, traceLoc_
);
1994 virtual Kernel::ContRef
up( ) const
1998 virtual RefCountPtr
< const char > description( ) const
2000 std::ostringstream msg
;
2001 msg
<< "force span parameter number " << i_
;
2002 return strrefdup( msg
);
2004 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2006 const_cast< Kernel::SpanThunks
* >( thunks_
.getPtr( ) )->gcMark( marked
);
2007 const_cast< Lang::SingleList
* >( values_
.getPtr( ) )->gcMark( marked
);
2008 const_cast< Lang::Value
* >( last_
.getPtr( ) )->gcMark( marked
);
2009 cont_
->gcMark( marked
);
2015 RefCountPtr
< const Lang::Class
> Lang::Span::TypeID( new Lang::SystemFinalClass( strrefdup( "Span" ) ) );
2016 TYPEINFOIMPL( Span
);
2018 Lang::Span::Span( const Kernel::VariableHandle
& begin
, const Kernel::VariableHandle
& end
, const Kernel::VariableHandle
& step
, const Kernel::VariableHandle
& count
)
2019 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<span>" ), true ) ),
2020 thunks_( new Kernel::SpanThunks( begin
, end
, step
, count
) )
2022 formals_
->appendEvaluatedCoreFormal( "last", Kernel::THE_SLOT_VARIABLE
);
2025 Lang::Span::~Span( )
2029 Lang::Span::gcMark( Kernel::GCMarkedSet
& marked
)
2031 const_cast< Kernel::SpanThunks
* >( thunks_
.getPtr( ) )->gcMark( marked
);
2035 Lang::Span::show( std::ostream
& os
) const
2041 Lang::Span::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2043 args
.applyDefaults( );
2045 RefCountPtr
< const Lang::SingleList
> values
= Lang::THE_CONS_NULL
;
2046 for( size_t i
= 0; i
< 4; ++i
)
2048 const Kernel::VariableHandle
& var
= (*thunks_
)[ i
];
2049 if( var
->isThunk( ) )
2051 evalState
->cont_
= Kernel::ContRef( new Kernel::SpanForcingContinuation( thunks_
, i
, values
, args
.getValue( 0 ), evalState
->cont_
, callLoc
) );
2052 var
->force( var
, evalState
);
2053 evalState
->dyn_
= Kernel::PassedDyn( new Kernel::DynamicEnvironment( evalState
->dyn_
, args
.getValue( 0 ) ) );
2056 values
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( var
, values
) );
2059 /* We only reach this point if there were no thunks at all to be forced. */
2060 Kernel::SpanForcingContinuation::finish( values
, args
.getValue( 0 ), evalState
, callLoc
);
2064 Lang::Span::isTransforming( ) const
2070 Lang::UserFunction::UserFunction( Kernel::EvaluatedFormals
* formals
, Ast::Expression
* body
, Kernel::PassedEnv env
, const Ast::FunctionMode
& functionMode
)
2071 : Lang::Function( formals
), body_( body
), env_( env
), functionMode_( functionMode
)
2074 // DISPATCHIMPL( UserFunction );
2076 Lang::UserFunction::~UserFunction( )
2078 // Note that we don't delete the things that we most likely share with other objects
2079 // Reference counting could be used here, but there will never be more such things than there are function expressions in the source
2081 // This prevents formals->formals from being deleted by Lang::Function::~Function
2087 Lang::UserFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2089 args
.applyDefaults( );
2090 evalState
->env_
= new Kernel::Environment( Kernel::theEnvironmentList
, env_
, formals_
->formals_
->argumentIdentifiers_
, args
.getVariables( ), formals_
->formals_
->stateIdentifiers_
, args
.getStates( ), "Closure" );
2091 evalState
->expr_
= body_
;
2095 Lang::UserFunction::isTransforming( ) const
2097 return ( functionMode_
& Ast::FUNCTION_TRANSFORMING
) != 0;
2101 Lang::UserFunction::gcMark( Kernel::GCMarkedSet
& marked
)
2103 env_
->gcMark( marked
);
2107 Lang::UserFunction::body( )
2113 Lang::UserFunction::show( std::ostream
& os
) const
2115 os
<< "< user function with body at " << body_
->loc( ) << " >" ;
2119 Lang::TransformedFunction2D::TransformedFunction2D( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Function
> & fun
)
2120 : Lang::Function( 0 ), tf_( tf
), fun_( fun
)
2123 Lang::TransformedFunction2D::~TransformedFunction2D( )
2127 Lang::TransformedFunction2D::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2129 evalState
->cont_
= Kernel::ContRef( new Kernel::Transform2DCont( tf_
, evalState
->cont_
, 0 ) );
2130 fun_
->call( evalState
, args
, callLoc
);
2134 Lang::TransformedFunction2D::isTransforming( ) const
2136 return fun_
->isTransforming( );
2140 Lang::TransformedFunction2D::gcMark( Kernel::GCMarkedSet
& marked
)
2142 const_cast< Lang::Function
* >( fun_
.getPtr( ) )->gcMark( marked
);
2146 Lang::TransformedFunction2D::show( std::ostream
& os
) const
2148 os
<< "< transformed function >" ;
2153 Lang::VectorFunction::VectorFunction( const std::vector
< Kernel::ValueRef
> * mem
)
2154 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "<vector>" ), true ) ), mem_( mem
),
2155 memNumeric_( NullPtr
< const std::vector
< double > >( ) ),
2156 list_( NullPtr
< Kernel::Variable
>( ) )
2158 formals_
->appendEvaluatedCoreFormal( "index", Kernel::THE_SLOT_VARIABLE
);
2161 // DISPATCHIMPL( VectorFunction );
2163 Lang::VectorFunction::~VectorFunction( )
2166 RefCountPtr
< const Lang::Class
> Lang::VectorFunction::TypeID( new Lang::SystemFinalClass( strrefdup( "VectorFunction" ), Kernel::VectorFunction_register_methods
) );
2167 TYPEINFOIMPL( VectorFunction
);
2169 Kernel::VariableHandle
2170 Lang::VectorFunction::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
2172 if( strcmp( fieldID
, "size" ) == 0 )
2174 return Helpers::newValHandle( new Lang::Integer( mem_
->size( ) ) );
2176 if( strcmp( fieldID
, "range" ) == 0 )
2178 return Helpers::newValHandle( new Lang::SingleListRange
< Lang::Integer
>( 0, 1, mem_
->size( ) ) );
2180 if( strcmp( fieldID
, "reverse_range" ) == 0 )
2182 return Helpers::newValHandle( new Lang::SingleListRange
< Lang::Integer
>( mem_
->size( ) - 1, -1, mem_
->size( ) ) );
2184 if( strcmp( fieldID
, "list" ) == 0 )
2190 return TypeID
->getMethod( selfRef
, fieldID
); /* This will throw if there is no such method. */
2193 const char * Lang::VectorFunction::title_
= "<vector>";
2196 Lang::VectorFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2198 const size_t ARITY
= 1;
2199 if( args
.size( ) != ARITY
)
2201 throw Exceptions::CoreArityMismatch( title_
, ARITY
, args
.size( ) );
2204 typedef const Lang::Integer ArgType
;
2205 RefCountPtr
< ArgType
> arg
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
);
2209 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "Index is negative." );
2212 if( arg
->val_
>= static_cast< int >( mem_
->size( ) ) )
2214 throw Exceptions::CoreOutOfRange( title_
, args
, 0, "Index exceeds vector size." );
2217 Kernel::ContRef cont
= evalState
->cont_
;
2218 cont
->takeValue( (*mem_
)[ arg
->val_
],
2223 Lang::VectorFunction::isTransforming( ) const
2229 Lang::VectorFunction::gcMark( Kernel::GCMarkedSet
& marked
)
2231 gcMark( mem_
, marked
);
2235 Lang::VectorFunction::gcMark( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, Kernel::GCMarkedSet
& marked
)
2237 for( std::vector
< Kernel::ValueRef
>::const_iterator i
= mem
->begin( ); i
!= mem
->end( ); ++i
)
2239 const_cast< Lang::Value
* >( i
->getPtr( ) )->gcMark( marked
);
2244 Lang::VectorFunction::show( std::ostream
& os
) const
2246 os
<< "< vector function >" ;
2249 RefCountPtr
< const std::vector
< double > >
2250 Lang::VectorFunction::getNumeric( const Ast::SourceLocation
& callLoc
) const
2252 if( memNumeric_
== NullPtr
< const std::vector
< double > >( ) )
2254 RefCountPtr
< std::vector
< double > > res( new std::vector
< double > ); // Note that this is not const, so far...
2255 res
->reserve( mem_
->size( ) );
2256 typedef typeof *mem_ SrcType
;
2257 for( SrcType::const_iterator src
= mem_
->begin( ); src
!= mem_
->end( ); ++src
)
2259 res
->push_back( Helpers::down_cast
< const Lang::Float
>( *src
, callLoc
)->val_
);
2268 Lang::VectorFunction::compute_list( ) const
2270 if( list_
!= NullPtr
< Kernel::Variable
>( ) )
2274 RefCountPtr
< const Lang::SingleList
> newList
= Lang::THE_CONS_NULL
;
2275 typedef typeof *mem_ ListType
;
2276 for( ListType::const_reverse_iterator src
= mem_
->rbegin( ); src
!= mem_
->rend( ); ++src
)
2278 newList
= RefCountPtr
< const Lang::SingleList
>( new Lang::SingleListPair( Kernel::VariableHandle( new Kernel::Variable( *src
) ), newList
) );
2280 list_
= Kernel::VariableHandle( new Kernel::Variable( newList
) );
2288 class VectorFunctionFoldLCont
: public Kernel::Continuation
2290 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
2291 RefCountPtr
< const Lang::Function
> op_
;
2292 Shapes::Lang::VectorFunction::vector_type::const_iterator i_
;
2293 Kernel::PassedDyn dyn_
;
2294 Kernel::ContRef cont_
;
2296 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
)
2297 : Kernel::Continuation( traceLoc
), mem_( mem
), op_( op
), i_( i
), dyn_( dyn
), cont_( cont
)
2299 virtual ~VectorFunctionFoldLCont( ) { }
2300 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
2302 evalState
->dyn_
= dyn_
;
2303 evalState
->cont_
= cont_
;
2304 Lang::VectorFunction::foldl( mem_
, evalState
, op_
, val
, i_
, traceLoc_
);
2306 virtual Kernel::ContRef
up( ) const
2310 virtual RefCountPtr
< const char > description( ) const
2312 return strrefdup( "VectorFunction's foldl" );
2314 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2316 Lang::VectorFunction::gcMark( mem_
, marked
);
2317 const_cast< Lang::Function
* >( op_
.getPtr( ) )->gcMark( marked
);
2318 dyn_
->gcMark( marked
);
2319 cont_
->gcMark( marked
);
2323 class VectorFunctionFoldRCont
: public Kernel::Continuation
2325 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
2326 RefCountPtr
< const Lang::Function
> op_
;
2327 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_
;
2328 Kernel::PassedDyn dyn_
;
2329 Kernel::ContRef cont_
;
2331 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
)
2332 : Kernel::Continuation( traceLoc
), mem_( mem
), op_( op
), i_( i
), dyn_( dyn
), cont_( cont
)
2334 virtual ~VectorFunctionFoldRCont( ) { }
2335 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
2337 evalState
->dyn_
= dyn_
;
2338 evalState
->cont_
= cont_
;
2339 Lang::VectorFunction::foldr( mem_
, evalState
, op_
, val
, i_
, traceLoc_
);
2341 virtual Kernel::ContRef
up( ) const
2345 virtual RefCountPtr
< const char > description( ) const
2347 return strrefdup( "VectorFunction's foldr" );
2349 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2351 Lang::VectorFunction::gcMark( mem_
, marked
);
2352 const_cast< Lang::Function
* >( op_
.getPtr( ) )->gcMark( marked
);
2353 dyn_
->gcMark( marked
);
2354 cont_
->gcMark( marked
);
2358 class VectorFunctionFoldSLCont
: public Kernel::Continuation
2360 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
2361 RefCountPtr
< const Lang::Function
> op_
;
2362 Shapes::Lang::VectorFunction::vector_type::const_iterator i_
;
2363 Kernel::StateHandle state_
;
2364 Kernel::PassedDyn dyn_
;
2365 Kernel::ContRef cont_
;
2367 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
)
2368 : Kernel::Continuation( traceLoc
), mem_( mem
), op_( op
), i_( i
), state_( state
), dyn_( dyn
), cont_( cont
)
2370 virtual ~VectorFunctionFoldSLCont( ) { }
2371 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
2373 evalState
->dyn_
= dyn_
;
2374 evalState
->cont_
= cont_
;
2375 Lang::VectorFunction::foldsl( mem_
, evalState
, op_
, val
, state_
, i_
, traceLoc_
);
2377 virtual Kernel::ContRef
up( ) const
2381 virtual RefCountPtr
< const char > description( ) const
2383 return strrefdup( "VectorFunction's foldsl" );
2385 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2387 Lang::VectorFunction::gcMark( mem_
, marked
);
2388 const_cast< Lang::Function
* >( op_
.getPtr( ) )->gcMark( marked
);
2389 state_
->gcMark( marked
);
2390 dyn_
->gcMark( marked
);
2391 cont_
->gcMark( marked
);
2395 class VectorFunctionFoldSRCont
: public Kernel::Continuation
2397 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
2398 RefCountPtr
< const Lang::Function
> op_
;
2399 Shapes::Lang::VectorFunction::vector_type::const_reverse_iterator i_
;
2400 Kernel::StateHandle state_
;
2401 Kernel::PassedDyn dyn_
;
2402 Kernel::ContRef cont_
;
2404 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
)
2405 : Kernel::Continuation( traceLoc
), mem_( mem
), op_( op
), i_( i
), state_( state
), dyn_( dyn
), cont_( cont
)
2407 virtual ~VectorFunctionFoldSRCont( ) { }
2408 virtual void takeHandle( Kernel::VariableHandle val
, Kernel::EvalState
* evalState
, bool dummy
) const
2410 evalState
->dyn_
= dyn_
;
2411 evalState
->cont_
= cont_
;
2412 Lang::VectorFunction::foldsr( mem_
, evalState
, op_
, val
, state_
, i_
, traceLoc_
);
2414 virtual Kernel::ContRef
up( ) const
2418 virtual RefCountPtr
< const char > description( ) const
2420 return strrefdup( "VectorFunction's foldsr" );
2422 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
2424 Lang::VectorFunction::gcMark( mem_
, marked
);
2425 const_cast< Lang::Function
* >( op_
.getPtr( ) )->gcMark( marked
);
2426 state_
->gcMark( marked
);
2427 dyn_
->gcMark( marked
);
2428 cont_
->gcMark( marked
);
2436 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
)
2438 if( i
== mem
->end( ) )
2440 Kernel::ContRef cont
= evalState
->cont_
;
2441 cont
->takeHandle( nullResult
,
2446 Kernel::VariableHandle elem
= Kernel::VariableHandle( new Kernel::Variable( *i
) );
2448 evalState
->cont_
= Kernel::ContRef( new Kernel::VectorFunctionFoldLCont( mem
, op
, i
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
2450 op
->call( op
, evalState
, nullResult
, elem
, callLoc
);
2454 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
)
2456 if( i
== mem
->rend( ) )
2458 Kernel::ContRef cont
= evalState
->cont_
;
2459 cont
->takeHandle( nullResult
,
2464 Kernel::VariableHandle elem
= Kernel::VariableHandle( new Kernel::Variable( *i
) );
2466 evalState
->cont_
= Kernel::ContRef( new Kernel::VectorFunctionFoldRCont( mem
, op
, i
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
2468 op
->call( op
, evalState
, nullResult
, elem
, callLoc
);
2472 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
)
2474 if( i
== mem
->end( ) )
2476 Kernel::ContRef cont
= evalState
->cont_
;
2477 cont
->takeHandle( nullResult
,
2482 Kernel::VariableHandle elem
= Kernel::VariableHandle( new Kernel::Variable( *i
) );
2484 evalState
->cont_
= Kernel::ContRef( new Kernel::VectorFunctionFoldSLCont( mem
, op
, i
, state
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
2486 op
->call( op
, evalState
, nullResult
, elem
, state
, callLoc
);
2490 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
)
2492 if( i
== mem
->rend( ) )
2494 Kernel::ContRef cont
= evalState
->cont_
;
2495 cont
->takeHandle( nullResult
,
2500 Kernel::VariableHandle elem
= Kernel::VariableHandle( new Kernel::Variable( *i
) );
2502 evalState
->cont_
= Kernel::ContRef( new Kernel::VectorFunctionFoldSRCont( mem
, op
, i
, state
, evalState
->dyn_
, evalState
->cont_
, callLoc
) );
2504 op
->call( op
, evalState
, nullResult
, elem
, state
, callLoc
);
2508 const char * Lang::ColorInterpolator::title_
= "<color-interpolator>";
2510 Lang::ColorInterpolator::ColorInterpolator( const RefCountPtr
< KeyContainer
> & key
,
2511 const RefCountPtr
< RGBContainer
> & RGBcolor
,
2512 const RefCountPtr
< GrayContainer
> & graycolor
,
2513 const RefCountPtr
< CMYKContainer
> & CMYKcolor
,
2514 ColorType colorType
)
2515 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( Lang::ColorInterpolator::title_
), true ) ),
2516 key_( key
), RGBcolor_ ( RGBcolor
), graycolor_ ( graycolor
), CMYKcolor_ ( CMYKcolor
), colorType_(colorType
)
2518 formals_
->appendEvaluatedCoreFormal( "key", Kernel::THE_SLOT_VARIABLE
);
2521 Lang::ColorInterpolator::~ColorInterpolator( )
2524 Kernel::VariableHandle
2525 Lang::ColorInterpolator::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
2527 if( strcmp( fieldID
, "low" ) == 0 )
2529 return Helpers::newValHandle( new Lang::Float( key_
->front( ) ) );
2531 if( strcmp( fieldID
, "high" ) == 0 )
2533 return Helpers::newValHandle( new Lang::Float( key_
->back( ) ) );
2535 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
2539 template <class COLOR_TYPE
, class COLOR_CONTAINER
>
2541 Lang::ColorInterpolator::callHelper( Kernel::EvalState
* evalState
,
2542 const RefCountPtr
< COLOR_CONTAINER
> & colorContainer
,
2543 double key
, KeyContainer::const_iterator keyHi
) const
2545 if( keyHi
== key_
->end( ) )
2547 Kernel::ContRef cont
= evalState
->cont_
;
2548 cont
->takeValue( RefCountPtr
< const::Lang::Value
>( new COLOR_TYPE( colorContainer
->back( ) ) ),
2553 if( keyHi
== key_
->begin( ) )
2555 Kernel::ContRef cont
= evalState
->cont_
;
2556 cont
->takeValue( RefCountPtr
< const::Lang::Value
>( new COLOR_TYPE( colorContainer
->front( ) ) ),
2561 KeyContainer::const_iterator keyLo
= keyHi
- 1;
2562 double rem
= ( key
- *keyLo
) / ( *keyHi
- *keyLo
);
2564 Kernel::ContRef cont
= evalState
->cont_
;
2566 typename
COLOR_CONTAINER::const_iterator colorHi
= colorContainer
->begin( ) + ( keyHi
- key_
->begin( ) );
2567 typename
COLOR_CONTAINER::const_iterator colorLo
= colorHi
- 1;
2569 cont
->takeValue( RefCountPtr
< const::Lang::Value
>( new COLOR_TYPE( colorLo
->mulNoCheck( 1 - rem
).addNoCheck( colorHi
->mulNoCheck( rem
) ) ) ),
2575 Lang::ColorInterpolator::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2577 const size_t ARITY
= 1;
2578 if( args
.size( ) != ARITY
)
2580 throw Exceptions::CoreArityMismatch( title_
, ARITY
, args
.size( ) );
2583 typedef const Lang::Float ArgType
;
2584 double key
= Helpers::down_cast_CoreArgument
< ArgType
>( title_
, args
, 0, callLoc
)->val_
;
2586 KeyContainer::const_iterator keyHi
= lower_bound( key_
->begin( ), key_
->end( ), key
);
2587 switch( colorType_
)
2590 callHelper
< Lang::RGB
>( evalState
, RGBcolor_
, key
, keyHi
);
2593 callHelper
< Lang::Gray
>( evalState
, graycolor_
, key
, keyHi
);
2596 callHelper
< Lang::CMYK
>( evalState
, CMYKcolor_
, key
, keyHi
);
2599 throw Exceptions::InternalError( "ColorInterpolator::call: Did not expect UNDEFINED in ennum switch." );
2604 Lang::ColorInterpolator::isTransforming( ) const
2610 Lang::ColorInterpolator::gcMark( Kernel::GCMarkedSet
& marked
)
2614 Lang::ColorInterpolator::show( std::ostream
& os
) const
2616 os
<< "< color interpolator in " ;
2617 switch( colorType_
)
2629 throw Exceptions::InternalError( "ColorInterpolator::show: Did not expect UNDEFINED in ennum switch." );
2634 Lang::BinaryOperatorFunction::BinaryOperatorFunction( Ast::BinaryInfixExpr
* opExpr
, const char * title
)
2635 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) ), opExpr_( opExpr
), title_( title
)
2637 formals_
->appendEvaluatedCoreFormal( "first", Kernel::THE_SLOT_VARIABLE
);
2638 formals_
->appendEvaluatedCoreFormal( "second", Kernel::THE_SLOT_VARIABLE
);
2641 Lang::BinaryOperatorFunction::~BinaryOperatorFunction( )
2647 Lang::BinaryOperatorFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2649 const size_t ARITY
= 2;
2650 CHECK_ARITY( args
, ARITY
, title_
);
2651 RefCountPtr
< const Lang::Value
> arg1
= args
.getValue( 0 );
2652 RefCountPtr
< const Lang::Value
> arg2
= args
.getValue( 1 );
2656 Kernel::ContRef cont
= evalState
->cont_
;
2657 cont
->takeValue( arg1
->binaryDispatch1( arg1
, arg2
, evalState
->dyn_
, opExpr_
),
2660 catch( Exceptions::BinaryInfixNotApplicable
& ball
)
2662 ball
.setOperatorSymbol( title_
);
2668 Lang::BinaryOperatorFunction::isTransforming( ) const
2674 Lang::BinaryOperatorFunction::show( std::ostream
& os
) const
2676 os
<< "< binary operator function for " << title_
<< " >" ;
2680 Lang::UnaryOperatorFunction::UnaryOperatorFunction( Ast::UnaryExpr
* opExpr
, const char * title
)
2681 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( title
), true ) ), opExpr_( opExpr
), title_( title
)
2683 formals_
->appendEvaluatedCoreFormal( "only", Kernel::THE_SLOT_VARIABLE
);
2686 Lang::UnaryOperatorFunction::~UnaryOperatorFunction( )
2692 Lang::UnaryOperatorFunction::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2694 const size_t ARITY
= 1;
2695 CHECK_ARITY( args
, ARITY
, title_
);
2697 RefCountPtr
< const Lang::Value
> arg
= args
.getValue( 0 );
2701 Kernel::ContRef cont
= evalState
->cont_
;
2702 cont
->takeValue( arg
->unaryDispatch( arg
, evalState
->dyn_
, opExpr_
),
2705 catch( Exceptions::UnaryPrefixNotApplicable
& ball
)
2707 ball
.setOperatorSymbol( title_
);
2710 catch( Exceptions::UnaryPostfixNotApplicable
& ball
)
2712 ball
.setOperatorSymbol( title_
);
2718 Lang::UnaryOperatorFunction::isTransforming( ) const
2724 Lang::UnaryOperatorFunction::show( std::ostream
& os
) const
2726 os
<< "< unary operator function for " << title_
<< " >" ;
2730 Lang::Transform2DMethod_chop::Transform2DMethod_chop( RefCountPtr
< const Lang::Transform2D
> self
, const Ast::FileID
* fullMethodID
)
2731 : Lang::MethodBase
< class_type
>( self
, fullMethodID
, false, true )
2733 formals_
->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE
);
2734 formals_
->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE
);
2737 Lang::Transform2DMethod_chop::~Transform2DMethod_chop( )
2741 Lang::Transform2DMethod_chop::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2743 args
.applyDefaults( );
2746 double Ltol
= Helpers::down_cast_CoreArgument
< const Lang::Float
>( title_
, args
, argsi
, callLoc
)->val_
;
2749 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Tolerances must not be negative." );
2753 Concrete::Length ptol
= Helpers::down_cast_CoreArgument
< const Lang::Length
>( title_
, args
, argsi
, callLoc
)->get( );
2754 if( ptol
< Concrete::ZERO_LENGTH
)
2756 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Tolerances must not be negative." );
2759 Lang::Transform2D
* res
= self_
->clone( );
2761 CHOP_Ltol( res
->xx_
);
2762 CHOP_Ltol( res
->yx_
);
2764 CHOP_Ltol( res
->xy_
);
2765 CHOP_Ltol( res
->yy_
);
2767 CHOP_ptol( res
->xt_
);
2768 CHOP_ptol( res
->yt_
);
2770 Kernel::ContRef cont
= evalState
->cont_
;
2771 cont
->takeValue( RefCountPtr
< const Lang::Value
>( res
),
2776 Lang::Transform3DMethod_chop::Transform3DMethod_chop( RefCountPtr
< const Lang::Transform3D
> self
, const Ast::FileID
* fullMethodID
)
2777 : Lang::MethodBase
< class_type
>( self
, fullMethodID
, false, true )
2779 formals_
->appendEvaluatedCoreFormal( "L", Kernel::THE_SLOT_VARIABLE
);
2780 formals_
->appendEvaluatedCoreFormal( "p", Kernel::THE_SLOT_VARIABLE
);
2783 Lang::Transform3DMethod_chop::~Transform3DMethod_chop( )
2787 Lang::Transform3DMethod_chop::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
2789 args
.applyDefaults( );
2792 double Ltol
= Helpers::down_cast_CoreArgument
< const Lang::Float
>( title_
, args
, argsi
, callLoc
)->val_
;
2795 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Tolerances must not be negative." );
2799 Concrete::Length ptol
= Helpers::down_cast_CoreArgument
< const Lang::Length
>( title_
, args
, argsi
, callLoc
)->get( );
2800 if( ptol
< Concrete::ZERO_LENGTH
)
2802 throw Exceptions::CoreOutOfRange( title_
, args
, argsi
, "Tolerances must not be negative." );
2805 Lang::Transform3D
* res
= self_
->clone( );
2807 CHOP_Ltol( res
->xx_
);
2808 CHOP_Ltol( res
->yx_
);
2809 CHOP_Ltol( res
->zx_
);
2811 CHOP_Ltol( res
->xy_
);
2812 CHOP_Ltol( res
->yy_
);
2813 CHOP_Ltol( res
->zy_
);
2815 CHOP_Ltol( res
->xz_
);
2816 CHOP_Ltol( res
->yz_
);
2817 CHOP_Ltol( res
->zz_
);
2819 CHOP_ptol( res
->xt_
);
2820 CHOP_ptol( res
->yt_
);
2821 CHOP_ptol( res
->zt_
);
2823 Kernel::ContRef cont
= evalState
->cont_
;
2824 cont
->takeValue( RefCountPtr
< const Lang::Value
>( res
),