Update procedures
[shapes.git] / source / astclass.cc
blobf011a871e6eb14bd513f394480a7511f6d8b6ab1
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, 2010, 2014 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"
28 #include "warn.h"
30 #include <string>
32 using namespace Shapes;
35 Ast::MethodIdExpr::MethodIdExpr( const Ast::SourceLocation & loc, Ast::Expression * classPart, const char * name )
36 : loc_( loc, bool( ) ), classPart_( classPart ), name_( name )
37 { }
39 Ast::MethodIdExpr::~MethodIdExpr( )
40 { }
42 // Kernel::MethodId
43 // Ast::MethodIdExpr::identifier( Kernel::Environment::VariableHandle dstgroup, SimplePDF::PDF_out * pdfo, Kernel::GraphicsState * metaState, Kernel::PassedEnv env ) const
44 // {
45 // RefCountPtr< const Lang::Value > untypedClass = classPart->value( dstgroup, pdfo, metaState, env );
46 // typedef const Lang::Class ArgType;
47 // RefCountPtr< ArgType > typedClass = untypedClass.down_cast< ArgType >( );
48 // if( typedClass == NullPtr< ArgType >( ) )
49 // {
50 // throw Exceptions::TypeMismatch( classPart, untypedClass->getTypeName( ), ArgType::staticTypeName( ) );
51 // }
52 // return Kernel::MethodId( typedClass, id->identifier( dstgroup, pdfo, metaState, env ) );
53 // }
57 Ast::MemberDeclaration::MemberDeclaration( const Ast::SourceLocation & loc, const char * id, Ast::Expression * init, const Ast::MemberMode & mode )
58 : loc_( loc, bool( ) ), id_( id ), init_( init ), mode_( mode )
60 checkModeConsistency( );
63 Ast::MemberDeclaration::~MemberDeclaration( )
65 delete init_;
68 void
69 Ast::MemberDeclaration::addModeBits( const Ast::MemberMode & bits )
71 mode_ |= bits;
72 checkModeConsistency( );
75 void
76 Ast::MemberDeclaration::checkModeConsistency( )
78 if( ( mode_ & Ast::MEMBER_CONST ) != 0 && ( mode_ & ( Ast::MEMBER_ACCESS_PUBLIC_INSERT | Ast::MEMBER_ACCESS_PROTECTED_INSERT ) ) != 0 )
80 throw Exceptions::ParserError( loc_, strrefdup( "The member cannot be declared both const and assignable." ) );
85 Ast::ClassSection::ClassSection( )
86 { }
88 Ast::ClassSection::~ClassSection( )
89 { }
92 Ast::MemberSection::MemberSection( )
93 { }
95 Ast::MemberSection::~MemberSection( )
97 /* 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.
101 void
102 Ast::MemberSection::addModeBits( const Ast::MemberMode & bits )
104 for( iterator i = begin( ); i != end( ); ++i )
106 (*i)->addModeBits( bits );
111 Ast::PrepareSection::PrepareSection( const Ast::SourceLocation & loc, std::list< Ast::Node * > * nodes )
112 : loc_( loc, bool( ) ), nodes_( nodes )
115 Ast::PrepareSection::~PrepareSection( )
117 /* 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.
118 * However, the list shall be deleted.
120 delete nodes_;
124 Ast::AbstractSection::AbstractSection( const Ast::SourceLocation & loc, const std::list< RefCountPtr< const char > > * methods )
125 : loc_( loc, bool( ) ), methods_( methods )
128 Ast::AbstractSection::~AbstractSection( )
130 delete methods_;
134 Ast::OverridesSection::OverridesSection( Ast::Expression * super, Ast::MemberSection * members )
135 : super_( super ), members_( members )
138 Ast::OverridesSection::~OverridesSection( )
140 delete super_;
141 delete members_;
145 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 )
146 : Lang::Function( new Kernel::EvaluatedFormals( Ast::FileID::build_internal( "< class construction >" ), true ) ), loc_( loc, bool( ) ), name_( name ), constructorFormals_( constructorFormals ), parentsWithInitArgs_( parentsWithInitArgs ), isAbstract_( ( classMode & Ast::CLASS_MODE_ABSTRACT ) != 0 ), isFinal_( ( classMode & Ast::CLASS_MODE_FINAL ) != 0 )
148 for( std::list< Ast::ClassSection * >::iterator i = sections->begin( ); i != sections->end( ); ++i )
151 typedef Ast::MemberSection T;
152 T * memberSection = dynamic_cast< T * >( *i );
153 if( memberSection != 0 )
155 for( std::list< Ast::MemberDeclaration * >::iterator j = memberSection->begin( );
156 j != memberSection->end( );
157 ++j )
159 members_.push_back( *j );
161 delete *i;
162 continue;
166 typedef Ast::PrepareSection T;
167 T * prepareSection = dynamic_cast< T * >( *i );
168 if( prepareSection != 0 )
170 for( std::list< Ast::Node * >::iterator j = prepareSection->nodes_->begin( );
171 j != prepareSection->nodes_->end( );
172 ++j )
174 preparations_.push_back( *j );
176 delete *i;
177 continue;
181 typedef Ast::OverridesSection T;
182 T * overridesSection = dynamic_cast< T * >( *i );
183 if( overridesSection != 0 )
185 overrides_.push_back( overridesSection );
186 continue;
190 typedef Ast::AbstractSection T;
191 T * abstractSection = dynamic_cast< T * >( *i );
192 if( abstractSection != 0 )
194 for( std::list< RefCountPtr< const char > >::const_iterator j = abstractSection->methods_->begin( );
195 j != abstractSection->methods_->end( );
196 ++j )
198 abstractSet_.insert( strdup( j->getPtr( ) ) );
200 continue;
203 throw Exceptions::InternalError( strrefdup( "ClassFunction::ClassFunction: the ClassSection was neither of the expected types" ) );
205 delete sections;
208 typedef std::map< const char *, Ast::MemberDeclaration *, charPtrLess > MapType;
209 MapType seen;
210 for( std::list< Ast::MemberDeclaration * >::const_iterator i = members_.begin( ); i != members_.end( ); ++i )
213 if( abstractSet_.find( (*i)->id_ ) != abstractSet_.end( ) )
215 throw Exceptions::MemberAlsoAbstract( (*i)->loc_, (*i)->id_, Ast::THE_UNKNOWN_LOCATION );
217 MapType::const_iterator j = seen.find( (*i)->id_ );
218 if( j != seen.end( ) )
220 throw Exceptions::MemberAlreadyDeclared( (*i)->loc_, (*i)->id_, j->second->loc_ );
222 seen[ (*i)->id_ ] = *i;
224 if( ( (*i)->mode_ & Ast::MEMBER_ACCESS_PUBLIC_GET ) != 0 )
226 if( ( (*i)->mode_ & Ast::MEMBER_METHOD ) == 0 && ! isFinal_ )
228 throw Exceptions::PublicGetSetInNonfinalClass( (*i)->loc_, (*i)->id_ );
230 publicGetSet_.insert( (*i)->id_ );
232 if( ( (*i)->mode_ & Ast::MEMBER_ACCESS_PROTECTED_GET ) != 0 )
234 protectedGetSet_.insert( (*i)->id_ );
236 if( ( (*i)->mode_ & Ast::MEMBER_ACCESS_PUBLIC_INSERT ) != 0 )
238 if( ( (*i)->mode_ & Ast::MEMBER_METHOD ) == 0 && ! isFinal_ )
240 throw Exceptions::PublicGetSetInNonfinalClass( (*i)->loc_, (*i)->id_ );
242 publicSetSet_.insert( (*i)->id_ );
244 if( ( (*i)->mode_ & Ast::MEMBER_ACCESS_PROTECTED_INSERT ) != 0 )
246 protectedSetSet_.insert( (*i)->id_ );
248 if( ( (*i)->mode_ & Ast::MEMBER_FINAL ) != 0 )
250 finalSet_.insert( (*i)->id_ );
252 if( ( (*i)->mode_ & Ast::MEMBER_TRANSFORMING ) != 0 )
254 if( ( (*i)->mode_ & Ast::MEMBER_METHOD ) == 0 && ! isFinal_ )
256 throw Exceptions::TransformingMemberInNonfinalClass( (*i)->loc_, (*i)->id_ );
258 transformingSet_.insert( (*i)->id_ );
264 Ast::ClassFunction::~ClassFunction( )
266 delete name_;
268 delete constructorFormals_;
270 for( std::list< const Ast::CallExpr * >::iterator i = parentsWithInitArgs_->begin( );
271 i != parentsWithInitArgs_->end( );
272 ++i )
274 delete *i;
276 delete parentsWithInitArgs_;
278 /* preparations_ and members_ delete their elements by themselves
283 void
284 Ast::ClassFunction::push_exprs( Ast::ArgListExprs * args ) const
286 args->orderedExprs_->push_back( name_ );
288 constructorFormals_->push_exprs( args );
290 typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ParentClassList;
291 RefCountPtr< ParentClassList > parents = RefCountPtr< ParentClassList >( new ParentClassList );
292 for( std::list< const Ast::CallExpr * >::iterator i = parentsWithInitArgs_->begin( );
293 i != parentsWithInitArgs_->end( );
294 ++i )
296 args->orderedExprs_->push_back( (*i)->funExpr_ );
300 typedef std::map< RefCountPtr< const Lang::Class >, std::map< const char *, Ast::MemberDeclaration *, charPtrLess > > MapType;
301 MapType seen;
303 typedef typeof overrides_ ListType;
304 for( ListType::const_iterator i = overrides_.begin( ); i != overrides_.end( ); ++i )
306 args->orderedExprs_->push_back( (*i)->super_ );
312 void
313 Ast::ClassFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
315 size_t pos = 0;
316 RefCountPtr< const Lang::String > typedName = args.getHandle( pos )->getVal< const Lang::String >( name_->loc( ) );
317 ++pos;
319 Kernel::EvaluatedFormals * evaluatedFormals = constructorFormals_->newEvaluatedFormals( args, & pos );
321 typedef std::list< std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * > > ParentClassList;
322 RefCountPtr< ParentClassList > parents = RefCountPtr< ParentClassList >( new ParentClassList );
323 for( std::list< const Ast::CallExpr * >::iterator i = parentsWithInitArgs_->begin( );
324 i != parentsWithInitArgs_->end( );
325 ++i )
327 RefCountPtr< const Lang::Class > typedParent = args.getHandle( pos )->getVal< const Lang::Class >( (*i)->funExpr_->loc( ) );
328 ++pos;
329 parents->push_back( std::pair< RefCountPtr< const Lang::Class >, const Ast::ArgListExprs * >( typedParent, (*i)->argList_ ) );
332 std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > > * overridesMap = new std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > >;
334 typedef std::map< RefCountPtr< const Lang::Class >, std::map< const char *, Ast::MemberDeclaration *, charPtrLess > > MapType;
335 MapType seen;
337 typedef typeof overrides_ ListType;
338 for( ListType::const_iterator i = overrides_.begin( ); i != overrides_.end( ); ++i )
340 RefCountPtr< const Lang::Class > typedParent = args.getHandle( pos )->getVal< const Lang::Class >( (*i)->super_->loc( ) );
341 ++pos;
342 std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > >::iterator j = overridesMap->find( typedParent );
343 if( j == overridesMap->end( ) )
345 j = overridesMap->insert( j, std::pair< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > >( typedParent, std::list< Ast::MemberDeclaration * >( ) ) );
347 std::map< const char *, Ast::MemberDeclaration *, charPtrLess > & currentClassSeen = seen[ typedParent ];
348 for( std::list< Ast::MemberDeclaration * >::const_iterator k = (*i)->members_->begin( ); k != (*i)->members_->end( ); ++k )
350 std::map< const char *, Ast::MemberDeclaration *, charPtrLess >::const_iterator l = currentClassSeen.find( (*k)->id_ );
351 if( l != currentClassSeen.end( ) )
353 throw Exceptions::MemberAlreadyDeclared( (*k)->loc_, (*k)->id_, l->second->loc_ );
355 currentClassSeen[ (*k)->id_ ] = *k;
357 j->second.push_back( *k );
362 Lang::UserClass * res = new Lang::UserClass( this,
363 // evalState->env_,
364 typedName->val_,
365 evaluatedFormals,
366 parents,
367 RefCountPtr< std::map< RefCountPtr< const Lang::Class >, std::list< Ast::MemberDeclaration * > > >( overridesMap ),
368 isFinal_ );
369 RefCountPtr< const Lang::Class > resRef = RefCountPtr< const Lang::Class >( res );
370 res->setSelfRef( resRef );
371 res->setupAndCheck( isAbstract_ );
373 Kernel::ContRef cont = evalState->cont_;
374 cont->takeValue( resRef,
375 evalState );
378 bool
379 Ast::ClassFunction::isInPublicGetSet( const char * field ) const
381 return publicGetSet_.find( field ) != publicGetSet_.end( );
384 bool
385 Ast::ClassFunction::isInPublicSetSet( const char * field ) const
387 return publicSetSet_.find( field ) != publicSetSet_.end( );
390 bool
391 Ast::ClassFunction::isInProtectedGetSet( const char * field ) const
393 return protectedGetSet_.find( field ) != protectedGetSet_.end( );
396 bool
397 Ast::ClassFunction::isInProtectedSetSet( const char * field ) const
399 return protectedSetSet_.find( field ) != protectedSetSet_.end( );
402 bool
403 Ast::ClassFunction::isInAbstractSet( const char * field ) const
405 return abstractSet_.find( field ) != abstractSet_.end( );
408 bool
409 Ast::ClassFunction::isInFinalSet( const char * field ) const
411 return finalSet_.find( field ) != finalSet_.end( );
414 bool
415 Ast::ClassFunction::isInTransformingSet( const char * field ) const
417 return transformingSet_.find( field ) != transformingSet_.end( );
420 Lang::Class::MessageMapType
421 Ast::ClassFunction::getLocalMessageMap( RefCountPtr< const Lang::Class > _myClass ) const
423 Lang::Class::MessageMapType res;
425 typedef typeof abstractSet_ ListType;
426 for( ListType::const_iterator i = abstractSet_.begin( ); i != abstractSet_.end( ); ++i )
428 res[ Kernel::MethodId( _myClass, *i ) ];
432 typedef typeof members_ ListType;
433 for( ListType::const_iterator i = members_.begin( ); i != members_.end( ); ++i )
435 if( ( (*i)->mode_ & Ast::MEMBER_METHOD ) == 0 )
437 continue;
439 std::set< RefCountPtr< const Lang::Class > > & theSet = res[ Kernel::MethodId( _myClass, (*i)->id_ ) ];
440 theSet.insert( theSet.begin( ), _myClass );
443 return res;
446 bool
447 Ast::ClassFunction::isRepeatableBase( ) const
449 return constructorFormals_->argumentOrder_->empty( );
452 #if 0
453 void
454 Ast::ClassFunction::bindInitializationArguments( RefCountPtr< const Lang::Class > theClass, Kernel::PassedEnv initEnv, Kernel::Arguments & args ) const
456 if( args.size( ) != constructorFormals_->size( ) )
458 throw Exceptions::UserArityMismatch( this, constructorFormals_->size( ), args.size( ), Exceptions::UserArityMismatch::VARIABLE );
461 std::list< Kernel::ValueRef >::const_iterator val = args.begin( );
462 std::list< Kernel::ValueRef >::const_iterator end = args.end( );
463 std::list< RefCountPtr< const char > >::const_iterator formal = constructorFormals_->begin( );
464 Ast::SourceLocation dummy;
465 for( ; val != end; ++val, ++formal )
467 initEnv->define( dummy, *formal, *val, true ); /* true means constant; the initialization parameters shall not be confused with object states */
470 #endif
472 void
473 Ast::ClassFunction::setupInstance( Kernel::PassedEnv instanceEnv, Kernel::PassedEnv privateEnv, Kernel::EvalState * evalState, Kernel::PassedEnv initEnv ) const
475 throw Exceptions::NotImplemented( "ClassFunction::setupInstance" );
477 // typedef typeof members_ ListType;
478 // for( ListType::const_iterator i = members_.begin( ); i != members_.end( ); ++i )
479 // {
480 // const Ast::MemberDeclaration & decl = **i;
482 // Kernel::PassedEnv * defineEnv = & instanceEnv;
483 // if( ( decl.mode & Ast::MEMBER_ACCESS_BITS ) == Ast::MEMBER_ACCESS_PRIVATE )
484 // {
485 // defineEnv = & privateEnv;
486 // }
488 // Kernel::PassedEnv & evalEnv = initEnv;
489 // if( ( decl.mode & Ast::MEMBER_METHOD ) != 0 )
490 // {
491 // evalEnv = privateEnv;
492 // }
494 // (*defineEnv)->define( decl.loc, decl.id, decl.init->value( dstgroup, pdfo, metaState, evalEnv ), ( decl.mode & ( Ast::MEMBER_METHOD | Ast::MEMBER_CONST ) ) != 0 );
495 // }
498 void
499 Ast::ClassFunction::prepareInstance( Kernel::EvalState * evalState, Kernel::PassedEnv privateEnv ) const
501 throw Exceptions::NotImplemented( "ClassFunction::prepareInstance" );
503 // Ast::CodeBracket::evalSequence( preparations.begin( ), preparations.end( ), metaState, privateEnv, false );
506 const Ast::SourceLocation &
507 Ast::ClassFunction::loc( ) const
509 return loc_;
513 Ast::PublicMethodReferenceFunction::PublicMethodReferenceFunction( const Ast::SourceLocation & loc, Ast::Expression * obj, MethodIdExpr * methodId )
514 : Lang::Function( 0 ), loc_( loc, bool( ) ), obj_( obj ), methodClass_( methodId->classPart_ ), methodName_( strdup( methodId->name_ ) )
516 WARN_OR_THROW( Exceptions::InternalError( "Ast::PublicMethodReferenceFunction::PublicMethodReferenceFunction initializes Lang::Function with 0 pointer to formals.", true ) );
517 delete methodId;
520 Ast::PublicMethodReferenceFunction::~PublicMethodReferenceFunction( )
522 delete obj_;
523 delete methodClass_;
526 void
527 Ast::PublicMethodReferenceFunction::push_exprs( Ast::ArgListExprs * args ) const
529 args->orderedExprs_->push_back( obj_ );
530 args->orderedExprs_->push_back( methodClass_ );
533 void
534 Ast::PublicMethodReferenceFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
536 RefCountPtr< const Lang::Value > untypedObj = args.getValue( 0 );
537 Kernel::MethodId methodId( args.getHandle( 1 )->getVal< const Lang::Class >( methodClass_->loc( ) ), methodName_ );
539 typedef const Lang::Instance ObjType;
540 ObjType * typedObj = dynamic_cast< ObjType * >( untypedObj.getPtr( ) );
541 if( typedObj != 0 )
543 Kernel::ContRef cont = evalState->cont_;
544 cont->takeValue( typedObj->getMethod( methodId ),
545 evalState );
546 return;
550 typedef const Lang::TransformedInstance ObjType;
551 ObjType * typedObj = dynamic_cast< ObjType * >( untypedObj.getPtr( ) );
552 if( typedObj != 0 )
554 Kernel::ContRef cont = evalState->cont_;
555 cont->takeValue( typedObj->getMethod( methodId ),
556 evalState );
557 return;
560 throw Exceptions::TypeMismatch( obj_->loc( ), untypedObj->getTypeName( ), Helpers::typeSetString( Lang::Instance::staticTypeName( ), Lang::TransformedInstance::staticTypeName( ) ) );
565 Ast::ProtectedMethodReferenceFunction::ProtectedMethodReferenceFunction( const Ast::SourceLocation & loc, const Ast::SourceLocation & selfLoc, Ast::Expression * parent, Ast::MethodIdExpr * methodId )
566 : Lang::Function( 0 ), loc_( loc, bool( ) ), selfLoc_( selfLoc, bool( ) ), parent_( parent ), methodClass_( methodId->classPart_ ), methodName_( strdup( methodId->name_ ) ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
568 WARN_OR_THROW( Exceptions::InternalError( "Ast::PublicMethodReferenceFunction::PublicMethodReferenceFunction initializes Lang::Function with 0 pointer to formals.", true ) );
569 /* Currently, a runtime check is used to ensure that this expression indeed refers to a super instance.
571 delete methodId;
574 Ast::ProtectedMethodReferenceFunction::~ProtectedMethodReferenceFunction( )
576 delete parent_;
577 delete methodClass_;
578 delete methodName_;
579 if( *idKey_ != 0 )
581 delete *idKey_;
583 delete idKey_; // This can be done only as long as this is not shared!
586 void
587 Ast::ProtectedMethodReferenceFunction::push_exprs( Ast::ArgListExprs * args ) const
589 args->orderedExprs_->push_back( methodClass_ );
590 if( parent_ != 0 )
592 args->orderedExprs_->push_back( parent_ );
596 void
597 Ast::ProtectedMethodReferenceFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
599 /* argument expressions shall be analyzed from the calling expression.
600 * Here, they are only used to locate errors.
603 if( *idKey_ == 0 )
607 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalVariableKey( selfLoc_, Lang::SELF_ID ) );
609 catch( const Exceptions::LookupUnknown & ball )
611 throw Exceptions::MisplacedSuperReference( selfLoc_ );
616 void
617 Ast::ProtectedMethodReferenceFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
619 typedef const Lang::Instance SelfType;
620 RefCountPtr< const Lang::Value > untypedSelf = evalState->env_->getVarHandle( **idKey_ )->getUntyped( );
621 SelfType * typedSelf = dynamic_cast< SelfType * >( untypedSelf.getPtr( ) );
622 if( typedSelf == 0 )
624 throw Exceptions::InternalError( strrefdup( "ProtectedMethodAccess: the self variable was not an instance." ) );
627 Kernel::MethodId methodId( args.getHandle( 0 )->getVal< const Lang::Class >( methodClass_->loc( ) ), methodName_ );
629 if( parent_ != 0 )
631 RefCountPtr< const Lang::Class > typedParent = args.getHandle( 1 )->getVal< const Lang::Class >( parent_->loc( ) );
632 Kernel::ContRef cont = evalState->cont_;
633 cont->takeValue( typedSelf->superReference( typedParent )->getLocalMethod( methodId ),
634 evalState );
635 return;
638 /* parent == 0 means a reference to a local override */
639 Kernel::ContRef cont = evalState->cont_;
640 cont->takeValue( typedSelf->getLocalMethod( methodId ),
641 evalState );
645 Ast::ProtectedMemberReferenceFunction::ProtectedMemberReferenceFunction( const Ast::SourceLocation & loc, const Ast::SourceLocation & selfLoc, Ast::Expression * parent, const Ast::SourceLocation & idLoc, const char * id )
646 : Lang::Function( 0 ), loc_( loc, bool( ) ), selfLoc_( selfLoc, bool( ) ), parent_( parent ), idLoc_( idLoc, bool( ) ), id_( id ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
648 WARN_OR_THROW( Exceptions::InternalError( "Ast::ProtectedMemberReferenceFunction::ProtectedMemberReferenceFunction initializes Lang::Function with 0 pointer to formals.", true ) );
649 /* Currently, a runtime check is used to ensure that this expression indeed refers to a super instance.
653 Ast::ProtectedMemberReferenceFunction::~ProtectedMemberReferenceFunction( )
655 delete parent_;
656 delete id_;
657 if( *idKey_ != 0 )
659 delete *idKey_;
661 delete idKey_; // This can be done only as long as this is not shared!
664 void
665 Ast::ProtectedMemberReferenceFunction::push_exprs( Ast::ArgListExprs * args ) const
667 args->orderedExprs_->push_back( parent_ );
670 void
671 Ast::ProtectedMemberReferenceFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
673 /* argument expressions shall be analyzed from the calling expression.
674 * Here, they are only used to locate errors.
677 if( *idKey_ == 0 )
681 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalVariableKey( selfLoc_, Lang::SELF_ID ) );
683 catch( const Exceptions::LookupUnknown & ball )
685 throw Exceptions::MisplacedSuperReference( selfLoc_ );
690 void
691 Ast::ProtectedMemberReferenceFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
693 typedef const Lang::Instance SelfType;
694 RefCountPtr< const Lang::Value > untypedSelf = evalState->env_->getVarHandle( **idKey_ )->getUntyped( );
695 SelfType * typedSelf = dynamic_cast< SelfType * >( untypedSelf.getPtr( ) );
696 if( typedSelf == 0 )
698 throw Exceptions::InternalError( strrefdup( "ProtectedMethodAccess: the self variable was not an instance." ) );
701 RefCountPtr< const Lang::Class > typedParent = args.getHandle( 0 )->getVal< const Lang::Class >( parent_->loc( ) );
702 Kernel::ContRef cont = evalState->cont_;
703 cont->takeHandle( typedSelf->superReference( typedParent )->getLocalField( id_ ),
704 evalState );
708 Ast::ProtectedMemberInsertionFunction::ProtectedMemberInsertionFunction( const Ast::SourceLocation & loc, const Ast::SourceLocation & selfLoc, Ast::Expression * parent, const Ast::SourceLocation & idLoc, const char * id, Ast::Expression * pieceExpr )
709 : Lang::Function( 0 ), loc_( loc, bool( ) ), selfLoc_( selfLoc, bool( ) ), parent_( parent ), idLoc_( idLoc, bool( ) ), id_( id ), pieceExpr_( pieceExpr ), idKey_( new Kernel::Environment::LexicalKey * ( 0 ) )
711 WARN_OR_THROW( Exceptions::InternalError( "Ast::ProtectedMemberInsertionFunction::ProtectedMemberInsertionFunction initializes Lang::Function with 0 pointer to formals.", true ) );
712 /* Currently, a runtime check is used to ensure that this expression indeed refers to a super instance.
716 Ast::ProtectedMemberInsertionFunction::~ProtectedMemberInsertionFunction( )
718 if( parent_ != 0 )
720 delete parent_;
722 delete id_;
723 delete pieceExpr_;
724 if( *idKey_ != 0 )
726 delete *idKey_;
728 delete idKey_; // This can be done only as long as this is not shared!
731 void
732 Ast::ProtectedMemberInsertionFunction::push_exprs( Ast::ArgListExprs * args ) const
734 args->orderedExprs_->push_back( pieceExpr_ );
735 if( parent_ != 0 )
737 args->orderedExprs_->push_back( parent_ );
741 void
742 Ast::ProtectedMemberInsertionFunction::analyze_impl( Ast::Node * parent, Ast::AnalysisEnvironment * env, Ast::StateIDSet * freeStatesDst )
744 /* argument expressions shall be analyzed from the calling expression.
745 * Here, they are only used to locate errors.
748 if( *idKey_ == 0 )
752 *idKey_ = new Kernel::Environment::LexicalKey( env->findLexicalStateKey( selfLoc_, Lang::SELF_ID, parent_ ) );
754 catch( const Exceptions::LookupUnknown & ball )
756 throw Exceptions::MisplacedSuperReference( selfLoc_ );
761 void
762 Ast::ProtectedMemberInsertionFunction::call( Kernel::EvalState * evalState, Kernel::Arguments & args, const Ast::SourceLocation & callLoc ) const
764 typedef const Lang::Instance SelfType;
765 RefCountPtr< const Lang::Value > untypedSelf = evalState->env_->getVarHandle( **idKey_ )->getUntyped( );
766 SelfType * typedSelf = dynamic_cast< SelfType * >( untypedSelf.getPtr( ) );
767 if( typedSelf == 0 )
769 throw Exceptions::InternalError( strrefdup( "ProtectedMethodAccess: The self variable was not an instance." ) );
772 RefCountPtr< const Lang::Value > piece = args.getValue( 0 );
774 throw Exceptions::NotImplemented( "Tacking on fields." );
776 // if( parent_ == 0 )
777 // {
778 // typedSelf->getField( id_, untypedSelf )->tackOn( evalState, piece, pieceExpr_->loc( ) );
779 // return;
780 // }
782 // RefCountPtr< const Lang::Class > typedParent = args.getHandle( 1 )->getVal< const Lang::Class >( parent_->loc( ) );
783 // typedSelf->superReference( typedParent )->getLocalField( id_ )->tackOn( evalState, piece, pieceExpr_->loc( ) );