Helper class for Structure creation in the kernel: Kernel::StructureFactory.
[shapes.git] / source / containertypes.cc
blobffdb3e4f5de2c1227722a92e39ef040474dddcb9
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 "shapestypes.h"
20 #include "shapesexceptions.h"
21 #include "astexpr.h"
22 #include "consts.h"
23 #include "angleselect.h"
24 #include "astvar.h"
25 #include "astclass.h"
26 #include "globals.h"
28 using namespace Shapes;
31 Lang::SingleList::SingleList( )
32 { }
34 Lang::SingleList::~SingleList( )
35 { }
37 RefCountPtr< const Lang::Class > Lang::SingleList::TypeID( new Lang::SystemFinalClass( strrefdup( "SingleList" ) ) );
38 TYPEINFOIMPL( SingleList );
40 Kernel::VariableHandle
41 Lang::SingleList::getField( const char * fieldId, const RefCountPtr< const Lang::Value > & selfRef ) const
43 RefCountPtr< const Lang::SingleList > typedSelfRef = Helpers::down_cast< const Lang::SingleList >( selfRef, "< SingleList::getField >" );
44 if( strcmp( fieldId, "foldl" ) == 0 )
46 return Helpers::newValHandle( new Lang::SingleListMethodFoldL( typedSelfRef ) );
48 if( strcmp( fieldId, "foldr" ) == 0 )
50 return Helpers::newValHandle( new Lang::SingleListMethodFoldR( typedSelfRef ) );
52 if( strcmp( fieldId, "foldsl" ) == 0 )
54 return Helpers::newValHandle( new Lang::SingleListMethodFoldSL( typedSelfRef ) );
56 if( strcmp( fieldId, "foldsr" ) == 0 )
58 return Helpers::newValHandle( new Lang::SingleListMethodFoldSR( typedSelfRef ) );
60 throw Exceptions::NonExistentMember( getTypeName( ), fieldId );
64 namespace Shapes
66 namespace Kernel
69 class SingleFoldLCont : public Kernel::Continuation
71 RefCountPtr< const Lang::SingleList > cdr_;
72 RefCountPtr< const Lang::Function > op_;
73 Kernel::PassedDyn dyn_;
74 Kernel::ContRef cont_;
75 public:
76 SingleFoldLCont( const RefCountPtr< const Lang::SingleList > & cdr, const RefCountPtr< const Lang::Function > & op, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
77 : Kernel::Continuation( traceLoc ), cdr_( cdr ), op_( op ), dyn_( dyn ), cont_( cont )
78 { }
79 virtual ~SingleFoldLCont( ) { }
80 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
82 evalState->dyn_ = dyn_;
83 evalState->cont_ = cont_;
84 cdr_->foldl( evalState, op_, val, traceLoc_ );
86 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
88 trace->push_front( Kernel::Continuation::BackTraceElem( this, "singly linked list's foldl" ) );
89 cont_->backTrace( trace );
91 virtual void gcMark( Kernel::GCMarkedSet & marked )
93 const_cast< Lang::SingleList * >( cdr_.getPtr( ) )->gcMark( marked );
94 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
95 dyn_->gcMark( marked );
96 cont_->gcMark( marked );
100 class SingleFoldRCont : public Kernel::Continuation
102 Kernel::VariableHandle car_;
103 RefCountPtr< const Lang::Function > op_;
104 Kernel::PassedDyn dyn_;
105 Kernel::ContRef cont_;
106 public:
107 SingleFoldRCont( const Kernel::VariableHandle & car, const RefCountPtr< const Lang::Function > & op, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
108 : Kernel::Continuation( traceLoc ), car_( car ), op_( op ), dyn_( dyn ), cont_( cont )
110 virtual ~SingleFoldRCont( ) { }
111 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
113 evalState->dyn_ = dyn_;
114 evalState->cont_ = cont_;
115 op_->call( op_, evalState, val, car_, traceLoc_ );
117 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
119 trace->push_front( Kernel::Continuation::BackTraceElem( this, "singly linked list's foldr" ) );
120 cont_->backTrace( trace );
122 virtual void gcMark( Kernel::GCMarkedSet & marked )
124 car_->gcMark( marked );
125 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
126 dyn_->gcMark( marked );
127 cont_->gcMark( marked );
131 class SingleFoldSLCont : public Kernel::Continuation
133 RefCountPtr< const Lang::SingleList > cdr_;
134 RefCountPtr< const Lang::Function > op_;
135 Kernel::StateHandle state_;
136 Kernel::PassedDyn dyn_;
137 Kernel::ContRef cont_;
138 public:
139 SingleFoldSLCont( const RefCountPtr< const Lang::SingleList > & cdr, const RefCountPtr< const Lang::Function > & op, Kernel::StateHandle state, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
140 : Kernel::Continuation( traceLoc ), cdr_( cdr ), op_( op ), state_( state ), dyn_( dyn ), cont_( cont )
142 virtual ~SingleFoldSLCont( ) { }
143 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
145 evalState->dyn_ = dyn_;
146 evalState->cont_ = cont_;
147 cdr_->foldsl( evalState, op_, val, state_, traceLoc_ );
149 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
151 trace->push_front( Kernel::Continuation::BackTraceElem( this, "singly linked list's foldsl" ) );
152 cont_->backTrace( trace );
154 virtual void gcMark( Kernel::GCMarkedSet & marked )
156 const_cast< Lang::SingleList * >( cdr_.getPtr( ) )->gcMark( marked );
157 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
158 state_->gcMark( marked );
159 dyn_->gcMark( marked );
160 cont_->gcMark( marked );
164 class SingleFoldSRCont : public Kernel::Continuation
166 Kernel::VariableHandle car_;
167 RefCountPtr< const Lang::Function > op_;
168 Kernel::StateHandle state_;
169 Kernel::PassedDyn dyn_;
170 Kernel::ContRef cont_;
171 public:
172 SingleFoldSRCont( const Kernel::VariableHandle & car, const RefCountPtr< const Lang::Function > & op, Kernel::StateHandle state, const Kernel::PassedDyn & dyn, Kernel::ContRef cont, const Ast::SourceLocation & traceLoc )
173 : Kernel::Continuation( traceLoc ), car_( car ), op_( op ), state_( state ),dyn_( dyn ), cont_( cont )
175 virtual ~SingleFoldSRCont( ) { }
176 virtual void takeHandle( Kernel::VariableHandle val, Kernel::EvalState * evalState, bool dummy ) const
178 evalState->dyn_ = dyn_;
179 evalState->cont_ = cont_;
180 op_->call( op_, evalState, val, car_, state_, traceLoc_ );
182 virtual void backTrace( std::list< Kernel::Continuation::BackTraceElem > * trace ) const
184 trace->push_front( Kernel::Continuation::BackTraceElem( this, "singly linked list's foldsr" ) );
185 cont_->backTrace( trace );
187 virtual void gcMark( Kernel::GCMarkedSet & marked )
189 car_->gcMark( marked );
190 const_cast< Lang::Function * >( op_.getPtr( ) )->gcMark( marked );
191 state_->gcMark( marked );
192 dyn_->gcMark( marked );
193 cont_->gcMark( marked );
201 Lang::SingleListPair::SingleListPair( const Kernel::VariableHandle & car, const RefCountPtr< const Lang::SingleList > & cdr )
202 : car_( car ), cdr_( cdr )
205 Lang::SingleListPair::~SingleListPair( )
208 bool
209 Lang::SingleListPair::isNull( ) const
211 return false;
214 void
215 Lang::SingleListPair::foldl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, const Ast::SourceLocation & callLoc ) const
217 evalState->cont_ = Kernel::ContRef( new Kernel::SingleFoldLCont( cdr_, op, evalState->dyn_, evalState->cont_, callLoc ) );
219 op->call( op, evalState, nullResult, car_, callLoc );
222 void
223 Lang::SingleListPair::foldr( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, const Ast::SourceLocation & callLoc ) const
225 evalState->cont_ = Kernel::ContRef( new Kernel::SingleFoldRCont( car_, op, evalState->dyn_, evalState->cont_, callLoc ) );
227 cdr_->foldr( evalState, op, nullResult, callLoc );
230 void
231 Lang::SingleListPair::foldsl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const
233 evalState->cont_ = Kernel::ContRef( new Kernel::SingleFoldSLCont( cdr_, op, state, evalState->dyn_, evalState->cont_, callLoc ) );
235 op->call( op, evalState, nullResult, car_, state, callLoc );
238 void
239 Lang::SingleListPair::foldsr( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const
241 evalState->cont_ = Kernel::ContRef( new Kernel::SingleFoldSRCont( car_, op, state, evalState->dyn_, evalState->cont_, callLoc ) );
243 cdr_->foldsr( evalState, op, nullResult, state, callLoc );
246 void
247 Lang::SingleListPair::gcMark( Kernel::GCMarkedSet & marked )
249 car_->gcMark( marked );
250 const_cast< Lang::SingleList * >( cdr_.getPtr( ) )->gcMark( marked );
253 Lang::SingleListNull::SingleListNull( )
256 Lang::SingleListNull::~SingleListNull( )
259 bool
260 Lang::SingleListNull::isNull( ) const
262 return true;
265 void
266 Lang::SingleListNull::foldl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, const Ast::SourceLocation & callLoc ) const
268 Kernel::ContRef cont = evalState->cont_;
269 cont->takeHandle( nullResult,
270 evalState );
273 void
274 Lang::SingleListNull::foldr( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, const Ast::SourceLocation & callLoc ) const
276 Kernel::ContRef cont = evalState->cont_;
277 cont->takeHandle( nullResult,
278 evalState );
281 void
282 Lang::SingleListNull::foldsl( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const
284 Kernel::ContRef cont = evalState->cont_;
285 cont->takeHandle( nullResult,
286 evalState );
289 void
290 Lang::SingleListNull::foldsr( Kernel::EvalState * evalState, const RefCountPtr< const Lang::Function > & op, const Kernel::VariableHandle & nullResult, Kernel::StateHandle state, const Ast::SourceLocation & callLoc ) const
292 Kernel::ContRef cont = evalState->cont_;
293 cont->takeHandle( nullResult,
294 evalState );
298 Lang::ConsPair::ConsPair( const Kernel::VariableHandle & car, const Kernel::VariableHandle & cdr )
299 : car_( car ), cdr_( cdr )
302 Lang::ConsPair::~ConsPair( )
305 RefCountPtr< const Lang::Class > Lang::ConsPair::TypeID( new Lang::SystemFinalClass( strrefdup( "ConsPair" ) ) );
306 TYPEINFOIMPL( ConsPair );
308 void
309 Lang::ConsPair::show( std::ostream & os ) const
311 os << "< a lazy pair >" ;
314 Kernel::VariableHandle
315 Lang::ConsPair::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
317 if( strcmp( fieldID, "car" ) == 0 )
319 return car_;
321 if( strcmp( fieldID, "cdr" ) == 0 )
323 return cdr_;
325 throw Exceptions::NonExistentMember( getTypeName( ), fieldID );
328 void
329 Lang::ConsPair::gcMark( Kernel::GCMarkedSet & marked )
331 car_->gcMark( marked );
332 cdr_->gcMark( marked );
336 Lang::SingleListMethodBase::SingleListMethodBase( RefCountPtr< const Lang::SingleList > self, Kernel::EvaluatedFormals * formals )
337 : Lang::Function( formals ), self_( self )
340 Lang::SingleListMethodBase::~SingleListMethodBase( )
343 void
344 Lang::SingleListMethodBase::gcMark( Kernel::GCMarkedSet & marked )
346 const_cast< Lang::SingleList * >( self_.getPtr( ) )->gcMark( marked );
349 bool
350 Lang::SingleListMethodBase::isTransforming( ) const
352 return false;
355 Lang::SingleListMethodFoldL::SingleListMethodFoldL( RefCountPtr< const Lang::SingleList > self )
356 : Lang::SingleListMethodBase( self,
357 new Kernel::EvaluatedFormals( strdup( Kernel::MethodId( Lang::SingleList::TypeID, "foldl" ).prettyName( ).getPtr( ) ) ) )
359 formals_->appendEvaluatedCoreFormal( "op", Kernel::THE_SLOT_VARIABLE, true );
360 formals_->appendEvaluatedCoreFormal( "nullRes", Kernel::THE_SLOT_VARIABLE, false );
363 Lang::SingleListMethodFoldL::~SingleListMethodFoldL( )
366 void
367 Lang::SingleListMethodFoldL::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
369 args.applyDefaults( );
371 self_->foldl( evalState,
372 Helpers::down_cast_CoreArgument< const Lang::Function >( "< core method foldl >", args, 0, callLoc ),
373 args.getHandle( 1 ),
374 callLoc );
377 Lang::SingleListMethodFoldR::SingleListMethodFoldR( RefCountPtr< const Lang::SingleList > self )
378 : Lang::SingleListMethodBase( self,
379 new Kernel::EvaluatedFormals( strdup( Kernel::MethodId( Lang::SingleList::TypeID, "foldr" ).prettyName( ).getPtr( ) ) ) )
381 formals_->appendEvaluatedCoreFormal( "op", Kernel::THE_SLOT_VARIABLE, true );
382 formals_->appendEvaluatedCoreFormal( "nullRes", Kernel::THE_SLOT_VARIABLE, false );
385 Lang::SingleListMethodFoldR::~SingleListMethodFoldR( )
388 void
389 Lang::SingleListMethodFoldR::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
391 args.applyDefaults( );
393 self_->foldr( evalState,
394 Helpers::down_cast_CoreArgument< const Lang::Function >( "< core method foldr >", args, 0, callLoc ),
395 args.getHandle( 1 ),
396 callLoc );
399 Lang::SingleListMethodFoldSL::SingleListMethodFoldSL( RefCountPtr< const Lang::SingleList > self )
400 : Lang::SingleListMethodBase( self,
401 new Kernel::EvaluatedFormals( strdup( Kernel::MethodId( Lang::SingleList::TypeID, "foldsl" ).prettyName( ).getPtr( ) ) ) )
403 formals_->appendEvaluatedCoreFormal( "op", Kernel::THE_SLOT_VARIABLE, true );
404 formals_->appendEvaluatedCoreFormal( "nullRes", Kernel::THE_SLOT_VARIABLE, false );
405 formals_->appendCoreStateFormal( "state" );
408 Lang::SingleListMethodFoldSL::~SingleListMethodFoldSL( )
411 void
412 Lang::SingleListMethodFoldSL::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
414 args.applyDefaults( );
416 self_->foldsl( evalState,
417 Helpers::down_cast_CoreArgument< const Lang::Function >( "< core method foldl >", args, 0, callLoc ),
418 args.getHandle( 1 ),
419 args.getState( 0 ),
420 callLoc );
423 Lang::SingleListMethodFoldSR::SingleListMethodFoldSR( RefCountPtr< const Lang::SingleList > self )
424 : Lang::SingleListMethodBase( self,
425 new Kernel::EvaluatedFormals( strdup( Kernel::MethodId( Lang::SingleList::TypeID, "foldsr" ).prettyName( ).getPtr( ) ) ) )
427 formals_->appendEvaluatedCoreFormal( "op", Kernel::THE_SLOT_VARIABLE, true );
428 formals_->appendEvaluatedCoreFormal( "nullRes", Kernel::THE_SLOT_VARIABLE, false );
429 formals_->appendCoreStateFormal( "state" );
432 Lang::SingleListMethodFoldSR::~SingleListMethodFoldSR( )
435 void
436 Lang::SingleListMethodFoldSR::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
438 args.applyDefaults( );
440 self_->foldsr( evalState,
441 Helpers::down_cast_CoreArgument< const Lang::Function >( "< core method foldr >", args, 0, callLoc ),
442 args.getHandle( 1 ),
443 args.getState( 0 ),
444 callLoc );
448 Lang::Structure::Structure( const Ast::ArgListExprs * argList, const RefCountPtr< const Lang::SingleList > & values, bool argListOwner )
449 : argListOwner_( argListOwner ), argList_( argList ), values_( values )
452 Lang::Structure::~Structure( )
454 if( argListOwner_ )
456 delete argList_;
460 RefCountPtr< const Lang::Class > Lang::Structure::TypeID( new Lang::SystemFinalClass( strrefdup( "Union" ) ) );
461 TYPEINFOIMPL( Structure );
463 Kernel::VariableHandle
464 Lang::Structure::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & selfRef ) const
466 return argList_->findNamed( values_, fieldID );
469 Kernel::VariableHandle
470 Lang::Structure::getPosition( size_t pos, const RefCountPtr< const Lang::Value > & selfRef ) const
472 return argList_->getOrdered( values_, pos );
475 RefCountPtr< const Lang::Structure >
476 Lang::Structure::getSink( size_t consumedArguments ) const
478 if( argList_->orderedExprs_->size( ) <= consumedArguments )
480 return Lang::THE_EMPTY_STRUCT;
483 static std::vector< const Ast::ArgListExprs * > argLists;
484 size_t resSize = argList_->orderedExprs_->size( ) - consumedArguments;
485 if( resSize >= argLists.size( ) )
487 argLists.reserve( resSize + 1 );
488 while( argLists.size( ) <= resSize )
490 argLists.push_back( new Ast::ArgListExprs( argLists.size( ) ) );
494 RefCountPtr< const Lang::SingleList > resValues = values_;
497 for( size_t i = 0; i < consumedArguments; ++i )
499 resValues = Helpers::try_cast_CoreArgument< const Lang::SingleListPair >( resValues )->cdr_;
502 catch( const NonLocalExit::NotThisType & ball )
504 throw Exceptions::InternalError( "When constructing the sink, there was not enough arguments." );
506 return RefCountPtr< const Lang::Structure >( new Lang::Structure( argLists[ resSize ], resValues, false ) );
509 void
510 Lang::Structure::gcMark( Kernel::GCMarkedSet & marked )
512 const_cast< Lang::SingleList * >( values_.getPtr( ) )->gcMark( marked );
516 Kernel::StructureFactory::StructureFactory( const std::list< const char * > & fields )
518 init( fields );
521 Kernel::StructureFactory::StructureFactory( const char * field1 )
523 std::list< const char * > fields;
524 fields.push_back( field1 );
525 init( fields );
528 Kernel::StructureFactory::StructureFactory( const char * field1, const char * field2 )
530 std::list< const char * > fields;
531 fields.push_back( field1 );
532 fields.push_back( field2 );
533 init( fields );
536 Kernel::StructureFactory::StructureFactory( const char * field1, const char * field2, const char * field3 )
538 std::list< const char * > fields;
539 fields.push_back( field1 );
540 fields.push_back( field2 );
541 fields.push_back( field3 );
542 init( fields );
545 Kernel::StructureFactory::StructureFactory( const char * field1, const char * field2, const char * field3, const char * field4 )
547 std::list< const char * > fields;
548 fields.push_back( field1 );
549 fields.push_back( field2 );
550 fields.push_back( field3 );
551 fields.push_back( field4 );
552 init( fields );
555 void
556 Kernel::StructureFactory::init( const std::list< const char * > & fields )
558 Ast::ArgListExprs * tmp = new Ast::ArgListExprs( false );
559 typedef typeof fields ListType;
560 for( ListType::const_iterator i = fields.begin( ); i != fields.end( ); ++i )
562 (*tmp->namedExprs_)[ *i ] = 0;
563 typedef typeof values_ MapType;
564 values_.insert( MapType::value_type( *i, Kernel::THE_VOID_VARIABLE ) );
566 argList_ = tmp;
569 void
570 Kernel::StructureFactory::clear( )
572 typedef typeof values_ MapType;
573 for( MapType::iterator i = values_.begin( ); i != values_.end( ); ++i )
575 i->second = Kernel::THE_VOID_VARIABLE;
579 void
580 Kernel::StructureFactory::set( const char * field, const Kernel::VariableHandle & value )
582 typedef typeof values_ MapType;
583 MapType::iterator i = values_.find( field );
584 if( i == values_.end( ) )
586 throw Exceptions::InternalError( "Kernel::StructureFactory::set: Field was not declared." );
588 i->second = value;
591 RefCountPtr< const Lang::Structure >
592 Kernel::StructureFactory::build( )
594 RefCountPtr< const Lang::SingleList > tmp = Lang::THE_CONS_NULL;
595 typedef typeof values_ MapType;
596 for( MapType::iterator i = values_.begin( ); i != values_.end( ); ++i )
598 tmp = RefCountPtr< const Lang::SingleList >( new Lang::SingleListPair( i->second, tmp ) );
600 return RefCountPtr< const Lang::Structure >( new Lang::Structure( argList_, tmp ) );