Example: Changed glyph-outline.shape for use with FontConfig.
[shapes.git] / source / coreast.cc
blob22d7667b5eb7fb93c3effd39ff842b910f763d7d
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 #include <cmath>
21 #include "Shapes_Helpers_decls.h"
23 #include "shapescore.h"
24 #include "continuations.h"
25 #include "globals.h"
26 #include "texlabelmanager.h"
27 #include "shapesexceptions.h"
29 using namespace Shapes;
32 namespace Shapes
34 namespace Lang
37 class Core_TeX : public Lang::CoreFunction
39 public:
40 Core_TeX( const char * title )
41 : CoreFunction( title )
42 { }
43 virtual void
44 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
46 const size_t ARITY = 1;
47 CHECK_ARITY( args, ARITY, title_ );
49 typedef const Lang::String ArgType;
50 RefCountPtr< ArgType > arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, 0, callLoc );
52 Kernel::ContRef cont = evalState->cont_;
53 cont->takeValue( Kernel::theTeXLabelManager.request( std::string( arg->val_.getPtr( ) ), args.getLoc( 0 ), evalState->dyn_ ),
54 evalState );
58 class Core_Unicode : public Lang::CoreFunction
60 public:
61 Core_Unicode( const char * title )
62 : CoreFunction( title )
63 { }
64 virtual void
65 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
67 const size_t ARITY = 1;
68 CHECK_ARITY( args, ARITY, title_ );
70 size_t argsi = 0;
71 typedef const Lang::Integer ArgType;
72 ArgType::ValueType arg = Helpers::down_cast_CoreArgument< ArgType >( title_, args, argsi, callLoc )->val_;
73 if( arg < 0 )
75 throw Exceptions::CoreOutOfRange( title_, args, argsi, "Unicode code points cannot be negative." );
78 Kernel::ContRef cont = evalState->cont_;
79 cont->takeValue( Kernel::ValueRef( new Lang::Character( arg ) ),
80 evalState );
84 class Core_coords2D : public Lang::CoreFunction
86 public:
87 Core_coords2D( const char * title )
88 : CoreFunction( title )
89 { }
90 virtual void
91 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
93 const size_t ARITY = 2;
94 CHECK_ARITY( args, ARITY, title_ );
96 RefCountPtr< const Lang::Value > xUntyped = args.getValue( 0 );
97 RefCountPtr< const Lang::Value > yUntyped = args.getValue( 1 );
100 typedef const Lang::Float ArgType;
101 ArgType * xVal = dynamic_cast< ArgType * >( xUntyped.getPtr( ) );
102 if( xVal != 0 )
104 ArgType * yVal = dynamic_cast< ArgType * >( yUntyped.getPtr( ) );
105 if( yVal == 0 )
107 if( xVal->val_ == 0 )
109 /* This is a special case, where 0 is interpreted as a length.
111 typedef const Lang::Length ArgTypeY;
112 ArgTypeY * yVal = dynamic_cast< ArgTypeY * >( yUntyped.getPtr( ) );
113 if( yVal != 0 )
115 Kernel::ContRef cont = evalState->cont_;
116 cont->takeValue( Kernel::ValueRef( new Lang::Coords2D( Lang::Length( 0 ), *yVal ) ),
117 evalState );
118 return;
121 throw Exceptions::CoreTypeMismatch( callLoc, "(<>, y )", args, 1, ArgType::staticTypeName( ) );
124 Kernel::ContRef cont = evalState->cont_;
125 cont->takeValue( Kernel::ValueRef( new Lang::FloatPair( xVal->val_, yVal->val_ ) ),
126 evalState );
127 return;
132 typedef const Lang::Length ArgType;
133 ArgType * xVal = dynamic_cast< ArgType * >( xUntyped.getPtr( ) );
134 if( xVal != 0 )
136 ArgType * yVal = dynamic_cast< ArgType * >( yUntyped.getPtr( ) );
137 if( yVal == 0 )
139 /* A Float with value 0 is still allowed
141 typedef const Lang::Float ArgTypeY;
142 ArgTypeY * yVal = dynamic_cast< ArgTypeY * >( yUntyped.getPtr( ) );
143 if( yVal != 0 )
145 if( yVal->val_ == 0 )
147 Kernel::ContRef cont = evalState->cont_;
148 cont->takeValue( Kernel::ValueRef( new Lang::Coords2D( *xVal, Lang::Length( 0 ) ) ),
149 evalState );
150 return;
153 throw Exceptions::CoreTypeMismatch( callLoc, "(<>, y )", args, 1, ArgType::staticTypeName( ) );
156 Kernel::ContRef cont = evalState->cont_;
157 cont->takeValue( Kernel::ValueRef( new Lang::Coords2D( *xVal, *yVal ) ),
158 evalState );
159 return;
163 throw Exceptions::CoreTypeMismatch( callLoc, "( x ,<>)", args, 0, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
167 class Core_cornercoords2D : public Lang::CoreFunction
169 public:
170 Core_cornercoords2D( const char * title )
171 : CoreFunction( title )
173 virtual void
174 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
177 * We don't check for presence of named arguments here since this function is generally called internally, and
178 * we don't want the extra overhead of an unnecessary check.
181 Kernel::ContRef cont = evalState->cont_;
182 switch( args.size( ) )
184 case 2:
185 cont->takeValue( Kernel::ValueRef( new Lang::CornerCoords2D( * Helpers::down_cast_CoreArgument< const Lang::Length >( "( x, <> ^ )", args, 0, callLoc ),
186 * Helpers::down_cast_CoreArgument< const Lang::Length >( "( <>, y ^ )", args, 1, callLoc ),
187 std::numeric_limits< double >::signaling_NaN( ) ) ),
188 evalState );
189 break;
190 case 3:
191 cont->takeValue( Kernel::ValueRef( new Lang::CornerCoords2D( * Helpers::down_cast_CoreArgument< const Lang::Length >( "( x, <> ^ <> )", args, 0, callLoc ),
192 * Helpers::down_cast_CoreArgument< const Lang::Length >( "( <>, y ^ <> )", args, 1, callLoc ),
193 Helpers::down_cast_CoreArgument< const Lang::Float >( "( <>, <> ^ a )", args, 2, callLoc )->val_ ) ),
194 evalState );
195 break;
196 default:
197 throw Exceptions::CoreArityMismatch( title_, 2, 3, args.size( ) );
203 class Core_coords3D : public Lang::CoreFunction
205 public:
206 Core_coords3D( const char * title )
207 : CoreFunction( title )
209 virtual void
210 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
212 const size_t ARITY = 3;
213 CHECK_ARITY( args, ARITY, title_ );
215 RefCountPtr< const Lang::Value > xUntyped = args.getValue( 0 );
216 RefCountPtr< const Lang::Value > yUntyped = args.getValue( 1 );
217 RefCountPtr< const Lang::Value > zUntyped = args.getValue( 2 );
220 typedef const Lang::Float ArgType;
221 ArgType * xVal = dynamic_cast< ArgType * >( xUntyped.getPtr( ) );
222 if( xVal != 0 )
224 Kernel::ContRef cont = evalState->cont_;
225 cont->takeValue( Kernel::ValueRef( new Lang::FloatTriple( xVal->val_,
226 Helpers::down_cast_CoreArgument< ArgType >( "(<>, y ,<>)", args, 1, callLoc )->val_,
227 Helpers::down_cast_CoreArgument< ArgType >( "(<>,<>, z )", args, 2, callLoc )->val_ ) ),
228 evalState );
229 return;
234 typedef const Lang::Length ArgType;
235 ArgType * xVal = dynamic_cast< ArgType * >( xUntyped.getPtr( ) );
236 if( xVal != 0 )
238 Kernel::ContRef cont = evalState->cont_;
239 cont->takeValue( Kernel::ValueRef( new Lang::Coords3D( *xVal,
240 * Helpers::down_cast_CoreArgument< ArgType >( "(<>, y ,<>)", args, 1, callLoc ),
241 * Helpers::down_cast_CoreArgument< ArgType >( "(<>,<>, z )", args, 2, callLoc ) ) ),
242 evalState );
243 return;
247 throw Exceptions::CoreTypeMismatch( callLoc, "( x ,<>,<>)", args, 0, Helpers::typeSetString( Lang::Float::staticTypeName( ), Lang::Length::staticTypeName( ) ) );
251 class Core_polarHandle2DFree_r : public Lang::CoreFunction
253 public:
254 Core_polarHandle2DFree_r( const char * title )
255 : CoreFunction( title )
257 virtual void
258 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
260 const size_t ARITY = 1;
261 CHECK_ARITY( args, ARITY, title_ );
263 Kernel::ContRef cont = evalState->cont_;
264 cont->takeValue( Kernel::ValueRef( new Lang::PolarHandle2DFree_r( evalState->dyn_->getDefaultUnit( ),
265 Helpers::down_cast_CoreArgument< const Lang::Float >( "(^ a )", args, 0, callLoc )->val_ ) ),
266 evalState );
270 class Core_polarHandle2DFree_ra : public Lang::CoreFunction
272 public:
273 Core_polarHandle2DFree_ra( const char * title )
274 : CoreFunction( title )
276 virtual void
277 call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
279 const size_t ARITY = 0;
280 CHECK_ARITY( args, ARITY, title_ );
282 Kernel::ContRef cont = evalState->cont_;
283 cont->takeValue( Kernel::ValueRef( new Lang::PolarHandle2DFree_ra( evalState->dyn_->getDefaultUnit( ) ) ),
284 evalState );
293 RefCountPtr< const Lang::CoreFunction > Ast::THE_FUNCTION_coords2D( new Lang::Core_coords2D( "coords" ) );
294 RefCountPtr< const Lang::CoreFunction > Ast::THE_FUNCTION_cornercoords2D( new Lang::Core_cornercoords2D( "cornercoords" ) );
295 RefCountPtr< const Lang::CoreFunction > Ast::THE_FUNCTION_coords3D( new Lang::Core_coords3D( "coords3D" ) );
296 RefCountPtr< const Lang::CoreFunction > Ast::THE_FUNCTION_polarHandle2DFree_r( new Lang::Core_polarHandle2DFree_r( "polarHandleFree_r" ) );
297 RefCountPtr< const Lang::CoreFunction > Ast::THE_FUNCTION_polarHandle2DFree_ra( new Lang::Core_polarHandle2DFree_ra( "polarHandleFree_ra" ) );
298 /* This belongs in consts.cc but we must make sure it is initialized before we use it below. Note that the identifier will actually be destroyed
299 * before Ast::THE_FUNCTION_TeX is destroyed, but that should not cause a failure...
301 RefCountPtr< const char > Lang::TEX_SYNTAX_ID = strrefdup( "TeX" );
302 RefCountPtr< const Lang::CoreFunction > Ast::THE_FUNCTION_TeX( new Lang::Core_TeX( Lang::TEX_SYNTAX_ID.getPtr( ) ) );
303 RefCountPtr< const Lang::CoreFunction > Ast::THE_FUNCTION_Unicode( new Lang::Core_Unicode( "Unicode" ) );