Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / astclass.cc
blob42a00edfb81a8820012efa7815fa770d9a77d62e
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 "Shapes_Helpers_decls.h"
21 #include "astclass.h"
22 #include "shapesexceptions.h"
23 #include "classexceptions.h"
24 #include "consts.h"
25 #include "globals.h"
26 #include "astvar.h"
27 #include "shapescore.h"
29 #include <string>
31 using namespace Shapes;
34 Ast::MethodIdExpr::MethodIdExpr( const Ast::SourceLocation & loc, Ast::Expression * classPart, const char * name )
35 : loc_( loc ), classPart_( classPart ), name_( name )
36 { }
38 Ast::MethodIdExpr::~MethodIdExpr( )
39 { }
41 // Kernel::MethodId
42 // Ast::MethodIdExpr::identifier( Kernel::Environment::VariableHandle dstgroup, SimplePDF::PDF_out * pdfo, Kernel::GraphicsState * metaState, Kernel::PassedEnv env ) const
43 // {
44 // RefCountPtr< const Lang::Value > untypedClass = classPart->value( dstgroup, pdfo, metaState, env );
45 // typedef const Lang::Class ArgType;
46 // RefCountPtr< ArgType > typedClass = untypedClass.down_cast< ArgType >( );
47 // if( typedClass == NullPtr< ArgType >( ) )
48 // {
49 // throw Exceptions::TypeMismatch( classPart, untypedClass->getTypeName( ), ArgType::staticTypeName( ) );
50 // }
51 // return Kernel::MethodId( typedClass, id->identifier( dstgroup, pdfo, metaState, env ) );
52 // }
56 Ast::MemberDeclaration::MemberDeclaration( const Ast::SourceLocation & loc, const char * id, Ast::Expression * init, const Ast::MemberMode & mode )
57 : loc_( loc ), id_( id ), init_( init ), mode_( mode )
59 checkModeConsistency( );
62 Ast::MemberDeclaration::~MemberDeclaration( )
64 delete init_;
67 void
68 Ast::MemberDeclaration::addModeBits( const Ast::MemberMode & bits )
70 mode_ |= bits;
71 checkModeConsistency( );
74 void
75 Ast::MemberDeclaration::checkModeConsistency( )
77 if( ( mode_ & Ast::MEMBER_CONST ) != 0 && ( mode_ & ( Ast::MEMBER_ACCESS_PUBLIC_INSERT | Ast::MEMBER_ACCESS_PROTECTED_INSERT ) ) != 0 )
79 throw Exceptions::ParserError( loc_, strrefdup( "The member cannot be declared both const and assignable." ) );
84 Ast::ClassSection::ClassSection( )
85 { }
87 Ast::ClassSection::~ClassSection( )
88 { }
91 Ast::MemberSection::MemberSection( )
92 { }
94 Ast::MemberSection::~MemberSection( )
96 /* We must not delete the declarations here. This class is only used to pass these declarations on to a ClassExpression, which will be responsible for deletion.
100 void
101 Ast::MemberSection::addModeBits( const Ast::MemberMode & bits )
103 for( iterator i = begin( ); i != end( ); ++i )
105 (*i)->addModeBits( bits );
110 Ast::PrepareSection::PrepareSection( const Ast::SourceLocation & loc, std::list< Ast::Node * > * nodes )
111 : loc_( loc ), nodes_( nodes )
114 Ast::PrepareSection::~PrepareSection( )
116 /* We must not delete the expressions here. This class is only used to pass these expressions on to a ClassExpression, which will be responsible for deletion.
117 * However, the list shall be deleted.
119 delete nodes_;
123 Ast::AbstractSection::AbstractSection( const Ast::SourceLocation & loc, const std::list< RefCountPtr< const char > > * methods )
124 : loc_( loc ), methods_( methods )
127 Ast::AbstractSection::~AbstractSection( )
129 delete methods_;
133 Ast::OverridesSection::OverridesSection( Ast::Expression * super, Ast::MemberSection * members )
134 : super_( super ), members_( members )
137 Ast::OverridesSection::~OverridesSection( )
139 delete super_;
140 delete members_;
144 Ast::ClassFunction::ClassFunction( const Ast::SourceLocation & loc, Ast::Expression * name, const Kernel::Formals * constructorFormals, std::list< const Ast::CallExpr * > * parentsWithInitArgs, Ast::MemberMode classMode, std::list< Ast::ClassSection * > * sections )
145 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< class construction >" ), true ) ), loc_( loc ), name_( name ), constructorFormals_( constructorFormals ), parentsWithInitArgs_( parentsWithInitArgs ), isAbstract_( ( classMode & Ast::CLASS_MODE_ABSTRACT ) != 0 ), isFinal_( ( classMode & Ast::CLASS_MODE_FINAL ) != 0 )
147 for( std::list< Ast::ClassSection * >::iterator i = sections->begin( ); i != sections->end( ); ++i )
150 typedef Ast::MemberSection T;
151 T * memberSection = dynamic_cast< T * >( *i );
152 if( memberSection != 0 )
154 for( std::list< Ast::MemberDeclaration * >::iterator j = memberSection->begin( );
155 j != memberSection->end( );
156 ++j )
158 members_.push_back( *j );
160 delete *i;
161 continue;
165 typedef Ast::PrepareSection T;
166 T * prepareSection = dynamic_cast< T * >( *i );
167 if( prepareSection != 0 )
169 for( std::list< Ast::Node * >::iterator j = prepareSection->nodes_->begin( );
170 j != prepareSection->nodes_->end( );
171 ++j )
173 preparations_.push_back( *j );
175 delete *i;
176 continue;
180 typedef Ast::OverridesSection T;
181 T * overridesSection = dynamic_cast< T * >( *i );
182 if( overridesSection != 0 )
184 overrides_.push_back( overridesSection );
185 continue;
189 typedef Ast::AbstractSection T;
190 T * abstractSection = dynamic_cast< T * >( *i );
191 if( abstractSection != 0 )
193 for( std::list< RefCountPtr< const char > >::const_iterator j = abstractSection->methods_->begin( );
194 j != abstractSection->methods_->end( );
195 ++j )
197 abstractSet_.insert( strdup( j->getPtr( ) ) );
199 continue;
202 throw Exceptions::InternalError( strrefdup( "ClassFunction::ClassFunction: the ClassSection was neither of the expected types" ) );
204 delete sections;
207 typedef std::map< const char *, Ast::MemberDeclaration *, charPtrLess > MapType;
208 MapType seen;
209 for( std::list< Ast::MemberDeclaration * >::const_iterator i = members_.begin( ); i != members_.end( ); ++i )
212 if( abstractSet_.find( (*i)->id_ ) != abstractSet_.end( ) )
214 throw Exceptions::MemberAlsoAbstract( (*i)->loc_, (*i)->id_, Ast::THE_UNKNOWN_LOCATION );
216 MapType::const_iterator j = seen.find( (*i)->id_ );
217 if( j != seen.end( ) )
219 throw Exceptions::MemberAlreadyDeclared( (*i)->loc_, (*i)->id_, j->second->loc_ );
221 seen[ (*i)->id_ ] = *i;
223 if( ( (*i)->mode_ & Ast::MEMBER_ACCESS_PUBLIC_GET ) != 0 )
225 if( ( (*i)->mode_ & Ast::MEMBER_METHOD ) == 0 && ! isFinal_ )
227 throw Exceptions::PublicGetSetInNonfinalClass( (*i)->loc_, (*i)->id_ );
229 publicGetSet_.insert( (*i)->id_ );
231 if( ( (*i)->mode_ & Ast::MEMBER_ACCESS_PROTECTED_GET ) != 0 )
233 protectedGetSet_.insert( (*i)->id_ );
235 if( ( (*i)->mode_ & Ast::MEMBER_ACCESS_PUBLIC_INSERT ) != 0 )
237 if( ( (*i)->mode_ & Ast::MEMBER_METHOD ) == 0 && ! isFinal_ )
239 throw Exceptions::PublicGetSetInNonfinalClass( (*i)->loc_, (*i)->id_ );
241 publicSetSet_.insert( (*i)->id_ );
243 if( ( (*i)->mode_ & Ast::MEMBER_ACCESS_PROTECTED_INSERT ) != 0 )
245 protectedSetSet_.insert( (*i)->id_ );
247 if( ( (*i)->mode_ & Ast::MEMBER_FINAL ) != 0 )
249 finalSet_.insert( (*i)->id_ );
251 if( ( (*i)->mode_ & Ast::MEMBER_TRANSFORMING ) != 0 )
253 if( ( (*i)->mode_ & Ast::MEMBER_METHOD ) == 0 && ! isFinal_ )
255 throw Exceptions::TransformingMemberInNonfinalClass( (*i)->loc_, (*i)->id_ );
257 transformingSet_.insert( (*i)->id_ );
263 Ast::ClassFunction::~ClassFunction( )
265 delete name_;
267 delete constructorFormals_;
269 for( std::list< const Ast::CallExpr * >::iterator i = parentsWithInitArgs_->begin( );
270 i != parentsWithInitArgs_->end( );
271 ++i )
273 delete *i;
275 delete parentsWithInitArgs_;
277 /* preparations_ and members_ delete their elements by themselves
282 void
283 Ast::ClassFunction::push_exprs( Ast::ArgListExprs * args ) const
285 args->orderedExprs_->push_back( name_ );
287 constructorFormals_->push_exprs( args );
289 typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ParentClassList;
290 RefCountPtr< ParentClassList > parents = RefCountPtr< ParentClassList >( new ParentClassList );
291 for( std::list< const Ast::CallExpr * >::iterator i = parentsWithInitArgs_->begin( );
292 i != parentsWithInitArgs_->end( );
293 ++i )
295 args->orderedExprs_->push_back( (*i)->funExpr_ );
299 typedef std::map< RefCountPtr< const Lang::Class >, std::map< const char *, Ast::MemberDeclaration *, charPtrLess > > MapType;
300 MapType seen;
302 typedef typeof overrides_ ListType;
303 for( ListType::const_iterator i = overrides_.begin( ); i != overrides_.end( ); ++i )
305 args->orderedExprs_->push_back( (*i)->super_ );
311 void
312 Ast::ClassFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
314 size_t pos = 0;
315 RefCountPtr< const Lang::String > typedName = args.getHandle( pos )->getVal< const Lang::String >( name_->loc( ) );
316 ++pos;
318 Kernel::EvaluatedFormals * evaluatedFormals = constructorFormals_->newEvaluatedFormals( args, & pos );
320 typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ParentClassList;
321 RefCountPtr< ParentClassList > parents = RefCountPtr< ParentClassList >( new ParentClassList );
322 for( std::list< const Ast::CallExpr * >::iterator i = parentsWithInitArgs_->begin( );
323 i != parentsWithInitArgs_->end( );
324 ++i )
326 RefCountPtr< const Lang::Class > typedParent = args.getHandle( pos )->getVal< const Lang::Class >( (*i)->funExpr_->loc( ) );
327 ++pos;
328 parents->push_back( std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * >( typedParent, (*i)->argList_ ) );
331 std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > > * overridesMap = new std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > >;
333 typedef std::map< RefCountPtr< const Lang::Class >, std::map< const char *, Ast::MemberDeclaration *, charPtrLess > > MapType;
334 MapType seen;
336 typedef typeof overrides_ ListType;
337 for( ListType::const_iterator i = overrides_.begin( ); i != overrides_.end( ); ++i )
339 RefCountPtr< const Lang::Class > typedParent = args.getHandle( pos )->getVal< const Lang::Class >( (*i)->super_->loc( ) );
340 ++pos;
341 std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > >::iterator j = overridesMap->find( typedParent );
342 if( j == overridesMap->end( ) )
344 j = overridesMap->insert( j, std::pair< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > >( typedParent, std::list< Ast::MemberDeclaration * >( ) ) );
346 std::map< const char *, Ast::MemberDeclaration *, charPtrLess > & currentClassSeen = seen[ typedParent ];
347 for( std::list< Ast::MemberDeclaration * >::const_iterator k = (*i)->members_->begin( ); k != (*i)->members_->end( ); ++k )
349 std::map< const char *, Ast::MemberDeclaration *, charPtrLess >::const_iterator l = currentClassSeen.find( (*k)->id_ );
350 if( l != currentClassSeen.end( ) )
352 throw Exceptions::MemberAlreadyDeclared( (*k)->loc_, (*k)->id_, l->second->loc_ );
354 currentClassSeen[ (*k)->id_ ] = *k;
356 j->second.push_back( *k );
361 Lang::UserClass * res = new Lang::UserClass( this,
362 evalState->env_,
363 typedName->val_,
364 evaluatedFormals,
365 parents,
366 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > > >( overridesMap ),
367 isFinal_ );
368 RefCountPtr< const Lang::Class > resRef = RefCountPtr< const Lang::Class >( res );
369 res->setSelfRef( resRef );
370 res->setupAndCheck( isAbstract_ );
372 Kernel::ContRef cont = evalState->cont_;
373 cont->takeValue( resRef,
374 evalState );
377 bool
378 Ast::ClassFunction::isInPublicGetSet( const char * field ) const
380 return publicGetSet_.find( field ) != publicGetSet_.end( );
383 bool
384 Ast::ClassFunction::isInPublicSetSet( const char * field ) const
386 return publicSetSet_.find( field ) != publicSetSet_.end( );
389 bool
390 Ast::ClassFunction::isInProtectedGetSet( const char * field ) const
392 return protectedGetSet_.find( field ) != protectedGetSet_.end( );
395 bool
396 Ast::ClassFunction::isInProtectedSetSet( const char * field ) const
398 return protectedSetSet_.find( field ) != protectedSetSet_.end( );
401 bool
402 Ast::ClassFunction::isInAbstractSet( const char * field ) const
404 return abstractSet_.find( field ) != abstractSet_.end( );
407 bool
408 Ast::ClassFunction::isInFinalSet( const char * field ) const
410 return finalSet_.find( field ) != finalSet_.end( );
413 bool
414 Ast::ClassFunction::isInTransformingSet( const char * field ) const
416 return transformingSet_.find( field ) != transformingSet_.end( );
419 Lang::Class::MessageMapType
420 Ast::ClassFunction::getLocalMessageMap( RefCountPtr< const Lang::Class > _myClass ) const
422 Lang::Class::MessageMapType res;
424 typedef typeof abstractSet_ ListType;
425 for( ListType::const_iterator i = abstractSet_.begin( ); i != abstractSet_.end( ); ++i )
427 res[ Kernel::MethodId( _myClass, *i ) ];
431 typedef typeof members_ ListType;
432 for( ListType::const_iterator i = members_.begin( ); i != members_.end( ); ++i )
434 if( ( (*i)->mode_ & Ast::MEMBER_METHOD ) == 0 )
436 continue;
438 std::set< RefCountPtr< const Lang::Class > > & theSet = res[ Kernel::MethodId( _myClass, (*i)->id_ ) ];
439 theSet.insert( theSet.begin( ), _myClass );
442 return res;
445 bool
446 Ast::ClassFunction::isRepeatableBase( ) const
448 return constructorFormals_->argumentOrder_->empty( );
451 #if 0
452 void
453 Ast::ClassFunction::bindInitializationArguments( RefCountPtr< const Lang::Class > theClass, Kernel::PassedEnv initEnv, Kernel::Arguments & args ) const
455 if( args.size( ) != constructorFormals_->size( ) )
457 throw Exceptions::UserArityMismatch( this, constructorFormals_->size( ), args.size( ), Exceptions::UserArityMismatch::VARIABLE );
460 std::list< Kernel::ValueRef >::const_iterator val = args.begin( );
461 std::list< Kernel::ValueRef >::const_iterator end = args.end( );
462 std::list< RefCountPtr< const char > >::const_iterator formal = constructorFormals_->begin( );
463 Ast::SourceLocation dummy;
464 for( ; val != end; ++val, ++formal )
466 initEnv->define( dummy, *formal, *val, true ); /* true means constant; the initialization parameters shall not be confused with object states */
469 #endif
471 void
472 Ast::ClassFunction::setupInstance( Kernel::PassedEnv instanceEnv, Kernel::PassedEnv privateEnv, Kernel::EvalState * evalState, Kernel::PassedEnv initEnv ) const
474 throw Exceptions::NotImplemented( "ClassFunction::setupInstance" );
476 // typedef typeof members_ ListType;
477 // for( ListType::const_iterator i = members_.begin( ); i != members_.end( ); ++i )
478 // {
479 // const Ast::MemberDeclaration & decl = **i;
481 // Kernel::PassedEnv * defineEnv = & instanceEnv;
482 // if( ( decl.mode & Ast::MEMBER_ACCESS_BITS ) == Ast::MEMBER_ACCESS_PRIVATE )
483 // {
484 // defineEnv = & privateEnv;
485 // }
487 // Kernel::PassedEnv & evalEnv = initEnv;
488 // if( ( decl.mode & Ast::MEMBER_METHOD ) != 0 )
489 // {
490 // evalEnv = privateEnv;
491 // }
493 // (*defineEnv)->define( decl.loc, decl.id, decl.init->value( dstgroup, pdfo, metaState, evalEnv ), ( decl.mode & ( Ast::MEMBER_METHOD | Ast::MEMBER_CONST ) ) != 0 );
494 // }
497 void
498 Ast::ClassFunction::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
500 throw Exceptions::NotImplemented( "ClassFunction::prepareInstance" );
502 // Ast::CodeBracket::evalSequence( preparations.begin( ), preparations.end( ), metaState, privateEnv, false );
505 const Ast::SourceLocation &
506 Ast::ClassFunction::loc( ) const
508 return loc_;
512 Ast::PublicMethodReferenceFunction::PublicMethodReferenceFunction( const Ast::SourceLocation & loc, Ast::Expression * obj, MethodIdExpr * methodId )
513 : Lang::Function( 0 ), loc_( loc ), obj_( obj ), methodClass_( methodId->classPart_ ), methodName_( strdup( methodId->name_ ) )
515 std::cerr << "Warning: Ast::PublicMethodReferenceFunction::PublicMethodReferenceFunction initializes Lang::Function with 0 pointer to formals." << std::endl ;
516 delete methodId;
519 Ast::PublicMethodReferenceFunction::~PublicMethodReferenceFunction( )
521 delete obj_;
522 delete methodClass_;
525 void
526 Ast::PublicMethodReferenceFunction::push_exprs( Ast::ArgListExprs * args ) const
528 args->orderedExprs_->push_back( obj_ );
529 args->orderedExprs_->push_back( methodClass_ );
532 void
533 Ast::PublicMethodReferenceFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
535 RefCountPtr< const Lang::Value > untypedObj = args.getValue( 0 );
536 Kernel::MethodId methodId( args.getHandle( 1 )->getVal< const Lang::Class >( methodClass_->loc( ) ), methodName_ );
538 typedef const Lang::Instance ObjType;
539 ObjType * typedObj = dynamic_cast< ObjType * >( untypedObj.getPtr( ) );
540 if( typedObj != 0 )
542 Kernel::ContRef cont = evalState->cont_;
543 cont->takeValue( typedObj->getMethod( methodId ),
544 evalState );
545 return;
549 typedef const Lang::TransformedInstance ObjType;
550 ObjType * typedObj = dynamic_cast< ObjType * >( untypedObj.getPtr( ) );
551 if( typedObj != 0 )
553 Kernel::ContRef cont = evalState->cont_;
554 cont->takeValue( typedObj->getMethod( methodId ),
555 evalState );
556 return;
559 throw Exceptions::TypeMismatch( obj_->loc( ), untypedObj->getTypeName( ), Helpers::typeSetString( Lang::Instance::staticTypeName( ), Lang::TransformedInstance::staticTypeName( ) ) );
564 Ast::ProtectedMethodReferenceFunction::ProtectedMethodReferenceFunction( const Ast::SourceLocation & loc, const Ast::SourceLocation & selfLoc, Ast::Expression * parent, Ast::MethodIdExpr * methodId )
565 : Lang::Function( 0 ), loc_( loc ), selfLoc_( selfLoc ), parent_( parent ), methodClass_( methodId->classPart_ ), methodName_( strdup( methodId->name_ ) ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
567 std::cerr << "Warning: Ast::PublicMethodReferenceFunction::PublicMethodReferenceFunction initializes Lang::Function with 0 pointer to formals." << std::endl ;
568 /* Currently, a runtime check is used to ensure that this expression indeed refers to a super instance.
570 delete methodId;
573 Ast::ProtectedMethodReferenceFunction::~ProtectedMethodReferenceFunction( )
575 delete parent_;
576 delete methodClass_;
577 delete methodName_;
578 if( *idKey_ != 0 )
580 delete *idKey_;
582 delete idKey_; // This can be done only as long as this is not shared!
585 void
586 Ast::ProtectedMethodReferenceFunction::push_exprs( Ast::ArgListExprs * args ) const
588 args->orderedExprs_->push_back( methodClass_ );
589 if( parent_ != 0 )
591 args->orderedExprs_->push_back( parent_ );
595 void
596 Ast::ProtectedMethodReferenceFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
598 /* argument expressions shall be analyzed from the calling expression.
599 * Here, they are only used to locate errors.
602 if( *idKey_ == 0 )
606 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalVariableKey( selfLoc_, Lang::SELF_ID ) );
608 catch( const Exceptions::LookupUnknown & ball )
610 throw Exceptions::MisplacedSuperReference( selfLoc_ );
615 void
616 Ast::ProtectedMethodReferenceFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
618 typedef const Lang::Instance SelfType;
619 RefCountPtr< const Lang::Value > untypedSelf = evalState->env_->getVarHandle( **idKey_ )->getUntyped( );
620 SelfType * typedSelf = dynamic_cast< SelfType * >( untypedSelf.getPtr( ) );
621 if( typedSelf == 0 )
623 throw Exceptions::InternalError( strrefdup( "ProtectedMethodAccess: the self variable was not an instance." ) );
626 Kernel::MethodId methodId( args.getHandle( 0 )->getVal< const Lang::Class >( methodClass_->loc( ) ), methodName_ );
628 if( parent_ != 0 )
630 RefCountPtr< const Lang::Class > typedParent = args.getHandle( 1 )->getVal< const Lang::Class >( parent_->loc( ) );
631 Kernel::ContRef cont = evalState->cont_;
632 cont->takeValue( typedSelf->superReference( typedParent )->getLocalMethod( methodId ),
633 evalState );
634 return;
637 /* parent == 0 means a reference to a local override */
638 Kernel::ContRef cont = evalState->cont_;
639 cont->takeValue( typedSelf->getLocalMethod( methodId ),
640 evalState );
644 Ast::ProtectedMemberReferenceFunction::ProtectedMemberReferenceFunction( const Ast::SourceLocation & loc, const Ast::SourceLocation & selfLoc, Ast::Expression * parent, const Ast::SourceLocation & idLoc, const char * id )
645 : Lang::Function( 0 ), loc_( loc ), selfLoc_( selfLoc ), parent_( parent ), idLoc_( idLoc ), id_( id ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
647 std::cerr << "Warning: Ast::ProtectedMemberReferenceFunction::ProtectedMemberReferenceFunction initializes Lang::Function with 0 pointer to formals." << std::endl ;
648 /* Currently, a runtime check is used to ensure that this expression indeed refers to a super instance.
652 Ast::ProtectedMemberReferenceFunction::~ProtectedMemberReferenceFunction( )
654 delete parent_;
655 delete id_;
656 if( *idKey_ != 0 )
658 delete *idKey_;
660 delete idKey_; // This can be done only as long as this is not shared!
663 void
664 Ast::ProtectedMemberReferenceFunction::push_exprs( Ast::ArgListExprs * args ) const
666 args->orderedExprs_->push_back( parent_ );
669 void
670 Ast::ProtectedMemberReferenceFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
672 /* argument expressions shall be analyzed from the calling expression.
673 * Here, they are only used to locate errors.
676 if( *idKey_ == 0 )
680 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalVariableKey( selfLoc_, Lang::SELF_ID ) );
682 catch( const Exceptions::LookupUnknown & ball )
684 throw Exceptions::MisplacedSuperReference( selfLoc_ );
689 void
690 Ast::ProtectedMemberReferenceFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
692 typedef const Lang::Instance SelfType;
693 RefCountPtr< const Lang::Value > untypedSelf = evalState->env_->getVarHandle( **idKey_ )->getUntyped( );
694 SelfType * typedSelf = dynamic_cast< SelfType * >( untypedSelf.getPtr( ) );
695 if( typedSelf == 0 )
697 throw Exceptions::InternalError( strrefdup( "ProtectedMethodAccess: the self variable was not an instance." ) );
700 RefCountPtr< const Lang::Class > typedParent = args.getHandle( 0 )->getVal< const Lang::Class >( parent_->loc( ) );
701 Kernel::ContRef cont = evalState->cont_;
702 cont->takeHandle( typedSelf->superReference( typedParent )->getLocalField( id_ ),
703 evalState );
707 Ast::ProtectedMemberInsertionFunction::ProtectedMemberInsertionFunction( const Ast::SourceLocation & loc, const Ast::SourceLocation & selfLoc, Ast::Expression * parent, const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * pieceExpr )
708 : Lang::Function( 0 ), loc_( loc ), selfLoc_( selfLoc ), parent_( parent ), idLoc_( idLoc ), id_( id ), pieceExpr_( pieceExpr ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
710 std::cerr << "Warning: Ast::ProtectedMemberInsertionFunction::ProtectedMemberInsertionFunction initializes Lang::Function with 0 pointer to formals." << std::endl ;
711 /* Currently, a runtime check is used to ensure that this expression indeed refers to a super instance.
715 Ast::ProtectedMemberInsertionFunction::~ProtectedMemberInsertionFunction( )
717 if( parent_ != 0 )
719 delete parent_;
721 delete id_;
722 delete pieceExpr_;
723 if( *idKey_ != 0 )
725 delete *idKey_;
727 delete idKey_; // This can be done only as long as this is not shared!
730 void
731 Ast::ProtectedMemberInsertionFunction::push_exprs( Ast::ArgListExprs * args ) const
733 args->orderedExprs_->push_back( pieceExpr_ );
734 if( parent_ != 0 )
736 args->orderedExprs_->push_back( parent_ );
740 void
741 Ast::ProtectedMemberInsertionFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
743 /* argument expressions shall be analyzed from the calling expression.
744 * Here, they are only used to locate errors.
747 if( *idKey_ == 0 )
751 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalStateKey( selfLoc_, Lang::SELF_ID ) );
753 catch( const Exceptions::LookupUnknown & ball )
755 throw Exceptions::MisplacedSuperReference( selfLoc_ );
760 void
761 Ast::ProtectedMemberInsertionFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
763 typedef const Lang::Instance SelfType;
764 RefCountPtr< const Lang::Value > untypedSelf = evalState->env_->getVarHandle( **idKey_ )->getUntyped( );
765 SelfType * typedSelf = dynamic_cast< SelfType * >( untypedSelf.getPtr( ) );
766 if( typedSelf == 0 )
768 throw Exceptions::InternalError( strrefdup( "ProtectedMethodAccess: the self variable was not an instance." ) );
771 RefCountPtr< const Lang::Value > piece = args.getValue( 0 );
773 throw Exceptions::NotImplemented( "Tacking on fields." );
775 // if( parent_ == 0 )
776 // {
777 // typedSelf->getField( id_, untypedSelf )->tackOn( evalState, piece, pieceExpr_->loc( ) );
778 // return;
779 // }
781 // RefCountPtr< const Lang::Class > typedParent = args.getHandle( 1 )->getVal< const Lang::Class >( parent_->loc( ) );
782 // typedSelf->superReference( typedParent )->getLocalField( id_ )->tackOn( evalState, piece, pieceExpr_->loc( ) );