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, 2014 Henrik Tidefelt
21 #include "shapescore.h"
23 #include "shapesexceptions.h"
25 #include "simplepdfi.h"
27 #include "continuations.h"
28 #include "multipage.h"
38 using namespace Shapes
;
46 class NullFunction
: public Lang::CoreFunction
49 NullFunction( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
50 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
52 Kernel::ContRef cont
= evalState
->cont_
;
53 cont
->takeValue( Lang::THE_VOID
,
58 class Core_identity
: public Lang::CoreFunction
61 Core_identity( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
62 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
64 const size_t ARITY
= 1;
65 CHECK_ARITY( args
, ARITY
, id_
);
67 Kernel::ContRef cont
= evalState
->cont_
;
68 cont
->takeHandle( args
.getHandle( 0 ),
73 class Core_typeof
: public Lang::CoreFunction
76 Core_typeof( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
77 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
79 const size_t ARITY
= 1;
80 CHECK_ARITY( args
, ARITY
, id_
);
82 Kernel::ContRef cont
= evalState
->cont_
;
83 cont
->takeValue( args
.getValue( 0 )->getClass( ),
88 class Core_error
: public Lang::CoreFunction
91 Core_error( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
92 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
94 formals_
->appendEvaluatedCoreFormal( "kind", Kernel::THE_SLOT_VARIABLE
);
95 formals_
->appendEvaluatedCoreFormal( "source", Kernel::THE_SLOT_VARIABLE
);
96 formals_
->appendEvaluatedCoreFormal( "message", Kernel::THE_SLOT_VARIABLE
);
97 formals_
->appendEvaluatedCoreFormal( "details", Kernel::THE_VOID_VARIABLE
);
98 formals_
->appendEvaluatedCoreFormal( "cause", Kernel::THE_VOID_VARIABLE
);
100 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
102 args
.applyDefaults( callLoc
);
104 static Lang::Symbol
OUT_OF_RANGE( "out_of_range" );
105 static Lang::Symbol
TYPE_MISMATCH( "type_mismatch" );
106 static Lang::Symbol
MISC( "misc" );
107 static Lang::Symbol
EXTERNAL( "external" );
108 static Lang::Symbol
PDF_VERSION( "PDF_version" );
109 static Lang::Symbol
DTMIN( "dtmin" );
110 static Lang::Symbol
NUMERIC( "numeric" );
113 typedef const Lang::Symbol KindType
;
114 RefCountPtr
< KindType
> kind
= Helpers::down_cast_CoreArgument
< KindType
>( id_
, args
, argsi
, callLoc
);
117 typedef const Lang::String SourceType
;
118 RefCountPtr
< SourceType
> source
= Helpers::down_cast_CoreArgument
< SourceType
>( id_
, args
, argsi
, callLoc
);
121 typedef const Lang::String MessageType
;
122 RefCountPtr
< MessageType
> message
= Helpers::down_cast_CoreArgument
< MessageType
>( id_
, args
, argsi
, callLoc
);
125 size_t details_argsi
= argsi
;
128 size_t cause_argsi
= argsi
;
130 Kernel::VariableHandle cause
= args
.getHandle( argsi
);
131 if( *kind
!= TYPE_MISMATCH
&&
132 cause
!= Kernel::THE_VOID_VARIABLE
)
134 throw Exceptions::CoreRequirement( "The argument <cause> must not be provided for the given value of <kind>.", id_
, callLoc
);
138 if( *kind
== OUT_OF_RANGE
)
140 typedef const Lang::Integer DetailsType
;
141 RefCountPtr
< DetailsType
> details
= Helpers::down_cast_CoreArgument
< DetailsType
>( id_
, args
, details_argsi
, callLoc
);
142 throw Exceptions::UserOutOfRange( kind
, source
, details
, message
->val_
);
144 else if( *kind
== TYPE_MISMATCH
)
146 typedef const Lang::Integer DetailsType
;
147 RefCountPtr
< DetailsType
> details
= Helpers::down_cast_CoreArgument
< DetailsType
>( id_
, args
, details_argsi
, callLoc
);
149 throw Exceptions::UserTypeMismatch( kind
, source
, details
, message
->val_
, args
.getValue( cause_argsi
)->getTypeName( ) );
151 else if( *kind
== MISC
||
153 *kind
== PDF_VERSION
||
156 Kernel::VariableHandle details
= args
.getHandle( details_argsi
);
157 if( details
!= Kernel::THE_VOID_VARIABLE
)
159 throw Exceptions::CoreRequirement( "The argument <details> must not be provided for the given value of <kind>.", id_
, callLoc
);
162 throw Exceptions::UserError( kind
, source
, args
.getValue( details_argsi
), message
->val_
);
164 else if( *kind
== DTMIN
)
166 typedef const Lang::Float DetailsType
;
167 RefCountPtr
< DetailsType
> details
= Helpers::down_cast_CoreArgument
< DetailsType
>( id_
, args
, details_argsi
, callLoc
);
169 throw Exceptions::UserError( kind
, source
, details
, message
->val_
);
173 throw Exceptions::UserError( kind
, source
, args
.getValue( details_argsi
), message
->val_
);
179 class Core_show
: public Lang::CoreFunction
182 Core_show( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
184 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
186 std::ostringstream oss
;
187 for( size_t i
= 0; i
!= args
.size( ); ++i
)
189 args
.getValue( i
)->show( oss
);
191 Kernel::ContRef cont
= evalState
->cont_
;
192 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::String( strrefdup( oss
) ) ),
197 class Core_typename
: public Lang::CoreFunction
200 Core_typename( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
202 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
204 const size_t ARITY
= 1;
205 CHECK_ARITY( args
, ARITY
, id_
);
207 Kernel::ContRef cont
= evalState
->cont_
;
208 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::String( args
.getValue( 0 )->getTypeName( ) ) ),
213 class Core_debuglog_before
: public Lang::CoreFunction
216 Core_debuglog_before( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
217 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
) ) )
219 formals_
->appendEvaluatedCoreFormal( "msg", Kernel::THE_SLOT_VARIABLE
, true );
220 formals_
->appendEvaluatedCoreFormal( "result", Kernel::THE_SLOT_VARIABLE
, false );
223 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
225 args
.applyDefaults( callLoc
);
227 args
.getValue( 0 )->show( Kernel::theDebugLog
.os( ) );
228 Kernel::theDebugLog
.os( ) << std::flush
;
230 Kernel::ContRef cont
= evalState
->cont_
;
231 cont
->takeHandle( args
.getHandle( 1 ),
236 class Core_debuglog_after
: public Lang::CoreFunction
239 Core_debuglog_after( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
240 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
) ) )
242 formals_
->appendEvaluatedCoreFormal( "msg", Kernel::THE_SLOT_VARIABLE
, true );
243 formals_
->appendEvaluatedCoreFormal( "result", Kernel::THE_SLOT_VARIABLE
, true );
246 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
248 args
.applyDefaults( callLoc
);
250 args
.getValue( 0 )->show( Kernel::theDebugLog
.os( ) );
251 Kernel::theDebugLog
.os( ) << std::flush
;
253 Kernel::ContRef cont
= evalState
->cont_
;
254 cont
->takeValue( args
.getValue( 1 ),
259 class Core_if
: public Lang::CoreFunction
262 Core_if( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
263 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
) ) )
265 formals_
->appendEvaluatedCoreFormal( "predicate", Kernel::THE_SLOT_VARIABLE
, true );
266 formals_
->appendEvaluatedCoreFormal( "consequence", Kernel::THE_SLOT_VARIABLE
, false );
267 formals_
->appendEvaluatedCoreFormal( "alternative", Kernel::VariableHandle( new Kernel::Variable( Lang::THE_VOID
) ), false );
271 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
273 args
.applyDefaults( callLoc
);
275 evalState
->cont_
= Kernel::ContRef( new Kernel::IfContinuation( args
.getHandle( 1 ), args
.getHandle( 2 ), evalState
->cont_
, callLoc
) );
277 Kernel::ContRef cont
= evalState
->cont_
;
278 cont
->takeHandle( args
.getHandle( 0 ), evalState
);
282 class Core_memoryinfo
: public Lang::CoreFunction
285 Core_memoryinfo( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
287 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
289 const size_t ARITY
= 0;
290 CHECK_ARITY( args
, ARITY
, id_
);
291 std::cerr
<< "Environments: alive: " << Kernel::Environment::liveCount
<< " of total: " << Kernel::Environment::createdCount
292 << " (" << 100 * static_cast< double >( Kernel::Environment::liveCount
) / static_cast< double >( Kernel::Environment::createdCount
) << "%)" << std::endl
;
293 Kernel::ContRef cont
= evalState
->cont_
;
294 cont
->takeHandle( Kernel::THE_VOID_VARIABLE
,
299 class Core_rectangle
: public Lang::CoreFunction
302 Core_rectangle( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
304 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
306 const size_t ARITY
= 2;
307 CHECK_ARITY( args
, ARITY
, id_
);
309 typedef const Lang::Coords2D ArgType
;
311 RefCountPtr
< ArgType
> arg1
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 0, callLoc
);
312 RefCountPtr
< ArgType
> arg2
= Helpers::down_cast_CoreArgument
< ArgType
>( id_
, args
, 1, callLoc
);
314 Lang::ElementaryPath2D
* res
= new Lang::ElementaryPath2D
;
316 res
->push_back( new Concrete::PathPoint2D( arg1
->x_
.get( ), arg1
->y_
.get( ) ) );
317 res
->push_back( new Concrete::PathPoint2D( arg2
->x_
.get( ), arg1
->y_
.get( ) ) );
318 res
->push_back( new Concrete::PathPoint2D( arg2
->x_
.get( ), arg2
->y_
.get( ) ) );
319 res
->push_back( new Concrete::PathPoint2D( arg1
->x_
.get( ), arg2
->y_
.get( ) ) );
322 Kernel::ContRef cont
= evalState
->cont_
;
323 cont
->takeValue( Kernel::ValueRef( res
),
328 class Core_hot
: public Lang::CoreFunction
331 Core_hot( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
332 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
334 formals_
->appendEvaluatedCoreFormal( "init", Kernel::THE_SLOT_VARIABLE
);
335 formals_
->appendEvaluatedCoreFormal( "tackon", Kernel::THE_SLOT_VARIABLE
);
336 formals_
->appendEvaluatedCoreFormal( "freeze", Kernel::VariableHandle( new Kernel::Variable( Lang::THE_IDENTITY
) ) );
340 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
342 args
.applyDefaults( callLoc
);
344 Kernel::ContRef cont
= evalState
->cont_
;
345 cont
->takeValue( Kernel::ValueRef( new Lang::HotTriple
346 ( args
.getValue( 0 ),
347 Helpers::down_cast_CoreArgument
< const Lang::Function
>( id_
, args
, 1, callLoc
),
348 Helpers::down_cast_CoreArgument
< const Lang::Function
>( id_
, args
, 2, callLoc
) ) ),
353 class Core_ampersand_dynamic
: public Lang::CoreFunction
356 Core_ampersand_dynamic( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
)
357 : CoreFunction( ns
, name
, new Kernel::EvaluatedFormals( Ast::FileID::build_internal( name
), true ) )
362 call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
364 // args.applyDefaults( callLoc );
366 * Here, we should check that there are no named arguments, and that there are no states being passed...
369 RefCountPtr
< const Lang::DynamicBindings
> res
= RefCountPtr
< const Lang::DynamicBindings
>( new Lang::DynamicBindingsNull( ) );
371 for( size_t i
= 0; i
!= args
.size( ); ++i
)
373 res
= RefCountPtr
< const Lang::DynamicBindings
>
374 ( new Lang::DynamicBindingsPair( Helpers::down_cast_CoreArgument
< const Lang::DynamicBindings
>( id_
, args
, args
.size( ) - 1 - i
, callLoc
, true ),
378 Kernel::ContRef cont
= evalState
->cont_
;
379 cont
->takeValue( res
,
384 class Core_locate
: public Lang::CoreFunction
387 Core_locate( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
388 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
390 const size_t ARITY
= 1;
391 CHECK_ARITY( args
, ARITY
, id_
);
393 RefCountPtr
< const Lang::Value
> res
= args
.getValue( 0 );
394 res
->set_node( args
.getNode( 0 ) );
396 Kernel::ContRef cont
= evalState
->cont_
;
397 cont
->takeValue( res
,
402 class Core_sourceof
: public Lang::CoreFunction
405 Core_sourceof( const RefCountPtr
< const Ast::NamespacePath
> & ns
, const char * name
) : CoreFunction( ns
, name
) { }
406 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
408 const size_t ARITY
= 1;
409 CHECK_ARITY( args
, ARITY
, id_
);
411 const Ast::Node
* node
= args
.getValue( 0 )->node( );
414 throw Exceptions::CoreOutOfRange( id_
, args
, 0, "The value has not been located." );
417 std::ostringstream oss
;
420 node
->loc( ).copy( & oss
);
422 catch( const std::string
& ball
)
424 std::ostringstream msg
;
425 msg
<< "Source of located value could not be copied. Reason: " << ball
;
426 throw Exceptions::CoreOutOfRange( id_
, args
, 0, strrefdup( msg
) );
429 Kernel::ContRef cont
= evalState
->cont_
;
430 cont
->takeValue( RefCountPtr
< const Lang::Value
>( new Lang::String( strrefdup( oss
.str( ) ) ) ),
439 RefCountPtr
< const Lang::CoreFunction
> Lang::THE_IDENTITY( new Lang::Core_identity( Lang::THE_NAMESPACE_Shapes
, "identity" ) );
442 Kernel::registerCore_misc( Kernel::Environment
* env
)
444 env
->initDefineCoreFunction( new Lang::Core_typeof( Lang::THE_NAMESPACE_Shapes
, "typeof" ) );
445 env
->initDefineCoreFunction( new Lang::Core_error( Lang::THE_NAMESPACE_Shapes
, "error" ) );
446 env
->initDefineCoreFunction( new Lang::Core_show( Lang::THE_NAMESPACE_Shapes_String
, "show" ) );
447 env
->initDefineCoreFunction( new Lang::Core_typename( Lang::THE_NAMESPACE_Shapes_Debug
, "typename" ) );
448 env
->initDefineCoreFunction( new Lang::Core_debuglog_before( Lang::THE_NAMESPACE_Shapes_Debug
, "log_before" ) );
449 env
->initDefineCoreFunction( new Lang::Core_debuglog_after( Lang::THE_NAMESPACE_Shapes_Debug
, "log_after" ) );
450 env
->initDefineCoreFunction( new Lang::Core_if( Lang::THE_NAMESPACE_Shapes
, "if" ) );
451 env
->initDefineCoreFunction( new Lang::NullFunction( Lang::THE_NAMESPACE_Shapes
, "ignore" ) );
452 env
->initDefineCoreFunction( new Lang::Core_rectangle( Lang::THE_NAMESPACE_Shapes_Geometry
, "rectangle" ) );
453 env
->initDefineCoreFunction( new Lang::Core_memoryinfo( Lang::THE_NAMESPACE_Shapes_Debug
, "memoryinfo" ) );
454 env
->initDefineCoreFunction( new Lang::Core_hot( Lang::THE_NAMESPACE_Shapes
, "hot" ) );
455 env
->initDefineCoreFunction( new Lang::Core_ampersand_dynamic( Lang::THE_NAMESPACE_Shapes
, "bindings" ) );
457 env
->initDefineCoreFunction( new Lang::Core_locate( Lang::THE_NAMESPACE_Shapes_Debug
, "locate" ) );
458 env
->initDefineCoreFunction( new Lang::Core_sourceof( Lang::THE_NAMESPACE_Shapes_Debug
, "sourceof" ) );