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 "Shapes_Lang_decls.h"
22 #include "Shapes_Kernel_decls.h"
23 #include "Shapes_Ast_decls.h"
25 #include "shapesvalue.h"
28 #include "pdfstructure.h"
29 #include "environment.h"
30 #include "charptrless.h"
32 #include "elementarytypes.h"
33 #include "elementarycoords.h"
39 #include <gsl/gsl_matrix.h>
42 #define CHECK_ARITY( argsVar, arity, titleExpr ) \
43 if( argsVar.size( ) != ARITY )\
45 throw Exceptions::CoreArityMismatch( titleExpr, arity, argsVar.size( ) );\
58 const Kernel::EvaluatedFormals
* formals_
;
59 Environment::ValueVector variables_
;
60 std::vector
< const Ast::Node
* > locations_
;
63 // Putting dstEnd_ after hasSink_ makes initialization more convenient.
64 size_t dstEnd_
; // This is one less than there are variables if there is a sink.
65 bool isSink_
; // This is used by functions in the core.
67 Ast::ArgListExprs
* sinkArgList_
; // If null, there is no sink.
68 RefCountPtr
< const Lang::SingleList
> sinkValues_
;
70 Environment::StateVector states_
; // This type must match that used in Environment
71 std::vector
< const Ast::Node
* > stateLocations_
;
74 Kernel::StateHandle mutatorSelf_
;
77 Arguments( const Kernel::EvaluatedFormals
* formals
);
80 Kernel::Arguments
clone( ) const;
82 void addOrderedArgument( const Kernel::VariableHandle
& arg
, Ast::Expression
* loc
);
83 void addNamedArgument( const char * id
, const Kernel::VariableHandle
& arg
, Ast::Expression
* loc
);
85 void addOrderedState( const Kernel::StateHandle
& state
, Ast::Node
* loc
);
86 void addNamedState( const char * id
, const Kernel::StateHandle
& state
, Ast::Node
* loc
);
88 void applyDefaults( );
90 Kernel::VariableHandle
& getHandle( size_t i
);
91 RefCountPtr
< const Lang::Value
> & getValue( size_t i
);
92 const Ast::SourceLocation
& getLoc( size_t i
) const;
93 const Ast::Node
* getNode( size_t i
) const;
94 Kernel::Thunk
* getThunk( size_t i
); // This funciton returns a newly created copy!
95 bool isSlot( size_t i
) const;
100 Kernel::StateHandle
getState( size_t i
);
101 const Ast::SourceLocation
& getStateLoc( size_t i
) const;
103 void setMutatorSelf( Kernel::StateHandle mutatorSelf
);
104 Kernel::StateHandle
getMutatorSelf( );
106 void gcMark( Kernel::GCMarkedSet
& marked
);
108 Environment::ValueVector
getVariables( ); // This function should only be called when setting up a new environment
109 Environment::StateVector
getStates( ); // This function should only be called when setting up a new environment
112 class EvaluatedFormals
114 bool selectiveForcing_
;
117 Kernel::Formals
* formals_
; /* it would have been const if it was not for appendEvaluatedFormal */
118 std::vector
< Kernel::VariableHandle
> defaults_
;
119 std::vector
< const Ast::Node
* > locations_
;
122 EvaluatedFormals( Kernel::Formals
* _formals
);
123 EvaluatedFormals( const Ast::FileID
* locationFileID
);
124 EvaluatedFormals( const Ast::FileID
* locationFileID
, bool _forceAll
);
125 ~EvaluatedFormals( );
127 void appendEvaluatedFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, const Ast::Node
* loc
, bool force
);
128 void appendEvaluatedFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, const Ast::Node
* loc
);
129 void appendEvaluatedCoreFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
, bool force
);
130 void appendEvaluatedCoreFormal( const char * id
, const Kernel::VariableHandle
& defaultVal
);
131 void appendCoreStateFormal( const char * id
);
133 RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const;
134 RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const;
136 void gcMark( Kernel::GCMarkedSet
& marked
);
139 void VectorFunction_register_methods( Lang::SystemFinalClass
* dstClass
); /* Implemented in containertypes.cc for convenience. */
148 down_cast_CoreArgument( const char * coreTitle
, Kernel::Arguments
& args
, size_t i
, const Ast::SourceLocation
& callLoc
, bool voidIsNull
= false )
150 RefCountPtr
< const Lang::Value
> val
= args
.getValue( i
);
151 RefCountPtr
< T
> res
= val
.down_cast
< T
>( );
152 if( res
== NullPtr
< T
>( ) )
155 dynamic_cast< const Lang::Void
* >( val
.getPtr( ) ) == 0 )
157 throw Exceptions::CoreTypeMismatch( callLoc
, coreTitle
, args
.getLoc( i
), val
->getTypeName( ), T::staticTypeName( ) );
165 down_cast_CoreState( const char * coreTitle
, Kernel::Arguments
& args
, size_t i
, const Ast::SourceLocation
& callLoc
)
167 Kernel::StateHandle st
= args
.getState( i
);
168 T
* res
= dynamic_cast< T
* >( st
);
169 if( res
== NullPtr
< T
>( ) )
171 throw Exceptions::CoreStateTypeMismatch( callLoc
, coreTitle
, args
.getStateLoc( i
), st
->getTypeName( ), T::staticTypeName( ) );
178 down_cast_CoreDynamic( const char * coreTitle
, const char * id
, const RefCountPtr
< const Lang::Value
> & val
, const Ast::SourceLocation
& callLoc
)
180 RefCountPtr
< T
> res
= val
.down_cast
< T
>( );
181 if( res
== NullPtr
< T
>( ) )
183 throw Exceptions::CoreDynamicTypeMismatch( callLoc
, coreTitle
, id
, val
->getTypeName( ), T::staticTypeName( ) );
190 try_cast_CoreArgument( const RefCountPtr
< const Lang::Value
> & val
, bool voidIsNull
= false )
192 RefCountPtr
< T
> res
= val
.down_cast
< T
>( );
193 if( res
== NullPtr
< T
>( ) )
196 dynamic_cast< const Lang::Void
* >( val
.getPtr( ) ) == 0 )
198 throw NonLocalExit::NotThisType( );
206 try_cast_CoreState( Kernel::StateHandle st
)
208 T
* res
= dynamic_cast< T
* >( st
);
209 if( res
== NullPtr
< T
>( ) )
211 throw NonLocalExit::NotThisType( );
218 mutator_cast_self( Kernel::StateHandle st
)
220 T
* res
= dynamic_cast< T
* >( st
);
221 if( res
== NullPtr
< T
>( ) )
223 throw Exceptions::InternalError( "Type of self state does not match mutator signature." );
234 class Transform2D
: public Lang::Value
241 Concrete::Length xt_
;
242 Concrete::Length yt_
;
243 Transform2D( double xx
, double yx
, double xy
, double yy
,
244 Concrete::Length xt
, Concrete::Length yt
);
245 Transform2D( const Lang::Transform2D
& tf2
, const Lang::Transform2D
& tf1
);
246 virtual ~Transform2D( );
247 virtual Kernel::VariableHandle
getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const;
248 Transform2D
* clone( ) const;
249 bool isIdentity( ) const;
250 bool isTranslation( ) const;
251 void write_gsl_matrix( gsl_matrix
* matrix_2_2
) const;
252 void write_gsl_vector( gsl_vector
* vec_2
) const;
253 void shipout( std::ostream
& os
) const;
254 void replaceBy( const Lang::Transform2D
& newtf
); // to be used by text moveto commands
255 void prependShift( const Concrete::Coords2D
& d
); // to be used by text newline commands
256 void prependXShift( const Concrete::Length
& dx
); // to be used by text painting commands
257 void prependYShift( const Concrete::Length
& dy
); // to be used for text rise
258 void prependXScale( double a
); // to be used for text horizontal scaling
260 virtual void gcMark( Kernel::GCMarkedSet
& marked
){ };
261 virtual void show( std::ostream
& os
) const;
265 class Transform3D
: public Lang::Value
267 static const int N
= 3;
268 mutable gsl_matrix
* planeNormalTransformData_
;
279 Concrete::Length xt_
;
280 Concrete::Length yt_
;
281 Concrete::Length zt_
;
282 Transform3D( double xx
, double yx
, double zx
, double xy
, double yy
, double zy
, double xz
, double yz
, double zz
,
283 Concrete::Length xt
, Concrete::Length yt
, Concrete::Length zt
);
284 Transform3D( const gsl_matrix
* matrix_3_3
, const gsl_vector
* vec_3
);
285 Transform3D( const Lang::Transform3D
& tf2
, const Lang::Transform3D
& tf1
);
286 virtual ~Transform3D( );
287 virtual Kernel::VariableHandle
getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const;
288 Transform3D
* clone( ) const;
289 bool isIdentity( ) const;
290 bool isTranslation( ) const;
291 Concrete::UnitFloatTriple
transformPlaneUnitNormal( const Concrete::UnitFloatTriple
& n
) const;
292 void write_gsl_matrix( gsl_matrix
* matrix_3_3
) const;
293 void write_gsl_vector( gsl_vector
* vec_3
) const;
295 virtual void gcMark( Kernel::GCMarkedSet
& marked
){ };
296 virtual void show( std::ostream
& os
) const;
300 class Function
: public Lang::Value
303 Kernel::EvaluatedFormals
* formals_
; // the reason that this is not const is only to allow convenient setup
304 virtual void analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
);
306 Function( Kernel::EvaluatedFormals
* formals
);
307 virtual ~Function( );
308 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const = 0;
309 virtual Kernel::ValueRef
transformed( const Lang::Transform2D
& tf
, Kernel::ValueRef self
) const;
310 virtual bool isTransforming( ) const = 0;
311 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const;
312 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const;
313 virtual Kernel::Arguments
newCurriedArguments( ) const;
314 virtual void call( Kernel::EvalState
* evalState
, const Kernel::ValueRef
& arg1
, const Ast::SourceLocation
& callLoc
) const;
315 virtual void call( Kernel::EvalState
* evalState
, const Kernel::ValueRef
& arg1
, const Kernel::ValueRef
& arg2
, const Ast::SourceLocation
& callLoc
) const;
316 virtual void call( const RefCountPtr
< const Lang::Function
> & selfRef
, Kernel::EvalState
* evalState
, const Kernel::VariableHandle
& arg1
, const Ast::SourceLocation
& callLoc
) const;
317 virtual void call( const RefCountPtr
< const Lang::Function
> & selfRef
, Kernel::EvalState
* evalState
, const Kernel::VariableHandle
& arg1
, const Kernel::VariableHandle
& arg2
, const Ast::SourceLocation
& callLoc
) const;
318 virtual void 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;
320 void analyze( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
);
325 static Ast::ArgListExprs
* oneExprArgList
;
326 static Ast::ArgListExprs
* twoExprsArgList
;
329 class CuteFunction
: public Lang::Function
331 RefCountPtr
< const Lang::Function
> callee_
;
332 Kernel::Arguments someArgs_
;
334 CuteFunction( RefCountPtr
< const Lang::Function
> _callee
, const Kernel::Arguments
& _someArgs
);
335 virtual ~CuteFunction( );
336 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const;
337 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const;
338 virtual Kernel::Arguments
newCurriedArguments( ) const;
339 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
340 virtual void show( std::ostream
& os
) const;
341 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
342 virtual bool isTransforming( ) const;
345 class ComposedFunction
: public Lang::Function
347 RefCountPtr
< const Lang::Function
> second_
;
348 RefCountPtr
< const Lang::Function
> first_
;
350 ComposedFunction( const RefCountPtr
< const Lang::Function
> & _second
, const RefCountPtr
< const Lang::Function
> & _first
);
351 virtual ~ComposedFunction( );
352 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const;
353 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const;
354 virtual Kernel::Arguments
newCurriedArguments( ) const;
355 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
356 virtual bool isTransforming( ) const;
357 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
358 virtual void show( std::ostream
& os
) const;
361 class Span
: public Lang::Function
363 RefCountPtr
< const Kernel::SpanThunks
> thunks_
;
365 Span( const Kernel::VariableHandle
& begin
, const Kernel::VariableHandle
& end
, const Kernel::VariableHandle
& step
, const Kernel::VariableHandle
& count
);
367 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
368 virtual void show( std::ostream
& os
) const;
369 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
370 virtual bool isTransforming( ) const;
374 class UserFunction
: public Lang::Function
376 Ast::Expression
* body_
;
377 Kernel::PassedEnv env_
;
378 Ast::FunctionMode functionMode_
;
380 UserFunction( Kernel::EvaluatedFormals
* _formals
, Ast::Expression
* _body
, Kernel::PassedEnv _env
, const Ast::FunctionMode
& _functionMode
);
381 virtual ~UserFunction( );
382 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
383 virtual bool isTransforming( ) const;
384 virtual void show( std::ostream
& os
) const;
385 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
386 Ast::Expression
* body( ); /* Will typically require a const_cast to be callable. */
389 class TransformedFunction2D
: public Lang::Function
391 Lang::Transform2D tf_
;
392 RefCountPtr
< const Lang::Function
> fun_
;
394 TransformedFunction2D( const Lang::Transform2D
& _tf
, const RefCountPtr
< const Lang::Function
> & _fun
);
395 virtual ~TransformedFunction2D( );
396 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
397 virtual void show( std::ostream
& os
) const;
398 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
399 virtual bool isTransforming( ) const;
402 class VectorFunction
: public Lang::Function
405 typedef std::vector
< Kernel::ValueRef
> vector_type
;
407 RefCountPtr
< const vector_type
> mem_
;
408 mutable RefCountPtr
< const std::vector
< double > > memNumeric_
;
409 mutable Kernel::VariableHandle list_
;
410 static const char * title_
;
412 VectorFunction( const std::vector
< Kernel::ValueRef
> * mem
);
413 virtual ~VectorFunction( );
414 virtual Kernel::VariableHandle
getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const;
415 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
416 static void gcMark( const RefCountPtr
< const std::vector
< Kernel::ValueRef
> > & mem
, Kernel::GCMarkedSet
& marked
);
417 virtual void show( std::ostream
& os
) const;
418 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
419 virtual bool isTransforming( ) const;
420 RefCountPtr
< const std::vector
< double > > getNumeric( const Ast::SourceLocation
& callLoc
) const;
422 static void 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
);
423 static void 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
);
424 static void 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
);
425 static void 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
);
427 /* In order to be able to use the same method template as ConsPair, we support that the <op> argument is additionally passed as a VariableHandle. */
428 inline void foldl( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Function
> & op
, const Kernel::VariableHandle
& opHandle
, const Kernel::VariableHandle
& nullResult
, const Ast::SourceLocation
& callLoc
) const
430 foldl( mem_
, evalState
, op
, nullResult
, mem_
->begin( ), callLoc
);
432 inline void foldr( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Function
> & op
, const Kernel::VariableHandle
& opHandle
, const Kernel::VariableHandle
& nullResult
, const Ast::SourceLocation
& callLoc
) const
434 foldr( mem_
, evalState
, op
, nullResult
, mem_
->rbegin( ), callLoc
);
436 inline void foldsl( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Function
> & op
, const Kernel::VariableHandle
& opHandle
, const Kernel::VariableHandle
& nullResult
, Kernel::StateHandle state
, const Ast::SourceLocation
& callLoc
) const
438 foldsl( mem_
, evalState
, op
, nullResult
, state
, mem_
->begin( ), callLoc
);
440 inline void foldsr( Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Function
> & op
, const Kernel::VariableHandle
& opHandle
, const Kernel::VariableHandle
& nullResult
, Kernel::StateHandle state
, const Ast::SourceLocation
& callLoc
) const
442 foldsr( mem_
, evalState
, op
, nullResult
, state
, mem_
->rbegin( ), callLoc
);
447 void compute_list( ) const; /* This will modify mutable data! */
450 class ColorInterpolator
: public Lang::Function
453 typedef std::vector
< double > KeyContainer
;
454 typedef std::vector
< Concrete::RGB
> RGBContainer
;
455 typedef std::vector
< Concrete::Gray
> GrayContainer
;
456 typedef std::vector
< Concrete::CMYK
> CMYKContainer
;
457 enum ColorType
{ UNDEFINED
, RGB
, GRAY
, CMYK
};
460 RefCountPtr
< const KeyContainer
> key_
;
461 RefCountPtr
< const RGBContainer
> RGBcolor_
;
462 RefCountPtr
< const GrayContainer
> graycolor_
;
463 RefCountPtr
< const CMYKContainer
> CMYKcolor_
;
464 static const char * title_
;
465 ColorType colorType_
;
468 ColorInterpolator( const RefCountPtr
< KeyContainer
> & key
,
469 const RefCountPtr
< RGBContainer
> & RGBcolor
,
470 const RefCountPtr
< GrayContainer
> & graycolor
,
471 const RefCountPtr
< CMYKContainer
> & CMYKcolor
,
472 ColorType colorType
);
473 virtual ~ColorInterpolator( );
474 virtual Kernel::VariableHandle
getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const;
475 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
476 virtual void show( std::ostream
& os
) const;
477 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
478 virtual bool isTransforming( ) const;
481 template <class COLOR_TYPE
, class COLOR_CONTAINER
>
482 void callHelper( Kernel::EvalState
* evalState
, const RefCountPtr
< COLOR_CONTAINER
> & colorContainer
,
483 double key
, KeyContainer::const_iterator keyHi
) const;
487 class BinaryOperatorFunction
: public Lang::Function
489 Ast::BinaryInfixExpr
* opExpr_
;
492 BinaryOperatorFunction( Ast::BinaryInfixExpr
* opExpr
, const char * title
);
493 virtual ~BinaryOperatorFunction( );
494 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
495 virtual bool isTransforming( ) const;
496 virtual void gcMark( Kernel::GCMarkedSet
& marked
){ };
497 virtual void show( std::ostream
& os
) const;
500 class UnaryOperatorFunction
: public Lang::Function
502 Ast::UnaryExpr
* opExpr_
;
505 UnaryOperatorFunction( Ast::UnaryExpr
* opExpr
, const char * title
);
506 virtual ~UnaryOperatorFunction( );
507 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
508 virtual bool isTransforming( ) const;
509 virtual void gcMark( Kernel::GCMarkedSet
& marked
){ };
510 virtual void show( std::ostream
& os
) const;