Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / classtypes.cc
blob490d1d6ab6ea7dc839a69e91924169276af597a3
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 "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"
35 #include <ctype.h>
36 #include <stack>
37 #include <string>
38 #include <algorithm>
40 using namespace Shapes;
41 using namespace std;
44 Kernel::MethodId::MethodId( const RefCountPtr< const Lang::Class > & _myClass, const char * _msg )
45 : myClass( _myClass ), msg( _msg )
46 { }
48 Kernel::MethodId::~MethodId( )
49 { }
51 const char *
52 Kernel::MethodId::getIdentifier( ) const
54 return msg;
58 Lang::Instance::Instance( Kernel::PassedEnv _env, Kernel::PassedEnv _privateEnv, RefCountPtr< const Lang::Class > _myClass, bool _protectedAccess, const Kernel::PassedDyn & _my_dyn )
59 : env( _env ), privateEnv( _privateEnv ), warm2D( 0 ), warm3D( 0 ), my_dyn( _my_dyn ), myClass( _myClass ), prepared( false ), protectedAccess( _protectedAccess )
60 { }
62 DISPATCHIMPL( Instance );
64 Lang::Instance::~Instance( )
65 { }
67 void
68 Lang::Instance::gcMark( Kernel::GCMarkedSet & marked )
70 env->gcMark( marked );
71 privateEnv->gcMark( marked );
72 my_dyn->gcMark( marked );
76 void
77 Lang::Instance::prepare( Kernel::EvalState * evalState )
79 if( prepared )
81 return;
83 prepared = true;
85 for( std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = parents->begin( ); i != parents->end( ); ++i )
87 i->second->prepare( evalState );
91 myClass->prepareInstance( evalState, privateEnv );
94 Kernel::VariableHandle
95 Lang::Instance::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
97 if( ! myClass->getFinal( ) )
99 throw Exceptions::IllegalFinalReference( myClass->getPrettyName( ), fieldID );
102 return getLocalField( fieldID );
105 Kernel::VariableHandle
106 Lang::Instance::getLocalField( const char * fieldID ) const
108 if( protectedAccess )
110 if( myClass->isInProtectedGetSet( fieldID ) )
112 throw Exceptions::NotImplemented( "Instance::getLocalField" );
113 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
114 // return env->getVarHandle( key );
116 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
118 else
120 if( myClass->isInPublicGetSet( fieldID ) )
122 throw Exceptions::NotImplemented( "Instance::getLocalField" );
123 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
124 // return env->getVarHandle( key );
126 if( myClass->isInProtectedGetSet( fieldID ) )
128 throw Exceptions::ProtectedMemberPublicScope( myClass->getPrettyName( ), fieldID );
130 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
134 void
135 Lang::Instance::tackOn( const char * fieldID, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
137 if( ! myClass->getFinal( ) )
139 throw Exceptions::IllegalFinalReference( myClass->getPrettyName( ), fieldID );
142 tackOnLocal( fieldID, evalState, piece, callLoc );
145 void
146 Lang::Instance::tackOnLocal( const char * fieldID, Kernel::EvalState * evalState, const RefCountPtr< const Lang::Value > & piece, const Ast::SourceLocation & callLoc )
148 if( protectedAccess )
150 if( myClass->isInProtectedSetSet( fieldID ) )
152 throw Exceptions::NotImplemented( "Instance::tackOnLocal" );
153 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
154 // env->tackOn( key, evalState, piece, callLoc );
155 return;
157 if( myClass->isInProtectedGetSet( fieldID ) )
159 throw Exceptions::MemberNotAssignable( myClass->getPrettyName( ), fieldID, Interaction::PROTECTED_SCOPE_NAME );
161 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
163 else
165 if( myClass->isInPublicSetSet( fieldID ) )
167 throw Exceptions::NotImplemented( "Instance::tackOnLocal" );
168 // Kernel::Environment::LexicalKey key = env->findLexicalVariableKey( Ast::THE_UNKNOWN_LOCATION, fieldID );
169 // env->tackOn( key, evalState, piece, callLoc );
170 return;
172 if( myClass->isInPublicGetSet( fieldID ) )
174 throw Exceptions::MemberNotAssignable( myClass->getPrettyName( ), fieldID, Interaction::PUBLIC_SCOPE_NAME );
176 if( myClass->isInProtectedGetSet( fieldID ) )
178 throw Exceptions::ProtectedMemberPublicScope( myClass->getPrettyName( ), fieldID );
180 throw Exceptions::NonExistentMember( myClass->getPrettyName( ), fieldID );
184 RefCountPtr< const Lang::Function >
185 Lang::Instance::getMethod( Kernel::MethodId fieldID ) const
187 typedef typeof methodTable MethodMapType;
188 MethodMapType::iterator i = methodTable.find( fieldID );
189 if( i != methodTable.end( ) )
191 return i->second;
194 const RefCountPtr< const Lang::Class > & defClass = myClass->getMethodDefinitionClass( fieldID );
196 RefCountPtr< const Lang::Function > fun = NullPtr< const Lang::Function >( );
198 if( defClass == myClass )
200 fun = getLocalMethod( fieldID );
202 else
204 typedef typeof *parents ParentMapType;
205 ParentMapType::const_iterator p = parents->find( defClass );
206 if( p == parents->end( ) )
208 throw Exceptions::InternalError( "The class defining a method was not found among the parents." );
210 fun = p->second->getLocalMethod( fieldID );
213 methodTable.insert( i, MethodMapType::value_type( fieldID, fun ) );
215 return fun;
218 RefCountPtr< const Lang::Function >
219 Lang::Instance::getLocalMethod( Kernel::MethodId fieldID ) const
222 if( fieldID.getClass( ) == myClass )
224 Kernel::VariableHandle untypedFun = getLocalField( fieldID.getIdentifier( ) );
225 return untypedFun->getVal< const Lang::Function >( "getLocalMethod: The user was (almost) able to retrieve member data from super instance." );
228 typedef typeof overrides ClassMapType;
229 ClassMapType::const_iterator i = overrides.find( fieldID.getClass( ) );
230 if( i == overrides.end( ) )
232 throw Exceptions::NoSuchLocalMethod( myClass, fieldID );
235 typedef typeof i->second IdMapType;
237 IdMapType::const_iterator j = i->second.find( fieldID.getIdentifier( ) );
238 if( j == i->second.end( ) )
240 throw Exceptions::NoSuchLocalMethod( myClass, fieldID );
242 return j->second;
245 RefCountPtr< const Lang::Instance >
246 Lang::Instance::superReference( RefCountPtr< const Lang::Class > parent ) const
248 typedef typeof *parents ParentMapType;
249 ParentMapType::const_iterator p = parents->find( parent );
250 if( p == parents->end( ) )
252 throw Exceptions::SuperReferenceClassNotParent( myClass, parent );
254 return p->second;
257 RefCountPtr< const Lang::Geometric2D >
258 Lang::Instance::transformed( const Lang::Transform2D & tf, const RefCountPtr< const Lang::Geometric2D > & self ) const
260 return RefCountPtr< const Lang::Geometric2D >( new Lang::TransformedInstance( tf, self.down_cast< const Lang::Instance >( ) ) );
263 void
264 Lang::Instance::shipout( std::ostream & os, Kernel::PageContentStates * pdfState, const Lang::Transform2D & tf ) const
266 if( ! myClass->method_isa( Lang::Drawable2D::TypeID ) )
268 throw Exceptions::InternalError( "Invoking Instance::shipout on a non Drawable object should not be possible" );
271 if( warm2D == 0 )
273 throw Exceptions::InternalError( "Instance::shipout: warm2D == 0." );
277 RefCountPtr< const Lang::Value > val = getMethod( Kernel::MethodId( Lang::Drawable2D::TypeID, Shapes::MESSAGE_DRAWABLE_DRAW_ID ) )->call( dstgroup, my_pdfo, & stateCopy, Kernel::EMPTY_ARGLIST );
278 if( dynamic_cast< const Lang::Void * >( val.getPtr( ) ) == 0 )
280 throw Exceptions::TypeMismatch( val->getTypeName( ), Lang::Void::staticTypeName( ) );
284 warm2D->getPile( )->shipout( os, pdfState, tf );
287 RefCountPtr< const Lang::ElementaryPath2D >
288 Lang::Instance::bbox( Lang::Drawable2D::BoxType boxType ) const
290 if( ! myClass->method_isa( Lang::Drawable2D::TypeID ) )
292 throw Exceptions::InternalError( "Invoking Instance::shipout on a non Drawable object should not be possible" );
295 if( warm2D == 0 )
297 throw Exceptions::InternalError( "Instance::shipout: warm2D == 0." );
300 return warm2D->getPile( )->bbox( boxType );
303 RefCountPtr< const char >
304 Lang::Instance::staticTypeName( )
306 return strrefdup( "<Instance>" );
309 const RefCountPtr< const Lang::Class > &
310 Lang::Instance::getClass( ) const
312 return myClass;
315 void
316 Lang::Instance::show( std::ostream & os ) const
318 os << "Instance of class " << myClass->getPrettyName( ).getPtr( ) ;
322 Lang::TransformedInstance::TransformedInstance( const Lang::Transform2D & _tf, const RefCountPtr< const Lang::Instance > & _obj )
323 : tf( _tf ), obj( _obj )
326 Lang::TransformedInstance::~TransformedInstance( )
329 Kernel::VariableHandle
330 Lang::TransformedInstance::getField( const char * fieldID, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
332 if( obj->getClass( )->isInTransformingSet( fieldID ) )
334 Kernel::VariableHandle argUntyped = obj->getField( fieldID, obj );
335 typedef const Lang::Geometric2D ArgType;
336 RefCountPtr< ArgType > arg = argUntyped->getVal< ArgType >( "<inside transformed instance getField>" );
337 return Kernel::VariableHandle( new Kernel::Variable( arg->transformed( tf, arg ) ) );
339 return obj->getField( fieldID, obj );
342 RefCountPtr< const Lang::Function >
343 Lang::TransformedInstance::getMethod( Kernel::MethodId fieldID ) const
345 /* Fetch the method first to make sure it exists, then see whether it is transforming.
347 RefCountPtr< const Lang::Function > arg = obj->getMethod( fieldID );
348 if( arg->isTransforming( ) )
350 return RefCountPtr< const Lang::Function >( new Lang::TransformedFunction2D( tf, arg ) );
352 return arg;
355 RefCountPtr< const Lang::Geometric2D >
356 Lang::TransformedInstance::transformed( const Lang::Transform2D & tf2, const RefCountPtr< const Lang::Geometric2D > & self ) const
358 return RefCountPtr< const Lang::Geometric2D >( new Lang::TransformedInstance( Lang::Transform2D( tf2, tf ) , obj ) );
362 void
363 Lang::TransformedInstance::shipout( std::ostream & os, Kernel::PageContentStates * pdfState, const Lang::Transform2D & tfIn ) const
365 obj->shipout( os, pdfState, Lang::Transform2D( tfIn, tf ) );
368 RefCountPtr< const Lang::ElementaryPath2D >
369 Lang::TransformedInstance::bbox( Lang::Drawable2D::BoxType boxType ) const
371 return obj->bbox( boxType )->elementaryTransformed( tf );
374 RefCountPtr< const Lang::Class > Lang::TransformedInstance::TypeID( new Lang::SystemFinalClass( strrefdup( "TransformedInstance" ) ) );
375 TYPEINFOIMPL( TransformedInstance );
377 void
378 Lang::TransformedInstance::show( std::ostream & os ) const
380 os << "Transformed instance. The class is not available in this implementation." ;
383 void
384 Lang::TransformedInstance::gcMark( Kernel::GCMarkedSet & marked )
386 const_cast< Lang::Instance * >( obj.getPtr( ) )->gcMark( marked );
389 RefCountPtr< const char >
390 Kernel::MethodId::prettyName( ) const
392 string res = myClass->getPrettyName( ).getPtr( );
393 res += "#";
394 res += msg;
395 return strrefdup( res.c_str( ) );
398 bool
399 Kernel::operator < ( const Kernel::MethodId & mid1, const Kernel::MethodId & mid2 )
401 if( mid1.myClass < mid2.myClass )
403 return true;
405 if( mid1.myClass > mid2.myClass )
407 return false;
409 return strcmp( mid1.msg, mid2.msg ) < 0;
413 Lang::Class::Class( RefCountPtr< const char > _prettyName )
414 : prettyName( _prettyName ), selfRef( NullPtr< Lang::Class >( ) ), isFinal( false )
417 Lang::Class::~Class( )
419 /* Knowing that each class is reference counted, the destructor is being called as an effect
420 * of the reference count reaching zero. Thus, the self reference must simply be detached
421 * from this object, to avoid cyclic destruction.
423 selfRef.abortPtr( );
426 void
427 Lang::Class::setSelfRef( RefCountPtr< const Lang::Class > _selfRef ) const
429 selfRef = _selfRef; // selfRef is mutable!
430 /* Don't count this cyclic reference!
432 --*selfRef.getCounterPtr( );
435 RefCountPtr< const Lang::Class > Lang::Class::TypeID( new Lang::MetaClass( ) );
436 TYPEINFOIMPL( Class );
438 RefCountPtr< const char >
439 Lang::Class::getPrettyName( ) const
441 return prettyName;
444 bool
445 Lang::Class::isInPublicGetSet( const char * field ) const
447 return false;
450 bool
451 Lang::Class::isInPublicSetSet( const char * field ) const
453 return false;
456 bool
457 Lang::Class::isInProtectedGetSet( const char * field ) const
459 return false;
462 bool
463 Lang::Class::isInProtectedSetSet( const char * field ) const
465 return false;
468 bool
469 Lang::Class::isInTransformingSet( const char * field ) const
471 return false;
474 Kernel::VariableHandle
475 Lang::Class::getMethod( const RefCountPtr< const Lang::Value > & self, const char * methodID ) const
477 throw Exceptions::InternalError( "Method request not defined for this type of class." );
480 RefCountPtr< const Lang::Function >
481 Lang::Class::getMutator( const char * mutatorID ) const
483 throw Exceptions::InternalError( "Mutator request not defined for this type of class." );
486 void
487 Lang::Class::showAbstractSet( std::ostream & os ) const
489 os << "{" ;
490 typedef typeof abstractSet SetType;
491 for( SetType::const_iterator i = abstractSet.begin( ); i != abstractSet.end( ); ++i )
493 os << " " << i->prettyName( ) ;
495 os << " }" ;
499 void
500 Lang::Class::show( std::ostream & os ) const
502 os << "Pretty-name: " << prettyName.getPtr( ) ;
504 if( ! abstractSet.empty( ) )
506 os << ", +" ;
508 else
510 os << ", -" ;
512 os << "abstract" ;
514 if( isFinal )
516 os << ", +" ;
518 else
520 os << ", -" ;
522 os << "final" ;
525 bool isRepeatable = false;
528 isRepeatable = this->isRepeatableBase( );
530 catch( const Exceptions::MiscellaneousRequirement & ball )
532 /* Probably something saying that MetaClass is not repeatable... */
535 if( isRepeatable )
537 os << ", +" ;
539 else
541 os << ", -" ;
543 os << "repeatable" ;
547 Kernel::VariableHandle
548 Lang::Class::getField( const char * fieldId, const RefCountPtr< const Lang::Value > & dummySelfRef ) const
550 if( strcmp( fieldId, "new" ) == 0 )
552 return Helpers::newValHandle( new Lang::ClassMethodNew( selfRef ) );
554 if( strcmp( fieldId, "isa" ) == 0 )
556 return Helpers::newValHandle( new Lang::ClassMethodIsa( selfRef ) );
558 if( strcmp( fieldId, "name" ) == 0 )
560 return Helpers::newValHandle( new Lang::String( prettyName ) );
562 throw Exceptions::NonExistentMember( getTypeName( ), fieldId );
565 bool
566 Lang::Class::getFinal( ) const
568 return isFinal;
571 const Lang::Class::MessageMapType &
572 Lang::Class::getMessageMap( ) const
574 return messageMap;
577 const RefCountPtr< const Lang::Class > &
578 Lang::Class::getMethodDefinitionClass( const Kernel::MethodId & method ) const
580 MessageMapType::const_iterator i = messageMap.find( method );
581 if( i == messageMap.end( ) )
583 throw Exceptions::NoSuchMethod( selfRef, method );
585 if( i->second.empty( ) )
587 throw Exceptions::InternalError( "Asking for class defining abstract method." );
589 return *( i->second.begin( ) );
593 void
594 Lang::Class::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
596 typedef typeof *_allParents SetType;
597 SetType::const_iterator i = _allParents->find( selfRef );
598 if( i != _allParents->end( ) )
600 _multiParents->insert( selfRef );
602 else
604 _allParents->insert( i, selfRef );
608 void
609 Lang::Class::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
611 /* Only UserClass instances do any preparations. */
614 DISPATCHIMPL( Class );
618 Lang::Object::Object( )
619 : Lang::Class( strrefdup( "Object" ) ), dummyEnv( NullPtr< Kernel::Environment >( ) )
622 Lang::Object::~Object( )
625 Kernel::ValueRef
626 Lang::Object::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
628 const size_t ARITY = 0;
629 CHECK_ARITY( args, ARITY, Kernel::MethodId( Lang::Class::TypeID, "new" ).prettyName( ) );
631 return RefCountPtr< const Lang::Geometric2D >( new Lang::Instance( dummyEnv, dummyEnv, selfRef, false, evalState->dyn_ ) );
634 bool
635 Lang::Object::method_isa( RefCountPtr< const Lang::Class > T ) const
637 return T == selfRef;
640 void
641 Lang::Object::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
643 /* There are no parent classes to consider. */
646 void
647 Lang::Object::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
649 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
652 void
653 Lang::Object::superNew( RefCountPtr< Lang::Instance > instanceSelf,
654 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
655 Kernel::Arguments & emptyArglist,
656 Kernel::EvalState * evalState ) const
658 std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = createdObjects->find( selfRef );
659 if( i != createdObjects->end( ) )
661 return;
663 Lang::Instance * newObj = new Lang::Instance( dummyEnv, dummyEnv, selfRef, true, evalState->dyn_ );
664 newObj->parents = createdObjects;
665 createdObjects->insert( i, pair< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >( selfRef, RefCountPtr< Lang::Instance >( newObj ) ) );
668 bool
669 Lang::Object::isRepeatableBase( ) const
671 return true;
674 void
675 Lang::Object::gcMark( Kernel::GCMarkedSet & marked )
678 Lang::MetaClass::MetaClass( )
679 : Lang::Class( strrefdup( "MetaClass" ) )
682 Lang::MetaClass::~MetaClass( )
685 Kernel::ValueRef
686 Lang::MetaClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
688 throw Exceptions::MiscellaneousRequirement( "Calling the \"new\" method of MetaClass is actually not the way to create new classes, sorry." );
691 bool
692 Lang::MetaClass::method_isa( RefCountPtr< const Lang::Class > T ) const
694 return T == Lang::Class::TypeID || T == Lang::THE_OBJECT;
697 void
698 Lang::MetaClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
700 /* There are no parent classes to consider. */
703 void
704 Lang::MetaClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
706 if( strcmp( id, "new" ) == 0 ||
707 strcmp( id, "isa" ) == 0 )
709 throw Exceptions::OverridingFinalMethod( caller, selfRef, id );
711 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
714 void
715 Lang::MetaClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
716 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
717 Kernel::Arguments & emptyArglist,
718 Kernel::EvalState * evalState ) const
720 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from MetaClass, sorry." );
723 void
724 Lang::MetaClass::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
726 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from MetaClass, sorry." );
729 bool
730 Lang::MetaClass::isRepeatableBase( ) const
732 throw Exceptions::MiscellaneousRequirement( "MetaClass can certainly not be a repeated base." );
735 void
736 Lang::MetaClass::gcMark( Kernel::GCMarkedSet & marked )
741 Lang::SystemFinalClass::SystemFinalClass( RefCountPtr< const char > _prettyName )
742 : Lang::Class( _prettyName ), registerFunction_( 0 )
745 Lang::SystemFinalClass::SystemFinalClass( RefCountPtr< const char > _prettyName, RegisterFunction registerFunction )
746 : Lang::Class( _prettyName ), registerFunction_( registerFunction )
749 Lang::SystemFinalClass::~SystemFinalClass( )
752 void
753 Lang::SystemFinalClass::init( )
755 if( registerFunction_ != 0 )
757 registerFunction_( this );
761 void
762 Lang::SystemFinalClass::registerMethod( Kernel::MethodFactoryBase * factory )
764 typedef typeof methods_ MapType;
765 methods_.insert( MapType::value_type( factory->field( ), RefCountPtr< const Kernel::MethodFactoryBase >( factory ) ) );
768 void
769 Lang::SystemFinalClass::registerMutator( Lang::CoreFunction * fun, const char * alias )
771 RefCountPtr< const Lang::Function > funRef = RefCountPtr< const Lang::Function >( fun );
772 typedef typeof mutators_ MapType;
773 mutators_.insert( MapType::value_type( fun->getTitle( ), funRef ) );
774 if( alias != 0 )
776 mutators_.insert( MapType::value_type( alias, funRef ) );
780 Kernel::ValueRef
781 Lang::SystemFinalClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
783 throw Exceptions::MiscellaneousRequirement( "Use dedicated syntax rather than calling the \"new\" method of a system class." );
786 bool
787 Lang::SystemFinalClass::method_isa( RefCountPtr< const Lang::Class > T ) const
789 return T == selfRef || T == Lang::THE_OBJECT;
792 void
793 Lang::SystemFinalClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
795 /* There are no parent classes to consider. */
798 void
799 Lang::SystemFinalClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
801 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
804 void
805 Lang::SystemFinalClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
806 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
807 Kernel::Arguments & emptyArglist,
808 Kernel::EvalState * evalState ) const
810 throw Exceptions::MiscellaneousRequirement( "It is forbidden to inherit from SystemFinalClass, sorry." );
813 bool
814 Lang::SystemFinalClass::isRepeatableBase( ) const
816 return false;
819 Kernel::VariableHandle
820 Lang::SystemFinalClass::getMethod( const RefCountPtr< const Lang::Value > & self, const char * methodID ) const
822 typedef typeof methods_ MapType;
823 MapType::const_iterator i = methods_.find( methodID );
824 if( i == methods_.end( ) )
826 throw Exceptions::NonExistentMember( self->getTypeName( ), methodID );
828 return i->second->build( self );
831 RefCountPtr< const Lang::Function >
832 Lang::SystemFinalClass::getMutator( const char * mutatorID ) const
834 typedef typeof mutators_ MapType;
835 MapType::const_iterator i = mutators_.find( mutatorID );
836 if( i == mutators_.end( ) )
838 throw Exceptions::NonExistentMutator( staticTypeName( ), mutatorID );
840 return i->second;
843 void
844 Lang::SystemFinalClass::gcMark( Kernel::GCMarkedSet & marked )
848 Lang::SystemVirtualInterface::SystemVirtualInterface( RefCountPtr< const char > _prettyName )
849 : Lang::Class( _prettyName )
852 Lang::SystemVirtualInterface::~SystemVirtualInterface( )
855 void
856 Lang::SystemVirtualInterface::addVirtual( const char * id )
858 messageMap[ Kernel::MethodId( selfRef, id ) ];
861 Kernel::ValueRef
862 Lang::SystemVirtualInterface::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
864 throw Exceptions::InstantiatingAbstractClass( selfRef );
867 bool
868 Lang::SystemVirtualInterface::method_isa( RefCountPtr< const Lang::Class > T ) const
870 throw Exceptions::InternalError( "method_isa was called on an abstract system class." );
873 void
874 Lang::SystemVirtualInterface::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
876 /* There are no parent classes to consider. */
879 void
880 Lang::SystemVirtualInterface::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
882 if( messageMap.find( Kernel::MethodId( selfRef, id ) ) == messageMap.end( ) )
884 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
888 void
889 Lang::SystemVirtualInterface::superNew( RefCountPtr< Lang::Instance > instanceSelf,
890 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
891 Kernel::Arguments & emptyArglist,
892 Kernel::EvalState * evalState ) const
895 bool
896 Lang::SystemVirtualInterface::isRepeatableBase( ) const
898 return true;
901 void
902 Lang::SystemVirtualInterface::gcMark( Kernel::GCMarkedSet & marked )
906 Lang::UserClass::UserClass( const Ast::ClassFunction * _classExpr,
907 Kernel::PassedEnv _env,
908 RefCountPtr< const char > _prettyName,
909 Kernel::EvaluatedFormals * _formals,
910 RefCountPtr< std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > > _parents,
911 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > > > _overrides,
912 bool _isFinal )
913 : Lang::Class( _prettyName ), classExpr( _classExpr ), formals( _formals ), env( _env ), parents( _parents ), overrides( _overrides )
915 Lang::Class::isFinal = _isFinal;
918 Lang::UserClass::~UserClass( )
920 delete formals;
923 void
924 Lang::UserClass::setupAndCheck( bool declaredAbstract )
926 for( std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > >::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
928 typedef typeof immediateParents SetType;
929 SetType::const_iterator j = immediateParents.find( i->first );
930 if( j != immediateParents.end( ) )
932 throw Exceptions::RepeatedImmediateParent( selfRef, i->first );
934 if( i->first->getFinal( ) )
936 throw Exceptions::InheritingFinal( selfRef, i->first );
938 immediateParents.insert( j, i->first );
941 findParents( & allParents, & multiParents );
943 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = multiParents.begin( ); i != multiParents.end( ); ++i )
945 if( ! (*i)->isRepeatableBase( ) )
947 throw Exceptions::IllegalRepeatedBase( selfRef, *i );
951 messageMap = classExpr->getLocalMessageMap( selfRef );
953 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = immediateParents.begin( ); i != immediateParents.end( ); ++i )
955 const MessageMapType & parentMap = (*i)->getMessageMap( );
956 for( MessageMapType::const_iterator j = parentMap.begin( ); j != parentMap.end( ); ++j )
958 std::set< RefCountPtr< const Lang::Class > > & messageSet = messageMap[ j->first ];
959 std::set< RefCountPtr< const Lang::Class > > res;
960 set_union( messageSet.begin( ), messageSet.end( ),
961 j->second.begin( ), j->second.end( ),
962 insert_iterator< std::set< RefCountPtr< const Lang::Class > > >( res, res.begin( ) ) );
963 messageSet = res;
968 typedef typeof *overrides MapType;
969 for( MapType::const_iterator i = overrides->begin( ); i != overrides->end( ); ++i )
971 typedef typeof allParents ClassSetType;
973 ClassSetType::const_iterator j = allParents.find( i->first );
974 if( j == allParents.end( ) )
976 throw Exceptions::OverridingNonParent( selfRef, i->first );
980 typedef typeof i->second ListType;
981 for( ListType::const_iterator j = i->second.begin( ); j != i->second.end( ); ++j )
983 i->first->assertMethodOverridable( (*j)->id_, selfRef );
984 std::set< RefCountPtr< const Lang::Class > > & messageSet = messageMap[ Kernel::MethodId( i->first, (*j)->id_ ) ];
985 messageSet.clear( );
986 messageSet.insert( messageSet.begin( ), selfRef );
995 std::cerr << "Message map of " << getPrettyName( ) << ":" << std::endl ;
997 std::set< Kernel::MethodId >::iterator j = abstractSet.begin( );
998 MessageMapType::iterator k = messageMap.begin( );
999 for( MessageMapType::const_iterator i = messageMap.begin( ); i != messageMap.end( ); ++i )
1002 std::cerr << " " << i->first.prettyName( ) << " --> " ;
1003 for( std::set< RefCountPtr< const Lang::Class > >::const_iterator l = i->second.begin( ); l != i->second.end( ); ++l )
1005 std::cerr << (*l)->getPrettyName( ) << " " ;
1007 std::cerr << std::endl ;
1009 if( i->second.size( ) == 1 )
1011 continue;
1013 if( i->second.empty( ) )
1015 j = abstractSet.insert( j, i->first );
1017 else
1019 throw Exceptions::AmbiguousInheritedMethod( selfRef, i->first.prettyName( ), i->second );
1024 if( ! declaredAbstract && ! abstractSet.empty( ) )
1026 throw Exceptions::FailedToDeclareClassAbstract( selfRef, classExpr );
1030 Kernel::ValueRef
1031 Lang::UserClass::method_new( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1033 if( ! abstractSet.empty( ) )
1035 throw Exceptions::InstantiatingAbstractClass( selfRef );
1038 throw Exceptions::NotImplemented( "UserClass::method_new" );
1040 // // std::vector< VariableHandle > * envValues = new std::vector< VariableHandle >;
1041 // // envValues->reserve( argumentOrder->size( ) );
1042 // // while( envValues->size( ) < argumentOrder->size( ) )
1043 // // {
1044 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1045 // // }
1046 // Kernel::PassedEnv instanceEnv( new Kernel::Environment( Shapes::theEnvironmentList, evalState->env_, argumentOrder, RefCountPtr< std::vector< VariableHandle > >( envValues ) ) );
1048 // // std::vector< VariableHandle > * envValues = new std::vector< VariableHandle >;
1049 // // envValues->reserve( argumentOrder->size( ) );
1050 // // while( envValues->size( ) < argumentOrder->size( ) )
1051 // // {
1052 // // envValues->push_back( NullPtr< Kernel::Variable >( ) );
1053 // // }
1054 // Kernel::PassedEnv privateEnv( new Kernel::Environment( Shapes::theEnvironmentList, instanceEnv, argumentOrder, RefCountPtr< std::vector< VariableHandle > >( envValues ) ) );
1056 // RefCountPtr< Lang::Instance > instanceSelf = RefCountPtr< Lang::Instance >( new Lang::Instance( instanceEnv, privateEnv, selfRef, false, evalState->dyn_ ) );
1058 // privateEnv->define( classExpr->loc( ), SELF_ID, RefCountPtr< const Lang::Geometric2D >( instanceSelf ), true ); /* true means constant */
1060 // RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects( new std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > );
1061 // instanceSelf->parents = createdObjects;
1063 // for( std::set< RefCountPtr< const Lang::Class > >::const_iterator i = multiParents.begin( ); i != multiParents.end( ); ++i )
1064 // {
1065 // (*i)->superNew( instanceSelf, createdObjects, EMPTY_ARGLIST, evalState );
1066 // }
1068 // args.mergeWithFormals( formals )
1069 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1071 // {
1072 // typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ListType;
1073 // for( ListType::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
1074 // {
1075 // RefCountPtr< Kernel::Arguments > superArgs( new Kernel::Arguments( true ) ); /* true means constant */
1076 // i->second->evaluate( superArgs, dstgroup, pdfo, metaState, initEnv );
1077 // i->first->superNew( instanceSelf, createdObjects, *superArgs, evalState );
1078 // }
1079 // }
1081 // classExpr->setupInstance( instanceEnv, privateEnv, dstgroup, pdfo, metaState, initEnv );
1083 // addOverrides( instanceSelf, privateEnv, dstgroup, pdfo, metaState );
1085 // instanceSelf->prepare( dstgroup, pdfo, metaState );
1087 // return RefCountPtr< const Lang::Geometric2D >( instanceSelf );
1090 bool
1091 Lang::UserClass::method_isa( RefCountPtr< const Lang::Class > T ) const
1093 if( T == selfRef )
1095 return true;
1097 return allParents.find( T ) != allParents.end( );
1100 void
1101 Lang::UserClass::findMultiplyInheritedClasses( std::set< RefCountPtr< Lang::Class > > * visited, std::set< RefCountPtr< Lang::Class > > * found ) const
1103 throw Exceptions::NotImplemented( "UserClass::findMultiplyInheritedClasses" );
1106 void
1107 Lang::UserClass::assertMethodOverridable( const char * id, const RefCountPtr< const Lang::Class > & caller ) const
1109 if( classExpr->isInPublicGetSet( id ) || classExpr->isInAbstractSet( id ) )
1111 if( classExpr->isInFinalSet( id ) )
1113 throw Exceptions::OverridingFinalMethod( caller, selfRef, id );
1116 else
1118 throw Exceptions::OverridingUndeclaredMethod( caller, selfRef, id );
1122 void
1123 Lang::UserClass::superNew( RefCountPtr< Lang::Instance > instanceSelf,
1124 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > > > createdObjects,
1125 Kernel::Arguments & args,
1126 Kernel::EvalState * evalState ) const
1128 std::map< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >::iterator i = createdObjects->find( selfRef );
1129 if( i != createdObjects->end( ) )
1131 return;
1134 throw Exceptions::NotImplemented( "UserClass::superNew" );
1136 // Kernel::PassedEnv instanceEnv( new Kernel::Environment( env ) );
1137 // Kernel::PassedEnv privateEnv( new Kernel::Environment( instanceEnv ) );
1139 // privateEnv->define( classExpr->loc( ), SELF_ID, RefCountPtr< const Lang::Geometric2D >( instanceSelf ), true ); /* true means constant */
1141 // args.mergeWithFormals( formals )
1142 // Kernel::PassedEnv initEnv = new Kernel::Environment( theEnvironmentList, env, formals->formals->argumentOrder, args.orderedArguments );
1144 // {
1145 // typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ListType;
1146 // for( ListType::const_iterator i = parents->begin( ); i != parents->end( ); ++i )
1147 // {
1148 // RefCountPtr< Kernel::Arguments > superArgs( new Kernel::Arguments( true ) ); /* true means constant */
1149 // i->second->evaluate( superArgs, dstgroup, pdfo, metaState, initEnv );
1150 // i->first->superNew( instanceSelf, createdObjects, *superArgs, evalState );
1151 // }
1152 // }
1154 // classExpr->setupInstance( instanceEnv, privateEnv, dstgroup, pdfo, metaState, initEnv );
1156 // Lang::Instance * newObj = new Lang::Instance( instanceEnv, privateEnv, selfRef, true, evalState->dyn_ );
1157 // newObj->parents = createdObjects;
1158 // createdObjects->insert( i, pair< RefCountPtr< const Lang::Class >, RefCountPtr< Lang::Instance > >( selfRef, RefCountPtr< Lang::Instance >( newObj ) ) );
1161 void
1162 Lang::UserClass::findParents( std::set< RefCountPtr< const Lang::Class > > * _allParents, std::set< RefCountPtr< const Lang::Class > > * _multiParents ) const
1164 Lang::Class::findParents( _allParents, _multiParents );
1165 typedef typeof immediateParents SetType;
1166 for( SetType::const_iterator i = immediateParents.begin( ); i != immediateParents.end( ); ++i )
1168 (*i)->findParents( _allParents, _multiParents );
1172 bool
1173 Lang::UserClass::isRepeatableBase( ) const
1175 return classExpr->isRepeatableBase( );
1178 void
1179 Lang::UserClass::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
1181 classExpr->prepareInstance( evalState, privateEnv );
1185 bool
1186 Lang::UserClass::isInPublicGetSet( const char * field ) const
1188 return classExpr->isInPublicGetSet( field );
1191 bool
1192 Lang::UserClass::isInPublicSetSet( const char * field ) const
1194 return classExpr->isInPublicSetSet( field );
1197 bool
1198 Lang::UserClass::isInProtectedGetSet( const char * field ) const
1200 return classExpr->isInProtectedGetSet( field );
1203 bool
1204 Lang::UserClass::isInProtectedSetSet( const char * field ) const
1206 return classExpr->isInProtectedSetSet( field );
1209 bool
1210 Lang::UserClass::isInTransformingSet( const char * field ) const
1212 return classExpr->isInTransformingSet( field );
1216 void
1217 Lang::UserClass::addOverrides( Kernel::EvalState * evalState, RefCountPtr< Lang::Instance > instance, Kernel::PassedEnv privateEnv ) const
1219 typedef typeof *overrides DefMapType;
1220 for( DefMapType::const_iterator i = overrides->begin( ); i != overrides->end( ); ++i )
1222 typedef std::map< const char *, RefCountPtr< const Lang::Function >, charPtrLess > InstanceMapType;
1223 InstanceMapType & instanceMap = instance->overrides[ i->first ];
1224 typedef typeof i->second DefListType;
1225 InstanceMapType::iterator lastInsert = instanceMap.begin( );
1226 for( DefListType::const_iterator j = i->second.begin( ); j != i->second.end( ); ++j )
1228 throw Exceptions::NotImplemented( "addOverrides" );
1229 // RefCountPtr< const Lang::Value > untypedMethod = (*j)->init->value( dstgroup, pdfo, metaState, privateEnv );
1230 // typedef const Lang::Function FunType;
1231 // RefCountPtr< FunType > typedMethod = untypedMethod.down_cast< FunType >( );
1232 // if( typedMethod == NullPtr< FunType >( ) )
1233 // {
1234 // throw Exceptions::TypeMismatch( (*j)->init, untypedMethod->getTypeName( ), FunType::staticTypeName( ) );
1235 // }
1236 // lastInsert = instanceMap.insert( lastInsert, InstanceMapType::value_type( (*j)->id, typedMethod ) );
1241 void
1242 Lang::UserClass::gcMark( Kernel::GCMarkedSet & marked )
1244 throw Exceptions::NotImplemented( "UserClass::gcMark" );
1250 Lang::ClassMethodBase::ClassMethodBase( RefCountPtr< const Lang::Class > _self )
1251 : Lang::Function( 0 ), self( _self )
1253 std::cerr << "Warning: Lang::ClassMethodBase::ClassMethodBase initializes Lang::Function with 0 pointer to formals." << std::endl ;
1256 Lang::ClassMethodBase::~ClassMethodBase( )
1259 void
1260 Lang::ClassMethodBase::gcMark( Kernel::GCMarkedSet & marked )
1262 const_cast< Lang::Class * >( self.getPtr( ) )->gcMark( marked );
1265 bool
1266 Lang::ClassMethodBase::isTransforming( ) const
1268 return false;
1271 Lang::ClassMethodNew::ClassMethodNew( RefCountPtr< const Lang::Class > _self )
1272 : Lang::ClassMethodBase( _self )
1275 void
1276 Lang::ClassMethodNew::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1278 self->method_new( evalState, args, callLoc );
1281 Lang::ClassMethodIsa::ClassMethodIsa( RefCountPtr< const Lang::Class > _self )
1282 : Lang::ClassMethodBase( _self )
1285 void
1286 Lang::ClassMethodIsa::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
1288 const size_t ARITY = 1;
1289 CHECK_ARITY( args, ARITY, Kernel::MethodId( Lang::Class::TypeID, "isa" ).prettyName( ) );
1291 typedef const Lang::Class ArgType;
1292 RefCountPtr< ArgType > T = args.getValue( 0 ).down_cast< ArgType >( );
1293 if( T == NullPtr< ArgType >( ) )
1295 throw Exceptions::CoreTypeMismatch( callLoc, Kernel::MethodId( Lang::Class::TypeID, "isa" ).prettyName( ), args, 0, ArgType::staticTypeName( ) );
1298 Kernel::ContRef cont = evalState->cont_;
1299 cont->takeValue( Kernel::ValueRef( new Lang::Boolean( self->method_isa( T ) ) ),
1300 evalState );