Merge branch 'ht/mutator'
[shapes.git] / source / classtypes.cc
blobc0231f2dcc5fcab6997c3f0097655ee32994fdaf
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 "shapestypes.h"
22 #include "shapesexceptions.h"
23 #include "astexpr.h"
24 #include "globals.h"
25 #include "consts.h"
26 #include "angleselect.h"
27 #include "astvar.h"
28 #include "astclass.h"
29 #include "autoonoff.h"
30 #include "shapescore.h"
31 #include "astfun.h"
33 #include <ctype.h>
34 #include <stack>
35 #include <string>
37 using namespace Shapes;
38 using namespace std;
41 Kernel::MethodId::MethodId( const RefCountPtr< const Lang::Class > & _myClass, const char * _msg )
42 : myClass( _myClass ), msg( _msg )
43 { }
45 Kernel::MethodId::~MethodId( )
46 { }
48 const char *
49 Kernel::MethodId::getIdentifier( ) const
51 return msg;
55 Lang::Instance::Instance( Kernel::PassedEnv _env, Kernel::PassedEnv _privateEnv, RefCountPtr< const Lang::Class > _myClass, bool _protectedAccess, const Kernel::PassedDyn & _my_dyn )
56 : env( _env ), privateEnv( _privateEnv ), warm2D( 0 ), warm3D( 0 ), my_dyn( _my_dyn ), myClass( _myClass ), prepared( false ), protectedAccess( _protectedAccess )
57 { }
59 DISPATCHIMPL( Instance );
61 Lang::Instance::~Instance( )
62 { }
64 void
65 Lang::Instance::gcMark( Kernel::GCMarkedSet & marked )
67 env->gcMark( marked );
68 privateEnv->gcMark( marked );
69 my_dyn->gcMark( marked );
73 void
74 Lang::Instance::prepare( Kernel::EvalState * evalState )
76 if( prepared )
78 return;
80 prepared = true;
82 for( std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = parents->begin( ); i != parents->end( ); ++i )
84 i->second->prepare( evalState );
88 myClass->prepareInstance( evalState, privateEnv );
91 Kernel::VariableHandle
92 Lang::Instance::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
94 if( ! myClass->getFinal( ) )
96 throw Exceptions::IllegalFinalReference( myClass->getPrettyName( ), fieldID );
99 return getLocalField( fieldID );
102 Kernel::VariableHandle
103 Lang::Instance::getLocalField( const char * fieldID ) const
105 if( protectedAccess )
107 if( myClass->isInProtectedGetSet( fieldID ) )
109 throw Exceptions::NotImplemented( "Instance::getLocalField" );
110 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
111 // return env->getVarHandle( key );
113 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
115 else
117 if( myClass->isInPublicGetSet( fieldID ) )
119 throw Exceptions::NotImplemented( "Instance::getLocalField" );
120 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
121 // return env->getVarHandle( key );
123 if( myClass->isInProtectedGetSet( fieldID ) )
125 throw Exceptions::ProtectedMemberPublicScope( myClass->getPrettyName( ), fieldID );
127 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
131 void
132 Lang::Instance::tackOn( const char * fieldID, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
134 if( ! myClass->getFinal( ) )
136 throw Exceptions::IllegalFinalReference( myClass->getPrettyName( ), fieldID );
139 tackOnLocal( fieldID, evalState, piece, callLoc );
142 void
143 Lang::Instance::tackOnLocal( const char * fieldID, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
145 if( protectedAccess )
147 if( myClass->isInProtectedSetSet( fieldID ) )
149 throw Exceptions::NotImplemented( "Instance::tackOnLocal" );
150 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
151 // env->tackOn( key, evalState, piece, callLoc );
152 return;
154 if( myClass->isInProtectedGetSet( fieldID ) )
156 throw Exceptions::MemberNotAssignable( myClass->getPrettyName( ), fieldID, Interaction::PROTECTED_SCOPE_NAME );
158 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
160 else
162 if( myClass->isInPublicSetSet( fieldID ) )
164 throw Exceptions::NotImplemented( "Instance::tackOnLocal" );
165 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
166 // env->tackOn( key, evalState, piece, callLoc );
167 return;
169 if( myClass->isInPublicGetSet( fieldID ) )
171 throw Exceptions::MemberNotAssignable( myClass->getPrettyName( ), fieldID, Interaction::PUBLIC_SCOPE_NAME );
173 if( myClass->isInProtectedGetSet( fieldID ) )
175 throw Exceptions::ProtectedMemberPublicScope( myClass->getPrettyName( ), fieldID );
177 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
181 RefCountPtr< const Lang::Function >
182 Lang::Instance::getMethod( Kernel::MethodId fieldID ) const
184 typedef typeof methodTable MethodMapType;
185 MethodMapType::iterator i = methodTable.find( fieldID );
186 if( i != methodTable.end( ) )
188 return i->second;
191 const RefCountPtr< const Lang::Class > & defClass = myClass->getMethodDefinitionClass( fieldID );
193 RefCountPtr< const Lang::Function > fun = NullPtr< const Lang::Function >( );
195 if( defClass == myClass )
197 fun = getLocalMethod( fieldID );
199 else
201 typedef typeof *parents ParentMapType;
202 ParentMapType::const_iterator p = parents->find( defClass );
203 if( p == parents->end( ) )
205 throw Exceptions::InternalError( "The class defining a method was not found among the parents." );
207 fun = p->second->getLocalMethod( fieldID );
210 methodTable.insert( i, MethodMapType::value_type( fieldID, fun ) );
212 return fun;
215 RefCountPtr< const Lang::Function >
216 Lang::Instance::getLocalMethod( Kernel::MethodId fieldID ) const
219 if( fieldID.getClass( ) == myClass )
221 Kernel::VariableHandle untypedFun = getLocalField( fieldID.getIdentifier( ) );
222 return untypedFun->getVal< const Lang::Function >( "getLocalMethod: The user was (almost) able to retrieve member data from super instance." );
225 typedef typeof overrides ClassMapType;
226 ClassMapType::const_iterator i = overrides.find( fieldID.getClass( ) );
227 if( i == overrides.end( ) )
229 throw Exceptions::NoSuchLocalMethod( myClass, fieldID );
232 typedef typeof i->second IdMapType;
234 IdMapType::const_iterator j = i->second.find( fieldID.getIdentifier( ) );
235 if( j == i->second.end( ) )
237 throw Exceptions::NoSuchLocalMethod( myClass, fieldID );
239 return j->second;
242 RefCountPtr< const Lang::Instance >
243 Lang::Instance::superReference( RefCountPtr< const Lang::Class > parent ) const
245 typedef typeof *parents ParentMapType;
246 ParentMapType::const_iterator p = parents->find( parent );
247 if( p == parents->end( ) )
249 throw Exceptions::SuperReferenceClassNotParent( myClass, parent );
251 return p->second;
254 RefCountPtr< const Lang::Geometric2D >
255 Lang::Instance::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
257 return RefCountPtr< const Lang::Geometric2D >( new Lang::TransformedInstance( tf, self.down_cast< const Lang::Instance >( ) ) );
260 void
261 Lang::Instance::shipout( std::ostream & os, Kernel::PageContentStates * pdfState, const Lang::Transform2D & tf ) const
263 if( ! myClass->method_isa( Lang::Drawable2D::TypeID ) )
265 throw Exceptions::InternalError( "Invoking Instance::shipout on a non Drawable object should not be possible" );
268 if( warm2D == 0 )
270 throw Exceptions::InternalError( "Instance::shipout: warm2D == 0." );
274 RefCountPtr< const Lang::Value > val = getMethod( Kernel::MethodId( Lang::Drawable2D::TypeID, Shapes::MESSAGE_DRAWABLE_DRAW_ID ) )->call( dstgroup, my_pdfo, & stateCopy, Kernel::EMPTY_ARGLIST );
275 if( dynamic_cast< const Lang::Void * >( val.getPtr( ) ) == 0 )
277 throw Exceptions::TypeMismatch( val->getTypeName( ), Lang::Void::staticTypeName( ) );
281 warm2D->getPile( )->shipout( os, pdfState, tf );
284 RefCountPtr< const Lang::ElementaryPath2D >
285 Lang::Instance::bbox( ) const
287 if( ! myClass->method_isa( Lang::Drawable2D::TypeID ) )
289 throw Exceptions::InternalError( "Invoking Instance::shipout on a non Drawable object should not be possible" );
292 if( warm2D == 0 )
294 throw Exceptions::InternalError( "Instance::shipout: warm2D == 0." );
297 return warm2D->getPile( )->bbox( );
300 RefCountPtr< const char >
301 Lang::Instance::staticTypeName( )
303 return strrefdup( "<Instance>" );
306 const RefCountPtr< const Lang::Class > &
307 Lang::Instance::getClass( ) const
309 return myClass;
312 void
313 Lang::Instance::show( std::ostream & os ) const
315 os << "Instance of class " << myClass->getPrettyName( ).getPtr( ) ;
319 Lang::TransformedInstance::TransformedInstance( const Lang::Transform2D & _tf, const RefCountPtr< const Lang::Instance > & _obj )
320 : tf( _tf ), obj( _obj )
323 Lang::TransformedInstance::~TransformedInstance( )
326 Kernel::VariableHandle
327 Lang::TransformedInstance::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
329 if( obj->getClass( )->isInTransformingSet( fieldID ) )
331 Kernel::VariableHandle argUntyped = obj->getField( fieldID, obj );
332 typedef const Lang::Geometric2D ArgType;
333 RefCountPtr< ArgType > arg = argUntyped->getVal< ArgType >( "<inside transformed instance getField>" );
334 return Kernel::VariableHandle( new Kernel::Variable( arg->transformed( tf, arg ) ) );
336 return obj->getField( fieldID, obj );
339 RefCountPtr< const Lang::Function >
340 Lang::TransformedInstance::getMethod( Kernel::MethodId fieldID ) const
342 /* Fetch the method first to make sure it exists, then see whether it is transforming.
344 RefCountPtr< const Lang::Function > arg = obj->getMethod( fieldID );
345 if( arg->isTransforming( ) )
347 return RefCountPtr< const Lang::Function >( new Lang::TransformedFunction2D( tf, arg ) );
349 return arg;
352 RefCountPtr< const Lang::Geometric2D >
353 Lang::TransformedInstance::transformed( const Lang::Transform2D & tf2, const RefCountPtr< const Lang::Geometric2D > & self ) const
355 return RefCountPtr< const Lang::Geometric2D >( new Lang::TransformedInstance( Lang::Transform2D( tf2, tf ) , obj ) );
359 void
360 Lang::TransformedInstance::shipout( std::ostream & os, Kernel::PageContentStates * pdfState, const Lang::Transform2D & tfIn ) const
362 obj->shipout( os, pdfState, Lang::Transform2D( tfIn, tf ) );
365 RefCountPtr< const Lang::ElementaryPath2D >
366 Lang::TransformedInstance::bbox( ) const
368 return obj->bbox( )->elementaryTransformed( tf );
371 RefCountPtr< const Lang::Class > Lang::TransformedInstance::TypeID( new Lang::SystemFinalClass( strrefdup( "TransformedInstance" ) ) );
372 TYPEINFOIMPL( TransformedInstance );
374 void
375 Lang::TransformedInstance::show( std::ostream & os ) const
377 os << "Transformed instance. The class is not available in this implementation." ;
380 void
381 Lang::TransformedInstance::gcMark( Kernel::GCMarkedSet & marked )
383 const_cast< Lang::Instance * >( obj.getPtr( ) )->gcMark( marked );
386 RefCountPtr< const char >
387 Kernel::MethodId::prettyName( ) const
389 string res = myClass->getPrettyName( ).getPtr( );
390 res += "#";
391 res += msg;
392 return strrefdup( res.c_str( ) );
395 bool
396 Kernel::operator < ( const Kernel::MethodId & mid1, const Kernel::MethodId & mid2 )
398 if( mid1.myClass < mid2.myClass )
400 return true;
402 if( mid1.myClass > mid2.myClass )
404 return false;
406 return strcmp( mid1.msg, mid2.msg ) < 0;
410 Lang::Class::Class( RefCountPtr< const char > _prettyName )
411 : prettyName( _prettyName ), selfRef( NullPtr< Lang::Class >( ) ), isFinal( false )
414 Lang::Class::~Class( )
416 /* Knowing that each class is reference counted, the destructor is being called as an effect
417 * of the reference count reaching zero. Thus, the self reference must simply be detached
418 * from this object, to avoid cyclic destruction.
420 selfRef.abortPtr( );
423 void
424 Lang::Class::setSelfRef( RefCountPtr< const Lang::Class > _selfRef ) const
426 selfRef = _selfRef; // selfRef is mutable!
427 /* Don't count this cyclic reference!
429 --*selfRef.getCounterPtr( );
432 RefCountPtr< const Lang::Class > Lang::Class::TypeID( new Lang::MetaClass( ) );
433 TYPEINFOIMPL( Class );
435 RefCountPtr< const char >
436 Lang::Class::getPrettyName( ) const
438 return prettyName;
441 bool
442 Lang::Class::isInPublicGetSet( const char * field ) const
444 return false;
447 bool
448 Lang::Class::isInPublicSetSet( const char * field ) const
450 return false;
453 bool
454 Lang::Class::isInProtectedGetSet( const char * field ) const
456 return false;
459 bool
460 Lang::Class::isInProtectedSetSet( const char * field ) const
462 return false;
465 bool
466 Lang::Class::isInTransformingSet( const char * field ) const
468 return false;
471 RefCountPtr< const Lang::Function >
472 Lang::Class::getMutator( const char * mutatorID ) const
474 throw Exceptions::InternalError( "Mutator request not defined for this type of class." );
477 void
478 Lang::Class::showAbstractSet( std::ostream & os ) const
480 os << "{" ;
481 typedef typeof abstractSet SetType;
482 for( SetType::const_iterator i = abstractSet.begin( ); i != abstractSet.end( ); ++i )
484 os << " " << i->prettyName( ) ;
486 os << " }" ;
490 void
491 Lang::Class::show( std::ostream & os ) const
493 os << "Pretty-name: " << prettyName.getPtr( ) ;
495 if( ! abstractSet.empty( ) )
497 os << ", +" ;
499 else
501 os << ", -" ;
503 os << "abstract" ;
505 if( isFinal )
507 os << ", +" ;
509 else
511 os << ", -" ;
513 os << "final" ;
516 bool isRepeatable = false;
519 isRepeatable = this->isRepeatableBase( );
521 catch( const Exceptions::MiscellaneousRequirement & ball )
523 /* Probably something saying that MetaClass is not repeatable... */
526 if( isRepeatable )
528 os << ", +" ;
530 else
532 os << ", -" ;
534 os << "repeatable" ;
538 Kernel::VariableHandle
539 Lang::Class::getField( const char * fieldId, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
541 if( strcmp( fieldId, "new" ) == 0 )
543 return Helpers::newValHandle( new Lang::ClassMethodNew( selfRef ) );
545 if( strcmp( fieldId, "isa" ) == 0 )
547 return Helpers::newValHandle( new Lang::ClassMethodIsa( selfRef ) );
549 if( strcmp( fieldId, "name" ) == 0 )
551 return Helpers::newValHandle( new Lang::String( prettyName ) );
553 throw Exceptions::NonExistentMember( getTypeName( ), fieldId );
556 bool
557 Lang::Class::getFinal( ) const
559 return isFinal;
562 const Lang::Class::MessageMapType &
563 Lang::Class::getMessageMap( ) const
565 return messageMap;
568 const RefCountPtr< const Lang::Class > &
569 Lang::Class::getMethodDefinitionClass( const Kernel::MethodId & method ) const
571 MessageMapType::const_iterator i = messageMap.find( method );
572 if( i == messageMap.end( ) )
574 throw Exceptions::NoSuchMethod( selfRef, method );
576 if( i->second.empty( ) )
578 throw Exceptions::InternalError( "Asking for class defining abstract method." );
580 return *( i->second.begin( ) );
584 void
585 Lang::Class::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
587 typedef typeof *_allParents SetType;
588 SetType::const_iterator i = _allParents->find( selfRef );
589 if( i != _allParents->end( ) )
591 _multiParents->insert( selfRef );
593 else
595 _allParents->insert( i, selfRef );
599 void
600 Lang::Class::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
602 /* Only UserClass instances do any preparations. */
605 DISPATCHIMPL( Class );
609 Lang::Object::Object( )
610 : Lang::Class( strrefdup( "Object" ) ), dummyEnv( NullPtr< Kernel::Environment >( ) )
613 Lang::Object::~Object( )
616 Kernel::ValueRef
617 Lang::Object::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
619 const size_t ARITY = 0;
620 CHECK_ARITY( args, ARITY, Kernel::MethodId( Lang::Class::TypeID, "new" ).prettyName( ) );
622 return RefCountPtr< const Lang::Geometric2D >( new Lang::Instance( dummyEnv, dummyEnv, selfRef, false, evalState->dyn_ ) );
625 bool
626 Lang::Object::method_isa( RefCountPtr< const Lang::Class > T ) const
628 return T == selfRef;
631 void
632 Lang::Object::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
634 /* There are no parent classes to consider. */
637 void
638 Lang::Object::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
640 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
643 void
644 Lang::Object::superNew( RefCountPtr< Lang::Instance > instanceSelf,
645 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
646 Kernel::Arguments & emptyArglist,
647 Kernel::EvalState * evalState ) const
649 std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = createdObjects->find( selfRef );
650 if( i != createdObjects->end( ) )
652 return;
654 Lang::Instance * newObj = new Lang::Instance( dummyEnv, dummyEnv, selfRef, true, evalState->dyn_ );
655 newObj->parents = createdObjects;
656 createdObjects->insert( i, pair< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >( selfRef, RefCountPtr< Lang::Instance >( newObj ) ) );
659 bool
660 Lang::Object::isRepeatableBase( ) const
662 return true;
665 void
666 Lang::Object::gcMark( Kernel::GCMarkedSet & marked )
669 Lang::MetaClass::MetaClass( )
670 : Lang::Class( strrefdup( "MetaClass" ) )
673 Lang::MetaClass::~MetaClass( )
676 Kernel::ValueRef
677 Lang::MetaClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
679 throw Exceptions::MiscellaneousRequirement( "Calling the \"new\" method of MetaClass is actually not the way to create new classes, sorry." );
682 bool
683 Lang::MetaClass::method_isa( RefCountPtr< const Lang::Class > T ) const
685 return T == Lang::Class::TypeID || T == Lang::THE_OBJECT;
688 void
689 Lang::MetaClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
691 /* There are no parent classes to consider. */
694 void
695 Lang::MetaClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
697 if( strcmp( id, "new" ) == 0 ||
698 strcmp( id, "isa" ) == 0 )
700 throw Exceptions::OverridingFinalMethod( caller, selfRef, id );
702 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
705 void
706 Lang::MetaClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
707 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
708 Kernel::Arguments & emptyArglist,
709 Kernel::EvalState * evalState ) const
711 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from MetaClass, sorry." );
714 void
715 Lang::MetaClass::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
717 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from MetaClass, sorry." );
720 bool
721 Lang::MetaClass::isRepeatableBase( ) const
723 throw Exceptions::MiscellaneousRequirement( "MetaClass can certainly not be a repeated base." );
726 void
727 Lang::MetaClass::gcMark( Kernel::GCMarkedSet & marked )
732 Lang::SystemFinalClass::SystemFinalClass( RefCountPtr< const char > _prettyName )
733 : Lang::Class( _prettyName ), registerMutatorFunction_( 0 )
736 Lang::SystemFinalClass::SystemFinalClass( RefCountPtr< const char > _prettyName, RegisterMutatorFunction registerMutatorFunction )
737 : Lang::Class( _prettyName ), registerMutatorFunction_( registerMutatorFunction )
740 Lang::SystemFinalClass::~SystemFinalClass( )
743 void
744 Lang::SystemFinalClass::initMutators( )
746 if( registerMutatorFunction_ != 0 )
748 registerMutatorFunction_( this );
752 void
753 Lang::SystemFinalClass::registerMutator( Lang::CoreFunction * fun )
755 typedef typeof mutators_ MapType;
756 mutators_.insert( MapType::value_type( fun->getTitle( ), RefCountPtr< const Lang::Function >( fun ) ) );
759 Kernel::ValueRef
760 Lang::SystemFinalClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
762 throw Exceptions::MiscellaneousRequirement( "Use dedicated syntax rather than calling the \"new\" method of a system class." );
765 bool
766 Lang::SystemFinalClass::method_isa( RefCountPtr< const Lang::Class > T ) const
768 return T == selfRef || T == Lang::THE_OBJECT;
771 void
772 Lang::SystemFinalClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
774 /* There are no parent classes to consider. */
777 void
778 Lang::SystemFinalClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
780 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
783 void
784 Lang::SystemFinalClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
785 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
786 Kernel::Arguments & emptyArglist,
787 Kernel::EvalState * evalState ) const
789 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from SystemFinalClass, sorry." );
792 bool
793 Lang::SystemFinalClass::isRepeatableBase( ) const
795 return false;
798 RefCountPtr< const Lang::Function >
799 Lang::SystemFinalClass::getMutator( const char * mutatorID ) const
801 typedef typeof mutators_ MapType;
802 MapType::const_iterator i = mutators_.find( mutatorID );
803 if( i == mutators_.end( ) )
805 throw Exceptions::NonExistentMutator( staticTypeName( ), mutatorID );
807 return i->second;
810 void
811 Lang::SystemFinalClass::gcMark( Kernel::GCMarkedSet & marked )
815 Lang::SystemVirtualInterface::SystemVirtualInterface( RefCountPtr< const char > _prettyName )
816 : Lang::Class( _prettyName )
819 Lang::SystemVirtualInterface::~SystemVirtualInterface( )
822 void
823 Lang::SystemVirtualInterface::addVirtual( const char * id )
825 messageMap[ Kernel::MethodId( selfRef, id ) ];
828 Kernel::ValueRef
829 Lang::SystemVirtualInterface::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
831 throw Exceptions::InstantiatingAbstractClass( selfRef );
834 bool
835 Lang::SystemVirtualInterface::method_isa( RefCountPtr< const Lang::Class > T ) const
837 throw Exceptions::InternalError( "method_isa was called on an abstract system class." );
840 void
841 Lang::SystemVirtualInterface::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
843 /* There are no parent classes to consider. */
846 void
847 Lang::SystemVirtualInterface::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
849 if( messageMap.find( Kernel::MethodId( selfRef, id ) ) == messageMap.end( ) )
851 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
855 void
856 Lang::SystemVirtualInterface::superNew( RefCountPtr< Lang::Instance > instanceSelf,
857 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
858 Kernel::Arguments & emptyArglist,
859 Kernel::EvalState * evalState ) const
862 bool
863 Lang::SystemVirtualInterface::isRepeatableBase( ) const
865 return true;
868 void
869 Lang::SystemVirtualInterface::gcMark( Kernel::GCMarkedSet & marked )
873 Lang::UserClass::UserClass( const Ast::ClassFunction * _classExpr,
874 Kernel::PassedEnv _env,
875 RefCountPtr< const char > _prettyName,
876 Kernel::EvaluatedFormals * _formals,
877 RefCountPtr< std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > > _parents,
878 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > > > _overrides,
879 bool _isFinal )
880 : Lang::Class( _prettyName ), classExpr( _classExpr ), formals( _formals ), env( _env ), parents( _parents ), overrides( _overrides )
882 Lang::Class::isFinal = _isFinal;
885 Lang::UserClass::~UserClass( )
887 delete formals;
890 void
891 Lang::UserClass::setupAndCheck( bool declaredAbstract )
893 for( std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > >::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
895 typedef typeof immediateParents SetType;
896 SetType::const_iterator j = immediateParents.find( i->first );
897 if( j != immediateParents.end( ) )
899 throw Exceptions::RepeatedImmediateParent( selfRef, i->first );
901 if( i->first->getFinal( ) )
903 throw Exceptions::InheritingFinal( selfRef, i->first );
905 immediateParents.insert( j, i->first );
908 findParents( & allParents, & multiParents );
910 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = multiParents.begin( ); i != multiParents.end( ); ++i )
912 if( ! (*i)->isRepeatableBase( ) )
914 throw Exceptions::IllegalRepeatedBase( selfRef, *i );
918 messageMap = classExpr->getLocalMessageMap( selfRef );
920 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = immediateParents.begin( ); i != immediateParents.end( ); ++i )
922 const MessageMapType & parentMap = (*i)->getMessageMap( );
923 for( MessageMapType::const_iterator j = parentMap.begin( ); j != parentMap.end( ); ++j )
925 std::set< RefCountPtr< const Lang::Class > > & messageSet = messageMap[ j->first ];
926 std::set< RefCountPtr< const Lang::Class > > res;
927 set_union( messageSet.begin( ), messageSet.end( ),
928 j->second.begin( ), j->second.end( ),
929 insert_iterator< std::set< RefCountPtr< const Lang::Class > > >( res, res.begin( ) ) );
930 messageSet = res;
935 typedef typeof *overrides MapType;
936 for( MapType::const_iterator i = overrides->begin( ); i != overrides->end( ); ++i )
938 typedef typeof allParents ClassSetType;
940 ClassSetType::const_iterator j = allParents.find( i->first );
941 if( j == allParents.end( ) )
943 throw Exceptions::OverridingNonParent( selfRef, i->first );
947 typedef typeof i->second ListType;
948 for( ListType::const_iterator j = i->second.begin( ); j != i->second.end( ); ++j )
950 i->first->assertMethodOverridable( (*j)->id_, selfRef );
951 std::set< RefCountPtr< const Lang::Class > > & messageSet = messageMap[ Kernel::MethodId( i->first, (*j)->id_ ) ];
952 messageSet.clear( );
953 messageSet.insert( messageSet.begin( ), selfRef );
962 std::cerr << "Message map of " << getPrettyName( ) << ":" << std::endl ;
964 std::set< Kernel::MethodId >::iterator j = abstractSet.begin( );
965 MessageMapType::iterator k = messageMap.begin( );
966 for( MessageMapType::const_iterator i = messageMap.begin( ); i != messageMap.end( ); ++i )
969 std::cerr << " " << i->first.prettyName( ) << " --> " ;
970 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator l = i->second.begin( ); l != i->second.end( ); ++l )
972 std::cerr << (*l)->getPrettyName( ) << " " ;
974 std::cerr << std::endl ;
976 if( i->second.size( ) == 1 )
978 continue;
980 if( i->second.empty( ) )
982 j = abstractSet.insert( j, i->first );
984 else
986 throw Exceptions::AmbiguousInheritedMethod( selfRef, i->first.prettyName( ), i->second );
991 if( ! declaredAbstract && ! abstractSet.empty( ) )
993 throw Exceptions::FailedToDeclareClassAbstract( selfRef, classExpr );
997 Kernel::ValueRef
998 Lang::UserClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1000 if( ! abstractSet.empty( ) )
1002 throw Exceptions::InstantiatingAbstractClass( selfRef );
1005 throw Exceptions::NotImplemented( "UserClass::method_new" );
1007 // // std::vector< VariableHandle > * envValues = new std::vector< VariableHandle >;
1008 // // envValues->reserve( argumentOrder->size( ) );
1009 // // while( envValues->size( ) < argumentOrder->size( ) )
1010 // // {
1011 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1012 // // }
1013 // Kernel::PassedEnv instanceEnv( new Kernel::Environment( Shapes::theEnvironmentList, evalState->env_, argumentOrder, RefCountPtr< std::vector< VariableHandle > >( envValues ) ) );
1015 // // std::vector< VariableHandle > * envValues = new std::vector< VariableHandle >;
1016 // // envValues->reserve( argumentOrder->size( ) );
1017 // // while( envValues->size( ) < argumentOrder->size( ) )
1018 // // {
1019 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1020 // // }
1021 // Kernel::PassedEnv privateEnv( new Kernel::Environment( Shapes::theEnvironmentList, instanceEnv, argumentOrder, RefCountPtr< std::vector< VariableHandle > >( envValues ) ) );
1023 // RefCountPtr< Lang::Instance > instanceSelf = RefCountPtr< Lang::Instance >( new Lang::Instance( instanceEnv, privateEnv, selfRef, false, evalState->dyn_ ) );
1025 // privateEnv->define( classExpr->loc( ), SELF_ID, RefCountPtr< const Lang::Geometric2D >( instanceSelf ), true ); /* true means constant */
1027 // RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects( new std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > );
1028 // instanceSelf->parents = createdObjects;
1030 // for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = multiParents.begin( ); i != multiParents.end( ); ++i )
1031 // {
1032 // (*i)->superNew( instanceSelf, createdObjects, EMPTY_ARGLIST, evalState );
1033 // }
1035 // args.mergeWithFormals( formals )
1036 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1038 // {
1039 // typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ListType;
1040 // for( ListType::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
1041 // {
1042 // RefCountPtr< Kernel::Arguments > superArgs( new Kernel::Arguments( true ) ); /* true means constant */
1043 // i->second->evaluate( superArgs, dstgroup, pdfo, metaState, initEnv );
1044 // i->first->superNew( instanceSelf, createdObjects, *superArgs, evalState );
1045 // }
1046 // }
1048 // classExpr->setupInstance( instanceEnv, privateEnv, dstgroup, pdfo, metaState, initEnv );
1050 // addOverrides( instanceSelf, privateEnv, dstgroup, pdfo, metaState );
1052 // instanceSelf->prepare( dstgroup, pdfo, metaState );
1054 // return RefCountPtr< const Lang::Geometric2D >( instanceSelf );
1057 bool
1058 Lang::UserClass::method_isa( RefCountPtr< const Lang::Class > T ) const
1060 if( T == selfRef )
1062 return true;
1064 return allParents.find( T ) != allParents.end( );
1067 void
1068 Lang::UserClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
1070 throw Exceptions::NotImplemented( "UserClass::findMultiplyInheritedClasses" );
1073 void
1074 Lang::UserClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
1076 if( classExpr->isInPublicGetSet( id ) || classExpr->isInAbstractSet( id ) )
1078 if( classExpr->isInFinalSet( id ) )
1080 throw Exceptions::OverridingFinalMethod( caller, selfRef, id );
1083 else
1085 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
1089 void
1090 Lang::UserClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
1091 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
1092 Kernel::Arguments & args,
1093 Kernel::EvalState * evalState ) const
1095 std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = createdObjects->find( selfRef );
1096 if( i != createdObjects->end( ) )
1098 return;
1101 throw Exceptions::NotImplemented( "UserClass::superNew" );
1103 // Kernel::PassedEnv instanceEnv( new Kernel::Environment( env ) );
1104 // Kernel::PassedEnv privateEnv( new Kernel::Environment( instanceEnv ) );
1106 // privateEnv->define( classExpr->loc( ), SELF_ID, RefCountPtr< const Lang::Geometric2D >( instanceSelf ), true ); /* true means constant */
1108 // args.mergeWithFormals( formals )
1109 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1111 // {
1112 // typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ListType;
1113 // for( ListType::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
1114 // {
1115 // RefCountPtr< Kernel::Arguments > superArgs( new Kernel::Arguments( true ) ); /* true means constant */
1116 // i->second->evaluate( superArgs, dstgroup, pdfo, metaState, initEnv );
1117 // i->first->superNew( instanceSelf, createdObjects, *superArgs, evalState );
1118 // }
1119 // }
1121 // classExpr->setupInstance( instanceEnv, privateEnv, dstgroup, pdfo, metaState, initEnv );
1123 // Lang::Instance * newObj = new Lang::Instance( instanceEnv, privateEnv, selfRef, true, evalState->dyn_ );
1124 // newObj->parents = createdObjects;
1125 // createdObjects->insert( i, pair< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >( selfRef, RefCountPtr< Lang::Instance >( newObj ) ) );
1128 void
1129 Lang::UserClass::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
1131 Lang::Class::findParents( _allParents, _multiParents );
1132 typedef typeof immediateParents SetType;
1133 for( SetType::const_iterator i = immediateParents.begin( ); i != immediateParents.end( ); ++i )
1135 (*i)->findParents( _allParents, _multiParents );
1139 bool
1140 Lang::UserClass::isRepeatableBase( ) const
1142 return classExpr->isRepeatableBase( );
1145 void
1146 Lang::UserClass::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
1148 classExpr->prepareInstance( evalState, privateEnv );
1152 bool
1153 Lang::UserClass::isInPublicGetSet( const char * field ) const
1155 return classExpr->isInPublicGetSet( field );
1158 bool
1159 Lang::UserClass::isInPublicSetSet( const char * field ) const
1161 return classExpr->isInPublicSetSet( field );
1164 bool
1165 Lang::UserClass::isInProtectedGetSet( const char * field ) const
1167 return classExpr->isInProtectedGetSet( field );
1170 bool
1171 Lang::UserClass::isInProtectedSetSet( const char * field ) const
1173 return classExpr->isInProtectedSetSet( field );
1176 bool
1177 Lang::UserClass::isInTransformingSet( const char * field ) const
1179 return classExpr->isInTransformingSet( field );
1183 void
1184 Lang::UserClass::addOverrides( Kernel::EvalState * evalState, RefCountPtr< Lang::Instance > instance, Kernel::PassedEnv privateEnv ) const
1186 typedef typeof *overrides DefMapType;
1187 for( DefMapType::const_iterator i = overrides->begin( ); i != overrides->end( ); ++i )
1189 typedef std::map< const char *, RefCountPtr< const Lang::Function >, charPtrLess > InstanceMapType;
1190 InstanceMapType & instanceMap = instance->overrides[ i->first ];
1191 typedef typeof i->second DefListType;
1192 InstanceMapType::iterator lastInsert = instanceMap.begin( );
1193 for( DefListType::const_iterator j = i->second.begin( ); j != i->second.end( ); ++j )
1195 throw Exceptions::NotImplemented( "addOverrides" );
1196 // RefCountPtr< const Lang::Value > untypedMethod = (*j)->init->value( dstgroup, pdfo, metaState, privateEnv );
1197 // typedef const Lang::Function FunType;
1198 // RefCountPtr< FunType > typedMethod = untypedMethod.down_cast< FunType >( );
1199 // if( typedMethod == NullPtr< FunType >( ) )
1200 // {
1201 // throw Exceptions::TypeMismatch( (*j)->init, untypedMethod->getTypeName( ), FunType::staticTypeName( ) );
1202 // }
1203 // lastInsert = instanceMap.insert( lastInsert, InstanceMapType::value_type( (*j)->id, typedMethod ) );
1208 void
1209 Lang::UserClass::gcMark( Kernel::GCMarkedSet & marked )
1211 throw Exceptions::NotImplemented( "UserClass::gcMark" );
1217 Lang::ClassMethodBase::ClassMethodBase( RefCountPtr< const Lang::Class > _self )
1218 : Lang::Function( 0 ), self( _self )
1220 std::cerr << "Warning: Lang::ClassMethodBase::ClassMethodBase initializes Lang::Function with 0 pointer to formals." << std::endl ;
1223 Lang::ClassMethodBase::~ClassMethodBase( )
1226 void
1227 Lang::ClassMethodBase::gcMark( Kernel::GCMarkedSet & marked )
1229 const_cast< Lang::Class * >( self.getPtr( ) )->gcMark( marked );
1232 bool
1233 Lang::ClassMethodBase::isTransforming( ) const
1235 return false;
1238 Lang::ClassMethodNew::ClassMethodNew( RefCountPtr< const Lang::Class > _self )
1239 : Lang::ClassMethodBase( _self )
1242 void
1243 Lang::ClassMethodNew::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1245 self->method_new( evalState, args, callLoc );
1248 Lang::ClassMethodIsa::ClassMethodIsa( RefCountPtr< const Lang::Class > _self )
1249 : Lang::ClassMethodBase( _self )
1252 void
1253 Lang::ClassMethodIsa::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1255 const size_t ARITY = 1;
1256 CHECK_ARITY( args, ARITY, Kernel::MethodId( Lang::Class::TypeID, "isa" ).prettyName( ) );
1258 typedef const Lang::Class ArgType;
1259 RefCountPtr< ArgType > T = args.getValue( 0 ).down_cast< ArgType >( );
1260 if( T == NullPtr< ArgType >( ) )
1262 throw Exceptions::CoreTypeMismatch( callLoc, Kernel::MethodId( Lang::Class::TypeID, "isa" ).prettyName( ), args, 0, ArgType::staticTypeName( ) );
1265 Kernel::ContRef cont = evalState->cont_;
1266 cont->takeValue( Kernel::ValueRef( new Lang::Boolean( self->method_isa( T ) ) ),
1267 evalState );