Update procedures
[shapes.git] / source / classtypes.cc
blob8567597f510a30fabe710bd8bbcbb8cecffbc2e3
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, 2013 Henrik Tidefelt
19 #include <cmath>
21 #include "shapestypes.h"
22 #include "shapesexceptions.h"
23 #include "classexceptions.h"
24 #include "astexpr.h"
25 #include "globals.h"
26 #include "consts.h"
27 #include "angleselect.h"
28 #include "astvar.h"
29 #include "astclass.h"
30 #include "autoonoff.h"
31 #include "shapescore.h"
32 #include "astfun.h"
33 #include "methodbase.h"
34 #include "corelocation.h"
35 #include "warn.h"
37 #include <ctype.h>
38 #include <stack>
39 #include <string>
40 #include <algorithm>
42 using namespace Shapes;
43 using namespace std;
46 Kernel::MethodId::MethodId( const RefCountPtr< const Lang::Class > & myClass, const char * name )
47 : myClass_( myClass ), name_( name )
48 { }
50 Kernel::MethodId::~MethodId( )
51 { }
53 const char *
54 Kernel::MethodId::getIdentifier( ) const
56 return name_;
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 )
62 { }
64 DISPATCHIMPL( Instance );
66 Lang::Instance::~Instance( )
67 { }
69 void
70 Lang::Instance::gcMark( Kernel::GCMarkedSet & marked )
72 env->gcMark( marked );
73 privateEnv->gcMark( marked );
74 my_dyn->gcMark( marked );
78 void
79 Lang::Instance::prepare( Kernel::EvalState * evalState )
81 if( prepared )
83 return;
85 prepared = true;
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 );
120 else
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 );
136 void
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 );
147 void
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 );
157 return;
159 if( myClass->isInProtectedGetSet( fieldID ) )
161 throw Exceptions::MemberNotAssignable( myClass->getPrettyName( ), fieldID, Interaction::PROTECTED_SCOPE_NAME );
163 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
165 else
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 );
172 return;
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( ) )
193 return i->second;
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 );
204 else
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 ) );
217 return 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 );
244 return j->second;
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 );
256 return p->second;
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 >( ) ) );
265 void
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" );
273 if( warm2D == 0 )
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" );
297 if( warm2D == 0 )
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
314 return myClass;
317 void
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 ) );
354 return 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 ) );
364 void
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 );
379 void
380 Lang::TransformedInstance::show( std::ostream & os ) const
382 os << "Transformed instance. The class is not available in this implementation." ;
385 void
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( );
395 res += "#";
396 res += name_;
397 return strrefdup( res.c_str( ) );
400 bool
401 Kernel::operator < ( const Kernel::MethodId & mid1, const Kernel::MethodId & mid2 )
403 if( mid1.myClass_ < mid2.myClass_ )
405 return true;
407 if( mid1.myClass_ > mid2.myClass_ )
409 return false;
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.
425 selfRef.abortPtr( );
428 void
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
443 return prettyName;
446 bool
447 Lang::Class::isInPublicGetSet( const char * field ) const
449 return false;
452 bool
453 Lang::Class::isInPublicSetSet( const char * field ) const
455 return false;
458 bool
459 Lang::Class::isInProtectedGetSet( const char * field ) const
461 return false;
464 bool
465 Lang::Class::isInProtectedSetSet( const char * field ) const
467 return false;
470 bool
471 Lang::Class::isInTransformingSet( const char * field ) const
473 return false;
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." );
488 void
489 Lang::Class::showAbstractSet( std::ostream & os ) const
491 os << "{" ;
492 typedef typeof abstractSet SetType;
493 for( SetType::const_iterator i = abstractSet.begin( ); i != abstractSet.end( ); ++i )
495 os << " " << i->prettyName( ) ;
497 os << " }" ;
501 void
502 Lang::Class::show( std::ostream & os ) const
504 os << "Pretty-name: " << prettyName.getPtr( ) ;
506 if( ! abstractSet.empty( ) )
508 os << ", +" ;
510 else
512 os << ", -" ;
514 os << "abstract" ;
516 if( isFinal )
518 os << ", +" ;
520 else
522 os << ", -" ;
524 os << "final" ;
527 bool isRepeatable = false;
530 isRepeatable = this->isRepeatableBase( );
532 catch( const Exceptions::MiscellaneousRequirement & ball )
534 /* Probably something saying that MetaClass is not repeatable... */
537 if( isRepeatable )
539 os << ", +" ;
541 else
543 os << ", -" ;
545 os << "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 );
567 bool
568 Lang::Class::getFinal( ) const
570 return isFinal;
573 const Lang::Class::MessageMapType &
574 Lang::Class::getMessageMap( ) const
576 return messageMap;
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( ) );
595 void
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 );
604 else
606 _allParents->insert( i, selfRef );
610 void
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( )
627 Kernel::ValueRef
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_ ) );
636 bool
637 Lang::Object::method_isa( RefCountPtr< const Lang::Class > T ) const
639 return T == selfRef;
642 void
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. */
648 void
649 Lang::Object::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
651 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
654 void
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( ) )
663 return;
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 ) ) );
670 bool
671 Lang::Object::isRepeatableBase( ) const
673 return true;
676 void
677 Lang::Object::gcMark( Kernel::GCMarkedSet & marked )
680 Lang::MetaClass::MetaClass( )
681 : Lang::Class( strrefdup( "MetaClass" ) )
684 Lang::MetaClass::~MetaClass( )
687 Kernel::ValueRef
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." );
693 bool
694 Lang::MetaClass::method_isa( RefCountPtr< const Lang::Class > T ) const
696 return T == Lang::Class::TypeID || T == Lang::THE_OBJECT;
699 void
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. */
705 void
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 );
716 void
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." );
725 void
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." );
731 bool
732 Lang::MetaClass::isRepeatableBase( ) const
734 throw Exceptions::MiscellaneousRequirement( "MetaClass can certainly not be a repeated base." );
737 void
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( )
754 void
755 Lang::SystemFinalClass::init( )
757 if( registerFunction_ != 0 )
759 registerFunction_( this );
763 void
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 ) ) );
770 void
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 ) );
776 if( alias != 0 )
778 mutators_.insert( MapType::value_type( alias, funRef ) );
782 Kernel::ValueRef
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." );
788 bool
789 Lang::SystemFinalClass::method_isa( RefCountPtr< const Lang::Class > T ) const
791 return T == selfRef || T == Lang::THE_OBJECT;
794 void
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. */
800 void
801 Lang::SystemFinalClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
803 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
806 void
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." );
815 bool
816 Lang::SystemFinalClass::isRepeatableBase( ) const
818 return false;
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 );
842 return i->second;
845 void
846 Lang::SystemFinalClass::gcMark( Kernel::GCMarkedSet & marked )
850 Lang::SystemVirtualInterface::SystemVirtualInterface( RefCountPtr< const char > _prettyName )
851 : Lang::Class( _prettyName )
854 Lang::SystemVirtualInterface::~SystemVirtualInterface( )
857 void
858 Lang::SystemVirtualInterface::addVirtual( const char * id )
860 messageMap[ Kernel::MethodId( selfRef, id ) ];
863 Kernel::ValueRef
864 Lang::SystemVirtualInterface::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
866 throw Exceptions::InstantiatingAbstractClass( selfRef );
869 bool
870 Lang::SystemVirtualInterface::method_isa( RefCountPtr< const Lang::Class > T ) const
872 throw Exceptions::InternalError( "method_isa was called on an abstract system class." );
875 void
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. */
881 void
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 );
890 void
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
897 bool
898 Lang::SystemVirtualInterface::isRepeatableBase( ) const
900 return true;
903 void
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,
914 bool _isFinal )
915 : Lang::Class( _prettyName ), classExpr( _classExpr ), formals( _formals ), parents( _parents ), overrides( _overrides )
917 Lang::Class::isFinal = _isFinal;
920 Lang::UserClass::~UserClass( )
922 delete formals;
925 void
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( ) ) );
965 messageSet = res;
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_ ) ];
987 messageSet.clear( );
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 )
1002 // {
1003 // std::cerr << (*l)->getPrettyName( ) << " " ;
1004 // }
1005 // std::cerr << std::endl ;
1006 if( i->second.size( ) == 1 )
1008 continue;
1010 if( i->second.empty( ) )
1012 j = abstractSet.insert( j, i->first );
1014 else
1016 throw Exceptions::AmbiguousInheritedMethod( selfRef, i->first.prettyName( ), i->second );
1021 if( ! declaredAbstract && ! abstractSet.empty( ) )
1023 throw Exceptions::FailedToDeclareClassAbstract( selfRef, classExpr );
1027 Kernel::ValueRef
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( ) )
1040 // // {
1041 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1042 // // }
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( ) )
1048 // // {
1049 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1050 // // }
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 )
1061 // {
1062 // (*i)->superNew( instanceSelf, createdObjects, EMPTY_ARGLIST, evalState );
1063 // }
1065 // args.mergeWithFormals( formals )
1066 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1068 // {
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 )
1071 // {
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 );
1075 // }
1076 // }
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 );
1087 bool
1088 Lang::UserClass::method_isa( RefCountPtr< const Lang::Class > T ) const
1090 if( T == selfRef )
1092 return true;
1094 return allParents.find( T ) != allParents.end( );
1097 void
1098 Lang::UserClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
1100 throw Exceptions::NotImplemented( "UserClass::findMultiplyInheritedClasses" );
1103 void
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 );
1113 else
1115 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
1119 void
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( ) )
1128 return;
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 );
1141 // {
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 )
1144 // {
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 );
1148 // }
1149 // }
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 ) ) );
1158 void
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 );
1169 bool
1170 Lang::UserClass::isRepeatableBase( ) const
1172 return classExpr->isRepeatableBase( );
1175 void
1176 Lang::UserClass::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
1178 classExpr->prepareInstance( evalState, privateEnv );
1182 bool
1183 Lang::UserClass::isInPublicGetSet( const char * field ) const
1185 return classExpr->isInPublicGetSet( field );
1188 bool
1189 Lang::UserClass::isInPublicSetSet( const char * field ) const
1191 return classExpr->isInPublicSetSet( field );
1194 bool
1195 Lang::UserClass::isInProtectedGetSet( const char * field ) const
1197 return classExpr->isInProtectedGetSet( field );
1200 bool
1201 Lang::UserClass::isInProtectedSetSet( const char * field ) const
1203 return classExpr->isInProtectedSetSet( field );
1206 bool
1207 Lang::UserClass::isInTransformingSet( const char * field ) const
1209 return classExpr->isInTransformingSet( field );
1213 void
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 >( ) )
1230 // {
1231 // throw Exceptions::TypeMismatch( (*j)->init, untypedMethod->getTypeName( ), FunType::staticTypeName( ) );
1232 // }
1233 // lastInsert = instanceMap.insert( lastInsert, InstanceMapType::value_type( (*j)->id, typedMethod ) );
1238 void
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( )
1256 void
1257 Lang::ClassMethodBase::gcMark( Kernel::GCMarkedSet & marked )
1259 const_cast< Lang::Class * >( self.getPtr( ) )->gcMark( marked );
1262 bool
1263 Lang::ClassMethodBase::isTransforming( ) const
1265 return false;
1268 Lang::ClassMethodNew::ClassMethodNew( RefCountPtr< const Lang::Class > _self )
1269 : Lang::ClassMethodBase( _self )
1272 void
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 )
1282 void
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 ) ) ),
1297 evalState );