#include "AST.h" #include "compiler.h" #include "sharing.h" SharingEnforcement sharingEnforcement = Late; Sharing modifiersToSharing( Common::Modifiers modifiers ) { return modifiers & Common::NonsharedQ ? Nonshared : (modifiers & Common::PolysharedQ ? Polyshared : Shared); } Common::Modifiers sharingToModifiers( Sharing sharing ) { switch (sharing) { case Shared: return Common::None; case Nonshared: return Common::NonsharedQ; case Polyshared: return Common::PolysharedQ; default: assert( 0 ); return (Common::Modifiers) 0; } } Sharing lub( Sharing a, Sharing b ) { switch (a) { case Unconstrained: return b; case Shared: switch (b) { case Unconstrained: case Shared: return Shared; case Nonshared: case Polyshared: return Polyshared; } case Nonshared: switch (b) { case Unconstrained: case Nonshared: return Nonshared; case Shared: case Polyshared: return Polyshared; } case Polyshared: return Polyshared; } fatal_error(""); return Unconstrained; } bool conformsTo( Sharing sub, Sharing super ) { if (sub == super) return true; if (sub == Unconstrained) return true; if (super == Polyshared) return true; return false; } bool conformsTo( Common::Modifiers sub, Common::Modifiers super ) { const bool subGlobal = !(sub & Common::Local); const bool superGlobal = !(super & Common::Local); const Sharing subShare = modifiersToSharing( sub ); const Sharing superShare = modifiersToSharing( super ); if (subGlobal && !superGlobal) return false; if (!conformsTo( subShare, superShare )) return false; if (sharingEnforcement == Early && subShare != Shared && superGlobal) return false; return true; } static const string &sharingToString( Sharing sharing ) { static const string shared( "shared" ); static const string nonshared( "nonshared" ); static const string polyshared( "polyshared" ); static const string empty; switch (sharing) { case Shared: return shared; case Nonshared: return nonshared; case Polyshared: return polyshared; default: assert( 0 ); return empty; } } ostream &operator << ( ostream &out, Sharing sharing ) { return out << sharingToString( sharing ); } string operator + ( const string &prefix, Sharing sharing ) { return prefix + sharingToString( sharing ); } string operator + ( const char prefix[], Sharing sharing ) { return prefix + sharingToString( sharing ); } string operator + ( Sharing sharing, const string &prefix ) { return sharingToString( sharing ) + prefix; } string operator + ( Sharing sharing, const char prefix[] ) { return sharingToString( sharing ) + prefix; } string &operator += ( string &prefix, Sharing sharing ) { return prefix += sharingToString( sharing ); } //////////////////////////////////////////////////////////////////////// void TypeNode::checkShared( const TreeNode &attribution, const char thing[], const char action[] ) const { assert( !isLocal() ); const Sharing mySharing = sharing(); if (mySharing != Shared) attribution.error() << "cannot " << action << " a " << mySharing << ' ' << thing << " across a global reference" << endl; } static bool isSharedField(const TypeNode *t) { ClassDecl *cd = dynamic_cast(t->decl()); switch (cd->kind()) { case Common::ClassKind: case Common::InterfaceKind: return cd->allFieldsShared(); case Common::ImmutableKind: // An immutable is a shared field if all of its constituent fields // are shared fields. Ooh, recursion! foriter (field, cd->environ()->allProperDecls(), EnvironIter) if (field->category() == Decl::Field && !(field->modifiers() & Common::Static) && !field->type()->isSharedField()) return false; return true; default: t->fatal( "unable to check field sharing of " + cd->errorName() ); return false; } } bool TypeNameNode::isSharedField() const { return ::isSharedField(this); } bool TemplateInstanceTypeNode::isSharedField() const { return ::isSharedField(this); } bool ClassDecl::allFieldsShared() { if (_allFieldsShared == Maybe) { _allFieldsShared = this == ObjectDecl || !superClass() || superClass()->allFieldsShared() ? Yes : No; if (_allFieldsShared == Yes) foriter (member, environ()->allProperDecls(), EnvironIter) if (member->category() == Decl::Field && !(member->modifiers() & Common::Static) && !member->type()->isSharedField()) { _allFieldsShared = No; break; } } return _allFieldsShared == Yes; }