Adjust to updated function signature in libpng.
[shapes.git] / source / functiontypes.h
blob3dfd77bb94e6540963516a754b2373000be84c60
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
6 * any later version.
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
19 #pragma once
21 #include "Shapes_Lang_decls.h"
22 #include "Shapes_Kernel_decls.h"
23 #include "Shapes_Ast_decls.h"
25 #include "shapesvalue.h"
26 #include "ptrowner.h"
27 #include "refcount.h"
28 #include "pdfstructure.h"
29 #include "environment.h"
30 #include "charptrless.h"
31 #include "consts.h"
32 #include "elementarytypes.h"
33 #include "elementarycoords.h"
35 #include <list>
36 #include <iostream>
37 #include <stack>
38 #include <set>
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( ) );\
50 namespace Shapes
53 namespace Kernel
56 class Arguments
58 const Kernel::EvaluatedFormals * formals_;
59 Environment::ValueVector variables_;
60 std::vector< const Ast::Node * > locations_;
61 size_t dst_;
62 bool hasSink_;
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_;
72 size_t stateDst_;
74 Kernel::StateHandle mutatorSelf_;
76 public:
77 Arguments( const Kernel::EvaluatedFormals * formals );
78 ~Arguments( );
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;
97 size_t size( ) const;
98 bool empty( ) 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_;
115 bool forceAll_;
116 public:
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_;
120 bool isSink_;
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. */
143 namespace Helpers
146 template< class T >
147 RefCountPtr< T >
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 >( ) )
154 if( ! voidIsNull ||
155 dynamic_cast< const Lang::Void * >( val.getPtr( ) ) == 0 )
157 throw Exceptions::CoreTypeMismatch( callLoc, coreTitle, args.getLoc( i ), val->getTypeName( ), T::staticTypeName( ) );
160 return res;
163 template< class T >
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( ) );
173 return res;
176 template< class T >
177 RefCountPtr< T >
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( ) );
185 return res;
188 template< class T >
189 RefCountPtr< T >
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 >( ) )
195 if( ! voidIsNull ||
196 dynamic_cast< const Lang::Void * >( val.getPtr( ) ) == 0 )
198 throw NonLocalExit::NotThisType( );
201 return res;
204 template< class T >
206 try_cast_CoreState( Kernel::StateHandle st )
208 T * res = dynamic_cast< T * >( st );
209 if( res == NullPtr< T >( ) )
211 throw NonLocalExit::NotThisType( );
213 return res;
216 template< class T >
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." );
225 return res;
231 namespace Lang
234 class Transform2D : public Lang::Value
236 public:
237 double xx_;
238 double yx_;
239 double xy_;
240 double yy_;
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
259 TYPEINFODECL;
260 virtual void gcMark( Kernel::GCMarkedSet & marked ){ };
261 virtual void show( std::ostream & os ) const;
262 DISPATCHDECL;
265 class Transform3D : public Lang::Value
267 static const int N = 3;
268 mutable gsl_matrix * planeNormalTransformData_;
269 public:
270 double xx_;
271 double yx_;
272 double zx_;
273 double xy_;
274 double yy_;
275 double zy_;
276 double xz_;
277 double yz_;
278 double zz_;
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;
294 TYPEINFODECL;
295 virtual void gcMark( Kernel::GCMarkedSet & marked ){ };
296 virtual void show( std::ostream & os ) const;
297 DISPATCHDECL;
300 class Function : public Lang::Value
302 protected:
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 );
305 public:
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 );
322 TYPEINFODECL;
323 DISPATCHDECL;
324 private:
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_;
333 public:
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_;
349 public:
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_;
364 public:
365 Span( const Kernel::VariableHandle & begin, const Kernel::VariableHandle & end, const Kernel::VariableHandle & step, const Kernel::VariableHandle & count );
366 virtual ~Span( );
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;
371 TYPEINFODECL;
374 class UserFunction : public Lang::Function
376 Ast::Expression * body_;
377 Kernel::PassedEnv env_;
378 Ast::FunctionMode functionMode_;
379 public:
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_;
393 public:
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
404 public:
405 typedef std::vector< Kernel::ValueRef > vector_type;
406 private:
407 RefCountPtr< const vector_type > mem_;
408 mutable RefCountPtr< const std::vector< double > > memNumeric_;
409 mutable Kernel::VariableHandle list_;
410 static const char * title_;
411 public:
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 );
445 TYPEINFODECL;
446 private:
447 void compute_list( ) const; /* This will modify mutable data! */
450 class ColorInterpolator : public Lang::Function
452 public:
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 };
459 private:
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_;
467 public:
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;
480 private:
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_;
490 const char * title_;
491 public:
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_;
503 const char * title_;
504 public:
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;