1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008, 2013 Henrik Tidefelt
21 #include "shapestypes.h"
22 #include "shapesexceptions.h"
23 #include "classexceptions.h"
27 #include "angleselect.h"
30 #include "autoonoff.h"
31 #include "shapescore.h"
33 #include "methodbase.h"
34 #include "corelocation.h"
42 using namespace Shapes
;
46 Kernel::MethodId::MethodId( const RefCountPtr
< const Lang::Class
> & myClass
, const char * name
)
47 : myClass_( myClass
), name_( name
)
50 Kernel::MethodId::~MethodId( )
54 Kernel::MethodId::getIdentifier( ) const
60 Lang::Instance::Instance( Kernel::PassedEnv _env
, Kernel::PassedEnv _privateEnv
, RefCountPtr
< const Lang::Class
> _myClass
, bool _protectedAccess
, const Kernel::PassedDyn
& _my_dyn
)
61 : env( _env
), privateEnv( _privateEnv
), warm2D( 0 ), warm3D( 0 ), my_dyn( _my_dyn
), myClass( _myClass
), prepared( false ), protectedAccess( _protectedAccess
)
64 DISPATCHIMPL( Instance
);
66 Lang::Instance::~Instance( )
70 Lang::Instance::gcMark( Kernel::GCMarkedSet
& marked
)
72 env
->gcMark( marked
);
73 privateEnv
->gcMark( marked
);
74 my_dyn
->gcMark( marked
);
79 Lang::Instance::prepare( Kernel::EvalState
* evalState
)
87 for( std::map
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> >::iterator i
= parents
->begin( ); i
!= parents
->end( ); ++i
)
89 i
->second
->prepare( evalState
);
93 myClass
->prepareInstance( evalState
, privateEnv
);
96 Kernel::VariableHandle
97 Lang::Instance::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & dummySelfRef
) const
99 if( ! myClass
->getFinal( ) )
101 throw Exceptions::IllegalFinalReference( myClass
->getPrettyName( ), fieldID
);
104 return getLocalField( fieldID
);
107 Kernel::VariableHandle
108 Lang::Instance::getLocalField( const char * fieldID
) const
110 if( protectedAccess
)
112 if( myClass
->isInProtectedGetSet( fieldID
) )
114 throw Exceptions::NotImplemented( "Instance::getLocalField" );
115 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
116 // return env->getVarHandle( key );
118 throw Exceptions::NonExistentMember( myClass
->getPrettyName( ), fieldID
);
122 if( myClass
->isInPublicGetSet( fieldID
) )
124 throw Exceptions::NotImplemented( "Instance::getLocalField" );
125 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
126 // return env->getVarHandle( key );
128 if( myClass
->isInProtectedGetSet( fieldID
) )
130 throw Exceptions::ProtectedMemberPublicScope( myClass
->getPrettyName( ), fieldID
);
132 throw Exceptions::NonExistentMember( myClass
->getPrettyName( ), fieldID
);
137 Lang::Instance::tackOn( const char * fieldID
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
, const Ast::SourceLocation
& callLoc
)
139 if( ! myClass
->getFinal( ) )
141 throw Exceptions::IllegalFinalReference( myClass
->getPrettyName( ), fieldID
);
144 tackOnLocal( fieldID
, evalState
, piece
, callLoc
);
148 Lang::Instance::tackOnLocal( const char * fieldID
, Kernel::EvalState
* evalState
, const RefCountPtr
< const Lang::Value
> & piece
, const Ast::SourceLocation
& callLoc
)
150 if( protectedAccess
)
152 if( myClass
->isInProtectedSetSet( fieldID
) )
154 throw Exceptions::NotImplemented( "Instance::tackOnLocal" );
155 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
156 // env->tackOn( key, evalState, piece, callLoc );
159 if( myClass
->isInProtectedGetSet( fieldID
) )
161 throw Exceptions::MemberNotAssignable( myClass
->getPrettyName( ), fieldID
, Interaction::PROTECTED_SCOPE_NAME
);
163 throw Exceptions::NonExistentMember( myClass
->getPrettyName( ), fieldID
);
167 if( myClass
->isInPublicSetSet( fieldID
) )
169 throw Exceptions::NotImplemented( "Instance::tackOnLocal" );
170 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
171 // env->tackOn( key, evalState, piece, callLoc );
174 if( myClass
->isInPublicGetSet( fieldID
) )
176 throw Exceptions::MemberNotAssignable( myClass
->getPrettyName( ), fieldID
, Interaction::PUBLIC_SCOPE_NAME
);
178 if( myClass
->isInProtectedGetSet( fieldID
) )
180 throw Exceptions::ProtectedMemberPublicScope( myClass
->getPrettyName( ), fieldID
);
182 throw Exceptions::NonExistentMember( myClass
->getPrettyName( ), fieldID
);
186 RefCountPtr
< const Lang::Function
>
187 Lang::Instance::getMethod( Kernel::MethodId fieldID
) const
189 typedef typeof methodTable MethodMapType
;
190 MethodMapType::iterator i
= methodTable
.find( fieldID
);
191 if( i
!= methodTable
.end( ) )
196 const RefCountPtr
< const Lang::Class
> & defClass
= myClass
->getMethodDefinitionClass( fieldID
);
198 RefCountPtr
< const Lang::Function
> fun
= NullPtr
< const Lang::Function
>( );
200 if( defClass
== myClass
)
202 fun
= getLocalMethod( fieldID
);
206 typedef typeof *parents ParentMapType
;
207 ParentMapType::const_iterator p
= parents
->find( defClass
);
208 if( p
== parents
->end( ) )
210 throw Exceptions::InternalError( "The class defining a method was not found among the parents." );
212 fun
= p
->second
->getLocalMethod( fieldID
);
215 methodTable
.insert( i
, MethodMapType::value_type( fieldID
, fun
) );
220 RefCountPtr
< const Lang::Function
>
221 Lang::Instance::getLocalMethod( Kernel::MethodId fieldID
) const
224 if( fieldID
.getClass( ) == myClass
)
226 Kernel::VariableHandle untypedFun
= getLocalField( fieldID
.getIdentifier( ) );
227 return untypedFun
->getVal
< const Lang::Function
>( "getLocalMethod: The user was (almost) able to retrieve member data from super instance." );
230 typedef typeof overrides ClassMapType
;
231 ClassMapType::const_iterator i
= overrides
.find( fieldID
.getClass( ) );
232 if( i
== overrides
.end( ) )
234 throw Exceptions::NoSuchLocalMethod( myClass
, fieldID
);
237 typedef typeof i
->second IdMapType
;
239 IdMapType::const_iterator j
= i
->second
.find( fieldID
.getIdentifier( ) );
240 if( j
== i
->second
.end( ) )
242 throw Exceptions::NoSuchLocalMethod( myClass
, fieldID
);
247 RefCountPtr
< const Lang::Instance
>
248 Lang::Instance::superReference( RefCountPtr
< const Lang::Class
> parent
) const
250 typedef typeof *parents ParentMapType
;
251 ParentMapType::const_iterator p
= parents
->find( parent
);
252 if( p
== parents
->end( ) )
254 throw Exceptions::SuperReferenceClassNotParent( myClass
, parent
);
259 RefCountPtr
< const Lang::Geometric2D
>
260 Lang::Instance::transformed( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Geometric2D
> & self
) const
262 return RefCountPtr
< const Lang::Geometric2D
>( new Lang::TransformedInstance( tf
, self
.down_cast
< const Lang::Instance
>( ) ) );
266 Lang::Instance::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tf
) const
268 if( ! myClass
->method_isa( Lang::Drawable2D::TypeID
) )
270 throw Exceptions::InternalError( "Invoking Instance::shipout on a non Drawable object should not be possible" );
275 throw Exceptions::InternalError( "Instance::shipout: warm2D == 0." );
279 RefCountPtr< const Lang::Value > val = getMethod( Kernel::MethodId( Lang::Drawable2D::TypeID, Shapes::MESSAGE_DRAWABLE_DRAW_ID ) )->call( dstgroup, my_pdfo, & stateCopy, Kernel::EMPTY_ARGLIST );
280 if( dynamic_cast< const Lang::Void * >( val.getPtr( ) ) == 0 )
282 throw Exceptions::TypeMismatch( val->getTypeName( ), Lang::Void::staticTypeName( ) );
286 warm2D
->getPile( )->shipout( os
, pdfState
, tf
);
289 RefCountPtr
< const Lang::ElementaryPath2D
>
290 Lang::Instance::bbox( Lang::Drawable2D::BoxType boxType
) const
292 if( ! myClass
->method_isa( Lang::Drawable2D::TypeID
) )
294 throw Exceptions::InternalError( "Invoking Instance::shipout on a non Drawable object should not be possible" );
299 throw Exceptions::InternalError( "Instance::shipout: warm2D == 0." );
302 return warm2D
->getPile( )->bbox( boxType
);
305 RefCountPtr
< const char >
306 Lang::Instance::staticTypeName( )
308 return strrefdup( "<Instance>" );
311 const RefCountPtr
< const Lang::Class
> &
312 Lang::Instance::getClass( ) const
318 Lang::Instance::show( std::ostream
& os
) const
320 os
<< "Instance of class " << myClass
->getPrettyName( ).getPtr( ) ;
324 Lang::TransformedInstance::TransformedInstance( const Lang::Transform2D
& _tf
, const RefCountPtr
< const Lang::Instance
> & _obj
)
325 : tf( _tf
), obj( _obj
)
328 Lang::TransformedInstance::~TransformedInstance( )
331 Kernel::VariableHandle
332 Lang::TransformedInstance::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & dummySelfRef
) const
334 if( obj
->getClass( )->isInTransformingSet( fieldID
) )
336 Kernel::VariableHandle argUntyped
= obj
->getField( fieldID
, obj
);
337 typedef const Lang::Geometric2D ArgType
;
338 RefCountPtr
< ArgType
> arg
= argUntyped
->getVal
< ArgType
>( "<inside transformed instance getField>" );
339 return Kernel::VariableHandle( new Kernel::Variable( arg
->transformed( tf
, arg
) ) );
341 return obj
->getField( fieldID
, obj
);
344 RefCountPtr
< const Lang::Function
>
345 Lang::TransformedInstance::getMethod( Kernel::MethodId fieldID
) const
347 /* Fetch the method first to make sure it exists, then see whether it is transforming.
349 RefCountPtr
< const Lang::Function
> arg
= obj
->getMethod( fieldID
);
350 if( arg
->isTransforming( ) )
352 return RefCountPtr
< const Lang::Function
>( new Lang::TransformedFunction2D( tf
, arg
) );
357 RefCountPtr
< const Lang::Geometric2D
>
358 Lang::TransformedInstance::transformed( const Lang::Transform2D
& tf2
, const RefCountPtr
< const Lang::Geometric2D
> & self
) const
360 return RefCountPtr
< const Lang::Geometric2D
>( new Lang::TransformedInstance( Lang::Transform2D( tf2
, tf
) , obj
) );
365 Lang::TransformedInstance::shipout( std::ostream
& os
, Kernel::PageContentStates
* pdfState
, const Lang::Transform2D
& tfIn
) const
367 obj
->shipout( os
, pdfState
, Lang::Transform2D( tfIn
, tf
) );
370 RefCountPtr
< const Lang::ElementaryPath2D
>
371 Lang::TransformedInstance::bbox( Lang::Drawable2D::BoxType boxType
) const
373 return obj
->bbox( boxType
)->elementaryTransformed( tf
);
376 RefCountPtr
< const Lang::Class
> Lang::TransformedInstance::TypeID( new Lang::SystemFinalClass( strrefdup( "TransformedInstance" ) ) );
377 TYPEINFOIMPL( TransformedInstance
);
380 Lang::TransformedInstance::show( std::ostream
& os
) const
382 os
<< "Transformed instance. The class is not available in this implementation." ;
386 Lang::TransformedInstance::gcMark( Kernel::GCMarkedSet
& marked
)
388 const_cast< Lang::Instance
* >( obj
.getPtr( ) )->gcMark( marked
);
391 RefCountPtr
< const char >
392 Kernel::MethodId::prettyName( ) const
394 string res
= myClass_
->getPrettyName( ).getPtr( );
397 return strrefdup( res
.c_str( ) );
401 Kernel::operator < ( const Kernel::MethodId
& mid1
, const Kernel::MethodId
& mid2
)
403 if( mid1
.myClass_
< mid2
.myClass_
)
407 if( mid1
.myClass_
> mid2
.myClass_
)
411 return strcmp( mid1
.name_
, mid2
.name_
) < 0;
415 Lang::Class::Class( RefCountPtr
< const char > _prettyName
)
416 : prettyName( _prettyName
), selfRef( NullPtr
< Lang::Class
>( ) ), isFinal( false )
419 Lang::Class::~Class( )
421 /* Knowing that each class is reference counted, the destructor is being called as an effect
422 * of the reference count reaching zero. Thus, the self reference must simply be detached
423 * from this object, to avoid cyclic destruction.
429 Lang::Class::setSelfRef( RefCountPtr
< const Lang::Class
> _selfRef
) const
431 selfRef
= _selfRef
; // selfRef is mutable!
432 /* Don't count this cyclic reference!
434 --*selfRef
.getCounterPtr( );
437 RefCountPtr
< const Lang::Class
> Lang::Class::TypeID( new Lang::MetaClass( ) );
438 TYPEINFOIMPL( Class
);
440 RefCountPtr
< const char >
441 Lang::Class::getPrettyName( ) const
447 Lang::Class::isInPublicGetSet( const char * field
) const
453 Lang::Class::isInPublicSetSet( const char * field
) const
459 Lang::Class::isInProtectedGetSet( const char * field
) const
465 Lang::Class::isInProtectedSetSet( const char * field
) const
471 Lang::Class::isInTransformingSet( const char * field
) const
476 Kernel::VariableHandle
477 Lang::Class::getMethod( const RefCountPtr
< const Lang::Value
> & self
, const char * methodID
) const
479 throw Exceptions::InternalError( "Method request not defined for this type of class." );
482 RefCountPtr
< const Lang::Function
>
483 Lang::Class::getMutator( const char * mutatorID
) const
485 throw Exceptions::InternalError( "Mutator request not defined for this type of class." );
489 Lang::Class::showAbstractSet( std::ostream
& os
) const
492 typedef typeof abstractSet SetType
;
493 for( SetType::const_iterator i
= abstractSet
.begin( ); i
!= abstractSet
.end( ); ++i
)
495 os
<< " " << i
->prettyName( ) ;
502 Lang::Class::show( std::ostream
& os
) const
504 os
<< "Pretty-name: " << prettyName
.getPtr( ) ;
506 if( ! abstractSet
.empty( ) )
527 bool isRepeatable
= false;
530 isRepeatable
= this->isRepeatableBase( );
532 catch( const Exceptions::MiscellaneousRequirement
& ball
)
534 /* Probably something saying that MetaClass is not repeatable... */
549 Kernel::VariableHandle
550 Lang::Class::getField( const char * fieldId
, const RefCountPtr
< const Lang::Value
> & dummySelfRef
) const
552 if( strcmp( fieldId
, "new" ) == 0 )
554 return Helpers::newValHandle( new Lang::ClassMethodNew( selfRef
) );
556 if( strcmp( fieldId
, "isa" ) == 0 )
558 return Helpers::newValHandle( new Lang::ClassMethodIsa( selfRef
) );
560 if( strcmp( fieldId
, "name" ) == 0 )
562 return Helpers::newValHandle( new Lang::String( prettyName
) );
564 throw Exceptions::NonExistentMember( getTypeName( ), fieldId
);
568 Lang::Class::getFinal( ) const
573 const Lang::Class::MessageMapType
&
574 Lang::Class::getMessageMap( ) const
579 const RefCountPtr
< const Lang::Class
> &
580 Lang::Class::getMethodDefinitionClass( const Kernel::MethodId
& method
) const
582 MessageMapType::const_iterator i
= messageMap
.find( method
);
583 if( i
== messageMap
.end( ) )
585 throw Exceptions::NoSuchMethod( selfRef
, method
);
587 if( i
->second
.empty( ) )
589 throw Exceptions::InternalError( "Asking for class defining abstract method." );
591 return *( i
->second
.begin( ) );
596 Lang::Class::findParents( std::set
< RefCountPtr
< const Lang::Class
> > * _allParents
, std::set
< RefCountPtr
< const Lang::Class
> > * _multiParents
) const
598 typedef typeof *_allParents SetType
;
599 SetType::const_iterator i
= _allParents
->find( selfRef
);
600 if( i
!= _allParents
->end( ) )
602 _multiParents
->insert( selfRef
);
606 _allParents
->insert( i
, selfRef
);
611 Lang::Class::prepareInstance( Kernel::EvalState
* evalState
, Kernel::PassedEnv privateEnv
) const
613 /* Only UserClass instances do any preparations. */
616 DISPATCHIMPL( Class
);
620 Lang::Object::Object( )
621 : Lang::Class( strrefdup( "Object" ) ), dummyEnv( NullPtr
< Kernel::Environment
>( ) )
624 Lang::Object::~Object( )
628 Lang::Object::method_new( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
630 const size_t ARITY
= 0;
631 CHECK_ARITY( args
, ARITY
, new Interaction::MethodLocation( Kernel::MethodId( Lang::Class::TypeID
, "new" ) ) );
633 return RefCountPtr
< const Lang::Geometric2D
>( new Lang::Instance( dummyEnv
, dummyEnv
, selfRef
, false, evalState
->dyn_
) );
637 Lang::Object::method_isa( RefCountPtr
< const Lang::Class
> T
) const
643 Lang::Object::findMultiplyInheritedClasses( std::set
< RefCountPtr
< Lang::Class
> > * visited
, std::set
< RefCountPtr
< Lang::Class
> > * found
) const
645 /* There are no parent classes to consider. */
649 Lang::Object::assertMethodOverridable( const char * id
, const RefCountPtr
< const Lang::Class
> & caller
) const
651 throw Exceptions::OverridingUndeclaredMethod( caller
, selfRef
, id
);
655 Lang::Object::superNew( RefCountPtr
< Lang::Instance
> instanceSelf
,
656 RefCountPtr
< std::map
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> > > createdObjects
,
657 Kernel::Arguments
& emptyArglist
,
658 Kernel::EvalState
* evalState
) const
660 std::map
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> >::iterator i
= createdObjects
->find( selfRef
);
661 if( i
!= createdObjects
->end( ) )
665 Lang::Instance
* newObj
= new Lang::Instance( dummyEnv
, dummyEnv
, selfRef
, true, evalState
->dyn_
);
666 newObj
->parents
= createdObjects
;
667 createdObjects
->insert( i
, pair
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> >( selfRef
, RefCountPtr
< Lang::Instance
>( newObj
) ) );
671 Lang::Object::isRepeatableBase( ) const
677 Lang::Object::gcMark( Kernel::GCMarkedSet
& marked
)
680 Lang::MetaClass::MetaClass( )
681 : Lang::Class( strrefdup( "MetaClass" ) )
684 Lang::MetaClass::~MetaClass( )
688 Lang::MetaClass::method_new( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
690 throw Exceptions::MiscellaneousRequirement( "Calling the \"new\" method of MetaClass is actually not the way to create new classes, sorry." );
694 Lang::MetaClass::method_isa( RefCountPtr
< const Lang::Class
> T
) const
696 return T
== Lang::Class::TypeID
|| T
== Lang::THE_OBJECT
;
700 Lang::MetaClass::findMultiplyInheritedClasses( std::set
< RefCountPtr
< Lang::Class
> > * visited
, std::set
< RefCountPtr
< Lang::Class
> > * found
) const
702 /* There are no parent classes to consider. */
706 Lang::MetaClass::assertMethodOverridable( const char * id
, const RefCountPtr
< const Lang::Class
> & caller
) const
708 if( strcmp( id
, "new" ) == 0 ||
709 strcmp( id
, "isa" ) == 0 )
711 throw Exceptions::OverridingFinalMethod( caller
, selfRef
, id
);
713 throw Exceptions::OverridingUndeclaredMethod( caller
, selfRef
, id
);
717 Lang::MetaClass::superNew( RefCountPtr
< Lang::Instance
> instanceSelf
,
718 RefCountPtr
< std::map
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> > > createdObjects
,
719 Kernel::Arguments
& emptyArglist
,
720 Kernel::EvalState
* evalState
) const
722 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from MetaClass, sorry." );
726 Lang::MetaClass::findParents( std::set
< RefCountPtr
< const Lang::Class
> > * _allParents
, std::set
< RefCountPtr
< const Lang::Class
> > * _multiParents
) const
728 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from MetaClass, sorry." );
732 Lang::MetaClass::isRepeatableBase( ) const
734 throw Exceptions::MiscellaneousRequirement( "MetaClass can certainly not be a repeated base." );
738 Lang::MetaClass::gcMark( Kernel::GCMarkedSet
& marked
)
743 Lang::SystemFinalClass::SystemFinalClass( RefCountPtr
< const char > _prettyName
)
744 : Lang::Class( _prettyName
), registerFunction_( 0 )
747 Lang::SystemFinalClass::SystemFinalClass( RefCountPtr
< const char > _prettyName
, RegisterFunction registerFunction
)
748 : Lang::Class( _prettyName
), registerFunction_( registerFunction
)
751 Lang::SystemFinalClass::~SystemFinalClass( )
755 Lang::SystemFinalClass::init( )
757 if( registerFunction_
!= 0 )
759 registerFunction_( this );
764 Lang::SystemFinalClass::registerMethod( Kernel::MethodFactoryBase
* factory
)
766 typedef typeof methods_ MapType
;
767 methods_
.insert( MapType::value_type( factory
->field( ), RefCountPtr
< const Kernel::MethodFactoryBase
>( factory
) ) );
771 Lang::SystemFinalClass::registerMutator( Lang::CoreMutator
* mut
, const char * alias
)
773 RefCountPtr
< const Lang::Function
> funRef
= RefCountPtr
< const Lang::Function
>( mut
);
774 typedef typeof mutators_ MapType
;
775 mutators_
.insert( MapType::value_type( mut
->name( ), funRef
) );
778 mutators_
.insert( MapType::value_type( alias
, funRef
) );
783 Lang::SystemFinalClass::method_new( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
785 throw Exceptions::MiscellaneousRequirement( "Use dedicated syntax rather than calling the \"new\" method of a system class." );
789 Lang::SystemFinalClass::method_isa( RefCountPtr
< const Lang::Class
> T
) const
791 return T
== selfRef
|| T
== Lang::THE_OBJECT
;
795 Lang::SystemFinalClass::findMultiplyInheritedClasses( std::set
< RefCountPtr
< Lang::Class
> > * visited
, std::set
< RefCountPtr
< Lang::Class
> > * found
) const
797 /* There are no parent classes to consider. */
801 Lang::SystemFinalClass::assertMethodOverridable( const char * id
, const RefCountPtr
< const Lang::Class
> & caller
) const
803 throw Exceptions::OverridingUndeclaredMethod( caller
, selfRef
, id
);
807 Lang::SystemFinalClass::superNew( RefCountPtr
< Lang::Instance
> instanceSelf
,
808 RefCountPtr
< std::map
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> > > createdObjects
,
809 Kernel::Arguments
& emptyArglist
,
810 Kernel::EvalState
* evalState
) const
812 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from SystemFinalClass, sorry." );
816 Lang::SystemFinalClass::isRepeatableBase( ) const
821 Kernel::VariableHandle
822 Lang::SystemFinalClass::getMethod( const RefCountPtr
< const Lang::Value
> & self
, const char * methodID
) const
824 typedef typeof methods_ MapType
;
825 MapType::const_iterator i
= methods_
.find( methodID
);
826 if( i
== methods_
.end( ) )
828 throw Exceptions::NonExistentMember( self
->getTypeName( ), methodID
);
830 return i
->second
->build( self
);
833 RefCountPtr
< const Lang::Function
>
834 Lang::SystemFinalClass::getMutator( const char * mutatorID
) const
836 typedef typeof mutators_ MapType
;
837 MapType::const_iterator i
= mutators_
.find( mutatorID
);
838 if( i
== mutators_
.end( ) )
840 throw Exceptions::NonExistentMutator( staticTypeName( ), mutatorID
);
846 Lang::SystemFinalClass::gcMark( Kernel::GCMarkedSet
& marked
)
850 Lang::SystemVirtualInterface::SystemVirtualInterface( RefCountPtr
< const char > _prettyName
)
851 : Lang::Class( _prettyName
)
854 Lang::SystemVirtualInterface::~SystemVirtualInterface( )
858 Lang::SystemVirtualInterface::addVirtual( const char * id
)
860 messageMap
[ Kernel::MethodId( selfRef
, id
) ];
864 Lang::SystemVirtualInterface::method_new( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
866 throw Exceptions::InstantiatingAbstractClass( selfRef
);
870 Lang::SystemVirtualInterface::method_isa( RefCountPtr
< const Lang::Class
> T
) const
872 throw Exceptions::InternalError( "method_isa was called on an abstract system class." );
876 Lang::SystemVirtualInterface::findMultiplyInheritedClasses( std::set
< RefCountPtr
< Lang::Class
> > * visited
, std::set
< RefCountPtr
< Lang::Class
> > * found
) const
878 /* There are no parent classes to consider. */
882 Lang::SystemVirtualInterface::assertMethodOverridable( const char * id
, const RefCountPtr
< const Lang::Class
> & caller
) const
884 if( messageMap
.find( Kernel::MethodId( selfRef
, id
) ) == messageMap
.end( ) )
886 throw Exceptions::OverridingUndeclaredMethod( caller
, selfRef
, id
);
891 Lang::SystemVirtualInterface::superNew( RefCountPtr
< Lang::Instance
> instanceSelf
,
892 RefCountPtr
< std::map
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> > > createdObjects
,
893 Kernel::Arguments
& emptyArglist
,
894 Kernel::EvalState
* evalState
) const
898 Lang::SystemVirtualInterface::isRepeatableBase( ) const
904 Lang::SystemVirtualInterface::gcMark( Kernel::GCMarkedSet
& marked
)
908 Lang::UserClass::UserClass( const Ast::ClassFunction
* _classExpr
,
909 // Kernel::PassedEnv _env,
910 RefCountPtr
< const char > _prettyName
,
911 Kernel::EvaluatedFormals
* _formals
,
912 RefCountPtr
< std::list
< std::pair
< RefCountPtr
< const Lang::Class
>, const Ast::ArgListExprs
* > > > _parents
,
913 RefCountPtr
< std::map
< RefCountPtr
< const Lang::Class
>, std::list
< Ast::MemberDeclaration
* > > > _overrides
,
915 : Lang::Class( _prettyName
), classExpr( _classExpr
), formals( _formals
), parents( _parents
), overrides( _overrides
)
917 Lang::Class::isFinal
= _isFinal
;
920 Lang::UserClass::~UserClass( )
926 Lang::UserClass::setupAndCheck( bool declaredAbstract
)
928 for( std::list
< std::pair
< RefCountPtr
< const Lang::Class
>, const Ast::ArgListExprs
* > >::const_iterator i
= parents
->begin( ); i
!= parents
->end( ); ++i
)
930 typedef typeof immediateParents SetType
;
931 SetType::const_iterator j
= immediateParents
.find( i
->first
);
932 if( j
!= immediateParents
.end( ) )
934 throw Exceptions::RepeatedImmediateParent( selfRef
, i
->first
);
936 if( i
->first
->getFinal( ) )
938 throw Exceptions::InheritingFinal( selfRef
, i
->first
);
940 immediateParents
.insert( j
, i
->first
);
943 findParents( & allParents
, & multiParents
);
945 for( std::set
< RefCountPtr
< const Lang::Class
> >::const_iterator i
= multiParents
.begin( ); i
!= multiParents
.end( ); ++i
)
947 if( ! (*i
)->isRepeatableBase( ) )
949 throw Exceptions::IllegalRepeatedBase( selfRef
, *i
);
953 messageMap
= classExpr
->getLocalMessageMap( selfRef
);
955 for( std::set
< RefCountPtr
< const Lang::Class
> >::const_iterator i
= immediateParents
.begin( ); i
!= immediateParents
.end( ); ++i
)
957 const MessageMapType
& parentMap
= (*i
)->getMessageMap( );
958 for( MessageMapType::const_iterator j
= parentMap
.begin( ); j
!= parentMap
.end( ); ++j
)
960 std::set
< RefCountPtr
< const Lang::Class
> > & messageSet
= messageMap
[ j
->first
];
961 std::set
< RefCountPtr
< const Lang::Class
> > res
;
962 set_union( messageSet
.begin( ), messageSet
.end( ),
963 j
->second
.begin( ), j
->second
.end( ),
964 insert_iterator
< std::set
< RefCountPtr
< const Lang::Class
> > >( res
, res
.begin( ) ) );
970 typedef typeof *overrides MapType
;
971 for( MapType::const_iterator i
= overrides
->begin( ); i
!= overrides
->end( ); ++i
)
973 typedef typeof allParents ClassSetType
;
975 ClassSetType::const_iterator j
= allParents
.find( i
->first
);
976 if( j
== allParents
.end( ) )
978 throw Exceptions::OverridingNonParent( selfRef
, i
->first
);
982 typedef typeof i
->second ListType
;
983 for( ListType::const_iterator j
= i
->second
.begin( ); j
!= i
->second
.end( ); ++j
)
985 i
->first
->assertMethodOverridable( (*j
)->id_
, selfRef
);
986 std::set
< RefCountPtr
< const Lang::Class
> > & messageSet
= messageMap
[ Kernel::MethodId( i
->first
, (*j
)->id_
) ];
988 messageSet
.insert( messageSet
.begin( ), selfRef
);
996 // std::cerr << "Message map of " << getPrettyName( ) << ":" << std::endl ;
997 std::set
< Kernel::MethodId
>::iterator j
= abstractSet
.begin( );
998 for( MessageMapType::const_iterator i
= messageMap
.begin( ); i
!= messageMap
.end( ); ++i
)
1000 // std::cerr << " " << i->first.prettyName( ) << " --> " ;
1001 // for( std::set< RefCountPtr< const Lang::Class > >::const_iterator l = i->second.begin( ); l != i->second.end( ); ++l )
1003 // std::cerr << (*l)->getPrettyName( ) << " " ;
1005 // std::cerr << std::endl ;
1006 if( i
->second
.size( ) == 1 )
1010 if( i
->second
.empty( ) )
1012 j
= abstractSet
.insert( j
, i
->first
);
1016 throw Exceptions::AmbiguousInheritedMethod( selfRef
, i
->first
.prettyName( ), i
->second
);
1021 if( ! declaredAbstract
&& ! abstractSet
.empty( ) )
1023 throw Exceptions::FailedToDeclareClassAbstract( selfRef
, classExpr
);
1028 Lang::UserClass::method_new( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1030 if( ! abstractSet
.empty( ) )
1032 throw Exceptions::InstantiatingAbstractClass( selfRef
);
1035 throw Exceptions::NotImplemented( "UserClass::method_new" );
1037 // // std::vector< VariableHandle > * envValues = new std::vector< VariableHandle >;
1038 // // envValues->reserve( argumentOrder->size( ) );
1039 // // while( envValues->size( ) < argumentOrder->size( ) )
1041 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1043 // Kernel::PassedEnv instanceEnv( new Kernel::Environment( Shapes::theEnvironmentList, evalState->env_, argumentOrder, RefCountPtr< std::vector< VariableHandle > >( envValues ) ) );
1045 // // std::vector< VariableHandle > * envValues = new std::vector< VariableHandle >;
1046 // // envValues->reserve( argumentOrder->size( ) );
1047 // // while( envValues->size( ) < argumentOrder->size( ) )
1049 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1051 // Kernel::PassedEnv privateEnv( new Kernel::Environment( Shapes::theEnvironmentList, instanceEnv, argumentOrder, RefCountPtr< std::vector< VariableHandle > >( envValues ) ) );
1053 // RefCountPtr< Lang::Instance > instanceSelf = RefCountPtr< Lang::Instance >( new Lang::Instance( instanceEnv, privateEnv, selfRef, false, evalState->dyn_ ) );
1055 // privateEnv->define( classExpr->loc( ), SELF_ID, RefCountPtr< const Lang::Geometric2D >( instanceSelf ), true ); /* true means constant */
1057 // RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects( new std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > );
1058 // instanceSelf->parents = createdObjects;
1060 // for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = multiParents.begin( ); i != multiParents.end( ); ++i )
1062 // (*i)->superNew( instanceSelf, createdObjects, EMPTY_ARGLIST, evalState );
1065 // args.mergeWithFormals( formals )
1066 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1069 // typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ListType;
1070 // for( ListType::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
1072 // RefCountPtr< Kernel::Arguments > superArgs( new Kernel::Arguments( true ) ); /* true means constant */
1073 // i->second->evaluate( superArgs, dstgroup, pdfo, metaState, initEnv );
1074 // i->first->superNew( instanceSelf, createdObjects, *superArgs, evalState );
1078 // classExpr->setupInstance( instanceEnv, privateEnv, dstgroup, pdfo, metaState, initEnv );
1080 // addOverrides( instanceSelf, privateEnv, dstgroup, pdfo, metaState );
1082 // instanceSelf->prepare( dstgroup, pdfo, metaState );
1084 // return RefCountPtr< const Lang::Geometric2D >( instanceSelf );
1088 Lang::UserClass::method_isa( RefCountPtr
< const Lang::Class
> T
) const
1094 return allParents
.find( T
) != allParents
.end( );
1098 Lang::UserClass::findMultiplyInheritedClasses( std::set
< RefCountPtr
< Lang::Class
> > * visited
, std::set
< RefCountPtr
< Lang::Class
> > * found
) const
1100 throw Exceptions::NotImplemented( "UserClass::findMultiplyInheritedClasses" );
1104 Lang::UserClass::assertMethodOverridable( const char * id
, const RefCountPtr
< const Lang::Class
> & caller
) const
1106 if( classExpr
->isInPublicGetSet( id
) || classExpr
->isInAbstractSet( id
) )
1108 if( classExpr
->isInFinalSet( id
) )
1110 throw Exceptions::OverridingFinalMethod( caller
, selfRef
, id
);
1115 throw Exceptions::OverridingUndeclaredMethod( caller
, selfRef
, id
);
1120 Lang::UserClass::superNew( RefCountPtr
< Lang::Instance
> instanceSelf
,
1121 RefCountPtr
< std::map
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> > > createdObjects
,
1122 Kernel::Arguments
& args
,
1123 Kernel::EvalState
* evalState
) const
1125 std::map
< RefCountPtr
< const Lang::Class
>, RefCountPtr
< Lang::Instance
> >::iterator i
= createdObjects
->find( selfRef
);
1126 if( i
!= createdObjects
->end( ) )
1131 throw Exceptions::NotImplemented( "UserClass::superNew" );
1133 // Kernel::PassedEnv instanceEnv( new Kernel::Environment( env ) );
1134 // Kernel::PassedEnv privateEnv( new Kernel::Environment( instanceEnv ) );
1136 // privateEnv->define( classExpr->loc( ), SELF_ID, RefCountPtr< const Lang::Geometric2D >( instanceSelf ), true ); /* true means constant */
1138 // args.mergeWithFormals( formals )
1139 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1142 // typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ListType;
1143 // for( ListType::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
1145 // RefCountPtr< Kernel::Arguments > superArgs( new Kernel::Arguments( true ) ); /* true means constant */
1146 // i->second->evaluate( superArgs, dstgroup, pdfo, metaState, initEnv );
1147 // i->first->superNew( instanceSelf, createdObjects, *superArgs, evalState );
1151 // classExpr->setupInstance( instanceEnv, privateEnv, dstgroup, pdfo, metaState, initEnv );
1153 // Lang::Instance * newObj = new Lang::Instance( instanceEnv, privateEnv, selfRef, true, evalState->dyn_ );
1154 // newObj->parents = createdObjects;
1155 // createdObjects->insert( i, pair< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >( selfRef, RefCountPtr< Lang::Instance >( newObj ) ) );
1159 Lang::UserClass::findParents( std::set
< RefCountPtr
< const Lang::Class
> > * _allParents
, std::set
< RefCountPtr
< const Lang::Class
> > * _multiParents
) const
1161 Lang::Class::findParents( _allParents
, _multiParents
);
1162 typedef typeof immediateParents SetType
;
1163 for( SetType::const_iterator i
= immediateParents
.begin( ); i
!= immediateParents
.end( ); ++i
)
1165 (*i
)->findParents( _allParents
, _multiParents
);
1170 Lang::UserClass::isRepeatableBase( ) const
1172 return classExpr
->isRepeatableBase( );
1176 Lang::UserClass::prepareInstance( Kernel::EvalState
* evalState
, Kernel::PassedEnv privateEnv
) const
1178 classExpr
->prepareInstance( evalState
, privateEnv
);
1183 Lang::UserClass::isInPublicGetSet( const char * field
) const
1185 return classExpr
->isInPublicGetSet( field
);
1189 Lang::UserClass::isInPublicSetSet( const char * field
) const
1191 return classExpr
->isInPublicSetSet( field
);
1195 Lang::UserClass::isInProtectedGetSet( const char * field
) const
1197 return classExpr
->isInProtectedGetSet( field
);
1201 Lang::UserClass::isInProtectedSetSet( const char * field
) const
1203 return classExpr
->isInProtectedSetSet( field
);
1207 Lang::UserClass::isInTransformingSet( const char * field
) const
1209 return classExpr
->isInTransformingSet( field
);
1214 Lang::UserClass::addOverrides( Kernel::EvalState
* evalState
, RefCountPtr
< Lang::Instance
> instance
, Kernel::PassedEnv privateEnv
) const
1216 typedef typeof *overrides DefMapType
;
1217 for( DefMapType::const_iterator i
= overrides
->begin( ); i
!= overrides
->end( ); ++i
)
1219 // typedef std::map< const char *, RefCountPtr< const Lang::Function >, charPtrLess > InstanceMapType;
1220 // InstanceMapType & instanceMap = instance->overrides[ i->first ];
1221 typedef typeof i
->second DefListType
;
1222 // InstanceMapType::iterator lastInsert = instanceMap.begin( );
1223 for( DefListType::const_iterator j
= i
->second
.begin( ); j
!= i
->second
.end( ); ++j
)
1225 throw Exceptions::NotImplemented( "addOverrides" );
1226 // RefCountPtr< const Lang::Value > untypedMethod = (*j)->init->value( dstgroup, pdfo, metaState, privateEnv );
1227 // typedef const Lang::Function FunType;
1228 // RefCountPtr< FunType > typedMethod = untypedMethod.down_cast< FunType >( );
1229 // if( typedMethod == NullPtr< FunType >( ) )
1231 // throw Exceptions::TypeMismatch( (*j)->init, untypedMethod->getTypeName( ), FunType::staticTypeName( ) );
1233 // lastInsert = instanceMap.insert( lastInsert, InstanceMapType::value_type( (*j)->id, typedMethod ) );
1239 Lang::UserClass::gcMark( Kernel::GCMarkedSet
& marked
)
1241 throw Exceptions::NotImplemented( "UserClass::gcMark" );
1247 Lang::ClassMethodBase::ClassMethodBase( RefCountPtr
< const Lang::Class
> _self
)
1248 : Lang::Function( 0 ), self( _self
)
1250 WARN_OR_THROW( Exceptions::InternalError( "Lang::ClassMethodBase::ClassMethodBase initializes Lang::Function with 0 pointer to formals.", true ) );
1253 Lang::ClassMethodBase::~ClassMethodBase( )
1257 Lang::ClassMethodBase::gcMark( Kernel::GCMarkedSet
& marked
)
1259 const_cast< Lang::Class
* >( self
.getPtr( ) )->gcMark( marked
);
1263 Lang::ClassMethodBase::isTransforming( ) const
1268 Lang::ClassMethodNew::ClassMethodNew( RefCountPtr
< const Lang::Class
> _self
)
1269 : Lang::ClassMethodBase( _self
)
1273 Lang::ClassMethodNew::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1275 self
->method_new( evalState
, args
, callLoc
);
1278 Lang::ClassMethodIsa::ClassMethodIsa( RefCountPtr
< const Lang::Class
> _self
)
1279 : Lang::ClassMethodBase( _self
)
1283 Lang::ClassMethodIsa::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1285 const size_t ARITY
= 1;
1286 CHECK_ARITY( args
, ARITY
, new Interaction::MethodLocation( Kernel::MethodId( Lang::Class::TypeID
, "isa" ) ) );
1288 typedef const Lang::Class ArgType
;
1289 RefCountPtr
< ArgType
> T
= args
.getValue( 0 ).down_cast
< ArgType
>( );
1290 if( T
== NullPtr
< ArgType
>( ) )
1292 throw Exceptions::CoreTypeMismatch( callLoc
, new Interaction::MethodLocation( Kernel::MethodId( Lang::Class::TypeID
, "isa" ) ), args
, 0, ArgType::staticTypeName( ) );
1295 Kernel::ContRef cont
= evalState
->cont_
;
1296 cont
->takeValue( Kernel::ValueRef( new Lang::Boolean( self
->method_isa( T
) ) ),