Mutators for Catalog states.
[shapes.git] / source / classtypes.cc
blobf7d836286f5507589468b5e9beaa5207221cd65b
1 #include <cmath>
3 #include "shapestypes.h"
4 #include "shapesexceptions.h"
5 #include "astexpr.h"
6 #include "globals.h"
7 #include "consts.h"
8 #include "angleselect.h"
9 #include "astvar.h"
10 #include "astclass.h"
11 #include "autoonoff.h"
12 #include "shapescore.h"
13 #include "astfun.h"
15 #include <ctype.h>
16 #include <stack>
17 #include <string>
19 using namespace Shapes;
20 using namespace std;
23 Kernel::MethodId::MethodId( const RefCountPtr< const Lang::Class > & _myClass, const char * _msg )
24 : myClass( _myClass ), msg( _msg )
25 { }
27 Kernel::MethodId::~MethodId( )
28 { }
30 const char *
31 Kernel::MethodId::getIdentifier( ) const
33 return msg;
37 Lang::Instance::Instance( Kernel::PassedEnv _env, Kernel::PassedEnv _privateEnv, RefCountPtr< const Lang::Class > _myClass, bool _protectedAccess, const Kernel::PassedDyn & _my_dyn )
38 : env( _env ), privateEnv( _privateEnv ), warm2D( 0 ), warm3D( 0 ), my_dyn( _my_dyn ), myClass( _myClass ), prepared( false ), protectedAccess( _protectedAccess )
39 { }
41 DISPATCHIMPL( Instance );
43 Lang::Instance::~Instance( )
44 { }
46 void
47 Lang::Instance::gcMark( Kernel::GCMarkedSet & marked )
49 env->gcMark( marked );
50 privateEnv->gcMark( marked );
51 my_dyn->gcMark( marked );
55 void
56 Lang::Instance::prepare( Kernel::EvalState * evalState )
58 if( prepared )
60 return;
62 prepared = true;
64 for( std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = parents->begin( ); i != parents->end( ); ++i )
66 i->second->prepare( evalState );
70 myClass->prepareInstance( evalState, privateEnv );
73 Kernel::VariableHandle
74 Lang::Instance::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
76 if( ! myClass->getFinal( ) )
78 throw Exceptions::IllegalFinalReference( myClass->getPrettyName( ), fieldID );
81 return getLocalField( fieldID );
84 Kernel::VariableHandle
85 Lang::Instance::getLocalField( const char * fieldID ) const
87 if( protectedAccess )
89 if( myClass->isInProtectedGetSet( fieldID ) )
91 throw Exceptions::NotImplemented( "Instance::getLocalField" );
92 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
93 // return env->getVarHandle( key );
95 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
97 else
99 if( myClass->isInPublicGetSet( fieldID ) )
101 throw Exceptions::NotImplemented( "Instance::getLocalField" );
102 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
103 // return env->getVarHandle( key );
105 if( myClass->isInProtectedGetSet( fieldID ) )
107 throw Exceptions::ProtectedMemberPublicScope( myClass->getPrettyName( ), fieldID );
109 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
113 void
114 Lang::Instance::tackOn( const char * fieldID, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
116 if( ! myClass->getFinal( ) )
118 throw Exceptions::IllegalFinalReference( myClass->getPrettyName( ), fieldID );
121 tackOnLocal( fieldID, evalState, piece, callLoc );
124 void
125 Lang::Instance::tackOnLocal( const char * fieldID, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
127 if( protectedAccess )
129 if( myClass->isInProtectedSetSet( fieldID ) )
131 throw Exceptions::NotImplemented( "Instance::tackOnLocal" );
132 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
133 // env->tackOn( key, evalState, piece, callLoc );
134 return;
136 if( myClass->isInProtectedGetSet( fieldID ) )
138 throw Exceptions::MemberNotAssignable( myClass->getPrettyName( ), fieldID, Interaction::PROTECTED_SCOPE_NAME );
140 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
142 else
144 if( myClass->isInPublicSetSet( fieldID ) )
146 throw Exceptions::NotImplemented( "Instance::tackOnLocal" );
147 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
148 // env->tackOn( key, evalState, piece, callLoc );
149 return;
151 if( myClass->isInPublicGetSet( fieldID ) )
153 throw Exceptions::MemberNotAssignable( myClass->getPrettyName( ), fieldID, Interaction::PUBLIC_SCOPE_NAME );
155 if( myClass->isInProtectedGetSet( fieldID ) )
157 throw Exceptions::ProtectedMemberPublicScope( myClass->getPrettyName( ), fieldID );
159 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
163 RefCountPtr< const Lang::Function >
164 Lang::Instance::getMethod( Kernel::MethodId fieldID ) const
166 typedef typeof methodTable MethodMapType;
167 MethodMapType::iterator i = methodTable.find( fieldID );
168 if( i != methodTable.end( ) )
170 return i->second;
173 const RefCountPtr< const Lang::Class > & defClass = myClass->getMethodDefinitionClass( fieldID );
175 RefCountPtr< const Lang::Function > fun = NullPtr< const Lang::Function >( );
177 if( defClass == myClass )
179 fun = getLocalMethod( fieldID );
181 else
183 typedef typeof *parents ParentMapType;
184 ParentMapType::const_iterator p = parents->find( defClass );
185 if( p == parents->end( ) )
187 throw Exceptions::InternalError( "The class defining a method was not found among the parents." );
189 fun = p->second->getLocalMethod( fieldID );
192 methodTable.insert( i, MethodMapType::value_type( fieldID, fun ) );
194 return fun;
197 RefCountPtr< const Lang::Function >
198 Lang::Instance::getLocalMethod( Kernel::MethodId fieldID ) const
201 if( fieldID.getClass( ) == myClass )
203 Kernel::VariableHandle untypedFun = getLocalField( fieldID.getIdentifier( ) );
204 return untypedFun->getVal< const Lang::Function >( "getLocalMethod: The user was (almost) able to retrieve member data from super instance." );
207 typedef typeof overrides ClassMapType;
208 ClassMapType::const_iterator i = overrides.find( fieldID.getClass( ) );
209 if( i == overrides.end( ) )
211 throw Exceptions::NoSuchLocalMethod( myClass, fieldID );
214 typedef typeof i->second IdMapType;
216 IdMapType::const_iterator j = i->second.find( fieldID.getIdentifier( ) );
217 if( j == i->second.end( ) )
219 throw Exceptions::NoSuchLocalMethod( myClass, fieldID );
221 return j->second;
224 RefCountPtr< const Lang::Instance >
225 Lang::Instance::superReference( RefCountPtr< const Lang::Class > parent ) const
227 typedef typeof *parents ParentMapType;
228 ParentMapType::const_iterator p = parents->find( parent );
229 if( p == parents->end( ) )
231 throw Exceptions::SuperReferenceClassNotParent( myClass, parent );
233 return p->second;
236 RefCountPtr< const Lang::Geometric2D >
237 Lang::Instance::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
239 return RefCountPtr< const Lang::Geometric2D >( new Lang::TransformedInstance( tf, self.down_cast< const Lang::Instance >( ) ) );
242 void
243 Lang::Instance::shipout( std::ostream & os, Kernel::PageContentStates * pdfState, const Lang::Transform2D & tf ) const
245 if( ! myClass->method_isa( Lang::Drawable2D::TypeID ) )
247 throw Exceptions::InternalError( "Invoking Instance::shipout on a non Drawable object should not be possible" );
250 if( warm2D == 0 )
252 throw Exceptions::InternalError( "Instance::shipout: warm2D == 0." );
256 RefCountPtr< const Lang::Value > val = getMethod( Kernel::MethodId( Lang::Drawable2D::TypeID, Shapes::MESSAGE_DRAWABLE_DRAW_ID ) )->call( dstgroup, my_pdfo, & stateCopy, Kernel::EMPTY_ARGLIST );
257 if( dynamic_cast< const Lang::Void * >( val.getPtr( ) ) == 0 )
259 throw Exceptions::TypeMismatch( val->getTypeName( ), Lang::Void::staticTypeName( ) );
263 warm2D->getPile( )->shipout( os, pdfState, tf );
266 RefCountPtr< const Lang::ElementaryPath2D >
267 Lang::Instance::bbox( ) const
269 if( ! myClass->method_isa( Lang::Drawable2D::TypeID ) )
271 throw Exceptions::InternalError( "Invoking Instance::shipout on a non Drawable object should not be possible" );
274 if( warm2D == 0 )
276 throw Exceptions::InternalError( "Instance::shipout: warm2D == 0." );
279 return warm2D->getPile( )->bbox( );
282 RefCountPtr< const char >
283 Lang::Instance::staticTypeName( )
285 return strrefdup( "<Instance>" );
288 const RefCountPtr< const Lang::Class > &
289 Lang::Instance::getClass( ) const
291 return myClass;
294 void
295 Lang::Instance::show( std::ostream & os ) const
297 os << "Instance of class " << myClass->getPrettyName( ).getPtr( ) ;
301 Lang::TransformedInstance::TransformedInstance( const Lang::Transform2D & _tf, const RefCountPtr< const Lang::Instance > & _obj )
302 : tf( _tf ), obj( _obj )
305 Lang::TransformedInstance::~TransformedInstance( )
308 Kernel::VariableHandle
309 Lang::TransformedInstance::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
311 if( obj->getClass( )->isInTransformingSet( fieldID ) )
313 Kernel::VariableHandle argUntyped = obj->getField( fieldID, obj );
314 typedef const Lang::Geometric2D ArgType;
315 RefCountPtr< ArgType > arg = argUntyped->getVal< ArgType >( "<inside transformed instance getField>" );
316 return Kernel::VariableHandle( new Kernel::Variable( arg->transformed( tf, arg ) ) );
318 return obj->getField( fieldID, obj );
321 RefCountPtr< const Lang::Function >
322 Lang::TransformedInstance::getMethod( Kernel::MethodId fieldID ) const
324 /* Fetch the method first to make sure it exists, then see whether it is transforming.
326 RefCountPtr< const Lang::Function > arg = obj->getMethod( fieldID );
327 if( arg->isTransforming( ) )
329 return RefCountPtr< const Lang::Function >( new Lang::TransformedFunction2D( tf, arg ) );
331 return arg;
334 RefCountPtr< const Lang::Geometric2D >
335 Lang::TransformedInstance::transformed( const Lang::Transform2D & tf2, const RefCountPtr< const Lang::Geometric2D > & self ) const
337 return RefCountPtr< const Lang::Geometric2D >( new Lang::TransformedInstance( Lang::Transform2D( tf2, tf ) , obj ) );
341 void
342 Lang::TransformedInstance::shipout( std::ostream & os, Kernel::PageContentStates * pdfState, const Lang::Transform2D & tfIn ) const
344 obj->shipout( os, pdfState, Lang::Transform2D( tfIn, tf ) );
347 RefCountPtr< const Lang::ElementaryPath2D >
348 Lang::TransformedInstance::bbox( ) const
350 return obj->bbox( )->elementaryTransformed( tf );
353 RefCountPtr< const Lang::Class > Lang::TransformedInstance::TypeID( new Lang::SystemFinalClass( strrefdup( "TransformedInstance" ) ) );
354 TYPEINFOIMPL( TransformedInstance );
356 void
357 Lang::TransformedInstance::show( std::ostream & os ) const
359 os << "Transformed instance. The class is not available in this implementation." ;
362 void
363 Lang::TransformedInstance::gcMark( Kernel::GCMarkedSet & marked )
365 const_cast< Lang::Instance * >( obj.getPtr( ) )->gcMark( marked );
368 RefCountPtr< const char >
369 Kernel::MethodId::prettyName( ) const
371 string res = myClass->getPrettyName( ).getPtr( );
372 res += "#";
373 res += msg;
374 return strrefdup( res.c_str( ) );
377 bool
378 Kernel::operator < ( const Kernel::MethodId & mid1, const Kernel::MethodId & mid2 )
380 if( mid1.myClass < mid2.myClass )
382 return true;
384 if( mid1.myClass > mid2.myClass )
386 return false;
388 return strcmp( mid1.msg, mid2.msg ) < 0;
392 Lang::Class::Class( RefCountPtr< const char > _prettyName )
393 : prettyName( _prettyName ), selfRef( NullPtr< Lang::Class >( ) ), isFinal( false )
396 Lang::Class::~Class( )
398 /* Knowing that each class is reference counted, the destructor is being called as an effect
399 * of the reference count reaching zero. Thus, the self reference must simply be detached
400 * from this object, to avoid cyclic destruction.
402 selfRef.abortPtr( );
405 void
406 Lang::Class::setSelfRef( RefCountPtr< const Lang::Class > _selfRef ) const
408 selfRef = _selfRef; // selfRef is mutable!
409 /* Don't count this cyclic reference!
411 --*selfRef.getCounterPtr( );
414 RefCountPtr< const Lang::Class > Lang::Class::TypeID( new Lang::MetaClass( ) );
415 TYPEINFOIMPL( Class );
417 RefCountPtr< const char >
418 Lang::Class::getPrettyName( ) const
420 return prettyName;
423 bool
424 Lang::Class::isInPublicGetSet( const char * field ) const
426 return false;
429 bool
430 Lang::Class::isInPublicSetSet( const char * field ) const
432 return false;
435 bool
436 Lang::Class::isInProtectedGetSet( const char * field ) const
438 return false;
441 bool
442 Lang::Class::isInProtectedSetSet( const char * field ) const
444 return false;
447 bool
448 Lang::Class::isInTransformingSet( const char * field ) const
450 return false;
453 RefCountPtr< const Lang::Function >
454 Lang::Class::getMutator( const char * mutatorID ) const
456 throw Exceptions::InternalError( "Mutator request not defined for this type of class." );
459 void
460 Lang::Class::showAbstractSet( std::ostream & os ) const
462 os << "{" ;
463 typedef typeof abstractSet SetType;
464 for( SetType::const_iterator i = abstractSet.begin( ); i != abstractSet.end( ); ++i )
466 os << " " << i->prettyName( ) ;
468 os << " }" ;
472 void
473 Lang::Class::show( std::ostream & os ) const
475 os << "Pretty-name: " << prettyName.getPtr( ) ;
477 if( ! abstractSet.empty( ) )
479 os << ", +" ;
481 else
483 os << ", -" ;
485 os << "abstract" ;
487 if( isFinal )
489 os << ", +" ;
491 else
493 os << ", -" ;
495 os << "final" ;
498 bool isRepeatable = false;
501 isRepeatable = this->isRepeatableBase( );
503 catch( const Exceptions::MiscellaneousRequirement & ball )
505 /* Probably something saying that MetaClass is not repeatable... */
508 if( isRepeatable )
510 os << ", +" ;
512 else
514 os << ", -" ;
516 os << "repeatable" ;
520 Kernel::VariableHandle
521 Lang::Class::getField( const char * fieldId, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
523 if( strcmp( fieldId, "new" ) == 0 )
525 return Helpers::newValHandle( new Lang::ClassMethodNew( selfRef ) );
527 if( strcmp( fieldId, "isa" ) == 0 )
529 return Helpers::newValHandle( new Lang::ClassMethodIsa( selfRef ) );
531 if( strcmp( fieldId, "name" ) == 0 )
533 return Helpers::newValHandle( new Lang::String( prettyName ) );
535 throw Exceptions::NonExistentMember( getTypeName( ), fieldId );
538 bool
539 Lang::Class::getFinal( ) const
541 return isFinal;
544 const Lang::Class::MessageMapType &
545 Lang::Class::getMessageMap( ) const
547 return messageMap;
550 const RefCountPtr< const Lang::Class > &
551 Lang::Class::getMethodDefinitionClass( const Kernel::MethodId & method ) const
553 MessageMapType::const_iterator i = messageMap.find( method );
554 if( i == messageMap.end( ) )
556 throw Exceptions::NoSuchMethod( selfRef, method );
558 if( i->second.empty( ) )
560 throw Exceptions::InternalError( "Asking for class defining abstract method." );
562 return *( i->second.begin( ) );
566 void
567 Lang::Class::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
569 typedef typeof *_allParents SetType;
570 SetType::const_iterator i = _allParents->find( selfRef );
571 if( i != _allParents->end( ) )
573 _multiParents->insert( selfRef );
575 else
577 _allParents->insert( i, selfRef );
581 void
582 Lang::Class::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
584 /* Only UserClass instances do any preparations. */
587 DISPATCHIMPL( Class );
591 Lang::Object::Object( )
592 : Lang::Class( strrefdup( "Object" ) ), dummyEnv( NullPtr< Kernel::Environment >( ) )
595 Lang::Object::~Object( )
598 Kernel::ValueRef
599 Lang::Object::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
601 const size_t ARITY = 0;
602 CHECK_ARITY( args, ARITY, Kernel::MethodId( Lang::Class::TypeID, "new" ).prettyName( ) );
604 return RefCountPtr< const Lang::Geometric2D >( new Lang::Instance( dummyEnv, dummyEnv, selfRef, false, evalState->dyn_ ) );
607 bool
608 Lang::Object::method_isa( RefCountPtr< const Lang::Class > T ) const
610 return T == selfRef;
613 void
614 Lang::Object::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
616 /* There are no parent classes to consider. */
619 void
620 Lang::Object::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
622 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
625 void
626 Lang::Object::superNew( RefCountPtr< Lang::Instance > instanceSelf,
627 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
628 Kernel::Arguments & emptyArglist,
629 Kernel::EvalState * evalState ) const
631 std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = createdObjects->find( selfRef );
632 if( i != createdObjects->end( ) )
634 return;
636 Lang::Instance * newObj = new Lang::Instance( dummyEnv, dummyEnv, selfRef, true, evalState->dyn_ );
637 newObj->parents = createdObjects;
638 createdObjects->insert( i, pair< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >( selfRef, RefCountPtr< Lang::Instance >( newObj ) ) );
641 bool
642 Lang::Object::isRepeatableBase( ) const
644 return true;
647 void
648 Lang::Object::gcMark( Kernel::GCMarkedSet & marked )
651 Lang::MetaClass::MetaClass( )
652 : Lang::Class( strrefdup( "MetaClass" ) )
655 Lang::MetaClass::~MetaClass( )
658 Kernel::ValueRef
659 Lang::MetaClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
661 throw Exceptions::MiscellaneousRequirement( "Calling the \"new\" method of MetaClass is actually not the way to create new classes, sorry." );
664 bool
665 Lang::MetaClass::method_isa( RefCountPtr< const Lang::Class > T ) const
667 return T == Lang::Class::TypeID || T == Lang::THE_OBJECT;
670 void
671 Lang::MetaClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
673 /* There are no parent classes to consider. */
676 void
677 Lang::MetaClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
679 if( strcmp( id, "new" ) == 0 ||
680 strcmp( id, "isa" ) == 0 )
682 throw Exceptions::OverridingFinalMethod( caller, selfRef, id );
684 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
687 void
688 Lang::MetaClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
689 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
690 Kernel::Arguments & emptyArglist,
691 Kernel::EvalState * evalState ) const
693 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from MetaClass, sorry." );
696 void
697 Lang::MetaClass::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
699 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from MetaClass, sorry." );
702 bool
703 Lang::MetaClass::isRepeatableBase( ) const
705 throw Exceptions::MiscellaneousRequirement( "MetaClass can certainly not be a repeated base." );
708 void
709 Lang::MetaClass::gcMark( Kernel::GCMarkedSet & marked )
714 Lang::SystemFinalClass::SystemFinalClass( RefCountPtr< const char > _prettyName )
715 : Lang::Class( _prettyName ), registerMutatorFunction_( 0 )
718 Lang::SystemFinalClass::SystemFinalClass( RefCountPtr< const char > _prettyName, RegisterMutatorFunction registerMutatorFunction )
719 : Lang::Class( _prettyName ), registerMutatorFunction_( registerMutatorFunction )
722 Lang::SystemFinalClass::~SystemFinalClass( )
725 void
726 Lang::SystemFinalClass::initMutators( )
728 if( registerMutatorFunction_ != 0 )
730 registerMutatorFunction_( this );
734 void
735 Lang::SystemFinalClass::registerMutator( Lang::CoreFunction * fun )
737 typedef typeof mutators_ MapType;
738 mutators_.insert( MapType::value_type( fun->getTitle( ), RefCountPtr< const Lang::Function >( fun ) ) );
741 Kernel::ValueRef
742 Lang::SystemFinalClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
744 throw Exceptions::MiscellaneousRequirement( "Use dedicated syntax rather than calling the \"new\" method of a system class." );
747 bool
748 Lang::SystemFinalClass::method_isa( RefCountPtr< const Lang::Class > T ) const
750 return T == selfRef || T == Lang::THE_OBJECT;
753 void
754 Lang::SystemFinalClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
756 /* There are no parent classes to consider. */
759 void
760 Lang::SystemFinalClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
762 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
765 void
766 Lang::SystemFinalClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
767 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
768 Kernel::Arguments & emptyArglist,
769 Kernel::EvalState * evalState ) const
771 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from SystemFinalClass, sorry." );
774 bool
775 Lang::SystemFinalClass::isRepeatableBase( ) const
777 return false;
780 RefCountPtr< const Lang::Function >
781 Lang::SystemFinalClass::getMutator( const char * mutatorID ) const
783 typedef typeof mutators_ MapType;
784 MapType::const_iterator i = mutators_.find( mutatorID );
785 if( i == mutators_.end( ) )
787 throw Exceptions::NonExistentMutator( staticTypeName( ), mutatorID );
789 return i->second;
792 void
793 Lang::SystemFinalClass::gcMark( Kernel::GCMarkedSet & marked )
797 Lang::SystemVirtualInterface::SystemVirtualInterface( RefCountPtr< const char > _prettyName )
798 : Lang::Class( _prettyName )
801 Lang::SystemVirtualInterface::~SystemVirtualInterface( )
804 void
805 Lang::SystemVirtualInterface::addVirtual( const char * id )
807 messageMap[ Kernel::MethodId( selfRef, id ) ];
810 Kernel::ValueRef
811 Lang::SystemVirtualInterface::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
813 throw Exceptions::InstantiatingAbstractClass( selfRef );
816 bool
817 Lang::SystemVirtualInterface::method_isa( RefCountPtr< const Lang::Class > T ) const
819 throw Exceptions::InternalError( "method_isa was called on an abstract system class." );
822 void
823 Lang::SystemVirtualInterface::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
825 /* There are no parent classes to consider. */
828 void
829 Lang::SystemVirtualInterface::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
831 if( messageMap.find( Kernel::MethodId( selfRef, id ) ) == messageMap.end( ) )
833 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
837 void
838 Lang::SystemVirtualInterface::superNew( RefCountPtr< Lang::Instance > instanceSelf,
839 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
840 Kernel::Arguments & emptyArglist,
841 Kernel::EvalState * evalState ) const
844 bool
845 Lang::SystemVirtualInterface::isRepeatableBase( ) const
847 return true;
850 void
851 Lang::SystemVirtualInterface::gcMark( Kernel::GCMarkedSet & marked )
855 Lang::UserClass::UserClass( const Ast::ClassFunction * _classExpr,
856 Kernel::PassedEnv _env,
857 RefCountPtr< const char > _prettyName,
858 Kernel::EvaluatedFormals * _formals,
859 RefCountPtr< std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > > _parents,
860 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > > > _overrides,
861 bool _isFinal )
862 : Lang::Class( _prettyName ), classExpr( _classExpr ), formals( _formals ), env( _env ), parents( _parents ), overrides( _overrides )
864 Lang::Class::isFinal = _isFinal;
867 Lang::UserClass::~UserClass( )
869 delete formals;
872 void
873 Lang::UserClass::setupAndCheck( bool declaredAbstract )
875 for( std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > >::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
877 typedef typeof immediateParents SetType;
878 SetType::const_iterator j = immediateParents.find( i->first );
879 if( j != immediateParents.end( ) )
881 throw Exceptions::RepeatedImmediateParent( selfRef, i->first );
883 if( i->first->getFinal( ) )
885 throw Exceptions::InheritingFinal( selfRef, i->first );
887 immediateParents.insert( j, i->first );
890 findParents( & allParents, & multiParents );
892 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = multiParents.begin( ); i != multiParents.end( ); ++i )
894 if( ! (*i)->isRepeatableBase( ) )
896 throw Exceptions::IllegalRepeatedBase( selfRef, *i );
900 messageMap = classExpr->getLocalMessageMap( selfRef );
902 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = immediateParents.begin( ); i != immediateParents.end( ); ++i )
904 const MessageMapType & parentMap = (*i)->getMessageMap( );
905 for( MessageMapType::const_iterator j = parentMap.begin( ); j != parentMap.end( ); ++j )
907 std::set< RefCountPtr< const Lang::Class > > & messageSet = messageMap[ j->first ];
908 std::set< RefCountPtr< const Lang::Class > > res;
909 set_union( messageSet.begin( ), messageSet.end( ),
910 j->second.begin( ), j->second.end( ),
911 insert_iterator< std::set< RefCountPtr< const Lang::Class > > >( res, res.begin( ) ) );
912 messageSet = res;
917 typedef typeof *overrides MapType;
918 for( MapType::const_iterator i = overrides->begin( ); i != overrides->end( ); ++i )
920 typedef typeof allParents ClassSetType;
922 ClassSetType::const_iterator j = allParents.find( i->first );
923 if( j == allParents.end( ) )
925 throw Exceptions::OverridingNonParent( selfRef, i->first );
929 typedef typeof i->second ListType;
930 for( ListType::const_iterator j = i->second.begin( ); j != i->second.end( ); ++j )
932 i->first->assertMethodOverridable( (*j)->id_, selfRef );
933 std::set< RefCountPtr< const Lang::Class > > & messageSet = messageMap[ Kernel::MethodId( i->first, (*j)->id_ ) ];
934 messageSet.clear( );
935 messageSet.insert( messageSet.begin( ), selfRef );
944 std::cerr << "Message map of " << getPrettyName( ) << ":" << std::endl ;
946 std::set< Kernel::MethodId >::iterator j = abstractSet.begin( );
947 MessageMapType::iterator k = messageMap.begin( );
948 for( MessageMapType::const_iterator i = messageMap.begin( ); i != messageMap.end( ); ++i )
951 std::cerr << " " << i->first.prettyName( ) << " --> " ;
952 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator l = i->second.begin( ); l != i->second.end( ); ++l )
954 std::cerr << (*l)->getPrettyName( ) << " " ;
956 std::cerr << std::endl ;
958 if( i->second.size( ) == 1 )
960 continue;
962 if( i->second.empty( ) )
964 j = abstractSet.insert( j, i->first );
966 else
968 throw Exceptions::AmbiguousInheritedMethod( selfRef, i->first.prettyName( ), i->second );
973 if( ! declaredAbstract && ! abstractSet.empty( ) )
975 throw Exceptions::FailedToDeclareClassAbstract( selfRef, classExpr );
979 Kernel::ValueRef
980 Lang::UserClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
982 if( ! abstractSet.empty( ) )
984 throw Exceptions::InstantiatingAbstractClass( selfRef );
987 throw Exceptions::NotImplemented( "UserClass::method_new" );
989 // // std::vector< VariableHandle > * envValues = new std::vector< VariableHandle >;
990 // // envValues->reserve( argumentOrder->size( ) );
991 // // while( envValues->size( ) < argumentOrder->size( ) )
992 // // {
993 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
994 // // }
995 // Kernel::PassedEnv instanceEnv( new Kernel::Environment( Shapes::theEnvironmentList, evalState->env_, argumentOrder, RefCountPtr< std::vector< VariableHandle > >( envValues ) ) );
997 // // std::vector< VariableHandle > * envValues = new std::vector< VariableHandle >;
998 // // envValues->reserve( argumentOrder->size( ) );
999 // // while( envValues->size( ) < argumentOrder->size( ) )
1000 // // {
1001 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1002 // // }
1003 // Kernel::PassedEnv privateEnv( new Kernel::Environment( Shapes::theEnvironmentList, instanceEnv, argumentOrder, RefCountPtr< std::vector< VariableHandle > >( envValues ) ) );
1005 // RefCountPtr< Lang::Instance > instanceSelf = RefCountPtr< Lang::Instance >( new Lang::Instance( instanceEnv, privateEnv, selfRef, false, evalState->dyn_ ) );
1007 // privateEnv->define( classExpr->loc( ), SELF_ID, RefCountPtr< const Lang::Geometric2D >( instanceSelf ), true ); /* true means constant */
1009 // RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects( new std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > );
1010 // instanceSelf->parents = createdObjects;
1012 // for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = multiParents.begin( ); i != multiParents.end( ); ++i )
1013 // {
1014 // (*i)->superNew( instanceSelf, createdObjects, EMPTY_ARGLIST, evalState );
1015 // }
1017 // args.mergeWithFormals( formals )
1018 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1020 // {
1021 // typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ListType;
1022 // for( ListType::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
1023 // {
1024 // RefCountPtr< Kernel::Arguments > superArgs( new Kernel::Arguments( true ) ); /* true means constant */
1025 // i->second->evaluate( superArgs, dstgroup, pdfo, metaState, initEnv );
1026 // i->first->superNew( instanceSelf, createdObjects, *superArgs, evalState );
1027 // }
1028 // }
1030 // classExpr->setupInstance( instanceEnv, privateEnv, dstgroup, pdfo, metaState, initEnv );
1032 // addOverrides( instanceSelf, privateEnv, dstgroup, pdfo, metaState );
1034 // instanceSelf->prepare( dstgroup, pdfo, metaState );
1036 // return RefCountPtr< const Lang::Geometric2D >( instanceSelf );
1039 bool
1040 Lang::UserClass::method_isa( RefCountPtr< const Lang::Class > T ) const
1042 if( T == selfRef )
1044 return true;
1046 return allParents.find( T ) != allParents.end( );
1049 void
1050 Lang::UserClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
1052 throw Exceptions::NotImplemented( "UserClass::findMultiplyInheritedClasses" );
1055 void
1056 Lang::UserClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
1058 if( classExpr->isInPublicGetSet( id ) || classExpr->isInAbstractSet( id ) )
1060 if( classExpr->isInFinalSet( id ) )
1062 throw Exceptions::OverridingFinalMethod( caller, selfRef, id );
1065 else
1067 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
1071 void
1072 Lang::UserClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
1073 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
1074 Kernel::Arguments & args,
1075 Kernel::EvalState * evalState ) const
1077 std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = createdObjects->find( selfRef );
1078 if( i != createdObjects->end( ) )
1080 return;
1083 throw Exceptions::NotImplemented( "UserClass::superNew" );
1085 // Kernel::PassedEnv instanceEnv( new Kernel::Environment( env ) );
1086 // Kernel::PassedEnv privateEnv( new Kernel::Environment( instanceEnv ) );
1088 // privateEnv->define( classExpr->loc( ), SELF_ID, RefCountPtr< const Lang::Geometric2D >( instanceSelf ), true ); /* true means constant */
1090 // args.mergeWithFormals( formals )
1091 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1093 // {
1094 // typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ListType;
1095 // for( ListType::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
1096 // {
1097 // RefCountPtr< Kernel::Arguments > superArgs( new Kernel::Arguments( true ) ); /* true means constant */
1098 // i->second->evaluate( superArgs, dstgroup, pdfo, metaState, initEnv );
1099 // i->first->superNew( instanceSelf, createdObjects, *superArgs, evalState );
1100 // }
1101 // }
1103 // classExpr->setupInstance( instanceEnv, privateEnv, dstgroup, pdfo, metaState, initEnv );
1105 // Lang::Instance * newObj = new Lang::Instance( instanceEnv, privateEnv, selfRef, true, evalState->dyn_ );
1106 // newObj->parents = createdObjects;
1107 // createdObjects->insert( i, pair< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >( selfRef, RefCountPtr< Lang::Instance >( newObj ) ) );
1110 void
1111 Lang::UserClass::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
1113 Lang::Class::findParents( _allParents, _multiParents );
1114 typedef typeof immediateParents SetType;
1115 for( SetType::const_iterator i = immediateParents.begin( ); i != immediateParents.end( ); ++i )
1117 (*i)->findParents( _allParents, _multiParents );
1121 bool
1122 Lang::UserClass::isRepeatableBase( ) const
1124 return classExpr->isRepeatableBase( );
1127 void
1128 Lang::UserClass::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
1130 classExpr->prepareInstance( evalState, privateEnv );
1134 bool
1135 Lang::UserClass::isInPublicGetSet( const char * field ) const
1137 return classExpr->isInPublicGetSet( field );
1140 bool
1141 Lang::UserClass::isInPublicSetSet( const char * field ) const
1143 return classExpr->isInPublicSetSet( field );
1146 bool
1147 Lang::UserClass::isInProtectedGetSet( const char * field ) const
1149 return classExpr->isInProtectedGetSet( field );
1152 bool
1153 Lang::UserClass::isInProtectedSetSet( const char * field ) const
1155 return classExpr->isInProtectedSetSet( field );
1158 bool
1159 Lang::UserClass::isInTransformingSet( const char * field ) const
1161 return classExpr->isInTransformingSet( field );
1165 void
1166 Lang::UserClass::addOverrides( Kernel::EvalState * evalState, RefCountPtr< Lang::Instance > instance, Kernel::PassedEnv privateEnv ) const
1168 typedef typeof *overrides DefMapType;
1169 for( DefMapType::const_iterator i = overrides->begin( ); i != overrides->end( ); ++i )
1171 typedef std::map< const char *, RefCountPtr< const Lang::Function >, charPtrLess > InstanceMapType;
1172 InstanceMapType & instanceMap = instance->overrides[ i->first ];
1173 typedef typeof i->second DefListType;
1174 InstanceMapType::iterator lastInsert = instanceMap.begin( );
1175 for( DefListType::const_iterator j = i->second.begin( ); j != i->second.end( ); ++j )
1177 throw Exceptions::NotImplemented( "addOverrides" );
1178 // RefCountPtr< const Lang::Value > untypedMethod = (*j)->init->value( dstgroup, pdfo, metaState, privateEnv );
1179 // typedef const Lang::Function FunType;
1180 // RefCountPtr< FunType > typedMethod = untypedMethod.down_cast< FunType >( );
1181 // if( typedMethod == NullPtr< FunType >( ) )
1182 // {
1183 // throw Exceptions::TypeMismatch( (*j)->init, untypedMethod->getTypeName( ), FunType::staticTypeName( ) );
1184 // }
1185 // lastInsert = instanceMap.insert( lastInsert, InstanceMapType::value_type( (*j)->id, typedMethod ) );
1190 void
1191 Lang::UserClass::gcMark( Kernel::GCMarkedSet & marked )
1193 throw Exceptions::NotImplemented( "UserClass::gcMark" );
1199 Lang::ClassMethodBase::ClassMethodBase( RefCountPtr< const Lang::Class > _self )
1200 : Lang::Function( 0 ), self( _self )
1202 std::cerr << "Warning: Lang::ClassMethodBase::ClassMethodBase initializes Lang::Function with 0 pointer to formals." << std::endl ;
1205 Lang::ClassMethodBase::~ClassMethodBase( )
1208 void
1209 Lang::ClassMethodBase::gcMark( Kernel::GCMarkedSet & marked )
1211 const_cast< Lang::Class * >( self.getPtr( ) )->gcMark( marked );
1214 bool
1215 Lang::ClassMethodBase::isTransforming( ) const
1217 return false;
1220 Lang::ClassMethodNew::ClassMethodNew( RefCountPtr< const Lang::Class > _self )
1221 : Lang::ClassMethodBase( _self )
1224 void
1225 Lang::ClassMethodNew::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1227 self->method_new( evalState, args, callLoc );
1230 Lang::ClassMethodIsa::ClassMethodIsa( RefCountPtr< const Lang::Class > _self )
1231 : Lang::ClassMethodBase( _self )
1234 void
1235 Lang::ClassMethodIsa::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1237 const size_t ARITY = 1;
1238 CHECK_ARITY( args, ARITY, Kernel::MethodId( Lang::Class::TypeID, "isa" ).prettyName( ) );
1240 typedef const Lang::Class ArgType;
1241 RefCountPtr< ArgType > T = args.getValue( 0 ).down_cast< ArgType >( );
1242 if( T == NullPtr< ArgType >( ) )
1244 throw Exceptions::CoreTypeMismatch( callLoc, Kernel::MethodId( Lang::Class::TypeID, "isa" ).prettyName( ), args, 0, ArgType::staticTypeName( ) );
1247 Kernel::ContRef cont = evalState->cont_;
1248 cont->takeValue( Kernel::ValueRef( new Lang::Boolean( self->method_isa( T ) ) ),
1249 evalState );