Update procedures
[shapes.git] / source / coremisc.cc
blob74740c7a267659855ea7448e508096631b8ab23e
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, 2014 Henrik Tidefelt
19 #include <cmath>
21 #include "shapescore.h"
22 #include "globals.h"
23 #include "shapesexceptions.h"
24 #include "consts.h"
25 #include "simplepdfi.h"
26 #include "astfun.h"
27 #include "continuations.h"
28 #include "multipage.h"
29 #include "debuglog.h"
31 #include <iostream>
32 #include <sstream>
33 #include <fstream>
34 #include <vector>
35 #include <stdio.h>
36 #include <sys/time.h>
38 using namespace Shapes;
41 namespace Shapes
43 namespace Lang
46 class NullFunction : public Lang::CoreFunction
48 public:
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,
54 evalState );
58 class Core_identity : public Lang::CoreFunction
60 public:
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 ),
69 evalState );
73 class Core_typeof : public Lang::CoreFunction
75 public:
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( ),
84 evalState );
88 class Core_error : public Lang::CoreFunction
90 public:
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" );
112 size_t argsi = 0;
113 typedef const Lang::Symbol KindType;
114 RefCountPtr< KindType > kind = Helpers::down_cast_CoreArgument< KindType >( id_, args, argsi, callLoc );
116 ++argsi;
117 typedef const Lang::String SourceType;
118 RefCountPtr< SourceType > source = Helpers::down_cast_CoreArgument< SourceType >( id_, args, argsi, callLoc );
120 ++argsi;
121 typedef const Lang::String MessageType;
122 RefCountPtr< MessageType > message = Helpers::down_cast_CoreArgument< MessageType >( id_, args, argsi, callLoc );
124 ++argsi;
125 size_t details_argsi = argsi;
127 ++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 ||
152 *kind == EXTERNAL ||
153 *kind == PDF_VERSION ||
154 *kind == NUMERIC )
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_ );
171 else
173 throw Exceptions::UserError( kind, source, args.getValue( details_argsi ), message->val_ );
179 class Core_show : public Lang::CoreFunction
181 public:
182 Core_show( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
183 virtual void
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 ) ) ),
193 evalState );
197 class Core_typename : public Lang::CoreFunction
199 public:
200 Core_typename( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
201 virtual void
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( ) ) ),
209 evalState );
213 class Core_debuglog_before : public Lang::CoreFunction
215 public:
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 );
222 virtual void
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 ),
232 evalState );
236 class Core_debuglog_after : public Lang::CoreFunction
238 public:
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 );
245 virtual void
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 ),
255 evalState );
259 class Core_if : public Lang::CoreFunction
261 public:
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 );
270 virtual void
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
284 public:
285 Core_memoryinfo( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
286 virtual void
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,
295 evalState );
299 class Core_rectangle : public Lang::CoreFunction
301 public:
302 Core_rectangle( const RefCountPtr< const Ast::NamespacePath > & ns, const char * name ) : CoreFunction( ns, name ) { }
303 virtual void
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( ) ) );
320 res->close( );
322 Kernel::ContRef cont = evalState->cont_;
323 cont->takeValue( Kernel::ValueRef( res ),
324 evalState );
328 class Core_hot : public Lang::CoreFunction
330 public:
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 ) ) );
339 virtual void
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 ) ) ),
349 evalState );
353 class Core_ampersand_dynamic : public Lang::CoreFunction
355 public:
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 ) )
361 virtual void
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 ),
375 res ) );
378 Kernel::ContRef cont = evalState->cont_;
379 cont->takeValue( res,
380 evalState );
384 class Core_locate : public Lang::CoreFunction
386 public:
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,
398 evalState );
402 class Core_sourceof : public Lang::CoreFunction
404 public:
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( );
412 if( node == 0 )
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( ) ) ) ),
431 evalState );
439 RefCountPtr< const Lang::CoreFunction > Lang::THE_IDENTITY( new Lang::Core_identity( Lang::THE_NAMESPACE_Shapes, "identity" ) );
441 void
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" ) );