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
);
147 down_cast_CoreArgument( const char * coreTitle
, Kernel::Arguments
& args
, size_t i
, const Ast::SourceLocation
& callLoc
, bool voidIsNull
= false )
149 RefCountPtr
< const Lang::Value
> val
= args
.getValue( i
);
150 RefCountPtr
< T
> res
= val
.down_cast
< T
>( );
151 if( res
== NullPtr
< T
>( ) )
154 dynamic_cast< const Lang::Void
* >( val
.getPtr( ) ) == 0 )
156 throw Exceptions::CoreTypeMismatch( callLoc
, coreTitle
, args
.getLoc( i
), val
->getTypeName( ), T::staticTypeName( ) );
164 down_cast_CoreState( const char * coreTitle
, Kernel::Arguments
& args
, size_t i
, const Ast::SourceLocation
& callLoc
)
166 Kernel::StateHandle st
= args
.getState( i
);
167 T
* res
= dynamic_cast< T
* >( st
);
168 if( res
== NullPtr
< T
>( ) )
170 throw Exceptions::CoreStateTypeMismatch( callLoc
, coreTitle
, args
.getStateLoc( i
), st
->getTypeName( ), T::staticTypeName( ) );
177 down_cast_CoreDynamic( const char * coreTitle
, const char * id
, const RefCountPtr
< const Lang::Value
> & val
, const Ast::SourceLocation
& callLoc
)
179 RefCountPtr
< T
> res
= val
.down_cast
< T
>( );
180 if( res
== NullPtr
< T
>( ) )
182 throw Exceptions::CoreDynamicTypeMismatch( callLoc
, coreTitle
, id
, val
->getTypeName( ), T::staticTypeName( ) );
189 try_cast_CoreArgument( const RefCountPtr
< const Lang::Value
> & val
, bool voidIsNull
= false )
191 RefCountPtr
< T
> res
= val
.down_cast
< T
>( );
192 if( res
== NullPtr
< T
>( ) )
195 dynamic_cast< const Lang::Void
* >( val
.getPtr( ) ) == 0 )
197 throw NonLocalExit::NotThisType( );
205 try_cast_CoreState( Kernel::StateHandle st
)
207 T
* res
= dynamic_cast< T
* >( st
);
208 if( res
== NullPtr
< T
>( ) )
210 throw NonLocalExit::NotThisType( );
217 mutator_cast_self( Kernel::StateHandle st
)
219 T
* res
= dynamic_cast< T
* >( st
);
220 if( res
== NullPtr
< T
>( ) )
222 throw Exceptions::InternalError( "Type of self state does not match mutator signature." );
233 class Transform2D
: public Lang::Value
240 Concrete::Length xt_
;
241 Concrete::Length yt_
;
242 Transform2D( double xx
, double yx
, double xy
, double yy
,
243 Concrete::Length xt
, Concrete::Length yt
);
244 Transform2D( const Lang::Transform2D
& tf2
, const Lang::Transform2D
& tf1
);
245 virtual ~Transform2D( );
246 virtual Kernel::VariableHandle
getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const;
247 Transform2D
* clone( ) const;
248 bool isIdentity( ) const;
249 bool isTranslation( ) const;
250 void write_gsl_matrix( gsl_matrix
* matrix_2_2
) const;
251 void write_gsl_vector( gsl_vector
* vec_2
) const;
252 void shipout( std::ostream
& os
) const;
253 void replaceBy( const Lang::Transform2D
& newtf
); // to be used by text moveto commands
254 void prependShift( const Concrete::Coords2D
& d
); // to be used by text newline commands
255 void prependXShift( const Concrete::Length
& dx
); // to be used by text painting commands
257 virtual void gcMark( Kernel::GCMarkedSet
& marked
){ };
258 virtual void show( std::ostream
& os
) const;
262 class Transform3D
: public Lang::Value
264 static const int N
= 3;
265 mutable gsl_matrix
* planeNormalTransformData_
;
276 Concrete::Length xt_
;
277 Concrete::Length yt_
;
278 Concrete::Length zt_
;
279 Transform3D( double xx
, double yx
, double zx
, double xy
, double yy
, double zy
, double xz
, double yz
, double zz
,
280 Concrete::Length xt
, Concrete::Length yt
, Concrete::Length zt
);
281 Transform3D( const gsl_matrix
* matrix_3_3
, const gsl_vector
* vec_3
);
282 Transform3D( const Lang::Transform3D
& tf2
, const Lang::Transform3D
& tf1
);
283 virtual ~Transform3D( );
284 virtual Kernel::VariableHandle
getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const;
285 Transform3D
* clone( ) const;
286 bool isIdentity( ) const;
287 bool isTranslation( ) const;
288 Concrete::UnitFloatTriple
transformPlaneUnitNormal( const Concrete::UnitFloatTriple
& n
) const;
289 void write_gsl_matrix( gsl_matrix
* matrix_3_3
) const;
290 void write_gsl_vector( gsl_vector
* vec_3
) const;
292 virtual void gcMark( Kernel::GCMarkedSet
& marked
){ };
293 virtual void show( std::ostream
& os
) const;
297 class Function
: public Lang::Value
300 Kernel::EvaluatedFormals
* formals_
; // the reason that this is not const is only to allow convenient setup
301 virtual void analyze_impl( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
, Ast::StateIDSet
* freeStatesDst
);
303 Function( Kernel::EvaluatedFormals
* formals
);
304 virtual ~Function( );
305 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const = 0;
306 virtual Kernel::ValueRef
transformed( const Lang::Transform2D
& tf
, Kernel::ValueRef self
) const;
307 virtual bool isTransforming( ) const = 0;
308 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const;
309 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const;
310 virtual Kernel::Arguments
newCurriedArguments( ) const;
311 virtual void call( Kernel::EvalState
* evalState
, const Kernel::ValueRef
& arg1
, const Ast::SourceLocation
& callLoc
) const;
312 virtual void call( Kernel::EvalState
* evalState
, const Kernel::ValueRef
& arg1
, const Kernel::ValueRef
& arg2
, const Ast::SourceLocation
& callLoc
) const;
313 virtual void call( const RefCountPtr
< const Lang::Function
> & selfRef
, Kernel::EvalState
* evalState
, const Kernel::VariableHandle
& arg1
, const Ast::SourceLocation
& callLoc
) const;
314 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;
315 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;
317 void analyze( Ast::Node
* parent
, Ast::AnalysisEnvironment
* env
);
322 static Ast::ArgListExprs
* oneExprArgList
;
323 static Ast::ArgListExprs
* twoExprsArgList
;
326 class CuteFunction
: public Lang::Function
328 RefCountPtr
< const Lang::Function
> callee_
;
329 Kernel::Arguments someArgs_
;
331 CuteFunction( RefCountPtr
< const Lang::Function
> _callee
, const Kernel::Arguments
& _someArgs
);
332 virtual ~CuteFunction( );
333 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const;
334 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const;
335 virtual Kernel::Arguments
newCurriedArguments( ) const;
336 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
337 virtual void show( std::ostream
& os
) const;
338 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
339 virtual bool isTransforming( ) const;
342 class ComposedFunction
: public Lang::Function
344 RefCountPtr
< const Lang::Function
> second_
;
345 RefCountPtr
< const Lang::Function
> first_
;
347 ComposedFunction( const RefCountPtr
< const Lang::Function
> & _second
, const RefCountPtr
< const Lang::Function
> & _first
);
348 virtual ~ComposedFunction( );
349 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
) const;
350 virtual RefCountPtr
< Kernel::CallContInfo
> newCallContInfo( const Ast::ArgListExprs
* argList
, const Kernel::EvalState
& evalState
, const Kernel::Arguments
& curryArgs
) const;
351 virtual Kernel::Arguments
newCurriedArguments( ) const;
352 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
353 virtual bool isTransforming( ) const;
354 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
355 virtual void show( std::ostream
& os
) const;
358 class UserFunction
: public Lang::Function
360 Ast::Expression
* body_
;
361 Kernel::PassedEnv env_
;
362 Ast::FunctionMode functionMode_
;
364 UserFunction( Kernel::EvaluatedFormals
* _formals
, Ast::Expression
* _body
, Kernel::PassedEnv _env
, const Ast::FunctionMode
& _functionMode
);
365 virtual ~UserFunction( );
366 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
367 virtual bool isTransforming( ) const;
368 virtual void show( std::ostream
& os
) const;
369 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
370 Ast::Expression
* body( ); /* Will typically require a const_cast to be callable. */
373 class TransformedFunction2D
: public Lang::Function
375 Lang::Transform2D tf_
;
376 RefCountPtr
< const Lang::Function
> fun_
;
378 TransformedFunction2D( const Lang::Transform2D
& _tf
, const RefCountPtr
< const Lang::Function
> & _fun
);
379 virtual ~TransformedFunction2D( );
380 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
381 virtual void show( std::ostream
& os
) const;
382 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
383 virtual bool isTransforming( ) const;
386 class VectorFunction
: public Lang::Function
388 RefCountPtr
< const std::vector
< Kernel::ValueRef
> > mem_
;
389 mutable RefCountPtr
< const std::vector
< double > > memNumeric_
;
390 static const char * title_
;
392 VectorFunction( const std::vector
< Kernel::ValueRef
> * mem
);
393 virtual ~VectorFunction( );
394 virtual Kernel::VariableHandle
getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const;
395 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
396 virtual void show( std::ostream
& os
) const;
397 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
398 virtual bool isTransforming( ) const;
399 RefCountPtr
< const std::vector
< double > > getNumeric( const Ast::SourceLocation
& callLoc
) const;
402 class ColorInterpolator
: public Lang::Function
405 typedef std::vector
< double > KeyContainer
;
406 typedef std::vector
< Concrete::RGB
> RGBContainer
;
407 typedef std::vector
< Concrete::Gray
> GrayContainer
;
408 typedef std::vector
< Concrete::CMYK
> CMYKContainer
;
409 enum ColorType
{ UNDEFINED
, RGB
, GRAY
, CMYK
};
412 RefCountPtr
< const KeyContainer
> key_
;
413 RefCountPtr
< const RGBContainer
> RGBcolor_
;
414 RefCountPtr
< const GrayContainer
> graycolor_
;
415 RefCountPtr
< const CMYKContainer
> CMYKcolor_
;
416 static const char * title_
;
417 ColorType colorType_
;
420 ColorInterpolator( const RefCountPtr
< KeyContainer
> & key
,
421 const RefCountPtr
< RGBContainer
> & RGBcolor
,
422 const RefCountPtr
< GrayContainer
> & graycolor
,
423 const RefCountPtr
< CMYKContainer
> & CMYKcolor
,
424 ColorType colorType
);
425 virtual ~ColorInterpolator( );
426 virtual Kernel::VariableHandle
getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const;
427 virtual void gcMark( Kernel::GCMarkedSet
& marked
);
428 virtual void show( std::ostream
& os
) const;
429 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
430 virtual bool isTransforming( ) const;
433 template <class COLOR_TYPE
, class COLOR_CONTAINER
>
434 void callHelper( Kernel::EvalState
* evalState
, const RefCountPtr
< COLOR_CONTAINER
> & colorContainer
,
435 double key
, KeyContainer::const_iterator keyHi
) const;
439 class BinaryOperatorFunction
: public Lang::Function
441 Ast::BinaryInfixExpr
* opExpr_
;
444 BinaryOperatorFunction( Ast::BinaryInfixExpr
* opExpr
, const char * title
);
445 virtual ~BinaryOperatorFunction( );
446 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
447 virtual bool isTransforming( ) const;
448 virtual void gcMark( Kernel::GCMarkedSet
& marked
){ };
449 virtual void show( std::ostream
& os
) const;
452 class UnaryOperatorFunction
: public Lang::Function
454 Ast::UnaryExpr
* opExpr_
;
457 UnaryOperatorFunction( Ast::UnaryExpr
* opExpr
, const char * title
);
458 virtual ~UnaryOperatorFunction( );
459 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
460 virtual bool isTransforming( ) const;
461 virtual void gcMark( Kernel::GCMarkedSet
& marked
){ };
462 virtual void show( std::ostream
& os
) const;