Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / functiontypes.h
blob79acfffb88fd49ac426fc1390cee2ec1e3fcf4fa
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 );
142 namespace Helpers
145 template< class T >
146 RefCountPtr< T >
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 >( ) )
153 if( ! voidIsNull ||
154 dynamic_cast< const Lang::Void * >( val.getPtr( ) ) == 0 )
156 throw Exceptions::CoreTypeMismatch( callLoc, coreTitle, args.getLoc( i ), val->getTypeName( ), T::staticTypeName( ) );
159 return res;
162 template< class T >
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( ) );
172 return res;
175 template< class T >
176 RefCountPtr< T >
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( ) );
184 return res;
187 template< class T >
188 RefCountPtr< T >
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 >( ) )
194 if( ! voidIsNull ||
195 dynamic_cast< const Lang::Void * >( val.getPtr( ) ) == 0 )
197 throw NonLocalExit::NotThisType( );
200 return res;
203 template< class T >
205 try_cast_CoreState( Kernel::StateHandle st )
207 T * res = dynamic_cast< T * >( st );
208 if( res == NullPtr< T >( ) )
210 throw NonLocalExit::NotThisType( );
212 return res;
215 template< class T >
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." );
224 return res;
230 namespace Lang
233 class Transform2D : public Lang::Value
235 public:
236 double xx_;
237 double yx_;
238 double xy_;
239 double yy_;
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
256 TYPEINFODECL;
257 virtual void gcMark( Kernel::GCMarkedSet & marked ){ };
258 virtual void show( std::ostream & os ) const;
259 DISPATCHDECL;
262 class Transform3D : public Lang::Value
264 static const int N = 3;
265 mutable gsl_matrix * planeNormalTransformData_;
266 public:
267 double xx_;
268 double yx_;
269 double zx_;
270 double xy_;
271 double yy_;
272 double zy_;
273 double xz_;
274 double yz_;
275 double zz_;
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;
291 TYPEINFODECL;
292 virtual void gcMark( Kernel::GCMarkedSet & marked ){ };
293 virtual void show( std::ostream & os ) const;
294 DISPATCHDECL;
297 class Function : public Lang::Value
299 protected:
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 );
302 public:
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 );
319 TYPEINFODECL;
320 DISPATCHDECL;
321 private:
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_;
330 public:
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_;
346 public:
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_;
363 public:
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_;
377 public:
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_;
391 public:
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
404 public:
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 };
411 private:
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_;
419 public:
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;
432 private:
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_;
442 const char * title_;
443 public:
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_;
455 const char * title_;
456 public:
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;